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-2009, 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 
00082 class PQXX_LIBEXPORT parameterized_invocation : statement_parameters
00083 {
00084 public:
00085   parameterized_invocation(connection_base &, const PGSTD::string &query);
00086 
00087   parameterized_invocation &operator()() { add_param(); return *this; }
00088   template<typename T> parameterized_invocation &operator()(const T &v)
00089         { add_param(v); return *this; }
00090   template<typename T>
00091         parameterized_invocation &operator()(const T &v, bool nonnull)
00092         { add_param(v, nonnull); return *this; }
00093 
00094   result exec();
00095 
00096 private:
00098   parameterized_invocation &operator=(const parameterized_invocation &);
00099 
00100   connection_base &m_home;
00101   const PGSTD::string m_query;
00102 };
00103 } // namespace internal
00104 
00105 
00106 namespace internal
00107 {
00108 namespace gate
00109 {
00110 class transaction_subtransaction;
00111 class transaction_tablereader;
00112 class transaction_tablewriter;
00113 class transaction_transactionfocus;
00114 } // namespace internal::gate
00115 } // namespace internal
00116 
00117 
00119 
00129 class PQXX_LIBEXPORT PQXX_NOVTABLE transaction_base :
00130   public virtual internal::namedclass
00131 {
00132 public:
00134   typedef isolation_traits<read_committed> isolation_tag;
00135 
00136   virtual ~transaction_base() =0;                                       //[t1]
00137 
00139 
00151   void commit();                                                        //[t1]
00152 
00154 
00157   void abort();                                                         //[t10]
00158 
00163 
00164   PGSTD::string esc(const char str[]) const                             //[t90]
00165                                                      { return m_Conn.esc(str); }
00167   PGSTD::string esc(const char str[], size_t maxlen) const              //[t90]
00168                                              { return m_Conn.esc(str, maxlen); }
00170   PGSTD::string esc(const PGSTD::string &str) const                     //[t90]
00171                                                      { return m_Conn.esc(str); }
00172 
00174 
00185   PGSTD::string esc_raw(const unsigned char str[], size_t len) const    //[t62]
00186                                             { return m_Conn.esc_raw(str, len); }
00188   PGSTD::string esc_raw(const PGSTD::string &) const;                   //[t62]
00189 
00191 
00192   template<typename T> PGSTD::string quote(const T &t) const
00193                                                      { return m_Conn.quote(t); }
00195 
00197 
00212   result exec(const PGSTD::string &Query,
00213               const PGSTD::string &Desc=PGSTD::string());               //[t1]
00214 
00215   result exec(const PGSTD::stringstream &Query,
00216               const PGSTD::string &Desc=PGSTD::string())                //[t9]
00217         { return exec(Query.str(), Desc); }
00218 
00220   /* Use this to build up a parameterized statement invocation, then invoke it
00221    * using @c exec()
00222    *
00223    * Example: @c trans.parameterized("SELECT $1 + 1")(1).exec();
00224    */
00225   internal::parameterized_invocation parameterized(const PGSTD::string &query);
00226 
00231 
00232 
00276   prepare::invocation prepared(const PGSTD::string &statement=PGSTD::string());
00277 
00279 
00284 
00285   void process_notice(const char Msg[]) const                           //[t14]
00286         { m_Conn.process_notice(Msg); }
00288   void process_notice(const PGSTD::string &Msg) const                   //[t14]
00289         { m_Conn.process_notice(Msg); }
00291 
00293   connection_base &conn() const { return m_Conn; }                      //[t4]
00294 
00296 
00304   void set_variable(const PGSTD::string &Var, const PGSTD::string &Val);//[t61]
00305 
00307 
00316   PGSTD::string get_variable(const PGSTD::string &);                    //[t61]
00317 
00318 
00319 protected:
00321 
00327   explicit transaction_base(connection_base &c, bool direct=true);
00328 
00330 
00332   void Begin();
00333 
00335   void End() throw ();
00336 
00338   virtual void do_begin() =0;
00340   virtual result do_exec(const char Query[]) =0;
00342   virtual void do_commit() =0;
00344   virtual void do_abort() =0;
00345 
00346   // For use by implementing class:
00347 
00349 
00357   result DirectExec(const char C[], int Retries=0);
00358 
00360   void reactivation_avoidance_clear() throw ()
00361         {m_reactivation_avoidance.clear();}
00362 
00363 protected:
00365 
00367   internal::reactivation_avoidance_counter m_reactivation_avoidance;
00368 
00369 private:
00370   /* A transaction goes through the following stages in its lifecycle:
00371    * <ul>
00372    * <li> nascent: the transaction hasn't actually begun yet.  If our connection
00373    *    fails at this stage, it may recover and the transaction can attempt to
00374    *    establish itself again.
00375    * <li> active: the transaction has begun.  Since no commit command has been
00376    *    issued, abortion is implicit if the connection fails now.
00377    * <li> aborted: an abort has been issued; the transaction is terminated and
00378    *    its changes to the database rolled back.  It will accept no further
00379    *    commands.
00380    * <li> committed: the transaction has completed successfully, meaning that a
00381    *    commit has been issued.  No further commands are accepted.
00382    * <li> in_doubt: the connection was lost at the exact wrong time, and there
00383    *    is no way of telling whether the transaction was committed or aborted.
00384    * </ul>
00385    *
00386    * Checking and maintaining state machine logic is the responsibility of the
00387    * base class (ie., this one).
00388    */
00389   enum Status
00390   {
00391     st_nascent,
00392     st_active,
00393     st_aborted,
00394     st_committed,
00395     st_in_doubt
00396   };
00397 
00399   void PQXX_PRIVATE activate();
00400 
00401   void PQXX_PRIVATE CheckPendingError();
00402 
00403   template<typename T> bool parm_is_null(T *p) const throw () { return !p; }
00404   template<typename T> bool parm_is_null(T) const throw () { return false; }
00405 
00406   friend class pqxx::internal::gate::transaction_transactionfocus;
00407   void PQXX_PRIVATE RegisterFocus(internal::transactionfocus *);
00408   void PQXX_PRIVATE UnregisterFocus(internal::transactionfocus *) throw ();
00409   void PQXX_PRIVATE RegisterPendingError(const PGSTD::string &) throw ();
00410 
00411   friend class pqxx::internal::gate::transaction_tablereader;
00412   void PQXX_PRIVATE BeginCopyRead(const PGSTD::string &, const PGSTD::string &);
00413   bool ReadCopyLine(PGSTD::string &);
00414 
00415   friend class pqxx::internal::gate::transaction_tablewriter;
00416   void PQXX_PRIVATE BeginCopyWrite(
00417         const PGSTD::string &Table,
00418         const PGSTD::string &Columns);
00419   void WriteCopyLine(const PGSTD::string &);
00420   void EndCopyWrite();
00421 
00422   friend class pqxx::internal::gate::transaction_subtransaction;
00423 
00424   connection_base &m_Conn;
00425 
00426   internal::unique<internal::transactionfocus> m_Focus;
00427   Status m_Status;
00428   bool m_Registered;
00429   PGSTD::map<PGSTD::string, PGSTD::string> m_Vars;
00430   PGSTD::string m_PendingError;
00431 
00433   transaction_base();
00435   transaction_base(const transaction_base &);
00437   transaction_base &operator=(const transaction_base &);
00438 };
00439 
00440 } // namespace pqxx
00441 
00442 
00443 #include "pqxx/compiler-internal-post.hxx"
00444 
00445 #endif
00446 

Generated on Mon Feb 15 18:22:41 2010 for libpqxx by  doxygen 1.5.5