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
00069 class PQXX_LIBEXPORT ConnectionItf
00070 {
00071 public:
00073
00076 explicit ConnectionItf(const PGSTD::string &ConnInfo);
00077
00079
00083 explicit ConnectionItf(const char ConnInfo[]);
00084
00086 virtual ~ConnectionItf() =0;
00087
00089 void Disconnect() const throw ();
00090
00092 bool is_open() const;
00093
00095
00103 template<typename TRANSACTOR>
00104 void Perform(const TRANSACTOR &T, int Attempts=3);
00105
00106
00108
00109 * Noticer is also passed to the caller, so unless it is stored in another
00110 * auto_ptr, it will be deleted from the caller's context.
00111 * This may be important when running under Windows, where a DLL cannot free
00112 * memory allocated by the main program.
00113 * If a Noticer is set when the ConnectionItf is destructed, it will also be
00114 * deleted.
00115 * @param N the new message handler; must not be null or equal to the old one
00116 */
00117 PGSTD::auto_ptr<Noticer> SetNoticer(PGSTD::auto_ptr<Noticer> N);
00118 Noticer *GetNoticer() const throw () { return m_Noticer.get(); }
00119
00121 void ProcessNotice(const char[]) throw ();
00123
00124 { ProcessNotice(msg.c_str()); }
00125
00127 void Trace(FILE *);
00128
00130 void GetNotifs();
00131
00132
00133
00135 const char *DbName() const throw ()
00136 { Activate(); return PQdb(m_Conn); }
00137
00139 const char *UserName() const throw ()
00140 { Activate(); return PQuser(m_Conn); }
00141
00143 const char *HostName() const throw ()
00144 { Activate(); return PQhost(m_Conn); }
00145
00147 const char *Port() const throw ()
00148 { Activate(); return PQport(m_Conn); }
00149
00151 const char *Options() const throw ()
00152 { return m_ConnInfo.c_str(); }
00153
00155
00162 int BackendPID() const
00163 { return m_Conn ? PQbackendPID(m_Conn) : 0; }
00164
00166
00176 void Activate() const { if (!m_Conn) Connect(); }
00177
00179
00187 void Deactivate() const;
00188
00190
00196 void SetClientEncoding(const char Encoding[]);
00197
00198 protected:
00200 void Connect() const;
00201
00202 private:
00203 void SetupState() const;
00204 void InternalSetTrace() const;
00205 int Status() const { return PQstatus(m_Conn); }
00206 const char *ErrMsg() const;
00207 void Reset(const char OnReconnect[]=0);
00208 void close() throw ();
00209
00210 PGSTD::string m_ConnInfo;
00211 mutable PGconn *m_Conn;
00212 Unique<TransactionItf> m_Trans;
00213
00214 PGSTD::auto_ptr<Noticer> m_Noticer;
00215 FILE *m_Trace;
00216
00217 typedef PGSTD::multimap<PGSTD::string, pqxx::Trigger *> TriggerList;
00218 TriggerList m_Triggers;
00219
00220 friend class TransactionItf;
00221 Result Exec(const char[], int Retries=3, const char OnReconnect[]=0);
00222 void RegisterTransaction(const TransactionItf *);
00223 void UnregisterTransaction(const TransactionItf *) throw ();
00224 void MakeEmpty(Result &, ExecStatusType=PGRES_EMPTY_QUERY);
00225 void BeginCopyRead(const PGSTD::string &Table);
00226 bool ReadCopyLine(PGSTD::string &);
00227 void BeginCopyWrite(const PGSTD::string &Table);
00228 void WriteCopyLine(const PGSTD::string &);
00229 void EndCopy();
00230
00231 friend class LargeObject;
00232 PGconn *RawConnection() const { return m_Conn; }
00233
00234 friend class Trigger;
00235 void AddTrigger(Trigger *);
00236 void RemoveTrigger(Trigger *) throw ();
00237
00238
00239 ConnectionItf(const ConnectionItf &);
00240 ConnectionItf &operator=(const ConnectionItf &);
00241 };
00242
00243
00244 }
00245
00246
00257 template<typename TRANSACTOR>
00258 inline void pqxx::ConnectionItf::Perform(const TRANSACTOR &T,
00259 int Attempts)
00260 {
00261 if (Attempts <= 0) return;
00262
00263 bool Done = false;
00264
00265
00266
00267 do
00268 {
00269 --Attempts;
00270
00271
00272 TRANSACTOR T2(T);
00273 try
00274 {
00275 typename TRANSACTOR::argument_type X(*this, T2.Name());
00276 T2(X);
00277 X.Commit();
00278 Done = true;
00279 }
00280 catch (const in_doubt_error &)
00281 {
00282
00283
00284 T2.OnDoubt();
00285 throw;
00286 }
00287 catch (const PGSTD::exception &e)
00288 {
00289
00290 T2.OnAbort(e.what());
00291 if (Attempts <= 0) throw;
00292 continue;
00293 }
00294 catch (...)
00295 {
00296
00297 T2.OnAbort("Unknown exception");
00298 throw;
00299 }
00300
00301 T2.OnCommit();
00302 } while (!Done);
00303 }
00304
00305
00306
00307 inline pqxx::ConnectionItf::~ConnectionItf()
00308 {
00309 close();
00310 }
00311
00312 #endif
00313