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
00084 explicit Connection(const PGSTD::string &ConnInfo,
00085 bool Immediate=true);
00086
00088 ~Connection();
00089
00091 void Disconnect() throw ();
00092
00094 bool IsOpen() const;
00095
00097 template<typename TRANSACTOR>
00098 void Perform(const TRANSACTOR &, int Attempts=3);
00099
00101
00105 NoticeProcessor SetNoticeProcessor(NoticeProcessor, void *arg);
00106
00108 void ProcessNotice(const char[]) throw ();
00110
00111 { ProcessNotice(msg.c_str()); }
00112
00114 void Trace(FILE *);
00116
00117
00118
00120 void GetNotifs();
00121
00122
00123
00125 const char *DbName() const throw ()
00126 { return m_Conn ? PQdb(m_Conn) : ""; }
00127
00129 const char *UserName() const throw ()
00130 { return m_Conn ? PQuser(m_Conn) : ""; }
00131
00133 const char *HostName() const throw ()
00134 { return m_Conn ? PQhost(m_Conn) : ""; }
00135
00137 const char *Port() const throw ()
00138 { return m_Conn ? PQport(m_Conn) : ""; }
00139
00141 const char *Options() const throw ()
00142 { return m_ConnInfo.c_str(); }
00143
00145
00152 int BackendPID() const;
00153
00154 private:
00155 void Connect();
00156 void SetupState();
00157 int Status() const { return PQstatus(m_Conn); }
00158 const char *ErrMsg() const;
00159 void Reset(const char OnReconnect[]=0);
00160
00161 PGSTD::string m_ConnInfo;
00162 PGconn *m_Conn;
00163 Unique<TransactionItf> m_Trans;
00164
00165 NoticeProcessor m_NoticeProcessor;
00166 void *m_NoticeProcessorArg;
00167 FILE *m_Trace;
00168
00169 typedef PGSTD::multimap<PGSTD::string, pqxx::Trigger *> TriggerList;
00170 TriggerList m_Triggers;
00171
00172 friend class TransactionItf;
00173 Result Exec(const char[], int Retries=3, const char OnReconnect[]=0);
00174 void RegisterTransaction(const TransactionItf *);
00175 void UnregisterTransaction(const TransactionItf *) throw ();
00176 void MakeEmpty(Result &, ExecStatusType=PGRES_EMPTY_QUERY);
00177 void BeginCopyRead(PGSTD::string Table);
00178 bool ReadCopyLine(PGSTD::string &);
00179 void BeginCopyWrite(PGSTD::string Table);
00180 void WriteCopyLine(PGSTD::string);
00181 void EndCopy();
00182
00183 friend class Trigger;
00184 void AddTrigger(Trigger *);
00185 void RemoveTrigger(Trigger *) throw ();
00186
00187
00188 Connection(const Connection &);
00189 Connection &operator=(const Connection &);
00190 };
00191
00192
00193
00204 template<typename TRANSACTOR>
00205 inline void Connection::Perform(const TRANSACTOR &T,
00206 int Attempts)
00207 {
00208 if (Attempts <= 0) return;
00209
00210 bool Done = false;
00211
00212
00213
00214 do
00215 {
00216 --Attempts;
00217
00218
00219 TRANSACTOR T2(T);
00220 try
00221 {
00222 typename TRANSACTOR::argument_type X(*this, T2.Name());
00223 T2(X);
00224 X.Commit();
00225 Done = true;
00226 }
00227 catch (const in_doubt_error &)
00228 {
00229
00230
00231 T2.OnDoubt();
00232 throw;
00233 }
00234 catch (const PGSTD::exception &e)
00235 {
00236
00237 T2.OnAbort(e.what());
00238 if (Attempts <= 0) throw;
00239 continue;
00240 }
00241 catch (...)
00242 {
00243
00244 T2.OnAbort("Unknown exception");
00245 throw;
00246 }
00247
00248 T2.OnCommit();
00249 } while (!Done);
00250 }
00251
00252
00253 }
00254
00255 #endif
00256