123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940 |
- /** Definition of the pqxx::connection_base abstract base class.
- *
- * pqxx::connection_base encapsulates a frontend to backend connection
- *
- * DO NOT INCLUDE THIS FILE DIRECTLY; include pqxx/connection_base instead.
- *
- * Copyright (c) 2000-2019, Jeroen T. Vermeulen.
- *
- * See COPYING for copyright license. If you did not receive a file called
- * COPYING with this source code, please notify the distributor of this mistake,
- * or contact the author.
- */
- #ifndef PQXX_H_CONNECTION_BASE
- #define PQXX_H_CONNECTION_BASE
- #include "pqxx/compiler-public.hxx"
- #include "pqxx/compiler-internal-pre.hxx"
- #include <bitset>
- #include <list>
- #include <map>
- #include <memory>
- #include "pqxx/errorhandler.hxx"
- #include "pqxx/except.hxx"
- #include "pqxx/prepared_statement.hxx"
- #include "pqxx/strconv.hxx"
- #include "pqxx/util.hxx"
- #include "pqxx/version.hxx"
- /* Use of the libpqxx library starts here.
- *
- * Everything that can be done with a database through libpqxx must go through
- * a connection object derived from connection_base.
- */
- /* Methods tested in eg. self-test program test1 are marked with "//[t01]"
- */
- namespace pqxx
- {
- namespace internal
- {
- class reactivation_avoidance_exemption;
- class sql_cursor;
- class reactivation_avoidance_counter
- {
- public:
- reactivation_avoidance_counter() =default;
- void add(int n) noexcept { m_counter += n; }
- void clear() noexcept { m_counter = 0; }
- int get() const noexcept { return m_counter; }
- private:
- int m_counter = 0;
- };
- }
- /// Encrypt password for given user.
- /** Use this when setting a new password for the user if password encryption is
- * enabled. Inputs are the username the password is for, and the plaintext
- * password.
- *
- * @return encrypted version of the password, suitable for encrypted PostgreSQL
- * authentication.
- *
- * Thus the password for a user can be changed with:
- * @code
- * void setpw(transaction_base &t, const string &user, const string &pw)
- * {
- * t.exec("ALTER USER " + user + " "
- * "PASSWORD '" + encrypt_password(user,pw) + "'");
- * }
- * @endcode
- */
- std::string PQXX_LIBEXPORT encrypt_password( //[t00]
- const std::string &user,
- const std::string &password);
- namespace internal
- {
- namespace gate
- {
- class connection_dbtransaction;
- class connection_errorhandler;
- class connection_largeobject;
- class connection_notification_receiver;
- class connection_parameterized_invocation;
- class connection_pipeline;
- class connection_prepare_invocation;
- class connection_reactivation_avoidance_exemption;
- class connection_sql_cursor;
- class connection_transaction;
- class const_connection_largeobject;
- } // namespace pqxx::internal::gate
- } // namespace pqxx::internal
- /// connection_base abstract base class; represents a connection to a database.
- /** This is the first class to look at when you wish to work with a database
- * through libpqxx. Depending on the implementing concrete child class, a
- * connection can be automatically opened when it is constructed, or when it is
- * first used, or somewhere inbetween. The connection is automatically closed
- * upon destruction (if it hasn't been closed already).
- *
- * To query or manipulate the database once connected, use one of the
- * transaction classes (see pqxx/transaction_base.hxx) or preferably the
- * transactor framework (see pqxx/transactor.hxx).
- *
- * If a network connection to the database server fails, the connection will be
- * restored automatically (although any transaction going on at the time will
- * have to be aborted). This also means that any information set in previous
- * transactions that is not stored in the database, such as temp tables or
- * connection-local variables defined with PostgreSQL's SET command, will be
- * lost. Whenever you create such state, either keept it local to one
- * transaction, where possible, or inhibit automatic reactivation of the
- * connection using the inhibit_reactivation() method.
- *
- * When a connection breaks, you will typically get a broken_connection
- * exception. This can happen at almost any point, and the details may depend
- * on which connection class (all derived from this one) you use.
- *
- * As a general rule, always avoid raw queries if libpqxx offers a dedicated
- * function for the same purpose. There may be hidden logic to hide certain
- * complications from you, such as reinstating session variables when a
- * broken or disabled connection is reactivated.
- *
- * @warning On Unix-like systems, including GNU and BSD systems, your program
- * may receive the SIGPIPE signal when the connection to the backend breaks. By
- * default this signal will abort your program. Use "signal(SIGPIPE, SIG_IGN)"
- * if you want your program to continue running after a connection fails.
- */
- class PQXX_LIBEXPORT connection_base
- {
- public:
- /// Explicitly close connection.
- void disconnect() noexcept; //[t02]
- /// Is this connection open at the moment?
- /** @warning This function is @b not needed in most code. Resist the
- * temptation to check it after opening a connection; instead, rely on the
- * broken_connection exception that will be thrown on connection failure.
- */
- bool PQXX_PURE is_open() const noexcept; //[t01]
- /**
- * @name Activation
- *
- * @warning Connection deactivation/reactivation will probably be removed in
- * libpqxx 7. If your application relies on an ability to "put connections
- * to sleep" and reactivate them later, you'll need to wrap them in some way
- * to handle this.
- *
- * Connections can be temporarily deactivated, or they can break because of
- * overly impatient firewalls dropping TCP connections. Where possible,
- * libpqxx will try to re-activate these when resume using them, or you can
- * wake them up explicitly. You probably won't need this feature, but you
- * should be aware of it.
- */
- //@{
- /// @deprecated Explicitly activate deferred or deactivated connection.
- /** Use of this method is entirely optional. Whenever a connection is used
- * while in a deferred or deactivated state, it will transparently try to
- * bring itself into an activated state. This function is best viewed as an
- * explicit hint to the connection that "if you're not in an active state, now
- * would be a good time to get into one." Whether a connection is currently
- * in an active state or not makes no real difference to its functionality.
- * There is also no particular need to match calls to activate() with calls to
- * deactivate(). A good time to call activate() might be just before you
- * first open a transaction on a lazy connection.
- */
- PQXX_DEPRECATED void activate(); //[t12]
- /// @deprecated Explicitly deactivate connection.
- /** Like its counterpart activate(), this method is entirely optional.
- * Calling this function really only makes sense if you won't be using this
- * connection for a while and want to reduce the number of open connections on
- * the database server.
- * There is no particular need to match or pair calls to deactivate() with
- * calls to activate(), but calling deactivate() during a transaction is an
- * error.
- */
- PQXX_DEPRECATED void deactivate(); //[t12]
- /// @deprecated Disallow (or permit) connection recovery
- /** A connection whose underlying socket is not currently connected to the
- * server will normally (re-)establish communication with the server whenever
- * needed, or when the client program requests it (although for reasons of
- * integrity, never inside a transaction; but retrying the whole transaction
- * may implicitly cause the connection to be restored). In normal use this is
- * quite a convenient thing to have and presents a simple, safe, predictable
- * interface.
- *
- * There is at least one situation where this feature is not desirable,
- * however. Although most session state (prepared statements, session
- * variables) is automatically restored to its working state upon connection
- * reactivation, temporary tables and so-called WITH HOLD cursors (which can
- * live outside transactions) are not.
- *
- * Cursors that live outside transactions are automatically handled, and the
- * library will quietly ignore requests to deactivate or reactivate
- * connections while they exist; it does not want to give you the illusion of
- * being back in your transaction when in reality you just dropped a cursor.
- * With temporary tables this is not so easy: there is no easy way for the
- * library to detect their creation or track their lifetimes.
- *
- * So if your program uses temporary tables, and any part of this use happens
- * outside of any database transaction (or spans multiple transactions), some
- * of the work you have done on these tables may unexpectedly be undone if the
- * connection is broken or deactivated while any of these tables exists, and
- * then reactivated or implicitly restored before you are finished with it.
- *
- * If this describes any part of your program, guard it against unexpected
- * reconnections by inhibiting reconnection at the beginning. And if you want
- * to continue doing work on the connection afterwards that no longer requires
- * the temp tables, you can permit it again to get the benefits of connection
- * reactivation for the remainder of the program.
- *
- * @param inhibit should reactivation be inhibited from here on?
- *
- * @warning Some connection types (the lazy and asynchronous types) defer
- * completion of the socket-level connection until it is actually needed by
- * the client program. Inhibiting reactivation before this connection is
- * really established will prevent these connection types from doing their
- * work. For those connection types, if you are sure that reactivation needs
- * to be inhibited before any query goes across the connection, activate() the
- * connection first. This will ensure that definite activation happens before
- * you inhibit it.
- */
- PQXX_DEPRECATED void inhibit_reactivation(bool inhibit) //[t86]
- { m_inhibit_reactivation=inhibit; }
- /// Make the connection fail. @warning Do not use this except for testing!
- /** Breaks the connection in some unspecified, horrible, dirty way to enable
- * failure testing.
- *
- * Do not use this in normal programs. This is only meant for testing.
- */
- void simulate_failure(); //[t94]
- //@}
- /// Invoke notice processor function. The message should end in newline.
- void process_notice(const char[]) noexcept; //[t14]
- /// Invoke notice processor function. Newline at end is recommended.
- void process_notice(const std::string &) noexcept; //[t14]
- /// Enable tracing to a given output stream, or nullptr to disable.
- void trace(std::FILE *) noexcept; //[t03]
- /**
- * @name Connection properties
- *
- * These are probably not of great interest, since most are derived from
- * information supplied by the client program itself, but they are included
- * for completeness.
- */
- //@{
- /// Name of database we're connected to, if any.
- /** @warning This activates the connection, which may fail with a
- * broken_connection exception.
- */
- const char *dbname(); //[t01]
- /// Database user ID we're connected under, if any.
- /** @warning This activates the connection, which may fail with a
- * broken_connection exception.
- */
- const char *username(); //[t01]
- /// Address of server, or nullptr if none specified (i.e. default or local)
- /** @warning This activates the connection, which may fail with a
- * broken_connection exception.
- */
- const char *hostname(); //[t01]
- /// Server port number we're connected to.
- /** @warning This activates the connection, which may fail with a
- * broken_connection exception.
- */
- const char *port(); //[t01]
- /// Process ID for backend process.
- /** Use with care: connections may be lost and automatically re-established
- * without your knowledge, in which case this process ID may no longer be
- * correct. You may, however, assume that this number remains constant and
- * reliable within the span of a successful backend transaction. If the
- * transaction fails, which may be due to a lost connection, then this number
- * will have become invalid at some point within the transaction.
- *
- * @return Process identifier, or 0 if not currently connected.
- */
- int PQXX_PURE backendpid() const noexcept; //[t01]
- /// Socket currently used for connection, or -1 for none. Use with care!
- /** Query the current socket number. This is intended for event loops based
- * on functions such as select() or poll(), where multiple file descriptors
- * are watched.
- *
- * Please try to stay away from this function. It is really only meant for
- * event loops that need to wait on more than one file descriptor. If all you
- * need is to block until a notification arrives, for instance, use
- * await_notification(). If you want to issue queries and retrieve results in
- * nonblocking fashion, check out the pipeline class.
- *
- * @warning Don't store this value anywhere, and always be prepared for the
- * possibility that, at any given time, there may not be a socket! The
- * socket may change or even go away or be established during any invocation
- * of libpqxx code on the connection, no matter how trivial.
- */
- int PQXX_PURE sock() const noexcept; //[t87]
- /**
- * @name Capabilities
- *
- * Some functionality may only be available in certain versions of the
- * backend, or only when speaking certain versions of the communications
- * protocol that connects us to the backend.
- */
- //@{
- /// Session capabilities.
- /** No capabilities are defined at the moment: all capabilities that older
- * versions checked for are now always supported.
- */
- enum capability
- {
- /// Not a capability value; end-of-enumeration marker
- cap_end,
- };
- /// Does this connection seem to support the given capability?
- /** Don't try to be smart by caching this information anywhere. Obtaining it
- * is quite fast (especially after the first time) and what's more, a
- * capability may "suddenly" appear or disappear if the connection is broken
- * or deactivated, and then restored. This may happen silently any time no
- * backend transaction is active; if it turns out that the server was upgraded
- * or restored from an older backup, or the new connection goes to a different
- * backend, then the restored session may have different capabilities than
- * were available previously.
- *
- * Some guesswork is involved in establishing the presence of any capability;
- * try not to rely on this function being exactly right.
- *
- * @warning Make sure your connection is active before calling this function,
- * or the answer will always be "no." In particular, if you are using this
- * function on a newly-created lazyconnection, activate the connection first.
- */
- bool supports(capability c) const noexcept //[t88]
- { return m_caps.test(c); }
- /// What version of the PostgreSQL protocol is this connection using?
- /** The answer can be 0 (when there is no connection); 3 for protocol 3.0; or
- * possibly higher values as newer protocol versions are taken into use.
- *
- * If the connection is broken and restored, the restored connection could
- * possibly use a different server and protocol version. This would normally
- * happen if the server is upgraded without shutting down the client program,
- * for example.
- */
- int PQXX_PURE protocol_version() const noexcept; //[t01]
- /// What version of the PostgreSQL server are we connected to?
- /** The result is a bit complicated: each of the major, medium, and minor
- * release numbers is written as a two-digit decimal number, and the three
- * are then concatenated. Thus server version 9.4.2 will be returned as the
- * decimal number 90402. If there is no connection to the server, this
- * returns zero.
- *
- * @warning When writing version numbers in your code, don't add zero at the
- * beginning! Numbers beginning with zero are interpreted as octal (base-8)
- * in C++. Thus, 070402 is not the same as 70402, and 080000 is not a number
- * at all because there is no digit "8" in octal notation. Use strictly
- * decimal notation when it comes to these version numbers.
- */
- int PQXX_PURE server_version() const noexcept; //[t01]
- //@}
- /// @name Text encoding
- /**
- * Each connection is governed by a "client encoding," which dictates how
- * strings and other text is represented in bytes. The database server will
- * send text data to you in this encoding, and you should use it for the
- * queries and data which you send to the server.
- *
- * Search the PostgreSQL documentation for "character set encodings" to find
- * out more about the available encodings, how to extend them, and how to use
- * them. Not all server-side encodings are compatible with all client-side
- * encodings or vice versa.
- *
- * Encoding names are case-insensitive, so e.g. "UTF8" is equivalent to
- * "utf8".
- *
- * You can change the client encoding, but this may not work when the
- * connection is in a special state, such as when streaming a table. It's
- * not clear what happens if you change the encoding during a transaction,
- * and then abort the transaction.
- */
- //@{
- /// Get client-side character encoding, by name.
- std::string get_client_encoding() const;
- /// Set client-side character encoding, by name.
- /**
- * @param Encoding Name of the character set encoding to use.
- */
- void set_client_encoding(const std::string &encoding); //[t07]
- /// Set client-side character encoding, by name.
- /**
- * @param Encoding Name of the character set encoding to use.
- */
- void set_client_encoding(const char encoding[]); //[t07]
- /// Get the connection's encoding, as a PostgreSQL-defined code.
- int PQXX_PRIVATE encoding_id() const;
- //@}
- /// Set session variable
- /** Set a session variable for this connection, using the SET command. If the
- * connection to the database is lost and recovered, the last-set value will
- * be restored automatically. See the PostgreSQL documentation for a list of
- * variables that can be set and their permissible values.
- * If a transaction is currently in progress, aborting that transaction will
- * normally discard the newly set value. However nontransaction (which
- * doesn't start a real backend transaction) is an exception.
- *
- * @warning Do not mix the set_variable interface with manual setting of
- * variables by executing the corresponding SQL commands, and do not get or
- * set variables while a tablestream or pipeline is active on the same
- * connection.
- * @param Var Variable to set
- * @param Value Value vor Var to assume: an identifier, a quoted string, or a
- * number.
- */
- void set_variable( //[t60]
- const std::string &Var,
- const std::string &Value);
- /// Read session variable
- /** Will try to read the value locally, from the list of variables set with
- * the set_variable function. If that fails, the database is queried.
- * @warning Do not mix the set_variable interface with manual setting of
- * variables by executing the corresponding SQL commands, and do not get or
- * set variables while a tablestream or pipeline is active on the same
- * connection.
- */
- std::string get_variable(const std::string &); //[t60]
- //@}
- /**
- * @name Notifications and Receivers
- */
- //@{
- /// Check for pending notifications and take appropriate action.
- /**
- * All notifications found pending at call time are processed by finding
- * any matching receivers and invoking those. If no receivers matched the
- * notification string, none are invoked but the notification is considered
- * processed.
- *
- * Exceptions thrown by client-registered receivers are reported using the
- * connection's errorhandlers, but the exceptions themselves are not passed
- * on outside this function.
- *
- * @return Number of notifications processed
- */
- int get_notifs(); //[t04]
- /// Wait for a notification to come in
- /** The wait may also be terminated by other events, such as the connection
- * to the backend failing. Any pending or received notifications are
- * processed as part of the call.
- *
- * @return Number of notifications processed
- */
- int await_notification(); //[t78]
- /// Wait for a notification to come in, or for given timeout to pass
- /** The wait may also be terminated by other events, such as the connection
- * to the backend failing. Any pending or received notifications are
- * processed as part of the call.
- * @return Number of notifications processed
- */
- int await_notification(long seconds, long microseconds); //[t79]
- //@}
- /**
- * @name Prepared statements
- *
- * PostgreSQL supports prepared SQL statements, i.e. statements that can be
- * registered under a client-provided name, optimized once by the backend, and
- * executed any number of times under the given name.
- *
- * Prepared statement definitions are not sensitive to transaction boundaries;
- * a statement defined inside a transaction will remain defined outside that
- * transaction, even if the transaction itself is subsequently aborted. Once
- * a statement has been prepared, only closing the connection or explicitly
- * "unpreparing" it can make it go away.
- *
- * Use the @c pqxx::transaction_base::exec_prepared functions to execute a
- * prepared statement. Use @c prepared().exists() to find out whether a
- * statement has been prepared under a given name. See \ref prepared for a
- * full discussion.
- *
- * Never try to prepare, execute, or unprepare a prepared statement manually
- * using direct SQL queries. Always use the functions provided by libpqxx.
- *
- * @{
- */
- /// Define a prepared statement.
- /**
- * The statement's definition can refer to a parameter using the parameter's
- * positional number n in the definition. For example, the first parameter
- * can be used as a variable "$1", the second as "$2" and so on.
- *
- * Here's an example of how to use prepared statements. Note the unusual
- * syntax for passing parameters: every new argument is a parenthesized
- * expression that is simply tacked onto the end of the statement!
- *
- * @code
- * using namespace pqxx;
- * void foo(connection_base &C)
- * {
- * C.prepare("findtable", "select * from pg_tables where name=$1");
- * work W{C};
- * result R = W.exec_prepared("findtable", "mytable");
- * if (R.empty()) throw runtime_error{"mytable not found!"};
- * }
- * @endcode
- *
- * To save time, prepared statements aren't really registered with the backend
- * until they are first used. If this is not what you want, e.g. because you
- * have very specific realtime requirements, you can use the @c prepare_now()
- * function to force immediate preparation.
- *
- * The statement may not be registered with the backend until it is actually
- * used. So if, for example, the statement is syntactically incorrect, you
- * may see a syntax_error here, or later when you try to call the statement,
- * or during a @c prepare_now() call.
- *
- * @param name unique name for the new prepared statement.
- * @param definition SQL statement to prepare.
- */
- void prepare(const std::string &name, const std::string &definition);
- /// Define a nameless prepared statement.
- /**
- * This can be useful if you merely want to pass large binary parameters to a
- * statement without otherwise wishing to prepare it. If you use this
- * feature, always keep the definition and the use close together to avoid
- * the nameless statement being redefined unexpectedly by code somewhere else.
- */
- void prepare(const std::string &definition);
- /// Drop prepared statement.
- void unprepare(const std::string &name);
- /// Request that prepared statement be registered with the server.
- /** If the statement had already been fully prepared, this will do nothing.
- *
- * If the connection should break and be transparently restored, then the new
- * connection will again defer registering the statement with the server.
- * Since connections are never restored inside backend transactions, doing
- * this once at the beginning of your transaction ensures that the statement
- * will not be re-registered during that transaction. In most cases, however,
- * it's probably better not to use this and let the connection decide when and
- * whether to register prepared statements that you've defined.
- */
- void prepare_now(const std::string &name);
- /**
- * @}
- */
- /// @deprecated Pre-C++11 transactor function.
- /**
- * This has been superseded by the new transactor framework and
- * @c pqxx::perform.
- *
- * Invokes the given transactor, making at most Attempts attempts to perform
- * the encapsulated code. If the code throws any exception other than
- * broken_connection, it will be aborted right away.
- *
- * @param T The transactor to be executed.
- * @param Attempts Maximum number of attempts to be made to execute T.
- */
- template<typename TRANSACTOR>
- PQXX_DEPRECATED void perform(const TRANSACTOR &T, int Attempts); //[t04]
- /// @deprecated Pre-C++11 transactor function. Use @c pqxx::perform instead.
- /**
- * This has been superseded by the new transactor framework and
- * @c pqxx::perform.
- *
- * @param T The transactor to be executed.
- */
- template<typename TRANSACTOR>
- PQXX_DEPRECATED void perform(const TRANSACTOR &T)
- {
- #include "pqxx/internal/ignore-deprecated-pre.hxx"
- perform(T, 3);
- #include "pqxx/internal/ignore-deprecated-post.hxx"
- }
- /// Suffix unique number to name to make it unique within session context
- /** Used internally to generate identifiers for SQL objects (such as cursors
- * and nested transactions) based on a given human-readable base name.
- */
- std::string adorn_name(const std::string &); //[90]
- /**
- * @defgroup escaping-functions String-escaping functions
- */
- //@{
- /// Escape string for use as SQL string literal on this connection
- std::string esc(const char str[]);
- /// Escape string for use as SQL string literal on this connection
- std::string esc(const char str[], size_t maxlen);
- /// Escape string for use as SQL string literal on this connection
- std::string esc(const std::string &str);
- /// Escape binary string for use as SQL string literal on this connection
- std::string esc_raw(const unsigned char str[], size_t len);
- /// Unescape binary data, e.g. from a table field or notification payload.
- /** Takes a binary string as escaped by PostgreSQL, and returns a restored
- * copy of the original binary data.
- */
- std::string unesc_raw(const std::string &text)
- { return unesc_raw(text.c_str()); }
- /// Unescape binary data, e.g. from a table field or notification payload.
- /** Takes a binary string as escaped by PostgreSQL, and returns a restored
- * copy of the original binary data.
- */
- std::string unesc_raw(const char *text);
- /// Escape and quote a string of binary data.
- std::string quote_raw(const unsigned char str[], size_t len);
- /// Escape and quote an SQL identifier for use in a query.
- std::string quote_name(const std::string &identifier);
- /// Represent object as SQL string, including quoting & escaping.
- /** Nulls are recognized and represented as SQL nulls. */
- template<typename T>
- std::string quote(const T &t)
- {
- if (string_traits<T>::is_null(t)) return "NULL";
- return "'" + this->esc(to_string(t)) + "'";
- }
- std::string quote(const binarystring &);
- /// Escape string for literal LIKE match.
- /** Use this when part of an SQL "LIKE" pattern should match only as a
- * literal string, not as a pattern, even if it contains "%" or "_"
- * characters that would normally act as wildcards.
- *
- * The string does not get string-escaped or quoted. You do that later.
- *
- * For instance, let's say you have a string @c name entered by the user,
- * and you're searching a @c file column for items that match @c name
- * followed by a dot and three letters. Even if @c name contains wildcard
- * characters "%" or "_", you only want those to match literally, so "_"
- * only matches "_" and "%" only matches a single "%".
- *
- * You do that by "like-escaping" @c name, appending the wildcard pattern
- * @c ".___", and finally, escaping and quoting the result for inclusion in
- * your query:
- *
- * tx.exec(
- * "SELECT file FROM item WHERE file LIKE " +
- * tx.quote(tx.esc_like(name) + ".___"));
- *
- * The SQL "LIKE" operator also lets you choose your own escape character.
- * This is supported, but must be a single-byte character.
- */
- std::string esc_like(const std::string &str, char escape_char='\\') const;
- //@}
- /// Attempt to cancel the ongoing query, if any.
- void cancel_query();
- /// Error verbosity levels.
- enum error_verbosity
- {
- // These values must match those in libpq's PGVerbosity enum.
- terse=0,
- normal=1,
- verbose=2
- };
- /// Set session verbosity.
- /** Set the verbosity of error messages to "terse", "normal" (i.e. default) or
- * "verbose."
- *
- * If "terse", returned messages include severity, primary text, and position
- * only; this will normally fit on a single line. "normal" produces messages
- * that include the above plus any detail, hint, or context fields (these
- * might span multiple lines). "verbose" includes all available fields.
- */
- void set_verbosity(error_verbosity verbosity) noexcept;
- /// Retrieve current error verbosity
- error_verbosity get_verbosity() const noexcept {return m_verbosity;}
- /// Return pointers to the active errorhandlers.
- /** The entries are ordered from oldest to newest handler.
- *
- * You may use this to find errorhandlers that your application wants to
- * delete when destroying the connection. Be aware, however, that libpqxx
- * may also add errorhandlers of its own, and those will be included in the
- * list. If this is a problem for you, derive your errorhandlers from a
- * custom base class derived from pqxx::errorhandler. Then use dynamic_cast
- * to find which of the error handlers are yours.
- *
- * The pointers point to the real errorhandlers. The container it returns
- * however is a copy of the one internal to the connection, not a reference.
- */
- std::vector<errorhandler *> get_errorhandlers() const;
- protected:
- explicit connection_base(connectionpolicy &pol) :
- m_policy{pol}
- {
- // Check library version. The check_library_version template is declared
- // for any library version, but only actually defined for the version of
- // the libpqxx binary against which the code is linked.
- //
- // If the library binary is a different version than the one declared in
- // these headers, then this call will fail to link: there will be no
- // definition for the function with these exact template parameter values.
- // There will be a definition, but the version in the parameter values will
- // be different.
- //
- // There is no particular reason to do this here in this constructor, except
- // to ensure that every meaningful libpqxx client will execute it. The call
- // must be in the execution path somewhere or the compiler won't try to link
- // it. We can't use it to initialise a global or class-static variable,
- // because a smart compiler might resolve it at compile time.
- //
- // On the other hand, we don't want to make a useless function call too
- // often for performance reasons. A local static variable is initialised
- // only on the definition's first execution. Compilers will be well
- // optimised for this behaviour, so there's a minimal one-time cost.
- static const auto version_ok =
- internal::check_library_version<PQXX_VERSION_MAJOR, PQXX_VERSION_MINOR>();
- ignore_unused(version_ok);
- clearcaps();
- }
- void init();
- void close() noexcept;
- void wait_read() const;
- void wait_read(long seconds, long microseconds) const;
- void wait_write() const;
- private:
- result make_result(internal::pq::PGresult *rhs, const std::string &query);
- void clearcaps() noexcept;
- void PQXX_PRIVATE set_up_state();
- void PQXX_PRIVATE check_result(const result &);
- void PQXX_PRIVATE internal_set_trace() noexcept;
- int PQXX_PRIVATE PQXX_PURE status() const noexcept;
- friend class internal::gate::const_connection_largeobject;
- const char * PQXX_PURE err_msg() const noexcept;
- void PQXX_PRIVATE reset();
- std::string PQXX_PRIVATE raw_get_var(const std::string &);
- void PQXX_PRIVATE process_notice_raw(const char msg[]) noexcept;
- void read_capabilities();
- prepare::internal::prepared_def &find_prepared(const std::string &);
- prepare::internal::prepared_def ®ister_prepared(const std::string &);
- friend class internal::gate::connection_prepare_invocation;
- /// @deprecated Use exec_prepared instead.
- PQXX_DEPRECATED result prepared_exec(
- const std::string &,
- const char *const[],
- const int[],
- const int[],
- int,
- result_format format);
- result exec_prepared(const std::string &statement, const internal::params &, result_format format = result_format::text);
- bool prepared_exists(const std::string &) const;
- /// Connection handle.
- internal::pq::PGconn *m_conn = nullptr;
- connectionpolicy &m_policy;
- /// Active transaction on connection, if any.
- internal::unique<transaction_base> m_trans;
- /// Set libpq notice processor to call connection's error handlers chain.
- void set_notice_processor();
- /// Clear libpq notice processor.
- void clear_notice_processor();
- std::list<errorhandler *> m_errorhandlers;
- /// File to trace to, if any
- std::FILE *m_trace = nullptr;
- using receiver_list =
- std::multimap<std::string, pqxx::notification_receiver *>;
- /// Notification receivers.
- receiver_list m_receivers;
- /// Variables set in this session
- std::map<std::string, std::string> m_vars;
- using PSMap = std::map<std::string, prepare::internal::prepared_def>;
- /// Prepared statements existing in this section
- PSMap m_prepared;
- /// Server version
- int m_serverversion = 0;
- /// Stacking counter: known objects that can't be auto-reactivated
- internal::reactivation_avoidance_counter m_reactivation_avoidance;
- /// Unique number to use as suffix for identifiers (see adorn_name())
- int m_unique_id = 0;
- /// Have we successfully established this connection?
- bool m_completed = false;
- /// Is reactivation currently inhibited?
- bool m_inhibit_reactivation = false;
- /// Set of session capabilities
- std::bitset<cap_end> m_caps;
- /// Current verbosity level
- error_verbosity m_verbosity = normal;
- friend class internal::gate::connection_errorhandler;
- void PQXX_PRIVATE register_errorhandler(errorhandler *);
- void PQXX_PRIVATE unregister_errorhandler(errorhandler *) noexcept;
- friend class internal::gate::connection_transaction;
- result PQXX_PRIVATE exec(const char[], int Retries);
- void PQXX_PRIVATE register_transaction(transaction_base *);
- void PQXX_PRIVATE unregister_transaction(transaction_base *) noexcept;
- bool PQXX_PRIVATE read_copy_line(std::string &);
- void PQXX_PRIVATE write_copy_line(const std::string &);
- void PQXX_PRIVATE end_copy_write();
- void PQXX_PRIVATE raw_set_var(const std::string &, const std::string &);
- void PQXX_PRIVATE add_variables(const std::map<std::string, std::string> &);
- friend class internal::gate::connection_largeobject;
- internal::pq::PGconn *raw_connection() const { return m_conn; }
- friend class internal::gate::connection_notification_receiver;
- void add_receiver(notification_receiver *);
- void remove_receiver(notification_receiver *) noexcept;
- friend class internal::gate::connection_pipeline;
- void PQXX_PRIVATE start_exec(const std::string &);
- bool PQXX_PRIVATE consume_input() noexcept;
- bool PQXX_PRIVATE is_busy() const noexcept;
- internal::pq::PGresult *get_result();
- friend class internal::gate::connection_dbtransaction;
- friend class internal::gate::connection_sql_cursor;
- void add_reactivation_avoidance_count(int);
- friend class internal::gate::connection_reactivation_avoidance_exemption;
- friend class internal::gate::connection_parameterized_invocation;
- /// @deprecated Use exec_params instead.
- PQXX_DEPRECATED result parameterized_exec(
- const std::string &query,
- const char *const params[],
- const int paramlengths[],
- const int binaries[],
- int nparams);
- result exec_params(
- const std::string &query,
- const internal::params &args);
- connection_base(const connection_base &) =delete;
- connection_base &operator=(const connection_base &) =delete;
- };
- namespace internal
- {
- /// Scoped exemption to reactivation avoidance
- class PQXX_LIBEXPORT reactivation_avoidance_exemption
- {
- public:
- explicit reactivation_avoidance_exemption(connection_base &C);
- ~reactivation_avoidance_exemption();
- void close_connection() noexcept { m_open = false; }
- private:
- connection_base &m_home;
- int m_count;
- bool m_open;
- };
- void wait_read(const internal::pq::PGconn *);
- void wait_read(const internal::pq::PGconn *, long seconds, long microseconds);
- void wait_write(const internal::pq::PGconn *);
- } // namespace pqxx::internal
- } // namespace pqxx
- #include "pqxx/compiler-internal-post.hxx"
- #endif
|