00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #ifndef PQXX_H_TRANSACTION_BASE
00021 #define PQXX_H_TRANSACTION_BASE
00022
00023 #include "pqxx/compiler-public.hxx"
00024 #include "pqxx/compiler-internal-pre.hxx"
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035 #include "pqxx/connection_base"
00036 #include "pqxx/isolation"
00037 #include "pqxx/result"
00038
00039
00040
00041
00042 namespace pqxx
00043 {
00044 class connection_base;
00045 class transaction_base;
00046
00047
00048 namespace internal
00049 {
00050 class sql_cursor;
00051
00052 class PQXX_LIBEXPORT transactionfocus : public virtual namedclass
00053 {
00054 public:
00055 explicit transactionfocus(transaction_base &t) :
00056 namedclass("transactionfocus"),
00057 m_Trans(t),
00058 m_registered(false)
00059 {
00060 }
00061
00062 protected:
00063 void register_me();
00064 void unregister_me() throw ();
00065 void reg_pending_error(const PGSTD::string &) throw ();
00066 bool registered() const throw () { return m_registered; }
00067
00068 transaction_base &m_Trans;
00069
00070 private:
00071 bool m_registered;
00072
00074 transactionfocus();
00076 transactionfocus(const transactionfocus &);
00078 transactionfocus &operator=(const transactionfocus &);
00079 };
00080
00081 }
00082
00083
00084
00086
00096 class PQXX_LIBEXPORT PQXX_NOVTABLE transaction_base :
00097 public virtual internal::namedclass
00098 {
00099 public:
00101 typedef isolation_traits<read_committed> isolation_tag;
00102
00103 virtual ~transaction_base() =0;
00104
00106
00118 void commit();
00119
00121
00124 void abort();
00125
00130
00131 PGSTD::string esc(const char str[]) const
00132 { return m_Conn.esc(str); }
00134 PGSTD::string esc(const char str[], size_t maxlen) const
00135 { return m_Conn.esc(str, maxlen); }
00137 PGSTD::string esc(const PGSTD::string &str) const
00138 { return m_Conn.esc(str); }
00139
00141
00152 PGSTD::string esc_raw(const unsigned char str[], size_t len) const
00153 { return m_Conn.esc_raw(str, len); }
00155 PGSTD::string esc_raw(const PGSTD::string &) const;
00156
00158
00159 template<typename T> PGSTD::string quote(const T &t) const
00160 { return m_Conn.quote(t); }
00162
00164
00179 result exec(const PGSTD::string &Query,
00180 const PGSTD::string &Desc=PGSTD::string());
00181
00182 result exec(const PGSTD::stringstream &Query,
00183 const PGSTD::string &Desc=PGSTD::string())
00184 { return exec(Query.str(), Desc); }
00185
00190
00191
00225 prepare::invocation prepared(const PGSTD::string &statement);
00226
00228
00233
00234 void process_notice(const char Msg[]) const
00235 { m_Conn.process_notice(Msg); }
00237 void process_notice(const PGSTD::string &Msg) const
00238 { m_Conn.process_notice(Msg); }
00240
00242 connection_base &conn() const { return m_Conn; }
00243
00245
00253 void set_variable(const PGSTD::string &Var, const PGSTD::string &Val);
00254
00256
00265 PGSTD::string get_variable(const PGSTD::string &);
00266
00267
00268 protected:
00270
00275 explicit transaction_base(connection_base &, bool direct=true);
00276
00278
00280 void Begin();
00281
00283 void End() throw ();
00284
00286 virtual void do_begin() =0;
00288 virtual result do_exec(const char Query[]) =0;
00290 virtual void do_commit() =0;
00292 virtual void do_abort() =0;
00293
00294
00295
00297
00305 result DirectExec(const char C[], int Retries=0);
00306
00308 void reactivation_avoidance_clear() throw ()
00309 {m_reactivation_avoidance.clear();}
00310
00311 private:
00312
00313
00314
00315
00316
00317
00318
00319
00320
00321
00322
00323
00324
00325
00326
00327
00328
00329
00330
00331 enum Status
00332 {
00333 st_nascent,
00334 st_active,
00335 st_aborted,
00336 st_committed,
00337 st_in_doubt
00338 };
00339
00341 void PQXX_PRIVATE activate();
00342
00343 void PQXX_PRIVATE CheckPendingError();
00344
00345 template<typename T> bool parm_is_null(T *p) const throw () { return !p; }
00346 template<typename T> bool parm_is_null(T) const throw () { return false; }
00347
00348 friend class pqxx::internal::sql_cursor;
00349 void MakeEmpty(result &R) const { m_Conn.MakeEmpty(R); }
00350
00351 friend class internal::transactionfocus;
00352 void PQXX_PRIVATE RegisterFocus(internal::transactionfocus *);
00353 void PQXX_PRIVATE UnregisterFocus(internal::transactionfocus *) throw ();
00354 void PQXX_PRIVATE RegisterPendingError(const PGSTD::string &) throw ();
00355 friend class tablereader;
00356 void PQXX_PRIVATE BeginCopyRead(const PGSTD::string &, const PGSTD::string &);
00357 bool ReadCopyLine(PGSTD::string &L) { return m_Conn.ReadCopyLine(L); }
00358 friend class tablewriter;
00359 void PQXX_PRIVATE BeginCopyWrite(const PGSTD::string &Table,
00360 const PGSTD::string &Columns = PGSTD::string());
00361 void WriteCopyLine(const PGSTD::string &L) { m_Conn.WriteCopyLine(L); }
00362 void EndCopyWrite() { m_Conn.EndCopyWrite(); }
00363
00364 friend class pipeline;
00365 void start_exec(const PGSTD::string &Q) { m_Conn.start_exec(Q); }
00366 internal::pq::PGresult *get_result() { return m_Conn.get_result(); }
00367 bool consume_input() throw () { return m_Conn.consume_input(); }
00368 bool is_busy() const throw () { return m_Conn.is_busy(); }
00369
00370 friend class prepare::invocation;
00371 result prepared_exec(const PGSTD::string &,
00372 const char *const[],
00373 const int[],
00374 int);
00375
00376 connection_base &m_Conn;
00377
00378 internal::unique<internal::transactionfocus> m_Focus;
00379 Status m_Status;
00380 bool m_Registered;
00381 PGSTD::map<PGSTD::string, PGSTD::string> m_Vars;
00382 PGSTD::string m_PendingError;
00383
00384 friend class subtransaction;
00386
00388 internal::reactivation_avoidance_counter m_reactivation_avoidance;
00389
00391 transaction_base();
00393 transaction_base(const transaction_base &);
00395 transaction_base &operator=(const transaction_base &);
00396 };
00397
00398 }
00399
00400
00401 #include "pqxx/compiler-internal-post.hxx"
00402
00403 #endif
00404