libpqxx 4.0
|
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 ®ister_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