connection_base.hxx
00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
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
00034
00035
00036
00037
00038
00039
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(){}
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(){}
00099 virtual void operator()(const char []) throw () {}
00100 };
00101
00106
00107
00125 PGSTD::string PQXX_LIBEXPORT encrypt_password(
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 ();
00168
00170
00174 bool is_open() const throw ();
00175
00186
00187
00197 void activate();
00198
00200
00208 void deactivate();
00209
00211
00255 void inhibit_reactivation(bool inhibit)
00256 { m_inhibit_reactivation=inhibit; }
00257
00259
00264 void simulate_failure();
00266
00276
00278
00290 PGSTD::auto_ptr<noticer> set_noticer(PGSTD::auto_ptr<noticer> N)
00291 throw ();
00292 noticer *get_noticer() const throw () { return m_Noticer.get(); }
00293
00295 void process_notice(const char[]) throw ();
00297 void process_notice(const PGSTD::string &) throw ();
00298
00300
00302 void trace(FILE *) throw ();
00303
00312
00313
00316 const char *dbname();
00317
00319
00322 const char *username();
00323
00325
00328 const char *hostname();
00329
00331
00334 const char *port();
00335
00337
00346 int backendpid() const throw ();
00347
00349
00363 int sock() const throw ();
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]; }
00421
00423
00435 int protocol_version() const throw ();
00436
00438
00450 int server_version() const throw ();
00452
00454
00460 void set_client_encoding(const PGSTD::string &Encoding)
00461 { set_variable("CLIENT_ENCODING", Encoding); }
00462
00464
00480 void set_variable(const PGSTD::string &Var,
00481 const PGSTD::string &Value);
00482
00484
00491 PGSTD::string get_variable(const PGSTD::string &);
00493
00494
00499
00500
00512 int get_notifs();
00513
00514
00516
00522 int await_notification();
00523
00525
00531 int await_notification(long seconds, long microseconds);
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);
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 &);
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 ®ister_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
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
00983
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 }
01001
01002
01003 }
01004
01005 #include "pqxx/compiler-internal-post.hxx"
01006
01007 #endif
01008