# 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    //[t62]
    00145         { return m_Conn.esc_raw(str, len); }
    00147   PGSTD::string esc_raw(const PGSTD::string &) const;                   //[t62]
    00149
    00151
    00156   result exec(const PGSTD::string &Query,
    00157               const PGSTD::string &Desc=PGSTD::string());               //[t1]
    00158
    00159   result exec(const PGSTD::stringstream &Query,
    00160               const PGSTD::string &Desc=PGSTD::string())                //[t9]
    00161         { return exec(Query.str(), Desc); }
    00162
    00167
    00168
    00202   prepare::invocation prepared(const PGSTD::string &statement);         //[t85]
    00203
    00205
    00210
    00211   void process_notice(const char Msg[]) const                           //[t14]
    00212         { m_Conn.process_notice(Msg); }
    00214   void process_notice(const PGSTD::string &Msg) const                   //[t14]
    00215         { m_Conn.process_notice(Msg); }
    00217
    00219   connection_base &conn() const { return m_Conn; }                      //[t4]
    00220
    00222
    00230   void set_variable(const PGSTD::string &Var, const PGSTD::string &Val);//[t61]
    00231
    00233
    00242   PGSTD::string get_variable(const PGSTD::string &);                    //[t61]
    00243
    00244
    00245 protected:
    00247
    00252   explicit transaction_base(connection_base &, bool direct=true);
    00253
    00255
    00257   void Begin();
    00258
    00260   void End() throw ();
    00261
    00263   virtual void do_begin() =0;
    00265   virtual result do_exec(const char Query[]) =0;
    00267   virtual void do_commit() =0;
    00269   virtual void do_abort() =0;
    00270
    00271   // For use by implementing class:
    00272
    00274
    00282   result DirectExec(const char C[], int Retries=0);
    00283
    00285   void reactivation_avoidance_clear() throw ()
    00286         {m_reactivation_avoidance.clear();}
    00287
    00288 private:
    00289   /* A transaction goes through the following stages in its lifecycle:
    00290    * <ul>
    00291    * <li> nascent: the transaction hasn't actually begun yet.  If our connection
    00292    *    fails at this stage, it may recover and the transaction can attempt to
    00293    *    establish itself again.
    00294    * <li> active: the transaction has begun.  Since no commit command has been
    00295    *    issued, abortion is implicit if the connection fails now.
    00296    * <li> aborted: an abort has been issued; the transaction is terminated and
    00297    *    its changes to the database rolled back.  It will accept no further
    00298    *    commands.
    00299    * <li> committed: the transaction has completed successfully, meaning that a
    00300    *    commit has been issued.  No further commands are accepted.
    00301    * <li> in_doubt: the connection was lost at the exact wrong time, and there
    00302    *    is no way of telling whether the transaction was committed or aborted.
    00303    * </ul>
    00304    *
    00305    * Checking and maintaining state machine logic is the responsibility of the
    00306    * base class (ie., this one).
    00307    */
    00308   enum Status
    00309   {
    00310     st_nascent,
    00311     st_active,
    00312     st_aborted,
    00313     st_committed,
    00314     st_in_doubt
    00315   };
    00316
    00317
    00318   void PQXX_PRIVATE CheckPendingError();
    00319
    00320   template<typename T> bool parm_is_null(T *p) const throw () { return !p; }
    00321   template<typename T> bool parm_is_null(T) const throw () { return false; }
    00322
    00323   friend class Cursor;
    00324   friend class cursor_base;
    00325   void MakeEmpty(result &R) const { m_Conn.MakeEmpty(R); }
    00326
    00327   friend class internal::transactionfocus;
    00328   void PQXX_PRIVATE RegisterFocus(internal::transactionfocus *);
    00329   void PQXX_PRIVATE UnregisterFocus(internal::transactionfocus *) throw ();
    00330   void PQXX_PRIVATE RegisterPendingError(const PGSTD::string &) throw ();
    00331   friend class tablereader;
    00332   void PQXX_PRIVATE BeginCopyRead(const PGSTD::string &, const PGSTD::string &);
    00333   bool ReadCopyLine(PGSTD::string &L) { return m_Conn.ReadCopyLine(L); }
    00334   friend class tablewriter;
    00335   void PQXX_PRIVATE BeginCopyWrite(const PGSTD::string &Table,
    00336         const PGSTD::string &Columns = PGSTD::string());
    00337   void WriteCopyLine(const PGSTD::string &L) { m_Conn.WriteCopyLine(L); }
    00338   void EndCopyWrite() { m_Conn.EndCopyWrite(); }
    00339
    00340   friend class pipeline;
    00341   void start_exec(const PGSTD::string &Q) { m_Conn.start_exec(Q); }
    00342   internal::pq::PGresult *get_result() { return m_Conn.get_result(); }
    00343   void consume_input() throw () { m_Conn.consume_input(); }
    00344   bool is_busy() const throw () { return m_Conn.is_busy(); }
    00345
    00346   friend class prepare::invocation;
    00347   result prepared_exec(const PGSTD::string &,
    00348         const char *const[],
    00349         const int[],
    00350         int);
    00351
    00352   connection_base &m_Conn;
    00353
    00354   internal::unique<internal::transactionfocus> m_Focus;
    00355   Status m_Status;
    00356   bool m_Registered;
    00357   PGSTD::map<PGSTD::string, PGSTD::string> m_Vars;
    00358   PGSTD::string m_PendingError;
    00359
    00360   friend class subtransaction;
    00362
    00364   internal::reactivation_avoidance_counter m_reactivation_avoidance;
    00365
    00367   transaction_base();
    00369   transaction_base(const transaction_base &);
    00371   transaction_base &operator=(const transaction_base &);
    00372 };
    00373
    00374 } // namespace pqxx
    00375
    00376
    00377 #include "pqxx/compiler-internal-post.hxx"