Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Namespace Members | Class Members | File Members | Related Pages

connection_base.hxx

Go to the documentation of this file.
00001 /*-------------------------------------------------------------------------
00002  *
00003  *   FILE
00004  *      pqxx/connection_base.hxx
00005  *
00006  *   DESCRIPTION
00007  *      definition of the pqxx::connection_base abstract base class.
00008  *   pqxx::connection_base encapsulates a frontend to backend connection
00009  *   DO NOT INCLUDE THIS FILE DIRECTLY; include pqxx/connection_base instead.
00010  *
00011  * Copyright (c) 2001-2005, Jeroen T. Vermeulen <jtv@xs4all.nl>
00012  *
00013  * See COPYING for copyright license.  If you did not receive a file called
00014  * COPYING with this source code, please notify the distributor of this mistake,
00015  * or contact the author.
00016  *
00017  *-------------------------------------------------------------------------
00018  */
00019 #include "pqxx/libcompiler.h"
00020 
00021 #include <map>
00022 #include <memory>
00023 
00024 #ifdef _WIN32
00025 #include <winsock2.h>   // for fd_set
00026 #endif  // _WIN32
00027 
00028 #include "pqxx/except"
00029 #include "pqxx/util"
00030 
00031 
00032 /* Use of the libpqxx library starts here.
00033  *
00034  * Everything that can be done with a database through libpqxx must go through
00035  * a connection object derived from connection_base.
00036  */
00037 
00038 /* Methods tested in eg. self-test program test1 are marked with "//[t1]"
00039  */
00040 
00041 namespace pqxx
00042 {
00043 class result;
00044 class transaction_base;
00045 class trigger;
00046 
00047 
00049 
00053 struct PQXX_LIBEXPORT noticer : PGSTD::unary_function<const char[], void>
00054 {
00055   virtual ~noticer() throw () {}
00056   virtual void operator()(const char Msg[]) throw () =0;
00057 };
00058 
00059 
00061 struct PQXX_LIBEXPORT nonnoticer : noticer
00062 {
00063   virtual void operator()(const char []) throw () {}
00064 };
00065 
00066 
00068 
00088 class PQXX_LIBEXPORT connection_base
00089 {
00090 public:
00092 
00102   explicit connection_base(const PGSTD::string &ConnInfo);              //[t2]
00103 
00105 
00109   explicit connection_base(const char ConnInfo[]);                      //[t2]
00110 
00112   virtual ~connection_base() =0;                                        //[t1]
00113 
00115   void disconnect() throw ();                                           //[t2]
00116 
00118 
00122   bool is_open() const throw ();                                        //[t1]
00123 
00125 
00133   template<typename TRANSACTOR>
00134   void perform(const TRANSACTOR &T, int Attempts);                      //[t4]
00135 
00137 
00144   template<typename TRANSACTOR>
00145   void perform(const TRANSACTOR &T) { perform(T, 3); }
00146 
00147   // TODO: Define a default noticer (mainly to help out Windows users)
00149 
00161   PGSTD::auto_ptr<noticer> set_noticer(PGSTD::auto_ptr<noticer> N)
00162     throw ();                                                           //[t14]
00163   noticer *get_noticer() const throw () { return m_Noticer.get(); }     //[t14]
00164 
00166   void process_notice(const char[]) throw ();                           //[t14]
00168   void process_notice(const PGSTD::string &) throw ();                  //[t14]
00169 
00171   void trace(FILE *) throw ();                                          //[t3]
00172 
00174 
00178   int get_notifs();                                                     //[t4]
00179 
00180   // Miscellaneous query functions (probably not needed very often)
00181 
00183   const char *dbname();                                                 //[t1]
00184 
00186   const char *username();                                               //[t1]
00187 
00189   const char *hostname();                                               //[t1]
00190 
00192   const char *port();                                                   //[t1]
00193 
00195   const char *options() const throw ()                                  //[t1]
00196         { return m_ConnInfo.c_str(); }
00197 
00198 
00200 
00209   int backendpid() const throw ();                                      //[t1]
00210 
00212 
00222   void activate();                                                      //[t12]
00223 
00225 
00233   void deactivate();                                                    //[t12]
00234 
00236 
00242   void set_client_encoding(const PGSTD::string &Encoding)               //[t7]
00243         { set_variable("CLIENT_ENCODING", Encoding); }
00244 
00246 
00262   void set_variable(const PGSTD::string &Var,
00263                     const PGSTD::string &Value);                        //[t60]
00264 
00266 
00273   PGSTD::string get_variable(const PGSTD::string &);                    //[t60]
00274 
00276 
00279   int await_notification();                                             //[t78]
00280 
00282 
00286   int await_notification(long seconds, long microseconds);              //[t79]
00287 
00289 
00307   void prepare(const PGSTD::string &name, const PGSTD::string &def)     //[t85]
00308         { pq_prepare(name, def, ""); }
00309 
00311 
00329   template<typename ITER>
00330     void prepare(const PGSTD::string &name,
00331         const PGSTD::string &def,
00332         ITER beginparms,
00333         ITER endparms)                                                  //[t85]
00334   {
00335     pq_prepare(name, def, 
00336         (beginparms==endparms) ? 
00337                 "" : ("("+separated_list(",",beginparms,endparms)+")"));
00338   }
00339 
00341 
00359   template<typename CNTNR>
00360     void prepare(const PGSTD::string &name,
00361         const PGSTD::string &def,
00362         const CNTNR &params)                                            //[t85]
00363         { prepare(name, def, params.begin(), params.end()); }
00364 
00366   void unprepare(const PGSTD::string &name);                            //[t85]
00367 
00368 #ifdef PQXX_DEPRECATED_HEADERS
00369 
00370   void Disconnect() throw () { disconnect(); }
00372   template<typename TRANSACTOR> void Perform(const TRANSACTOR &T, int A=3)
00373         { return perform(T,A); }
00375   PGSTD::auto_ptr<noticer> SetNoticer(PGSTD::auto_ptr<noticer> N)
00376         { return set_noticer(N); }
00378   noticer *GetNoticer() const throw ()
00379         { return get_noticer(); }
00381   void ProcessNotice(const char msg[]) throw () { return process_notice(msg); }
00383   void ProcessNotice(const PGSTD::string &msg) throw ()
00384         { return process_notice(msg); }
00386   void Trace(FILE *F) { trace(F); }
00388   void GetNotifs() { get_notifs(); }
00390   const char *DbName() { return dbname(); }
00392   const char *UserName() { return username(); }
00394   const char *HostName() { return hostname(); }
00396   const char *Port() { return port(); }
00398   const char *Options() const throw () { return options(); }
00400   int BackendPID() const { return backendpid(); }
00402   void Activate() { activate(); }
00404   void Deactivate() { deactivate(); }
00406   void SetClientEncoding(const PGSTD::string &E) { set_client_encoding(E); }
00408   void SetVariable(const PGSTD::string &Var, const PGSTD::string &Val)
00409         { set_variable(Var, Val); }
00410 #endif
00411 
00412 
00413 protected:
00415 
00416   virtual void startconnect() =0;
00417 
00419 
00420   virtual void completeconnect() =0;
00421 
00423 
00424   virtual void dropconnect() throw () {}
00425 
00427   internal::pq::PGconn *get_conn() const throw () { return m_Conn; }
00428 
00430   void set_conn(internal::pq::PGconn *C) throw () { m_Conn = C; }
00431 
00432   void close() throw ();
00433   void wait_read() const;
00434   void wait_read(long seconds, long microseconds) const;
00435   void wait_write() const;
00436 
00437 private:
00438   void SetupState();
00439 
00440   void InternalSetTrace() throw ();
00441   int Status() const throw ();
00442   const char *ErrMsg() const throw ();
00443   void Reset();
00444   void RestoreVars();
00445   int set_fdmask() const;
00446   void clear_fdmask() throw ();
00447   PGSTD::string RawGetVar(const PGSTD::string &);
00448   void process_notice_raw(const char msg[]) throw ();
00449 
00450 
00452   PGSTD::string m_ConnInfo;
00453 
00455   internal::pq::PGconn *m_Conn;
00457   internal::unique<transaction_base> m_Trans;
00458 
00460   PGSTD::auto_ptr<noticer> m_Noticer;
00462   FILE *m_Trace;
00463 
00464   typedef PGSTD::multimap<PGSTD::string, pqxx::trigger *> TriggerList;
00466   TriggerList m_Triggers;
00467 
00469   PGSTD::map<PGSTD::string, PGSTD::string> m_Vars;
00470 
00472   struct prepared_def
00473   {
00475     PGSTD::string definition;
00477     PGSTD::string parameters;
00479     bool registered;
00480 
00481     prepared_def() : definition(), parameters(), registered(false) {}
00482     prepared_def(const PGSTD::string &def, const PGSTD::string &params) :
00483       definition(def), parameters(params), registered(false) {}
00484   };
00485 
00486   typedef PGSTD::map<PGSTD::string, prepared_def> PSMap;
00487 
00489   PSMap m_prepared;
00490 
00491   mutable fd_set m_fdmask;
00492 
00493   friend class transaction_base;
00494   result Exec(const char[], int Retries);
00495   void pq_prepare(const PGSTD::string &name,
00496       const PGSTD::string &def,
00497       const PGSTD::string &params);
00498   result pq_exec_prepared(const PGSTD::string &, int, const char *const *);
00499   void RegisterTransaction(transaction_base *);
00500   void UnregisterTransaction(transaction_base *) throw ();
00501   void MakeEmpty(result &);
00502   bool ReadCopyLine(PGSTD::string &);
00503   void WriteCopyLine(const PGSTD::string &);
00504   void EndCopyWrite();
00505   void start_exec(const PGSTD::string &);
00506   internal::pq::PGresult *get_result();
00507 
00508   void RawSetVar(const PGSTD::string &Var, const PGSTD::string &Value);
00509   void AddVariables(const PGSTD::map<PGSTD::string, PGSTD::string> &);
00510 
00511   friend class largeobject;
00512   internal::pq::PGconn *RawConnection() const { return m_Conn; }
00513 
00514   friend class trigger;
00515   void AddTrigger(trigger *);
00516   void RemoveTrigger(trigger *) throw ();
00517 
00518   friend class pipeline;
00519   void consume_input() throw ();
00520   bool is_busy() const throw ();
00521 
00522   // Not allowed:
00523   connection_base(const connection_base &);
00524   connection_base &operator=(const connection_base &);
00525 };
00526 
00527 
00528 // Put this here so on Windows, any noticers can be deleted in caller's context
00529 inline connection_base::~connection_base()
00530 {
00531   // Visual C++ seems to have a problem with output during destructors!
00532 #ifdef PQXX_QUIET_DESTRUCTORS
00533   set_noticer(PGSTD::auto_ptr<noticer>(new nonnoticer()));
00534 #endif
00535 }
00536 
00537 
00538 namespace internal
00539 {
00540 
00542 
00548 class PQXX_LIBEXPORT scoped_noticer
00549 {
00550 public:
00552 
00556   scoped_noticer(connection_base &c, PGSTD::auto_ptr<noticer> t) throw () :
00557     m_c(c), m_org(c.set_noticer(t)) { }
00558 
00559   ~scoped_noticer() { m_c.set_noticer(m_org); }
00560 
00561 private:
00562   connection_base &m_c;
00563   PGSTD::auto_ptr<noticer> m_org;
00564 
00566   scoped_noticer();
00567   scoped_noticer(const scoped_noticer &);
00568   scoped_noticer operator=(const scoped_noticer &);
00569 };
00570 
00571 
00573 class PQXX_LIBEXPORT disable_noticer : scoped_noticer
00574 {
00575 public:
00576   explicit disable_noticer(connection_base &c) :
00577     scoped_noticer(c, PGSTD::auto_ptr<noticer>(new nonnoticer)) {}
00578 };
00579 
00580 
00581 } // namespace pqxx::internal
00582 
00583 
00584 } // namespace pqxx
00585 

Generated on Fri May 6 17:10:10 2005 for libpqxx by  doxygen 1.4.2