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
00186 const char *username();
00187
00189 const char *hostname();
00190
00192 const char *port();
00193
00195 const char *options() const throw ()
00196 { return m_ConnInfo.c_str(); }
00197
00198
00200
00209 int backendpid() const throw ();
00210
00212
00222 void activate();
00223
00225
00233 void deactivate();
00234
00236
00242 void set_client_encoding(const PGSTD::string &Encoding)
00243 { set_variable("CLIENT_ENCODING", Encoding); }
00244
00246
00262 void set_variable(const PGSTD::string &Var,
00263 const PGSTD::string &Value);
00264
00266
00273 PGSTD::string get_variable(const PGSTD::string &);
00274
00276
00279 int await_notification();
00280
00282
00286 int await_notification(long seconds, long microseconds);
00287
00289
00307 void prepare(const PGSTD::string &name, const PGSTD::string &def)
00308 { pq_prepare(name, def, ""); }
00309
00311
00329 template<typename ITER>
00330 void prepare(const PGSTD::string &name,
00331 const PGSTD::string &def,
00332 ITER beginparms,
00333 ITER endparms)
00334 {
00335 pq_prepare(name, def,
00336 (beginparms==endparms) ?
00337 "" : ("("+separated_list(",",beginparms,endparms)+")"));
00338 }
00339
00341
00359 template<typename CNTNR>
00360 void prepare(const PGSTD::string &name,
00361 const PGSTD::string &def,
00362 const CNTNR ¶ms)
00363 { prepare(name, def, params.begin(), params.end()); }
00364
00366 void unprepare(const PGSTD::string &name);
00367
00368 #ifdef PQXX_DEPRECATED_HEADERS
00369
00370 void Disconnect() throw () { disconnect(); }
00372 template<typename TRANSACTOR> void Perform(const TRANSACTOR &T, int A=3)
00373 { return perform(T,A); }
00375 PGSTD::auto_ptr<noticer> SetNoticer(PGSTD::auto_ptr<noticer> N)
00376 { return set_noticer(N); }
00378 noticer *GetNoticer() const throw ()
00379 { return get_noticer(); }
00381 void ProcessNotice(const char msg[]) throw () { return process_notice(msg); }
00383 void ProcessNotice(const PGSTD::string &msg) throw ()
00384 { return process_notice(msg); }
00386 void Trace(FILE *F) { trace(F); }
00388 void GetNotifs() { get_notifs(); }
00390 const char *DbName() { return dbname(); }
00392 const char *UserName() { return username(); }
00394 const char *HostName() { return hostname(); }
00396 const char *Port() { return port(); }
00398 const char *Options() const throw () { return options(); }
00400 int BackendPID() const { return backendpid(); }
00402 void Activate() { activate(); }
00404 void Deactivate() { deactivate(); }
00406 void SetClientEncoding(const PGSTD::string &E) { set_client_encoding(E); }
00408 void SetVariable(const PGSTD::string &Var, const PGSTD::string &Val)
00409 { set_variable(Var, Val); }
00410 #endif
00411
00412
00413 protected:
00415
00416 virtual void startconnect() =0;
00417
00419
00420 virtual void completeconnect() =0;
00421
00423
00424 virtual void dropconnect() throw () {}
00425
00427 internal::pq::PGconn *get_conn() const throw () { return m_Conn; }
00428
00430 void set_conn(internal::pq::PGconn *C) throw () { m_Conn = C; }
00431
00432 void close() throw ();
00433 void wait_read() const;
00434 void wait_read(long seconds, long microseconds) const;
00435 void wait_write() const;
00436
00437 private:
00438 void SetupState();
00439
00440 void InternalSetTrace() throw ();
00441 int Status() const throw ();
00442 const char *ErrMsg() const throw ();
00443 void Reset();
00444 void RestoreVars();
00445 int set_fdmask() const;
00446 void clear_fdmask() throw ();
00447 PGSTD::string RawGetVar(const PGSTD::string &);
00448 void process_notice_raw(const char msg[]) throw ();
00449
00450
00452 PGSTD::string m_ConnInfo;
00453
00455 internal::pq::PGconn *m_Conn;
00457 internal::unique<transaction_base> m_Trans;
00458
00460 PGSTD::auto_ptr<noticer> m_Noticer;
00462 FILE *m_Trace;
00463
00464 typedef PGSTD::multimap<PGSTD::string, pqxx::trigger *> TriggerList;
00466 TriggerList m_Triggers;
00467
00469 PGSTD::map<PGSTD::string, PGSTD::string> m_Vars;
00470
00472 struct prepared_def
00473 {
00475 PGSTD::string definition;
00477 PGSTD::string parameters;
00479 bool registered;
00480
00481 prepared_def() : definition(), parameters(), registered(false) {}
00482 prepared_def(const PGSTD::string &def, const PGSTD::string ¶ms) :
00483 definition(def), parameters(params), registered(false) {}
00484 };
00485
00486 typedef PGSTD::map<PGSTD::string, prepared_def> PSMap;
00487
00489 PSMap m_prepared;
00490
00491 mutable fd_set m_fdmask;
00492
00493 friend class transaction_base;
00494 result Exec(const char[], int Retries);
00495 void pq_prepare(const PGSTD::string &name,
00496 const PGSTD::string &def,
00497 const PGSTD::string ¶ms);
00498 result pq_exec_prepared(const PGSTD::string &, int, const char *const *);
00499 void RegisterTransaction(transaction_base *);
00500 void UnregisterTransaction(transaction_base *) throw ();
00501 void MakeEmpty(result &);
00502 bool ReadCopyLine(PGSTD::string &);
00503 void WriteCopyLine(const PGSTD::string &);
00504 void EndCopyWrite();
00505 void start_exec(const PGSTD::string &);
00506 internal::pq::PGresult *get_result();
00507
00508 void RawSetVar(const PGSTD::string &Var, const PGSTD::string &Value);
00509 void AddVariables(const PGSTD::map<PGSTD::string, PGSTD::string> &);
00510
00511 friend class largeobject;
00512 internal::pq::PGconn *RawConnection() const { return m_Conn; }
00513
00514 friend class trigger;
00515 void AddTrigger(trigger *);
00516 void RemoveTrigger(trigger *) throw ();
00517
00518 friend class pipeline;
00519 void consume_input() throw ();
00520 bool is_busy() const throw ();
00521
00522
00523 connection_base(const connection_base &);
00524 connection_base &operator=(const connection_base &);
00525 };
00526
00527
00528
00529 inline connection_base::~connection_base()
00530 {
00531
00532 #ifdef PQXX_QUIET_DESTRUCTORS
00533 set_noticer(PGSTD::auto_ptr<noticer>(new nonnoticer()));
00534 #endif
00535 }
00536
00537
00538 namespace internal
00539 {
00540
00542
00548 class PQXX_LIBEXPORT scoped_noticer
00549 {
00550 public:
00552
00556 scoped_noticer(connection_base &c, PGSTD::auto_ptr<noticer> t) throw () :
00557 m_c(c), m_org(c.set_noticer(t)) { }
00558
00559 ~scoped_noticer() { m_c.set_noticer(m_org); }
00560
00561 private:
00562 connection_base &m_c;
00563 PGSTD::auto_ptr<noticer> m_org;
00564
00566 scoped_noticer();
00567 scoped_noticer(const scoped_noticer &);
00568 scoped_noticer operator=(const scoped_noticer &);
00569 };
00570
00571
00573 class PQXX_LIBEXPORT disable_noticer : scoped_noticer
00574 {
00575 public:
00576 explicit disable_noticer(connection_base &c) :
00577 scoped_noticer(c, PGSTD::auto_ptr<noticer>(new nonnoticer)) {}
00578 };
00579
00580
00581 }
00582
00583
00584 }
00585