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 

Generated on Sat Aug 15 00:16:49 2009 for libpqxx by  doxygen 1.5.8