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

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-2003, 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 
00035 
00036 namespace pqxx
00037 {
00038 class in_doubt_error;   // See pqxx/transactionitf.h
00039 class Result;           // See pqxx/result.h
00040 class TransactionItf;   // See pqxx/transactionitf.h
00041 class Trigger;          // See pqxx/trigger.h
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);                             //[t1]
00088 
00090   ~Connection();                                                        //[t1]
00091 
00093   void Disconnect() const throw ();                                     //[t2]
00094 
00096   bool is_open() const;                                                 //[t1]
00097 
00099   bool IsOpen() const { return is_open(); }
00100 
00102   template<typename TRANSACTOR> 
00103   void Perform(const TRANSACTOR &, int Attempts=3);                     //[t4]
00104 
00106 
00110   NoticeProcessor SetNoticeProcessor(NoticeProcessor, void *arg);       //[t1]
00111 
00113   void ProcessNotice(const char[]) throw ();                            //[t1]
00115   void ProcessNotice(const PGSTD::string &msg) throw ()                 //[t1]
00116         { ProcessNotice(msg.c_str()); }
00117 
00119   void Trace(FILE *);                                                   //[t3]
00121   void Untrace() { Trace(0); }
00122 
00123 
00125   void GetNotifs();                                                     //[t4]
00126 
00127   // Miscellaneous query functions (probably not needed very often)
00128  
00130   const char *DbName() const throw ()                                   //[t1]
00131         { Activate(); return PQdb(m_Conn); }
00132 
00134   const char *UserName() const throw ()                                 //[t1]
00135         { Activate(); return  PQuser(m_Conn); }
00136 
00138   const char *HostName() const throw ()                                 //[t1]
00139         { Activate(); return PQhost(m_Conn); }
00140 
00142   const char *Port() const throw ()                                     //[t1]
00143         { Activate(); return PQport(m_Conn); }
00144 
00146   const char *Options() const throw ()                                  //[t1]
00147         { return m_ConnInfo.c_str(); }
00148 
00150 
00157   int BackendPID() const                                                //[t1]
00158         { return m_Conn ? PQbackendPID(m_Conn) : 0; }
00159 
00161 
00171   void Activate() const { if (!m_Conn) Connect(); }                     //[]
00172 
00174 
00182   void Deactivate() const;                                              //[]
00183 
00184 private:
00185   void Connect() const;
00186   void SetupState() const;
00187   void InternalSetTrace() const;
00188   int Status() const { return PQstatus(m_Conn); }
00189   const char *ErrMsg() const;
00190   void Reset(const char OnReconnect[]=0);
00191 
00192   PGSTD::string m_ConnInfo;     
00193   mutable PGconn *m_Conn;       
00194   Unique<TransactionItf> m_Trans;
00195 
00197   mutable NoticeProcessor m_NoticeProcessor;
00198   void *m_NoticeProcessorArg;   // Client-set argument to notice processor func
00199   FILE *m_Trace;                // File to trace to, if any
00200 
00201   typedef PGSTD::multimap<PGSTD::string, pqxx::Trigger *> TriggerList;
00202   TriggerList m_Triggers;
00203 
00204   friend class TransactionItf;
00205   Result Exec(const char[], int Retries=3, const char OnReconnect[]=0);
00206   void RegisterTransaction(const TransactionItf *);
00207   void UnregisterTransaction(const TransactionItf *) throw ();
00208   void MakeEmpty(Result &, ExecStatusType=PGRES_EMPTY_QUERY);
00209   void BeginCopyRead(const PGSTD::string &Table);
00210   bool ReadCopyLine(PGSTD::string &);
00211   void BeginCopyWrite(const PGSTD::string &Table);
00212   void WriteCopyLine(const PGSTD::string &);
00213   void EndCopy();
00214 
00215   friend class Trigger;
00216   void AddTrigger(Trigger *);
00217   void RemoveTrigger(Trigger *) throw ();
00218 
00219   // Not allowed:
00220   Connection(const Connection &);
00221   Connection &operator=(const Connection &);
00222 };
00223 
00224 
00225 
00236 template<typename TRANSACTOR> 
00237 inline void Connection::Perform(const TRANSACTOR &T,
00238                                 int Attempts)                           //[t4]
00239 {
00240   if (Attempts <= 0) return;
00241 
00242   bool Done = false;
00243 
00244   // Make attempts to perform T
00245   // TODO: Differentiate between db-related exceptions and other exceptions?
00246   do
00247   {
00248     --Attempts;
00249 
00250     // Work on a copy of T2 so we can restore the starting situation if need be
00251     TRANSACTOR T2(T);
00252     try
00253     {
00254       typename TRANSACTOR::argument_type X(*this, T2.Name());
00255       T2(X);
00256       X.Commit();
00257       Done = true;
00258     }
00259     catch (const in_doubt_error &)
00260     {
00261       // Not sure whether transaction went through or not.  The last thing in
00262       // the world that we should do now is retry.
00263       T2.OnDoubt();
00264       throw;
00265     }
00266     catch (const PGSTD::exception &e)
00267     {
00268       // Could be any kind of error.  
00269       T2.OnAbort(e.what());
00270       if (Attempts <= 0) throw;
00271       continue;
00272     }
00273     catch (...)
00274     {
00275       // Don't try to forge ahead if we don't even know what happened
00276       T2.OnAbort("Unknown exception");
00277       throw;
00278     }
00279 
00280     T2.OnCommit();
00281   } while (!Done);
00282 }
00283 
00284 
00285 }
00286 
00287 #endif
00288 

Generated on Tue Feb 11 12:56:39 2003 for libpqxx by doxygen1.3-rc2