libpqxx 3.1.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-2009, 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 template<typename T> parameterized_invocation &operator()(const T &v)
89 { add_param(v); return *this; }
90 template<typename T>
91 parameterized_invocation &operator()(const T &v, bool nonnull)
92 { add_param(v, nonnull); return *this; }
93
94 result exec();
95
96 private:
98 parameterized_invocation &operator=(const parameterized_invocation &);
99
100 connection_base &m_home;
101 const PGSTD::string m_query;
102 };
103 } // namespace internal
104
105
106 namespace internal
107 {
108 namespace gate
109 {
110 class transaction_subtransaction;
111 class transaction_tablereader;
112 class transaction_tablewriter;
113 class transaction_transactionfocus;
114 } // namespace internal::gate
115 } // namespace internal
116
117
119
129 class PQXX_LIBEXPORT PQXX_NOVTABLE transaction_base :
130 public virtual internal::namedclass
131 {
132 public:
134 typedef isolation_traits<read_committed> isolation_tag;
135
136 virtual ~transaction_base() =0; //[t1]
137
139
151 void commit(); //[t1]
152
154
157 void abort(); //[t10]
158
163
164 PGSTD::string esc(const char str[]) const //[t90]
165 { return m_Conn.esc(str); }
167 PGSTD::string esc(const char str[], size_t maxlen) const //[t90]
168 { return m_Conn.esc(str, maxlen); }
170 PGSTD::string esc(const PGSTD::string &str) const //[t90]
171 { return m_Conn.esc(str); }
172
174
185 PGSTD::string esc_raw(const unsigned char str[], size_t len) const //[t62]
186 { return m_Conn.esc_raw(str, len); }
188 PGSTD::string esc_raw(const PGSTD::string &) const; //[t62]
189
191
192 template<typename T> PGSTD::string quote(const T &t) const
193 { return m_Conn.quote(t); }
195
197
212 result exec(const PGSTD::string &Query,
213 const PGSTD::string &Desc=PGSTD::string()); //[t1]
214
215 result exec(const PGSTD::stringstream &Query,
216 const PGSTD::string &Desc=PGSTD::string()) //[t9]
217 { return exec(Query.str(), Desc); }
218
220 /* Use this to build up a parameterized statement invocation, then invoke it
221 * using @c exec()
222 *
223 * Example: @c trans.parameterized("SELECT $1 + 1")(1).exec();
224 */
225 internal::parameterized_invocation parameterized(const PGSTD::string &query);
226
231
232
276 prepare::invocation prepared(const PGSTD::string &statement=PGSTD::string());
277
279
284
285 void process_notice(const char Msg[]) const //[t14]
286 { m_Conn.process_notice(Msg); }
288 void process_notice(const PGSTD::string &Msg) const //[t14]
289 { m_Conn.process_notice(Msg); }
291
293 connection_base &conn() const { return m_Conn; } //[t4]
294
296
304 void set_variable(const PGSTD::string &Var, const PGSTD::string &Val);//[t61]
305
307
316 PGSTD::string get_variable(const PGSTD::string &); //[t61]
317
318
319 protected:
321
327 explicit transaction_base(connection_base &c, bool direct=true);
328
330
332 void Begin();
333
335 void End() throw ();
336
338 virtual void do_begin() =0;
340 virtual result do_exec(const char Query[]) =0;
342 virtual void do_commit() =0;
344 virtual void do_abort() =0;
345
346 // For use by implementing class:
347
349
357 result DirectExec(const char C[], int Retries=0);
358
360 void reactivation_avoidance_clear() throw ()
361 {m_reactivation_avoidance.clear();}
362
363 protected:
365
367 internal::reactivation_avoidance_counter m_reactivation_avoidance;
368
369 private:
370 /* A transaction goes through the following stages in its lifecycle:
371 * <ul>
372 * <li> nascent: the transaction hasn't actually begun yet. If our connection
373 * fails at this stage, it may recover and the transaction can attempt to
374 * establish itself again.
375 * <li> active: the transaction has begun. Since no commit command has been
376 * issued, abortion is implicit if the connection fails now.
377 * <li> aborted: an abort has been issued; the transaction is terminated and
378 * its changes to the database rolled back. It will accept no further
379 * commands.
380 * <li> committed: the transaction has completed successfully, meaning that a
381 * commit has been issued. No further commands are accepted.
382 * <li> in_doubt: the connection was lost at the exact wrong time, and there
383 * is no way of telling whether the transaction was committed or aborted.
384 * </ul>
385 *
386 * Checking and maintaining state machine logic is the responsibility of the
387 * base class (ie., this one).
388 */
389 enum Status
390 {
391 st_nascent,
392 st_active,
393 st_aborted,
394 st_committed,
395 st_in_doubt
396 };
397
399 void PQXX_PRIVATE activate();
400
401 void PQXX_PRIVATE CheckPendingError();
402
403 template<typename T> bool parm_is_null(T *p) const throw () { return !p; }
404 template<typename T> bool parm_is_null(T) const throw () { return false; }
405
406 friend class pqxx::internal::gate::transaction_transactionfocus;
407 void PQXX_PRIVATE RegisterFocus(internal::transactionfocus *);
408 void PQXX_PRIVATE UnregisterFocus(internal::transactionfocus *) throw ();
409 void PQXX_PRIVATE RegisterPendingError(const PGSTD::string &) throw ();
410
411 friend class pqxx::internal::gate::transaction_tablereader;
412 void PQXX_PRIVATE BeginCopyRead(const PGSTD::string &, const PGSTD::string &);
413 bool ReadCopyLine(PGSTD::string &);
414
415 friend class pqxx::internal::gate::transaction_tablewriter;
416 void PQXX_PRIVATE BeginCopyWrite(
417 const PGSTD::string &Table,
418 const PGSTD::string &Columns);
419 void WriteCopyLine(const PGSTD::string &);
420 void EndCopyWrite();
421
422 friend class pqxx::internal::gate::transaction_subtransaction;
423
424 connection_base &m_Conn;
425
426 internal::unique<internal::transactionfocus> m_Focus;
427 Status m_Status;
428 bool m_Registered;
429 PGSTD::map<PGSTD::string, PGSTD::string> m_Vars;
430 PGSTD::string m_PendingError;
431
433 transaction_base();
435 transaction_base(const transaction_base &);
437 transaction_base &operator=(const transaction_base &);
438 };
439
440 } // namespace pqxx
441
442
443 #include "pqxx/compiler-internal-post.hxx"
444
445 #endif
446