00001 
00002 
00003 
00004 
00005 
00006 
00007 
00008 
00009 
00010 
00011 
00012 
00013 
00014 
00015 
00016 
00017 
00018 
00019 
00020 #include "pqxx/libcompiler.h"
00021 
00022 
00023 
00024 
00025 
00026 
00027 
00028 
00029 
00030 
00031 #include "pqxx/connection_base"
00032 #include "pqxx/isolation"
00033 #include "pqxx/result"
00034 
00035 
00036 
00037 
00038 
00039 
00040 namespace pqxx
00041 {
00042 class connection_base;
00043 class transaction_base;
00044 
00045 
00046 namespace internal
00047 {
00048 class PQXX_LIBEXPORT transactionfocus : public namedclass
00049 {
00050 public:
00051   transactionfocus(transaction_base &t,
00052       const PGSTD::string &Name,
00053       const PGSTD::string &Classname) :
00054     namedclass(Name, Classname),
00055     m_Trans(t),
00056     m_registered(false)
00057   {
00058   }
00059 
00060 protected:
00061   void register_me();
00062   void unregister_me() throw ();
00063   void reg_pending_error(const PGSTD::string &) throw ();
00064   bool registered() const throw () { return m_registered; }
00065 
00066   transaction_base &m_Trans;
00067 
00068 private:
00069   bool m_registered;
00070 
00072   transactionfocus();
00074   transactionfocus(const transactionfocus &);
00076   transactionfocus &operator=(const transactionfocus &);
00077 };
00078 } 
00079 
00080 
00081 
00083 
00091 class PQXX_LIBEXPORT transaction_base : public internal::namedclass
00092 {
00093   
00094 public:
00096   typedef isolation_traits<read_committed> isolation_tag;
00097 
00098   virtual ~transaction_base() =0;                                       
00099 
00101 
00113   void commit();                                                        
00114 
00116 
00119   void abort();                                                         
00120 
00122 
00127   result exec(const char Query[],
00128               const PGSTD::string &Desc=PGSTD::string());               
00129 
00131 
00139   result exec(const PGSTD::string &Query,
00140               const PGSTD::string &Desc=PGSTD::string())                
00141         { return exec(Query.c_str(), Desc); }
00142 
00143   result exec(const PGSTD::stringstream &Query,
00144               const PGSTD::string &Desc=PGSTD::string())                
00145         { return exec(Query.str(), Desc); }
00146 
00148 
00163   result exec_prepared(const PGSTD::string &qname)                      
00164         { return m_Conn.pq_exec_prepared(qname.c_str(), 0, 0); }
00165 
00167 
00182   result exec_prepared(const char qname[])                              
00183         { return m_Conn.pq_exec_prepared(qname, 0, 0); }
00184 
00186 
00201   template<typename STRING, typename ITER>
00202     result exec_prepared(STRING qname, ITER beginargs, ITER endargs)    
00203   {
00204     if (beginargs == endargs) return exec_prepared(qname);
00205 
00206     typedef PGSTD::vector<PGSTD::string> pvec;
00207     pvec p;
00208     for (; beginargs!=endargs; ++beginargs) p.push_back(to_string(*beginargs));
00209     result r;
00210     const internal::scoped_array<const char *> pindex(p.size()+1);
00211     const pvec::size_type stop = p.size();
00212     for (pvec::size_type i=0; i < stop; ++i) pindex[i] = p[i].c_str();
00213     pindex[stop] = 0;
00214     r = m_Conn.pq_exec_prepared(qname, p.size(), pindex.c_ptr());
00215     return r;
00216   }
00217 
00219 
00234   template<typename CNTNR> result exec_prepared(const char qname[],     
00235       const CNTNR &args)
00236         { return exec_prepared(qname, args.begin(), args.end()); }
00237 
00239 
00254   template<typename CNTNR>
00255     result exec_prepared(const PGSTD::string &qname, CNTNR args)        
00256         { return exec_prepared(qname, args.begin(), args.end()); }
00257 
00259   void process_notice(const char Msg[]) const                           
00260         { m_Conn.process_notice(Msg); }
00262   void process_notice(const PGSTD::string &Msg) const                   
00263         { m_Conn.process_notice(Msg); }
00264 
00266   connection_base &conn() const { return m_Conn; }                      
00267 
00269 
00277   void set_variable(const PGSTD::string &Var, const PGSTD::string &Val);
00278 
00280 
00286   PGSTD::string get_variable(const PGSTD::string &) const;              
00287 
00288 #ifdef PQXX_DEPRECATED_HEADERS
00289 
00290   void Commit() { commit(); }
00292   void Abort() { abort(); }
00294   result Exec(const char Q[], const PGSTD::string &D=PGSTD::string())
00295         { return exec(Q,D); }
00297   result Exec(const PGSTD::string &Q, const PGSTD::string &D=PGSTD::string())
00298         { return exec(Q,D); }
00300   void ProcessNotice(const char M[]) const { return process_notice(M); }
00302   void ProcessNotice(const PGSTD::string &M) const { return process_notice(M); }
00304   PGSTD::string Name() const { return name(); }
00306   connection_base &Conn() const { return conn(); }
00308   void SetVariable(const PGSTD::string &Var, const PGSTD::string &Val)
00309         { set_variable(Var,Val); }
00310 #endif
00311 
00312 protected:
00314 
00317   explicit transaction_base(connection_base &,
00318                           const PGSTD::string &TName,
00319                           const PGSTD::string &CName);
00320 
00322 
00324   void Begin();
00325 
00327   void End() throw ();
00328 
00330   virtual void do_begin() =0;
00332   virtual result do_exec(const char Query[]) =0;
00334   virtual void do_commit() =0;
00336   virtual void do_abort() =0;
00337 
00338   
00339 
00341 
00349   result DirectExec(const char C[], int Retries=0);
00350 
00351 private:
00352   
00353 
00354 
00355 
00356 
00357 
00358 
00359 
00360 
00361 
00362 
00363 
00364 
00365 
00366 
00367 
00368 
00369 
00370 
00371   enum Status
00372   {
00373     st_nascent,
00374     st_active,
00375     st_aborted,
00376     st_committed,
00377     st_in_doubt
00378   };
00379 
00380 
00381   void PQXX_PRIVATE CheckPendingError();
00382 
00383   friend class Cursor;
00384   friend class cursor_base;
00385   int GetUniqueCursorNum() { return m_UniqueCursorNum++; }
00386   void MakeEmpty(result &R) const { m_Conn.MakeEmpty(R); }
00387 
00388   friend class internal::transactionfocus;
00389   void PQXX_PRIVATE RegisterFocus(internal::transactionfocus *);
00390   void PQXX_PRIVATE UnregisterFocus(internal::transactionfocus *) throw ();
00391   void PQXX_PRIVATE RegisterPendingError(const PGSTD::string &) throw ();
00392   friend class tablereader;
00393   void PQXX_PRIVATE BeginCopyRead(const PGSTD::string &, const PGSTD::string &);
00394   bool ReadCopyLine(PGSTD::string &L) { return m_Conn.ReadCopyLine(L); }
00395   friend class tablewriter;
00396   void PQXX_PRIVATE BeginCopyWrite(const PGSTD::string &Table,
00397         const PGSTD::string &Columns = PGSTD::string());
00398   void WriteCopyLine(const PGSTD::string &L) { m_Conn.WriteCopyLine(L); }
00399   void EndCopyWrite() { m_Conn.EndCopyWrite(); }
00400 
00401   friend class pipeline;
00402   void start_exec(const PGSTD::string &Q) { m_Conn.start_exec(Q); }
00403   internal::pq::PGresult *get_result() { return m_Conn.get_result(); }
00404   void consume_input() throw () { m_Conn.consume_input(); }
00405   bool is_busy() const throw () { return m_Conn.is_busy(); }
00406 
00407   connection_base &m_Conn;
00408 
00409   int m_UniqueCursorNum;
00410   internal::unique<internal::transactionfocus> m_Focus;
00411   Status m_Status;
00412   bool m_Registered;
00413   mutable PGSTD::map<PGSTD::string, PGSTD::string> m_Vars;
00414   PGSTD::string m_PendingError;
00415 
00417   transaction_base();
00419   transaction_base(const transaction_base &);
00421   transaction_base &operator=(const transaction_base &);
00422 };
00423 
00424 } 
00425 
00426