# 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"