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 00139 result exec(const PGSTD::stringstream &Query, 00140 const PGSTD::string &Desc=PGSTD::string()) //[t9] 00141 { return exec(Query.str(), Desc); } 00142 00144 void process_notice(const char Msg[]) const //[t14] 00145 { m_Conn.process_notice(Msg); } 00147 void process_notice(const PGSTD::string &Msg) const //[t14] 00148 { m_Conn.process_notice(Msg); } 00149 00151 connection_base &conn() const { return m_Conn; } //[t4] 00152 00154 00162 void set_variable(const PGSTD::string &Var, const PGSTD::string &Val);//[t61] 00163 00165 00171 PGSTD::string get_variable(const PGSTD::string &) const; //[t61] 00172 00173 #ifdef PQXX_DEPRECATED_HEADERS 00175 void Commit() { commit(); } 00177 void Abort() { abort(); } 00179 result Exec(const char Q[], const PGSTD::string &D=PGSTD::string()) 00180 { return exec(Q,D); } 00182 result Exec(const PGSTD::string &Q, const PGSTD::string &D=PGSTD::string()) 00183 { return exec(Q,D); } 00185 void ProcessNotice(const char M[]) const { return process_notice(M); } 00187 void ProcessNotice(const PGSTD::string &M) const { return process_notice(M); } 00189 PGSTD::string Name() const { return name(); } 00191 connection_base &Conn() const { return conn(); } 00193 void SetVariable(const PGSTD::string &Var, const PGSTD::string &Val) 00194 { set_variable(Var,Val); } 00195 #endif 00196 00197 protected: 00199 00202 explicit transaction_base(connection_base &, 00203 const PGSTD::string &TName, 00204 const PGSTD::string &CName); 00205 00207 00209 void Begin(); 00210 00212 void End() throw (); 00213 00215 virtual void do_begin() =0; 00217 virtual result do_exec(const char Query[]) =0; 00219 virtual void do_commit() =0; 00221 virtual void do_abort() =0; 00222 00223 // For use by implementing class: 00224 00226 00234 result DirectExec(const char C[], int Retries=0); 00235 00236 private: 00237 /* A transaction goes through the following stages in its lifecycle: 00238 * - nascent: the transaction hasn't actually begun yet. If our connection 00239 * fails at this stage, it may recover and the transaction can attempt to 00240 * establish itself again. 00241 * - active: the transaction has begun. Since no commit command has been 00242 * issued, abortion is implicit if the connection fails now. 00243 * - aborted: an abort has been issued; the transaction is terminated and 00244 * its changes to the database rolled back. It will accept no further 00245 * commands. 00246 * - committed: the transaction has completed successfully, meaning that a 00247 * commit has been issued. No further commands are accepted. 00248 * - in_doubt: the connection was lost at the exact wrong time, and there is 00249 * no way of telling whether the transaction was committed or aborted. 00250 * 00251 * Checking and maintaining state machine logic is the responsibility of the 00252 * base class (ie., this one). 00253 */ 00254 enum Status 00255 { 00256 st_nascent, 00257 st_active, 00258 st_aborted, 00259 st_committed, 00260 st_in_doubt 00261 }; 00262 00263 00264 void CheckPendingError(); 00265 00266 friend class Cursor; 00267 friend class cursor_base; 00268 int GetUniqueCursorNum() { return m_UniqueCursorNum++; } 00269 void MakeEmpty(result &R) const { m_Conn.MakeEmpty(R); } 00270 00271 friend class internal::transactionfocus; 00272 void RegisterFocus(internal::transactionfocus *); 00273 void UnregisterFocus(internal::transactionfocus *) throw (); 00274 void RegisterPendingError(const PGSTD::string &) throw (); 00275 friend class tablereader; 00276 void BeginCopyRead(const PGSTD::string &Table, const PGSTD::string &Columns); 00277 bool ReadCopyLine(PGSTD::string &L) { return m_Conn.ReadCopyLine(L); } 00278 friend class tablewriter; 00279 void BeginCopyWrite(const PGSTD::string &Table, 00280 const PGSTD::string &Columns = PGSTD::string()); 00281 void WriteCopyLine(const PGSTD::string &L) { m_Conn.WriteCopyLine(L); } 00282 void EndCopyWrite() { m_Conn.EndCopyWrite(); } 00283 00284 friend class pipeline; 00285 void start_exec(const PGSTD::string &Q) { m_Conn.start_exec(Q); } 00286 internal::pq::PGresult *get_result() { return m_Conn.get_result(); } 00287 void consume_input() throw () { m_Conn.consume_input(); } 00288 bool is_busy() const throw () { return m_Conn.is_busy(); } 00289 00290 connection_base &m_Conn; 00291 00292 int m_UniqueCursorNum; 00293 internal::unique<internal::transactionfocus> m_Focus; 00294 Status m_Status; 00295 bool m_Registered; 00296 mutable PGSTD::map<PGSTD::string, PGSTD::string> m_Vars; 00297 PGSTD::string m_PendingError; 00298 00300 transaction_base(); 00302 transaction_base(const transaction_base &); 00304 transaction_base &operator=(const transaction_base &); 00305 }; 00306 00307 } // namespace pqxx 00308 00309

Generated on Sat Aug 21 03:39:32 2004 for libpqxx by doxygen 1.3.8