# transaction_base.hxx

    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