00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019 #include "pqxx/compiler-public.hxx"
00020 #include "pqxx/compiler-internal-pre.hxx"
00021
00022 #include <map>
00023 #include <memory>
00024
00025 #include "pqxx/except"
00026 #include "pqxx/prepared_statement"
00027 #include "pqxx/util"
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039 namespace pqxx
00040 {
00041 class result;
00042 class transaction_base;
00043 class trigger;
00044 class connectionpolicy;
00045
00046 namespace internal
00047 {
00048 class reactivation_avoidance_exemption;
00049
00050 class reactivation_avoidance_counter
00051 {
00052 public:
00053 reactivation_avoidance_counter() : m_counter(0) {}
00054
00055 void add(int n) throw () { m_counter += n; }
00056 void clear() throw () { m_counter = 0; }
00057 int get() const throw () { return m_counter; }
00058
00059 void give_to(reactivation_avoidance_counter &rhs) throw ()
00060 {
00061 rhs.add(m_counter);
00062 clear();
00063 }
00064
00065 private:
00066 int m_counter;
00067 };
00068
00069 }
00070
00076
00077
00082 struct PQXX_LIBEXPORT noticer : PGSTD::unary_function<const char[], void>
00083 {
00084 noticer(){}
00085 virtual ~noticer() throw () {}
00086 virtual void operator()(const char Msg[]) throw () =0;
00087 };
00088
00089
00091 struct PQXX_LIBEXPORT nonnoticer : noticer
00092 {
00093 nonnoticer(){}
00094 virtual void operator()(const char []) throw () {}
00095 };
00096
00102
00103
00123 class PQXX_LIBEXPORT connection_base
00124 {
00125 public:
00127 void disconnect() throw ();
00128
00130
00140 void activate();
00141
00143
00151 void deactivate();
00152
00154
00198 void inhibit_reactivation(bool inhibit)
00199 { m_inhibit_reactivation=inhibit; }
00200
00202
00206 bool is_open() const throw ();
00207
00209
00221 PGSTD::auto_ptr<noticer> set_noticer(PGSTD::auto_ptr<noticer> N)
00222 throw ();
00223 noticer *get_noticer() const throw () { return m_Noticer.get(); }
00224
00226 void process_notice(const char[]) throw ();
00228 void process_notice(const PGSTD::string &) throw ();
00229
00231 void trace(FILE *) throw ();
00232
00241
00242 const char *dbname();
00243
00245 const char *username();
00246
00248 const char *hostname();
00249
00251 const char *port();
00252
00254
00263 int backendpid() const throw ();
00264
00266
00280 int sock() const throw ();
00281
00283
00289 enum capability
00290 {
00292 cap_prepared_statements,
00293
00295 cap_create_table_with_oids,
00296
00298 cap_nested_transactions,
00299
00301 cap_cursor_scroll,
00303 cap_cursor_with_hold,
00305 cap_cursor_update,
00306
00308 cap_end
00309 };
00310
00311
00313
00326 bool supports(capability c) const throw () { return m_caps[c]; }
00327
00329
00341 int protocol_version() const throw ();
00342
00344
00358 int server_version() const throw ();
00359
00361
00367 void set_client_encoding(const PGSTD::string &Encoding)
00368 { set_variable("CLIENT_ENCODING", Encoding); }
00369
00371
00387 void set_variable(const PGSTD::string &Var,
00388 const PGSTD::string &Value);
00389
00391
00398 PGSTD::string get_variable(const PGSTD::string &);
00400
00401
00406
00407
00418 int get_notifs();
00419
00420
00422
00428 int await_notification();
00429
00431
00437 int await_notification(long seconds, long microseconds);
00439
00440
00472
00473
00503 prepare::declaration prepare(const PGSTD::string &name,
00504 const PGSTD::string &definition);
00505
00507 void unprepare(const PGSTD::string &name);
00508
00538
00539
00547 template<typename TRANSACTOR>
00548 void perform(const TRANSACTOR &T, int Attempts);
00549
00551
00554 template<typename TRANSACTOR>
00555 void perform(const TRANSACTOR &T) { perform(T, 3); }
00556
00561
00562
00565 PGSTD::string adorn_name(const PGSTD::string &);
00566
00567 #ifdef PQXX_DEPRECATED_HEADERS
00568
00576
00577 void Disconnect() throw () PQXX_DEPRECATED { disconnect(); }
00579 template<typename TRANSACTOR> void Perform(const TRANSACTOR &T, int A=3)
00580 PQXX_DEPRECATED { perform(T,A); }
00582 PGSTD::auto_ptr<noticer> SetNoticer(PGSTD::auto_ptr<noticer> N)
00583 PQXX_DEPRECATED { return set_noticer(N); }
00585 noticer *GetNoticer() const throw () PQXX_DEPRECATED { return get_noticer(); }
00587 void ProcessNotice(const char msg[]) throw () PQXX_DEPRECATED
00588 { return process_notice(msg); }
00590 void ProcessNotice(const PGSTD::string &msg) throw () PQXX_DEPRECATED
00591 { return process_notice(msg); }
00593 void Trace(FILE *F) PQXX_DEPRECATED { trace(F); }
00595 void GetNotifs() PQXX_DEPRECATED { get_notifs(); }
00597 const char *DbName() PQXX_DEPRECATED { return dbname(); }
00599 const char *UserName() PQXX_DEPRECATED { return username(); }
00601 const char *HostName() PQXX_DEPRECATED { return hostname(); }
00603 const char *Port() PQXX_DEPRECATED { return port(); }
00605 int BackendPID() const PQXX_DEPRECATED { return backendpid(); }
00607 void Activate() PQXX_DEPRECATED { activate(); }
00609 void Deactivate() PQXX_DEPRECATED { deactivate(); }
00611 void SetClientEncoding(const PGSTD::string &E) PQXX_DEPRECATED
00612 { set_client_encoding(E); }
00614 void SetVariable(const PGSTD::string &Var, const PGSTD::string &Val)
00615 PQXX_DEPRECATED { set_variable(Var, Val); }
00616
00620 #endif
00621
00622 protected:
00623 explicit connection_base(connectionpolicy &);
00624 void init();
00625
00626 void close() throw ();
00627 void wait_read() const;
00628 void wait_read(long seconds, long microseconds) const;
00629 void wait_write() const;
00630
00631 private:
00632 void PQXX_PRIVATE clearcaps() throw ();
00633 void PQXX_PRIVATE SetupState();
00634 void PQXX_PRIVATE check_result(const result &, const char Query[]);
00635
00636 void PQXX_PRIVATE InternalSetTrace() throw ();
00637 int PQXX_PRIVATE Status() const throw ();
00638 const char *ErrMsg() const throw ();
00639 void PQXX_PRIVATE Reset();
00640 void PQXX_PRIVATE RestoreVars();
00641 PGSTD::string PQXX_PRIVATE RawGetVar(const PGSTD::string &);
00642 void PQXX_PRIVATE process_notice_raw(const char msg[]) throw ();
00643 void switchnoticer(const PGSTD::auto_ptr<noticer> &) throw ();
00644
00645 void read_capabilities() throw ();
00646
00647 friend class subtransaction;
00648 void set_capability(capability) throw ();
00649
00650 prepare::internal::prepared_def &find_prepared(const PGSTD::string &);
00651
00652 friend class prepare::declaration;
00653 void prepare_param_declare(const PGSTD::string &statement,
00654 const PGSTD::string &sqltype,
00655 prepare::param_treatment);
00656
00657 result prepared_exec(const PGSTD::string &,
00658 const char *const[],
00659 const int[],
00660 int);
00661
00663 internal::pq::PGconn *m_Conn;
00664
00665 connectionpolicy &m_policy;
00666
00668 bool m_Completed;
00669
00671 internal::unique<transaction_base> m_Trans;
00672
00674 PGSTD::auto_ptr<noticer> m_Noticer;
00675
00677
00681 internal::pq::PQnoticeProcessor m_defaultNoticeProcessor;
00682
00684 FILE *m_Trace;
00685
00686 typedef PGSTD::multimap<PGSTD::string, pqxx::trigger *> TriggerList;
00688 TriggerList m_Triggers;
00689
00691 PGSTD::map<PGSTD::string, PGSTD::string> m_Vars;
00692
00693 typedef PGSTD::map<PGSTD::string, prepare::internal::prepared_def> PSMap;
00694
00696 PSMap m_prepared;
00697
00699 bool m_caps[cap_end];
00700
00702 bool m_inhibit_reactivation;
00703
00705 internal::reactivation_avoidance_counter m_reactivation_avoidance;
00706
00708 int m_unique_id;
00709
00710 friend class transaction_base;
00711 result PQXX_PRIVATE Exec(const char[], int Retries);
00712 result pq_exec_prepared(const PGSTD::string &, int, const char *const *);
00713 void PQXX_PRIVATE RegisterTransaction(transaction_base *);
00714 void PQXX_PRIVATE UnregisterTransaction(transaction_base *) throw ();
00715 void PQXX_PRIVATE MakeEmpty(result &);
00716 bool PQXX_PRIVATE ReadCopyLine(PGSTD::string &);
00717 void PQXX_PRIVATE WriteCopyLine(const PGSTD::string &);
00718 void PQXX_PRIVATE EndCopyWrite();
00719 void PQXX_PRIVATE start_exec(const PGSTD::string &);
00720 internal::pq::PGresult *get_result();
00721 PGSTD::string esc(const char str[], size_t maxlen);
00722 PGSTD::string esc_raw(const unsigned char str[], size_t len);
00723
00724 void PQXX_PRIVATE RawSetVar(const PGSTD::string &, const PGSTD::string &);
00725 void PQXX_PRIVATE AddVariables(const PGSTD::map<PGSTD::string,
00726 PGSTD::string> &);
00727
00728 friend class largeobject;
00729 internal::pq::PGconn *RawConnection() const { return m_Conn; }
00730
00731 friend class trigger;
00732 void AddTrigger(trigger *);
00733 void RemoveTrigger(trigger *) throw ();
00734
00735 friend class pipeline;
00736 bool PQXX_PRIVATE consume_input() throw ();
00737 bool PQXX_PRIVATE is_busy() const throw ();
00738
00739 friend class cursor_base;
00740 friend class dbtransaction;
00741 friend class internal::reactivation_avoidance_exemption;
00742
00743
00744 connection_base(const connection_base &);
00745 connection_base &operator=(const connection_base &);
00746 };
00747
00748
00749
00750 namespace internal
00751 {
00752
00754
00760 class PQXX_LIBEXPORT scoped_noticer
00761 {
00762 public:
00764
00768 scoped_noticer(connection_base &c, PGSTD::auto_ptr<noticer> t) throw () :
00769 m_c(c), m_org(c.set_noticer(t)) { }
00770
00771 ~scoped_noticer() { m_c.set_noticer(m_org); }
00772
00773 protected:
00775
00779 scoped_noticer(connection_base &c, noticer *t) throw () :
00780 m_c(c),
00781 m_org()
00782 {
00783 PGSTD::auto_ptr<noticer> x(t);
00784 PGSTD::auto_ptr<noticer> y(c.set_noticer(x));
00785 m_org = y;
00786 }
00787
00788 private:
00789 connection_base &m_c;
00790 PGSTD::auto_ptr<noticer> m_org;
00791
00793 scoped_noticer();
00794 scoped_noticer(const scoped_noticer &);
00795 scoped_noticer operator=(const scoped_noticer &);
00796 };
00797
00798
00800 class PQXX_LIBEXPORT disable_noticer : scoped_noticer
00801 {
00802 public:
00803 explicit disable_noticer(connection_base &c) :
00804 scoped_noticer(c, new nonnoticer) {}
00805 };
00806
00807
00809 class PQXX_LIBEXPORT reactivation_avoidance_exemption
00810 {
00811 public:
00812 explicit reactivation_avoidance_exemption(connection_base &C) :
00813 m_home(C),
00814 m_count(C.m_reactivation_avoidance.get()),
00815 m_open(C.is_open())
00816 {
00817 C.m_reactivation_avoidance.clear();
00818 }
00819
00820 ~reactivation_avoidance_exemption()
00821 {
00822
00823
00824 if (m_count && !m_open) m_home.deactivate();
00825 m_home.m_reactivation_avoidance.add(m_count);
00826 }
00827
00828 void close_connection() throw () { m_open = false; }
00829
00830 private:
00831 connection_base &m_home;
00832 int m_count;
00833 bool m_open;
00834 };
00835
00836
00837 void wait_read(const internal::pq::PGconn *);
00838 void wait_read(const internal::pq::PGconn *, long seconds, long microseconds);
00839 void wait_write(const internal::pq::PGconn *);
00840
00841 }
00842
00843
00844 }
00845
00846 #include "pqxx/compiler-internal-post.hxx"