libpqxx
transaction_base.hxx
1
14#ifndef PQXX_H_TRANSACTION_BASE
15#define PQXX_H_TRANSACTION_BASE
16
17#include "pqxx/compiler-public.hxx"
18#include "pqxx/compiler-internal-pre.hxx"
19
20/* End-user programs need not include this file, unless they define their own
21 * transaction classes. This is not something the typical program should want
22 * to do.
23 *
24 * However, reading this file is worthwhile because it defines the public
25 * interface for the available transaction classes such as transaction and
26 * nontransaction.
27 */
28
29#include "pqxx/connection_base.hxx"
30#include "pqxx/internal/encoding_group.hxx"
31#include "pqxx/isolation.hxx"
32#include "pqxx/result.hxx"
33#include "pqxx/row.hxx"
34
35// Methods tested in eg. test module test01 are marked with "//[t01]".
36
37namespace pqxx
38{
39namespace internal
40{
41class sql_cursor;
42
43class PQXX_LIBEXPORT transactionfocus : public virtual namedclass
44{
45public:
47 namedclass{"transactionfocus"},
48 m_trans{t},
49 m_registered{false}
50 {
51 }
52
56
57protected:
58 void register_me();
59 void unregister_me() noexcept;
60 void reg_pending_error(const std::string &) noexcept;
61 bool registered() const noexcept { return m_registered; }
62
64
65private:
66 bool m_registered;
67};
68
69
71
73class PQXX_LIBEXPORT parameterized_invocation : statement_parameters
74{
75public:
76 PQXX_DEPRECATED parameterized_invocation(
77 connection_base &, const std::string &query);
78
79 parameterized_invocation &operator()() { add_param(); return *this; }
81 { add_binary_param(v, true); return *this; }
82 template<typename T> parameterized_invocation &operator()(const T &v)
83 { add_param(v, true); return *this; }
85 { add_binary_param(v, nonnull); return *this; }
86 template<typename T>
87 parameterized_invocation &operator()(const T &v, bool nonnull)
88 { add_param(v, nonnull); return *this; }
89
90 result exec();
91
92private:
95 =delete;
96
97 connection_base &m_home;
98 const std::string m_query;
99};
100} // namespace internal
101
102
103namespace internal
104{
105namespace gate
106{
107class transaction_subtransaction;
108class transaction_tablereader;
109class transaction_sql_cursor;
110class transaction_stream_from;
111class transaction_tablewriter;
112class transaction_stream_to;
113class transaction_transactionfocus;
114} // namespace internal::gate
115} // namespace internal
116
117
131
136class PQXX_LIBEXPORT PQXX_NOVTABLE transaction_base :
137 public virtual internal::namedclass
138{
139public:
142
146
147 virtual ~transaction_base() =0; //[t01]
148
150
162 void commit(); //[t01]
163
165
168 void abort(); //[t10]
169
175 std::string esc(const char str[]) const { return conn().esc(str); }
177 std::string esc(const char str[], size_t maxlen) const
178 { return conn().esc(str, maxlen); }
180 std::string esc(const std::string &str) const { return conn().esc(str); }
181
183
194 std::string esc_raw(const unsigned char data[], size_t len) const //[t62]
195 { return conn().esc_raw(data, len); }
197 std::string esc_raw(const std::string &) const; //[t62]
198
200
203 std::string unesc_raw(const std::string &text) const
204 { return conn().unesc_raw(text); }
205
207
210 std::string unesc_raw(const char *text) const
211 { return conn().unesc_raw(text); }
212
214
215 template<typename T> std::string quote(const T &t) const
216 { return conn().quote(t); }
217
219 std::string quote_raw(const unsigned char str[], size_t len) const
220 { return conn().quote_raw(str, len); }
221
222 std::string quote_raw(const std::string &str) const;
223
225 std::string quote_name(const std::string &identifier) const
226 { return conn().quote_name(identifier); }
227
229 std::string esc_like(const std::string &str, char escape_char='\\') const
230 { return conn().esc_like(str, escape_char); }
232
234
249 result exec(
250 const std::string &Query,
251 const std::string &Desc=std::string{}); //[t01]
252
254 const std::stringstream &Query,
255 const std::string &Desc=std::string{})
256 { return exec(Query.str(), Desc); }
257
259
265 const std::string &Query,
266 const std::string &Desc=std::string{})
267 { return exec_n(0, Query, Desc); }
268
270
276 row exec1(const std::string &Query, const std::string &Desc=std::string{})
277 { return exec_n(1, Query, Desc).front(); }
278
280
285 result exec_n(
286 size_t rows,
287 const std::string &Query,
288 const std::string &Desc=std::string{});
289
320 template<typename ...Args>
321 result exec_params(const std::string &query, Args &&...args)
322 {
323 return internal_exec_params(
324 query, internal::params(std::forward<Args>(args)...));
325 }
326
327 // Execute parameterised statement, expect a single-row result.
330 template<typename ...Args>
331 row exec_params1(const std::string &query, Args&&... args)
332 {
333 return exec_params_n(1, query, std::forward<Args>(args)...).front();
334 }
335
336 // Execute parameterised statement, expect a result with zero rows.
339 template<typename ...Args>
340 result exec_params0(const std::string &query, Args &&...args)
341 {
342 return exec_params_n(0, query, std::forward<Args>(args)...);
343 }
344
345 // Execute parameterised statement, expect exactly a given number of rows.
348 template<typename ...Args>
349 result exec_params_n(size_t rows, const std::string &query, Args &&...args)
350 {
351 const auto r = exec_params(query, std::forward<Args>(args)...);
352 check_rowcount_params(rows, r.size());
353 return r;
354 }
355
357 /* Use this to build up a parameterized statement invocation, then invoke it
358 * using @c exec()
359 *
360 * Example: @c trans.parameterized("SELECT $1 + 1")(1).exec();
361 *
362 * This is the old, pre-C++11 way of handling parameterised statements. As
363 * of libpqxx 6.0, it's made much easier using variadic templates.
364 */
366 parameterized(const std::string &query);
368
393
395 template<typename ...Args>
396 result exec_prepared(const std::string &statement, Args&&... args)
397 {
398 return internal_exec_prepared(
399 statement, internal::params(std::forward<Args>(args)...));
400 }
401
403
405 template<typename ...Args>
406 row exec_prepared1(const std::string &statement, Args&&... args)
407 {
408 return exec_prepared_n(1, statement, std::forward<Args>(args)...).front();
409 }
410
412
414 template<typename ...Args>
415 result exec_prepared0(const std::string &statement, Args&&... args)
416 {
417 return exec_prepared_n(0, statement, std::forward<Args>(args)...);
418 }
419
421
424 template<typename ...Args>
426 size_t rows,
427 const std::string &statement,
428 Args&&... args)
429 {
430 const auto r = exec_prepared(statement, std::forward<Args>(args)...);
431 check_rowcount_prepared(statement, rows, r.size());
432 return r;
433 }
434
436
474 PQXX_DEPRECATED prepare::invocation
475 prepared(const std::string &statement=std::string{});
476
478
484 void process_notice(const char Msg[]) const //[t14]
485 { m_conn.process_notice(Msg); }
487 void process_notice(const std::string &Msg) const //[t14]
488 { m_conn.process_notice(Msg); }
490
492 connection_base &conn() const { return m_conn; } //[t04]
493
495
502 void set_variable(const std::string &Var, const std::string &Val); //[t61]
503
505
514 std::string get_variable(const std::string &); //[t61]
515
516protected:
518
524 explicit transaction_base(connection_base &c, bool direct=true);
525
527
529 void Begin();
530
532 void End() noexcept;
533
535 virtual void do_begin() =0;
537 virtual result do_exec(const char Query[]) =0;
539 virtual void do_commit() =0;
541 virtual void do_abort() =0;
542
543 // For use by implementing class:
544
546
554 result direct_exec(const char C[], int Retries=0);
555
557 void reactivation_avoidance_clear() noexcept
558 {m_reactivation_avoidance.clear();}
559
560protected:
562
565
566private:
567 /* A transaction goes through the following stages in its lifecycle:
568 * <ul>
569 * <li> nascent: the transaction hasn't actually begun yet. If our connection
570 * fails at this stage, it may recover and the transaction can attempt to
571 * establish itself again.
572 * <li> active: the transaction has begun. Since no commit command has been
573 * issued, abortion is implicit if the connection fails now.
574 * <li> aborted: an abort has been issued; the transaction is terminated and
575 * its changes to the database rolled back. It will accept no further
576 * commands.
577 * <li> committed: the transaction has completed successfully, meaning that a
578 * commit has been issued. No further commands are accepted.
579 * <li> in_doubt: the connection was lost at the exact wrong time, and there
580 * is no way of telling whether the transaction was committed or aborted.
581 * </ul>
582 *
583 * Checking and maintaining state machine logic is the responsibility of the
584 * base class (ie., this one).
585 */
586 enum Status
587 {
588 st_nascent,
589 st_active,
590 st_aborted,
591 st_committed,
592 st_in_doubt
593 };
594
596 PQXX_PRIVATE void activate();
597
598 PQXX_PRIVATE void CheckPendingError();
599
600 template<typename T> bool parm_is_null(T *p) const noexcept
601 { return p == nullptr; }
602 template<typename T> bool parm_is_null(T) const noexcept
603 { return false; }
604
605 result internal_exec_prepared(
606 const std::string &statement,
607 const internal::params &args);
608
609 result internal_exec_params(
610 const std::string &query,
611 const internal::params &args);
612
614 void check_rowcount_prepared(
615 const std::string &statement,
616 size_t expected_rows,
617 size_t actual_rows);
618
620 void check_rowcount_params(
621 size_t expected_rows, size_t actual_rows);
622
623 friend class pqxx::internal::gate::transaction_transactionfocus;
624 PQXX_PRIVATE void register_focus(internal::transactionfocus *);
625 PQXX_PRIVATE void unregister_focus(internal::transactionfocus *) noexcept;
626 PQXX_PRIVATE void register_pending_error(const std::string &) noexcept;
627
628 friend class pqxx::internal::gate::transaction_tablereader;
629 friend class pqxx::internal::gate::transaction_stream_from;
630 PQXX_PRIVATE void BeginCopyRead(const std::string &, const std::string &);
631 bool read_copy_line(std::string &);
632
633 friend class pqxx::internal::gate::transaction_tablewriter;
634 friend class pqxx::internal::gate::transaction_stream_to;
635 PQXX_PRIVATE void BeginCopyWrite(
636 const std::string &Table,
637 const std::string &Columns);
638 void write_copy_line(const std::string &);
639 void end_copy_write();
640
641 friend class pqxx::internal::gate::transaction_subtransaction;
642
643 connection_base &m_conn;
644
646 Status m_status = st_nascent;
647 bool m_registered = false;
648 std::map<std::string, std::string> m_vars;
649 std::string m_pending_error;
650};
651
652} // namespace pqxx
653
654#include "pqxx/compiler-internal-post.hxx"
655#endif
std::string esc(const char str[]) const
Escape string for use as SQL string literal in this transaction.
Definition: transaction_base.hxx:175
STL namespace.
The home of all libpqxx classes, functions, templates, etc.
Definition: array.hxx:26
Binary data corresponding to PostgreSQL's "BYTEA" binary-string type.
Definition: binarystring.hxx:54
Definition: connection_base.hxx:49
connection_base abstract base class; represents a connection to a database.
Definition: connection_base.hxx:140
Traits class to describe an isolation level; primarly for libpqxx's own use.
Definition: isolation.hxx:66
Helper class for passing parameters to, and executing, prepared statements.
Definition: prepared_statement.hxx:82
Result set containing data returned by a query or command.
Definition: result.hxx:70
void clear() noexcept
Definition: result.hxx:121
Reference to one row in a result.
Definition: row.hxx:41
reference front() const noexcept
Definition: row.cxx:59
Definition: transaction_base.hxx:44
transactionfocus(const transactionfocus &)=delete
transactionfocus & operator=(const transactionfocus &)=delete
transactionfocus(transaction_base &t)
Definition: transaction_base.hxx:46
transaction_base & m_trans
Definition: transaction_base.hxx:63
Helper class to construct an invocation of a parameterised statement.
Definition: transaction_base.hxx:74
parameterized_invocation & operator()(const binarystring &v, bool nonnull)
Definition: transaction_base.hxx:84
parameterized_invocation & operator()(const binarystring &v)
Definition: transaction_base.hxx:80
parameterized_invocation & operator()(const T &v)
Definition: transaction_base.hxx:82
parameterized_invocation & operator()()
Definition: transaction_base.hxx:79
parameterized_invocation & operator()(const T &v, bool nonnull)
Definition: transaction_base.hxx:87
Interface definition (and common code) for "transaction" classes.
Definition: transaction_base.hxx:138
result exec_params(const std::string &query, Args &&...args)
Execute an SQL statement with parameters.
Definition: transaction_base.hxx:321
std::string quote_raw(const unsigned char str[], size_t len) const
Binary-escape and quote a binarystring for use as an SQL constant.
Definition: transaction_base.hxx:219
result exec_params_n(size_t rows, const std::string &query, Args &&...args)
Definition: transaction_base.hxx:349
std::string esc(const char str[], size_t maxlen) const
Escape string for use as SQL string literal in this transaction.
Definition: transaction_base.hxx:177
result exec(const std::stringstream &Query, const std::string &Desc=std::string{})
Definition: transaction_base.hxx:253
std::string quote(const T &t) const
Represent object as SQL string, including quoting & escaping.
Definition: transaction_base.hxx:215
transaction_base(const transaction_base &)=delete
result exec_prepared0(const std::string &statement, Args &&... args)
Execute a prepared statement, and expect a result with zero rows.
Definition: transaction_base.hxx:415
result exec_prepared(const std::string &statement, Args &&... args)
Execute a prepared statement, with optional arguments.
Definition: transaction_base.hxx:396
std::string esc_raw(const unsigned char data[], size_t len) const
Escape binary data for use as SQL string literal in this transaction.
Definition: transaction_base.hxx:194
result exec0(const std::string &Query, const std::string &Desc=std::string{})
Execute query, which should zero rows of data.
Definition: transaction_base.hxx:264
transaction_base & operator=(const transaction_base &)=delete
result exec_prepared_n(size_t rows, const std::string &statement, Args &&... args)
Execute a prepared statement, expect a result with given number of rows.
Definition: transaction_base.hxx:425
connection_base & conn() const
Connection this transaction is running in.
Definition: transaction_base.hxx:492
void process_notice(const std::string &Msg) const
Have connection process warning message.
Definition: transaction_base.hxx:487
void process_notice(const char Msg[]) const
Have connection process warning message.
Definition: transaction_base.hxx:484
row exec_params1(const std::string &query, Args &&... args)
Definition: transaction_base.hxx:331
std::string unesc_raw(const std::string &text) const
Unescape binary data, e.g. from a table field or notification payload.
Definition: transaction_base.hxx:203
result exec_params0(const std::string &query, Args &&...args)
Definition: transaction_base.hxx:340
std::string esc(const std::string &str) const
Escape string for use as SQL string literal in this transaction.
Definition: transaction_base.hxx:180
std::string quote_name(const std::string &identifier) const
Escape an SQL identifier for use in a query.
Definition: transaction_base.hxx:225
row exec_prepared1(const std::string &statement, Args &&... args)
Execute a prepared statement, and expect a single-row result.
Definition: transaction_base.hxx:406
std::string unesc_raw(const char *text) const
Unescape binary data, e.g. from a table field or notification payload.
Definition: transaction_base.hxx:210
row exec1(const std::string &Query, const std::string &Desc=std::string{})
Execute query returning a single row of data.
Definition: transaction_base.hxx:276
internal::reactivation_avoidance_counter m_reactivation_avoidance
Resources allocated in this transaction that make reactivation impossible.
Definition: transaction_base.hxx:564
std::string esc_like(const std::string &str, char escape_char='\\') const
Escape string for literal LIKE match.
Definition: transaction_base.hxx:229
Helper base class: object descriptions for error messages and such.
Definition: util.hxx:234
Ensure proper opening/closing of GUEST objects related to a "host" object.
Definition: util.hxx:275