libpqxx: transaction_base.hxx Source File

libpqxx 4.0.1

- Main Page
- Related Pages
- Modules
- Namespaces
- Classes

transaction_base.hxx
1 /*-------------------------------------------------------------------------
2 *
3 * FILE
4 * pqxx/transaction_base.hxx
5 *
6 * DESCRIPTION
7 * common code and definitions for the transaction classes.
8 * pqxx::transaction_base defines the interface for any abstract class that
9 * represents a database transaction
10 * DO NOT INCLUDE THIS FILE DIRECTLY; include pqxx/transaction_base instead.
11 *
12 * Copyright (c) 2001-2011, Jeroen T. Vermeulen <jtv@xs4all.nl>
13 *
14 * See COPYING for copyright license. If you did not receive a file called
15 * COPYING with this source code, please notify the distributor of this mistake,
16 * or contact the author.
17 *
18 *-------------------------------------------------------------------------
19 */
20 #ifndef PQXX_H_TRANSACTION_BASE
21 #define PQXX_H_TRANSACTION_BASE
22
23 #include "pqxx/compiler-public.hxx"
24 #include "pqxx/compiler-internal-pre.hxx"
25
26 /* End-user programs need not include this file, unless they define their own
27 * transaction classes. This is not something the typical program should want
28 * to do.
29 *
30 * However, reading this file is worthwhile because it defines the public
31 * interface for the available transaction classes such as transaction and
32 * nontransaction.
33 */
34
35 #include "pqxx/connection_base"
36 #include "pqxx/isolation"
37 #include "pqxx/result"
38
39 /* Methods tested in eg. self-test program test001 are marked with "//[t1]"
40 */
41
42 namespace pqxx
43 {
44 class connection_base;
45 class transaction_base;
46
47
48 namespace internal
49 {
50 class sql_cursor;
51
52 class PQXX_LIBEXPORT transactionfocus : public virtual namedclass
53 {
54 public:
55 explicit transactionfocus(transaction_base &t) :
56 namedclass("transactionfocus"),
57 m_Trans(t),
58 m_registered(false)
59 {
60 }
61
62 protected:
63 void register_me();
64 void unregister_me() throw ();
65 void reg_pending_error(const PGSTD::string &) throw ();
66 bool registered() const throw () { return m_registered; }
67
68 transaction_base &m_Trans;
69
70 private:
71 bool m_registered;
72
74 transactionfocus();
76 transactionfocus(const transactionfocus &);
78 transactionfocus &operator=(const transactionfocus &);
79 };
80
81
82 class PQXX_LIBEXPORT parameterized_invocation : statement_parameters
83 {
84 public:
85 parameterized_invocation(connection_base &, const PGSTD::string &query);
86
87 parameterized_invocation &operator()() { add_param(); return *this; }
88 parameterized_invocation &operator()(const binarystring &v)
89 { add_binary_param(v, true); return *this; }
90 template<typename T> parameterized_invocation &operator()(const T &v)
91 { add_param(v, true); return *this; }
92 parameterized_invocation &operator()(const binarystring &v, bool nonnull)
93 { add_binary_param(v, nonnull); return *this; }
94 template<typename T>
95 parameterized_invocation &operator()(const T &v, bool nonnull)
96 { add_param(v, nonnull); return *this; }
97
98 result exec();
99
100 private:
102 parameterized_invocation &operator=(const parameterized_invocation &);
103
104 connection_base &m_home;
105 const PGSTD::string m_query;
106 };
107 } // namespace internal
108
109
110 namespace internal
111 {
112 namespace gate
113 {
114 class transaction_subtransaction;
115 class transaction_tablereader;
116 class transaction_tablewriter;
117 class transaction_transactionfocus;
118 } // namespace internal::gate
119 } // namespace internal
120
121
123
133 class PQXX_LIBEXPORT PQXX_NOVTABLE transaction_base :
134 public virtual internal::namedclass
135 {
136 public:
138 typedef isolation_traits<read_committed> isolation_tag;
139
140 virtual ~transaction_base() =0; //[t1]
141
143
155 void commit(); //[t1]
156
158
161 void abort(); //[t10]
162
167
168 PGSTD::string esc(const char str[]) const { return conn().esc(str); }
170 PGSTD::string esc(const char str[], size_t maxlen) const
171 { return conn().esc(str, maxlen); }
173 PGSTD::string esc(const PGSTD::string &str) const { return conn().esc(str); }
174
176
187 PGSTD::string esc_raw(const unsigned char str[], size_t len) const //[t62]
188 { return conn().esc_raw(str, len); }
190 PGSTD::string esc_raw(const PGSTD::string &) const; //[t62]
191
193
194 template<typename T> PGSTD::string quote(const T &t) const
195 { return conn().quote(t); }
196
198 PGSTD::string quote_raw(const unsigned char str[], size_t len) const
199 { return conn().quote_raw(str, len); }
200
201 PGSTD::string quote_raw(const PGSTD::string &str) const;
202
204 PGSTD::string quote_name(const PGSTD::string &identifier) const
205 { return conn().quote_name(identifier); }
207
209
224 result exec(const PGSTD::string &Query,
225 const PGSTD::string &Desc=PGSTD::string()); //[t1]
226
227 result exec(const PGSTD::stringstream &Query,
228 const PGSTD::string &Desc=PGSTD::string())
229 { return exec(Query.str(), Desc); }
230
232 /* Use this to build up a parameterized statement invocation, then invoke it
233 * using @c exec()
234 *
235 * Example: @c trans.parameterized("SELECT $1 + 1")(1).exec();
236 */
237 internal::parameterized_invocation parameterized(const PGSTD::string &query);
238
243
244
288 prepare::invocation prepared(const PGSTD::string &statement=PGSTD::string());
289
291
296
297 void process_notice(const char Msg[]) const //[t14]
298 { m_Conn.process_notice(Msg); }
300 void process_notice(const PGSTD::string &Msg) const //[t14]
301 { m_Conn.process_notice(Msg); }
303
305 connection_base &conn() const { return m_Conn; } //[t4]
306
308
316 void set_variable(const PGSTD::string &Var, const PGSTD::string &Val);//[t61]
317
319
328 PGSTD::string get_variable(const PGSTD::string &); //[t61]
329
330
331 protected:
333
339 explicit transaction_base(connection_base &c, bool direct=true);
340
342
344 void Begin();
345
347 void End() throw ();
348
350 virtual void do_begin() =0;
352 virtual result do_exec(const char Query[]) =0;
354 virtual void do_commit() =0;
356 virtual void do_abort() =0;
357
358 // For use by implementing class:
359
361
369 result DirectExec(const char C[], int Retries=0);
370
372 void reactivation_avoidance_clear() throw ()
373 {m_reactivation_avoidance.clear();}
374
375 protected:
377
379 internal::reactivation_avoidance_counter m_reactivation_avoidance;
380
381 private:
382 /* A transaction goes through the following stages in its lifecycle:
383 * <ul>
384 * <li> nascent: the transaction hasn't actually begun yet. If our connection
385 * fails at this stage, it may recover and the transaction can attempt to
386 * establish itself again.
387 * <li> active: the transaction has begun. Since no commit command has been
388 * issued, abortion is implicit if the connection fails now.
389 * <li> aborted: an abort has been issued; the transaction is terminated and
390 * its changes to the database rolled back. It will accept no further
391 * commands.
392 * <li> committed: the transaction has completed successfully, meaning that a
393 * commit has been issued. No further commands are accepted.
394 * <li> in_doubt: the connection was lost at the exact wrong time, and there
395 * is no way of telling whether the transaction was committed or aborted.
396 * </ul>
397 *
398 * Checking and maintaining state machine logic is the responsibility of the
399 * base class (ie., this one).
400 */
401 enum Status
402 {
403 st_nascent,
404 st_active,
405 st_aborted,
406 st_committed,
407 st_in_doubt
408 };
409
411 void PQXX_PRIVATE activate();
412
413 void PQXX_PRIVATE CheckPendingError();
414
415 template<typename T> bool parm_is_null(T *p) const throw () { return !p; }
416 template<typename T> bool parm_is_null(T) const throw () { return false; }
417
418 friend class pqxx::internal::gate::transaction_transactionfocus;
419 void PQXX_PRIVATE RegisterFocus(internal::transactionfocus *);
420 void PQXX_PRIVATE UnregisterFocus(internal::transactionfocus *) throw ();
421 void PQXX_PRIVATE RegisterPendingError(const PGSTD::string &) throw ();
422
423 friend class pqxx::internal::gate::transaction_tablereader;
424 void PQXX_PRIVATE BeginCopyRead(const PGSTD::string &, const PGSTD::string &);
425 bool ReadCopyLine(PGSTD::string &);
426
427 friend class pqxx::internal::gate::transaction_tablewriter;
428 void PQXX_PRIVATE BeginCopyWrite(
429 const PGSTD::string &Table,
430 const PGSTD::string &Columns);
431 void WriteCopyLine(const PGSTD::string &);
432 void EndCopyWrite();
433
434 friend class pqxx::internal::gate::transaction_subtransaction;
435
436 connection_base &m_Conn;
437
438 internal::unique<internal::transactionfocus> m_Focus;
439 Status m_Status;
440 bool m_Registered;
441 PGSTD::map<PGSTD::string, PGSTD::string> m_Vars;
442 PGSTD::string m_PendingError;
443
445 transaction_base();
447 transaction_base(const transaction_base &);
449 transaction_base &operator=(const transaction_base &);
450 };
451
452 } // namespace pqxx
453
454
455 #include "pqxx/compiler-internal-post.hxx"
456
457 #endif
458