libpqxx 4.0
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-2011, 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 <bitset>
00026 #include <list>
00027 #include <map>
00028 #include <memory>
00029 
00030 #include "pqxx/errorhandler"
00031 #include "pqxx/except"
00032 #include "pqxx/prepared_statement"
00033 #include "pqxx/strconv"
00034 #include "pqxx/util"
00035 
00036 
00037 /* Use of the libpqxx library starts here.
00038  *
00039  * Everything that can be done with a database through libpqxx must go through
00040  * a connection object derived from connection_base.
00041  */
00042 
00043 /* Methods tested in eg. self-test program test1 are marked with "//[t1]"
00044  */
00045 
00046 namespace pqxx
00047 {
00048 class binarystring;
00049 class connectionpolicy;
00050 class notification_receiver;
00051 class result;
00052 class transaction_base;
00053 
00054 namespace internal
00055 {
00056 class reactivation_avoidance_exemption;
00057 class sql_cursor;
00058 
00059 class reactivation_avoidance_counter
00060 {
00061 public:
00062   reactivation_avoidance_counter() : m_counter(0) {}
00063 
00064   void add(int n) throw () { m_counter += n; }
00065   void clear() throw () { m_counter = 0; }
00066   int get() const throw () { return m_counter; }
00067 
00068 private:
00069   int m_counter;
00070 };
00071 
00072 }
00073 
00074 
00076 
00094 PGSTD::string PQXX_LIBEXPORT encrypt_password(                          //[t0]
00095         const PGSTD::string &user,
00096         const PGSTD::string &password);
00097 
00098 
00099 namespace internal
00100 {
00101 namespace gate
00102 {
00103 class connection_dbtransaction;
00104 class connection_errorhandler;
00105 class connection_largeobject;
00106 class connection_notification_receiver;
00107 class connection_parameterized_invocation;
00108 class connection_pipeline;
00109 class connection_prepare_invocation;
00110 class connection_reactivation_avoidance_exemption;
00111 class connection_sql_cursor;
00112 class connection_transaction;
00113 } // namespace pqxx::internal::gate
00114 } // namespace pqxx::internal
00115 
00116 
00118 
00151 class PQXX_LIBEXPORT connection_base
00152 {
00153 public:
00155   void disconnect() throw ();                                           //[t2]
00156 
00158 
00162   bool PQXX_PURE is_open() const throw ();                              //[t1]
00163 
00174 
00175 
00185   void activate();                                                      //[t12]
00186 
00188 
00196   void deactivate();                                                    //[t12]
00197 
00199 
00243   void inhibit_reactivation(bool inhibit)                               //[t86]
00244         { m_inhibit_reactivation=inhibit; }
00245 
00247 
00252   void simulate_failure();                                              //[t94]
00254 
00256   void process_notice(const char[]) throw ();                           //[t14]
00258   void process_notice(const PGSTD::string &) throw ();                  //[t14]
00259 
00261   void trace(PGSTD::FILE *) throw ();                                   //[t3]
00262 
00271 
00272 
00275   const char *dbname();                                                 //[t1]
00276 
00278 
00281   const char *username();                                               //[t1]
00282 
00284 
00287   const char *hostname();                                               //[t1]
00288 
00290 
00293   const char *port();                                                   //[t1]
00294 
00296 
00305   int PQXX_PURE backendpid() const throw ();                            //[t1]
00306 
00308 
00322   int PQXX_PURE sock() const throw ();                                  //[t87]
00323 
00334  
00336   enum capability
00337   {
00339     cap_prepared_statements,
00340 
00342     cap_create_table_with_oids,
00343 
00345     cap_nested_transactions,
00346 
00348     cap_cursor_scroll,
00350     cap_cursor_with_hold,
00352     cap_cursor_update,
00354     cap_cursor_fetch_0,
00355 
00357     cap_table_column,
00358 
00360     cap_read_only_transactions,
00361 
00363     cap_statement_varargs,
00364 
00366     cap_prepare_unnamed_statement,
00367 
00369     cap_parameterized_statements,
00370 
00372     cap_notify_payload,
00373 
00375     cap_end
00376   };
00377 
00378 
00380 
00396   bool supports(capability c) const throw () { return m_caps.test(c); } //[t88]
00397 
00399 
00411   int PQXX_PURE protocol_version() const throw ();                      //[t1]
00412 
00414 
00426   int PQXX_PURE server_version() const throw ();                        //[t1]
00428 
00430 
00436   void set_client_encoding(const PGSTD::string &Encoding)               //[t7]
00437         { set_variable("CLIENT_ENCODING", Encoding); }
00438 
00440 
00456   void set_variable(const PGSTD::string &Var,
00457                     const PGSTD::string &Value);                        //[t60]
00458 
00460 
00467   PGSTD::string get_variable(const PGSTD::string &);                    //[t60]
00469 
00470 
00475 
00476 
00488   int get_notifs();                                                     //[t4]
00489 
00490 
00492 
00498   int await_notification();                                             //[t78]
00499 
00501 
00507   int await_notification(long seconds, long microseconds);              //[t79]
00509 
00510 
00547 
00548 
00581   void prepare(const PGSTD::string &name, const PGSTD::string &definition);
00582 
00584 
00590   void prepare(const PGSTD::string &definition);
00591 
00593   void unprepare(const PGSTD::string &name);
00594 
00596 
00606   void prepare_now(const PGSTD::string &name);
00607 
00637 
00638 
00646   template<typename TRANSACTOR>
00647   void perform(const TRANSACTOR &T, int Attempts);                      //[t4]
00648 
00650 
00653   template<typename TRANSACTOR>
00654   void perform(const TRANSACTOR &T) { perform(T, 3); }
00655 
00660 
00661 
00664   PGSTD::string adorn_name(const PGSTD::string &);                      //[90]
00665 
00734 
00735   PGSTD::string esc(const char str[]);
00736 
00738   PGSTD::string esc(const char str[], size_t maxlen);
00739 
00741   PGSTD::string esc(const PGSTD::string &str);
00742 
00744   PGSTD::string esc_raw(const unsigned char str[], size_t len);
00745 
00747   PGSTD::string quote_raw(const unsigned char str[], size_t len);
00748 
00750   PGSTD::string quote_name(const PGSTD::string &identifier);
00751 
00753 
00754   template<typename T>
00755   PGSTD::string quote(const T &t)
00756   {
00757     if (string_traits<T>::is_null(t)) return "NULL";
00758     return "'" + this->esc(to_string(t)) + "'";
00759   }
00760 
00761   PGSTD::string quote(const binarystring &);
00763 
00765   void cancel_query();
00766 
00768   enum error_verbosity
00769   {
00770       // These values must match those in libpq's PGVerbosity enum.
00771       terse=0,
00772       normal=1,
00773       verbose=2
00774   };
00775 
00777 
00785   void set_verbosity(error_verbosity verbosity) throw();
00787   error_verbosity get_verbosity() const throw() {return m_verbosity;}
00788 
00790 
00802   PGSTD::vector<errorhandler *> get_errorhandlers() const;
00803 
00804 protected:
00805   explicit connection_base(connectionpolicy &);
00806   void init();
00807 
00808   void close() throw ();
00809   void wait_read() const;
00810   void wait_read(long seconds, long microseconds) const;
00811   void wait_write() const;
00812 
00813 private:
00814 
00815   result make_result(internal::pq::PGresult *rhs, const PGSTD::string &query);
00816 
00817   void PQXX_PRIVATE clearcaps() throw ();
00818   void PQXX_PRIVATE SetupState();
00819   void PQXX_PRIVATE check_result(const result &);
00820 
00821   void PQXX_PRIVATE InternalSetTrace() throw ();
00822   int PQXX_PRIVATE PQXX_PURE Status() const throw ();
00823   const char * PQXX_PURE ErrMsg() const throw ();
00824   void PQXX_PRIVATE Reset();
00825   void PQXX_PRIVATE RestoreVars();
00826   PGSTD::string PQXX_PRIVATE RawGetVar(const PGSTD::string &);
00827   void PQXX_PRIVATE process_notice_raw(const char msg[]) throw ();
00828 
00829   void read_capabilities() throw ();
00830 
00831   prepare::internal::prepared_def &find_prepared(const PGSTD::string &);
00832 
00833   prepare::internal::prepared_def &register_prepared(const PGSTD::string &);
00834 
00835   friend class internal::gate::connection_prepare_invocation;
00836   result prepared_exec(const PGSTD::string &,
00837         const char *const[],
00838         const int[],
00839         const int[],
00840         int);
00841   bool prepared_exists(const PGSTD::string &) const;
00842 
00844   internal::pq::PGconn *m_Conn;
00845 
00846   connectionpolicy &m_policy;
00847 
00849   internal::unique<transaction_base> m_Trans;
00850 
00851   PGSTD::list<errorhandler *> m_errorhandlers;
00852 
00854   PGSTD::FILE *m_Trace;
00855 
00856   typedef PGSTD::multimap<PGSTD::string, pqxx::notification_receiver *>
00857         receiver_list;
00859   receiver_list m_receivers;
00860 
00862   PGSTD::map<PGSTD::string, PGSTD::string> m_Vars;
00863 
00864   typedef PGSTD::map<PGSTD::string, prepare::internal::prepared_def> PSMap;
00865 
00867   PSMap m_prepared;
00868 
00870   int m_serverversion;
00871 
00873   internal::reactivation_avoidance_counter m_reactivation_avoidance;
00874 
00876   int m_unique_id;
00877 
00879   bool m_Completed;
00880 
00882   bool m_inhibit_reactivation;
00883 
00885   PGSTD::bitset<cap_end> m_caps;
00886 
00888   error_verbosity m_verbosity;
00889 
00890   friend class internal::gate::connection_errorhandler;
00891   void PQXX_PRIVATE register_errorhandler(errorhandler *);
00892   void PQXX_PRIVATE unregister_errorhandler(errorhandler *) throw ();
00893 
00894   friend class internal::gate::connection_transaction;
00895   result PQXX_PRIVATE Exec(const char[], int Retries);
00896   void PQXX_PRIVATE RegisterTransaction(transaction_base *);
00897   void PQXX_PRIVATE UnregisterTransaction(transaction_base *) throw ();
00898   bool PQXX_PRIVATE ReadCopyLine(PGSTD::string &);
00899   void PQXX_PRIVATE WriteCopyLine(const PGSTD::string &);
00900   void PQXX_PRIVATE EndCopyWrite();
00901   void PQXX_PRIVATE RawSetVar(const PGSTD::string &, const PGSTD::string &);
00902   void PQXX_PRIVATE AddVariables(const PGSTD::map<PGSTD::string,
00903       PGSTD::string> &);
00904 
00905   friend class internal::gate::connection_largeobject;
00906   internal::pq::PGconn *RawConnection() const { return m_Conn; }
00907 
00908   friend class internal::gate::connection_notification_receiver;
00909   void add_receiver(notification_receiver *);
00910   void remove_receiver(notification_receiver *) throw ();
00911 
00912   friend class internal::gate::connection_pipeline;
00913   void PQXX_PRIVATE start_exec(const PGSTD::string &);
00914   bool PQXX_PRIVATE consume_input() throw ();
00915   bool PQXX_PRIVATE is_busy() const throw ();
00916   int PQXX_PRIVATE encoding_code();
00917   internal::pq::PGresult *get_result();
00918 
00919   friend class internal::gate::connection_dbtransaction;
00920 
00921   friend class internal::gate::connection_sql_cursor;
00922   void add_reactivation_avoidance_count(int);
00923 
00924   friend class internal::gate::connection_reactivation_avoidance_exemption;
00925 
00926   friend class internal::gate::connection_parameterized_invocation;
00927   result parameterized_exec(
00928         const PGSTD::string &query,
00929         const char *const params[],
00930         const int paramlengths[],
00931         const int binaries[],
00932         int nparams);
00933 
00934   // Not allowed:
00935   connection_base(const connection_base &);
00936   connection_base &operator=(const connection_base &);
00937 };
00938 
00939 
00940 
00941 #ifdef PQXX_HAVE_AUTO_PTR
00942 
00943 struct PQXX_LIBEXPORT PQXX_NOVTABLE noticer :
00944   PGSTD::unary_function<const char[], void>
00945 {
00946   virtual ~noticer() throw () {}
00947   virtual void operator()(const char[]) throw () =0;
00948 };
00950 struct PQXX_LIBEXPORT nonnoticer : noticer
00951 {
00952   virtual void operator()(const char[]) throw () {}
00953 };
00955 class PQXX_LIBEXPORT scoped_noticer : errorhandler
00956 {
00957 public:
00958   scoped_noticer(connection_base &c, PGSTD::auto_ptr<noticer> t) throw () :
00959     errorhandler(c), m_noticer(t.release()) {}
00960 protected:
00961   scoped_noticer(connection_base &c, noticer *t) throw () :
00962     errorhandler(c), m_noticer(t) {}
00963   virtual bool operator()(const char msg[]) throw ()
00964   {
00965     (*m_noticer)(msg);
00966     return false;
00967   }
00968 private:
00969   PGSTD::auto_ptr<noticer> m_noticer;
00970 };
00972 class PQXX_LIBEXPORT disable_noticer : scoped_noticer
00973 {
00974 public:
00975   explicit disable_noticer(connection_base &c) :
00976     scoped_noticer(c, new nonnoticer) {}
00977 };
00978 #endif
00979 
00980 
00981 namespace internal
00982 {
00983 
00985 class PQXX_LIBEXPORT reactivation_avoidance_exemption
00986 {
00987 public:
00988   explicit reactivation_avoidance_exemption(connection_base &C);
00989   ~reactivation_avoidance_exemption();
00990 
00991   void close_connection() throw () { m_open = false; }
00992 
00993 private:
00994   connection_base &m_home;
00995   int m_count;
00996   bool m_open;
00997 };
00998 
00999 
01000 void wait_read(const internal::pq::PGconn *);
01001 void wait_read(const internal::pq::PGconn *, long seconds, long microseconds);
01002 void wait_write(const internal::pq::PGconn *);
01003 } // namespace pqxx::internal
01004 
01005 
01006 } // namespace pqxx
01007 
01008 #include "pqxx/compiler-internal-post.hxx"
01009 
01010 #endif