00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014 #ifndef PQXX_CONNECTIONITF_H
00015 #define PQXX_CONNECTIONITF_H
00016
00017 #include <map>
00018 #include <memory>
00019
00020 #include "pqxx/except.h"
00021 #include "pqxx/transactor.h"
00022 #include "pqxx/util.h"
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034 namespace pqxx
00035 {
00036 class Result;
00037 class TransactionItf;
00038 class Trigger;
00039
00041
00045 struct PQXX_LIBEXPORT Noticer
00046 {
00047 virtual ~Noticer() {}
00048 virtual void operator()(const char Msg[]) throw () =0;
00049 };
00050
00051
00053 template<> inline PGSTD::string Classname(const TransactionItf *)
00054 {
00055 return "TransactionItf";
00056 }
00057
00058
00060
00078 class PQXX_LIBEXPORT ConnectionItf
00079 {
00080 public:
00082
00085 explicit ConnectionItf(const PGSTD::string &ConnInfo);
00086
00088
00092 explicit ConnectionItf(const char ConnInfo[]);
00093
00095 virtual ~ConnectionItf() =0;
00096
00098 void Disconnect() throw ();
00099
00101 bool is_open() const;
00102
00104
00112 template<typename TRANSACTOR>
00113 void Perform(const TRANSACTOR &T, int Attempts=3);
00114
00115
00117
00118 * Noticer is also passed to the caller, so unless it is stored in another
00119 * auto_ptr, it will be deleted from the caller's context.
00120 * This may be important when running under Windows, where a DLL cannot free
00121 * memory allocated by the main program.
00122 * If a Noticer is set when the ConnectionItf is destructed, it will also be
00123 * deleted.
00124 * @param N the new message handler; must not be null or equal to the old one
00125 */
00126 PGSTD::auto_ptr<Noticer> SetNoticer(PGSTD::auto_ptr<Noticer> N);
00127 Noticer *GetNoticer() const throw () { return m_Noticer.get(); }
00128
00130 void ProcessNotice(const char[]) throw ();
00132
00133 { ProcessNotice(msg.c_str()); }
00134
00136 void Trace(FILE *);
00137
00139 void GetNotifs();
00140
00141
00142
00144 const char *DbName()
00145 { Activate(); return PQdb(m_Conn); }
00146
00148 const char *UserName()
00149 { Activate(); return PQuser(m_Conn); }
00150
00152 const char *HostName()
00153 { Activate(); return PQhost(m_Conn); }
00154
00156 const char *Port()
00157 { Activate(); return PQport(m_Conn); }
00158
00160 const char *Options() const throw ()
00161 { return m_ConnInfo.c_str(); }
00162
00164
00171 int BackendPID() const
00172 { return m_Conn ? PQbackendPID(m_Conn) : 0; }
00173
00175
00185 void Activate() { if (!m_Conn) Connect(); }
00186
00188
00196 void Deactivate();
00197
00199
00205 void SetClientEncoding(const PGSTD::string &Encoding)
00206 { SetVariable("CLIENT_ENCODING", Encoding); }
00207
00209
00220 void SetVariable(const PGSTD::string &Var, const PGSTD::string &Value);
00221
00222 protected:
00224 void Connect();
00225
00226 private:
00227 void SetupState();
00228 void InternalSetTrace();
00229 int Status() const { return PQstatus(m_Conn); }
00230 const char *ErrMsg() const;
00231 void Reset(const char OnReconnect[]=0);
00232 void close() throw ();
00233 void RestoreVars();
00234
00235 PGSTD::string m_ConnInfo;
00236 PGconn *m_Conn;
00237 Unique<TransactionItf> m_Trans;
00238
00239 PGSTD::auto_ptr<Noticer> m_Noticer;
00240 FILE *m_Trace;
00241
00242 typedef PGSTD::multimap<PGSTD::string, pqxx::Trigger *> TriggerList;
00243 TriggerList m_Triggers;
00244
00245 PGSTD::map<PGSTD::string, PGSTD::string> m_Vars;
00246
00247 friend class TransactionItf;
00248 Result Exec(const char[], int Retries=3, const char OnReconnect[]=0);
00249 void RegisterTransaction(TransactionItf *);
00250 void UnregisterTransaction(TransactionItf *) throw ();
00251 void MakeEmpty(Result &, ExecStatusType=PGRES_EMPTY_QUERY);
00252 void BeginCopyRead(const PGSTD::string &Table);
00253 bool ReadCopyLine(PGSTD::string &);
00254 void BeginCopyWrite(const PGSTD::string &Table);
00255 void WriteCopyLine(const PGSTD::string &);
00256 void EndCopy();
00257 void RawSetVar(const PGSTD::string &Var, const PGSTD::string &Value);
00258 void AddVariables(const PGSTD::map<PGSTD::string, PGSTD::string> &);
00259
00260 friend class LargeObject;
00261 PGconn *RawConnection() const { return m_Conn; }
00262
00263 friend class Trigger;
00264 void AddTrigger(Trigger *);
00265 void RemoveTrigger(Trigger *) throw ();
00266
00267
00268 ConnectionItf(const ConnectionItf &);
00269 ConnectionItf &operator=(const ConnectionItf &);
00270 };
00271
00272
00273 }
00274
00275
00286 template<typename TRANSACTOR>
00287 inline void pqxx::ConnectionItf::Perform(const TRANSACTOR &T,
00288 int Attempts)
00289 {
00290 if (Attempts <= 0) return;
00291
00292 bool Done = false;
00293
00294
00295
00296 do
00297 {
00298 --Attempts;
00299
00300
00301 TRANSACTOR T2(T);
00302 try
00303 {
00304 typename TRANSACTOR::argument_type X(*this, T2.Name());
00305 T2(X);
00306 X.Commit();
00307 Done = true;
00308 }
00309 catch (const in_doubt_error &)
00310 {
00311
00312
00313 T2.OnDoubt();
00314 throw;
00315 }
00316 catch (const PGSTD::exception &e)
00317 {
00318
00319 T2.OnAbort(e.what());
00320 if (Attempts <= 0) throw;
00321 continue;
00322 }
00323 catch (...)
00324 {
00325
00326 T2.OnAbort("Unknown exception");
00327 throw;
00328 }
00329
00330 T2.OnCommit();
00331 } while (!Done);
00332 }
00333
00334
00335
00336 inline pqxx::ConnectionItf::~ConnectionItf()
00337 {
00338 close();
00339 }
00340
00341 #endif
00342