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 
37 namespace pqxx
38 {
39 namespace internal
40 {
41 class sql_cursor;
42 
43 class PQXX_LIBEXPORT transactionfocus : public virtual namedclass
44 {
45 public:
47  namedclass{"transactionfocus"},
48  m_trans{t},
49  m_registered{false}
50  {
51  }
52 
53  transactionfocus() =delete;
54  transactionfocus(const transactionfocus &) =delete;
55  transactionfocus &operator=(const transactionfocus &) =delete;
56 
57 protected:
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 
65 private:
66  bool m_registered;
67 };
68 
69 
71 
73 class PQXX_LIBEXPORT parameterized_invocation : statement_parameters
74 {
75 public:
76  PQXX_DEPRECATED parameterized_invocation(
77  connection_base &, const std::string &query);
78 
79  parameterized_invocation &operator()() { add_param(); return *this; }
80  parameterized_invocation &operator()(const binarystring &v)
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; }
84  parameterized_invocation &operator()(const binarystring &v, bool nonnull)
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 
92 private:
94  parameterized_invocation &operator=(const parameterized_invocation &)
95  =delete;
96 
97  connection_base &m_home;
98  const std::string m_query;
99 };
100 } // namespace internal
101 
102 
103 namespace internal
104 {
105 namespace gate
106 {
107 class transaction_subtransaction;
108 class transaction_tablereader;
109 class transaction_sql_cursor;
110 class transaction_stream_from;
111 class transaction_tablewriter;
112 class transaction_stream_to;
113 class transaction_transactionfocus;
114 } // namespace internal::gate
115 } // namespace internal
116 
117 
130 
136 class PQXX_LIBEXPORT PQXX_NOVTABLE transaction_base :
137  public virtual internal::namedclass
138 {
139 public:
142 
143  transaction_base() =delete;
144  transaction_base(const transaction_base &) =delete;
145  transaction_base &operator=(const transaction_base &) =delete;
146 
147  virtual ~transaction_base() =0; //[t01]
148 
150 
162  void commit(); //[t01]
163 
165 
168  void abort(); //[t10]
169 
174  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 
319  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  */
365  PQXX_DEPRECATED internal::parameterized_invocation
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 
483  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 
516 protected:
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 
558  {m_reactivation_avoidance.clear();}
559 
560 protected:
562 
565 
566 private:
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
parameterized_invocation & operator()(const T &v)
Definition: transaction_base.hxx:82
Definition: transaction_base.hxx:43
result exec(const std::stringstream &Query, const std::string &Desc=std::string{})
Definition: transaction_base.hxx:253
parameterized_invocation & operator()(const binarystring &v, bool nonnull)
Definition: transaction_base.hxx:84
std::string quote_name(const std::string &identifier) const
Escape an SQL identifier for use in a query.
Definition: transaction_base.hxx:225
Helper class for passing parameters to, and executing, prepared statements.
Definition: prepared_statement.hxx:81
Helper base class: object descriptions for error messages and such.
Definition: util.hxx:233
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
std::string quote(const T &t) const
Represent object as SQL string, including quoting & escaping.
Definition: transaction_base.hxx:215
result exec_params0(const std::string &query, Args &&...args)
Definition: transaction_base.hxx:340
Result set containing data returned by a query or command.
Definition: result.hxx:69
parameterized_invocation & operator()(const binarystring &v)
Definition: transaction_base.hxx:80
bool registered() const noexcept
Definition: transaction_base.hxx:61
connection_base & conn() const
Connection this transaction is running in.
Definition: transaction_base.hxx:492
connection_base abstract base class; represents a connection to a database.
Definition: connection_base.hxx:139
Interface definition (and common code) for "transaction" classes.
Definition: transaction_base.hxx:136
Reference to one row in a result.
Definition: row.hxx:40
Binary data corresponding to PostgreSQL&#39;s "BYTEA" binary-string type.
Definition: binarystring.hxx:53
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
std::string esc_like(const std::string &str, char escape_char='\\') const
Escape string for literal LIKE match.
Definition: transaction_base.hxx:229
Definition: connection_base.hxx:48
Helper class to construct an invocation of a parameterised statement.
Definition: transaction_base.hxx:73
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
reference front() const noexcept
Definition: row.cxx:59
Traits class to describe an isolation level; primarly for libpqxx&#39;s own use.
Definition: isolation.hxx:65
parameterized_invocation & operator()()
Definition: transaction_base.hxx:79
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
Ensure proper opening/closing of GUEST objects related to a "host" object.
Definition: util.hxx:274
void reactivation_avoidance_clear() noexcept
Forget about any reactivation-blocking resources we tried to allocate.
Definition: transaction_base.hxx:557
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
std::string esc(const std::string &str) const
Escape string for use as SQL string literal in this transaction.
Definition: transaction_base.hxx:180
transactionfocus(transaction_base &t)
Definition: transaction_base.hxx:46
row exec_params1(const std::string &query, Args &&... args)
Definition: transaction_base.hxx:331
result exec_params_n(size_t rows, const std::string &query, Args &&...args)
Definition: transaction_base.hxx:349
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 exec0(const std::string &Query, const std::string &Desc=std::string{})
Execute query, which should zero rows of data.
Definition: transaction_base.hxx:264
internal::reactivation_avoidance_counter m_reactivation_avoidance
Resources allocated in this transaction that make reactivation impossible.
Definition: transaction_base.hxx:564
row exec_prepared1(const std::string &statement, Args &&... args)
Execute a prepared statement, and expect a single-row result.
Definition: transaction_base.hxx:406
void process_notice(const std::string &Msg) const
Have connection process warning message.
Definition: transaction_base.hxx:487
The home of all libpqxx classes, functions, templates, etc.
Definition: array.hxx:25
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
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_prepared(const std::string &statement, Args &&... args)
Execute a prepared statement, with optional arguments.
Definition: transaction_base.hxx:396
parameterized_invocation & operator()(const T &v, bool nonnull)
Definition: transaction_base.hxx:87
result exec_params(const std::string &query, Args &&...args)
Execute an SQL statement with parameters.
Definition: transaction_base.hxx:321
transaction_base & m_trans
Definition: transaction_base.hxx:63