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

connection_base.h

Go to the documentation of this file.
00001 /*-------------------------------------------------------------------------
00002  *
00003  *   FILE
00004  *      pqxx/connection_base.h
00005  *
00006  *   DESCRIPTION
00007  *      definition of the pqxx::Connection_base abstract base class.
00008  *   pqxx::Connection_base 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_BASE_H
00015 #define PQXX_CONNECTION_BASE_H
00016 
00017 #include <map>
00018 #include <memory>
00019 
00020 #include "pqxx/except.h"
00021 #include "pqxx/transactor.h"
00022 #include "pqxx/util.h"
00023 
00024 
00025 /* Use of the libpqxx library starts here.
00026  *
00027  * Everything that can be done with a database through libpqxx must go through
00028  * a connection object derived from Connection_base.
00029  */
00030 
00031 /* Methods tested in eg. self-test program test1 are marked with "//[t1]"
00032  */
00033 
00034 namespace pqxx
00035 {
00036 class Result;
00037 class Transaction_base;
00038 class Trigger;
00039 
00041 
00045 struct PQXX_LIBEXPORT Noticer
00046 {
00047   virtual ~Noticer() {}
00048   virtual void operator()(const char Msg[]) throw () =0;
00049 };
00050 
00051 
00053 template<> inline PGSTD::string Classname(const Transaction_base *) 
00054 { 
00055   return "Transaction_base"; 
00056 }
00057 
00058 
00060 
00078 class PQXX_LIBEXPORT Connection_base
00079 {
00080 public:
00082 
00085   explicit Connection_base(const PGSTD::string &ConnInfo);              //[t2]
00086 
00088 
00092   explicit Connection_base(const char ConnInfo[]);                      //[t2]
00093 
00095   virtual ~Connection_base() =0;                                                //[t1]
00096 
00098   void Disconnect() throw ();                                   //[t2]
00099 
00101   bool is_open() const;                                                 //[t1]
00102 
00104 
00112   template<typename TRANSACTOR> 
00113   void Perform(const TRANSACTOR &T, int Attempts=3);                    //[t4]
00114 
00115   // TODO: Define a default Noticer (mainly to help out Windows users)
00117   /** Return value is the previous handler.  Ownership of any previously set 
00118    * Noticer is also passed to the caller, so unless it is stored in another 
00119    * auto_ptr, it will be deleted from the caller's context.  
00120    * This may be important when running under Windows, where a DLL cannot free 
00121    * memory allocated by the main program.
00122    * If a Noticer is set when the Connection_base is destructed, it will also be
00123    * deleted.
00124    * @param N the new message handler; must not be null or equal to the old one
00125    */
00126   PGSTD::auto_ptr<Noticer> SetNoticer(PGSTD::auto_ptr<Noticer> N);      //[t14]
00127   Noticer *GetNoticer() const throw () { return m_Noticer.get(); }      //[t14]
00128 
00130   void ProcessNotice(const char[]) throw ();                            //[t14]
00132   void ProcessNotice(const PGSTD::string &msg) throw ()                 //[t14]
00133         { ProcessNotice(msg.c_str()); }
00134 
00136   void Trace(FILE *);                                                   //[t3]
00137 
00139   void GetNotifs();                                                     //[t4]
00140 
00141   // Miscellaneous query functions (probably not needed very often)
00142  
00144   const char *DbName()                                                  //[t1]
00145         { Activate(); return PQdb(m_Conn); }
00146 
00148   const char *UserName()                                                //[t1]
00149         { Activate(); return  PQuser(m_Conn); }
00150 
00152   const char *HostName()                                                //[t1]
00153         { Activate(); return PQhost(m_Conn); }
00154 
00156   const char *Port()                                                    //[t1]
00157         { Activate(); return PQport(m_Conn); }
00158 
00160   const char *Options() const throw ()                                  //[t1]
00161         { return m_ConnInfo.c_str(); }
00162 
00164 
00171   int BackendPID() const                                                //[t1]
00172         { return m_Conn ? PQbackendPID(m_Conn) : 0; }
00173 
00175 
00185   void Activate() { if (!m_Conn) Connect(); }                           //[t12]
00186 
00188 
00196   void Deactivate();                                                    //[t12]
00197 
00199 
00205   void SetClientEncoding(const PGSTD::string &Encoding)                 //[t7]
00206         { SetVariable("CLIENT_ENCODING", Encoding); }
00207 
00209 
00220   void SetVariable(const PGSTD::string &Var, const PGSTD::string &Value);//[]
00221 
00222 protected:
00224   void Connect();
00225 
00226 private:
00227   void SetupState();
00228   void InternalSetTrace();
00229   int Status() const { return PQstatus(m_Conn); }
00230   const char *ErrMsg() const;
00231   void Reset(const char OnReconnect[]=0);
00232   void close() throw ();
00233   void RestoreVars();
00234 
00235   PGSTD::string m_ConnInfo;     
00236   PGconn *m_Conn;       
00237   Unique<Transaction_base> m_Trans;
00238 
00239   PGSTD::auto_ptr<Noticer> m_Noticer;   
00240   FILE *m_Trace;                
00241 
00242   typedef PGSTD::multimap<PGSTD::string, pqxx::Trigger *> TriggerList;
00243   TriggerList m_Triggers;       
00244 
00245   PGSTD::map<PGSTD::string, PGSTD::string> m_Vars; 
00246 
00247   friend class Transaction_base;
00248   Result Exec(const char[], int Retries=3, const char OnReconnect[]=0);
00249   void RegisterTransaction(Transaction_base *);
00250   void UnregisterTransaction(Transaction_base *) throw ();
00251   void MakeEmpty(Result &, ExecStatusType=PGRES_EMPTY_QUERY);
00252   void BeginCopyRead(const PGSTD::string &Table);
00253   bool ReadCopyLine(PGSTD::string &);
00254   void BeginCopyWrite(const PGSTD::string &Table);
00255   void WriteCopyLine(const PGSTD::string &);
00256   void EndCopy();
00257   void RawSetVar(const PGSTD::string &Var, const PGSTD::string &Value);
00258   void AddVariables(const PGSTD::map<PGSTD::string, PGSTD::string> &);
00259 
00260   friend class LargeObject;
00261   PGconn *RawConnection() const { return m_Conn; }
00262 
00263   friend class Trigger;
00264   void AddTrigger(Trigger *);
00265   void RemoveTrigger(Trigger *) throw ();
00266 
00267   // Not allowed:
00268   Connection_base(const Connection_base &);
00269   Connection_base &operator=(const Connection_base &);
00270 };
00271 
00272 
00273 }
00274 
00275 
00286 template<typename TRANSACTOR> 
00287 inline void pqxx::Connection_base::Perform(const TRANSACTOR &T,
00288                                          int Attempts)
00289 {
00290   if (Attempts <= 0) return;
00291 
00292   bool Done = false;
00293 
00294   // Make attempts to perform T
00295   // TODO: Differentiate between db-related exceptions and other exceptions?
00296   do
00297   {
00298     --Attempts;
00299 
00300     // Work on a copy of T2 so we can restore the starting situation if need be
00301     TRANSACTOR T2(T);
00302     try
00303     {
00304       typename TRANSACTOR::argument_type X(*this, T2.Name());
00305       T2(X);
00306       X.Commit();
00307       Done = true;
00308     }
00309     catch (const in_doubt_error &)
00310     {
00311       // Not sure whether transaction went through or not.  The last thing in
00312       // the world that we should do now is retry.
00313       T2.OnDoubt();
00314       throw;
00315     }
00316     catch (const PGSTD::exception &e)
00317     {
00318       // Could be any kind of error.  
00319       T2.OnAbort(e.what());
00320       if (Attempts <= 0) throw;
00321       continue;
00322     }
00323     catch (...)
00324     {
00325       // Don't try to forge ahead if we don't even know what happened
00326       T2.OnAbort("Unknown exception");
00327       throw;
00328     }
00329 
00330     T2.OnCommit();
00331   } while (!Done);
00332 }
00333 
00334 
00335 // Put this here so on Windows, any Noticer will be deleted in caller's context
00336 inline pqxx::Connection_base::~Connection_base()
00337 {
00338   close();
00339 }
00340 
00341 #endif
00342 

Generated on Sat May 24 02:03:11 2003 for libpqxx by doxygen1.3-rc3