00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #include <map>
00021 #include <memory>
00022
00023 #ifdef _WIN32
00024 #include <winsock2.h>
00025 #endif // _WIN32
00026
00027 #include "pqxx/except"
00028 #include "pqxx/util"
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040 namespace pqxx
00041 {
00042 class result;
00043 class transaction_base;
00044 class trigger;
00045
00046
00048
00052 struct PQXX_LIBEXPORT noticer : PGSTD::unary_function<const char[], void>
00053 {
00054 virtual ~noticer() throw () {}
00055 virtual void operator()(const char Msg[]) throw () =0;
00056 };
00057
00058
00060
00078 class PQXX_LIBEXPORT connection_base
00079 {
00080 public:
00082
00087 explicit connection_base(const PGSTD::string &ConnInfo);
00088
00090
00094 explicit connection_base(const char ConnInfo[]);
00095
00097 virtual ~connection_base() =0;
00098
00100 void disconnect() throw ();
00101
00103 bool is_open() const throw ();
00104
00106
00114 template<typename TRANSACTOR>
00115 void perform(const TRANSACTOR &T, int Attempts=3);
00116
00117 #ifdef PQXX_BROKEN_MEMBER_TEMPLATE_DEFAULT_ARG
00118 template<typename TRANSACTOR> void perform(TRANSACTOR &T, int Attempts);
00119 template<typename TRANSACTOR>
00120 void perform(const TRANSACTOR &T) { perform(T, 3); }
00121 #endif
00122
00123
00125
00134 PGSTD::auto_ptr<noticer> set_noticer(PGSTD::auto_ptr<noticer> N)
00135 throw ();
00136 noticer *get_noticer() const throw () { return m_Noticer.get(); }
00137
00139 void process_notice(const char[]) throw ();
00141 void process_notice(const PGSTD::string &msg) throw ();
00142
00144 void trace(FILE *) throw ();
00145
00147
00150 void get_notifs();
00151
00152
00153
00155 const char *dbname()
00156 { halfconnect(); return PQdb(m_Conn); }
00157
00159 const char *username()
00160 { halfconnect(); return PQuser(m_Conn); }
00161
00163 const char *hostname()
00164 { halfconnect(); return PQhost(m_Conn); }
00165
00167 const char *port()
00168 { halfconnect(); return PQport(m_Conn); }
00169
00171 const char *options() const throw ()
00172 { return m_ConnInfo.c_str(); }
00173
00174
00176
00183 int backendpid() const throw ()
00184 { return m_Conn ? PQbackendPID(m_Conn) : 0; }
00185
00187
00197 void activate() { Connect(); }
00198
00200
00208 void deactivate();
00209
00211
00217 void set_client_encoding(const PGSTD::string &Encoding)
00218 { set_variable("CLIENT_ENCODING", Encoding); }
00219
00221
00235 void set_variable(const PGSTD::string &Var,
00236 const PGSTD::string &Value);
00237
00239
00245 PGSTD::string get_variable(const PGSTD::string &);
00246
00247 #ifdef PQXX_DEPRECATED_HEADERS
00248
00249 void Disconnect() throw () { disconnect(); }
00251 template<typename TRANSACTOR> void Perform(const TRANSACTOR &T, int A=3)
00252 { return perform(T,A); }
00254 PGSTD::auto_ptr<noticer> SetNoticer(PGSTD::auto_ptr<noticer> N)
00255 { return set_noticer(N); }
00257 noticer *GetNoticer() const throw ()
00258 { return get_noticer(); }
00260 void ProcessNotice(const char msg[]) throw () { return process_notice(msg); }
00262 void ProcessNotice(const PGSTD::string &msg) throw ()
00263 { return process_notice(msg); }
00265 void Trace(FILE *F) { trace(F); }
00267 void GetNotifs() { get_notifs(); }
00269 const char *DbName() { return dbname(); }
00271 const char *UserName() { return username(); }
00273 const char *HostName() { return hostname(); }
00275 const char *Port() { return port(); }
00277 const char *Options() const throw () { return options(); }
00279 int BackendPID() const { return backendpid(); }
00281 void Activate() { activate(); }
00283 void Deactivate() { deactivate(); }
00285 void SetClientEncoding(const PGSTD::string &E) { set_client_encoding(E); }
00287 void SetVariable(const PGSTD::string &Var, const PGSTD::string &Val)
00288 { set_variable(Var, Val); }
00289 #endif
00290
00291
00292 protected:
00294 void Connect();
00295
00297 virtual void startconnect() =0;
00298
00300 virtual void completeconnect() =0;
00301
00303 virtual void dropconnect() {}
00304
00306 PGconn *get_conn() const throw () { return m_Conn; }
00307
00309 void set_conn(PGconn *C) throw () { m_Conn = C; }
00310
00311 void wait_read() const;
00312 void wait_write() const;
00313
00314 private:
00315 void SetupState();
00316 void InternalSetTrace() throw ();
00317 int Status() const { return PQstatus(m_Conn); }
00318 const char *ErrMsg() const;
00319 void Reset();
00320 void close() throw ();
00321 void RestoreVars();
00322 void halfconnect();
00323 int set_fdmask() const;
00324 void clear_fdmask() throw ();
00325 void go_sync();
00326 void go_async();
00327 PGSTD::string RawGetVar(const PGSTD::string &);
00328 void process_notice_raw(const char msg[]) throw ();
00329
00330
00332 PGSTD::string m_ConnInfo;
00333
00335 PGconn *m_Conn;
00337 internal::unique<transaction_base> m_Trans;
00338
00340 PGSTD::auto_ptr<noticer> m_Noticer;
00342 FILE *m_Trace;
00343
00344 typedef PGSTD::multimap<PGSTD::string, pqxx::trigger *> TriggerList;
00346 TriggerList m_Triggers;
00347
00349 PGSTD::map<PGSTD::string, PGSTD::string> m_Vars;
00350
00351 mutable fd_set m_fdmask;
00352
00353 friend class transaction_base;
00354 result Exec(const char[], int Retries);
00355 void RegisterTransaction(transaction_base *);
00356 void UnregisterTransaction(transaction_base *) throw ();
00357 void MakeEmpty(result &, ExecStatusType=PGRES_EMPTY_QUERY);
00358 bool ReadCopyLine(PGSTD::string &);
00359 bool WriteCopyLine(const PGSTD::string &, bool async=false);
00360 void EndCopyWrite();
00361 void start_exec(const PGSTD::string &);
00362 PGresult *get_result();
00363
00364 void RawSetVar(const PGSTD::string &Var, const PGSTD::string &Value);
00365 void AddVariables(const PGSTD::map<PGSTD::string, PGSTD::string> &);
00366
00367 friend class largeobject;
00368 PGconn *RawConnection() const { return m_Conn; }
00369
00370 friend class trigger;
00371 void AddTrigger(trigger *);
00372 void RemoveTrigger(trigger *) throw ();
00373
00374
00375 connection_base(const connection_base &);
00376 connection_base &operator=(const connection_base &);
00377 };
00378
00379
00380 }
00381
00382
00383
00384 inline pqxx::connection_base::~connection_base()
00385 {
00386 close();
00387 }
00388
00389