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
00093 class PQXX_LIBEXPORT transaction_base : public internal::namedclass
00094 {
00095 public:
00097 typedef isolation_traits<read_committed> isolation_tag;
00098
00099 virtual ~transaction_base() =0;
00100
00102
00114 void commit();
00115
00117
00120 void abort();
00121
00123
00128 result exec(const char Query[],
00129 const PGSTD::string &Desc=PGSTD::string());
00130
00132
00140 result exec(const PGSTD::string &Query,
00141 const PGSTD::string &Desc=PGSTD::string())
00142 { return exec(Query.c_str(), Desc); }
00143
00144 result exec(const PGSTD::stringstream &Query,
00145 const PGSTD::string &Desc=PGSTD::string())
00146 { return exec(Query.str(), Desc); }
00147
00152
00153
00168 result exec_prepared(const PGSTD::string &qname)
00169 { return m_Conn.pq_exec_prepared(qname.c_str(), 0, 0); }
00170
00172
00187 result exec_prepared(const char qname[])
00188 { return m_Conn.pq_exec_prepared(qname, 0, 0); }
00189
00191
00209 template<typename STRING, typename ITER>
00210 result exec_prepared(STRING qname, ITER beginargs, ITER endargs)
00211 {
00212 if (beginargs == endargs) return exec_prepared(qname);
00213
00214 typedef PGSTD::vector<PGSTD::string> pvec;
00215 pvec p;
00216 PGSTD::vector<bool> nulls;
00217 for (; beginargs!=endargs; ++beginargs)
00218 {
00219 const bool isnull = parm_is_null(*beginargs);
00220 nulls.push_back(isnull);
00221 p.push_back(to_string(isnull ? "" : *beginargs));
00222 }
00223 result r;
00224 const internal::scoped_array<const char *> pindex(p.size()+1);
00225 const pvec::size_type stop = p.size();
00226 for (pvec::size_type i=0; i < stop; ++i)
00227 pindex[i] = (nulls[i] ? 0 : p[i].c_str());
00228 pindex[stop] = 0;
00229 r = m_Conn.pq_exec_prepared(qname, p.size(), pindex.c_ptr());
00230 return r;
00231 }
00232
00234
00249 template<typename CNTNR> result exec_prepared(const char qname[],
00250 const CNTNR &args)
00251 { return exec_prepared(qname, args.begin(), args.end()); }
00252
00254
00269 template<typename CNTNR>
00270 result exec_prepared(const PGSTD::string &qname, CNTNR args)
00271 { return exec_prepared(qname, args.begin(), args.end()); }
00273
00278
00279 void process_notice(const char Msg[]) const
00280 { m_Conn.process_notice(Msg); }
00282 void process_notice(const PGSTD::string &Msg) const
00283 { m_Conn.process_notice(Msg); }
00285
00287 connection_base &conn() const { return m_Conn; }
00288
00290
00298 void set_variable(const PGSTD::string &Var, const PGSTD::string &Val);
00299
00301
00310 PGSTD::string get_variable(const PGSTD::string &);
00311
00312 #ifdef PQXX_DEPRECATED_HEADERS
00313
00317
00318 void Commit() { commit(); }
00320 void Abort() { abort(); }
00322 result Exec(const char Q[], const PGSTD::string &D=PGSTD::string())
00323 { return exec(Q,D); }
00325 result Exec(const PGSTD::string &Q, const PGSTD::string &D=PGSTD::string())
00326 { return exec(Q,D); }
00328 void ProcessNotice(const char M[]) const { return process_notice(M); }
00330 void ProcessNotice(const PGSTD::string &M) const { return process_notice(M); }
00332 PGSTD::string Name() const { return name(); }
00334 connection_base &Conn() const { return conn(); }
00336 void SetVariable(const PGSTD::string &Var, const PGSTD::string &Val)
00337 { set_variable(Var,Val); }
00339 #endif
00340
00341 protected:
00343
00346 explicit transaction_base(connection_base &,
00347 const PGSTD::string &TName,
00348 const PGSTD::string &CName);
00349
00351
00353 void Begin();
00354
00356 void End() throw ();
00357
00359 virtual void do_begin() =0;
00361 virtual result do_exec(const char Query[]) =0;
00363 virtual void do_commit() =0;
00365 virtual void do_abort() =0;
00366
00367
00368
00370
00378 result DirectExec(const char C[], int Retries=0);
00379
00381 void reactivation_avoidance_clear() throw () { m_reactivation_avoidance = 0; }
00382
00383 private:
00384
00385
00386
00387
00388
00389
00390
00391
00392
00393
00394
00395
00396
00397
00398
00399
00400
00401
00402
00403 enum Status
00404 {
00405 st_nascent,
00406 st_active,
00407 st_aborted,
00408 st_committed,
00409 st_in_doubt
00410 };
00411
00412
00413 void PQXX_PRIVATE CheckPendingError();
00414
00415 template<typename T> bool parm_is_null(T *p) const throw () { return !p; }
00416 template<typename T> bool parm_is_null(T) const throw () { return false; }
00417
00418 friend class Cursor;
00419 friend class cursor_base;
00420 int GetUniqueCursorNum() { return m_UniqueCursorNum++; }
00421 void MakeEmpty(result &R) const { m_Conn.MakeEmpty(R); }
00422 void reactivation_avoidance_inc() throw () { ++m_reactivation_avoidance; }
00423 void reactivation_avoidance_dec() throw () { --m_reactivation_avoidance; }
00424
00425 friend class internal::transactionfocus;
00426 void PQXX_PRIVATE RegisterFocus(internal::transactionfocus *);
00427 void PQXX_PRIVATE UnregisterFocus(internal::transactionfocus *) throw ();
00428 void PQXX_PRIVATE RegisterPendingError(const PGSTD::string &) throw ();
00429 friend class tablereader;
00430 void PQXX_PRIVATE BeginCopyRead(const PGSTD::string &, const PGSTD::string &);
00431 bool ReadCopyLine(PGSTD::string &L) { return m_Conn.ReadCopyLine(L); }
00432 friend class tablewriter;
00433 void PQXX_PRIVATE BeginCopyWrite(const PGSTD::string &Table,
00434 const PGSTD::string &Columns = PGSTD::string());
00435 void WriteCopyLine(const PGSTD::string &L) { m_Conn.WriteCopyLine(L); }
00436 void EndCopyWrite() { m_Conn.EndCopyWrite(); }
00437
00438 friend class pipeline;
00439 void start_exec(const PGSTD::string &Q) { m_Conn.start_exec(Q); }
00440 internal::pq::PGresult *get_result() { return m_Conn.get_result(); }
00441 void consume_input() throw () { m_Conn.consume_input(); }
00442 bool is_busy() const throw () { return m_Conn.is_busy(); }
00443
00444 connection_base &m_Conn;
00445
00446 int m_UniqueCursorNum;
00447 internal::unique<internal::transactionfocus> m_Focus;
00448 Status m_Status;
00449 bool m_Registered;
00450 PGSTD::map<PGSTD::string, PGSTD::string> m_Vars;
00451 PGSTD::string m_PendingError;
00453
00455 int m_reactivation_avoidance;
00456
00458 transaction_base();
00460 transaction_base(const transaction_base &);
00462 transaction_base &operator=(const transaction_base &);
00463 };
00464
00465 }
00466
00467