transaction_base.hxx

Go to the documentation of this file.
00001 /*-------------------------------------------------------------------------
00002  *
00003  *   FILE
00004  *      pqxx/transaction_base.hxx
00005  *
00006  *   DESCRIPTION
00007  *      common code and definitions for the transaction classes.
00008  *   pqxx::transaction_base defines the interface for any abstract class that
00009  *   represents a database transaction
00010  *   DO NOT INCLUDE THIS FILE DIRECTLY; include pqxx/transaction_base instead.
00011  *
00012  * Copyright (c) 2001-2008, Jeroen T. Vermeulen <jtv@xs4all.nl>
00013  *
00014  * See COPYING for copyright license.  If you did not receive a file called
00015  * COPYING with this source code, please notify the distributor of this mistake,
00016  * or contact the author.
00017  *
00018  *-------------------------------------------------------------------------
00019  */
00020 #ifndef PQXX_H_TRANSACTION_BASE
00021 #define PQXX_H_TRANSACTION_BASE
00022 
00023 #include "pqxx/compiler-public.hxx"
00024 #include "pqxx/compiler-internal-pre.hxx"
00025 
00026 /* End-user programs need not include this file, unless they define their own
00027  * transaction classes.  This is not something the typical program should want
00028  * to do.
00029  *
00030  * However, reading this file is worthwhile because it defines the public
00031  * interface for the available transaction classes such as transaction and
00032  * nontransaction.
00033  */
00034 
00035 #include "pqxx/connection_base"
00036 #include "pqxx/isolation"
00037 #include "pqxx/result"
00038 
00039 /* Methods tested in eg. self-test program test001 are marked with "//[t1]"
00040  */
00041 
00042 namespace pqxx
00043 {
00044 class connection_base;
00045 class transaction_base;
00046 
00047 
00048 namespace internal
00049 {
00050 class sql_cursor;
00051 
00052 class PQXX_LIBEXPORT transactionfocus : public virtual namedclass
00053 {
00054 public:
00055   explicit transactionfocus(transaction_base &t) :
00056     namedclass("transactionfocus"),
00057     m_Trans(t),
00058     m_registered(false)
00059   {
00060   }
00061 
00062 protected:
00063   void register_me();
00064   void unregister_me() throw ();
00065   void reg_pending_error(const PGSTD::string &) throw ();
00066   bool registered() const throw () { return m_registered; }
00067 
00068   transaction_base &m_Trans;
00069 
00070 private:
00071   bool m_registered;
00072 
00074   transactionfocus();
00076   transactionfocus(const transactionfocus &);
00078   transactionfocus &operator=(const transactionfocus &);
00079 };
00080 
00081 } // namespace internal
00082 
00083 
00084 
00086 
00096 class PQXX_LIBEXPORT PQXX_NOVTABLE transaction_base :
00097   public virtual internal::namedclass
00098 {
00099 public:
00101   typedef isolation_traits<read_committed> isolation_tag;
00102 
00103   virtual ~transaction_base() =0;                                       //[t1]
00104 
00106 
00118   void commit();                                                        //[t1]
00119 
00121 
00124   void abort();                                                         //[t10]
00125 
00130 
00131   PGSTD::string esc(const char str[]) const                             //[t90]
00132                                                      { return m_Conn.esc(str); }
00134   PGSTD::string esc(const char str[], size_t maxlen) const              //[t90]
00135                                              { return m_Conn.esc(str, maxlen); }
00137   PGSTD::string esc(const PGSTD::string &str) const                     //[t90]
00138                                                      { return m_Conn.esc(str); }
00139 
00141 
00152   PGSTD::string esc_raw(const unsigned char str[], size_t len) const    //[t62]
00153                                             { return m_Conn.esc_raw(str, len); }
00155   PGSTD::string esc_raw(const PGSTD::string &) const;                   //[t62]
00156 
00158 
00159   template<typename T> PGSTD::string quote(const T &t) const
00160                                                      { return m_Conn.quote(t); }
00162 
00164 
00179   result exec(const PGSTD::string &Query,
00180               const PGSTD::string &Desc=PGSTD::string());               //[t1]
00181 
00182   result exec(const PGSTD::stringstream &Query,
00183               const PGSTD::string &Desc=PGSTD::string())                //[t9]
00184         { return exec(Query.str(), Desc); }
00185 
00190 
00191 
00225   prepare::invocation prepared(const PGSTD::string &statement);
00226 
00228 
00233 
00234   void process_notice(const char Msg[]) const                           //[t14]
00235         { m_Conn.process_notice(Msg); }
00237   void process_notice(const PGSTD::string &Msg) const                   //[t14]
00238         { m_Conn.process_notice(Msg); }
00240 
00242   connection_base &conn() const { return m_Conn; }                      //[t4]
00243 
00245 
00253   void set_variable(const PGSTD::string &Var, const PGSTD::string &Val);//[t61]
00254 
00256 
00265   PGSTD::string get_variable(const PGSTD::string &);                    //[t61]
00266 
00267 
00268 protected:
00270 
00275   explicit transaction_base(connection_base &, bool direct=true);
00276 
00278 
00280   void Begin();
00281 
00283   void End() throw ();
00284 
00286   virtual void do_begin() =0;
00288   virtual result do_exec(const char Query[]) =0;
00290   virtual void do_commit() =0;
00292   virtual void do_abort() =0;
00293 
00294   // For use by implementing class:
00295 
00297 
00305   result DirectExec(const char C[], int Retries=0);
00306 
00308   void reactivation_avoidance_clear() throw ()
00309         {m_reactivation_avoidance.clear();}
00310 
00311 private:
00312   /* A transaction goes through the following stages in its lifecycle:
00313    * <ul>
00314    * <li> nascent: the transaction hasn't actually begun yet.  If our connection
00315    *    fails at this stage, it may recover and the transaction can attempt to
00316    *    establish itself again.
00317    * <li> active: the transaction has begun.  Since no commit command has been
00318    *    issued, abortion is implicit if the connection fails now.
00319    * <li> aborted: an abort has been issued; the transaction is terminated and
00320    *    its changes to the database rolled back.  It will accept no further
00321    *    commands.
00322    * <li> committed: the transaction has completed successfully, meaning that a
00323    *    commit has been issued.  No further commands are accepted.
00324    * <li> in_doubt: the connection was lost at the exact wrong time, and there
00325    *    is no way of telling whether the transaction was committed or aborted.
00326    * </ul>
00327    *
00328    * Checking and maintaining state machine logic is the responsibility of the
00329    * base class (ie., this one).
00330    */
00331   enum Status
00332   {
00333     st_nascent,
00334     st_active,
00335     st_aborted,
00336     st_committed,
00337     st_in_doubt
00338   };
00339 
00341   void PQXX_PRIVATE activate();
00342 
00343   void PQXX_PRIVATE CheckPendingError();
00344 
00345   template<typename T> bool parm_is_null(T *p) const throw () { return !p; }
00346   template<typename T> bool parm_is_null(T) const throw () { return false; }
00347 
00348   friend class pqxx::internal::sql_cursor;
00349   void MakeEmpty(result &R) const { m_Conn.MakeEmpty(R); }
00350 
00351   friend class internal::transactionfocus;
00352   void PQXX_PRIVATE RegisterFocus(internal::transactionfocus *);
00353   void PQXX_PRIVATE UnregisterFocus(internal::transactionfocus *) throw ();
00354   void PQXX_PRIVATE RegisterPendingError(const PGSTD::string &) throw ();
00355   friend class tablereader;
00356   void PQXX_PRIVATE BeginCopyRead(const PGSTD::string &, const PGSTD::string &);
00357   bool ReadCopyLine(PGSTD::string &L) { return m_Conn.ReadCopyLine(L); }
00358   friend class tablewriter;
00359   void PQXX_PRIVATE BeginCopyWrite(const PGSTD::string &Table,
00360         const PGSTD::string &Columns = PGSTD::string());
00361   void WriteCopyLine(const PGSTD::string &L) { m_Conn.WriteCopyLine(L); }
00362   void EndCopyWrite() { m_Conn.EndCopyWrite(); }
00363 
00364   friend class pipeline;
00365   void start_exec(const PGSTD::string &Q) { m_Conn.start_exec(Q); }
00366   internal::pq::PGresult *get_result() { return m_Conn.get_result(); }
00367   bool consume_input() throw () { return m_Conn.consume_input(); }
00368   bool is_busy() const throw () { return m_Conn.is_busy(); }
00369 
00370   friend class prepare::invocation;
00371   result prepared_exec(const PGSTD::string &,
00372         const char *const[],
00373         const int[],
00374         int);
00375 
00376   connection_base &m_Conn;
00377 
00378   internal::unique<internal::transactionfocus> m_Focus;
00379   Status m_Status;
00380   bool m_Registered;
00381   PGSTD::map<PGSTD::string, PGSTD::string> m_Vars;
00382   PGSTD::string m_PendingError;
00383 
00384   friend class subtransaction;
00386 
00388   internal::reactivation_avoidance_counter m_reactivation_avoidance;
00389 
00391   transaction_base();
00393   transaction_base(const transaction_base &);
00395   transaction_base &operator=(const transaction_base &);
00396 };
00397 
00398 } // namespace pqxx
00399 
00400 
00401 #include "pqxx/compiler-internal-post.hxx"
00402 
00403 #endif
00404 

Generated on Sun Nov 2 08:25:40 2008 for libpqxx by  doxygen 1.5.5