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 #include <stdexcept>
00020
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 in_doubt_error;
00037 class Result;
00038 class TransactionItf;
00039 class Trigger;
00040
00042
00046 struct PQXX_LIBEXPORT Noticer
00047 {
00048 virtual ~Noticer() {}
00049 virtual void operator()(const char Msg[]) throw () =0;
00050 };
00051
00052
00054 template<> inline PGSTD::string Classname(const TransactionItf *)
00055 {
00056 return "TransactionItf";
00057 }
00058
00059
00061
00062 class PQXX_LIBEXPORT broken_connection : public PGSTD::runtime_error
00063 {
00064 public:
00065 broken_connection() : PGSTD::runtime_error("Connection to back end failed") {}
00066 explicit broken_connection(const PGSTD::string &whatarg) :
00067 PGSTD::runtime_error(whatarg) {}
00068 };
00069
00070
00072
00081 class PQXX_LIBEXPORT ConnectionItf
00082 {
00083 public:
00085
00088 explicit ConnectionItf(const PGSTD::string &ConnInfo);
00089
00091
00095 explicit ConnectionItf(const char ConnInfo[]);
00096
00098 virtual ~ConnectionItf() =0;
00099
00101 void Disconnect() const throw ();
00102
00104 bool is_open() const;
00105
00107
00115 template<typename TRANSACTOR>
00116 void Perform(const TRANSACTOR &T, int Attempts=3);
00117
00118
00120
00121 * Noticer is also passed to the caller, so unless it is stored in another
00122 * auto_ptr, it will be deleted from the caller's context.
00123 * This may be important when running under Windows, where a DLL cannot free
00124 * memory allocated by the main program.
00125 * If a Noticer is set when the ConnectionItf is destructed, it will also be
00126 * deleted.
00127 * @param N the new message handler; must not be null or equal to the old one
00128 */
00129 PGSTD::auto_ptr<Noticer> SetNoticer(PGSTD::auto_ptr<Noticer> N);
00130 Noticer *GetNoticer() const throw () { return m_Noticer.get(); }
00131
00133 void ProcessNotice(const char[]) throw ();
00135
00136 { ProcessNotice(msg.c_str()); }
00137
00139 void Trace(FILE *);
00140
00142 void GetNotifs();
00143
00144
00145
00147 const char *DbName() const throw ()
00148 { Activate(); return PQdb(m_Conn); }
00149
00151 const char *UserName() const throw ()
00152 { Activate(); return PQuser(m_Conn); }
00153
00155 const char *HostName() const throw ()
00156 { Activate(); return PQhost(m_Conn); }
00157
00159 const char *Port() const throw ()
00160 { Activate(); return PQport(m_Conn); }
00161
00163 const char *Options() const throw ()
00164 { return m_ConnInfo.c_str(); }
00165
00167
00174 int BackendPID() const
00175 { return m_Conn ? PQbackendPID(m_Conn) : 0; }
00176
00178
00188 void Activate() const { if (!m_Conn) Connect(); }
00189
00191
00199 void Deactivate() const;
00200
00202
00208 void SetClientEncoding(const char Encoding[]);
00209
00210 protected:
00212 void Connect() const;
00213
00214 private:
00215 void SetupState() const;
00216 void InternalSetTrace() const;
00217 int Status() const { return PQstatus(m_Conn); }
00218 const char *ErrMsg() const;
00219 void Reset(const char OnReconnect[]=0);
00220 void close() throw ();
00221
00222 PGSTD::string m_ConnInfo;
00223 mutable PGconn *m_Conn;
00224 Unique<TransactionItf> m_Trans;
00225
00226 PGSTD::auto_ptr<Noticer> m_Noticer;
00227 FILE *m_Trace;
00228
00229 typedef PGSTD::multimap<PGSTD::string, pqxx::Trigger *> TriggerList;
00230 TriggerList m_Triggers;
00231
00232 friend class TransactionItf;
00233 Result Exec(const char[], int Retries=3, const char OnReconnect[]=0);
00234 void RegisterTransaction(const TransactionItf *);
00235 void UnregisterTransaction(const TransactionItf *) throw ();
00236 void MakeEmpty(Result &, ExecStatusType=PGRES_EMPTY_QUERY);
00237 void BeginCopyRead(const PGSTD::string &Table);
00238 bool ReadCopyLine(PGSTD::string &);
00239 void BeginCopyWrite(const PGSTD::string &Table);
00240 void WriteCopyLine(const PGSTD::string &);
00241 void EndCopy();
00242
00243 friend class LargeObject;
00244 PGconn *RawConnection() const { return m_Conn; }
00245
00246 friend class Trigger;
00247 void AddTrigger(Trigger *);
00248 void RemoveTrigger(Trigger *) throw ();
00249
00250
00251 ConnectionItf(const ConnectionItf &);
00252 ConnectionItf &operator=(const ConnectionItf &);
00253 };
00254
00255
00256 }
00257
00258
00269 template<typename TRANSACTOR>
00270 inline void pqxx::ConnectionItf::Perform(const TRANSACTOR &T,
00271 int Attempts)
00272 {
00273 if (Attempts <= 0) return;
00274
00275 bool Done = false;
00276
00277
00278
00279 do
00280 {
00281 --Attempts;
00282
00283
00284 TRANSACTOR T2(T);
00285 try
00286 {
00287 typename TRANSACTOR::argument_type X(*this, T2.Name());
00288 T2(X);
00289 X.Commit();
00290 Done = true;
00291 }
00292 catch (const in_doubt_error &)
00293 {
00294
00295
00296 T2.OnDoubt();
00297 throw;
00298 }
00299 catch (const PGSTD::exception &e)
00300 {
00301
00302 T2.OnAbort(e.what());
00303 if (Attempts <= 0) throw;
00304 continue;
00305 }
00306 catch (...)
00307 {
00308
00309 T2.OnAbort("Unknown exception");
00310 throw;
00311 }
00312
00313 T2.OnCommit();
00314 } while (!Done);
00315 }
00316
00317
00318
00319 inline pqxx::ConnectionItf::~ConnectionItf()
00320 {
00321 close();
00322 }
00323
00324 #endif
00325