00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019 #include "pqxx/libcompiler.h"
00020
00021 #include <map>
00022 #include <memory>
00023
00024 #include "pqxx/except"
00025 #include "pqxx/util"
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037 namespace pqxx
00038 {
00039 class result;
00040 class transaction_base;
00041 class trigger;
00042
00043
00048
00049
00053 struct PQXX_LIBEXPORT noticer : PGSTD::unary_function<const char[], void>
00054 {
00055 noticer(){}
00056 virtual ~noticer() throw () {}
00057 virtual void operator()(const char Msg[]) throw () =0;
00058 };
00059
00060
00062 struct PQXX_LIBEXPORT nonnoticer : noticer
00063 {
00064 nonnoticer(){}
00065 virtual void operator()(const char []) throw () {}
00066 };
00068
00069
00074
00075
00095 class PQXX_LIBEXPORT connection_base
00096 {
00097 public:
00099
00109 explicit connection_base(const PGSTD::string &ConnInfo);
00110
00112
00116 explicit connection_base(const char ConnInfo[]);
00117
00119 virtual ~connection_base() =0;
00120
00125
00126 void disconnect() throw ();
00127
00129
00139 void activate();
00140
00142
00150 void deactivate();
00151
00153
00197 void inhibit_reactivation(bool inhibit)
00198 { m_inhibit_reactivation=inhibit; }
00199
00201
00205 bool is_open() const throw ();
00207
00212
00214
00226 PGSTD::auto_ptr<noticer> set_noticer(PGSTD::auto_ptr<noticer> N)
00227 throw ();
00228 noticer *get_noticer() const throw () { return m_Noticer.get(); }
00229
00231 void process_notice(const char[]) throw ();
00233 void process_notice(const PGSTD::string &) throw ();
00235
00237 void trace(FILE *) throw ();
00238
00247
00248 const char *dbname();
00249
00251 const char *username();
00252
00254 const char *hostname();
00255
00257 const char *port();
00258
00260 const char *options() const throw ()
00261 { return m_ConnInfo.c_str(); }
00262
00263
00265
00274 int backendpid() const throw ();
00275
00277
00291 int sock() const throw ();
00292
00294
00300 enum capability
00301 {
00303 cap_create_table_with_oids,
00304
00306 cap_cursor_scroll,
00308 cap_cursor_with_hold,
00310 cap_cursor_update,
00311
00313 cap_end
00314 };
00315
00316
00318
00331 bool supports(capability c) const throw () { return m_caps[c]; }
00332
00334
00340 void set_client_encoding(const PGSTD::string &Encoding)
00341 { set_variable("CLIENT_ENCODING", Encoding); }
00342
00344
00360 void set_variable(const PGSTD::string &Var,
00361 const PGSTD::string &Value);
00362
00364
00371 PGSTD::string get_variable(const PGSTD::string &);
00373
00374
00379
00380
00391 int get_notifs();
00392
00393
00395
00401 int await_notification();
00402
00404
00410 int await_notification(long seconds, long microseconds);
00412
00413
00443
00444 void prepare(const PGSTD::string &name, const PGSTD::string &def)
00445 { pq_prepare(name, def, ""); }
00446
00448 template<typename ITER>
00449 void prepare(const PGSTD::string &name,
00450 const PGSTD::string &def,
00451 ITER beginparms,
00452 ITER endparms)
00453 {
00454 pq_prepare(name, def,
00455 (beginparms==endparms) ?
00456 "" : ("("+separated_list(",",beginparms,endparms)+")"));
00457 }
00458
00460 template<typename CNTNR>
00461 void prepare(const PGSTD::string &name,
00462 const PGSTD::string &def,
00463 const CNTNR ¶ms)
00464 { prepare(name, def, params.begin(), params.end()); }
00465
00467 void unprepare(const PGSTD::string &name);
00469
00470
00487
00488
00492 template<typename TRANSACTOR>
00493 void perform(const TRANSACTOR &T, int Attempts);
00494
00496
00499 template<typename TRANSACTOR>
00500 void perform(const TRANSACTOR &T) { perform(T, 3); }
00502
00503 #ifdef PQXX_DEPRECATED_HEADERS
00504
00511
00512 void Disconnect() throw () { disconnect(); }
00514 template<typename TRANSACTOR> void Perform(const TRANSACTOR &T, int A=3)
00515 { perform(T,A); }
00517 PGSTD::auto_ptr<noticer> SetNoticer(PGSTD::auto_ptr<noticer> N)
00518 { return set_noticer(N); }
00520 noticer *GetNoticer() const throw ()
00521 { return get_noticer(); }
00523 void ProcessNotice(const char msg[]) throw () { return process_notice(msg); }
00525 void ProcessNotice(const PGSTD::string &msg) throw ()
00526 { return process_notice(msg); }
00528 void Trace(FILE *F) { trace(F); }
00530 void GetNotifs() { get_notifs(); }
00532 const char *DbName() { return dbname(); }
00534 const char *UserName() { return username(); }
00536 const char *HostName() { return hostname(); }
00538 const char *Port() { return port(); }
00540 const char *Options() const throw () { return options(); }
00542 int BackendPID() const { return backendpid(); }
00544 void Activate() { activate(); }
00546 void Deactivate() { deactivate(); }
00548 void SetClientEncoding(const PGSTD::string &E) { set_client_encoding(E); }
00550 void SetVariable(const PGSTD::string &Var, const PGSTD::string &Val)
00551 { set_variable(Var, Val); }
00553 #endif
00554
00555
00556 protected:
00558
00559 virtual void startconnect() =0;
00560
00562
00563 virtual void completeconnect() =0;
00564
00566
00567 virtual void dropconnect() throw () {}
00568
00570 internal::pq::PGconn *get_conn() const throw () { return m_Conn; }
00571
00573 void set_conn(internal::pq::PGconn *C) throw () { m_Conn = C; }
00574
00575 void close() throw ();
00576 void wait_read() const;
00577 void wait_read(long seconds, long microseconds) const;
00578 void wait_write() const;
00579
00580 private:
00581 void PQXX_PRIVATE SetupState();
00582 void PQXX_PRIVATE check_result(const result &, const char Query[]);
00583
00584 void PQXX_PRIVATE InternalSetTrace() throw ();
00585 int PQXX_PRIVATE Status() const throw ();
00586 const char *ErrMsg() const throw ();
00587 void PQXX_PRIVATE Reset();
00588 void PQXX_PRIVATE RestoreVars();
00589 PGSTD::string PQXX_PRIVATE RawGetVar(const PGSTD::string &);
00590 void PQXX_PRIVATE process_notice_raw(const char msg[]) throw ();
00591
00592 void read_capabilities() throw ();
00593
00595 PGSTD::string m_ConnInfo;
00596
00598 internal::pq::PGconn *m_Conn;
00600 internal::unique<transaction_base> m_Trans;
00601
00603 PGSTD::auto_ptr<noticer> m_Noticer;
00605 FILE *m_Trace;
00606
00607 typedef PGSTD::multimap<PGSTD::string, pqxx::trigger *> TriggerList;
00609 TriggerList m_Triggers;
00610
00612 PGSTD::map<PGSTD::string, PGSTD::string> m_Vars;
00613
00615 struct PQXX_PRIVATE prepared_def
00616 {
00618 PGSTD::string definition;
00620 PGSTD::string parameters;
00622 bool registered;
00623
00624 prepared_def() : definition(), parameters(), registered(false) {}
00625 prepared_def(const PGSTD::string &def, const PGSTD::string ¶ms) :
00626 definition(def), parameters(params), registered(false) {}
00627 };
00628
00629 typedef PGSTD::map<PGSTD::string, prepared_def> PSMap;
00630
00632 PSMap m_prepared;
00633
00635 bool m_caps[cap_end];
00636
00638 bool m_inhibit_reactivation;
00639
00641 int m_reactivation_avoidance;
00642
00643 friend class transaction_base;
00644 result PQXX_PRIVATE Exec(const char[], int Retries);
00645 void pq_prepare(const PGSTD::string &name,
00646 const PGSTD::string &def,
00647 const PGSTD::string ¶ms);
00648 result pq_exec_prepared(const PGSTD::string &, int, const char *const *);
00649 void PQXX_PRIVATE RegisterTransaction(transaction_base *);
00650 void PQXX_PRIVATE UnregisterTransaction(transaction_base *) throw ();
00651 void PQXX_PRIVATE MakeEmpty(result &);
00652 bool PQXX_PRIVATE ReadCopyLine(PGSTD::string &);
00653 void PQXX_PRIVATE WriteCopyLine(const PGSTD::string &);
00654 void PQXX_PRIVATE EndCopyWrite();
00655 void PQXX_PRIVATE start_exec(const PGSTD::string &);
00656 internal::pq::PGresult *get_result();
00657
00658 void PQXX_PRIVATE RawSetVar(const PGSTD::string &, const PGSTD::string &);
00659 void PQXX_PRIVATE AddVariables(const PGSTD::map<PGSTD::string,
00660 PGSTD::string> &);
00661
00662 friend class largeobject;
00663 internal::pq::PGconn *RawConnection() const { return m_Conn; }
00664
00665 friend class trigger;
00666 void AddTrigger(trigger *);
00667 void RemoveTrigger(trigger *) throw ();
00668
00669 friend class pipeline;
00670 bool PQXX_PRIVATE consume_input() throw ();
00671 bool PQXX_PRIVATE is_busy() const throw ();
00672
00673 friend class cursor_base;
00674 void reactivation_avoidance_add(int) throw ();
00675 void reactivation_avoidance_dec() throw ();
00676
00677
00678 connection_base(const connection_base &);
00679 connection_base &operator=(const connection_base &);
00680 };
00681
00683
00684
00685
00686 inline connection_base::~connection_base()
00687 {
00688
00689 #ifdef PQXX_QUIET_DESTRUCTORS
00690 PGSTD::auto_ptr<noticer> n(new nonnoticer());
00691 set_noticer(n);
00692 #endif
00693 }
00694
00695
00696 namespace internal
00697 {
00698
00700
00706 class PQXX_LIBEXPORT scoped_noticer
00707 {
00708 public:
00710
00714 scoped_noticer(connection_base &c, PGSTD::auto_ptr<noticer> t) throw () :
00715 m_c(c), m_org(c.set_noticer(t)) { }
00716
00717 ~scoped_noticer() { m_c.set_noticer(m_org); }
00718
00719 protected:
00721
00725 scoped_noticer(connection_base &c, noticer *t) throw () :
00726 m_c(c),
00727 m_org()
00728 {
00729 PGSTD::auto_ptr<noticer> x(t);
00730 PGSTD::auto_ptr<noticer> y(c.set_noticer(x));
00731 m_org = y;
00732 }
00733
00734 private:
00735 connection_base &m_c;
00736 PGSTD::auto_ptr<noticer> m_org;
00737
00739 scoped_noticer();
00740 scoped_noticer(const scoped_noticer &);
00741 scoped_noticer operator=(const scoped_noticer &);
00742 };
00743
00744
00746 class PQXX_LIBEXPORT disable_noticer : scoped_noticer
00747 {
00748 public:
00749 explicit disable_noticer(connection_base &c) :
00750 scoped_noticer(c, new nonnoticer) {}
00751 };
00752
00753
00754 }
00755
00756
00757 }
00758