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 
00076 
00077 
00082 struct PQXX_LIBEXPORT noticer : PGSTD::unary_function<const char[], void>
00083 {
00084   noticer(){}           // Silences bogus warning in some gcc versions
00085   virtual ~noticer() throw () {}
00086   virtual void operator()(const char Msg[]) throw () =0;
00087 };
00088 
00089 
00091 struct PQXX_LIBEXPORT nonnoticer : noticer
00092 {
00093   nonnoticer(){}        // Silences bogus warning in some gcc versions
00094   virtual void operator()(const char []) throw () {}
00095 };
00096 
00102 
00103 
00123 class PQXX_LIBEXPORT connection_base
00124 {
00125 public:
00127   void disconnect() throw ();                                           //[t2]
00128 
00130 
00140   void activate();                                                      //[t12]
00141 
00143 
00151   void deactivate();                                                    //[t12]
00152 
00154 
00198   void inhibit_reactivation(bool inhibit)                               //[t86]
00199         { m_inhibit_reactivation=inhibit; }
00200 
00202 
00206   bool is_open() const throw ();                                        //[t1]
00207 
00209 
00221   PGSTD::auto_ptr<noticer> set_noticer(PGSTD::auto_ptr<noticer> N)
00222     throw ();                                                           //[t14]
00223   noticer *get_noticer() const throw () { return m_Noticer.get(); }     //[t14]
00224 
00226   void process_notice(const char[]) throw ();                           //[t14]
00228   void process_notice(const PGSTD::string &) throw ();                  //[t14]
00229 
00231   void trace(FILE *) throw ();                                          //[t3]
00232 
00241 
00242   const char *dbname();                                                 //[t1]
00243 
00245   const char *username();                                               //[t1]
00246 
00248   const char *hostname();                                               //[t1]
00249 
00251   const char *port();                                                   //[t1]
00252 
00254 
00263   int backendpid() const throw ();                                      //[t1]
00264 
00266 
00280   int sock() const throw ();                                            //[t87]
00281 
00283 
00289   enum capability
00290   {
00292     cap_prepared_statements,
00293 
00295     cap_create_table_with_oids,
00296 
00298     cap_nested_transactions,
00299 
00301     cap_cursor_scroll,
00303     cap_cursor_with_hold,
00305     cap_cursor_update,
00306 
00308     cap_end
00309   };
00310 
00311 
00313 
00326   bool supports(capability c) const throw () { return m_caps[c]; }      //[t88]
00327 
00329 
00341   int protocol_version() const throw ();                                //[t1]
00342 
00344 
00358   int server_version() const throw ();                                  //[t1]
00359 
00361 
00367   void set_client_encoding(const PGSTD::string &Encoding)               //[t7]
00368         { set_variable("CLIENT_ENCODING", Encoding); }
00369 
00371 
00387   void set_variable(const PGSTD::string &Var,
00388                     const PGSTD::string &Value);                        //[t60]
00389 
00391 
00398   PGSTD::string get_variable(const PGSTD::string &);                    //[t60]
00400 
00401 
00406 
00407 
00418   int get_notifs();                                                     //[t4]
00419 
00420 
00422 
00428   int await_notification();                                             //[t78]
00429 
00431 
00437   int await_notification(long seconds, long microseconds);              //[t79]
00439 
00440 
00472 
00473 
00503   prepare::declaration prepare(const PGSTD::string &name,
00504         const PGSTD::string &definition);                               //[t85]
00505 
00507   void unprepare(const PGSTD::string &name);                            //[t85]
00508 
00538 
00539 
00547   template<typename TRANSACTOR>
00548   void perform(const TRANSACTOR &T, int Attempts);                      //[t4]
00549 
00551 
00554   template<typename TRANSACTOR>
00555   void perform(const TRANSACTOR &T) { perform(T, 3); }
00556 
00561 
00562 
00565   PGSTD::string adorn_name(const PGSTD::string &);                      //[90]
00566 
00567 #ifdef PQXX_DEPRECATED_HEADERS
00568 
00576 
00577   void Disconnect() throw () PQXX_DEPRECATED { disconnect(); }
00579   template<typename TRANSACTOR> void Perform(const TRANSACTOR &T, int A=3)
00580         PQXX_DEPRECATED { perform(T,A); }
00582   PGSTD::auto_ptr<noticer> SetNoticer(PGSTD::auto_ptr<noticer> N)
00583         PQXX_DEPRECATED { return set_noticer(N); }
00585   noticer *GetNoticer() const throw () PQXX_DEPRECATED { return get_noticer(); }
00587   void ProcessNotice(const char msg[]) throw () PQXX_DEPRECATED
00588         { return process_notice(msg); }
00590   void ProcessNotice(const PGSTD::string &msg) throw () PQXX_DEPRECATED
00591         { return process_notice(msg); }
00593   void Trace(FILE *F) PQXX_DEPRECATED { trace(F); }
00595   void GetNotifs() PQXX_DEPRECATED { get_notifs(); }
00597   const char *DbName() PQXX_DEPRECATED { return dbname(); }
00599   const char *UserName() PQXX_DEPRECATED { return username(); }
00601   const char *HostName() PQXX_DEPRECATED { return hostname(); }
00603   const char *Port() PQXX_DEPRECATED { return port(); }
00605   int BackendPID() const PQXX_DEPRECATED { return backendpid(); }
00607   void Activate() PQXX_DEPRECATED { activate(); }
00609   void Deactivate() PQXX_DEPRECATED { deactivate(); }
00611   void SetClientEncoding(const PGSTD::string &E) PQXX_DEPRECATED
00612         { set_client_encoding(E); }
00614   void SetVariable(const PGSTD::string &Var, const PGSTD::string &Val)
00615         PQXX_DEPRECATED { set_variable(Var, Val); }
00616 
00620 #endif
00621 
00622 protected:
00623   explicit connection_base(connectionpolicy &);
00624   void init();
00625 
00626   void close() throw ();
00627   void wait_read() const;
00628   void wait_read(long seconds, long microseconds) const;
00629   void wait_write() const;
00630 
00631 private:
00632   void PQXX_PRIVATE clearcaps() throw ();
00633   void PQXX_PRIVATE SetupState();
00634   void PQXX_PRIVATE check_result(const result &, const char Query[]);
00635 
00636   void PQXX_PRIVATE InternalSetTrace() throw ();
00637   int PQXX_PRIVATE Status() const throw ();
00638   const char *ErrMsg() const throw ();
00639   void PQXX_PRIVATE Reset();
00640   void PQXX_PRIVATE RestoreVars();
00641   PGSTD::string PQXX_PRIVATE RawGetVar(const PGSTD::string &);
00642   void PQXX_PRIVATE process_notice_raw(const char msg[]) throw ();
00643   void switchnoticer(const PGSTD::auto_ptr<noticer> &) throw ();
00644 
00645   void read_capabilities() throw ();
00646 
00647   friend class subtransaction;
00648   void set_capability(capability) throw ();
00649 
00650   prepare::internal::prepared_def &find_prepared(const PGSTD::string &);
00651 
00652   friend class prepare::declaration;
00653   void prepare_param_declare(const PGSTD::string &statement,
00654       const PGSTD::string &sqltype,
00655       prepare::param_treatment);
00656 
00657   result prepared_exec(const PGSTD::string &,
00658         const char *const[],
00659         const int[],
00660         int);
00661 
00663   internal::pq::PGconn *m_Conn;
00664 
00665   connectionpolicy &m_policy;
00666 
00668   bool m_Completed;
00669 
00671   internal::unique<transaction_base> m_Trans;
00672 
00674   PGSTD::auto_ptr<noticer> m_Noticer;
00675 
00677 
00681   internal::pq::PQnoticeProcessor m_defaultNoticeProcessor;
00682 
00684   FILE *m_Trace;
00685 
00686   typedef PGSTD::multimap<PGSTD::string, pqxx::trigger *> TriggerList;
00688   TriggerList m_Triggers;
00689 
00691   PGSTD::map<PGSTD::string, PGSTD::string> m_Vars;
00692 
00693   typedef PGSTD::map<PGSTD::string, prepare::internal::prepared_def> PSMap;
00694 
00696   PSMap m_prepared;
00697 
00699   bool m_caps[cap_end];
00700 
00702   bool m_inhibit_reactivation;
00703 
00705   internal::reactivation_avoidance_counter m_reactivation_avoidance;
00706 
00708   int m_unique_id;
00709 
00710   friend class transaction_base;
00711   result PQXX_PRIVATE Exec(const char[], int Retries);
00712   result pq_exec_prepared(const PGSTD::string &, int, const char *const *);
00713   void PQXX_PRIVATE RegisterTransaction(transaction_base *);
00714   void PQXX_PRIVATE UnregisterTransaction(transaction_base *) throw ();
00715   void PQXX_PRIVATE MakeEmpty(result &);
00716   bool PQXX_PRIVATE ReadCopyLine(PGSTD::string &);
00717   void PQXX_PRIVATE WriteCopyLine(const PGSTD::string &);
00718   void PQXX_PRIVATE EndCopyWrite();
00719   void PQXX_PRIVATE start_exec(const PGSTD::string &);
00720   internal::pq::PGresult *get_result();
00721   PGSTD::string esc(const char str[], size_t maxlen);
00722   PGSTD::string esc_raw(const unsigned char str[], size_t len);
00723 
00724   void PQXX_PRIVATE RawSetVar(const PGSTD::string &, const PGSTD::string &);
00725   void PQXX_PRIVATE AddVariables(const PGSTD::map<PGSTD::string,
00726       PGSTD::string> &);
00727 
00728   friend class largeobject;
00729   internal::pq::PGconn *RawConnection() const { return m_Conn; }
00730 
00731   friend class trigger;
00732   void AddTrigger(trigger *);
00733   void RemoveTrigger(trigger *) throw ();
00734 
00735   friend class pipeline;
00736   bool PQXX_PRIVATE consume_input() throw ();
00737   bool PQXX_PRIVATE is_busy() const throw ();
00738 
00739   friend class cursor_base;
00740   friend class dbtransaction;
00741   friend class internal::reactivation_avoidance_exemption;
00742 
00743   // Not allowed:
00744   connection_base(const connection_base &);
00745   connection_base &operator=(const connection_base &);
00746 };
00747 
00748 
00749 
00750 namespace internal
00751 {
00752 
00754 
00760 class PQXX_LIBEXPORT scoped_noticer
00761 {
00762 public:
00764 
00768   scoped_noticer(connection_base &c, PGSTD::auto_ptr<noticer> t) throw () :
00769     m_c(c), m_org(c.set_noticer(t)) { }
00770 
00771   ~scoped_noticer() { m_c.set_noticer(m_org); }
00772 
00773 protected:
00775 
00779   scoped_noticer(connection_base &c, noticer *t) throw () :
00780     m_c(c),
00781     m_org()
00782   {
00783     PGSTD::auto_ptr<noticer> x(t);
00784     PGSTD::auto_ptr<noticer> y(c.set_noticer(x));
00785     m_org = y;
00786   }
00787 
00788 private:
00789   connection_base &m_c;
00790   PGSTD::auto_ptr<noticer> m_org;
00791 
00793   scoped_noticer();
00794   scoped_noticer(const scoped_noticer &);
00795   scoped_noticer operator=(const scoped_noticer &);
00796 };
00797 
00798 
00800 class PQXX_LIBEXPORT disable_noticer : scoped_noticer
00801 {
00802 public:
00803   explicit disable_noticer(connection_base &c) :
00804     scoped_noticer(c, new nonnoticer) {}
00805 };
00806 
00807 
00809 class PQXX_LIBEXPORT reactivation_avoidance_exemption
00810 {
00811 public:
00812   explicit reactivation_avoidance_exemption(connection_base &C) :
00813     m_home(C),
00814     m_count(C.m_reactivation_avoidance.get()),
00815     m_open(C.is_open())
00816   {
00817     C.m_reactivation_avoidance.clear();
00818   }
00819 
00820   ~reactivation_avoidance_exemption()
00821   {
00822     // Don't leave connection open if reactivation avoidance is in effect and
00823     // the connection needed to be reactivated temporarily.
00824     if (m_count && !m_open) m_home.deactivate();
00825     m_home.m_reactivation_avoidance.add(m_count);
00826   }
00827 
00828   void close_connection() throw () { m_open = false; }
00829 
00830 private:
00831   connection_base &m_home;
00832   int m_count;
00833   bool m_open;
00834 };
00835 
00836 
00837 void wait_read(const internal::pq::PGconn *);
00838 void wait_read(const internal::pq::PGconn *, long seconds, long microseconds);
00839 void wait_write(const internal::pq::PGconn *);
00840 
00841 } // namespace pqxx::internal
00842 
00843 
00844 } // namespace pqxx
00845 
00846 #include "pqxx/compiler-internal-post.hxx"

Generated on Wed Sep 6 16:54:12 2006 for libpqxx by  doxygen 1.4.7