Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | File List | Namespace Members | Class Members | File Members | Related Pages

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-2004, 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 
00021 /* End-user programs need not include this file, unless they define their own
00022  * transaction classes.  This is not something the typical program should want
00023  * to do.
00024  *
00025  * However, reading this file is worthwhile because it defines the public
00026  * interface for the available transaction classes such as transaction and 
00027  * nontransaction.
00028  */
00029 
00030 #include "pqxx/connection_base"
00031 #include "pqxx/isolation"
00032 #include "pqxx/result"
00033 
00034 /* Methods tested in eg. self-test program test001 are marked with "//[t1]"
00035  */
00036 
00037 
00038 namespace pqxx
00039 {
00040 class connection_base;
00041 class transaction_base;
00042 
00043 
00044 namespace internal
00045 {
00046 class PQXX_LIBEXPORT transactionfocus : public namedclass
00047 {
00048 public:
00049   transactionfocus(transaction_base &t, 
00050       const PGSTD::string &Name,
00051       const PGSTD::string &Classname) :
00052     namedclass(Name, Classname),
00053     m_Trans(t),
00054     m_registered(false)
00055   {
00056   }
00057 
00058 protected:
00059   void register_me();
00060   void unregister_me() throw ();
00061   void reg_pending_error(const PGSTD::string &) throw ();
00062   bool registered() const throw () { return m_registered; }
00063 
00064   transaction_base &m_Trans;
00065 
00066 private:
00067   bool m_registered;
00068 
00070   transactionfocus();
00072   transactionfocus(const transactionfocus &);
00074   transactionfocus &operator=(const transactionfocus &);
00075 };
00076 } // namespace internal
00077 
00078 
00079 
00081 
00089 class PQXX_LIBEXPORT transaction_base : public internal::namedclass
00090 {
00091   // TODO: Retry non-serializable transaction w/update only on broken_connection
00092 public:
00094   typedef isolation_traits<read_committed> isolation_tag;
00095 
00096   virtual ~transaction_base() =0;                                       //[t1]
00097 
00099 
00111   void commit();                                                        //[t1]
00112 
00114 
00117   void abort();                                                         //[t10]
00118 
00120 
00124   result exec(const char Query[], 
00125               const PGSTD::string &Desc=PGSTD::string());               //[t1]
00126 
00128 
00135   result exec(const PGSTD::string &Query,
00136               const PGSTD::string &Desc=PGSTD::string())                //[t2]
00137         { return exec(Query.c_str(), Desc); }
00138 
00140   void process_notice(const char Msg[]) const                           //[t14]
00141         { m_Conn.process_notice(Msg); }
00143   void process_notice(const PGSTD::string &Msg) const                   //[t14]
00144         { m_Conn.process_notice(Msg); }
00145 
00147   connection_base &conn() const { return m_Conn; }                      //[t4]
00148 
00150 
00158   void set_variable(const PGSTD::string &Var, const PGSTD::string &Val);//[t61]
00159 
00161 
00167   PGSTD::string get_variable(const PGSTD::string &) const;              //[t61]
00168 
00169 #ifdef PQXX_DEPRECATED_HEADERS
00170 
00171   void Commit() { commit(); }
00173   void Abort() { abort(); }
00175   result Exec(const char Q[], const PGSTD::string &D=PGSTD::string())
00176         { return exec(Q,D); }
00178   result Exec(const PGSTD::string &Q, const PGSTD::string &D=PGSTD::string())
00179         { return exec(Q,D); }
00181   void ProcessNotice(const char M[]) const { return process_notice(M); }
00183   void ProcessNotice(const PGSTD::string &M) const { return process_notice(M); }
00185   PGSTD::string Name() const { return name(); }
00187   connection_base &Conn() const { return conn(); }
00189   void SetVariable(const PGSTD::string &Var, const PGSTD::string &Val)
00190         { set_variable(Var,Val); }
00191 #endif
00192 
00193 protected:
00195 
00198   explicit transaction_base(connection_base &, 
00199                           const PGSTD::string &TName,
00200                           const PGSTD::string &CName);
00201 
00203 
00205   void Begin();
00206 
00208   void End() throw ();
00209 
00211   virtual void do_begin() =0;
00213   virtual result do_exec(const char Query[]) =0;
00215   virtual void do_commit() =0;
00217   virtual void do_abort() =0;
00218 
00219   // For use by implementing class:
00220 
00222 
00230   result DirectExec(const char C[], int Retries=0);
00231  
00232 private:
00233   /* A transaction goes through the following stages in its lifecycle:
00234    *  - nascent: the transaction hasn't actually begun yet.  If our connection 
00235    *    fails at this stage, it may recover and the transaction can attempt to
00236    *    establish itself again.
00237    *  - active: the transaction has begun.  Since no commit command has been 
00238    *    issued, abortion is implicit if the connection fails now.
00239    *  - aborted: an abort has been issued; the transaction is terminated and 
00240    *    its changes to the database rolled back.  It will accept no further 
00241    *    commands.
00242    *  - committed: the transaction has completed successfully, meaning that a 
00243    *    commit has been issued.  No further commands are accepted.
00244    *  - in_doubt: the connection was lost at the exact wrong time, and there is
00245    *    no way of telling whether the transaction was committed or aborted.
00246    *
00247    * Checking and maintaining state machine logic is the responsibility of the 
00248    * base class (ie., this one).
00249    */
00250   enum Status 
00251   { 
00252     st_nascent, 
00253     st_active, 
00254     st_aborted, 
00255     st_committed,
00256     st_in_doubt
00257   };
00258 
00259 
00260   void CheckPendingError();
00261 
00262   friend class Cursor;
00263   int GetUniqueCursorNum() { return m_UniqueCursorNum++; }
00264   void MakeEmpty(result &R) const { m_Conn.MakeEmpty(R); }
00265 
00266   friend class internal::transactionfocus;
00267   void RegisterFocus(internal::transactionfocus *);
00268   void UnregisterFocus(internal::transactionfocus *) throw ();
00269   void RegisterPendingError(const PGSTD::string &) throw ();
00270   friend class tablereader;
00271   void BeginCopyRead(const PGSTD::string &Table, const PGSTD::string &Columns);
00272   bool ReadCopyLine(PGSTD::string &L) { return m_Conn.ReadCopyLine(L); }
00273   friend class tablewriter;
00274   void BeginCopyWrite(const PGSTD::string &Table, 
00275         const PGSTD::string &Columns = PGSTD::string());
00276   bool WriteCopyLine(const PGSTD::string &L, bool async=false) 
00277         { return m_Conn.WriteCopyLine(L, async); }
00278   void EndCopyWrite() throw () { m_Conn.EndCopyWrite(); }
00279 
00280   friend class pipeline;
00281   void start_exec(const PGSTD::string &Q) { m_Conn.start_exec(Q); }
00282   PGresult *get_result() { return m_Conn.get_result(); }
00283 
00284   connection_base &m_Conn;
00285 
00286   int m_UniqueCursorNum;
00287   internal::unique<internal::transactionfocus> m_Focus;
00288   Status m_Status;
00289   bool m_Registered;
00290   mutable PGSTD::map<PGSTD::string, PGSTD::string> m_Vars;
00291   PGSTD::string m_PendingError;
00292 
00294   transaction_base();
00296   transaction_base(const transaction_base &);
00298   transaction_base &operator=(const transaction_base &);
00299 };
00300 
00301 } // namespace pqxx
00302 
00303 

Generated on Mon May 10 13:19:09 2004 for libpqxx by doxygen 1.3.6-20040222