Main Page   Namespace List   Class Hierarchy   Alphabetical List   Compound List   File List   Namespace Members   Compound Members   File Members  

connection.h

Go to the documentation of this file.
00001 /*-------------------------------------------------------------------------
00002  *
00003  *   FILE
00004  *      pqxx/connection.h
00005  *
00006  *   DESCRIPTION
00007  *      definition of the pqxx::Connection class.
00008  *   pqxx::Connection encapsulates a frontend to backend connection
00009  *
00010  * Copyright (c) 2001-2002, Jeroen T. Vermeulen <jtv@xs4all.nl>
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 /* Use of the libpqxx library starts here.
00025  *
00026  * Everything that can be done with a database through libpqxx must go through
00027  * a Connection object.
00028  */
00029 
00030 /* Methods tested in eg. self-test program test1 are marked with "//[t1]"
00031  */
00032 
00033 // TODO: Implement NoticeProcessors with C++ linkage
00034 // TODO: Teach Transactor to handle multiple connections--quasi "2-phase commit"
00035 
00036 
00037 namespace pqxx
00038 {
00039 class in_doubt_error;   // See pqxx/transactionitf.h
00040 class Result;           // See pqxx/result.h
00041 class TransactionItf;   // See pqxx/transactionitf.h
00042 class Trigger;          // See pqxx/trigger.h
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   // TODO: Allow two-stage creation (create first, open later)
00079   explicit Connection(const PGSTD::string &ConnInfo);                   //[t1]
00080 
00082   ~Connection();                                                        //[t1]
00083 
00085   void Disconnect() throw ();                                           //[t2]
00086 
00088   bool IsOpen() const;                                                  //[t1]
00089 
00091   template<typename TRANSACTOR> 
00092   void Perform(const TRANSACTOR &, int Attempts=3);                     //[t4]
00093 
00095 
00099   NoticeProcessor SetNoticeProcessor(NoticeProcessor, void *arg);       //[t1]
00100 
00102   void ProcessNotice(const char[]) throw ();                            //[t1]
00104   void ProcessNotice(PGSTD::string msg) throw ()                        //[t1]
00105         { ProcessNotice(msg.c_str()); }
00106 
00108   void Trace(FILE *);                                                   //[t3]
00110   void Untrace();                                                       //[t3]
00111 
00112 
00114   void GetNotifs();                                                     //[t4]
00115 
00116   // Miscellaneous query functions (probably not needed very often)
00117  
00119   const char *DbName() const throw ()                                   //[t1]
00120         { return m_Conn ? PQdb(m_Conn) : ""; }
00121 
00123   const char *UserName() const throw ()                                 //[t1]
00124         { return m_Conn ? PQuser(m_Conn) : ""; }
00125 
00127   const char *HostName() const throw ()                                 //[t1]
00128         { return m_Conn ? PQhost(m_Conn) : ""; }
00129 
00131   const char *Port() const throw ()                                     //[t1]
00132         { return m_Conn ? PQport(m_Conn) : ""; }
00133 
00135   const char *Options() const throw ()                                  //[t1]
00136         { return m_ConnInfo.c_str(); }
00137 
00139   int BackendPID() const;                                               //[t1]
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;     // Connection string
00148   PGconn *m_Conn;               // Connection handle
00149   Unique<TransactionItf> m_Trans;// Active transaction on connection, if any
00150   void *m_NoticeProcessorArg;   // Client-set argument to notice processor func
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   // Not allowed:
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)                           //[t4]
00190 {
00191   if (Attempts <= 0) return;
00192 
00193   bool Done = false;
00194 
00195   // Make attempts to perform T
00196   // TODO: Differentiate between db-related exceptions and other exceptions?
00197   do
00198   {
00199     --Attempts;
00200 
00201     // Work on a copy of T2 so we can restore the starting situation if need be
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       // Not sure whether transaction went through or not.  The last thing in
00213       // the world that we should do now is retry.
00214       T2.OnDoubt();
00215       throw;
00216     }
00217     catch (const PGSTD::exception &e)
00218     {
00219       // Could be any kind of error.  
00220       T2.OnAbort(e.what());
00221       if (Attempts <= 0) throw;
00222       continue;
00223     }
00224     catch (...)
00225     {
00226       // Don't try to forge ahead if we don't even know what happened
00227       T2.OnAbort("Unknown exception");
00228       throw;
00229     }
00230 
00231     T2.OnCommit();
00232   } while (!Done);
00233 }
00234 
00235 
00236 }
00237 
00238 #endif
00239 

Generated on Sat Aug 10 21:52:38 2002 for libpqxx by doxygen1.2.16