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 <bitset>
00026 #include <map>
00027 #include <memory>
00028
00029 #include "pqxx/except"
00030 #include "pqxx/prepared_statement"
00031 #include "pqxx/strconv"
00032 #include "pqxx/util"
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044 namespace pqxx
00045 {
00046 class result;
00047 class transaction_base;
00048 class notify_listener;
00049 class connectionpolicy;
00050
00051 namespace internal
00052 {
00053 class reactivation_avoidance_exemption;
00054 class sql_cursor;
00055
00056 class reactivation_avoidance_counter
00057 {
00058 public:
00059 reactivation_avoidance_counter() : m_counter(0) {}
00060
00061 void add(int n) throw () { m_counter += n; }
00062 void clear() throw () { m_counter = 0; }
00063 int get() const throw () { return m_counter; }
00064
00065 private:
00066 int m_counter;
00067 };
00068
00069 }
00070
00076
00077
00082 struct PQXX_LIBEXPORT PQXX_NOVTABLE noticer :
00083 PGSTD::unary_function<const char[], void>
00084 {
00085 noticer(){}
00086 virtual ~noticer() throw () {}
00087 virtual void operator()(const char Msg[]) throw () =0;
00088 };
00089
00090
00092 struct PQXX_LIBEXPORT nonnoticer : noticer
00093 {
00094 nonnoticer(){}
00095 virtual void operator()(const char []) throw () {}
00096 };
00097
00102
00103
00121 PGSTD::string PQXX_LIBEXPORT encrypt_password(
00122 const PGSTD::string &user,
00123 const PGSTD::string &password);
00124
00125
00126 namespace internal
00127 {
00128 namespace gate
00129 {
00130 class connection_dbtransaction;
00131 class connection_largeobject;
00132 class connection_notify_listener;
00133 class connection_parameterized_invocation;
00134 class connection_pipeline;
00135 class connection_prepare_declaration;
00136 class connection_prepare_invocation;
00137 class connection_reactivation_avoidance_exemption;
00138 class connection_sql_cursor;
00139 class connection_transaction;
00140 }
00141 }
00142
00143
00145
00178 class PQXX_LIBEXPORT connection_base
00179 {
00180 public:
00182 void disconnect() throw ();
00183
00185
00189 bool is_open() const throw ();
00190
00201
00202
00212 void activate();
00213
00215
00223 void deactivate();
00224
00226
00270 void inhibit_reactivation(bool inhibit)
00271 { m_inhibit_reactivation=inhibit; }
00272
00274
00279 void simulate_failure();
00281
00291
00293
00305 PGSTD::auto_ptr<noticer> set_noticer(PGSTD::auto_ptr<noticer> N)
00306 throw ();
00307 noticer *get_noticer() const throw () { return m_Noticer.get(); }
00308
00310 void process_notice(const char[]) throw ();
00312 void process_notice(const PGSTD::string &) throw ();
00313
00315
00317 void trace(FILE *) throw ();
00318
00327
00328
00331 const char *dbname();
00332
00334
00337 const char *username();
00338
00340
00343 const char *hostname();
00344
00346
00349 const char *port();
00350
00352
00361 int backendpid() const throw ();
00362
00364
00378 int sock() const throw ();
00379
00390
00392 enum capability
00393 {
00395 cap_prepared_statements,
00396
00398 cap_create_table_with_oids,
00399
00401 cap_nested_transactions,
00402
00404 cap_cursor_scroll,
00406 cap_cursor_with_hold,
00408 cap_cursor_update,
00410 cap_cursor_fetch_0,
00411
00413 cap_table_column,
00414
00416 cap_read_only_transactions,
00417
00419 cap_statement_varargs,
00420
00422 cap_prepare_unnamed_statement,
00423
00425 cap_parameterized_statements,
00426
00428 cap_end
00429 };
00430
00431
00433
00449 bool supports(capability c) const throw () { return m_caps.test(c); }
00450
00452
00464 int protocol_version() const throw ();
00465
00467
00479 int server_version() const throw ();
00481
00483
00489 void set_client_encoding(const PGSTD::string &Encoding)
00490 { set_variable("CLIENT_ENCODING", Encoding); }
00491
00493
00509 void set_variable(const PGSTD::string &Var,
00510 const PGSTD::string &Value);
00511
00513
00520 PGSTD::string get_variable(const PGSTD::string &);
00522
00523
00528
00529
00541 int get_notifs();
00542
00543
00545
00551 int await_notification();
00552
00554
00560 int await_notification(long seconds, long microseconds);
00562
00563
00600
00601
00643 prepare::declaration prepare(const PGSTD::string &name,
00644 const PGSTD::string &definition);
00645
00647
00653 prepare::declaration prepare(const PGSTD::string &definition);
00654
00656 void unprepare(const PGSTD::string &name);
00657
00659
00669 void prepare_now(const PGSTD::string &name);
00670
00700
00701
00709 template<typename TRANSACTOR>
00710 void perform(const TRANSACTOR &T, int Attempts);
00711
00713
00716 template<typename TRANSACTOR>
00717 void perform(const TRANSACTOR &T) { perform(T, 3); }
00718
00723
00724
00727 PGSTD::string adorn_name(const PGSTD::string &);
00728
00797
00798 PGSTD::string esc(const char str[]);
00799
00801 PGSTD::string esc(const char str[], size_t maxlen);
00802
00804 PGSTD::string esc(const PGSTD::string &str);
00805
00807 PGSTD::string esc_raw(const unsigned char str[], size_t len);
00808
00810
00811 template<typename T>
00812 PGSTD::string quote(const T &t)
00813 {
00814 if (string_traits<T>::is_null(t)) return "NULL";
00815 return "'" + this->esc(to_string(t)) + "'";
00816 }
00818
00820 void cancel_query();
00821
00822 protected:
00823 explicit connection_base(connectionpolicy &);
00824 void init();
00825
00826 void close() throw ();
00827 void wait_read() const;
00828 void wait_read(long seconds, long microseconds) const;
00829 void wait_write() const;
00830
00831 private:
00832 result make_result(internal::pq::PGresult *rhs, const PGSTD::string &query);
00833
00834 void PQXX_PRIVATE clearcaps() throw ();
00835 void PQXX_PRIVATE SetupState();
00836 void PQXX_PRIVATE check_result(const result &);
00837
00838 void PQXX_PRIVATE InternalSetTrace() throw ();
00839 int PQXX_PRIVATE Status() const throw ();
00840 const char *ErrMsg() const throw ();
00841 void PQXX_PRIVATE Reset();
00842 void PQXX_PRIVATE RestoreVars();
00843 PGSTD::string PQXX_PRIVATE RawGetVar(const PGSTD::string &);
00844 void PQXX_PRIVATE process_notice_raw(const char msg[]) throw ();
00845 void switchnoticer(const PGSTD::auto_ptr<noticer> &) throw ();
00846
00847 void read_capabilities() throw ();
00848
00849 prepare::internal::prepared_def &find_prepared(const PGSTD::string &);
00850
00851 friend class internal::gate::connection_prepare_declaration;
00852 void prepare_param_declare(
00853 const PGSTD::string &statement,
00854 const PGSTD::string &sqltype,
00855 prepare::param_treatment);
00856 void prepare_param_declare_varargs(
00857 const PGSTD::string &statement,
00858 prepare::param_treatment);
00859
00860 prepare::internal::prepared_def ®ister_prepared(const PGSTD::string &);
00861
00862 friend class internal::gate::connection_prepare_invocation;
00863 result prepared_exec(const PGSTD::string &,
00864 const char *const[],
00865 const int[],
00866 int);
00867 bool prepared_exists(const PGSTD::string &) const;
00868
00870 internal::pq::PGconn *m_Conn;
00871
00872 connectionpolicy &m_policy;
00873
00875 internal::unique<transaction_base> m_Trans;
00876
00878 PGSTD::auto_ptr<noticer> m_Noticer;
00879
00881
00885 internal::pq::PQnoticeProcessor m_defaultNoticeProcessor;
00886
00888 FILE *m_Trace;
00889
00890 typedef PGSTD::multimap<PGSTD::string, pqxx::notify_listener *> listenerlist;
00892 listenerlist m_listeners;
00893
00895 PGSTD::map<PGSTD::string, PGSTD::string> m_Vars;
00896
00897 typedef PGSTD::map<PGSTD::string, prepare::internal::prepared_def> PSMap;
00898
00900 PSMap m_prepared;
00901
00903 int m_serverversion;
00904
00906 internal::reactivation_avoidance_counter m_reactivation_avoidance;
00907
00909 int m_unique_id;
00910
00912 bool m_Completed;
00913
00915 bool m_inhibit_reactivation;
00916
00918 PGSTD::bitset<cap_end> m_caps;
00919
00920 friend class internal::gate::connection_transaction;
00921 result PQXX_PRIVATE Exec(const char[], int Retries);
00922 void PQXX_PRIVATE RegisterTransaction(transaction_base *);
00923 void PQXX_PRIVATE UnregisterTransaction(transaction_base *) throw ();
00924 bool PQXX_PRIVATE ReadCopyLine(PGSTD::string &);
00925 void PQXX_PRIVATE WriteCopyLine(const PGSTD::string &);
00926 void PQXX_PRIVATE EndCopyWrite();
00927 void PQXX_PRIVATE RawSetVar(const PGSTD::string &, const PGSTD::string &);
00928 void PQXX_PRIVATE AddVariables(const PGSTD::map<PGSTD::string,
00929 PGSTD::string> &);
00930
00931 friend class internal::gate::connection_largeobject;
00932 internal::pq::PGconn *RawConnection() const { return m_Conn; }
00933
00934 friend class internal::gate::connection_notify_listener;
00935 void add_listener(notify_listener *);
00936 void remove_listener(notify_listener *) throw ();
00937
00938 friend class internal::gate::connection_pipeline;
00939 void PQXX_PRIVATE start_exec(const PGSTD::string &);
00940 bool PQXX_PRIVATE consume_input() throw ();
00941 bool PQXX_PRIVATE is_busy() const throw ();
00942 int PQXX_PRIVATE encoding_code() throw ();
00943 internal::pq::PGresult *get_result();
00944
00945 friend class internal::gate::connection_dbtransaction;
00946
00947 friend class internal::gate::connection_sql_cursor;
00948 void add_reactivation_avoidance_count(int);
00949
00950 friend class internal::gate::connection_reactivation_avoidance_exemption;
00951
00952 friend class internal::gate::connection_parameterized_invocation;
00953 result parameterized_exec(
00954 const PGSTD::string &query,
00955 const char *const params[],
00956 const int paramlengths[],
00957 int nparams);
00958
00959
00960 connection_base(const connection_base &);
00961 connection_base &operator=(const connection_base &);
00962 };
00963
00964
00965
00967
00973 class PQXX_LIBEXPORT scoped_noticer
00974 {
00975 public:
00977
00981 scoped_noticer(connection_base &c, PGSTD::auto_ptr<noticer> t) throw () :
00982 m_c(c), m_org(c.set_noticer(t)) { }
00983
00984 ~scoped_noticer() { m_c.set_noticer(m_org); }
00985
00986 protected:
00988
00992 scoped_noticer(connection_base &c, noticer *t) throw () :
00993 m_c(c),
00994 m_org()
00995 {
00996 PGSTD::auto_ptr<noticer> x(t);
00997 PGSTD::auto_ptr<noticer> y(c.set_noticer(x));
00998 m_org = y;
00999 }
01000
01001 private:
01002 connection_base &m_c;
01003 PGSTD::auto_ptr<noticer> m_org;
01004
01006 scoped_noticer();
01007 scoped_noticer(const scoped_noticer &);
01008 scoped_noticer operator=(const scoped_noticer &);
01009 };
01010
01011
01013 class PQXX_LIBEXPORT disable_noticer : scoped_noticer
01014 {
01015 public:
01016 explicit disable_noticer(connection_base &c) :
01017 scoped_noticer(c, new nonnoticer) {}
01018 };
01019
01020
01021 namespace internal
01022 {
01023
01025 class PQXX_LIBEXPORT reactivation_avoidance_exemption
01026 {
01027 public:
01028 explicit reactivation_avoidance_exemption(connection_base &C);
01029 ~reactivation_avoidance_exemption();
01030
01031 void close_connection() throw () { m_open = false; }
01032
01033 private:
01034 connection_base &m_home;
01035 int m_count;
01036 bool m_open;
01037 };
01038
01039
01040 void wait_read(const internal::pq::PGconn *);
01041 void wait_read(const internal::pq::PGconn *, long seconds, long microseconds);
01042 void wait_write(const internal::pq::PGconn *);
01043 }
01044
01045
01046 }
01047
01048 #include "pqxx/compiler-internal-post.hxx"
01049
01050 #endif
01051