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
00037 namespace pqxx
00038 {
00039 class in_doubt_error;
00040 class Result;
00041 class TransactionItf;
00042 class Trigger;
00043
00044 extern "C" { typedef void (*NoticeProcessor)(void *arg, const char *msg); }
00045
00046
00048 template<> inline PGSTD::string Classname(const TransactionItf *)
00049 {
00050 return "TransactionItf";
00051 }
00052
00053
00055
00056 class broken_connection : public PGSTD::runtime_error
00057 {
00058 public:
00059 broken_connection() : PGSTD::runtime_error("Connection to back end failed") {}
00060 explicit broken_connection(const PGSTD::string &whatarg) :
00061 PGSTD::runtime_error(whatarg) {}
00062 };
00063
00064
00066
00074 class PQXX_LIBEXPORT Connection
00075 {
00076 public:
00077
00079
00080
00082 ~Connection();
00083
00085 void Disconnect() throw ();
00086
00088 bool IsOpen() const;
00089
00091 template<typename TRANSACTOR>
00092 void Perform(const TRANSACTOR &, int Attempts=3);
00093
00095
00099 NoticeProcessor SetNoticeProcessor(NoticeProcessor, void *arg);
00100
00102 void ProcessNotice(const char[]) throw ();
00104
00105 { ProcessNotice(msg.c_str()); }
00106
00108 void Trace(FILE *);
00110
00111
00112
00114 void GetNotifs();
00115
00116
00117
00119 const char *DbName() const throw ()
00120 { return m_Conn ? PQdb(m_Conn) : ""; }
00121
00123 const char *UserName() const throw ()
00124 { return m_Conn ? PQuser(m_Conn) : ""; }
00125
00127 const char *HostName() const throw ()
00128 { return m_Conn ? PQhost(m_Conn) : ""; }
00129
00131 const char *Port() const throw ()
00132 { return m_Conn ? PQport(m_Conn) : ""; }
00133
00135 const char *Options() const throw ()
00136 { return m_ConnInfo.c_str(); }
00137
00139 int BackendPID() const;
00140
00141 private:
00142 void Connect();
00143 int Status() const { return PQstatus(m_Conn); }
00144 const char *ErrMsg() const;
00145 void Reset(const char OnReconnect[]=0);
00146
00147 PGSTD::string m_ConnInfo;
00148 PGconn *m_Conn;
00149 Unique<TransactionItf> m_Trans;
00150 void *m_NoticeProcessorArg;
00151
00152 typedef PGSTD::multimap<PGSTD::string, pqxx::Trigger *> TriggerList;
00153 TriggerList m_Triggers;
00154
00155 friend class TransactionItf;
00156 Result Exec(const char[], int Retries=3, const char OnReconnect[]=0);
00157 void RegisterTransaction(const TransactionItf *);
00158 void UnregisterTransaction(const TransactionItf *) throw ();
00159 void MakeEmpty(Result &, ExecStatusType=PGRES_EMPTY_QUERY);
00160 void BeginCopyRead(PGSTD::string Table);
00161 bool ReadCopyLine(PGSTD::string &);
00162 void BeginCopyWrite(PGSTD::string Table);
00163 void WriteCopyLine(PGSTD::string);
00164 void EndCopy();
00165
00166 friend class Trigger;
00167 void AddTrigger(Trigger *);
00168 void RemoveTrigger(Trigger *) throw ();
00169
00170
00171 Connection(const Connection &);
00172 Connection &operator=(const Connection &);
00173 };
00174
00175
00176
00187 template<typename TRANSACTOR>
00188 inline void Connection::Perform(const TRANSACTOR &T,
00189 int Attempts)
00190 {
00191 if (Attempts <= 0) return;
00192
00193 bool Done = false;
00194
00195
00196
00197 do
00198 {
00199 --Attempts;
00200
00201
00202 TRANSACTOR T2(T);
00203 try
00204 {
00205 typename TRANSACTOR::argument_type X(*this, T2.Name());
00206 T2(X);
00207 X.Commit();
00208 Done = true;
00209 }
00210 catch (const in_doubt_error &)
00211 {
00212
00213
00214 T2.OnDoubt();
00215 throw;
00216 }
00217 catch (const PGSTD::exception &e)
00218 {
00219
00220 T2.OnAbort(e.what());
00221 if (Attempts <= 0) throw;
00222 continue;
00223 }
00224 catch (...)
00225 {
00226
00227 T2.OnAbort("Unknown exception");
00228 throw;
00229 }
00230
00231 T2.OnCommit();
00232 } while (!Done);
00233 }
00234
00235
00236 }
00237
00238 #endif
00239