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 #ifdef _WIN32
00025 #include <winsock2.h>
00026 #endif // _WIN32
00027
00028 #include "pqxx/except"
00029 #include "pqxx/util"
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041 namespace pqxx
00042 {
00043 class result;
00044 class transaction_base;
00045 class trigger;
00046
00047
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 };
00067
00068
00070
00090 class PQXX_LIBEXPORT connection_base
00091 {
00092 public:
00094
00104 explicit connection_base(const PGSTD::string &ConnInfo);
00105
00107
00111 explicit connection_base(const char ConnInfo[]);
00112
00114 virtual ~connection_base() =0;
00115
00117 void disconnect() throw ();
00118
00120
00124 bool is_open() const throw ();
00125
00127
00135 template<typename TRANSACTOR>
00136 void perform(const TRANSACTOR &T, int Attempts);
00137
00139
00146 template<typename TRANSACTOR>
00147 void perform(const TRANSACTOR &T) { perform(T, 3); }
00148
00149
00151
00163 PGSTD::auto_ptr<noticer> set_noticer(PGSTD::auto_ptr<noticer> N)
00164 throw ();
00165 noticer *get_noticer() const throw () { return m_Noticer.get(); }
00166
00168 void process_notice(const char[]) throw ();
00170 void process_notice(const PGSTD::string &) throw ();
00171
00173 void trace(FILE *) throw ();
00174
00176
00180 int get_notifs();
00181
00182
00183
00185 const char *dbname();
00186
00188 const char *username();
00189
00191 const char *hostname();
00192
00194 const char *port();
00195
00197 const char *options() const throw ()
00198 { return m_ConnInfo.c_str(); }
00199
00200
00202
00211 int backendpid() const throw ();
00212
00214
00224 void activate();
00225
00227
00235 void deactivate();
00236
00238
00244 void set_client_encoding(const PGSTD::string &Encoding)
00245 { set_variable("CLIENT_ENCODING", Encoding); }
00246
00248
00264 void set_variable(const PGSTD::string &Var,
00265 const PGSTD::string &Value);
00266
00268
00275 PGSTD::string get_variable(const PGSTD::string &);
00276
00278
00281 int await_notification();
00282
00284
00288 int await_notification(long seconds, long microseconds);
00289
00291
00309 void prepare(const PGSTD::string &name, const PGSTD::string &def)
00310 { pq_prepare(name, def, ""); }
00311
00313
00331 template<typename ITER>
00332 void prepare(const PGSTD::string &name,
00333 const PGSTD::string &def,
00334 ITER beginparms,
00335 ITER endparms)
00336 {
00337 pq_prepare(name, def,
00338 (beginparms==endparms) ?
00339 "" : ("("+separated_list(",",beginparms,endparms)+")"));
00340 }
00341
00343
00361 template<typename CNTNR>
00362 void prepare(const PGSTD::string &name,
00363 const PGSTD::string &def,
00364 const CNTNR ¶ms)
00365 { prepare(name, def, params.begin(), params.end()); }
00366
00368 void unprepare(const PGSTD::string &name);
00369
00370 #ifdef PQXX_DEPRECATED_HEADERS
00371
00372 void Disconnect() throw () { disconnect(); }
00374 template<typename TRANSACTOR> void Perform(const TRANSACTOR &T, int A=3)
00375 { return perform(T,A); }
00377 PGSTD::auto_ptr<noticer> SetNoticer(PGSTD::auto_ptr<noticer> N)
00378 { return set_noticer(N); }
00380 noticer *GetNoticer() const throw ()
00381 { return get_noticer(); }
00383 void ProcessNotice(const char msg[]) throw () { return process_notice(msg); }
00385 void ProcessNotice(const PGSTD::string &msg) throw ()
00386 { return process_notice(msg); }
00388 void Trace(FILE *F) { trace(F); }
00390 void GetNotifs() { get_notifs(); }
00392 const char *DbName() { return dbname(); }
00394 const char *UserName() { return username(); }
00396 const char *HostName() { return hostname(); }
00398 const char *Port() { return port(); }
00400 const char *Options() const throw () { return options(); }
00402 int BackendPID() const { return backendpid(); }
00404 void Activate() { activate(); }
00406 void Deactivate() { deactivate(); }
00408 void SetClientEncoding(const PGSTD::string &E) { set_client_encoding(E); }
00410 void SetVariable(const PGSTD::string &Var, const PGSTD::string &Val)
00411 { set_variable(Var, Val); }
00412 #endif
00413
00414
00415 protected:
00417
00418 virtual void startconnect() =0;
00419
00421
00422 virtual void completeconnect() =0;
00423
00425
00426 virtual void dropconnect() throw () {}
00427
00429 internal::pq::PGconn *get_conn() const throw () { return m_Conn; }
00430
00432 void set_conn(internal::pq::PGconn *C) throw () { m_Conn = C; }
00433
00434 void close() throw ();
00435 void wait_read() const;
00436 void wait_read(long seconds, long microseconds) const;
00437 void wait_write() const;
00438
00439 private:
00440 void PQXX_PRIVATE SetupState();
00441
00442 void PQXX_PRIVATE InternalSetTrace() throw ();
00443 int PQXX_PRIVATE Status() const throw ();
00444 const char *ErrMsg() const throw ();
00445 void PQXX_PRIVATE Reset();
00446 void PQXX_PRIVATE RestoreVars();
00447 int PQXX_PRIVATE set_fdmask() const;
00448 void PQXX_PRIVATE clear_fdmask() throw ();
00449 PGSTD::string PQXX_PRIVATE RawGetVar(const PGSTD::string &);
00450 void PQXX_PRIVATE process_notice_raw(const char msg[]) throw ();
00451
00452
00454 PGSTD::string m_ConnInfo;
00455
00457 internal::pq::PGconn *m_Conn;
00459 internal::unique<transaction_base> m_Trans;
00460
00462 PGSTD::auto_ptr<noticer> m_Noticer;
00464 FILE *m_Trace;
00465
00466 typedef PGSTD::multimap<PGSTD::string, pqxx::trigger *> TriggerList;
00468 TriggerList m_Triggers;
00469
00471 PGSTD::map<PGSTD::string, PGSTD::string> m_Vars;
00472
00474 struct PQXX_PRIVATE prepared_def
00475 {
00477 PGSTD::string definition;
00479 PGSTD::string parameters;
00481 bool registered;
00482
00483 prepared_def() : definition(), parameters(), registered(false) {}
00484 prepared_def(const PGSTD::string &def, const PGSTD::string ¶ms) :
00485 definition(def), parameters(params), registered(false) {}
00486 };
00487
00488 typedef PGSTD::map<PGSTD::string, prepared_def> PSMap;
00489
00491 PSMap m_prepared;
00492
00493 mutable fd_set m_fdmask;
00494
00495 friend class transaction_base;
00496 result PQXX_PRIVATE Exec(const char[], int Retries);
00497 void pq_prepare(const PGSTD::string &name,
00498 const PGSTD::string &def,
00499 const PGSTD::string ¶ms);
00500 result pq_exec_prepared(const PGSTD::string &, int, const char *const *);
00501 void PQXX_PRIVATE RegisterTransaction(transaction_base *);
00502 void PQXX_PRIVATE UnregisterTransaction(transaction_base *) throw ();
00503 void PQXX_PRIVATE MakeEmpty(result &);
00504 bool PQXX_PRIVATE ReadCopyLine(PGSTD::string &);
00505 void PQXX_PRIVATE WriteCopyLine(const PGSTD::string &);
00506 void PQXX_PRIVATE EndCopyWrite();
00507 void PQXX_PRIVATE start_exec(const PGSTD::string &);
00508 internal::pq::PGresult *get_result();
00509
00510 void PQXX_PRIVATE RawSetVar(const PGSTD::string &, const PGSTD::string &);
00511 void PQXX_PRIVATE AddVariables(const PGSTD::map<PGSTD::string,
00512 PGSTD::string> &);
00513
00514 friend class largeobject;
00515 internal::pq::PGconn *RawConnection() const { return m_Conn; }
00516
00517 friend class trigger;
00518 void AddTrigger(trigger *);
00519 void RemoveTrigger(trigger *) throw ();
00520
00521 friend class pipeline;
00522 void PQXX_PRIVATE consume_input() throw ();
00523 bool PQXX_PRIVATE is_busy() const throw ();
00524
00525
00526 connection_base(const connection_base &);
00527 connection_base &operator=(const connection_base &);
00528 };
00529
00530
00531
00532 inline connection_base::~connection_base()
00533 {
00534
00535 #ifdef PQXX_QUIET_DESTRUCTORS
00536 set_noticer(PGSTD::auto_ptr<noticer>(new nonnoticer()));
00537 #endif
00538 }
00539
00540
00541 namespace internal
00542 {
00543
00545
00551 class PQXX_LIBEXPORT scoped_noticer
00552 {
00553 public:
00555
00559 scoped_noticer(connection_base &c, PGSTD::auto_ptr<noticer> t) throw () :
00560 m_c(c), m_org(c.set_noticer(t)) { }
00561
00562 ~scoped_noticer() { m_c.set_noticer(m_org); }
00563
00564 private:
00565 connection_base &m_c;
00566 PGSTD::auto_ptr<noticer> m_org;
00567
00569 scoped_noticer();
00570 scoped_noticer(const scoped_noticer &);
00571 scoped_noticer operator=(const scoped_noticer &);
00572 };
00573
00574
00576 class PQXX_LIBEXPORT disable_noticer : scoped_noticer
00577 {
00578 public:
00579 explicit disable_noticer(connection_base &c) :
00580 scoped_noticer(c, PGSTD::auto_ptr<noticer>(new nonnoticer)) {}
00581 };
00582
00583
00584 }
00585
00586
00587 }
00588