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 <memory>
00019 #include <stdexcept>
00020 
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.
00029  */
00030 
00031 /* Methods tested in eg. self-test program test1 are marked with "//[t1]"
00032  */
00033 
00034 
00036 extern "C" void pqxxNoticeCaller(void *, const char *);
00037 
00038 namespace pqxx
00039 {
00040 class in_doubt_error;   // See pqxx/transactionitf.h
00041 class Result;
00042 class TransactionItf;
00043 class Trigger;
00044 
00046 extern "C" { typedef void (*NoticeProcessor)(void *arg, const char *msg); }
00047 
00049 
00053 struct Noticer
00054 {
00055   virtual ~Noticer() {}
00056   virtual void operator()(const char Msg[]) throw () =0;
00057 };
00058 
00059 
00061 template<> inline PGSTD::string Classname(const TransactionItf *) 
00062 { 
00063   return "TransactionItf"; 
00064 }
00065 
00066 
00068 
00069 class broken_connection : public PGSTD::runtime_error
00070 {
00071 public:
00072   broken_connection() : PGSTD::runtime_error("Connection to back end failed") {}
00073   explicit broken_connection(const PGSTD::string &whatarg) : 
00074     PGSTD::runtime_error(whatarg) {}
00075 };
00076 
00077 
00079 
00087 class PQXX_LIBEXPORT Connection
00088 {
00089 public:
00091 
00100   explicit Connection(const PGSTD::string &ConnInfo,
00101                       bool Immediate=true);                             //[t1]
00102 
00104 
00114   explicit Connection(const char ConnInfo[], bool Immediate=true);      //[t2]
00115 
00117   ~Connection();                                                        //[t1]
00118 
00120   void Disconnect() const throw ();                                     //[t2]
00121 
00123   bool is_open() const;                                                 //[t1]
00124 
00126   bool IsOpen() const { return is_open(); }
00127 
00129 
00137   template<typename TRANSACTOR> 
00138   void Perform(const TRANSACTOR &T, int Attempts=3);                    //[t4]
00139 
00141 
00144   NoticeProcessor SetNoticeProcessor(NoticeProcessor, void *arg);       //[t1]
00145 
00147 
00150   std::auto_ptr<Noticer> SetNoticer(std::auto_ptr<Noticer> N);
00151   Noticer *GetNoticer() const throw () { return m_Noticer.get(); }      //[]
00152 
00154   void ProcessNotice(const char[]) throw ();                            //[t1]
00156   void ProcessNotice(const PGSTD::string &msg) throw ()                 //[t1]
00157         { ProcessNotice(msg.c_str()); }
00158 
00160   void Trace(FILE *);                                                   //[t3]
00162   void Untrace() { Trace(0); }
00163 
00164 
00166   void GetNotifs();                                                     //[t4]
00167 
00168   // Miscellaneous query functions (probably not needed very often)
00169  
00171   const char *DbName() const throw ()                                   //[t1]
00172         { Activate(); return PQdb(m_Conn); }
00173 
00175   const char *UserName() const throw ()                                 //[t1]
00176         { Activate(); return  PQuser(m_Conn); }
00177 
00179   const char *HostName() const throw ()                                 //[t1]
00180         { Activate(); return PQhost(m_Conn); }
00181 
00183   const char *Port() const throw ()                                     //[t1]
00184         { Activate(); return PQport(m_Conn); }
00185 
00187   const char *Options() const throw ()                                  //[t1]
00188         { return m_ConnInfo.c_str(); }
00189 
00191 
00198   int BackendPID() const                                                //[t1]
00199         { return m_Conn ? PQbackendPID(m_Conn) : 0; }
00200 
00202 
00212   void Activate() const { if (!m_Conn) Connect(); }                     //[]
00213 
00215 
00223   void Deactivate() const;                                              //[]
00224 
00225 private:
00226   void Connect() const;
00227   void SetupState() const;
00228   void InternalSetTrace() const;
00229   int Status() const { return PQstatus(m_Conn); }
00230   const char *ErrMsg() const;
00231   void Reset(const char OnReconnect[]=0);
00232 
00233   PGSTD::string m_ConnInfo;     
00234   mutable PGconn *m_Conn;       
00235   Unique<TransactionItf> m_Trans;
00236 
00238   mutable NoticeProcessor m_NoticeProcessor;
00239   void *m_NoticeProcessorArg;   // Client-set argument to notice processor func
00240   std::auto_ptr<Noticer> m_Noticer;
00241   FILE *m_Trace;                // File to trace to, if any
00242 
00243   typedef PGSTD::multimap<PGSTD::string, pqxx::Trigger *> TriggerList;
00244   TriggerList m_Triggers;
00245 
00246   friend class TransactionItf;
00247   Result Exec(const char[], int Retries=3, const char OnReconnect[]=0);
00248   void RegisterTransaction(const TransactionItf *);
00249   void UnregisterTransaction(const TransactionItf *) throw ();
00250   void MakeEmpty(Result &, ExecStatusType=PGRES_EMPTY_QUERY);
00251   void BeginCopyRead(const PGSTD::string &Table);
00252   bool ReadCopyLine(PGSTD::string &);
00253   void BeginCopyWrite(const PGSTD::string &Table);
00254   void WriteCopyLine(const PGSTD::string &);
00255   void EndCopy();
00256 
00257   friend class LargeObject;
00258   PGconn *RawConnection() const { return m_Conn; }
00259 
00260   friend class Trigger;
00261   void AddTrigger(Trigger *);
00262   void RemoveTrigger(Trigger *) throw ();
00263 
00264   // Not allowed:
00265   Connection(const Connection &);
00266   Connection &operator=(const Connection &);
00267 };
00268 
00269 
00270 
00281 template<typename TRANSACTOR> 
00282 inline void Connection::Perform(const TRANSACTOR &T,
00283                                 int Attempts)                           //[t4]
00284 {
00285   if (Attempts <= 0) return;
00286 
00287   bool Done = false;
00288 
00289   // Make attempts to perform T
00290   // TODO: Differentiate between db-related exceptions and other exceptions?
00291   do
00292   {
00293     --Attempts;
00294 
00295     // Work on a copy of T2 so we can restore the starting situation if need be
00296     TRANSACTOR T2(T);
00297     try
00298     {
00299       typename TRANSACTOR::argument_type X(*this, T2.Name());
00300       T2(X);
00301       X.Commit();
00302       Done = true;
00303     }
00304     catch (const in_doubt_error &)
00305     {
00306       // Not sure whether transaction went through or not.  The last thing in
00307       // the world that we should do now is retry.
00308       T2.OnDoubt();
00309       throw;
00310     }
00311     catch (const PGSTD::exception &e)
00312     {
00313       // Could be any kind of error.  
00314       T2.OnAbort(e.what());
00315       if (Attempts <= 0) throw;
00316       continue;
00317     }
00318     catch (...)
00319     {
00320       // Don't try to forge ahead if we don't even know what happened
00321       T2.OnAbort("Unknown exception");
00322       throw;
00323     }
00324 
00325     T2.OnCommit();
00326   } while (!Done);
00327 }
00328 
00329 
00330 }
00331 
00332 #endif
00333 

Generated on Tue Mar 11 12:42:48 2003 for libpqxx by doxygen1.3-rc3