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
00075
00076
00081 struct PQXX_LIBEXPORT noticer : PGSTD::unary_function<const char[], void>
00082 {
00083 noticer(){}
00084 virtual ~noticer() throw () {}
00085 virtual void operator()(const char Msg[]) throw () =0;
00086 };
00087
00088
00090 struct PQXX_LIBEXPORT nonnoticer : noticer
00091 {
00092 nonnoticer(){}
00093 virtual void operator()(const char []) throw () {}
00094 };
00096
00097
00102
00103
00123 class PQXX_LIBEXPORT connection_base
00124 {
00125 public:
00130
00131 void disconnect() throw ();
00132
00134
00144 void activate();
00145
00147
00155 void deactivate();
00156
00158
00202 void inhibit_reactivation(bool inhibit)
00203 { m_inhibit_reactivation=inhibit; }
00204
00206
00210 bool is_open() const throw ();
00212
00217
00218
00230 PGSTD::auto_ptr<noticer> set_noticer(PGSTD::auto_ptr<noticer> N)
00231 throw ();
00232 noticer *get_noticer() const throw () { return m_Noticer.get(); }
00233
00235 void process_notice(const char[]) throw ();
00237 void process_notice(const PGSTD::string &) throw ();
00239
00241 void trace(FILE *) throw ();
00242
00251
00252 const char *dbname();
00253
00255 const char *username();
00256
00258 const char *hostname();
00259
00261 const char *port();
00262
00264
00273 int backendpid() const throw ();
00274
00276
00290 int sock() const throw ();
00291
00293
00299 enum capability
00300 {
00302 cap_prepared_statements,
00303
00305 cap_create_table_with_oids,
00306
00308 cap_nested_transactions,
00309
00311 cap_cursor_scroll,
00313 cap_cursor_with_hold,
00315 cap_cursor_update,
00316
00318 cap_end
00319 };
00320
00321
00323
00336 bool supports(capability c) const throw () { return m_caps[c]; }
00337
00339
00345 void set_client_encoding(const PGSTD::string &Encoding)
00346 { set_variable("CLIENT_ENCODING", Encoding); }
00347
00349
00365 void set_variable(const PGSTD::string &Var,
00366 const PGSTD::string &Value);
00367
00369
00376 PGSTD::string get_variable(const PGSTD::string &);
00378
00379
00384
00385
00396 int get_notifs();
00397
00398
00400
00406 int await_notification();
00407
00409
00415 int await_notification(long seconds, long microseconds);
00417
00418
00448
00449
00479 prepare::declaration prepare(const PGSTD::string &name,
00480 const PGSTD::string &definition);
00481
00483 void unprepare(const PGSTD::string &name);
00485
00486
00503
00504
00508 template<typename TRANSACTOR>
00509 void perform(const TRANSACTOR &T, int Attempts);
00510
00512
00515 template<typename TRANSACTOR>
00516 void perform(const TRANSACTOR &T) { perform(T, 3); }
00518
00520
00523 PGSTD::string adorn_name(const PGSTD::string &);
00524
00525 #ifdef PQXX_DEPRECATED_HEADERS
00526
00533
00534 void Disconnect() throw () PQXX_DEPRECATED { disconnect(); }
00536 template<typename TRANSACTOR> void Perform(const TRANSACTOR &T, int A=3)
00537 PQXX_DEPRECATED { perform(T,A); }
00539 PGSTD::auto_ptr<noticer> SetNoticer(PGSTD::auto_ptr<noticer> N)
00540 PQXX_DEPRECATED { return set_noticer(N); }
00542 noticer *GetNoticer() const throw () PQXX_DEPRECATED { return get_noticer(); }
00544 void ProcessNotice(const char msg[]) throw () PQXX_DEPRECATED
00545 { return process_notice(msg); }
00547 void ProcessNotice(const PGSTD::string &msg) throw () PQXX_DEPRECATED
00548 { return process_notice(msg); }
00550 void Trace(FILE *F) PQXX_DEPRECATED { trace(F); }
00552 void GetNotifs() PQXX_DEPRECATED { get_notifs(); }
00554 const char *DbName() PQXX_DEPRECATED { return dbname(); }
00556 const char *UserName() PQXX_DEPRECATED { return username(); }
00558 const char *HostName() PQXX_DEPRECATED { return hostname(); }
00560 const char *Port() PQXX_DEPRECATED { return port(); }
00562 int BackendPID() const PQXX_DEPRECATED { return backendpid(); }
00564 void Activate() PQXX_DEPRECATED { activate(); }
00566 void Deactivate() PQXX_DEPRECATED { deactivate(); }
00568 void SetClientEncoding(const PGSTD::string &E) PQXX_DEPRECATED
00569 { set_client_encoding(E); }
00571 void SetVariable(const PGSTD::string &Var, const PGSTD::string &Val)
00572 PQXX_DEPRECATED { set_variable(Var, Val); }
00574 #endif
00575
00576
00577 protected:
00578 explicit connection_base(connectionpolicy &);
00579 void init();
00580
00581 void close() throw ();
00582 void wait_read() const;
00583 void wait_read(long seconds, long microseconds) const;
00584 void wait_write() const;
00585
00586 private:
00587 void PQXX_PRIVATE clearcaps() throw ();
00588 void PQXX_PRIVATE SetupState();
00589 void PQXX_PRIVATE check_result(const result &, const char Query[]);
00590
00591 void PQXX_PRIVATE InternalSetTrace() throw ();
00592 int PQXX_PRIVATE Status() const throw ();
00593 const char *ErrMsg() const throw ();
00594 void PQXX_PRIVATE Reset();
00595 void PQXX_PRIVATE RestoreVars();
00596 PGSTD::string PQXX_PRIVATE RawGetVar(const PGSTD::string &);
00597 void PQXX_PRIVATE process_notice_raw(const char msg[]) throw ();
00598 void switchnoticer(const PGSTD::auto_ptr<noticer> &) throw ();
00599
00600 void read_capabilities() throw ();
00601
00602 friend class subtransaction;
00603 void set_capability(capability) throw ();
00604
00605 prepare::internal::prepared_def &find_prepared(const PGSTD::string &);
00606
00607 friend class prepare::declaration;
00608 void prepare_param_declare(const PGSTD::string &statement,
00609 const PGSTD::string &sqltype,
00610 prepare::param_treatment);
00611
00612 result prepared_exec(const PGSTD::string &, const char *const params[], int);
00613
00615 internal::pq::PGconn *m_Conn;
00616
00617 connectionpolicy &m_policy;
00618
00620 bool m_Completed;
00621
00623 internal::unique<transaction_base> m_Trans;
00624
00626 PGSTD::auto_ptr<noticer> m_Noticer;
00627
00629
00633 internal::pq::PQnoticeProcessor m_defaultNoticeProcessor;
00634
00636 FILE *m_Trace;
00637
00638 typedef PGSTD::multimap<PGSTD::string, pqxx::trigger *> TriggerList;
00640 TriggerList m_Triggers;
00641
00643 PGSTD::map<PGSTD::string, PGSTD::string> m_Vars;
00644
00645 typedef PGSTD::map<PGSTD::string, prepare::internal::prepared_def> PSMap;
00646
00648 PSMap m_prepared;
00649
00651 bool m_caps[cap_end];
00652
00654 bool m_inhibit_reactivation;
00655
00657 internal::reactivation_avoidance_counter m_reactivation_avoidance;
00658
00660 int m_unique_id;
00661
00662 friend class transaction_base;
00663 result PQXX_PRIVATE Exec(const char[], int Retries);
00664 result pq_exec_prepared(const PGSTD::string &, int, const char *const *);
00665 void PQXX_PRIVATE RegisterTransaction(transaction_base *);
00666 void PQXX_PRIVATE UnregisterTransaction(transaction_base *) throw ();
00667 void PQXX_PRIVATE MakeEmpty(result &);
00668 bool PQXX_PRIVATE ReadCopyLine(PGSTD::string &);
00669 void PQXX_PRIVATE WriteCopyLine(const PGSTD::string &);
00670 void PQXX_PRIVATE EndCopyWrite();
00671 void PQXX_PRIVATE start_exec(const PGSTD::string &);
00672 internal::pq::PGresult *get_result();
00673 PGSTD::string esc(const char str[], size_t maxlen);
00674 PGSTD::string esc_raw(const unsigned char str[], size_t len);
00675
00676 void PQXX_PRIVATE RawSetVar(const PGSTD::string &, const PGSTD::string &);
00677 void PQXX_PRIVATE AddVariables(const PGSTD::map<PGSTD::string,
00678 PGSTD::string> &);
00679
00680 friend class largeobject;
00681 internal::pq::PGconn *RawConnection() const { return m_Conn; }
00682
00683 friend class trigger;
00684 void AddTrigger(trigger *);
00685 void RemoveTrigger(trigger *) throw ();
00686
00687 friend class pipeline;
00688 bool PQXX_PRIVATE consume_input() throw ();
00689 bool PQXX_PRIVATE is_busy() const throw ();
00690
00691 friend class cursor_base;
00692 friend class dbtransaction;
00693 friend class internal::reactivation_avoidance_exemption;
00694
00695
00696 connection_base(const connection_base &);
00697 connection_base &operator=(const connection_base &);
00698 };
00699
00701
00702
00703
00704 namespace internal
00705 {
00706
00708
00714 class PQXX_LIBEXPORT scoped_noticer
00715 {
00716 public:
00718
00722 scoped_noticer(connection_base &c, PGSTD::auto_ptr<noticer> t) throw () :
00723 m_c(c), m_org(c.set_noticer(t)) { }
00724
00725 ~scoped_noticer() { m_c.set_noticer(m_org); }
00726
00727 protected:
00729
00733 scoped_noticer(connection_base &c, noticer *t) throw () :
00734 m_c(c),
00735 m_org()
00736 {
00737 PGSTD::auto_ptr<noticer> x(t);
00738 PGSTD::auto_ptr<noticer> y(c.set_noticer(x));
00739 m_org = y;
00740 }
00741
00742 private:
00743 connection_base &m_c;
00744 PGSTD::auto_ptr<noticer> m_org;
00745
00747 scoped_noticer();
00748 scoped_noticer(const scoped_noticer &);
00749 scoped_noticer operator=(const scoped_noticer &);
00750 };
00751
00752
00754 class PQXX_LIBEXPORT disable_noticer : scoped_noticer
00755 {
00756 public:
00757 explicit disable_noticer(connection_base &c) :
00758 scoped_noticer(c, new nonnoticer) {}
00759 };
00760
00761
00763 class PQXX_LIBEXPORT reactivation_avoidance_exemption
00764 {
00765 public:
00766 explicit reactivation_avoidance_exemption(connection_base &C) :
00767 m_home(C),
00768 m_count(C.m_reactivation_avoidance.get()),
00769 m_open(C.is_open())
00770 {
00771 C.m_reactivation_avoidance.clear();
00772 }
00773
00774 ~reactivation_avoidance_exemption()
00775 {
00776
00777
00778 if (m_count && !m_open) m_home.deactivate();
00779 m_home.m_reactivation_avoidance.add(m_count);
00780 }
00781
00782 void close_connection() throw () { m_open = false; }
00783
00784 private:
00785 connection_base &m_home;
00786 int m_count;
00787 bool m_open;
00788 };
00789
00790
00791 void wait_read(const internal::pq::PGconn *);
00792 void wait_read(const internal::pq::PGconn *, long seconds, long microseconds);
00793 void wait_write(const internal::pq::PGconn *);
00794
00795 }
00796
00797
00798 }
00799
00800 #include "pqxx/compiler-internal-post.hxx"