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 const char **const pindex = new const char *[p.size()+1];
00210 result r;
00211 try
00212 {
00213 const pvec::size_type stop = p.size();
00214 for (pvec::size_type i=0; i < stop; ++i) pindex[i] = p[i].c_str();
00215 pindex[stop] = 0;
00216 r = m_Conn.pq_exec_prepared(qname, p.size(), pindex);
00217 }
00218 catch (const PGSTD::exception &)
00219 {
00220 delete [] pindex;
00221 throw;
00222 }
00223 delete [] pindex;
00224 return r;
00225 }
00226
00228
00243 template<typename CNTNR> result exec_prepared(const char qname[],
00244 const CNTNR &args)
00245 { return exec_prepared(qname, args.begin(), args.end()); }
00246
00248
00263 template<typename CNTNR>
00264 result exec_prepared(const PGSTD::string &qname, CNTNR args)
00265 { return exec_prepared(qname, args.begin(), args.end()); }
00266
00268 void process_notice(const char Msg[]) const
00269 { m_Conn.process_notice(Msg); }
00271 void process_notice(const PGSTD::string &Msg) const
00272 { m_Conn.process_notice(Msg); }
00273
00275 connection_base &conn() const { return m_Conn; }
00276
00278
00286 void set_variable(const PGSTD::string &Var, const PGSTD::string &Val);
00287
00289
00295 PGSTD::string get_variable(const PGSTD::string &) const;
00296
00297 #ifdef PQXX_DEPRECATED_HEADERS
00298
00299 void Commit() { commit(); }
00301 void Abort() { abort(); }
00303 result Exec(const char Q[], const PGSTD::string &D=PGSTD::string())
00304 { return exec(Q,D); }
00306 result Exec(const PGSTD::string &Q, const PGSTD::string &D=PGSTD::string())
00307 { return exec(Q,D); }
00309 void ProcessNotice(const char M[]) const { return process_notice(M); }
00311 void ProcessNotice(const PGSTD::string &M) const { return process_notice(M); }
00313 PGSTD::string Name() const { return name(); }
00315 connection_base &Conn() const { return conn(); }
00317 void SetVariable(const PGSTD::string &Var, const PGSTD::string &Val)
00318 { set_variable(Var,Val); }
00319 #endif
00320
00321 protected:
00323
00326 explicit transaction_base(connection_base &,
00327 const PGSTD::string &TName,
00328 const PGSTD::string &CName);
00329
00331
00333 void Begin();
00334
00336 void End() throw ();
00337
00339 virtual void do_begin() =0;
00341 virtual result do_exec(const char Query[]) =0;
00343 virtual void do_commit() =0;
00345 virtual void do_abort() =0;
00346
00347
00348
00350
00358 result DirectExec(const char C[], int Retries=0);
00359
00360 private:
00361
00362
00363
00364
00365
00366
00367
00368
00369
00370
00371
00372
00373
00374
00375
00376
00377
00378
00379
00380 enum Status
00381 {
00382 st_nascent,
00383 st_active,
00384 st_aborted,
00385 st_committed,
00386 st_in_doubt
00387 };
00388
00389
00390 void CheckPendingError();
00391
00392 friend class Cursor;
00393 friend class cursor_base;
00394 int GetUniqueCursorNum() { return m_UniqueCursorNum++; }
00395 void MakeEmpty(result &R) const { m_Conn.MakeEmpty(R); }
00396
00397 friend class internal::transactionfocus;
00398 void RegisterFocus(internal::transactionfocus *);
00399 void UnregisterFocus(internal::transactionfocus *) throw ();
00400 void RegisterPendingError(const PGSTD::string &) throw ();
00401 friend class tablereader;
00402 void BeginCopyRead(const PGSTD::string &Table, const PGSTD::string &Columns);
00403 bool ReadCopyLine(PGSTD::string &L) { return m_Conn.ReadCopyLine(L); }
00404 friend class tablewriter;
00405 void BeginCopyWrite(const PGSTD::string &Table,
00406 const PGSTD::string &Columns = PGSTD::string());
00407 void WriteCopyLine(const PGSTD::string &L) { m_Conn.WriteCopyLine(L); }
00408 void EndCopyWrite() { m_Conn.EndCopyWrite(); }
00409
00410 friend class pipeline;
00411 void start_exec(const PGSTD::string &Q) { m_Conn.start_exec(Q); }
00412 internal::pq::PGresult *get_result() { return m_Conn.get_result(); }
00413 void consume_input() throw () { m_Conn.consume_input(); }
00414 bool is_busy() const throw () { return m_Conn.is_busy(); }
00415
00416 connection_base &m_Conn;
00417
00418 int m_UniqueCursorNum;
00419 internal::unique<internal::transactionfocus> m_Focus;
00420 Status m_Status;
00421 bool m_Registered;
00422 mutable PGSTD::map<PGSTD::string, PGSTD::string> m_Vars;
00423 PGSTD::string m_PendingError;
00424
00426 transaction_base();
00428 transaction_base(const transaction_base &);
00430 transaction_base &operator=(const transaction_base &);
00431 };
00432
00433 }
00434
00435