transaction_base.hxx
#ifndef PQXX_H_TRANSACTION_BASE
#define PQXX_H_TRANSACTION_BASE
#include "pqxx/compiler-public.hxx"
#include "pqxx/compiler-internal-pre.hxx"
/* End-user programs need not include this file, unless they define their own
* transaction classes. This is not something the typical program should want
* to do.
*
* However, reading this file is worthwhile because it defines the public
* interface for the available transaction classes such as transaction and
* nontransaction.
*/
#include "pqxx/connection_base.hxx"
#include "pqxx/internal/encoding_group.hxx"
#include "pqxx/isolation.hxx"
#include "pqxx/result.hxx"
#include "pqxx/row.hxx"
// Methods tested in eg. test module test01 are marked with "//[t01]".
namespace pqxx
{
namespace internal
{
class sql_cursor;
class PQXX_LIBEXPORT transactionfocus : public virtual namedclass
{
public:
explicit transactionfocus(transaction_base &t) :
namedclass{"transactionfocus"},
m_trans{t},
m_registered{false}
{
}
transactionfocus() =delete;
transactionfocus(const transactionfocus &) =delete;
transactionfocus &operator=(const transactionfocus &) =delete;
protected:
void register_me();
void unregister_me() noexcept;
void reg_pending_error(const std::string &) noexcept;
bool registered() const noexcept { return m_registered; }
transaction_base &m_trans;
private:
bool m_registered;
};
class PQXX_LIBEXPORT parameterized_invocation : statement_parameters
{
public:
PQXX_DEPRECATED parameterized_invocation(
connection_base &, const std::string &query);
parameterized_invocation &operator()() { add_param(); return *this; }
parameterized_invocation &operator()(const binarystring &v)
{ add_binary_param(v, true); return *this; }
template<typename T> parameterized_invocation &operator()(const T &v)
{ add_param(v, true); return *this; }
parameterized_invocation &operator()(const binarystring &v, bool nonnull)
{ add_binary_param(v, nonnull); return *this; }
template<typename T>
parameterized_invocation &operator()(const T &v, bool nonnull)
{ add_param(v, nonnull); return *this; }
result exec();
private:
parameterized_invocation &operator=(const parameterized_invocation &)
=delete;
connection_base &m_home;
const std::string m_query;
};
} // namespace internal
namespace internal
{
namespace gate
{
class transaction_subtransaction;
class transaction_tablereader;
class transaction_sql_cursor;
class transaction_stream_from;
class transaction_tablewriter;
class transaction_stream_to;
class transaction_transactionfocus;
} // namespace internal::gate
} // namespace internal
class PQXX_LIBEXPORT PQXX_NOVTABLE transaction_base :
public virtual internal::namedclass
{
public:
using isolation_tag = isolation_traits<read_committed>;
transaction_base() =delete;
transaction_base(const transaction_base &) =delete;
transaction_base &operator=(const transaction_base &) =delete;
virtual ~transaction_base() =0; //[t01]
void commit(); //[t01]
void abort(); //[t10]
std::string esc(const char str[]) const { return conn().esc(str); }
std::string esc(const char str[], size_t maxlen) const
{ return conn().esc(str, maxlen); }
std::string esc(const std::string &str) const { return conn().esc(str); }
std::string esc_raw(const unsigned char data[], size_t len) const //[t62]
{ return conn().esc_raw(data, len); }
std::string esc_raw(const std::string &) const; //[t62]
std::string unesc_raw(const std::string &text) const
{ return conn().unesc_raw(text); }
std::string unesc_raw(const char *text) const
{ return conn().unesc_raw(text); }
template<typename T> std::string quote(const T &t) const
{ return conn().quote(t); }
std::string quote_raw(const unsigned char str[], size_t len) const
{ return conn().quote_raw(str, len); }
std::string quote_raw(const std::string &str) const;
std::string quote_name(const std::string &identifier) const
{ return conn().quote_name(identifier); }
std::string esc_like(const std::string &str, char escape_char='\\') const
{ return conn().esc_like(str, escape_char); }
result exec(
const std::string &Query,
const std::string &Desc=std::string{}); //[t01]
result exec(
const std::stringstream &Query,
const std::string &Desc=std::string{})
{ return exec(Query.str(), Desc); }
result exec0(
const std::string &Query,
const std::string &Desc=std::string{})
{ return exec_n(0, Query, Desc); }
row exec1(const std::string &Query, const std::string &Desc=std::string{})
{ return exec_n(1, Query, Desc).front(); }
result exec_n(
size_t rows,
const std::string &Query,
const std::string &Desc=std::string{});
template<typename ...Args>
result exec_params(const std::string &query, Args &&...args)
{
return internal_exec_params(
query, internal::params(std::forward<Args>(args)...));
}
// Execute parameterised statement, expect a single-row result.
template<typename ...Args>
row exec_params1(const std::string &query, Args&&... args)
{
return exec_params_n(1, query, std::forward<Args>(args)...).front();
}
// Execute parameterised statement, expect a result with zero rows.
template<typename ...Args>
result exec_params0(const std::string &query, Args &&...args)
{
return exec_params_n(0, query, std::forward<Args>(args)...);
}
// Execute parameterised statement, expect exactly a given number of rows.
template<typename ...Args>
result exec_params_n(size_t rows, const std::string &query, Args &&...args)
{
const auto r = exec_params(query, std::forward<Args>(args)...);
check_rowcount_params(rows, r.size());
return r;
}
/* Use this to build up a parameterized statement invocation, then invoke it
* using @c exec()
*
* Example: @c trans.parameterized("SELECT $1 + 1")(1).exec();
*
* This is the old, pre-C++11 way of handling parameterised statements. As
* of libpqxx 6.0, it's made much easier using variadic templates.
*/
PQXX_DEPRECATED internal::parameterized_invocation
parameterized(const std::string &query);
template<typename ...Args>
result exec_prepared(const std::string &statement, Args&&... args)
{
return internal_exec_prepared(
statement, internal::params(std::forward<Args>(args)...));
}
template<typename ...Args>
row exec_prepared1(const std::string &statement, Args&&... args)
{
return exec_prepared_n(1, statement, std::forward<Args>(args)...).front();
}
template<typename ...Args>
result exec_prepared0(const std::string &statement, Args&&... args)
{
return exec_prepared_n(0, statement, std::forward<Args>(args)...);
}
template<typename ...Args>
result exec_prepared_n(
size_t rows,
const std::string &statement,
Args&&... args)
{
const auto r = exec_prepared(statement, std::forward<Args>(args)...);
check_rowcount_prepared(statement, rows, r.size());
return r;
}
PQXX_DEPRECATED prepare::invocation
prepared(const std::string &statement=std::string{});
void process_notice(const char Msg[]) const //[t14]
{ m_conn.process_notice(Msg); }
void process_notice(const std::string &Msg) const //[t14]
{ m_conn.process_notice(Msg); }
connection_base &conn() const { return m_conn; } //[t04]
void set_variable(const std::string &Var, const std::string &Val); //[t61]
std::string get_variable(const std::string &); //[t61]
protected:
explicit transaction_base(connection_base &c, bool direct=true);
void Begin();
void End() noexcept;
virtual void do_begin() =0;
virtual result do_exec(const char Query[]) =0;
virtual void do_commit() =0;
virtual void do_abort() =0;
// For use by implementing class:
result direct_exec(const char C[], int Retries=0);
void reactivation_avoidance_clear() noexcept
{m_reactivation_avoidance.clear();}
protected:
internal::reactivation_avoidance_counter m_reactivation_avoidance;
private:
/* A transaction goes through the following stages in its lifecycle:
* <ul>
* <li> nascent: the transaction hasn't actually begun yet. If our connection
* fails at this stage, it may recover and the transaction can attempt to
* establish itself again.
* <li> active: the transaction has begun. Since no commit command has been
* issued, abortion is implicit if the connection fails now.
* <li> aborted: an abort has been issued; the transaction is terminated and
* its changes to the database rolled back. It will accept no further
* commands.
* <li> committed: the transaction has completed successfully, meaning that a
* commit has been issued. No further commands are accepted.
* <li> in_doubt: the connection was lost at the exact wrong time, and there
* is no way of telling whether the transaction was committed or aborted.
* </ul>
*
* Checking and maintaining state machine logic is the responsibility of the
* base class (ie., this one).
*/
enum Status
{
st_nascent,
st_active,
st_aborted,
st_committed,
st_in_doubt
};
PQXX_PRIVATE void activate();
PQXX_PRIVATE void CheckPendingError();
template<typename T> bool parm_is_null(T *p) const noexcept
{ return p == nullptr; }
template<typename T> bool parm_is_null(T) const noexcept
{ return false; }
result internal_exec_prepared(
const std::string &statement,
const internal::params &args);
result internal_exec_params(
const std::string &query,
const internal::params &args);
void check_rowcount_prepared(
const std::string &statement,
size_t expected_rows,
size_t actual_rows);
void check_rowcount_params(
size_t expected_rows, size_t actual_rows);
friend class pqxx::internal::gate::transaction_transactionfocus;
PQXX_PRIVATE void register_focus(internal::transactionfocus *);
PQXX_PRIVATE void unregister_focus(internal::transactionfocus *) noexcept;
PQXX_PRIVATE void register_pending_error(const std::string &) noexcept;
friend class pqxx::internal::gate::transaction_tablereader;
friend class pqxx::internal::gate::transaction_stream_from;
PQXX_PRIVATE void BeginCopyRead(const std::string &, const std::string &);
bool read_copy_line(std::string &);
friend class pqxx::internal::gate::transaction_tablewriter;
friend class pqxx::internal::gate::transaction_stream_to;
PQXX_PRIVATE void BeginCopyWrite(
const std::string &Table,
const std::string &Columns);
void write_copy_line(const std::string &);
void end_copy_write();
friend class pqxx::internal::gate::transaction_subtransaction;
connection_base &m_conn;
internal::unique<internal::transactionfocus> m_focus;
Status m_status = st_nascent;
bool m_registered = false;
std::map<std::string, std::string> m_vars;
std::string m_pending_error;
};
} // namespace pqxx
#include "pqxx/compiler-internal-post.hxx"
#endif
pqxx::transaction_base::set_variable
void set_variable(const std::string &Var, const std::string &Val)
Set session variable in this connection.
Definition: transaction_base.cxx:367
pqxx::transaction_base::prepared
prepare::invocation prepared(const std::string &statement=std::string{})
Execute prepared statement.
Definition: transaction_base.cxx:332
pqxx::transaction_base::exec0
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
pqxx::result::size
PQXX_PURE size_type size() const noexcept
Definition: result.cxx:94
pqxx::transaction_base::esc_like
std::string esc_like(const std::string &str, char escape_char='\\') const
Escape string for literal LIKE match.
Definition: transaction_base.hxx:229
pqxx::internal::transactionfocus::register_me
void register_me()
Definition: transaction_base.cxx:555
pqxx::internal::parameterized_invocation
Helper class to construct an invocation of a parameterised statement.
Definition: transaction_base.hxx:73
pqxx::transaction_base::exec
result exec(const std::string &Query, const std::string &Desc=std::string{})
Execute query.
Definition: transaction_base.cxx:249
pqxx::transaction_base::~transaction_base
virtual ~transaction_base()=0
Definition: transaction_base.cxx:69
pqxx::transaction_base::exec_params1
row exec_params1(const std::string &query, Args &&... args)
Definition: transaction_base.hxx:331
pqxx::internal
Private namespace for libpqxx's internal use; do not access.
Definition: connection_base.hxx:43
pqxx::transaction_base::get_variable
std::string get_variable(const std::string &)
Get currently applicable value of variable.
Definition: transaction_base.cxx:378
pqxx::transaction_base::exec_prepared0
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
pqxx::internal::transactionfocus::reg_pending_error
void reg_pending_error(const std::string &) noexcept
Definition: transaction_base.cxx:571
pqxx::transaction_base::process_notice
void process_notice(const std::string &Msg) const
Have connection process warning message.
Definition: transaction_base.hxx:487
pqxx::transaction_base::exec_prepared1
row exec_prepared1(const std::string &statement, Args &&... args)
Execute a prepared statement, and expect a single-row result.
Definition: transaction_base.hxx:406
pqxx::internal::parameterized_invocation::exec
result exec()
Definition: transaction_base.cxx:40
pqxx::transaction_base::parameterized
internal::parameterized_invocation parameterized(const std::string &query)
Parameterize a statement.
Definition: transaction_base.cxx:323
pqxx::transaction_base::exec_prepared
result exec_prepared(const std::string &statement, Args &&... args)
Execute a prepared statement, with optional arguments.
Definition: transaction_base.hxx:396
pqxx::failure
Run-time failure encountered by libpqxx, similar to std::runtime_error.
Definition: except.hxx:89
pqxx::transaction_base::esc
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
pqxx::result
Result set containing data returned by a query or command.
Definition: result.hxx:69
pqxx::internal::parameterized_invocation::operator()
parameterized_invocation & operator()(const T &v, bool nonnull)
Definition: transaction_base.hxx:87
pqxx::internal::parameterized_invocation::operator()
parameterized_invocation & operator()(const T &v)
Definition: transaction_base.hxx:82
pqxx::transaction_base::abort
void abort()
Abort the transaction.
Definition: transaction_base.cxx:174
pqxx::transaction_base::Begin
void Begin()
Begin transaction (to be called by implementing class)
Definition: transaction_base.cxx:386
pqxx::transaction_base::exec_params_n
result exec_params_n(size_t rows, const std::string &query, Args &&...args)
Definition: transaction_base.hxx:349
pqxx::transaction_base::m_reactivation_avoidance
internal::reactivation_avoidance_counter m_reactivation_avoidance
Resources allocated in this transaction that make reactivation impossible.
Definition: transaction_base.hxx:564
pqxx::internal::transactionfocus::m_trans
transaction_base & m_trans
Definition: transaction_base.hxx:63
pqxx::transaction_base::quote_raw
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
pqxx::internal::parameterized_invocation::parameterized_invocation
parameterized_invocation(connection_base &, const std::string &query)
Definition: transaction_base.cxx:31
pqxx::transaction_base::commit
void commit()
Commit the transaction.
Definition: transaction_base.cxx:98
pqxx::prepare::invocation
Helper class for passing parameters to, and executing, prepared statements.
Definition: prepared_statement.hxx:81
pqxx::transaction_base::End
void End() noexcept
End transaction. To be called by implementing class' destructor.
Definition: transaction_base.cxx:408
pqxx::internal::parameterized_invocation::operator()
parameterized_invocation & operator()()
Definition: transaction_base.hxx:79
pqxx::internal::parameterized_invocation::operator()
parameterized_invocation & operator()(const binarystring &v)
Definition: transaction_base.hxx:80
pqxx::unexpected_rows
Query returned an unexpected number of rows.
Definition: except.hxx:262
pqxx::internal::reactivation_avoidance_counter
Definition: connection_base.hxx:48
pqxx::transaction_base::transaction_base
transaction_base()=delete
pqxx::internal::parameterized_invocation::operator()
parameterized_invocation & operator()(const binarystring &v, bool nonnull)
Definition: transaction_base.hxx:84
pqxx::transaction_base::quote_name
std::string quote_name(const std::string &identifier) const
Escape an SQL identifier for use in a query.
Definition: transaction_base.hxx:225
pqxx::internal_error
Internal error in libpqxx library.
Definition: except.hxx:207
pqxx::binarystring
Binary data corresponding to PostgreSQL's "BYTEA" binary-string type.
Definition: binarystring.hxx:53
pqxx::broken_connection
Exception class for lost or failed backend connection.
Definition: except.hxx:118
pqxx::transaction_base::quote
std::string quote(const T &t) const
Represent object as SQL string, including quoting & escaping.
Definition: transaction_base.hxx:215
pqxx::transaction_base::unesc_raw
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
pqxx::transaction_base::direct_exec
result direct_exec(const char C[], int Retries=0)
Execute query on connection directly.
Definition: transaction_base.cxx:462
pqxx::transaction_base::conn
connection_base & conn() const
Connection this transaction is running in.
Definition: transaction_base.hxx:492
pqxx::transaction_base::exec_params
result exec_params(const std::string &query, Args &&...args)
Execute an SQL statement with parameters.
Definition: transaction_base.hxx:321
pqxx::internal::namedclass
Helper base class: object descriptions for error messages and such.
Definition: util.hxx:233
pqxx::row::front
reference front() const noexcept
Definition: row.cxx:59
pqxx::transaction_base::esc
std::string esc(const std::string &str) const
Escape string for use as SQL string literal in this transaction.
Definition: transaction_base.hxx:180
pqxx::transaction_base::esc_raw
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
pqxx::transaction_base::exec_n
result exec_n(size_t rows, const std::string &Query, const std::string &Desc=std::string{})
Execute query, expect given number of rows.
Definition: transaction_base.cxx:277
pqxx::transaction_base::exec_prepared_n
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
pqxx::result::clear
void clear() noexcept
Definition: result.hxx:121
pqxx::internal::transactionfocus
Definition: transaction_base.hxx:43
pqxx::to_string
std::string to_string(const field &Obj)
Convert a field to a string.
Definition: result.cxx:451
pqxx::transaction_base::exec_params0
result exec_params0(const std::string &query, Args &&...args)
Definition: transaction_base.hxx:340
pqxx::transaction_base::unesc_raw
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
pqxx::connection_base
connection_base abstract base class; represents a connection to a database.
Definition: connection_base.hxx:139
pqxx::transaction_base::exec1
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
pqxx::internal::transactionfocus::unregister_me
void unregister_me() noexcept
Definition: transaction_base.cxx:563
pqxx::in_doubt_error
"Help, I don't know whether transaction was committed successfully!"
Definition: except.hxx:159
pqxx::transaction_base
Interface definition (and common code) for "transaction" classes.
Definition: transaction_base.hxx:136
pqxx
The home of all libpqxx classes, functions, templates, etc.
Definition: array.hxx:25
pqxx::row
Reference to one row in a result.
Definition: row.hxx:40
pqxx::internal::transactionfocus::transactionfocus
transactionfocus(transaction_base &t)
Definition: transaction_base.hxx:46
pqxx::usage_error
Error in usage of libpqxx library, similar to std::logic_error.
Definition: except.hxx:218
pqxx::transaction_base::exec
result exec(const std::stringstream &Query, const std::string &Desc=std::string{})
Definition: transaction_base.hxx:253
pqxx::isolation_traits
Traits class to describe an isolation level; primarly for libpqxx's own use.
Definition: isolation.hxx:65
pqxx::internal::unique
Ensure proper opening/closing of GUEST objects related to a "host" object.
Definition: util.hxx:274