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-2006, 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 #include "pqxx/compiler-public.hxx"
00021 #include "pqxx/compiler-internal-pre.hxx"
00022 
00023 /* End-user programs need not include this file, unless they define their own
00024  * transaction classes.  This is not something the typical program should want
00025  * to do.
00026  *
00027  * However, reading this file is worthwhile because it defines the public
00028  * interface for the available transaction classes such as transaction and
00029  * nontransaction.
00030  */
00031 
00032 #include "pqxx/connection_base"
00033 #include "pqxx/isolation"
00034 #include "pqxx/result"
00035 
00036 /* Methods tested in eg. self-test program test001 are marked with "//[t1]"
00037  */
00038 
00039 namespace pqxx
00040 {
00041 class connection_base;
00042 class transaction_base;
00043 
00044 
00045 namespace internal
00046 {
00047 class PQXX_LIBEXPORT transactionfocus : public virtual namedclass
00048 {
00049 public:
00050   explicit transactionfocus(transaction_base &t) :
00051     namedclass("transactionfocus"),
00052     m_Trans(t),
00053     m_registered(false)
00054   {
00055   }
00056 
00057 protected:
00058   void register_me();
00059   void unregister_me() throw ();
00060   void reg_pending_error(const PGSTD::string &) throw ();
00061   bool registered() const throw () { return m_registered; }
00062 
00063   transaction_base &m_Trans;
00064 
00065 private:
00066   bool m_registered;
00067 
00069   transactionfocus();
00071   transactionfocus(const transactionfocus &);
00073   transactionfocus &operator=(const transactionfocus &);
00074 };
00075 
00076 } // namespace internal
00077 
00078 
00079 
00081 
00091 class PQXX_LIBEXPORT transaction_base : public virtual internal::namedclass
00092 {
00093 public:
00095   typedef isolation_traits<read_committed> isolation_tag;
00096 
00097   virtual ~transaction_base() =0;                                       //[t1]
00098 
00100 
00112   void commit();                                                        //[t1]
00113 
00115 
00118   void abort();                                                         //[t10]
00119 
00124 
00125   PGSTD::string esc(const char str[]) const;                            //[t90]
00127   PGSTD::string esc(const char str[], size_t maxlen) const              //[t90]
00128         { return m_Conn.esc(str,maxlen); }
00130   PGSTD::string esc(const PGSTD::string &) const;                       //[t90]
00131 
00133 
00144   PGSTD::string esc_raw(const unsigned char str[], size_t len) const    //[]
00145         { return m_Conn.esc_raw(str, len); }
00147   PGSTD::string esc_raw(const PGSTD::string &) const;                   //[t62]
00149 
00151 
00156   result exec(const char Query[],
00157               const PGSTD::string &Desc=PGSTD::string());               //[t1]
00158 
00160 
00168   result exec(const PGSTD::string &Query,
00169               const PGSTD::string &Desc=PGSTD::string())                //[t2]
00170         { return exec(Query.c_str(), Desc); }
00171 
00172   result exec(const PGSTD::stringstream &Query,
00173               const PGSTD::string &Desc=PGSTD::string())                //[t9]
00174         { return exec(Query.str(), Desc); }
00175 
00180 
00181 
00215   prepare::invocation prepared(const PGSTD::string &statement);         //[t85]
00216 
00218 
00223 
00224   void process_notice(const char Msg[]) const                           //[t14]
00225         { m_Conn.process_notice(Msg); }
00227   void process_notice(const PGSTD::string &Msg) const                   //[t14]
00228         { m_Conn.process_notice(Msg); }
00230 
00232   connection_base &conn() const { return m_Conn; }                      //[t4]
00233 
00235 
00243   void set_variable(const PGSTD::string &Var, const PGSTD::string &Val);//[t61]
00244 
00246 
00255   PGSTD::string get_variable(const PGSTD::string &);                    //[t61]
00256 
00257 #ifdef PQXX_DEPRECATED_HEADERS
00258 
00262 
00263   void Commit() PQXX_DEPRECATED { commit(); }
00265   void Abort() PQXX_DEPRECATED { abort(); }
00267   result Exec(const char Q[], const PGSTD::string &D=PGSTD::string())
00268         PQXX_DEPRECATED { return exec(Q,D); }
00270   result Exec(const PGSTD::string &Q, const PGSTD::string &D=PGSTD::string())
00271         PQXX_DEPRECATED { return exec(Q,D); }
00273   void ProcessNotice(const char M[]) const PQXX_DEPRECATED
00274         { return process_notice(M); }
00276   void ProcessNotice(const PGSTD::string &M) const PQXX_DEPRECATED
00277         { return process_notice(M); }
00279   PGSTD::string Name() const PQXX_DEPRECATED { return name(); }
00281   connection_base &Conn() const PQXX_DEPRECATED { return conn(); }
00283   void SetVariable(const PGSTD::string &Var, const PGSTD::string &Val)
00284         PQXX_DEPRECATED { set_variable(Var,Val); }
00286 #endif
00287 
00288 protected:
00290 
00295   explicit transaction_base(connection_base &, bool direct=true);
00296 
00298 
00300   void Begin();
00301 
00303   void End() throw ();
00304 
00306   virtual void do_begin() =0;
00308   virtual result do_exec(const char Query[]) =0;
00310   virtual void do_commit() =0;
00312   virtual void do_abort() =0;
00313 
00314   // For use by implementing class:
00315 
00317 
00325   result DirectExec(const char C[], int Retries=0);
00326 
00328   void reactivation_avoidance_clear() throw ()
00329         {m_reactivation_avoidance.clear();}
00330 
00331 private:
00332   /* A transaction goes through the following stages in its lifecycle:
00333    * <ul>
00334    * <li> nascent: the transaction hasn't actually begun yet.  If our connection
00335    *    fails at this stage, it may recover and the transaction can attempt to
00336    *    establish itself again.
00337    * <li> active: the transaction has begun.  Since no commit command has been
00338    *    issued, abortion is implicit if the connection fails now.
00339    * <li> aborted: an abort has been issued; the transaction is terminated and
00340    *    its changes to the database rolled back.  It will accept no further
00341    *    commands.
00342    * <li> committed: the transaction has completed successfully, meaning that a
00343    *    commit has been issued.  No further commands are accepted.
00344    * <li> in_doubt: the connection was lost at the exact wrong time, and there
00345    *    is no way of telling whether the transaction was committed or aborted.
00346    * </ul>
00347    *
00348    * Checking and maintaining state machine logic is the responsibility of the
00349    * base class (ie., this one).
00350    */
00351   enum Status
00352   {
00353     st_nascent,
00354     st_active,
00355     st_aborted,
00356     st_committed,
00357     st_in_doubt
00358   };
00359 
00360 
00361   void PQXX_PRIVATE CheckPendingError();
00362 
00363   template<typename T> bool parm_is_null(T *p) const throw () { return !p; }
00364   template<typename T> bool parm_is_null(T) const throw () { return false; }
00365 
00366   friend class Cursor;
00367   friend class cursor_base;
00368   void MakeEmpty(result &R) const { m_Conn.MakeEmpty(R); }
00369 
00370   friend class internal::transactionfocus;
00371   void PQXX_PRIVATE RegisterFocus(internal::transactionfocus *);
00372   void PQXX_PRIVATE UnregisterFocus(internal::transactionfocus *) throw ();
00373   void PQXX_PRIVATE RegisterPendingError(const PGSTD::string &) throw ();
00374   friend class tablereader;
00375   void PQXX_PRIVATE BeginCopyRead(const PGSTD::string &, const PGSTD::string &);
00376   bool ReadCopyLine(PGSTD::string &L) { return m_Conn.ReadCopyLine(L); }
00377   friend class tablewriter;
00378   void PQXX_PRIVATE BeginCopyWrite(const PGSTD::string &Table,
00379         const PGSTD::string &Columns = PGSTD::string());
00380   void WriteCopyLine(const PGSTD::string &L) { m_Conn.WriteCopyLine(L); }
00381   void EndCopyWrite() { m_Conn.EndCopyWrite(); }
00382 
00383   friend class pipeline;
00384   void start_exec(const PGSTD::string &Q) { m_Conn.start_exec(Q); }
00385   internal::pq::PGresult *get_result() { return m_Conn.get_result(); }
00386   void consume_input() throw () { m_Conn.consume_input(); }
00387   bool is_busy() const throw () { return m_Conn.is_busy(); }
00388 
00389   friend class prepare::invocation;
00390   result prepared_exec(const PGSTD::string &, const char *const[], int);
00391 
00392   connection_base &m_Conn;
00393 
00394   internal::unique<internal::transactionfocus> m_Focus;
00395   Status m_Status;
00396   bool m_Registered;
00397   PGSTD::map<PGSTD::string, PGSTD::string> m_Vars;
00398   PGSTD::string m_PendingError;
00399 
00400   friend class subtransaction;
00402 
00404   internal::reactivation_avoidance_counter m_reactivation_avoidance;
00405 
00407   transaction_base();
00409   transaction_base(const transaction_base &);
00411   transaction_base &operator=(const transaction_base &);
00412 };
00413 
00414 } // namespace pqxx
00415 
00416 
00417 #include "pqxx/compiler-internal-post.hxx"

Generated on Sun Jun 18 14:51:00 2006 for libpqxx by  doxygen 1.4.6