connection_base.hxx

Go to the documentation of this file.
00001 /*-------------------------------------------------------------------------
00002  *
00003  *   FILE
00004  *      pqxx/connection_base.hxx
00005  *
00006  *   DESCRIPTION
00007  *      definition of the pqxx::connection_base abstract base class.
00008  *   pqxx::connection_base encapsulates a frontend to backend connection
00009  *   DO NOT INCLUDE THIS FILE DIRECTLY; include pqxx/connection_base instead.
00010  *
00011  * Copyright (c) 2001-2006, Jeroen T. Vermeulen <jtv@xs4all.nl>
00012  *
00013  * See COPYING for copyright license.  If you did not receive a file called
00014  * COPYING with this source code, please notify the distributor of this mistake,
00015  * or contact the author.
00016  *
00017  *-------------------------------------------------------------------------
00018  */
00019 #include "pqxx/compiler-public.hxx"
00020 #include "pqxx/compiler-internal-pre.hxx"
00021 
00022 #include <map>
00023 #include <memory>
00024 
00025 #include "pqxx/except"
00026 #include "pqxx/prepared_statement"
00027 #include "pqxx/util"
00028 
00029 
00030 /* Use of the libpqxx library starts here.
00031  *
00032  * Everything that can be done with a database through libpqxx must go through
00033  * a connection object derived from connection_base.
00034  */
00035 
00036 /* Methods tested in eg. self-test program test1 are marked with "//[t1]"
00037  */
00038 
00039 namespace pqxx
00040 {
00041 class result;
00042 class transaction_base;
00043 class trigger;
00044 class connectionpolicy;
00045 
00046 namespace internal
00047 {
00048 class reactivation_avoidance_exemption;
00049 
00050 class reactivation_avoidance_counter
00051 {
00052 public:
00053   reactivation_avoidance_counter() : m_counter(0) {}
00054 
00055   void add(int n) throw () { m_counter += n; }
00056   void clear() throw () { m_counter = 0; }
00057   int get() const throw () { return m_counter; }
00058 
00059   void give_to(reactivation_avoidance_counter &rhs) throw ()
00060   {
00061     rhs.add(m_counter);
00062     clear();
00063   }
00064 
00065 private:
00066   int m_counter;
00067 };
00068 
00069 }
00070 
00075 
00076 
00081 struct PQXX_LIBEXPORT noticer : PGSTD::unary_function<const char[], void>
00082 {
00083   noticer(){}           // Silences bogus warning in some gcc versions
00084   virtual ~noticer() throw () {}
00085   virtual void operator()(const char Msg[]) throw () =0;
00086 };
00087 
00088 
00090 struct PQXX_LIBEXPORT nonnoticer : noticer
00091 {
00092   nonnoticer(){}        // Silences bogus warning in some gcc versions
00093   virtual void operator()(const char []) throw () {}
00094 };
00096 
00097 
00102 
00103 
00123 class PQXX_LIBEXPORT connection_base
00124 {
00125 public:
00130 
00131   void disconnect() throw ();                                           //[t2]
00132 
00134 
00144   void activate();                                                      //[t12]
00145 
00147 
00155   void deactivate();                                                    //[t12]
00156 
00158 
00202   void inhibit_reactivation(bool inhibit)                               //[t86]
00203         { m_inhibit_reactivation=inhibit; }
00204 
00206 
00210   bool is_open() const throw ();                                        //[t1]
00212 
00217 
00218 
00230   PGSTD::auto_ptr<noticer> set_noticer(PGSTD::auto_ptr<noticer> N)
00231     throw ();                                                           //[t14]
00232   noticer *get_noticer() const throw () { return m_Noticer.get(); }     //[t14]
00233 
00235   void process_notice(const char[]) throw ();                           //[t14]
00237   void process_notice(const PGSTD::string &) throw ();                  //[t14]
00239 
00241   void trace(FILE *) throw ();                                          //[t3]
00242 
00251 
00252   const char *dbname();                                                 //[t1]
00253 
00255   const char *username();                                               //[t1]
00256 
00258   const char *hostname();                                               //[t1]
00259 
00261   const char *port();                                                   //[t1]
00262 
00264 
00273   int backendpid() const throw ();                                      //[t1]
00274 
00276 
00290   int sock() const throw ();                                            //[t87]
00291 
00293 
00299   enum capability
00300   {
00302     cap_prepared_statements,
00303 
00305     cap_create_table_with_oids,
00306 
00308     cap_nested_transactions,
00309 
00311     cap_cursor_scroll,
00313     cap_cursor_with_hold,
00315     cap_cursor_update,
00316 
00318     cap_end
00319   };
00320 
00321 
00323 
00336   bool supports(capability c) const throw () { return m_caps[c]; }      //[]
00337 
00339 
00345   void set_client_encoding(const PGSTD::string &Encoding)               //[t7]
00346         { set_variable("CLIENT_ENCODING", Encoding); }
00347 
00349 
00365   void set_variable(const PGSTD::string &Var,
00366                     const PGSTD::string &Value);                        //[t60]
00367 
00369 
00376   PGSTD::string get_variable(const PGSTD::string &);                    //[t60]
00378 
00379 
00384 
00385 
00396   int get_notifs();                                                     //[t4]
00397 
00398 
00400 
00406   int await_notification();                                             //[t78]
00407 
00409 
00415   int await_notification(long seconds, long microseconds);              //[t79]
00417 
00418 
00448 
00449 
00479   prepare::declaration prepare(const PGSTD::string &name,
00480         const PGSTD::string &definition);                               //[t85]
00481 
00483   void unprepare(const PGSTD::string &name);                            //[t85]
00485 
00486 
00503 
00504 
00508   template<typename TRANSACTOR>
00509   void perform(const TRANSACTOR &T, int Attempts);                      //[t4]
00510 
00512 
00515   template<typename TRANSACTOR>
00516   void perform(const TRANSACTOR &T) { perform(T, 3); }
00518 
00520 
00523   PGSTD::string adorn_name(const PGSTD::string &);                      //[]
00524 
00525 #ifdef PQXX_DEPRECATED_HEADERS
00526 
00533 
00534   void Disconnect() throw () PQXX_DEPRECATED { disconnect(); }
00536   template<typename TRANSACTOR> void Perform(const TRANSACTOR &T, int A=3)
00537         PQXX_DEPRECATED { perform(T,A); }
00539   PGSTD::auto_ptr<noticer> SetNoticer(PGSTD::auto_ptr<noticer> N)
00540         PQXX_DEPRECATED { return set_noticer(N); }
00542   noticer *GetNoticer() const throw () PQXX_DEPRECATED { return get_noticer(); }
00544   void ProcessNotice(const char msg[]) throw () PQXX_DEPRECATED
00545         { return process_notice(msg); }
00547   void ProcessNotice(const PGSTD::string &msg) throw () PQXX_DEPRECATED
00548         { return process_notice(msg); }
00550   void Trace(FILE *F) PQXX_DEPRECATED { trace(F); }
00552   void GetNotifs() PQXX_DEPRECATED { get_notifs(); }
00554   const char *DbName() PQXX_DEPRECATED { return dbname(); }
00556   const char *UserName() PQXX_DEPRECATED { return username(); }
00558   const char *HostName() PQXX_DEPRECATED { return hostname(); }
00560   const char *Port() PQXX_DEPRECATED { return port(); }
00562   int BackendPID() const PQXX_DEPRECATED { return backendpid(); }
00564   void Activate() PQXX_DEPRECATED { activate(); }
00566   void Deactivate() PQXX_DEPRECATED { deactivate(); }
00568   void SetClientEncoding(const PGSTD::string &E) PQXX_DEPRECATED
00569         { set_client_encoding(E); }
00571   void SetVariable(const PGSTD::string &Var, const PGSTD::string &Val)
00572         PQXX_DEPRECATED { set_variable(Var, Val); }
00574 #endif
00575 
00576 
00577 protected:
00578   explicit connection_base(connectionpolicy &);
00579   void init();
00580 
00581   void close() throw ();
00582   void wait_read() const;
00583   void wait_read(long seconds, long microseconds) const;
00584   void wait_write() const;
00585 
00586 private:
00587   void PQXX_PRIVATE clearcaps() throw ();
00588   void PQXX_PRIVATE SetupState();
00589   void PQXX_PRIVATE check_result(const result &, const char Query[]);
00590 
00591   void PQXX_PRIVATE InternalSetTrace() throw ();
00592   int PQXX_PRIVATE Status() const throw ();
00593   const char *ErrMsg() const throw ();
00594   void PQXX_PRIVATE Reset();
00595   void PQXX_PRIVATE RestoreVars();
00596   PGSTD::string PQXX_PRIVATE RawGetVar(const PGSTD::string &);
00597   void PQXX_PRIVATE process_notice_raw(const char msg[]) throw ();
00598   void switchnoticer(const PGSTD::auto_ptr<noticer> &) throw ();
00599 
00600   void read_capabilities() throw ();
00601 
00602   friend class subtransaction;
00603   void set_capability(capability) throw ();
00604 
00605   prepare::internal::prepared_def &find_prepared(const PGSTD::string &);
00606 
00607   friend class prepare::declaration;
00608   void prepare_param_declare(const PGSTD::string &statement,
00609       const PGSTD::string &sqltype,
00610       prepare::param_treatment);
00611 
00612   result prepared_exec(const PGSTD::string &, const char *const params[], int);
00613 
00615   internal::pq::PGconn *m_Conn;
00616 
00617   connectionpolicy &m_policy;
00618 
00620   bool m_Completed;
00621 
00623   internal::unique<transaction_base> m_Trans;
00624 
00626   PGSTD::auto_ptr<noticer> m_Noticer;
00627 
00629 
00633   internal::pq::PQnoticeProcessor m_defaultNoticeProcessor;
00634 
00636   FILE *m_Trace;
00637 
00638   typedef PGSTD::multimap<PGSTD::string, pqxx::trigger *> TriggerList;
00640   TriggerList m_Triggers;
00641 
00643   PGSTD::map<PGSTD::string, PGSTD::string> m_Vars;
00644 
00645   typedef PGSTD::map<PGSTD::string, prepare::internal::prepared_def> PSMap;
00646 
00648   PSMap m_prepared;
00649 
00651   bool m_caps[cap_end];
00652 
00654   bool m_inhibit_reactivation;
00655 
00657   internal::reactivation_avoidance_counter m_reactivation_avoidance;
00658 
00660   int m_unique_id;
00661 
00662   friend class transaction_base;
00663   result PQXX_PRIVATE Exec(const char[], int Retries);
00664   result pq_exec_prepared(const PGSTD::string &, int, const char *const *);
00665   void PQXX_PRIVATE RegisterTransaction(transaction_base *);
00666   void PQXX_PRIVATE UnregisterTransaction(transaction_base *) throw ();
00667   void PQXX_PRIVATE MakeEmpty(result &);
00668   bool PQXX_PRIVATE ReadCopyLine(PGSTD::string &);
00669   void PQXX_PRIVATE WriteCopyLine(const PGSTD::string &);
00670   void PQXX_PRIVATE EndCopyWrite();
00671   void PQXX_PRIVATE start_exec(const PGSTD::string &);
00672   internal::pq::PGresult *get_result();
00673   PGSTD::string esc(const char str[], size_t maxlen);
00674 
00675   void PQXX_PRIVATE RawSetVar(const PGSTD::string &, const PGSTD::string &);
00676   void PQXX_PRIVATE AddVariables(const PGSTD::map<PGSTD::string,
00677       PGSTD::string> &);
00678 
00679   friend class largeobject;
00680   internal::pq::PGconn *RawConnection() const { return m_Conn; }
00681 
00682   friend class trigger;
00683   void AddTrigger(trigger *);
00684   void RemoveTrigger(trigger *) throw ();
00685 
00686   friend class pipeline;
00687   bool PQXX_PRIVATE consume_input() throw ();
00688   bool PQXX_PRIVATE is_busy() const throw ();
00689 
00690   friend class cursor_base;
00691   friend class dbtransaction;
00692   friend class internal::reactivation_avoidance_exemption;
00693 
00694   // Not allowed:
00695   connection_base(const connection_base &);
00696   connection_base &operator=(const connection_base &);
00697 };
00698 
00700 
00701 
00702 
00703 namespace internal
00704 {
00705 
00707 
00713 class PQXX_LIBEXPORT scoped_noticer
00714 {
00715 public:
00717 
00721   scoped_noticer(connection_base &c, PGSTD::auto_ptr<noticer> t) throw () :
00722     m_c(c), m_org(c.set_noticer(t)) { }
00723 
00724   ~scoped_noticer() { m_c.set_noticer(m_org); }
00725 
00726 protected:
00728 
00732   scoped_noticer(connection_base &c, noticer *t) throw () :
00733     m_c(c),
00734     m_org()
00735   {
00736     PGSTD::auto_ptr<noticer> x(t);
00737     PGSTD::auto_ptr<noticer> y(c.set_noticer(x));
00738     m_org = y;
00739   }
00740 
00741 private:
00742   connection_base &m_c;
00743   PGSTD::auto_ptr<noticer> m_org;
00744 
00746   scoped_noticer();
00747   scoped_noticer(const scoped_noticer &);
00748   scoped_noticer operator=(const scoped_noticer &);
00749 };
00750 
00751 
00753 class PQXX_LIBEXPORT disable_noticer : scoped_noticer
00754 {
00755 public:
00756   explicit disable_noticer(connection_base &c) :
00757     scoped_noticer(c, new nonnoticer) {}
00758 };
00759 
00760 
00762 class PQXX_LIBEXPORT reactivation_avoidance_exemption
00763 {
00764 public:
00765   explicit reactivation_avoidance_exemption(connection_base &C) :
00766     m_home(C),
00767     m_count(C.m_reactivation_avoidance.get()),
00768     m_open(C.is_open())
00769   {
00770     C.m_reactivation_avoidance.clear();
00771   }
00772 
00773   ~reactivation_avoidance_exemption()
00774   {
00775     // Don't leave connection open if reactivation avoidance is in effect and
00776     // the connection needed to be reactivated temporarily.
00777     if (m_count && !m_open) m_home.deactivate();
00778     m_home.m_reactivation_avoidance.add(m_count);
00779   }
00780 
00781   void close_connection() throw () { m_open = false; }
00782 
00783 private:
00784   connection_base &m_home;
00785   int m_count;
00786   bool m_open;
00787 };
00788 
00789 
00790 void wait_read(const internal::pq::PGconn *);
00791 void wait_read(const internal::pq::PGconn *, long seconds, long microseconds);
00792 void wait_write(const internal::pq::PGconn *);
00793 
00794 } // namespace pqxx::internal
00795 
00796 
00797 } // namespace pqxx
00798 
00799 #include "pqxx/compiler-internal-post.hxx"

Generated on Sat May 27 17:33:49 2006 for libpqxx by  doxygen 1.4.6