# connection_base.hxx

    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-2008, 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 #ifndef PQXX_H_CONNECTION_BASE
    00020 #define PQXX_H_CONNECTION_BASE
    00021
    00022 #include "pqxx/compiler-public.hxx"
    00023 #include "pqxx/compiler-internal-pre.hxx"
    00024
    00025 #include <map>
    00026 #include <memory>
    00027
    00028 #include "pqxx/except"
    00029 #include "pqxx/prepared_statement"
    00030 #include "pqxx/util"
    00031
    00032
    00033 /* Use of the libpqxx library starts here.
    00034  *
    00035  * Everything that can be done with a database through libpqxx must go through
    00036  * a connection object derived from connection_base.
    00037  */
    00038
    00039 /* Methods tested in eg. self-test program test1 are marked with "//[t1]"
    00040  */
    00041
    00042 namespace pqxx
    00043 {
    00044 class result;
    00045 class transaction_base;
    00046 class notify_listener;
    00047 class connectionpolicy;
    00048
    00049 namespace internal
    00050 {
    00051 class reactivation_avoidance_exemption;
    00052 class sql_cursor;
    00053
    00054 class reactivation_avoidance_counter
    00055 {
    00056 public:
    00057   reactivation_avoidance_counter() : m_counter(0) {}
    00058
    00059   void add(int n) throw () { m_counter += n; }
    00060   void clear() throw () { m_counter = 0; }
    00061   int get() const throw () { return m_counter; }
    00062
    00063   void give_to(reactivation_avoidance_counter &rhs) throw ()
    00064   {
    00065     rhs.add(m_counter);
    00066     clear();
    00067   }
    00068
    00069 private:
    00070   int m_counter;
    00071 };
    00072
    00073 }
    00074
    00080
    00081
    00086 struct PQXX_LIBEXPORT PQXX_NOVTABLE noticer :
    00087   PGSTD::unary_function<const char[], void>
    00088 {
    00089   noticer(){}           // Silences bogus warning in some gcc versions
    00090   virtual ~noticer() throw () {}
    00091   virtual void operator()(const char Msg[]) throw () =0;
    00092 };
    00093
    00094
    00096 struct PQXX_LIBEXPORT nonnoticer : noticer
    00097 {
    00098   nonnoticer(){}        // Silences bogus warning in some gcc versions
    00099   virtual void operator()(const char []) throw () {}
    00100 };
    00101
    00106
    00107
    00125 PGSTD::string PQXX_LIBEXPORT encrypt_password(                          //[t0]
    00126         const PGSTD::string &user,
    00127         const PGSTD::string &password);
    00128
    00130
    00163 class PQXX_LIBEXPORT connection_base
    00164 {
    00165 public:
    00167   void disconnect() throw ();                                           //[t2]
    00168
    00170
    00174   bool is_open() const throw ();                                        //[t1]
    00175
    00186
    00187
    00197   void activate();                                                      //[t12]
    00198
    00200
    00208   void deactivate();                                                    //[t12]
    00209
    00211
    00255   void inhibit_reactivation(bool inhibit)                               //[t86]
    00256         { m_inhibit_reactivation=inhibit; }
    00257
    00259
    00264   void simulate_failure();                                              //[t94]
    00266
    00276
    00278
    00290   PGSTD::auto_ptr<noticer> set_noticer(PGSTD::auto_ptr<noticer> N)
    00291     throw ();                                                           //[t14]
    00292   noticer *get_noticer() const throw () { return m_Noticer.get(); }     //[t14]
    00293
    00295   void process_notice(const char[]) throw ();                           //[t14]
    00297   void process_notice(const PGSTD::string &) throw ();                  //[t14]
    00298
    00300
    00302   void trace(FILE *) throw ();                                          //[t3]
    00303
    00312
    00313
    00316   const char *dbname();                                                 //[t1]
    00317
    00319
    00322   const char *username();                                               //[t1]
    00323
    00325
    00328   const char *hostname();                                               //[t1]
    00329
    00331
    00334   const char *port();                                                   //[t1]
    00335
    00337
    00346   int backendpid() const throw ();                                      //[t1]
    00347
    00349
    00363   int sock() const throw ();                                            //[t87]
    00364
    00375
    00377   enum capability
    00378   {
    00380     cap_prepared_statements,
    00381
    00383     cap_create_table_with_oids,
    00384
    00386     cap_nested_transactions,
    00387
    00389     cap_cursor_scroll,
    00391     cap_cursor_with_hold,
    00393     cap_cursor_update,
    00394
    00396     cap_table_column,
    00397
    00399     cap_end
    00400   };
    00401
    00402
    00404
    00420   bool supports(capability c) const throw () { return m_caps[c]; }      //[t88]
    00421
    00423
    00435   int protocol_version() const throw ();                                //[t1]
    00436
    00438
    00450   int server_version() const throw ();                                  //[t1]
    00452
    00454
    00460   void set_client_encoding(const PGSTD::string &Encoding)               //[t7]
    00461         { set_variable("CLIENT_ENCODING", Encoding); }
    00462
    00464
    00480   void set_variable(const PGSTD::string &Var,
    00481                     const PGSTD::string &Value);                        //[t60]
    00482
    00484
    00491   PGSTD::string get_variable(const PGSTD::string &);                    //[t60]
    00493
    00494
    00499
    00500
    00512   int get_notifs();                                                     //[t4]
    00513
    00514
    00516
    00522   int await_notification();                                             //[t78]
    00523
    00525
    00531   int await_notification(long seconds, long microseconds);              //[t79]
    00533
    00534
    00566
    00567
    00609   prepare::declaration prepare(const PGSTD::string &name,
    00610         const PGSTD::string &definition);
    00611
    00613   void unprepare(const PGSTD::string &name);
    00614
    00616
    00626   void prepare_now(const PGSTD::string &name);
    00627
    00657
    00658
    00666   template<typename TRANSACTOR>
    00667   void perform(const TRANSACTOR &T, int Attempts);                      //[t4]
    00668
    00670
    00673   template<typename TRANSACTOR>
    00674   void perform(const TRANSACTOR &T) { perform(T, 3); }
    00675
    00680
    00681
    00684   PGSTD::string adorn_name(const PGSTD::string &);                      //[90]
    00685
    00754
    00755   PGSTD::string esc(const char str[]);
    00756
    00758   PGSTD::string esc(const char str[], size_t maxlen);
    00759
    00761   PGSTD::string esc(const PGSTD::string &str);
    00762
    00764   PGSTD::string esc_raw(const unsigned char str[], size_t len);
    00765
    00767
    00768   template<typename T>
    00769   PGSTD::string quote(const T &t)
    00770   {
    00771     if (string_traits<T>::is_null(t)) return "NULL";
    00772     return "'" + this->esc(to_string(t)) + "'";
    00773   }
    00775
    00776 protected:
    00777   explicit connection_base(connectionpolicy &);
    00778   void init();
    00779
    00780   void close() throw ();
    00781   void wait_read() const;
    00782   void wait_read(long seconds, long microseconds) const;
    00783   void wait_write() const;
    00784
    00785 private:
    00786   void PQXX_PRIVATE clearcaps() throw ();
    00787   void PQXX_PRIVATE SetupState();
    00788   void PQXX_PRIVATE check_result(const result &);
    00789
    00790   void PQXX_PRIVATE InternalSetTrace() throw ();
    00791   int PQXX_PRIVATE Status() const throw ();
    00792   const char *ErrMsg() const throw ();
    00793   void PQXX_PRIVATE Reset();
    00794   void PQXX_PRIVATE RestoreVars();
    00795   PGSTD::string PQXX_PRIVATE RawGetVar(const PGSTD::string &);
    00796   void PQXX_PRIVATE process_notice_raw(const char msg[]) throw ();
    00797   void switchnoticer(const PGSTD::auto_ptr<noticer> &) throw ();
    00798
    00799   void read_capabilities() throw ();
    00800
    00801   friend class subtransaction;
    00802   void set_capability(capability) throw ();
    00803
    00804   prepare::internal::prepared_def &find_prepared(const PGSTD::string &);
    00805
    00806   friend class prepare::declaration;
    00807   void prepare_param_declare(const PGSTD::string &statement,
    00808       const PGSTD::string &sqltype,
    00809       prepare::param_treatment);
    00810
    00811   prepare::internal::prepared_def &register_prepared(const PGSTD::string &);
    00812   result prepared_exec(const PGSTD::string &,
    00813         const char *const[],
    00814         const int[],
    00815         int);
    00816
    00817   friend class arrayvalue;
    00818   int PQXX_PRIVATE encoding_code() throw ();
    00819
    00821   internal::pq::PGconn *m_Conn;
    00822
    00823   connectionpolicy &m_policy;
    00824
    00826   bool m_Completed;
    00827
    00829   internal::unique<transaction_base> m_Trans;
    00830
    00832   PGSTD::auto_ptr<noticer> m_Noticer;
    00833
    00835
    00839   internal::pq::PQnoticeProcessor m_defaultNoticeProcessor;
    00840
    00842   FILE *m_Trace;
    00843
    00844   typedef PGSTD::multimap<PGSTD::string, pqxx::notify_listener *> listenerlist;
    00846   listenerlist m_listeners;
    00847
    00849   PGSTD::map<PGSTD::string, PGSTD::string> m_Vars;
    00850
    00851   typedef PGSTD::map<PGSTD::string, prepare::internal::prepared_def> PSMap;
    00852
    00854   PSMap m_prepared;
    00855
    00857   int m_serverversion;
    00858
    00860   bool m_caps[cap_end];
    00861
    00863   bool m_inhibit_reactivation;
    00864
    00866   internal::reactivation_avoidance_counter m_reactivation_avoidance;
    00867
    00869   int m_unique_id;
    00870
    00871   friend class transaction_base;
    00872   result PQXX_PRIVATE Exec(const char[], int Retries);
    00873   result pq_exec_prepared(const PGSTD::string &, int, const char *const *);
    00874   void PQXX_PRIVATE RegisterTransaction(transaction_base *);
    00875   void PQXX_PRIVATE UnregisterTransaction(transaction_base *) throw ();
    00876   void PQXX_PRIVATE MakeEmpty(result &);
    00877   bool PQXX_PRIVATE ReadCopyLine(PGSTD::string &);
    00878   void PQXX_PRIVATE WriteCopyLine(const PGSTD::string &);
    00879   void PQXX_PRIVATE EndCopyWrite();
    00880   void PQXX_PRIVATE start_exec(const PGSTD::string &);
    00881   internal::pq::PGresult *get_result();
    00882
    00883   void PQXX_PRIVATE RawSetVar(const PGSTD::string &, const PGSTD::string &);
    00884   void PQXX_PRIVATE AddVariables(const PGSTD::map<PGSTD::string,
    00885       PGSTD::string> &);
    00886
    00887   friend class largeobject;
    00888   internal::pq::PGconn *RawConnection() const { return m_Conn; }
    00889
    00890   friend class notify_listener;
    00891   void add_listener(notify_listener *);
    00892   void remove_listener(notify_listener *) throw ();
    00893
    00894   friend class pipeline;
    00895   bool PQXX_PRIVATE consume_input() throw ();
    00896   bool PQXX_PRIVATE is_busy() const throw ();
    00897   void cancel_query();
    00898
    00899   friend class internal::sql_cursor;
    00900   friend class dbtransaction;
    00901   friend class internal::reactivation_avoidance_exemption;
    00902
    00903   // Not allowed:
    00904   connection_base(const connection_base &);
    00905   connection_base &operator=(const connection_base &);
    00906 };
    00907
    00908
    00909
    00911
    00917 class PQXX_LIBEXPORT scoped_noticer
    00918 {
    00919 public:
    00921
    00925   scoped_noticer(connection_base &c, PGSTD::auto_ptr<noticer> t) throw () :
    00926     m_c(c), m_org(c.set_noticer(t)) { }
    00927
    00928   ~scoped_noticer() { m_c.set_noticer(m_org); }
    00929
    00930 protected:
    00932
    00936   scoped_noticer(connection_base &c, noticer *t) throw () :
    00937     m_c(c),
    00938     m_org()
    00939   {
    00940     PGSTD::auto_ptr<noticer> x(t);
    00941     PGSTD::auto_ptr<noticer> y(c.set_noticer(x));
    00942     m_org = y;
    00943   }
    00944
    00945 private:
    00946   connection_base &m_c;
    00947   PGSTD::auto_ptr<noticer> m_org;
    00948
    00950   scoped_noticer();
    00951   scoped_noticer(const scoped_noticer &);
    00952   scoped_noticer operator=(const scoped_noticer &);
    00953 };
    00954
    00955
    00957 class PQXX_LIBEXPORT disable_noticer : scoped_noticer
    00958 {
    00959 public:
    00960   explicit disable_noticer(connection_base &c) :
    00961     scoped_noticer(c, new nonnoticer) {}
    00962 };
    00963
    00964
    00965 namespace internal
    00966 {
    00967
    00969 class PQXX_LIBEXPORT reactivation_avoidance_exemption
    00970 {
    00971 public:
    00972   explicit reactivation_avoidance_exemption(connection_base &C) :
    00973     m_home(C),
    00974     m_count(C.m_reactivation_avoidance.get()),
    00975     m_open(C.is_open())
    00976   {
    00977     C.m_reactivation_avoidance.clear();
    00978   }
    00979
    00980   ~reactivation_avoidance_exemption()
    00981   {
    00982     // Don't leave connection open if reactivation avoidance is in effect and
    00983     // the connection needed to be reactivated temporarily.
    00984     if (m_count && !m_open) m_home.deactivate();
    00985     m_home.m_reactivation_avoidance.add(m_count);
    00986   }
    00987
    00988   void close_connection() throw () { m_open = false; }
    00989
    00990 private:
    00991   connection_base &m_home;
    00992   int m_count;
    00993   bool m_open;
    00994 };
    00995
    00996
    00997 void wait_read(const internal::pq::PGconn *);
    00998 void wait_read(const internal::pq::PGconn *, long seconds, long microseconds);
    00999 void wait_write(const internal::pq::PGconn *);
    01000 } // namespace pqxx::internal
    01001
    01002
    01003 } // namespace pqxx
    01004
    01005 #include "pqxx/compiler-internal-post.hxx"
    01006
    01007 #endif
    01008