00001 
00002 
00003 
00004 
00005 
00006 
00007 
00008 
00009 
00010 
00011 
00012 
00013 
00014 
00015 
00016 
00017 
00018 
00019 
00020 
00021 
00022 
00023 
00024 
00025 
00026 
00027 
00028 
00029 
00030 #include "pqxx/connection_base"
00031 #include "pqxx/isolation"
00032 #include "pqxx/result"
00033 
00034 
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 } 
00077 
00078 
00079 
00081 
00089 class PQXX_LIBEXPORT transaction_base : public internal::namedclass
00090 {
00091   
00092 public:
00094   typedef isolation_traits<read_committed> isolation_tag;
00095 
00096   virtual ~transaction_base() =0;                                       
00097 
00099 
00111   void commit();                                                        
00112 
00114 
00117   void abort();                                                         
00118 
00120 
00125   result exec(const char Query[], 
00126               const PGSTD::string &Desc=PGSTD::string());               
00127 
00129 
00137   result exec(const PGSTD::string &Query,
00138               const PGSTD::string &Desc=PGSTD::string())                
00139         { return exec(Query.c_str(), Desc); }
00140 
00141   result exec(const PGSTD::stringstream &Query,
00142               const PGSTD::string &Desc=PGSTD::string())                
00143         { return exec(Query.str(), Desc); }
00144 
00146   void process_notice(const char Msg[]) const                           
00147         { m_Conn.process_notice(Msg); }
00149   void process_notice(const PGSTD::string &Msg) const                   
00150         { m_Conn.process_notice(Msg); }
00151 
00153   connection_base &conn() const { return m_Conn; }                      
00154 
00156 
00164   void set_variable(const PGSTD::string &Var, const PGSTD::string &Val);
00165 
00167 
00173   PGSTD::string get_variable(const PGSTD::string &) const;              
00174 
00175 #ifdef PQXX_DEPRECATED_HEADERS
00176 
00177   void Commit() { commit(); }
00179   void Abort() { abort(); }
00181   result Exec(const char Q[], const PGSTD::string &D=PGSTD::string())
00182         { return exec(Q,D); }
00184   result Exec(const PGSTD::string &Q, const PGSTD::string &D=PGSTD::string())
00185         { return exec(Q,D); }
00187   void ProcessNotice(const char M[]) const { return process_notice(M); }
00189   void ProcessNotice(const PGSTD::string &M) const { return process_notice(M); }
00191   PGSTD::string Name() const { return name(); }
00193   connection_base &Conn() const { return conn(); }
00195   void SetVariable(const PGSTD::string &Var, const PGSTD::string &Val)
00196         { set_variable(Var,Val); }
00197 #endif
00198 
00199 protected:
00201 
00204   explicit transaction_base(connection_base &, 
00205                           const PGSTD::string &TName,
00206                           const PGSTD::string &CName);
00207 
00209 
00211   void Begin();
00212 
00214   void End() throw ();
00215 
00217   virtual void do_begin() =0;
00219   virtual result do_exec(const char Query[]) =0;
00221   virtual void do_commit() =0;
00223   virtual void do_abort() =0;
00224 
00225   
00226 
00228 
00236   result DirectExec(const char C[], int Retries=0);
00237  
00238 private:
00239   
00240 
00241 
00242 
00243 
00244 
00245 
00246 
00247 
00248 
00249 
00250 
00251 
00252 
00253 
00254 
00255 
00256 
00257 
00258   enum Status 
00259   { 
00260     st_nascent, 
00261     st_active, 
00262     st_aborted, 
00263     st_committed,
00264     st_in_doubt
00265   };
00266 
00267 
00268   void CheckPendingError();
00269 
00270   friend class Cursor;
00271   friend class cursor_base;
00272   int GetUniqueCursorNum() { return m_UniqueCursorNum++; }
00273   void MakeEmpty(result &R) const { m_Conn.MakeEmpty(R); }
00274 
00275   friend class internal::transactionfocus;
00276   void RegisterFocus(internal::transactionfocus *);
00277   void UnregisterFocus(internal::transactionfocus *) throw ();
00278   void RegisterPendingError(const PGSTD::string &) throw ();
00279   friend class tablereader;
00280   void BeginCopyRead(const PGSTD::string &Table, const PGSTD::string &Columns);
00281   bool ReadCopyLine(PGSTD::string &L) { return m_Conn.ReadCopyLine(L); }
00282   friend class tablewriter;
00283   void BeginCopyWrite(const PGSTD::string &Table, 
00284         const PGSTD::string &Columns = PGSTD::string());
00285   void WriteCopyLine(const PGSTD::string &L) { m_Conn.WriteCopyLine(L); }
00286   void EndCopyWrite() { m_Conn.EndCopyWrite(); }
00287 
00288   friend class pipeline;
00289   void start_exec(const PGSTD::string &Q) { m_Conn.start_exec(Q); }
00290   internal::pq::PGresult *get_result() { return m_Conn.get_result(); }
00291   void consume_input() throw () { m_Conn.consume_input(); }
00292   bool is_busy() const throw () { return m_Conn.is_busy(); }
00293 
00294   connection_base &m_Conn;
00295 
00296   int m_UniqueCursorNum;
00297   internal::unique<internal::transactionfocus> m_Focus;
00298   Status m_Status;
00299   bool m_Registered;
00300   mutable PGSTD::map<PGSTD::string, PGSTD::string> m_Vars;
00301   PGSTD::string m_PendingError;
00302 
00304   transaction_base();
00306   transaction_base(const transaction_base &);
00308   transaction_base &operator=(const transaction_base &);
00309 };
00310 
00311 } 
00312 
00313