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-2007, 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 
00101 
00102 
00120 PGSTD::string encrypt_password(const PGSTD::string &user,               //[t0]
00121         const PGSTD::string &password);
00122 
00124 
00149 class PQXX_LIBEXPORT connection_base
00150 {
00151 public:
00153   void disconnect() throw ();                                           //[t2]
00154 
00156 
00160   bool is_open() const throw ();                                        //[t1]
00161 
00172 
00173 
00183   void activate();                                                      //[t12]
00184 
00186 
00194   void deactivate();                                                    //[t12]
00195 
00197 
00241   void inhibit_reactivation(bool inhibit)                               //[t86]
00242         { m_inhibit_reactivation=inhibit; }
00243 
00245 
00250   void simulate_failure();                                              //[t94]
00252 
00262 
00264 
00276   PGSTD::auto_ptr<noticer> set_noticer(PGSTD::auto_ptr<noticer> N)
00277     throw ();                                                           //[t14]
00278   noticer *get_noticer() const throw () { return m_Noticer.get(); }     //[t14]
00279 
00281   void process_notice(const char[]) throw ();                           //[t14]
00283   void process_notice(const PGSTD::string &) throw ();                  //[t14]
00284 
00286 
00288   void trace(FILE *) throw ();                                          //[t3]
00289 
00298 
00299   const char *dbname();                                                 //[t1]
00300 
00302   const char *username();                                               //[t1]
00303 
00305   const char *hostname();                                               //[t1]
00306 
00308   const char *port();                                                   //[t1]
00309 
00311 
00320   int backendpid() const throw ();                                      //[t1]
00321 
00323 
00337   int sock() const throw ();                                            //[t87]
00338 
00349  
00351   enum capability
00352   {
00354     cap_prepared_statements,
00355 
00357     cap_create_table_with_oids,
00358 
00360     cap_nested_transactions,
00361 
00363     cap_cursor_scroll,
00365     cap_cursor_with_hold,
00367     cap_cursor_update,
00368 
00370     cap_table_column,
00371 
00373     cap_end
00374   };
00375 
00376 
00378 
00395   bool supports(capability c) const throw () { return m_caps[c]; }      //[t88]
00396 
00398 
00410   int protocol_version() const throw ();                                //[t1]
00411 
00413 
00425   int server_version() const throw ();                                  //[t1]
00427 
00429 
00435   void set_client_encoding(const PGSTD::string &Encoding)               //[t7]
00436         { set_variable("CLIENT_ENCODING", Encoding); }
00437 
00439 
00455   void set_variable(const PGSTD::string &Var,
00456                     const PGSTD::string &Value);                        //[t60]
00457 
00459 
00466   PGSTD::string get_variable(const PGSTD::string &);                    //[t60]
00468 
00469 
00474 
00475 
00486   int get_notifs();                                                     //[t4]
00487 
00488 
00490 
00496   int await_notification();                                             //[t78]
00497 
00499 
00505   int await_notification(long seconds, long microseconds);              //[t79]
00507 
00508 
00540 
00541 
00576   prepare::declaration prepare(const PGSTD::string &name,
00577         const PGSTD::string &definition);                               //[t85]
00578 
00580   void unprepare(const PGSTD::string &name);                            //[t85]
00581 
00583 
00593   void prepare_now(const PGSTD::string &name);                          //[t85]
00594 
00624 
00625 
00633   template<typename TRANSACTOR>
00634   void perform(const TRANSACTOR &T, int Attempts);                      //[t4]
00635 
00637 
00640   template<typename TRANSACTOR>
00641   void perform(const TRANSACTOR &T) { perform(T, 3); }
00642 
00647 
00648 
00651   PGSTD::string adorn_name(const PGSTD::string &);                      //[90]
00652 
00653 
00654 protected:
00655   explicit connection_base(connectionpolicy &);
00656   void init();
00657 
00658   void close() throw ();
00659   void wait_read() const;
00660   void wait_read(long seconds, long microseconds) const;
00661   void wait_write() const;
00662 
00663 private:
00664   void PQXX_PRIVATE clearcaps() throw ();
00665   void PQXX_PRIVATE SetupState();
00666   void PQXX_PRIVATE check_result(const result &);
00667 
00668   void PQXX_PRIVATE InternalSetTrace() throw ();
00669   int PQXX_PRIVATE Status() const throw ();
00670   const char *ErrMsg() const throw ();
00671   void PQXX_PRIVATE Reset();
00672   void PQXX_PRIVATE RestoreVars();
00673   PGSTD::string PQXX_PRIVATE RawGetVar(const PGSTD::string &);
00674   void PQXX_PRIVATE process_notice_raw(const char msg[]) throw ();
00675   void switchnoticer(const PGSTD::auto_ptr<noticer> &) throw ();
00676 
00677   void read_capabilities() throw ();
00678 
00679   friend class subtransaction;
00680   void set_capability(capability) throw ();
00681 
00682   prepare::internal::prepared_def &find_prepared(const PGSTD::string &);
00683 
00684   friend class prepare::declaration;
00685   void prepare_param_declare(const PGSTD::string &statement,
00686       const PGSTD::string &sqltype,
00687       prepare::param_treatment);
00688 
00689   prepare::internal::prepared_def &register_prepared(const PGSTD::string &);
00690   result prepared_exec(const PGSTD::string &,
00691         const char *const[],
00692         const int[],
00693         int);
00694 
00696   internal::pq::PGconn *m_Conn;
00697 
00698   connectionpolicy &m_policy;
00699 
00701   bool m_Completed;
00702 
00704   internal::unique<transaction_base> m_Trans;
00705 
00707   PGSTD::auto_ptr<noticer> m_Noticer;
00708 
00710 
00714   internal::pq::PQnoticeProcessor m_defaultNoticeProcessor;
00715 
00717   FILE *m_Trace;
00718 
00719   typedef PGSTD::multimap<PGSTD::string, pqxx::trigger *> TriggerList;
00721   TriggerList m_Triggers;
00722 
00724   PGSTD::map<PGSTD::string, PGSTD::string> m_Vars;
00725 
00726   typedef PGSTD::map<PGSTD::string, prepare::internal::prepared_def> PSMap;
00727 
00729   PSMap m_prepared;
00730 
00732   int m_serverversion;
00733 
00735   bool m_caps[cap_end];
00736 
00738   bool m_inhibit_reactivation;
00739 
00741   internal::reactivation_avoidance_counter m_reactivation_avoidance;
00742 
00744   int m_unique_id;
00745 
00746   friend class transaction_base;
00747   result PQXX_PRIVATE Exec(const char[], int Retries);
00748   result pq_exec_prepared(const PGSTD::string &, int, const char *const *);
00749   void PQXX_PRIVATE RegisterTransaction(transaction_base *);
00750   void PQXX_PRIVATE UnregisterTransaction(transaction_base *) throw ();
00751   void PQXX_PRIVATE MakeEmpty(result &);
00752   bool PQXX_PRIVATE ReadCopyLine(PGSTD::string &);
00753   void PQXX_PRIVATE WriteCopyLine(const PGSTD::string &);
00754   void PQXX_PRIVATE EndCopyWrite();
00755   void PQXX_PRIVATE start_exec(const PGSTD::string &);
00756   internal::pq::PGresult *get_result();
00757   PGSTD::string esc(const char str[], size_t maxlen);
00758   PGSTD::string esc_raw(const unsigned char str[], size_t len);
00759 
00760   void PQXX_PRIVATE RawSetVar(const PGSTD::string &, const PGSTD::string &);
00761   void PQXX_PRIVATE AddVariables(const PGSTD::map<PGSTD::string,
00762       PGSTD::string> &);
00763 
00764   friend class largeobject;
00765   internal::pq::PGconn *RawConnection() const { return m_Conn; }
00766 
00767   friend class trigger;
00768   void AddTrigger(trigger *);
00769   void RemoveTrigger(trigger *) throw ();
00770 
00771   friend class pipeline;
00772   bool PQXX_PRIVATE consume_input() throw ();
00773   bool PQXX_PRIVATE is_busy() const throw ();
00774 
00775   friend class cursor_base;
00776   friend class dbtransaction;
00777   friend class internal::reactivation_avoidance_exemption;
00778 
00779   // Not allowed:
00780   connection_base(const connection_base &);
00781   connection_base &operator=(const connection_base &);
00782 };
00783 
00784 
00785 
00787 
00793 class PQXX_LIBEXPORT scoped_noticer
00794 {
00795 public:
00797 
00801   scoped_noticer(connection_base &c, PGSTD::auto_ptr<noticer> t) throw () :
00802     m_c(c), m_org(c.set_noticer(t)) { }
00803 
00804   ~scoped_noticer() { m_c.set_noticer(m_org); }
00805 
00806 protected:
00808 
00812   scoped_noticer(connection_base &c, noticer *t) throw () :
00813     m_c(c),
00814     m_org()
00815   {
00816     PGSTD::auto_ptr<noticer> x(t);
00817     PGSTD::auto_ptr<noticer> y(c.set_noticer(x));
00818     m_org = y;
00819   }
00820 
00821 private:
00822   connection_base &m_c;
00823   PGSTD::auto_ptr<noticer> m_org;
00824 
00826   scoped_noticer();
00827   scoped_noticer(const scoped_noticer &);
00828   scoped_noticer operator=(const scoped_noticer &);
00829 };
00830 
00831 
00833 class PQXX_LIBEXPORT disable_noticer : scoped_noticer
00834 {
00835 public:
00836   explicit disable_noticer(connection_base &c) :
00837     scoped_noticer(c, new nonnoticer) {}
00838 };
00839 
00840 
00841 namespace internal
00842 {
00843 
00845 class PQXX_LIBEXPORT reactivation_avoidance_exemption
00846 {
00847 public:
00848   explicit reactivation_avoidance_exemption(connection_base &C) :
00849     m_home(C),
00850     m_count(C.m_reactivation_avoidance.get()),
00851     m_open(C.is_open())
00852   {
00853     C.m_reactivation_avoidance.clear();
00854   }
00855 
00856   ~reactivation_avoidance_exemption()
00857   {
00858     // Don't leave connection open if reactivation avoidance is in effect and
00859     // the connection needed to be reactivated temporarily.
00860     if (m_count && !m_open) m_home.deactivate();
00861     m_home.m_reactivation_avoidance.add(m_count);
00862   }
00863 
00864   void close_connection() throw () { m_open = false; }
00865 
00866 private:
00867   connection_base &m_home;
00868   int m_count;
00869   bool m_open;
00870 };
00871 
00872 
00873 void wait_read(const internal::pq::PGconn *);
00874 void wait_read(const internal::pq::PGconn *, long seconds, long microseconds);
00875 void wait_write(const internal::pq::PGconn *);
00876 } // namespace pqxx::internal
00877 
00878 
00879 } // namespace pqxx
00880 
00881 #include "pqxx/compiler-internal-post.hxx"

Generated on Thu Feb 1 17:12:08 2007 for libpqxx by  doxygen 1.5.1