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 <stdexcept>
00019
00020 #include "pqxx/transactor.h"
00021 #include "pqxx/util.h"
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036 namespace pqxx
00037 {
00038 class in_doubt_error;
00039 class Result;
00040 class TransactionItf;
00041 class Trigger;
00042
00043 extern "C" { typedef void (*NoticeProcessor)(void *arg, const char *msg); }
00044
00045
00047 template<> inline PGSTD::string Classname(const TransactionItf *)
00048 {
00049 return "TransactionItf";
00050 }
00051
00052
00054
00055 class broken_connection : public PGSTD::runtime_error
00056 {
00057 public:
00058 broken_connection() : PGSTD::runtime_error("Connection to back end failed") {}
00059 explicit broken_connection(const PGSTD::string &whatarg) :
00060 PGSTD::runtime_error(whatarg) {}
00061 };
00062
00063
00065
00073 class PQXX_LIBEXPORT Connection
00074 {
00075 public:
00077
00086 explicit Connection(const PGSTD::string &ConnInfo,
00087 bool Immediate=true);
00088
00090 ~Connection();
00091
00093 void Disconnect() const throw ();
00094
00096 bool IsOpen() const;
00097
00099 template<typename TRANSACTOR>
00100 void Perform(const TRANSACTOR &, int Attempts=3);
00101
00103
00107 NoticeProcessor SetNoticeProcessor(NoticeProcessor, void *arg);
00108
00110 void ProcessNotice(const char[]) throw ();
00112
00113 { ProcessNotice(msg.c_str()); }
00114
00116 void Trace(FILE *);
00118
00119
00120
00122 void GetNotifs();
00123
00124
00125
00127 const char *DbName() const throw ()
00128 { Activate(); return PQdb(m_Conn); }
00129
00131 const char *UserName() const throw ()
00132 { Activate(); return PQuser(m_Conn); }
00133
00135 const char *HostName() const throw ()
00136 { Activate(); return PQhost(m_Conn); }
00137
00139 const char *Port() const throw ()
00140 { Activate(); return PQport(m_Conn); }
00141
00143 const char *Options() const throw ()
00144 { return m_ConnInfo.c_str(); }
00145
00147
00154 int BackendPID() const
00155 { return m_Conn ? PQbackendPID(m_Conn) : 0; }
00156
00158
00168 void Activate() const { if (!m_Conn) Connect(); }
00169
00171
00179 void Deactivate() const;
00180
00181 private:
00182 void Connect() const;
00183 void SetupState() const;
00184 void InternalSetTrace() const;
00185 int Status() const { return PQstatus(m_Conn); }
00186 const char *ErrMsg() const;
00187 void Reset(const char OnReconnect[]=0);
00188
00189 PGSTD::string m_ConnInfo;
00190 mutable PGconn *m_Conn;
00191 Unique<TransactionItf> m_Trans;
00192
00194 mutable NoticeProcessor m_NoticeProcessor;
00195 void *m_NoticeProcessorArg;
00196 FILE *m_Trace;
00197
00198 typedef PGSTD::multimap<PGSTD::string, pqxx::Trigger *> TriggerList;
00199 TriggerList m_Triggers;
00200
00201 friend class TransactionItf;
00202 Result Exec(const char[], int Retries=3, const char OnReconnect[]=0);
00203 void RegisterTransaction(const TransactionItf *);
00204 void UnregisterTransaction(const TransactionItf *) throw ();
00205 void MakeEmpty(Result &, ExecStatusType=PGRES_EMPTY_QUERY);
00206 void BeginCopyRead(const PGSTD::string &Table);
00207 bool ReadCopyLine(PGSTD::string &);
00208 void BeginCopyWrite(const PGSTD::string &Table);
00209 void WriteCopyLine(const PGSTD::string &);
00210 void EndCopy();
00211
00212 friend class Trigger;
00213 void AddTrigger(Trigger *);
00214 void RemoveTrigger(Trigger *) throw ();
00215
00216
00217 Connection(const Connection &);
00218 Connection &operator=(const Connection &);
00219 };
00220
00221
00222
00233 template<typename TRANSACTOR>
00234 inline void Connection::Perform(const TRANSACTOR &T,
00235 int Attempts)
00236 {
00237 if (Attempts <= 0) return;
00238
00239 bool Done = false;
00240
00241
00242
00243 do
00244 {
00245 --Attempts;
00246
00247
00248 TRANSACTOR T2(T);
00249 try
00250 {
00251 typename TRANSACTOR::argument_type X(*this, T2.Name());
00252 T2(X);
00253 X.Commit();
00254 Done = true;
00255 }
00256 catch (const in_doubt_error &)
00257 {
00258
00259
00260 T2.OnDoubt();
00261 throw;
00262 }
00263 catch (const PGSTD::exception &e)
00264 {
00265
00266 T2.OnAbort(e.what());
00267 if (Attempts <= 0) throw;
00268 continue;
00269 }
00270 catch (...)
00271 {
00272
00273 T2.OnAbort("Unknown exception");
00274 throw;
00275 }
00276
00277 T2.OnCommit();
00278 } while (!Done);
00279 }
00280
00281
00282 }
00283
00284 #endif
00285