00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014 #ifndef PQXX_CONNECTION_H
00015 #define PQXX_CONNECTION_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
00036 extern "C" void pqxxNoticeCaller(void *, const char *);
00037
00038 namespace pqxx
00039 {
00040 class in_doubt_error;
00041 class Result;
00042 class TransactionItf;
00043 class Trigger;
00044
00046 extern "C" { typedef void (*NoticeProcessor)(void *arg, const char *msg); }
00047
00049 struct Noticer
00050 {
00051 virtual ~Noticer() {}
00052 virtual void operator()(const char Msg[]) throw () =0;
00053 };
00054
00055
00057 template<> inline PGSTD::string Classname(const TransactionItf *)
00058 {
00059 return "TransactionItf";
00060 }
00061
00062
00064
00065 class broken_connection : public PGSTD::runtime_error
00066 {
00067 public:
00068 broken_connection() : PGSTD::runtime_error("Connection to back end failed") {}
00069 explicit broken_connection(const PGSTD::string &whatarg) :
00070 PGSTD::runtime_error(whatarg) {}
00071 };
00072
00073
00075
00083 class PQXX_LIBEXPORT Connection
00084 {
00085 public:
00087
00096 explicit Connection(const PGSTD::string &ConnInfo,
00097 bool Immediate=true);
00098
00100
00110 explicit Connection(const char ConnInfo[], bool Immediate=true);
00111
00113 ~Connection();
00114
00116 void Disconnect() const throw ();
00117
00119 bool is_open() const;
00120
00122 bool IsOpen() const { return is_open(); }
00123
00125 template<typename TRANSACTOR>
00126 void Perform(const TRANSACTOR &, int Attempts=3);
00127
00129
00132 NoticeProcessor SetNoticeProcessor(NoticeProcessor, void *arg);
00133
00135
00137 std::auto_ptr<Noticer> SetNoticer(std::auto_ptr<Noticer>);
00138 Noticer *GetNoticer() const throw () { return m_Noticer.get(); }
00139
00141 void ProcessNotice(const char[]) throw ();
00143
00144 { ProcessNotice(msg.c_str()); }
00145
00147 void Trace(FILE *);
00149
00150
00151
00153 void GetNotifs();
00154
00155
00156
00158 const char *DbName() const throw ()
00159 { Activate(); return PQdb(m_Conn); }
00160
00162 const char *UserName() const throw ()
00163 { Activate(); return PQuser(m_Conn); }
00164
00166 const char *HostName() const throw ()
00167 { Activate(); return PQhost(m_Conn); }
00168
00170 const char *Port() const throw ()
00171 { Activate(); return PQport(m_Conn); }
00172
00174 const char *Options() const throw ()
00175 { return m_ConnInfo.c_str(); }
00176
00178
00185 int BackendPID() const
00186 { return m_Conn ? PQbackendPID(m_Conn) : 0; }
00187
00189
00199 void Activate() const { if (!m_Conn) Connect(); }
00200
00202
00210 void Deactivate() const;
00211
00212 private:
00213 void Connect() const;
00214 void SetupState() const;
00215 void InternalSetTrace() const;
00216 int Status() const { return PQstatus(m_Conn); }
00217 const char *ErrMsg() const;
00218 void Reset(const char OnReconnect[]=0);
00219
00220 PGSTD::string m_ConnInfo;
00221 mutable PGconn *m_Conn;
00222 Unique<TransactionItf> m_Trans;
00223
00225 mutable NoticeProcessor m_NoticeProcessor;
00226 void *m_NoticeProcessorArg;
00227 std::auto_ptr<Noticer> m_Noticer;
00228 FILE *m_Trace;
00229
00230 typedef PGSTD::multimap<PGSTD::string, pqxx::Trigger *> TriggerList;
00231 TriggerList m_Triggers;
00232
00233 friend class TransactionItf;
00234 Result Exec(const char[], int Retries=3, const char OnReconnect[]=0);
00235 void RegisterTransaction(const TransactionItf *);
00236 void UnregisterTransaction(const TransactionItf *) throw ();
00237 void MakeEmpty(Result &, ExecStatusType=PGRES_EMPTY_QUERY);
00238 void BeginCopyRead(const PGSTD::string &Table);
00239 bool ReadCopyLine(PGSTD::string &);
00240 void BeginCopyWrite(const PGSTD::string &Table);
00241 void WriteCopyLine(const PGSTD::string &);
00242 void EndCopy();
00243
00244 friend class Trigger;
00245 void AddTrigger(Trigger *);
00246 void RemoveTrigger(Trigger *) throw ();
00247
00248
00249 Connection(const Connection &);
00250 Connection &operator=(const Connection &);
00251 };
00252
00253
00254
00265 template<typename TRANSACTOR>
00266 inline void Connection::Perform(const TRANSACTOR &T,
00267 int Attempts)
00268 {
00269 if (Attempts <= 0) return;
00270
00271 bool Done = false;
00272
00273
00274
00275 do
00276 {
00277 --Attempts;
00278
00279
00280 TRANSACTOR T2(T);
00281 try
00282 {
00283 typename TRANSACTOR::argument_type X(*this, T2.Name());
00284 T2(X);
00285 X.Commit();
00286 Done = true;
00287 }
00288 catch (const in_doubt_error &)
00289 {
00290
00291
00292 T2.OnDoubt();
00293 throw;
00294 }
00295 catch (const PGSTD::exception &e)
00296 {
00297
00298 T2.OnAbort(e.what());
00299 if (Attempts <= 0) throw;
00300 continue;
00301 }
00302 catch (...)
00303 {
00304
00305 T2.OnAbort("Unknown exception");
00306 throw;
00307 }
00308
00309 T2.OnCommit();
00310 } while (!Done);
00311 }
00312
00313
00314 }
00315
00316 #endif
00317