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 #include "pqxx/except"
00024 #include "pqxx/util"
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036 namespace pqxx
00037 {
00038 class result;
00039 class transaction_base;
00040 class trigger;
00041
00043
00047 struct PQXX_LIBEXPORT noticer : PGSTD::unary_function<const char[], void>
00048 {
00049 virtual ~noticer() {}
00050 virtual void operator()(const char Msg[]) throw () =0;
00051 };
00052
00053
00055 template<> inline PGSTD::string Classname(const transaction_base *)
00056 {
00057 return "transaction_base";
00058 }
00059
00060
00062
00080 class PQXX_LIBEXPORT connection_base
00081 {
00082 public:
00084
00089 explicit connection_base(const PGSTD::string &ConnInfo);
00090
00092
00096 explicit connection_base(const char ConnInfo[]);
00097
00099 virtual ~connection_base() =0;
00100
00102 void disconnect() throw ();
00103
00105 bool is_open() const;
00106
00108
00116 template<typename TRANSACTOR>
00117 void perform(const TRANSACTOR &T, int Attempts=3);
00118
00119
00121
00130 PGSTD::auto_ptr<noticer> set_noticer(PGSTD::auto_ptr<noticer> N);
00131 noticer *get_noticer() const throw () { return m_Noticer.get(); }
00132
00134 void process_notice(const char[]) throw ();
00136 void process_notice(const PGSTD::string &msg) throw ()
00137 { process_notice(msg.c_str()); }
00138
00140 void trace(FILE *);
00141
00143 void get_notifs();
00144
00145
00146
00148 const char *dbname()
00149 { halfconnect(); return PQdb(m_Conn); }
00150
00152 const char *username()
00153 { halfconnect(); return PQuser(m_Conn); }
00154
00156 const char *hostname()
00157 { halfconnect(); return PQhost(m_Conn); }
00158
00160 const char *port()
00161 { halfconnect(); return PQport(m_Conn); }
00162
00164 const char *options() const throw ()
00165 { return m_ConnInfo.c_str(); }
00166
00167
00169
00176 int backendpid() const
00177 { return m_Conn ? PQbackendPID(m_Conn) : 0; }
00178
00180
00190 void activate() { Connect(); }
00191
00193
00201 void deactivate();
00202
00204
00210 void set_client_encoding(const PGSTD::string &Encoding)
00211 { set_variable("CLIENT_ENCODING", Encoding); }
00212
00214
00228 void set_variable(const PGSTD::string &Var,
00229 const PGSTD::string &Value);
00230
00232
00238 PGSTD::string get_variable(const PGSTD::string &);
00239
00240 #ifdef PQXX_DEPRECATED_HEADERS
00241
00242 void Disconnect() throw () { disconnect(); }
00244 template<typename TRANSACTOR> void Perform(const TRANSACTOR &T, int A=3)
00245 { return perform(T,A); }
00247 PGSTD::auto_ptr<noticer> SetNoticer(PGSTD::auto_ptr<noticer> N)
00248 { return set_noticer(N); }
00250 noticer *GetNoticer() const throw ()
00251 { return get_noticer(); }
00253 void ProcessNotice(const char msg[]) throw () { return process_notice(msg); }
00255 void ProcessNotice(const PGSTD::string &msg) throw ()
00256 { return process_notice(msg); }
00258 void Trace(FILE *F) { trace(F); }
00260 void GetNotifs() { get_notifs(); }
00262 const char *DbName() { return dbname(); }
00264 const char *UserName() { return username(); }
00266 const char *HostName() { return hostname(); }
00268 const char *Port() { return port(); }
00270 const char *Options() const throw () { return options(); }
00272 int BackendPID() const { return backendpid(); }
00274 void Activate() { activate(); }
00276 void Deactivate() { deactivate(); }
00278 void SetClientEncoding(const PGSTD::string &E) { set_client_encoding(E); }
00280 void SetVariable(const PGSTD::string &Var, const PGSTD::string &Val)
00281 { set_variable(Var, Val); }
00282 #endif
00283
00284
00285 protected:
00287 void Connect();
00288
00290 virtual void startconnect() =0;
00291
00293 virtual void completeconnect() =0;
00294
00296 virtual void dropconnect() {}
00297
00299 PGconn *get_conn() const throw () { return m_Conn; }
00300
00302 void set_conn(PGconn *C) throw () { m_Conn = C; }
00303
00304 protected:
00305 void wait_read() const;
00306 void wait_write() const;
00307
00308 private:
00309 void SetupState();
00310 void InternalSetTrace();
00311 int Status() const { return PQstatus(m_Conn); }
00312 const char *ErrMsg() const;
00313 void Reset();
00314 void close() throw ();
00315 void RestoreVars();
00316 void halfconnect();
00317 int set_fdmask() const;
00318 void clear_fdmask() throw ();
00319 void go_sync();
00320 void go_async();
00321 PGSTD::string RawGetVar(const PGSTD::string &);
00322
00323
00325 PGSTD::string m_ConnInfo;
00326
00328 PGconn *m_Conn;
00330 unique<transaction_base> m_Trans;
00331
00333 PGSTD::auto_ptr<noticer> m_Noticer;
00335 FILE *m_Trace;
00336
00337 typedef PGSTD::multimap<PGSTD::string, pqxx::trigger *> TriggerList;
00339 TriggerList m_Triggers;
00340
00342 PGSTD::map<PGSTD::string, PGSTD::string> m_Vars;
00343
00344 mutable fd_set m_fdmask;
00345
00346 friend class transaction_base;
00347 result Exec(const char[], int Retries);
00348 void RegisterTransaction(transaction_base *);
00349 void UnregisterTransaction(transaction_base *) throw ();
00350 void MakeEmpty(result &, ExecStatusType=PGRES_EMPTY_QUERY);
00351 bool ReadCopyLine(PGSTD::string &);
00352 bool WriteCopyLine(const PGSTD::string &, bool async=false);
00353 void EndCopyWrite();
00354
00355 void RawSetVar(const PGSTD::string &Var, const PGSTD::string &Value);
00356 void AddVariables(const PGSTD::map<PGSTD::string, PGSTD::string> &);
00357
00358 friend class largeobject;
00359 PGconn *RawConnection() const { return m_Conn; }
00360
00361 friend class trigger;
00362 void AddTrigger(trigger *);
00363 void RemoveTrigger(trigger *) throw ();
00364
00365
00366 connection_base(const connection_base &);
00367 connection_base &operator=(const connection_base &);
00368 };
00369
00370
00371 }
00372
00373
00374
00375 inline pqxx::connection_base::~connection_base()
00376 {
00377 close();
00378 }
00379
00380