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 virtual ~noticer() throw () {}
00056 virtual void operator()(const char Msg[]) throw () =0;
00057 };
00058
00059
00061 struct PQXX_LIBEXPORT nonnoticer : noticer
00062 {
00063 virtual void operator()(const char []) throw () {}
00064 };
00065
00066
00068
00088 class PQXX_LIBEXPORT connection_base
00089 {
00090 public:
00092
00102 explicit connection_base(const PGSTD::string &ConnInfo);
00103
00105
00109 explicit connection_base(const char ConnInfo[]);
00110
00112 virtual ~connection_base() =0;
00113
00115 void disconnect() throw ();
00116
00118
00122 bool is_open() const throw ();
00123
00125
00133 template<typename TRANSACTOR>
00134 void perform(const TRANSACTOR &T, int Attempts);
00135
00137
00144 template<typename TRANSACTOR>
00145 void perform(const TRANSACTOR &T) { perform(T, 3); }
00146
00147
00149
00161 PGSTD::auto_ptr<noticer> set_noticer(PGSTD::auto_ptr<noticer> N)
00162 throw ();
00163 noticer *get_noticer() const throw () { return m_Noticer.get(); }
00164
00166 void process_notice(const char[]) throw ();
00168 void process_notice(const PGSTD::string &) throw ();
00169
00171 void trace(FILE *) throw ();
00172
00174
00178 int get_notifs();
00179
00180
00181
00183 const char *dbname()
00184 { activate(); return PQdb(m_Conn); }
00185
00187 const char *username()
00188 { activate(); return PQuser(m_Conn); }
00189
00191 const char *hostname()
00192 { activate(); return PQhost(m_Conn); }
00193
00195 const char *port()
00196 { activate(); return PQport(m_Conn); }
00197
00199 const char *options() const throw ()
00200 { return m_ConnInfo.c_str(); }
00201
00202
00204
00213 int backendpid() const throw ()
00214 { return m_Conn ? PQbackendPID(m_Conn) : 0; }
00215
00217
00227 void activate();
00228
00230
00238 void deactivate();
00239
00241
00247 void set_client_encoding(const PGSTD::string &Encoding)
00248 { set_variable("CLIENT_ENCODING", Encoding); }
00249
00251
00267 void set_variable(const PGSTD::string &Var,
00268 const PGSTD::string &Value);
00269
00271
00278 PGSTD::string get_variable(const PGSTD::string &);
00279
00281
00284 int await_notification();
00285
00287
00291 int await_notification(long seconds, long microseconds);
00292
00293 #ifdef PQXX_DEPRECATED_HEADERS
00294
00295 void Disconnect() throw () { disconnect(); }
00297 template<typename TRANSACTOR> void Perform(const TRANSACTOR &T, int A=3)
00298 { return perform(T,A); }
00300 PGSTD::auto_ptr<noticer> SetNoticer(PGSTD::auto_ptr<noticer> N)
00301 { return set_noticer(N); }
00303 noticer *GetNoticer() const throw ()
00304 { return get_noticer(); }
00306 void ProcessNotice(const char msg[]) throw () { return process_notice(msg); }
00308 void ProcessNotice(const PGSTD::string &msg) throw ()
00309 { return process_notice(msg); }
00311 void Trace(FILE *F) { trace(F); }
00313 void GetNotifs() { get_notifs(); }
00315 const char *DbName() { return dbname(); }
00317 const char *UserName() { return username(); }
00319 const char *HostName() { return hostname(); }
00321 const char *Port() { return port(); }
00323 const char *Options() const throw () { return options(); }
00325 int BackendPID() const { return backendpid(); }
00327 void Activate() { activate(); }
00329 void Deactivate() { deactivate(); }
00331 void SetClientEncoding(const PGSTD::string &E) { set_client_encoding(E); }
00333 void SetVariable(const PGSTD::string &Var, const PGSTD::string &Val)
00334 { set_variable(Var, Val); }
00335 #endif
00336
00337
00338 protected:
00340
00341 virtual void startconnect() =0;
00342
00344
00345 virtual void completeconnect() =0;
00346
00348
00349 virtual void dropconnect() throw () {}
00350
00352 internal::pq::PGconn *get_conn() const throw () { return m_Conn; }
00353
00355 void set_conn(internal::pq::PGconn *C) throw () { m_Conn = C; }
00356
00357 void close() throw ();
00358 void wait_read() const;
00359 void wait_read(long seconds, long microseconds) const;
00360 void wait_write() const;
00361
00362 private:
00363 void SetupState();
00364
00365 void InternalSetTrace() throw ();
00366 int Status() const throw () { return PQXXPQ::PQstatus(m_Conn); }
00367 const char *ErrMsg() const throw ();
00368 void Reset();
00369 void RestoreVars();
00370 int set_fdmask() const;
00371 void clear_fdmask() throw ();
00372 PGSTD::string RawGetVar(const PGSTD::string &);
00373 void process_notice_raw(const char msg[]) throw ();
00374
00375
00377 PGSTD::string m_ConnInfo;
00378
00380 internal::pq::PGconn *m_Conn;
00382 internal::unique<transaction_base> m_Trans;
00383
00385 PGSTD::auto_ptr<noticer> m_Noticer;
00387 FILE *m_Trace;
00388
00389 typedef PGSTD::multimap<PGSTD::string, pqxx::trigger *> TriggerList;
00391 TriggerList m_Triggers;
00392
00394 PGSTD::map<PGSTD::string, PGSTD::string> m_Vars;
00395
00396 mutable fd_set m_fdmask;
00397
00398 friend class transaction_base;
00399 result Exec(const char[], int Retries);
00400 result exec_prepared(const char[],
00401 int NumParams,
00402 const char *const *Params,
00403 int Retries);
00404 void RegisterTransaction(transaction_base *);
00405 void UnregisterTransaction(transaction_base *) throw ();
00406 void MakeEmpty(result &);
00407 bool ReadCopyLine(PGSTD::string &);
00408 void WriteCopyLine(const PGSTD::string &);
00409 void EndCopyWrite();
00410 void start_exec(const PGSTD::string &);
00411 internal::pq::PGresult *get_result();
00412
00413 void RawSetVar(const PGSTD::string &Var, const PGSTD::string &Value);
00414 void AddVariables(const PGSTD::map<PGSTD::string, PGSTD::string> &);
00415
00416 friend class largeobject;
00417 internal::pq::PGconn *RawConnection() const { return m_Conn; }
00418
00419 friend class trigger;
00420 void AddTrigger(trigger *);
00421 void RemoveTrigger(trigger *) throw ();
00422
00423 friend class pipeline;
00424 void consume_input() throw () { PQconsumeInput(m_Conn); }
00425 bool is_busy() const throw () { return PQisBusy(m_Conn); }
00426
00427
00428 connection_base(const connection_base &);
00429 connection_base &operator=(const connection_base &);
00430 };
00431
00432
00433
00434 inline connection_base::~connection_base()
00435 {
00436
00437 #ifdef PQXX_QUIET_DESTRUCTORS
00438 set_noticer(PGSTD::auto_ptr<noticer>(new nonnoticer()));
00439 #endif
00440 }
00441
00442
00443 namespace internal
00444 {
00445
00447
00453 class PQXX_LIBEXPORT scoped_noticer
00454 {
00455 public:
00457
00461 scoped_noticer(connection_base &c, PGSTD::auto_ptr<noticer> t) throw () :
00462 m_c(c), m_org(c.set_noticer(t)) { }
00463
00464 ~scoped_noticer() { m_c.set_noticer(m_org); }
00465
00466 private:
00467 connection_base &m_c;
00468 PGSTD::auto_ptr<noticer> m_org;
00469
00471 scoped_noticer();
00472 scoped_noticer(const scoped_noticer &);
00473 scoped_noticer operator=(const scoped_noticer &);
00474 };
00475
00476
00478 class PQXX_LIBEXPORT disable_noticer : scoped_noticer
00479 {
00480 public:
00481 explicit disable_noticer(connection_base &c) :
00482 scoped_noticer(c, PGSTD::auto_ptr<noticer>(new nonnoticer)) {}
00483 };
00484
00485
00486 }
00487
00488
00489 }
00490