diff options
author | galaxycrab <UgnineSirdis@ydb.tech> | 2023-11-23 11:26:33 +0300 |
---|---|---|
committer | galaxycrab <UgnineSirdis@ydb.tech> | 2023-11-23 12:01:57 +0300 |
commit | 44354d0fc55926c1d4510d1d2c9c9f6a1a5e9300 (patch) | |
tree | cb4d75cd1c6dbc3da0ed927337fd8d1b6ed9da84 /contrib/libs/libpqxx/include | |
parent | 0e69bf615395fdd48ecee032faaec81bc468b0b8 (diff) | |
download | ydb-44354d0fc55926c1d4510d1d2c9c9f6a1a5e9300.tar.gz |
YQ Connector:test INNER JOIN
Diffstat (limited to 'contrib/libs/libpqxx/include')
102 files changed, 10158 insertions, 0 deletions
diff --git a/contrib/libs/libpqxx/include/pqxx/array b/contrib/libs/libpqxx/include/pqxx/array new file mode 100644 index 0000000000..97311d1c18 --- /dev/null +++ b/contrib/libs/libpqxx/include/pqxx/array @@ -0,0 +1,4 @@ +/** Handling of SQL arrays. + */ +// Actual definitions in .hxx file so editors and such recognize file type. +#include "pqxx/array.hxx" diff --git a/contrib/libs/libpqxx/include/pqxx/array.hxx b/contrib/libs/libpqxx/include/pqxx/array.hxx new file mode 100644 index 0000000000..dbb464c540 --- /dev/null +++ b/contrib/libs/libpqxx/include/pqxx/array.hxx @@ -0,0 +1,101 @@ +/** Handling of SQL arrays. + * + * DO NOT INCLUDE THIS FILE DIRECTLY; include pqxx/field 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_ARRAY +#define PQXX_H_ARRAY + +#include "pqxx/compiler-public.hxx" +#include "pqxx/compiler-internal-pre.hxx" + +#include "pqxx/internal/encoding_group.hxx" +#include "pqxx/internal/encodings.hxx" + +#include <stdexcept> +#include <string> +#include <utility> + + +namespace pqxx +{ +/// Low-level array parser. +/** Use this to read an array field retrieved from the database. + * + * This parser will only work reliably if your client encoding is UTF-8, ASCII, + * or a single-byte encoding which is a superset of ASCII (such as Latin-1). + * + * Also, the parser only supports array element types which use either a comma + * or a semicolon ("," or ";") as the separator between array elements. All + * built-in types use comma, except for one which uses semicolon, but some + * custom types may not work. + * + * The input is a C-style string containing the textual representation of an + * array, as returned by the database. The parser reads this representation + * on the fly. The string must remain in memory until parsing is done. + * + * Parse the array by making calls to @c get_next until it returns a + * @c juncture of "done". The @c juncture tells you what the parser found in + * that step: did the array "nest" to a deeper level, or "un-nest" back up? + */ +class PQXX_LIBEXPORT array_parser +{ +public: + /// What's the latest thing found in the array? + enum juncture + { + /// Starting a new row. + row_start, + /// Ending the current row. + row_end, + /// Found a NULL value. + null_value, + /// Found a string value. + string_value, + /// Parsing has completed. + done, + }; + +// XXX: Actually _pass_ encoding group! + /// Constructor. You don't need this; use @c field::as_array instead. + explicit array_parser( + const char input[], + internal::encoding_group=internal::encoding_group::MONOBYTE); + + /// Parse the next step in the array. + /** Returns what it found. If the juncture is @c string_value, the string + * will contain the value. Otherwise, it will be empty. + * + * Call this until the @c juncture it returns is @c done. + */ + std::pair<juncture, std::string> get_next(); + +private: + const char *const m_input; + const std::string::size_type m_end; + internal::glyph_scanner_func *const m_scan; + + /// Current parsing position in the input. + std::string::size_type m_pos; + + std::string::size_type scan_single_quoted_string() const; + std::string parse_single_quoted_string(std::string::size_type end) const; + std::string::size_type scan_double_quoted_string() const; + std::string parse_double_quoted_string(std::string::size_type end) const; + std::string::size_type scan_unquoted_string() const; + std::string parse_unquoted_string(std::string::size_type end) const; + + std::string::size_type scan_glyph(std::string::size_type pos) const; + std::string::size_type scan_glyph( + std::string::size_type pos, + std::string::size_type end) const; +}; +} // namespace pqxx + +#include "pqxx/compiler-internal-post.hxx" +#endif diff --git a/contrib/libs/libpqxx/include/pqxx/basic_connection.hxx b/contrib/libs/libpqxx/include/pqxx/basic_connection.hxx new file mode 100644 index 0000000000..6e7372195a --- /dev/null +++ b/contrib/libs/libpqxx/include/pqxx/basic_connection.hxx @@ -0,0 +1,107 @@ +/** Definition of the pqxx::basic_connection class template. + * + * Instantiations of basic_connection bring connections and policies together. + * + * DO NOT INCLUDE THIS FILE DIRECTLY; include pqxx/basic_connection 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_BASIC_CONNECTION +#define PQXX_H_BASIC_CONNECTION + +#include "pqxx/compiler-public.hxx" +#include "pqxx/compiler-internal-pre.hxx" + +#include <cstddef> +#include <memory> +#include <string> + +#include "pqxx/connection_base.hxx" + + +namespace pqxx +{ + +/// Base-class template for all libpqxx connection types. +/** @deprecated In libpqxx 7, all built-in connection types will be implemented + * as a single class. You'll specify the connection policy as an optional + * constructor argument. + * + * Combines connection_base (the highly complex class implementing essentially + * all connection-related functionality) with a connection policy (a simpler + * helper class determining the rules that govern the process of setting up the + * underlying connection to the backend). + * + * The pattern used to combine these classes is the same as for + * basic_transaction. Through use of the template mechanism, the policy object + * is embedded in the basic_connection object so that it does not need to be + * allocated separately. This also avoids the need for virtual functions in + * this class. + */ +template<typename CONNECTPOLICY> class basic_connection_base : + public connection_base +{ +public: + basic_connection_base() : + connection_base(m_policy), + m_options(std::string{}), + m_policy(m_options) + { init(); } + + /// The parsing of options is the same as libpq's PQconnect. + /// See: https://www.postgresql.org/docs/10/static/libpq-connect.html + explicit basic_connection_base(const std::string &opt) : + connection_base(m_policy), + m_options(opt), + m_policy(m_options) + {init();} + + /// See: @c basic_connection(const std::string &opt) + explicit basic_connection_base(const char opt[]) : + basic_connection_base(opt ? std::string{opt} : std::string{}) {} + + explicit basic_connection_base(std::nullptr_t) : basic_connection_base() {} + + ~basic_connection_base() noexcept + { close(); } + + const std::string &options() const noexcept //[t01] + {return m_policy.options();} + +private: + /// Connect string. @warn Must be initialized before the connector! + std::string m_options; + /// Connection policy. @warn Must be initialized after the connect string! + CONNECTPOLICY m_policy; +}; + + +/// Concrete connection type template. +/** @deprecated In libpqxx 7, all built-in connection types will be implemented + * as a single class. You'll specify the connection policy as an optional + * constructor argument. + */ +template<typename CONNECTPOLICY> struct basic_connection : + basic_connection_base<CONNECTPOLICY> +{ + PQXX_DEPRECATED basic_connection() =default; + PQXX_DEPRECATED explicit basic_connection(const std::string &opt) : + basic_connection(opt) {} + PQXX_DEPRECATED explicit basic_connection(const char opt[]) : + basic_connection(opt) {} + + PQXX_DEPRECATED explicit basic_connection(std::nullptr_t) : + basic_connection() {} + + using basic_connection_base<CONNECTPOLICY>::options; +}; + +} // namespace + +#include "pqxx/compiler-internal-post.hxx" + +#endif diff --git a/contrib/libs/libpqxx/include/pqxx/binarystring b/contrib/libs/libpqxx/include/pqxx/binarystring new file mode 100644 index 0000000000..4214f0257d --- /dev/null +++ b/contrib/libs/libpqxx/include/pqxx/binarystring @@ -0,0 +1,4 @@ +/** BYTEA (binary string) conversions. + */ +// Actual definitions in .hxx file so editors and such recognize file type. +#include "pqxx/binarystring.hxx" diff --git a/contrib/libs/libpqxx/include/pqxx/binarystring.hxx b/contrib/libs/libpqxx/include/pqxx/binarystring.hxx new file mode 100644 index 0000000000..4262938ef3 --- /dev/null +++ b/contrib/libs/libpqxx/include/pqxx/binarystring.hxx @@ -0,0 +1,157 @@ +/** Representation for raw, binary data. + * + * DO NOT INCLUDE THIS FILE DIRECTLY; include pqxx/binarystring 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_BINARYSTRING +#define PQXX_H_BINARYSTRING + +#include "pqxx/compiler-public.hxx" +#include "pqxx/compiler-internal-pre.hxx" + +#include <memory> +#include <string> + +#include "pqxx/result.hxx" + + +namespace pqxx +{ + +/// Binary data corresponding to PostgreSQL's "BYTEA" binary-string type. +/** @ingroup escaping-functions + * + * This class represents a binary string as stored in a field of type bytea. + * The raw value returned by a bytea field contains escape sequences for certain + * characters, which are filtered out by binarystring. + * + * Internally a binarystring is zero-terminated, but it may also contain zero + * bytes, just like any other byte value. So don't assume that it can be + * treated as a C-style string unless you've made sure of this yourself. + * + * The binarystring retains its value even if the result it was obtained from is + * destroyed, but it cannot be copied or assigned. + * + * \relatesalso transaction_base::esc_raw + * + * To convert the other way, i.e. from a raw series of bytes to a string + * suitable for inclusion as bytea values in your SQL, use the transaction's + * esc_raw() functions. + * + * @warning This class is implemented as a reference-counting smart pointer. + * Copying, swapping, and destroying binarystring objects that refer to the same + * underlying data block is <em>not thread-safe</em>. If you wish to pass + * binarystrings around between threads, make sure that each of these operations + * is protected against concurrency with similar operations on the same object, + * or other objects pointing to the same data block. + */ +class PQXX_LIBEXPORT binarystring +{ +public: + using char_type = unsigned char; + using value_type = std::char_traits<char_type>::char_type; + using size_type = size_t; + using difference_type = long; + using const_reference = const value_type &; + using const_pointer = const value_type *; + using const_iterator = const_pointer; + using const_reverse_iterator = std::reverse_iterator<const_iterator>; + + binarystring(const binarystring &) =default; + + /// Read and unescape bytea field + /** The field will be zero-terminated, even if the original bytea field isn't. + * @param F the field to read; must be a bytea field + */ + explicit binarystring(const field &); //[t62] + + /// Copy binary data from std::string. + explicit binarystring(const std::string &); + + /// Copy binary data of given length straight out of memory. + binarystring(const void *, size_t); + + /// Size of converted string in bytes + size_type size() const noexcept { return m_size; } //[t62] + /// Size of converted string in bytes + size_type length() const noexcept { return size(); } //[t62] + bool empty() const noexcept { return size()==0; } //[t62] + + const_iterator begin() const noexcept { return data(); } //[t62] + const_iterator cbegin() const noexcept { return begin(); } + const_iterator end() const noexcept { return data()+m_size; } //[t62] + const_iterator cend() const noexcept { return end(); } + + const_reference front() const noexcept { return *begin(); } //[t62] + const_reference back() const noexcept //[t62] + { return *(data()+m_size-1); } + + const_reverse_iterator rbegin() const //[t62] + { return const_reverse_iterator{end()}; } + const_reverse_iterator crbegin() const { return rbegin(); } + const_reverse_iterator rend() const //[t62] + { return const_reverse_iterator{begin()}; } + const_reverse_iterator crend() const { return rend(); } + + /// Unescaped field contents + const value_type *data() const noexcept {return m_buf.get();} //[t62] + + const_reference operator[](size_type i) const noexcept //[t62] + { return data()[i]; } + + PQXX_PURE bool operator==(const binarystring &) const noexcept; //[t62] + bool operator!=(const binarystring &rhs) const noexcept //[t62] + { return not operator==(rhs); } + + binarystring &operator=(const binarystring &); + + /// Index contained string, checking for valid index + const_reference at(size_type) const; //[t62] + + /// Swap contents with other binarystring + void swap(binarystring &); //[t62] + + /// Raw character buffer (no terminating zero is added) + /** @warning No terminating zero is added! If the binary data did not end in + * a null character, you will not find one here. + */ + const char *get() const noexcept //[t62] + { return reinterpret_cast<const char *>(m_buf.get()); } + + /// Read as regular C++ string (may include null characters) + /** @warning libpqxx releases before 3.1 stored the string and returned a + * reference to it. This is no longer the case! It now creates and returns + * a new string object. Avoid repeated use of this function; retrieve your + * string once and keep it in a local variable. Also, do not expect to be + * able to compare the string's address to that of an earlier invocation. + */ + std::string str() const; //[t62] + +private: + using smart_pointer_type = std::shared_ptr<value_type>; + + /// Shorthand: construct a smart_pointer_type. + static smart_pointer_type make_smart_pointer(unsigned char *buf=nullptr) + { +#if !(defined(_MSC_VER) && defined(__clang__)) + return smart_pointer_type{ + buf, + internal::freemallocmem_templated<unsigned char>}; +#else + return smart_pointer_type{buf, internal::freemallocmem}; +#endif + } + + smart_pointer_type m_buf; + size_type m_size; +}; +} + +#include "pqxx/compiler-internal-post.hxx" + +#endif diff --git a/contrib/libs/libpqxx/include/pqxx/compiler-internal-post.hxx b/contrib/libs/libpqxx/include/pqxx/compiler-internal-post.hxx new file mode 100644 index 0000000000..6af34b5d30 --- /dev/null +++ b/contrib/libs/libpqxx/include/pqxx/compiler-internal-post.hxx @@ -0,0 +1,21 @@ +/** Compiler deficiency workarounds for compiling libpqxx headers. + * + * To be included at the end of each libpqxx header, in order to restore the + * client program's settings. + * + * 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. + */ +// NO GUARDS HERE! This code should be executed every time! + +#ifdef _WIN32 + +#ifdef _MSC_VER +#pragma warning (pop) // Restore client program's warning state +#endif + +#endif + diff --git a/contrib/libs/libpqxx/include/pqxx/compiler-internal-pre.hxx b/contrib/libs/libpqxx/include/pqxx/compiler-internal-pre.hxx new file mode 100644 index 0000000000..ac3a7b89ab --- /dev/null +++ b/contrib/libs/libpqxx/include/pqxx/compiler-internal-pre.hxx @@ -0,0 +1,35 @@ +/** Compiler deficiency workarounds for compiling libpqxx headers. + * + * To be called at the start of each libpqxx header, in order to push the + * client program's settings and apply libpqxx's settings. + * + * Must be balanced by an include of -header-post.hxx at the end + * of the header. + * + * 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. + */ +// NO GUARDS HERE! This code should be executed every time! + +#ifdef _WIN32 +#ifdef _MSC_VER + +// Save client program warning state, and set warning level 4. +// Setting the warning level explicitly ensures that libpqxx +// headers will work with this warning level as well. +#pragma warning (push,4) + +#pragma warning (disable: 4251) +#pragma warning (disable: 4273) +#pragma warning (disable: 4275) +#pragma warning (disable: 4355) +#pragma warning (disable: 4511) // Copy constructor could not be generated. +#pragma warning (disable: 4512) // Assignment operator could not be generated. +#pragma warning (disable: 4996) // Deprecation warning, e.g. about strncpy(). + +#endif // _MSC_VER +#endif // _WIN32 + diff --git a/contrib/libs/libpqxx/include/pqxx/compiler-internal.hxx b/contrib/libs/libpqxx/include/pqxx/compiler-internal.hxx new file mode 100644 index 0000000000..9743f47866 --- /dev/null +++ b/contrib/libs/libpqxx/include/pqxx/compiler-internal.hxx @@ -0,0 +1,42 @@ +/** Compiler deficiency workarounds for compiling libpqxx itself. + * + * DO NOT INCLUDE THIS FILE when building client programs. + * + * 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_COMPILER_INTERNAL +#define PQXX_H_COMPILER_INTERNAL + + +// Workarounds & definitions needed to compile libpqxx into a library +#include "pqxx/config-internal-compiler.h" + +#ifdef _WIN32 + +#ifdef PQXX_SHARED +#undef PQXX_LIBEXPORT +#define PQXX_LIBEXPORT __declspec(dllexport) +#define PQXX_PRIVATE __declspec() +#endif // PQXX_SHARED + +#ifdef _MSC_VER +#pragma warning (disable: 4251 4275 4273) +#pragma warning (disable: 4355) +#pragma warning (disable: 4996) // Deprecation warning, e.g. about strncpy(). +#endif + +#elif defined(__GNUC__) && defined(PQXX_HAVE_GCC_VISIBILITY) // !_WIN32 + +#define PQXX_LIBEXPORT __attribute__ ((visibility("default"))) +#define PQXX_PRIVATE __attribute__ ((visibility("hidden"))) + +#endif // __GNUC__ && PQXX_HAVE_GCC_VISIBILITY + + +#include "pqxx/compiler-public.hxx" + +#endif diff --git a/contrib/libs/libpqxx/include/pqxx/compiler-public.hxx b/contrib/libs/libpqxx/include/pqxx/compiler-public.hxx new file mode 100644 index 0000000000..352956c237 --- /dev/null +++ b/contrib/libs/libpqxx/include/pqxx/compiler-public.hxx @@ -0,0 +1,122 @@ +/** Compiler deficiency workarounds for libpqxx clients. + * + * 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_COMPILER_PUBLIC +#define PQXX_H_COMPILER_PUBLIC + +// Workarounds & definitions that need to be included even in library's headers +#include "pqxx/config-public-compiler.h" + +// Some compilers, Visual Studio in particular, don't seem to support the +// standard's ISO-646 keywords out of the box. +#include <ciso646> + + +#if defined(__GNUC__) && defined(PQXX_HAVE_GCC_CONST) +/// Declare function without effects and without reading anything but its args. +#define PQXX_CONST __attribute__ ((const)) +#else +#define PQXX_CONST +#endif + +#if defined(PQXX_HAVE_DEPRECATED) +/// Mark an item as deprecated. +#define PQXX_DEPRECATED [[deprecated]] +#elif defined(__GNUC__) && defined(PQXX_HAVE_GCC_DEPRECATED) +#define PQXX_DEPRECATED __attribute__ ((deprecated)) +#else +#define PQXX_DEPRECATED +#endif + +#if defined(__GNUC__) && defined(PQXX_HAVE_GCC_PURE) +/// Declare function "pure": no side effects, only reads globals and its args. +#define PQXX_PURE __attribute__ ((pure)) +#else +#define PQXX_PURE +#endif + + +// Workarounds for Windows +#ifdef _WIN32 + +/* For now, export DLL symbols if _DLL is defined. This is done automatically + * by the compiler when linking to the dynamic version of the runtime library, + * according to "gzh" + */ +#if !defined(PQXX_LIBEXPORT) && defined(PQXX_SHARED) +#define PQXX_LIBEXPORT __declspec(dllimport) +#endif // !PQXX_LIBEXPORT && PQXX_SHARED + + +// Workarounds for Microsoft Visual C++ +#ifdef _MSC_VER + +// Suppress vtables on abstract classes. +#define PQXX_NOVTABLE __declspec(novtable) + +// Automatically link with the appropriate libpq (static or dynamic, debug or +// release). The default is to use the release DLL. Define PQXX_PQ_STATIC to +// link to a static version of libpq, and _DEBUG to link to a debug version. +// The two may be combined. +#if defined(PQXX_AUTOLINK) +#if defined(PQXX_PQ_STATIC) +#ifdef _DEBUG +#pragma comment(lib, "libpqd") +#else +#pragma comment(lib, "libpq") +#endif +#else +#ifdef _DEBUG +#pragma comment(lib, "libpqddll") +#else +#pragma comment(lib, "libpqdll") +#endif +#endif +#endif + +// If we're not compiling libpqxx itself, automatically link with the +// appropriate libpqxx library. To link with the libpqxx DLL, define +// PQXX_SHARED; the default is to link with the static library. A static link +// is the recommended practice. +// +// The preprocessor macro PQXX_INTERNAL is used to detect whether we +// are compiling the libpqxx library itself. When you compile the library +// yourself using your own project file, make sure to include this macro. +#if defined(PQXX_AUTOLINK) && !defined(PQXX_INTERNAL) + #ifdef PQXX_SHARED + #ifdef _DEBUG + #pragma comment(lib, "libpqxxD") + #else + #pragma comment(lib, "libpqxx") + #endif + #else // !PQXX_SHARED + #ifdef _DEBUG + #pragma comment(lib, "libpqxx_staticD") + #else + #pragma comment(lib, "libpqxx_static") + #endif + #endif +#endif + +#endif // _MSC_VER +#endif // _WIN32 + + +#ifndef PQXX_LIBEXPORT +#define PQXX_LIBEXPORT +#endif + +#ifndef PQXX_PRIVATE +#define PQXX_PRIVATE +#endif + +#ifndef PQXX_NOVTABLE +#define PQXX_NOVTABLE +#endif + +#endif diff --git a/contrib/libs/libpqxx/include/pqxx/config-internal-compiler.h b/contrib/libs/libpqxx/include/pqxx/config-internal-compiler.h new file mode 100644 index 0000000000..ddf45f0db7 --- /dev/null +++ b/contrib/libs/libpqxx/include/pqxx/config-internal-compiler.h @@ -0,0 +1,14 @@ +/* Automatically generated from config.h: internal/compiler config. */ + +#include <util/system/platform.h> + +#if defined(_linux_) || defined(_darwin_) + +# define HAVE_POLL 1 +# define HAVE_SYS_TIME_H 1 +# define HAVE_SYS_TYPES_H 1 +# define HAVE_UNISTD_H 1 +# define PQXX_HAVE_CHARCONV_INT 1 +# define PQXX_HAVE_GCC_VISIBILITY 1 + +#endif diff --git a/contrib/libs/libpqxx/include/pqxx/config-public-compiler.h b/contrib/libs/libpqxx/include/pqxx/config-public-compiler.h new file mode 100644 index 0000000000..5a6feb5739 --- /dev/null +++ b/contrib/libs/libpqxx/include/pqxx/config-public-compiler.h @@ -0,0 +1,11 @@ +/* Automatically generated from config.h: public/compiler config. */ + +#ifndef _MSC_VER +#define PQXX_HAVE_DEPRECATED 1 +#endif +#ifndef _MSC_VER +#define PQXX_HAVE_GCC_CONST 1 +#define PQXX_HAVE_GCC_DEPRECATED 1 +#define PQXX_HAVE_GCC_PURE 1 +#endif +#define PQXX_HAVE_OPTIONAL 1 diff --git a/contrib/libs/libpqxx/include/pqxx/connection b/contrib/libs/libpqxx/include/pqxx/connection new file mode 100644 index 0000000000..d08e357e93 --- /dev/null +++ b/contrib/libs/libpqxx/include/pqxx/connection @@ -0,0 +1,6 @@ +/** pqxx::connection and pqxx::lazyconnection classes. + * + * Different ways of setting up a backend connection. + */ +// Actual definitions in .hxx file so editors and such recognize file type. +#include "pqxx/connection.hxx" diff --git a/contrib/libs/libpqxx/include/pqxx/connection.hxx b/contrib/libs/libpqxx/include/pqxx/connection.hxx new file mode 100644 index 0000000000..cb00743fec --- /dev/null +++ b/contrib/libs/libpqxx/include/pqxx/connection.hxx @@ -0,0 +1,170 @@ +/** Definition of the pqxx::connection and pqxx::lazyconnection classes. + * + * Different ways of setting up a backend connection. + * + * DO NOT INCLUDE THIS FILE DIRECTLY; include pqxx/connection 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 +#define PQXX_H_CONNECTION + +#include "pqxx/compiler-public.hxx" +#include "pqxx/compiler-internal-pre.hxx" + +#include "pqxx/connectionpolicy.hxx" +#include "pqxx/basic_connection.hxx" + +namespace pqxx +{ + +/** + * @addtogroup connection Connection classes + * + * The connection classes are where the use of a database begins. You must + * connect to a database in order to access it. Your connection represents a + * session with the database. In the context of that connection you can create + * transactions, which in turn you can use to execute SQL. A connection can + * have only one regular transaction open at a time, but you can break your work + * down into any number of consecutive transactions and there is also some + * support for transaction nesting (using the subtransaction class). + * + * Many things come together in the connection classes. Handling of error and + * warning messages, for example, is defined by @e errorhandlers in the context + * of a connection. Prepared statements are also defined here. + * + * @warning In libpqxx 7, all built-in connection types will be implemented + * as a single class. You'll specify the connection policy as an optional + * constructor argument. + * + * Several types of connections are available, including plain connection and + * lazyconnection. These types are aliases combining a derivative of the + * connection_base class (where essentially all connection-related functionality + * is defined) with a policy class which governs how the connection is to be + * established. You pass details such as the database you wish to connect to, + * username and password, and so on as as PostgreSQL "connection string" and + * certain environment variables that you can learn more about from the core + * postgres documentation. + * + * See the connection_base documentation for a full list of features inherited + * by all connection classes. Connections can be deactivated and reactivated if + * needed (within reason, of course--you can't do this in the middle of a + * transaction), and where possible, disabled or broken connections are + * transparently re-enabled when you use them again. This is called + * "reactivation," and you may need to understand it because you'll want it + * disabled in certain situations. + * + * @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. + * + * You can also set certain variables defined by the backend to influence its + * behaviour for the duration of your session, such as the applicable text + * encoding. You can query the connection's capabilities (because some features + * will depend on the versions of libpq and of the server backend that you're + * using) and parameters that you set in your connection string and/or + * environment variables. + * + * @{ + */ + +/// Connection policy; creates an immediate connection to a database. +/** This is the policy you typically need when you work with a database through + * libpqxx. It connects to the database immediately. Another option is to + * defer setting up the underlying connection to the database until it's + * actually needed; the connect_lazy policy implements such "lazy" * behaviour. + * + * The advantage of having an "immediate" connection (as this policy gives you) + * is that any errors in setting up the connection will occur during + * construction of the connection object, rather than at some later point + * further down your program. + */ +class PQXX_LIBEXPORT connect_direct : public connectionpolicy +{ +public: + /// The parsing of options is the same as in libpq's PQconnect. + /// See: https://www.postgresql.org/docs/10/static/libpq-connect.html + explicit connect_direct(const std::string &opts) : connectionpolicy{opts} {} + virtual handle do_startconnect(handle) override; +}; + +/// The "standard" connection type: connect to database right now +using connection = basic_connection_base<connect_direct>; + + +/// Lazy connection policy; causes connection to be deferred until first use. +/** This is connect_direct's lazy younger brother. It does not attempt to open + * a connection right away; the connection is only created when it is actually + * used. + */ +class PQXX_LIBEXPORT connect_lazy : public connectionpolicy +{ +public: + /// The parsing of options is the same as in libpq's PQconnect. + /// See: https://www.postgresql.org/docs/10/static/libpq-connect.html + explicit connect_lazy(const std::string &opts) : connectionpolicy{opts} {} + virtual handle do_completeconnect(handle) override; +}; + + +/// A "lazy" connection type: connect to database only when needed +using lazyconnection = basic_connection_base<connect_lazy>; + + +/// Asynchronous connection policy; connects "in the background" +/** Connection is initiated immediately, but completion is deferred until the + * connection is actually needed. + * + * This may help performance by allowing the client to do useful work while + * waiting for an answer from the server. + */ +class PQXX_LIBEXPORT connect_async : public connectionpolicy +{ +public: + /// The parsing of options is the same as in libpq's PQConnect + /// See: https://www.postgresql.org/docs/10/static/libpq-connect.html + explicit connect_async(const std::string &opts); + virtual handle do_startconnect(handle) override; + virtual handle do_completeconnect(handle) override; + virtual handle do_dropconnect(handle) noexcept override; + virtual bool is_ready(handle) const noexcept override; + +private: + /// Is a connection attempt in progress? + bool m_connecting; +}; + + +/// "Asynchronous" connection type: start connecting, but don't wait for it +using asyncconnection = basic_connection_base<connect_async>; + + +/// Nonfunctional, always-down connection policy for testing/debugging purposes +/** @warning You don't want to use this policy in normal code. + * Written for debugging and testing, this "connection policy" always fails to + * connect, and the internal connection pointer always remains null. + */ +class PQXX_LIBEXPORT connect_null : public connectionpolicy +{ +public: + explicit connect_null(const std::string &opts) : connectionpolicy{opts} {} +}; + + +/// A "dummy" connection type: don't connect to any database at all +using nullconnection = basic_connection_base<connect_null>; + +/** + * @} + */ + +} + +#include "pqxx/compiler-internal-post.hxx" + +#endif diff --git a/contrib/libs/libpqxx/include/pqxx/connection_base b/contrib/libs/libpqxx/include/pqxx/connection_base new file mode 100644 index 0000000000..187b667cb3 --- /dev/null +++ b/contrib/libs/libpqxx/include/pqxx/connection_base @@ -0,0 +1,6 @@ +/** pqxx::connection_base abstract base class. + * + * pqxx::connection_base encapsulates a frontend-to-backend connection. + */ +// Actual definitions in .hxx file so editors and such recognize file type. +#include "pqxx/connection_base.hxx" diff --git a/contrib/libs/libpqxx/include/pqxx/connection_base.hxx b/contrib/libs/libpqxx/include/pqxx/connection_base.hxx new file mode 100644 index 0000000000..8809639873 --- /dev/null +++ b/contrib/libs/libpqxx/include/pqxx/connection_base.hxx @@ -0,0 +1,940 @@ +/** 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 diff --git a/contrib/libs/libpqxx/include/pqxx/connectionpolicy.hxx b/contrib/libs/libpqxx/include/pqxx/connectionpolicy.hxx new file mode 100644 index 0000000000..3eebf9edbe --- /dev/null +++ b/contrib/libs/libpqxx/include/pqxx/connectionpolicy.hxx @@ -0,0 +1,59 @@ +/** Definition of the connection policy classes. + * + * Interface for defining connection policies + * DO NOT INCLUDE THIS FILE DIRECTLY; include pqxx/connection 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_CONNECTIONPOLICY +#define PQXX_H_CONNECTIONPOLICY + +#include "pqxx/compiler-public.hxx" +#include "pqxx/compiler-internal-pre.hxx" + +#include <string> + +#include "pqxx/internal/libpq-forward.hxx" + + +namespace pqxx +{ + +/** + * @addtogroup connection Connection classes + */ +//@{ + +class PQXX_LIBEXPORT connectionpolicy +{ +public: + using handle = internal::pq::PGconn *; + + explicit connectionpolicy(const std::string &opts); + virtual ~connectionpolicy() noexcept; + + const std::string &options() const noexcept { return m_options; } + + virtual handle do_startconnect(handle orig); + virtual handle do_completeconnect(handle orig); + virtual handle do_dropconnect(handle orig) noexcept; + virtual handle do_disconnect(handle orig) noexcept; + virtual bool is_ready(handle) const noexcept; + +protected: + handle normalconnect(handle); + +private: + std::string m_options; +}; + +//@} +} // namespace + +#include "pqxx/compiler-internal-post.hxx" + +#endif diff --git a/contrib/libs/libpqxx/include/pqxx/cursor b/contrib/libs/libpqxx/include/pqxx/cursor new file mode 100644 index 0000000000..02979afda5 --- /dev/null +++ b/contrib/libs/libpqxx/include/pqxx/cursor @@ -0,0 +1,6 @@ +/** Definition of the iterator/container-style cursor classes. + * + * C++-style wrappers for SQL cursors + */ +// Actual definitions in .hxx file so editors and such recognize file type. +#include "pqxx/cursor.hxx" diff --git a/contrib/libs/libpqxx/include/pqxx/cursor.hxx b/contrib/libs/libpqxx/include/pqxx/cursor.hxx new file mode 100644 index 0000000000..a1b53ab1cb --- /dev/null +++ b/contrib/libs/libpqxx/include/pqxx/cursor.hxx @@ -0,0 +1,437 @@ +/** Definition of the iterator/container-style cursor classes. + * + * C++-style wrappers for SQL cursors + * + * DO NOT INCLUDE THIS FILE DIRECTLY; include pqxx/cursor 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_CURSOR +#define PQXX_H_CURSOR + +#include "pqxx/compiler-public.hxx" +#include "pqxx/compiler-internal-pre.hxx" + +#include <limits> +#include <stdexcept> + +#include "pqxx/result.hxx" +#include "pqxx/transaction_base.hxx" + + +namespace pqxx +{ +/// Common definitions for cursor types +/** In C++ terms, fetches are always done in pre-increment or pre-decrement + * fashion--i.e. the result does not include the row the cursor is on at the + * beginning of the fetch, and the cursor ends up being positioned on the last + * row in the result. + * + * There are singular positions akin to @c end() at both the beginning and the + * end of the cursor's range of movement, although these fit in so naturally + * with the semantics that one rarely notices them. The cursor begins at the + * first of these, but any fetch in the forward direction will move the cursor + * off this position and onto the first row before returning anything. + */ +class PQXX_LIBEXPORT cursor_base +{ +public: + using size_type = result_size_type; + using difference_type = result_difference_type; + + /// Cursor access-pattern policy + /** Allowing a cursor to move forward only can result in better performance, + * so use this access policy whenever possible. + */ + enum accesspolicy + { + /// Cursor can move forward only + forward_only, + /// Cursor can move back and forth + random_access + }; + + /// Cursor update policy + /** + * @warning Not all PostgreSQL versions support updatable cursors. + */ + enum updatepolicy + { + /// Cursor can be used to read data but not to write + read_only, + /// Cursor can be used to update data as well as read it + update + }; + + /// Cursor destruction policy + /** The normal thing to do is to make a cursor object the owner of the SQL + * cursor it represents. There may be cases, however, where a cursor needs to + * persist beyond the end of the current transaction (and thus also beyond the + * lifetime of the cursor object that created it!), where it can be "adopted" + * into a new cursor object. See the basic_cursor documentation for an + * explanation of cursor adoption. + * + * If a cursor is created with "loose" ownership policy, the object + * representing the underlying SQL cursor will not take the latter with it + * when its own lifetime ends, nor will its originating transaction. + * + * @warning Use this feature with care and moderation. Only one cursor object + * should be responsible for any one underlying SQL cursor at any given time. + * + * @warning Don't "leak" cursors! As long as any "loose" cursor exists, + * any attempts to deactivate or reactivate the connection, implicitly or + * explicitly, are quietly ignored. + */ + enum ownershippolicy + { + /// Destroy SQL cursor when cursor object is closed at end of transaction + owned, + /// Leave SQL cursor in existence after close of object and transaction + loose + }; + + cursor_base() =delete; + cursor_base(const cursor_base &) =delete; + cursor_base &operator=(const cursor_base &) =delete; + + /** + * @name Special movement distances. + */ + //@{ + + /// Special value: read until end. + /** @return Maximum value for result::difference_type, so the cursor will + * attempt to read the largest possible result set. + */ + static difference_type all() noexcept; //[t81] + + /// Special value: read one row only. + /** @return Unsurprisingly, 1. + */ + static difference_type next() noexcept { return 1; } //[t81] + + /// Special value: read backwards, one row only. + /** @return Unsurprisingly, -1. + */ + static difference_type prior() noexcept { return -1; } //[t00] + + /// Special value: read backwards from current position back to origin. + /** @return Minimum value for result::difference_type. + */ + static difference_type backward_all() noexcept; //[t00] + + //@} + + /// Name of underlying SQL cursor + /** + * @returns Name of SQL cursor, which may differ from original given name. + * @warning Don't use this to access the SQL cursor directly without going + * through the provided wrapper classes! + */ + const std::string &name() const noexcept { return m_name; } //[t81] + +protected: + cursor_base( + connection_base &, + const std::string &Name, + bool embellish_name=true); + + const std::string m_name; +}; +} // namespace pqxx + + +#include <pqxx/internal/sql_cursor.hxx> + + +namespace pqxx +{ +/// "Stateless cursor" class: easy API for retrieving parts of result sets +/** This is a front-end for SQL cursors, but with a more C++-like API. + * + * Actually, stateless_cursor feels entirely different from SQL cursors. You + * don't keep track of positions, fetches, and moves; you just say which rows + * you want. See the retrieve() member function. + */ +template<cursor_base::updatepolicy up, cursor_base::ownershippolicy op> +class stateless_cursor +{ +public: + using size_type = result_size_type; + using difference_type = result_difference_type; + + /// Create cursor. + stateless_cursor( + transaction_base &trans, + const std::string &query, + const std::string &cname, + bool hold) : + m_cur{trans, query, cname, cursor_base::random_access, up, op, hold} + { + } + + /// Adopt existing scrolling SQL cursor. + stateless_cursor( + transaction_base &trans, + const std::string adopted_cursor) : + m_cur{trans, adopted_cursor, op} + { + // Put cursor in known position + m_cur.move(cursor_base::backward_all()); + } + + void close() noexcept { m_cur.close(); } + + /// Number of rows in cursor's result set + /** @note This function is not const; it may need to scroll to find the size + * of the result set. + */ + size_type size() { return internal::obtain_stateless_cursor_size(m_cur); } + + /// Retrieve rows from begin_pos (inclusive) to end_pos (exclusive) + /** Rows are numbered starting from 0 to size()-1. + * + * @param begin_pos First row to retrieve. May be one row beyond the end of + * the result set, to avoid errors for empty result sets. Otherwise, must be + * a valid row number in the result set. + * @param end_pos Row up to which to fetch. Rows are returned ordered from + * begin_pos to end_pos, i.e. in ascending order if begin_pos < end_pos but + * in descending order if begin_pos > end_pos. The end_pos may be arbitrarily + * inside or outside the result set; only existing rows are included in the + * result. + */ + result retrieve(difference_type begin_pos, difference_type end_pos) + { + return internal::stateless_cursor_retrieve( + m_cur, + result::difference_type(size()), + begin_pos, + end_pos); + } + + const std::string &name() const noexcept { return m_cur.name(); } + +private: + internal::sql_cursor m_cur; +}; + + +class icursor_iterator; + + +namespace internal +{ +namespace gate +{ +class icursor_iterator_icursorstream; +class icursorstream_icursor_iterator; +} // namespace internal::gate +} // namespace internal + + +/// Simple read-only cursor represented as a stream of results +/** SQL cursors can be tricky, especially in C++ since the two languages seem to + * have been designed on different planets. An SQL cursor has two singular + * positions akin to @c end() on either side of the underlying result set. + * + * These cultural differences are hidden from view somewhat by libpqxx, which + * tries to make SQL cursors behave more like familiar C++ entities such as + * iterators, sequences, streams, and containers. + * + * Data is fetched from the cursor as a sequence of result objects. Each of + * these will contain the number of rows defined as the stream's stride, except + * of course the last block of data which may contain fewer rows. + * + * This class can create or adopt cursors that live outside any backend + * transaction, which your backend version may not support. + */ +class PQXX_LIBEXPORT icursorstream +{ +public: + using size_type = cursor_base::size_type; + using difference_type = cursor_base::difference_type; + + /// Set up a read-only, forward-only cursor + /** Roughly equivalent to a C++ Standard Library istream, this cursor type + * supports only two operations: reading a block of rows while moving forward, + * and moving forward without reading any data. + * + * @param context Transaction context that this cursor will be active in + * @param query SQL query whose results this cursor shall iterate + * @param basename Suggested name for the SQL cursor; a unique code will be + * appended by the library to ensure its uniqueness + * @param sstride Number of rows to fetch per read operation; must be a + * positive number + */ + icursorstream( + transaction_base &context, + const std::string &query, + const std::string &basename, + difference_type sstride=1); //[t81] + + /// Adopt existing SQL cursor. Use with care. + /** Forms a cursor stream around an existing SQL cursor, as returned by e.g. a + * server-side function. The SQL cursor will be cleaned up by the stream's + * destructor as if it had been created by the stream; cleaning it up by hand + * or adopting the same cursor twice is an error. + * + * Passing the name of the cursor as a string is not allowed, both to avoid + * confusion with the other constructor and to discourage unnecessary use of + * adopted cursors. + * + * @warning It is technically possible to adopt a "WITH HOLD" cursor, i.e. a + * cursor that stays alive outside its creating transaction. However, any + * cursor stream (including the underlying SQL cursor, naturally) must be + * destroyed before its transaction context object is destroyed. Therefore + * the only way to use SQL's WITH HOLD feature is to adopt the cursor, but + * defer doing so until after entering the transaction context that will + * eventually destroy it. + * + * @param context Transaction context that this cursor will be active in. + * @param cname Result field containing the name of the SQL cursor to adopt. + * @param sstride Number of rows to fetch per read operation; must be a + * positive number. + * @param op Ownership policy. Determines whether the cursor underlying this + * stream will be destroyed when the stream is closed. + */ + icursorstream( + transaction_base &context, + const field &cname, + difference_type sstride=1, + cursor_base::ownershippolicy op=cursor_base::owned); //[t84] + + operator bool() const noexcept { return not m_done; } + + /// Read new value into given result object; same as operator >> + /** The result set may continue any number of rows from zero to the chosen + * stride, inclusive. An empty result will only be returned if there are no + * more rows to retrieve. + * @return Reference to this very stream, to facilitate "chained" invocations + * ("C.get(r1).get(r2);") + */ + icursorstream &get(result &res) { res = fetchblock(); return *this; } //[t81] + /// Read new value into given result object; same as get(result &) + /** The result set may continue any number of rows from zero to the chosen + * stride, inclusive. An empty result will only be returned if there are no + * more rows to retrieve. + * @return Reference to this very stream, to facilitate "chained" invocations + * ("C >> r1 >> r2;") + */ + icursorstream &operator>>(result &res) { return get(res); } //[t81] + + /// Move given number of rows forward (ignoring stride) without reading data + /** + * @return Reference to this very stream, to facilitate "chained" invocations + * ("C.ignore(2).get(r).ignore(4);") + */ + icursorstream &ignore(std::streamsize n=1); //[t81] + + /// Change stride, i.e. the number of rows to fetch per read operation + /** + * @param stride Must be a positive number + */ + void set_stride(difference_type stride); //[t81] + difference_type stride() const noexcept { return m_stride; } //[t81] + +private: + result fetchblock(); + + friend class internal::gate::icursorstream_icursor_iterator; + size_type forward(size_type n=1); + void insert_iterator(icursor_iterator *) noexcept; + void remove_iterator(icursor_iterator *) const noexcept; + + void service_iterators(difference_type); + + internal::sql_cursor m_cur; + + difference_type m_stride; + difference_type m_realpos, m_reqpos; + + mutable icursor_iterator *m_iterators; + + bool m_done; +}; + + +/// Approximate istream_iterator for icursorstream +/** Intended as an implementation of an input_iterator (as defined by the C++ + * Standard Library), this class supports only two basic operations: reading the + * current element, and moving forward. In addition to the minimal guarantees + * for istream_iterators, this class supports multiple successive reads of the + * same position (the current result set is cached in the iterator) even after + * copying and even after new data have been read from the stream. This appears + * to be a requirement for input_iterators. Comparisons are also supported in + * the general case. + * + * The iterator does not care about its own position, however. Moving an + * iterator forward moves the underlying stream forward and reads the data from + * the new stream position, regardless of the iterator's old position in the + * stream. + * + * The stream's stride defines the granularity for all iterator movement or + * access operations, i.e. "ici += 1" advances the stream by one stride's worth + * of rows, and "*ici++" reads one stride's worth of rows from the stream. + * + * @warning Do not read from the underlying stream or its cursor, move its read + * position, or change its stride, between the time the first icursor_iterator + * on it is created and the time its last icursor_iterator is destroyed. + * + * @warning Manipulating these iterators within the context of a single cursor + * stream is <em>not thread-safe</em>. Creating a new iterator, copying one, or + * destroying one affects the stream as a whole. + */ +class PQXX_LIBEXPORT icursor_iterator +{ +public: + using iterator_category = std::input_iterator_tag; + using value_type = result; + using pointer = const result *; + using reference = const result &; + using istream_type = icursorstream; + using size_type = istream_type::size_type; + using difference_type = istream_type::difference_type; + + icursor_iterator() noexcept; //[t84] + explicit icursor_iterator(istream_type &) noexcept; //[t84] + icursor_iterator(const icursor_iterator &) noexcept; //[t84] + ~icursor_iterator() noexcept; + + const result &operator*() const { refresh(); return m_here; } //[t84] + const result *operator->() const { refresh(); return &m_here; } //[t84] + icursor_iterator &operator++(); //[t84] + icursor_iterator operator++(int); //[t84] + icursor_iterator &operator+=(difference_type); //[t84] + icursor_iterator &operator=(const icursor_iterator &) noexcept; //[t84] + + bool operator==(const icursor_iterator &rhs) const; //[t84] + bool operator!=(const icursor_iterator &rhs) const noexcept //[t84] + { return not operator==(rhs); } + bool operator<(const icursor_iterator &rhs) const; //[t84] + bool operator>(const icursor_iterator &rhs) const //[t84] + { return rhs < *this; } + bool operator<=(const icursor_iterator &rhs) const //[t84] + { return not (*this > rhs); } + bool operator>=(const icursor_iterator &rhs) const //[t84] + { return not (*this < rhs); } + +private: + void refresh() const; + + friend class internal::gate::icursor_iterator_icursorstream; + difference_type pos() const noexcept { return m_pos; } + void fill(const result &); + + icursorstream *m_stream = nullptr; + result m_here; + difference_type m_pos; + icursor_iterator *m_prev = nullptr, *m_next = nullptr; +}; +} // namespace pqxx + +#include "pqxx/compiler-internal-post.hxx" +#endif diff --git a/contrib/libs/libpqxx/include/pqxx/dbtransaction b/contrib/libs/libpqxx/include/pqxx/dbtransaction new file mode 100644 index 0000000000..d3d6092ca9 --- /dev/null +++ b/contrib/libs/libpqxx/include/pqxx/dbtransaction @@ -0,0 +1,6 @@ +/** pqxx::dbtransaction abstract base class. + * + * pqxx::dbransaction defines a real transaction on the database. + */ +// Actual definitions in .hxx file so editors and such recognize file type. +#include "pqxx/dbtransaction.hxx" diff --git a/contrib/libs/libpqxx/include/pqxx/dbtransaction.hxx b/contrib/libs/libpqxx/include/pqxx/dbtransaction.hxx new file mode 100644 index 0000000000..8ba7d70c6f --- /dev/null +++ b/contrib/libs/libpqxx/include/pqxx/dbtransaction.hxx @@ -0,0 +1,109 @@ +/** Definition of the pqxx::dbtransaction abstract base class. + * + * pqxx::dbransaction defines a real transaction on the database. + * + * DO NOT INCLUDE THIS FILE DIRECTLY; include pqxx/dbtransaction 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_DBTRANSACTION +#define PQXX_H_DBTRANSACTION + +#include "pqxx/compiler-public.hxx" +#include "pqxx/compiler-internal-pre.hxx" + +#include "pqxx/transaction_base.hxx" + +namespace pqxx +{ + +enum readwrite_policy +{ + read_only, + read_write +}; + + +/// Abstract base class responsible for bracketing a backend transaction. +/** + * @ingroup transaction + * + * Use a dbtransaction-derived object such as "work" (transaction<>) to enclose + * operations on a database in a single "unit of work." This ensures that the + * whole series of operations either succeeds as a whole or fails completely. + * In no case will it leave half-finished work behind in the database. + * + * Once processing on a transaction has succeeded and any changes should be + * allowed to become permanent in the database, call commit(). If something + * has gone wrong and the changes should be forgotten, call abort() instead. + * If you do neither, an implicit abort() is executed at destruction time. + * + * It is an error to abort a transaction that has already been committed, or to + * commit a transaction that has already been aborted. Aborting an already + * aborted transaction or committing an already committed one has been allowed + * to make errors easier to deal with. Repeated aborts or commits have no + * effect after the first one. + * + * Database transactions are not suitable for guarding long-running processes. + * If your transaction code becomes too long or too complex, please consider + * ways to break it up into smaller ones. There's no easy, general way to do + * this since application-specific considerations become important at this + * point. + * + * The actual operations for beginning and committing/aborting the backend + * transaction are implemented by a derived class. The implementing concrete + * class must also call Begin() and End() from its constructors and destructors, + * respectively, and implement do_exec(). + */ +class PQXX_LIBEXPORT PQXX_NOVTABLE dbtransaction : public transaction_base +{ +public: + virtual ~dbtransaction(); + +protected: + dbtransaction( + connection_base &, + const std::string &IsolationString, + readwrite_policy rw=read_write); + + explicit dbtransaction( + connection_base &, + bool direct=true, + readwrite_policy rw=read_write); + + + /// Start a transaction on the backend and set desired isolation level + void start_backend_transaction(); + + /// Sensible default implemented here: begin backend transaction + virtual void do_begin() override; //[t01] + /// Sensible default implemented here: perform query + virtual result do_exec(const char Query[]) override; + /// To be implemented by derived class: commit backend transaction + virtual void do_commit() override =0; + /// Sensible default implemented here: abort backend transaction + /** Default implementation does two things: + * <ol> + * <li>Clears the "connection reactivation avoidance counter"</li> + * <li>Executes a ROLLBACK statement</li> + * </ol> + */ + virtual void do_abort() override; //[t13] + + static std::string fullname(const std::string &ttype, + const std::string &isolation); + +private: + /// Precomputed SQL command to run at start of this transaction + std::string m_start_cmd; +}; + +} // namespace pqxx + +#include "pqxx/compiler-internal-post.hxx" + +#endif diff --git a/contrib/libs/libpqxx/include/pqxx/errorhandler b/contrib/libs/libpqxx/include/pqxx/errorhandler new file mode 100644 index 0000000000..fda3c0ae62 --- /dev/null +++ b/contrib/libs/libpqxx/include/pqxx/errorhandler @@ -0,0 +1,6 @@ +/** pqxx::errorhandler class. + * + * Callbacks for handling errors and warnings. + */ +// Actual definitions in .hxx file so editors and such recognize file type. +#include "pqxx/errorhandler.hxx" diff --git a/contrib/libs/libpqxx/include/pqxx/errorhandler.hxx b/contrib/libs/libpqxx/include/pqxx/errorhandler.hxx new file mode 100644 index 0000000000..03ce923a3b --- /dev/null +++ b/contrib/libs/libpqxx/include/pqxx/errorhandler.hxx @@ -0,0 +1,96 @@ +/** Definition of the pqxx::errorhandler class. + * + * pqxx::errorhandler handlers errors and warnings in a database session. + * + * 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_ERRORHANDLER +#define PQXX_H_ERRORHANDLER + +#include "pqxx/compiler-public.hxx" +#include "pqxx/compiler-internal-pre.hxx" + +#include "pqxx/types.hxx" + + +namespace pqxx +{ +namespace internal +{ +namespace gate +{ +class errorhandler_connection_base; +} +} + +/** + * @addtogroup errorhandler + * @{ + */ + +/// Base class for error-handler callbacks. +/** To receive errors and warnings from a connection, subclass this with your + * own error-handler functor, and instantiate it for the connection. Destroying + * the handler un-registers it. + * + * A connection can have multiple error handlers at the same time. When the + * database connection emits an error or warning message, it passes the message + * to each error handler, starting with the most recently registered one and + * progressing towards the oldest one. However an error handler may also + * instruct the connection not to pass the message to further handlers by + * returning "false." + * + * @warning Strange things happen when a result object outlives its parent + * connection. If you register an error handler on a connection, then you must + * not access the result after destroying the connection. This applies even if + * you destroy the error handler first! + */ +class PQXX_LIBEXPORT errorhandler +{ +public: + explicit errorhandler(connection_base &); + virtual ~errorhandler(); + + /// Define in subclass: receive an error or warning message from the database. + /** + * @return Whether the same error message should also be passed to the + * remaining, older errorhandlers. + */ + virtual bool operator()(const char msg[]) noexcept =0; + +private: + connection_base *m_home; + + friend class internal::gate::errorhandler_connection_base; + void unregister() noexcept; + + errorhandler() =delete; + errorhandler(const errorhandler &) =delete; + errorhandler &operator=(const errorhandler &) =delete; +}; + + +/// An error handler that suppresses any previously registered error handlers. +class quiet_errorhandler : public errorhandler +{ +public: + quiet_errorhandler(connection_base &conn) : errorhandler{conn} {} + + virtual bool operator()(const char[]) noexcept override { return false; } +}; + +/** + * @} + */ + +} // namespace pqxx + +#include "pqxx/compiler-internal-post.hxx" + +#endif diff --git a/contrib/libs/libpqxx/include/pqxx/except b/contrib/libs/libpqxx/include/pqxx/except new file mode 100644 index 0000000000..e3cf0b0d5c --- /dev/null +++ b/contrib/libs/libpqxx/include/pqxx/except @@ -0,0 +1,6 @@ +/** libpqxx exception classes. + * + * pqxx::sql_error, pqxx::broken_connection, pqxx::in_doubt_error, ... + */ +// Actual definitions in .hxx file so editors and such recognize file type. +#include "pqxx/except.hxx" diff --git a/contrib/libs/libpqxx/include/pqxx/except.hxx b/contrib/libs/libpqxx/include/pqxx/except.hxx new file mode 100644 index 0000000000..24d52d13e3 --- /dev/null +++ b/contrib/libs/libpqxx/include/pqxx/except.hxx @@ -0,0 +1,532 @@ +/** Definition of libpqxx exception classes. + * + * pqxx::sql_error, pqxx::broken_connection, pqxx::in_doubt_error, ... + * + * DO NOT INCLUDE THIS FILE DIRECTLY; include pqxx/except 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_EXCEPT +#define PQXX_H_EXCEPT + +#include "pqxx/compiler-public.hxx" +#include "pqxx/compiler-internal-pre.hxx" + +#include <stdexcept> + +#include "pqxx/util.hxx" + + +namespace pqxx +{ + +/** + * @addtogroup exception Exception classes + * + * These exception classes follow, roughly, the two-level hierarchy defined by + * the PostgreSQL error codes (see Appendix A of the PostgreSQL documentation + * corresponding to your server version). The hierarchy given here is, as yet, + * not a complete mirror of the error codes. There are some other differences + * as well, e.g. the error code statement_completion_unknown has a separate + * status in libpqxx as in_doubt_error, and too_many_connections is classified + * as a broken_connection rather than a subtype of insufficient_resources. + * + * @see http://www.postgresql.org/docs/9.4/interactive/errcodes-appendix.html + * + * @{ + */ + +/// Mixin base class to identify libpqxx-specific exception types +/** + * If you wish to catch all exception types specific to libpqxx for some reason, + * catch this type. All of libpqxx's exception classes are derived from it + * through multiple-inheritance (they also fit into the standard library's + * exception hierarchy in more fitting places). + * + * This class is not derived from std::exception, since that could easily lead + * to exception classes with multiple std::exception base-class objects. As + * Bart Samwel points out, "catch" is subject to some nasty fineprint in such + * cases. + */ +class PQXX_LIBEXPORT PQXX_NOVTABLE pqxx_exception +{ +public: + /// Support run-time polymorphism, and keep this class abstract + virtual ~pqxx_exception() noexcept =0; + + /// Return std::exception base-class object + /** Use this to get at the exception's what() function, or to downcast to a + * more specific type using dynamic_cast. + * + * Casting directly from pqxx_exception to a specific exception type is not + * likely to work since pqxx_exception is not (and could not safely be) + * derived from std::exception. + * + * For example, to test dynamically whether an exception is an sql_error: + * + * @code + * try + * { + * // ... + * } + * catch (const pqxx::pqxx_exception &e) + * { + * std::cerr << e.base().what() << std::endl; + * const pqxx::sql_error *s=dynamic_cast<const pqxx::sql_error*>(&e.base()); + * if (s) std::cerr << "Query was: " << s->query() << std::endl; + * } + * @endcode + */ + PQXX_CONST virtual const std::exception &base() const noexcept =0; //[t00] +}; + + +/// Run-time failure encountered by libpqxx, similar to std::runtime_error +class PQXX_LIBEXPORT failure : + public pqxx_exception, public std::runtime_error +{ + virtual const std::exception &base() const noexcept override + { return *this; } +public: + explicit failure(const std::string &); +}; + + +/// Exception class for lost or failed backend connection. +/** + * @warning When this happens on Unix-like systems, you may also get a SIGPIPE + * signal. That signal aborts the program by default, so if you wish to be able + * to continue after a connection breaks, be sure to disarm this signal. + * + * If you're working on a Unix-like system, see the manual page for + * @c signal (2) on how to deal with SIGPIPE. The easiest way to make this + * signal harmless is to make your program ignore it: + * + * @code + * #include <signal.h> + * + * int main() + * { + * signal(SIGPIPE, SIG_IGN); + * // ... + * @endcode + */ +class PQXX_LIBEXPORT broken_connection : public failure +{ +public: + broken_connection(); + explicit broken_connection(const std::string &); +}; + + +/// Exception class for failed queries. +/** Carries, in addition to a regular error message, a copy of the failed query + * and (if available) the SQLSTATE value accompanying the error. + */ +class PQXX_LIBEXPORT sql_error : public failure +{ + /// Query string. Empty if unknown. + const std::string m_query; + /// SQLSTATE string describing the error type, if known; or empty string. + const std::string m_sqlstate; + +public: + explicit sql_error( + const std::string &msg="", + const std::string &Q="", + const char sqlstate[]=nullptr); + virtual ~sql_error() noexcept; + + /// The query whose execution triggered the exception + PQXX_PURE const std::string &query() const noexcept; //[t56] + + /// SQLSTATE error code if known, or empty string otherwise. + PQXX_PURE const std::string &sqlstate() const noexcept; +}; + + +/// "Help, I don't know whether transaction was committed successfully!" +/** Exception that might be thrown in rare cases where the connection to the + * database is lost while finishing a database transaction, and there's no way + * of telling whether it was actually executed by the backend. In this case + * the database is left in an indeterminate (but consistent) state, and only + * manual inspection will tell which is the case. + */ +class PQXX_LIBEXPORT in_doubt_error : public failure +{ +public: + explicit in_doubt_error(const std::string &); +}; + + +/// The backend saw itself forced to roll back the ongoing transaction. +class PQXX_LIBEXPORT transaction_rollback : public failure +{ +public: + explicit transaction_rollback(const std::string &); +}; + + +/// Transaction failed to serialize. Please retry it. +/** Can only happen at transaction isolation levels REPEATABLE READ and + * SERIALIZABLE. + * + * The current transaction cannot be committed without violating the guarantees + * made by its isolation level. This is the effect of a conflict with another + * ongoing transaction. The transaction may still succeed if you try to + * perform it again. + */ +class PQXX_LIBEXPORT serialization_failure : public transaction_rollback +{ +public: + explicit serialization_failure(const std::string &); +}; + + +/// We can't tell whether our last statement succeeded. +class PQXX_LIBEXPORT statement_completion_unknown : public transaction_rollback +{ +public: + explicit statement_completion_unknown(const std::string &); +}; + + +/// The ongoing transaction has deadlocked. Retrying it may help. +class PQXX_LIBEXPORT deadlock_detected : public transaction_rollback +{ +public: + explicit deadlock_detected(const std::string &); +}; + + +/// Internal error in libpqxx library +class PQXX_LIBEXPORT internal_error : + public pqxx_exception, public std::logic_error +{ + virtual const std::exception &base() const noexcept override + { return *this; } +public: + explicit internal_error(const std::string &); +}; + + +/// Error in usage of libpqxx library, similar to std::logic_error +class PQXX_LIBEXPORT usage_error : + public pqxx_exception, public std::logic_error +{ + virtual const std::exception &base() const noexcept override + { return *this; } +public: + explicit usage_error(const std::string &); +}; + + +/// Invalid argument passed to libpqxx, similar to std::invalid_argument +class PQXX_LIBEXPORT argument_error : + public pqxx_exception, public std::invalid_argument +{ + virtual const std::exception &base() const noexcept override + { return *this; } +public: + explicit argument_error(const std::string &); +}; + + +/// Value conversion failed, e.g. when converting "Hello" to int. +class PQXX_LIBEXPORT conversion_error : + public pqxx_exception, public std::domain_error +{ + virtual const std::exception &base() const noexcept override + { return *this; } +public: + explicit conversion_error(const std::string &); +}; + + +/// Something is out of range, similar to std::out_of_range +class PQXX_LIBEXPORT range_error : + public pqxx_exception, public std::out_of_range +{ + virtual const std::exception &base() const noexcept override + { return *this; } +public: + explicit range_error(const std::string &); +}; + + +/// Query returned an unexpected number of rows. +class PQXX_LIBEXPORT unexpected_rows : public range_error +{ + virtual const std::exception &base() const noexcept override + { return *this; } +public: + explicit unexpected_rows(const std::string &msg) : range_error{msg} {} +}; + + +/// Database feature not supported in current setup +class PQXX_LIBEXPORT feature_not_supported : public sql_error +{ +public: + explicit feature_not_supported( + const std::string &err, + const std::string &Q="", + const char sqlstate[]=nullptr) : + sql_error{err, Q, sqlstate} {} +}; + +/// Error in data provided to SQL statement +class PQXX_LIBEXPORT data_exception : public sql_error +{ +public: + explicit data_exception( + const std::string &err, + const std::string &Q="", + const char sqlstate[]=nullptr) : + sql_error{err, Q, sqlstate} {} +}; + +class PQXX_LIBEXPORT integrity_constraint_violation : public sql_error +{ +public: + explicit integrity_constraint_violation( + const std::string &err, + const std::string &Q="", + const char sqlstate[]=nullptr) : + sql_error{err, Q, sqlstate} {} +}; + +class PQXX_LIBEXPORT restrict_violation : + public integrity_constraint_violation +{ +public: + explicit restrict_violation( + const std::string &err, + const std::string &Q="", + const char sqlstate[]=nullptr) : + integrity_constraint_violation{err, Q, sqlstate} {} +}; + +class PQXX_LIBEXPORT not_null_violation : + public integrity_constraint_violation +{ +public: + explicit not_null_violation( + const std::string &err, + const std::string &Q="", + const char sqlstate[]=nullptr) : + integrity_constraint_violation{err, Q, sqlstate} {} +}; + +class PQXX_LIBEXPORT foreign_key_violation : + public integrity_constraint_violation +{ +public: + explicit foreign_key_violation( + const std::string &err, + const std::string &Q="", + const char sqlstate[]=nullptr) : + integrity_constraint_violation{err, Q, sqlstate} {} +}; + +class PQXX_LIBEXPORT unique_violation : + public integrity_constraint_violation +{ +public: + explicit unique_violation( + const std::string &err, + const std::string &Q="", + const char sqlstate[]=nullptr) : + integrity_constraint_violation{err, Q, sqlstate} {} +}; + +class PQXX_LIBEXPORT check_violation : + public integrity_constraint_violation +{ +public: + explicit check_violation( + const std::string &err, + const std::string &Q="", + const char sqlstate[]=nullptr) : + integrity_constraint_violation{err, Q, sqlstate} {} +}; + +class PQXX_LIBEXPORT invalid_cursor_state : public sql_error +{ +public: + explicit invalid_cursor_state( + const std::string &err, + const std::string &Q="", + const char sqlstate[]=nullptr) : + sql_error{err, Q, sqlstate} {} +}; + +class PQXX_LIBEXPORT invalid_sql_statement_name : public sql_error +{ +public: + explicit invalid_sql_statement_name( + const std::string &err, + const std::string &Q="", + const char sqlstate[]=nullptr) : + sql_error{err, Q, sqlstate} {} +}; + +class PQXX_LIBEXPORT invalid_cursor_name : public sql_error +{ +public: + explicit invalid_cursor_name( + const std::string &err, + const std::string &Q="", + const char sqlstate[]=nullptr) : + sql_error{err, Q, sqlstate} {} +}; + +class PQXX_LIBEXPORT syntax_error : public sql_error +{ +public: + /// Approximate position in string where error occurred, or -1 if unknown. + const int error_position; + + explicit syntax_error( + const std::string &err, + const std::string &Q="", + const char sqlstate[]=nullptr, + int pos=-1) : + sql_error{err, Q, sqlstate}, error_position{pos} {} +}; + +class PQXX_LIBEXPORT undefined_column : public syntax_error +{ +public: + explicit undefined_column( + const std::string &err, + const std::string &Q="", + const char sqlstate[]=nullptr) : + syntax_error{err, Q, sqlstate} {} +}; + +class PQXX_LIBEXPORT undefined_function : public syntax_error +{ +public: + explicit undefined_function( + const std::string &err, + const std::string &Q="", + const char sqlstate[]=nullptr) : + syntax_error{err, Q, sqlstate} {} +}; + +class PQXX_LIBEXPORT undefined_table : public syntax_error +{ +public: + explicit undefined_table( + const std::string &err, + const std::string &Q="", + const char sqlstate[]=nullptr) : + syntax_error{err, Q, sqlstate} {} +}; + +class PQXX_LIBEXPORT insufficient_privilege : public sql_error +{ +public: + explicit insufficient_privilege( + const std::string &err, + const std::string &Q="", + const char sqlstate[]=nullptr) : + sql_error{err, Q, sqlstate} {} +}; + +/// Resource shortage on the server +class PQXX_LIBEXPORT insufficient_resources : public sql_error +{ +public: + explicit insufficient_resources( + const std::string &err, + const std::string &Q="", + const char sqlstate[]=nullptr) : + sql_error{err,Q, sqlstate} {} +}; + +class PQXX_LIBEXPORT disk_full : public insufficient_resources +{ +public: + explicit disk_full( + const std::string &err, + const std::string &Q="", + const char sqlstate[]=nullptr) : + insufficient_resources{err, Q, sqlstate} {} +}; + +class PQXX_LIBEXPORT out_of_memory : public insufficient_resources +{ +public: + explicit out_of_memory( + const std::string &err, + const std::string &Q="", + const char sqlstate[]=nullptr) : + insufficient_resources{err, Q, sqlstate} {} +}; + +class PQXX_LIBEXPORT too_many_connections : public broken_connection +{ +public: + explicit too_many_connections(const std::string &err) : + broken_connection{err} {} +}; + +/// PL/pgSQL error +/** Exceptions derived from this class are errors from PL/pgSQL procedures. + */ +class PQXX_LIBEXPORT plpgsql_error : public sql_error +{ +public: + explicit plpgsql_error( + const std::string &err, + const std::string &Q="", + const char sqlstate[]=nullptr) : + sql_error{err, Q, sqlstate} {} +}; + +/// Exception raised in PL/pgSQL procedure +class PQXX_LIBEXPORT plpgsql_raise : public plpgsql_error +{ +public: + explicit plpgsql_raise( + const std::string &err, + const std::string &Q="", + const char sqlstate[]=nullptr) : + plpgsql_error{err, Q, sqlstate} {} +}; + +class PQXX_LIBEXPORT plpgsql_no_data_found : public plpgsql_error +{ +public: + explicit plpgsql_no_data_found( + const std::string &err, + const std::string &Q="", + const char sqlstate[]=nullptr) : + plpgsql_error{err, Q, sqlstate} {} +}; + +class PQXX_LIBEXPORT plpgsql_too_many_rows : public plpgsql_error +{ +public: + explicit plpgsql_too_many_rows( + const std::string &err, + const std::string &Q="", + const char sqlstate[]=nullptr) : + plpgsql_error{err, Q, sqlstate} {} +}; + +/** + * @} + */ + +} + +#include "pqxx/compiler-internal-post.hxx" + +#endif diff --git a/contrib/libs/libpqxx/include/pqxx/field b/contrib/libs/libpqxx/include/pqxx/field new file mode 100644 index 0000000000..e799e6797b --- /dev/null +++ b/contrib/libs/libpqxx/include/pqxx/field @@ -0,0 +1,6 @@ +/** pqxx::field class. + * + * pqxx::field refers to a field in a query result. + */ +// Actual definitions in .hxx file so editors and such recognize file type. +#include "pqxx/field.hxx" diff --git a/contrib/libs/libpqxx/include/pqxx/field.hxx b/contrib/libs/libpqxx/include/pqxx/field.hxx new file mode 100644 index 0000000000..5676d2a848 --- /dev/null +++ b/contrib/libs/libpqxx/include/pqxx/field.hxx @@ -0,0 +1,373 @@ +/** Definitions for the pqxx::field class. + * + * pqxx::field refers to a field in a query result. + * + * DO NOT INCLUDE THIS FILE DIRECTLY; include pqxx/field 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_FIELD +#define PQXX_H_FIELD + +#include "pqxx/compiler-public.hxx" +#include "pqxx/compiler-internal-pre.hxx" +#include "pqxx/internal/type_utils.hxx" + +#if defined(PQXX_HAVE_OPTIONAL) +#include <optional> + +/* Use std::experimental::optional as a fallback for std::optional, if + * present. + * + * This may break compilation for some software, if using a libpqxx that was + * configured for a different language version. To stop libpqxx headers from + * using or supporting std::experimental::optional, define a macro + * PQXX_HIDE_EXP_OPTIONAL when building your software. + */ +#elif defined(PQXX_HAVE_EXP_OPTIONAL) && !defined(PQXX_HIDE_EXP_OPTIONAL) +#error #include <experimental/optional> +#endif + +#include "pqxx/array.hxx" +#include "pqxx/result.hxx" +#include "pqxx/strconv.hxx" +#include "pqxx/types.hxx" + + +// Methods tested in eg. test module test01 are marked with "//[t01]". + +namespace pqxx +{ +/// Reference to a field in a result set. +/** A field represents one entry in a row. It represents an actual value + * in the result set, and can be converted to various types. + */ +class PQXX_LIBEXPORT field +{ +public: + using size_type = field_size_type; + + /// Constructor. + /** Create field as reference to a field in a result set. + * @param R Row that this field is part of. + * @param C Column number of this field. + */ + field(const row &R, row_size_type C) noexcept; //[t01] + + /** + * @name Comparison + */ + //@{ + /// Byte-by-byte comparison of two fields (all nulls are considered equal) + /** @warning null handling is still open to discussion and change! + * + * Handling of null values differs from that in SQL where a comparison + * involving a null value yields null, so nulls are never considered equal + * to one another or even to themselves. + * + * Null handling also probably differs from the closest equivalent in C++, + * which is the NaN (Not-a-Number) value, a singularity comparable to + * SQL's null. This is because the builtin == operator demands that a == a. + * + * The usefulness of this operator is questionable. No interpretation + * whatsoever is imposed on the data; 0 and 0.0 are considered different, + * as are null vs. the empty string, or even different (but possibly + * equivalent and equally valid) encodings of the same Unicode character + * etc. + */ + bool operator==(const field &) const; //[t75] + + /// Byte-by-byte comparison (all nulls are considered equal) + /** @warning See operator==() for important information about this operator + */ + bool operator!=(const field &rhs) const //[t82] + {return not operator==(rhs);} + //@} + + /** + * @name Column information + */ + //@{ + /// Column name + const char *name() const; //[t11] + + /// Column type + oid type() const; //[t07] + + /// What table did this column come from? + oid table() const; //[t02] + + row_size_type num() const { return col(); } //[t82] + + /// What column number in its originating table did this column come from? + row_size_type table_column() const; //[t93] + //@} + + /** + * @name Content access + */ + //@{ + /// Read as plain C string + /** Since the field's data is stored internally in the form of a + * zero-terminated C string, this is the fastest way to read it. Use the + * to() or as() functions to convert the string to other types such as + * @c int, or to C++ strings. + */ + const char *c_str() const; //[t02] + + /// Is this field's value null? + bool is_null() const noexcept; //[t12] + + /// Return number of bytes taken up by the field's value. + /** + * Includes the terminating zero byte. + */ + size_type size() const noexcept; //[t11] + + /// Read value into Obj; or leave Obj untouched and return @c false if null + /** Note this can be used with optional types (except pointers other than + * C-strings) + */ + template<typename T> auto to(T &Obj) const //[t03] + -> typename std::enable_if<( + not std::is_pointer<T>::value + or std::is_same<T, const char*>::value + ), bool>::type + { + const char *const bytes = c_str(); + if (bytes[0] == '\0' and is_null()) return false; + from_string(bytes, Obj); + return true; + } + + /// Read value into Obj; or leave Obj untouched and return @c false if null + template<typename T> bool operator>>(T &Obj) const //[t07] + { return to(Obj); } + + /// Read value into Obj; or use Default & return @c false if null + /** Note this can be used with optional types (except pointers other than + * C-strings) + */ + template<typename T> auto to(T &Obj, const T &Default) const //[t12] + -> typename std::enable_if<( + not std::is_pointer<T>::value + or std::is_same<T, const char*>::value + ), bool>::type + { + const bool NotNull = to(Obj); + if (not NotNull) Obj = Default; + return NotNull; + } + + /// Return value as object of given type, or Default if null + /** Note that unless the function is instantiated with an explicit template + * argument, the Default value's type also determines the result type. + */ + template<typename T> T as(const T &Default) const //[t01] + { + T Obj; + to(Obj, Default); + return Obj; + } + + /// Return value as object of given type, or throw exception if null + /** Use as `as<std::optional<int>>()` or `as<my_untemplated_optional_t>()` as + * an alternative to `get<int>()`; this is disabled for use with raw pointers + * (other than C-strings) because storage for the value can't safely be + * allocated here + */ + template<typename T> T as() const //[t45] + { + T Obj; + if (not to(Obj)) Obj = string_traits<T>::null(); + return Obj; + } + + /// Return value wrapped in some optional type (empty for nulls) + /** Use as `get<int>()` as before to obtain previous behavior (i.e. only + * usable when `std::optional` or `std::experimental::optional` are + * available), or specify container type with `get<int, std::optional>()` + */ + template<typename T, template<typename> class O +#if defined(PQXX_HAVE_OPTIONAL) + = std::optional +#elif defined(PQXX_HAVE_EXP_OPTIONAL) && !defined(PQXX_HIDE_EXP_OPTIONAL) + = std::experimental::optional +#endif + > constexpr O<T> get() const { return as<O<T>>(); } + + /// Parse the field as an SQL array. + /** Call the parser to retrieve values (and structure) from the array. + * + * Make sure the @c result object stays alive until parsing is finished. If + * you keep the @c row of @c field object alive, it will keep the @c result + * object alive as well. + */ + array_parser as_array() const + { return array_parser{c_str(), m_home.m_encoding}; } + //@} + + +protected: + const result &home() const noexcept { return m_home; } + size_t idx() const noexcept { return m_row; } + row_size_type col() const noexcept { return row_size_type(m_col); } + + /** + * You'd expect this to be a size_t, but due to the way reverse iterators + * are related to regular iterators, it must be allowed to underflow to -1. + */ + long m_col; + +private: + result m_home; + size_t m_row; +}; + + +/// Specialization: <tt>to(string &)</tt>. +template<> +inline bool field::to<std::string>(std::string &Obj) const +{ + const char *const bytes = c_str(); + if (bytes[0] == '\0' and is_null()) return false; + Obj = std::string{bytes, size()}; + return true; +} + +/// Specialization: <tt>to(const char *&)</tt>. +/** The buffer has the same lifetime as the data in this result (i.e. of this + * result object, or the last remaining one copied from it etc.), so take care + * not to use it after the last result object referring to this query result is + * destroyed. + */ +template<> +inline bool field::to<const char *>(const char *&Obj) const +{ + if (is_null()) return false; + Obj = c_str(); + return true; +} + + +template<typename CHAR=char, typename TRAITS=std::char_traits<CHAR>> + class field_streambuf : + public std::basic_streambuf<CHAR, TRAITS> +{ +public: + using char_type = CHAR; + using traits_type = TRAITS; + using int_type = typename traits_type::int_type; + using pos_type = typename traits_type::pos_type; + using off_type = typename traits_type::off_type; + using openmode = std::ios::openmode; + using seekdir = std::ios::seekdir; + + explicit field_streambuf(const field &F) : //[t74] + m_field{F} + { + initialize(); + } + +protected: + virtual int sync() override { return traits_type::eof(); } + +protected: + virtual pos_type seekoff(off_type, seekdir, openmode) override + { return traits_type::eof(); } + virtual pos_type seekpos(pos_type, openmode) override + {return traits_type::eof();} + virtual int_type overflow(int_type) override + { return traits_type::eof(); } + virtual int_type underflow() override + { return traits_type::eof(); } + +private: + const field &m_field; + + int_type initialize() + { + char_type *G = + reinterpret_cast<char_type *>(const_cast<char *>(m_field.c_str())); + this->setg(G, G, G + m_field.size()); + return int_type(m_field.size()); + } +}; + + +/// Input stream that gets its data from a result field +/** Use this class exactly as you would any other istream to read data from a + * field. All formatting and streaming operations of @c std::istream are + * supported. What you'll typically want to use, however, is the fieldstream + * alias (which defines a basic_fieldstream for @c char). This is similar to + * how e.g. @c std::ifstream relates to @c std::basic_ifstream. + * + * This class has only been tested for the char type (and its default traits). + */ +template<typename CHAR=char, typename TRAITS=std::char_traits<CHAR>> + class basic_fieldstream : + public std::basic_istream<CHAR, TRAITS> +{ + using super = std::basic_istream<CHAR, TRAITS>; + +public: + using char_type = CHAR; + using traits_type = TRAITS; + using int_type = typename traits_type::int_type; + using pos_type = typename traits_type::pos_type; + using off_type = typename traits_type::off_type; + + basic_fieldstream(const field &F) : super{nullptr}, m_buf{F} + { super::init(&m_buf); } + +private: + field_streambuf<CHAR, TRAITS> m_buf; +}; + +using fieldstream = basic_fieldstream<char>; + +/// Write a result field to any type of stream +/** This can be convenient when writing a field to an output stream. More + * importantly, it lets you write a field to e.g. a @c stringstream which you + * can then use to read, format and convert the field in ways that to() does not + * support. + * + * Example: parse a field into a variable of the nonstandard + * "<tt>long long</tt>" type. + * + * @code + * extern result R; + * long long L; + * stringstream S; + * + * // Write field's string into S + * S << R[0][0]; + * + * // Parse contents of S into L + * S >> L; + * @endcode + */ +template<typename CHAR> +inline std::basic_ostream<CHAR> &operator<<( + std::basic_ostream<CHAR> &S, const field &F) //[t46] +{ + S.write(F.c_str(), std::streamsize(F.size())); + return S; +} + + +/// Convert a field's string contents to another type. +template<typename T> +inline void from_string(const field &F, T &Obj) //[t46] + { from_string(F.c_str(), Obj, F.size()); } + +/// Convert a field to a string. +template<> PQXX_LIBEXPORT std::string to_string(const field &Obj); //[t74] + +} // namespace pqxx +#include "pqxx/compiler-internal-post.hxx" +#endif diff --git a/contrib/libs/libpqxx/include/pqxx/internal/callgate.hxx b/contrib/libs/libpqxx/include/pqxx/internal/callgate.hxx new file mode 100644 index 0000000000..02ac152636 --- /dev/null +++ b/contrib/libs/libpqxx/include/pqxx/internal/callgate.hxx @@ -0,0 +1,79 @@ +#ifndef PQXX_H_CALLGATE +#define PQXX_H_CALLGATE + +/* +Here's what a typical gate class definition looks like: + +#include <pqxx/internal/callgate.hxx> + +namespace pqxx +{ +namespace internal +{ +namespace gate +{ +class PQXX_PRIVATE @gateclass@ : callgate<@host@> +{ + friend class @client@; + + @gateclass@(reference x) : super(x) {} + + // Methods here. Use home() to access the host-class object. +}; +} // namespace pqxx::internal::gate +} // namespace pqxx::internal +} // namespace pqxx +*/ + +namespace pqxx +{ +namespace internal +{ +/// Base class for call gates. +/** + * A call gate defines a limited, private interface on the host class that + * specified client classes can access. + * + * The metaphor works as follows: the gate stands in front of a "home," which is + * really a class, and only lets specific friends in. + * + * To implement a call gate that gives client C access to host H, + * - derive a gate class from callgate<H>; + * - make the gate class a friend of H; + * - make C a friend of the gate class; and + * - implement "stuff C can do with H" as private members in the gate class. + * + * This special kind of "gated" friendship gives C private access to H, but only + * through an expressly limited interface. The gate class can access its host + * object as home(). + * + * Keep gate classes entirely stateless. They should be ultra-lightweight + * wrappers for their host classes, and be optimized away as much as possible by + * the compiler. Once you start adding state, you're on a slippery slope away + * from the pure, clean, limited interface pattern that gate classes are meant + * to implement. + * + * Ideally, all member functions of the gate class should be one-liners passing + * calls straight on to the host class. It can be useful however to break this + * rule temporarily during inter-class refactoring. + */ +template<typename HOME> class PQXX_PRIVATE callgate +{ +protected: + /// This class, to keep constructors easy. + using super = callgate<HOME>; + /// A reference to the host class. Helps keep constructors easy. + using reference = HOME &; + + callgate(reference x) : m_home(x) {} + + /// The home object. The gate class has full "private" access. + reference home() const noexcept { return m_home; } + +private: + reference m_home; +}; +} // namespace pqxx::internal +} // namespace pqxx + +#endif diff --git a/contrib/libs/libpqxx/include/pqxx/internal/encoding_group.hxx b/contrib/libs/libpqxx/include/pqxx/internal/encoding_group.hxx new file mode 100644 index 0000000000..be31d083b4 --- /dev/null +++ b/contrib/libs/libpqxx/include/pqxx/internal/encoding_group.hxx @@ -0,0 +1,46 @@ +/** Enum type for supporting encodings in libpqxx + * + * 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_ENCODING_GROUP +#define PQXX_H_ENCODING_GROUP + + +namespace pqxx +{ +namespace internal +{ + +// Types of encodings supported by PostgreSQL, see +// https://www.postgresql.org/docs/current/static/multibyte.html#CHARSET-TABLE +enum class encoding_group +{ + // Handles all single-byte fixed-width encodings + MONOBYTE, + + // Multibyte encodings + BIG5, + EUC_CN, + EUC_JP, + EUC_JIS_2004, + EUC_KR, + EUC_TW, + GB18030, + GBK, + JOHAB, + MULE_INTERNAL, + SJIS, + SHIFT_JIS_2004, + UHC, + UTF8 +}; + +} // namespace pqxx::internal +} // namespace pqxx + + +#endif diff --git a/contrib/libs/libpqxx/include/pqxx/internal/encodings.hxx b/contrib/libs/libpqxx/include/pqxx/internal/encodings.hxx new file mode 100644 index 0000000000..01ca223d48 --- /dev/null +++ b/contrib/libs/libpqxx/include/pqxx/internal/encodings.hxx @@ -0,0 +1,99 @@ +/** Internal string encodings support for libpqxx + * + * 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_ENCODINGS +#define PQXX_H_ENCODINGS + +#include "pqxx/compiler-public.hxx" +#include "pqxx/compiler-internal-pre.hxx" +#include "pqxx/internal/encoding_group.hxx" + +#include <string> + + +namespace pqxx +{ +namespace internal +{ +const char *name_encoding(int encoding_id); + +/// Convert libpq encoding enum or encoding name to its libpqxx group. +encoding_group enc_group(int /* libpq encoding ID */); +encoding_group enc_group(const std::string&); + + +/// Function type: "find the end of the current glyph." +/** This type of function takes a text buffer, and a location in that buffer, + * and returns the location one byte past the end of the current glyph. + * + * The start offset marks the beginning of the current glyph. It must fall + * within the buffer. + * + * There are multiple different glyph scnaner implementations, for different + * kinds of encodings. + */ +using glyph_scanner_func = + std::string::size_type( + const char buffer[], + std::string::size_type buffer_len, + std::string::size_type start); + + +/// Look up the glyph scanner function for a given encoding group. +/** To identify the glyph boundaries in a buffer, call this to obtain the + * scanner function appropriate for the buffer's encoding. Then, repeatedly + * call the scanner function to find the glyphs. + */ +PQXX_LIBEXPORT glyph_scanner_func *get_glyph_scanner(encoding_group); + + +/// Find a single-byte "needle" character in a "haystack" text buffer. +std::string::size_type find_with_encoding( + encoding_group enc, + const std::string& haystack, + char needle, + std::string::size_type start = 0 +); + + +PQXX_LIBEXPORT std::string::size_type find_with_encoding( + encoding_group enc, + const std::string& haystack, + const std::string& needle, + std::string::size_type start = 0 +); + + +/// Iterate over the glyphs in a buffer. +/** Scans the glyphs in the buffer, and for each, passes its begin and its + * one-past-end pointers to @c callback. + */ +template<typename CALLABLE> PQXX_LIBEXPORT inline void for_glyphs( + encoding_group enc, + CALLABLE callback, + const char buffer[], + std::string::size_type buffer_len, + std::string::size_type start = 0 +) +{ + const auto scan = get_glyph_scanner(enc); + for ( + std::string::size_type here = start, next; + here < buffer_len; + here = next + ) + { + next = scan(buffer, buffer_len, here); + callback(buffer + here, buffer + next); + } +} +} // namespace pqxx::internal +} // namespace pqxx + +#include "pqxx/compiler-internal-post.hxx" +#endif diff --git a/contrib/libs/libpqxx/include/pqxx/internal/gates/connection-dbtransaction.hxx b/contrib/libs/libpqxx/include/pqxx/internal/gates/connection-dbtransaction.hxx new file mode 100644 index 0000000000..8ef2e4744f --- /dev/null +++ b/contrib/libs/libpqxx/include/pqxx/internal/gates/connection-dbtransaction.hxx @@ -0,0 +1,22 @@ +#include <pqxx/internal/callgate.hxx> + +namespace pqxx +{ +class dbtransaction; + +namespace internal +{ +namespace gate +{ +class PQXX_PRIVATE connection_dbtransaction : callgate<connection_base> +{ + friend class pqxx::dbtransaction; + + connection_dbtransaction(reference x) : super(x) {} + + int get_reactivation_avoidance_count() const noexcept + { return home().m_reactivation_avoidance.get(); } +}; +} // namespace pqxx::internal::gate +} // namespace pqxx::internal +} // namespace pqxx diff --git a/contrib/libs/libpqxx/include/pqxx/internal/gates/connection-errorhandler.hxx b/contrib/libs/libpqxx/include/pqxx/internal/gates/connection-errorhandler.hxx new file mode 100644 index 0000000000..9c62704dbe --- /dev/null +++ b/contrib/libs/libpqxx/include/pqxx/internal/gates/connection-errorhandler.hxx @@ -0,0 +1,25 @@ +#include <pqxx/internal/callgate.hxx> + +namespace pqxx +{ +class connection_base; +class errorhandler; + +namespace internal +{ +namespace gate +{ +class PQXX_PRIVATE connection_errorhandler : callgate<connection_base> +{ + friend class pqxx::errorhandler; + + connection_errorhandler(reference x) : super(x) {} + + void register_errorhandler(errorhandler *h) + { home().register_errorhandler(h); } + void unregister_errorhandler(errorhandler *h) + { home().unregister_errorhandler(h); } +}; +} // namespace pqxx::internal::gate +} // namespace pqxx::internal +} // namespace pqxx diff --git a/contrib/libs/libpqxx/include/pqxx/internal/gates/connection-largeobject.hxx b/contrib/libs/libpqxx/include/pqxx/internal/gates/connection-largeobject.hxx new file mode 100644 index 0000000000..e4f3b28fcc --- /dev/null +++ b/contrib/libs/libpqxx/include/pqxx/internal/gates/connection-largeobject.hxx @@ -0,0 +1,35 @@ +#include <string> + +#include <pqxx/internal/callgate.hxx> +#include <pqxx/internal/libpq-forward.hxx> + +namespace pqxx +{ +class largeobject; + +namespace internal +{ +namespace gate +{ +class PQXX_PRIVATE connection_largeobject : callgate<connection_base> +{ + friend class pqxx::largeobject; + + connection_largeobject(reference x) : super(x) {} + + pq::PGconn *raw_connection() const { return home().raw_connection(); } +}; + + +class PQXX_PRIVATE const_connection_largeobject : + callgate<const connection_base> +{ + friend class pqxx::largeobject; + + const_connection_largeobject(reference x) : super(x) {} + + std::string error_message() const { return home().err_msg(); } +}; +} // namespace pqxx::internal::gate +} // namespace pqxx::internal +} // namespace pqxx diff --git a/contrib/libs/libpqxx/include/pqxx/internal/gates/connection-notification_receiver.hxx b/contrib/libs/libpqxx/include/pqxx/internal/gates/connection-notification_receiver.hxx new file mode 100644 index 0000000000..d03f048f37 --- /dev/null +++ b/contrib/libs/libpqxx/include/pqxx/internal/gates/connection-notification_receiver.hxx @@ -0,0 +1,27 @@ +#include <pqxx/internal/callgate.hxx> + +#include <pqxx/connection_base> + + +namespace pqxx +{ +class notification_receiver; + +namespace internal +{ +namespace gate +{ +class PQXX_PRIVATE connection_notification_receiver : callgate<connection_base> +{ + friend class pqxx::notification_receiver; + + connection_notification_receiver(reference x) : super(x) {} + + void add_receiver(notification_receiver *receiver) + { home().add_receiver(receiver); } + void remove_receiver(notification_receiver *receiver) noexcept + { home().remove_receiver(receiver); } +}; +} // namespace pqxx::internal::gate +} // namespace pqxx::internal +} // namespace pqxx diff --git a/contrib/libs/libpqxx/include/pqxx/internal/gates/connection-parameterized_invocation.hxx b/contrib/libs/libpqxx/include/pqxx/internal/gates/connection-parameterized_invocation.hxx new file mode 100644 index 0000000000..364c5b6dac --- /dev/null +++ b/contrib/libs/libpqxx/include/pqxx/internal/gates/connection-parameterized_invocation.hxx @@ -0,0 +1,37 @@ +#include <pqxx/internal/callgate.hxx> + +namespace pqxx +{ +class connection_base; + +namespace internal +{ +namespace gate +{ +class PQXX_PRIVATE connection_parameterized_invocation : + callgate<connection_base> +{ + friend class pqxx::internal::parameterized_invocation; + + connection_parameterized_invocation(reference x) : super(x) {} + + result parameterized_exec( + const std::string &query, + const char *const params[], + const int paramlengths[], + const int binaries[], + int nparams) + { +#include <pqxx/internal/ignore-deprecated-pre.hxx> + return home().parameterized_exec( + query, + params, + paramlengths, + binaries, + nparams); +#include <pqxx/internal/ignore-deprecated-post.hxx> + } +}; +} // namespace pqxx::internal::gate +} // namespace pqxx::internal +} // namespace pqxx diff --git a/contrib/libs/libpqxx/include/pqxx/internal/gates/connection-pipeline.hxx b/contrib/libs/libpqxx/include/pqxx/internal/gates/connection-pipeline.hxx new file mode 100644 index 0000000000..d7d42ef981 --- /dev/null +++ b/contrib/libs/libpqxx/include/pqxx/internal/gates/connection-pipeline.hxx @@ -0,0 +1,27 @@ +#include <pqxx/internal/callgate.hxx> +#include "pqxx/internal/libpq-forward.hxx" + +namespace pqxx +{ +namespace internal +{ +namespace gate +{ +class PQXX_PRIVATE connection_pipeline : callgate<connection_base> +{ + friend class pqxx::pipeline; + + connection_pipeline(reference x) : super(x) {} + + void start_exec(const std::string &query) { home().start_exec(query); } + pqxx::internal::pq::PGresult *get_result() { return home().get_result(); } + void cancel_query() { home().cancel_query(); } + + bool consume_input() noexcept { return home().consume_input(); } + bool is_busy() const noexcept { return home().is_busy(); } + + int encoding_id() { return home().encoding_id(); } +}; +} // namespace pqxx::internal::gate +} // namespace pqxx::internal +} // namespace pqxx diff --git a/contrib/libs/libpqxx/include/pqxx/internal/gates/connection-prepare-invocation.hxx b/contrib/libs/libpqxx/include/pqxx/internal/gates/connection-prepare-invocation.hxx new file mode 100644 index 0000000000..c1c29583cc --- /dev/null +++ b/contrib/libs/libpqxx/include/pqxx/internal/gates/connection-prepare-invocation.hxx @@ -0,0 +1,45 @@ +#include <pqxx/internal/callgate.hxx> + +namespace pqxx +{ +namespace prepare +{ +class invocation; +} // namespace pqxx::prepare + +namespace internal +{ +namespace gate +{ +class PQXX_PRIVATE connection_prepare_invocation : callgate<connection_base> +{ + friend class pqxx::prepare::invocation; + + connection_prepare_invocation(reference x) : super(x) {} + + /// @deprecated To be replaced by exec_prepared. + result prepared_exec( + const std::string &statement, + const char *const params[], + const int paramlengths[], + const int binary[], + int nparams, + result_format format) + { +#include <pqxx/internal/ignore-deprecated-pre.hxx> + return home().prepared_exec( + statement, + params, + paramlengths, + binary, + nparams, + format); +#include <pqxx/internal/ignore-deprecated-post.hxx> + } + + bool prepared_exists(const std::string &statement) const + { return home().prepared_exists(statement); } +}; +} // namespace pqxx::internal::gate +} // namespace pqxx::internal +} // namespace pqxx diff --git a/contrib/libs/libpqxx/include/pqxx/internal/gates/connection-reactivation_avoidance_exemption.hxx b/contrib/libs/libpqxx/include/pqxx/internal/gates/connection-reactivation_avoidance_exemption.hxx new file mode 100644 index 0000000000..48ef89a46e --- /dev/null +++ b/contrib/libs/libpqxx/include/pqxx/internal/gates/connection-reactivation_avoidance_exemption.hxx @@ -0,0 +1,24 @@ +#include <pqxx/internal/callgate.hxx> + +namespace pqxx +{ +namespace internal +{ +class reactivation_avoidance_exemption; + +namespace gate +{ +class PQXX_PRIVATE connection_reactivation_avoidance_exemption : + callgate<connection_base> +{ + friend class pqxx::internal::reactivation_avoidance_exemption; + + connection_reactivation_avoidance_exemption(reference x) : super(x) {} + + int get_counter() const { return home().m_reactivation_avoidance.get(); } + void add_counter(int x) const { home().m_reactivation_avoidance.add(x); } + void clear_counter() { home().m_reactivation_avoidance.clear(); } +}; +} // namespace pqxx::internal::gate +} // namespace pqxx::internal +} // namespace pqxx diff --git a/contrib/libs/libpqxx/include/pqxx/internal/gates/connection-sql_cursor.hxx b/contrib/libs/libpqxx/include/pqxx/internal/gates/connection-sql_cursor.hxx new file mode 100644 index 0000000000..bb2cfee177 --- /dev/null +++ b/contrib/libs/libpqxx/include/pqxx/internal/gates/connection-sql_cursor.hxx @@ -0,0 +1,25 @@ +#include <pqxx/internal/callgate.hxx> + +namespace pqxx +{ +namespace internal +{ +class sql_cursor; + +namespace gate +{ +class PQXX_PRIVATE connection_sql_cursor : callgate<connection_base> +{ + friend class pqxx::internal::sql_cursor; + + connection_sql_cursor(reference x) : super(x) {} + + result exec(const char query[], int retries) + { return home().exec(query, retries); } + + void add_reactivation_avoidance_count(int n) + { home().add_reactivation_avoidance_count(n); } +}; +} // namespace pqxx::internal::gate +} // namespace pqxx::internal +} // namespace pqxx diff --git a/contrib/libs/libpqxx/include/pqxx/internal/gates/connection-transaction.hxx b/contrib/libs/libpqxx/include/pqxx/internal/gates/connection-transaction.hxx new file mode 100644 index 0000000000..f2aaac07f7 --- /dev/null +++ b/contrib/libs/libpqxx/include/pqxx/internal/gates/connection-transaction.hxx @@ -0,0 +1,77 @@ +#include <pqxx/internal/callgate.hxx> + +namespace pqxx +{ +class connection_base; + +namespace internal +{ +namespace gate +{ +class PQXX_PRIVATE connection_transaction : callgate<connection_base> +{ + friend class pqxx::transaction_base; + + connection_transaction(reference x) : super(x) {} + + result exec(const char query[], int retries) + { return home().exec(query, retries); } + void register_transaction(transaction_base *t) + { home().register_transaction(t); } + void unregister_transaction(transaction_base *t) noexcept + { home().unregister_transaction(t); } + + bool read_copy_line(std::string &line) + { return home().read_copy_line(line); } + void write_copy_line(const std::string &line) + { home().write_copy_line(line); } + void end_copy_write() { home().end_copy_write(); } + + std::string raw_get_var(const std::string &var) + { return home().raw_get_var(var); } + void raw_set_var(const std::string &var, const std::string &value) + { home().raw_set_var(var, value); } + void add_variables(const std::map<std::string, std::string> &vars) + { home().add_variables(vars); } + + /// @deprecated To be replaced by exec_prepared. + result prepared_exec( + const std::string &statement, + const char *const params[], + const int paramlengths[], + const int binaries[], + int nparams) + { +#include <pqxx/internal/ignore-deprecated-pre.hxx> + return home().prepared_exec( + statement, + params, + paramlengths, + binaries, + nparams, + result_format::text); +#include <pqxx/internal/ignore-deprecated-post.hxx> + } + + result exec_prepared( + const std::string &statement, + const internal::params &args, + result_format format) + { + return home().exec_prepared(statement, args, format); + } + + result exec_params(const std::string &query, const internal::params &args) + { + return home().exec_params(query, args); + } + + bool prepared_exists(const std::string &statement) const + { return home().prepared_exists(statement); } + + void take_reactivation_avoidance(int counter) + { home().m_reactivation_avoidance.add(counter); } +}; +} // namespace pqxx::internal::gate +} // namespace pqxx::internal +} // namespace pqxx diff --git a/contrib/libs/libpqxx/include/pqxx/internal/gates/errorhandler-connection.hxx b/contrib/libs/libpqxx/include/pqxx/internal/gates/errorhandler-connection.hxx new file mode 100644 index 0000000000..1b118e5610 --- /dev/null +++ b/contrib/libs/libpqxx/include/pqxx/internal/gates/errorhandler-connection.hxx @@ -0,0 +1,19 @@ +#include <pqxx/internal/callgate.hxx> + +namespace pqxx +{ +namespace internal +{ +namespace gate +{ +class PQXX_PRIVATE errorhandler_connection_base : callgate<errorhandler> +{ + friend class pqxx::connection_base; + + errorhandler_connection_base(reference x) : super(x) {} + + void unregister() noexcept { home().unregister(); } +}; +} // namespace pqxx::internal::gate +} // namespace pqxx::internal +} // namespace pqxx diff --git a/contrib/libs/libpqxx/include/pqxx/internal/gates/icursor_iterator-icursorstream.hxx b/contrib/libs/libpqxx/include/pqxx/internal/gates/icursor_iterator-icursorstream.hxx new file mode 100644 index 0000000000..9c17cf2916 --- /dev/null +++ b/contrib/libs/libpqxx/include/pqxx/internal/gates/icursor_iterator-icursorstream.hxx @@ -0,0 +1,28 @@ +#include <pqxx/internal/callgate.hxx> + +namespace pqxx +{ +namespace internal +{ +namespace gate +{ +class PQXX_PRIVATE icursor_iterator_icursorstream : callgate<icursor_iterator> +{ + friend class pqxx::icursorstream; + + icursor_iterator_icursorstream(reference x) : super(x) {} + + icursor_iterator::difference_type pos() const noexcept + { return home().pos(); } + + icursor_iterator *get_prev() { return home().m_prev; } + void set_prev(icursor_iterator *i) { home().m_prev = i; } + + icursor_iterator *get_next() { return home().m_next; } + void set_next(icursor_iterator *i) { home().m_next = i; } + + void fill(const result &r) { home().fill(r); } +}; +} // namespace pqxx::internal::gate +} // namespace pqxx::internal +} // namespace pqxx diff --git a/contrib/libs/libpqxx/include/pqxx/internal/gates/icursorstream-icursor_iterator.hxx b/contrib/libs/libpqxx/include/pqxx/internal/gates/icursorstream-icursor_iterator.hxx new file mode 100644 index 0000000000..8f28336bb5 --- /dev/null +++ b/contrib/libs/libpqxx/include/pqxx/internal/gates/icursorstream-icursor_iterator.hxx @@ -0,0 +1,30 @@ +#include <pqxx/internal/callgate.hxx> + +namespace pqxx +{ +namespace internal +{ +namespace gate +{ +class PQXX_PRIVATE icursorstream_icursor_iterator : callgate<icursorstream> +{ + friend class pqxx::icursor_iterator; + + icursorstream_icursor_iterator(reference x) : super(x) {} + + void insert_iterator(icursor_iterator *i) noexcept + { home().insert_iterator(i); } + + void remove_iterator(icursor_iterator *i) const noexcept + { home().remove_iterator(i); } + + icursorstream::size_type forward() { return home().forward(); } + icursorstream::size_type forward(icursorstream::size_type n) + { return home().forward(n); } + + void service_iterators(icursorstream::difference_type p) + { home().service_iterators(p); } +}; +} // namespace pqxx::internal::gate +} // namespace pqxx::internal +} // namespace pqxx diff --git a/contrib/libs/libpqxx/include/pqxx/internal/gates/result-connection.hxx b/contrib/libs/libpqxx/include/pqxx/internal/gates/result-connection.hxx new file mode 100644 index 0000000000..76c8e7a1f1 --- /dev/null +++ b/contrib/libs/libpqxx/include/pqxx/internal/gates/result-connection.hxx @@ -0,0 +1,20 @@ +#include <pqxx/internal/callgate.hxx> + +namespace pqxx +{ +namespace internal +{ +namespace gate +{ +class PQXX_PRIVATE result_connection : callgate<const result> +{ + friend class pqxx::connection_base; + + result_connection(reference x) : super(x) {} + + operator bool() const { return bool(home()); } + bool operator!() const { return not home(); } +}; +} // namespace pqxx::internal::gate +} // namespace pqxx::internal +} // namespace pqxx diff --git a/contrib/libs/libpqxx/include/pqxx/internal/gates/result-creation.hxx b/contrib/libs/libpqxx/include/pqxx/internal/gates/result-creation.hxx new file mode 100644 index 0000000000..6d5671c529 --- /dev/null +++ b/contrib/libs/libpqxx/include/pqxx/internal/gates/result-creation.hxx @@ -0,0 +1,28 @@ +#include <pqxx/internal/callgate.hxx> + +namespace pqxx +{ +namespace internal +{ +namespace gate +{ +class PQXX_PRIVATE result_creation : callgate<const result> +{ + friend class pqxx::connection_base; + friend class pqxx::pipeline; + + result_creation(reference x) : super(x) {} + + static result create( + internal::pq::PGresult *rhs, + const std::string &query, + encoding_group enc) + { + return result(rhs, query, enc); + } + + void check_status() const { return home().check_status(); } +}; +} // namespace pqxx::internal::gate +} // namespace pqxx::internal +} // namespace pqxx diff --git a/contrib/libs/libpqxx/include/pqxx/internal/gates/result-row.hxx b/contrib/libs/libpqxx/include/pqxx/internal/gates/result-row.hxx new file mode 100644 index 0000000000..692d3b5f5b --- /dev/null +++ b/contrib/libs/libpqxx/include/pqxx/internal/gates/result-row.hxx @@ -0,0 +1,22 @@ +#include <pqxx/internal/callgate.hxx> + +namespace pqxx +{ +namespace internal +{ +class row; + +namespace gate +{ +class PQXX_PRIVATE result_row : callgate<result> +{ + friend class pqxx::row; + + result_row(reference x) : super(x) {} + + operator bool() + { return bool(home()); } +}; +} // namespace pqxx::internal::gate +} // namespace pqxx::internal +} // namespace pqxx diff --git a/contrib/libs/libpqxx/include/pqxx/internal/gates/transaction-sql_cursor.hxx b/contrib/libs/libpqxx/include/pqxx/internal/gates/transaction-sql_cursor.hxx new file mode 100644 index 0000000000..878b171b95 --- /dev/null +++ b/contrib/libs/libpqxx/include/pqxx/internal/gates/transaction-sql_cursor.hxx @@ -0,0 +1,16 @@ +#include <pqxx/internal/callgate.hxx> + +namespace pqxx +{ +namespace internal +{ +namespace gate +{ +class PQXX_PRIVATE transaction_sql_cursor : callgate<transaction_base> +{ + friend class pqxx::internal::sql_cursor; + transaction_sql_cursor(reference x) : super(x) {} +}; +} // namespace pqxx::internal::gate +} // namespace pqxx::internal +} // namespace pqxx diff --git a/contrib/libs/libpqxx/include/pqxx/internal/gates/transaction-stream_from.hxx b/contrib/libs/libpqxx/include/pqxx/internal/gates/transaction-stream_from.hxx new file mode 100644 index 0000000000..6345543dda --- /dev/null +++ b/contrib/libs/libpqxx/include/pqxx/internal/gates/transaction-stream_from.hxx @@ -0,0 +1,23 @@ +#include <pqxx/internal/callgate.hxx> + +namespace pqxx +{ +namespace internal +{ +namespace gate +{ +class PQXX_PRIVATE transaction_stream_from : callgate<transaction_base> +{ + friend class pqxx::stream_from; + + transaction_stream_from(reference x) : super(x) {} + + void BeginCopyRead(const std::string &table, const std::string &columns) + { home().BeginCopyRead(table, columns); } + + bool read_copy_line(std::string &line) + { return home().read_copy_line(line); } +}; +} // namespace pqxx::internal::gate +} // namespace pqxx::internal +} // namespace pqxx diff --git a/contrib/libs/libpqxx/include/pqxx/internal/gates/transaction-stream_to.hxx b/contrib/libs/libpqxx/include/pqxx/internal/gates/transaction-stream_to.hxx new file mode 100644 index 0000000000..6ee9e9b7d6 --- /dev/null +++ b/contrib/libs/libpqxx/include/pqxx/internal/gates/transaction-stream_to.hxx @@ -0,0 +1,27 @@ +#include <pqxx/internal/callgate.hxx> + +namespace pqxx +{ +namespace internal +{ +namespace gate +{ +class PQXX_PRIVATE transaction_stream_to : callgate<transaction_base> +{ + friend class pqxx::stream_to; + + transaction_stream_to(reference x) : super(x) {} + + void BeginCopyWrite( + const std::string &table, + const std::string &columns = std::string{}) + { home().BeginCopyWrite(table, columns); } + + void write_copy_line(const std::string &line) + { home().write_copy_line(line); } + + void end_copy_write() { home().end_copy_write(); } +}; +} // namespace pqxx::internal::gate +} // namespace pqxx::internal +} // namespace pqxx diff --git a/contrib/libs/libpqxx/include/pqxx/internal/gates/transaction-subtransaction.hxx b/contrib/libs/libpqxx/include/pqxx/internal/gates/transaction-subtransaction.hxx new file mode 100644 index 0000000000..243f47a798 --- /dev/null +++ b/contrib/libs/libpqxx/include/pqxx/internal/gates/transaction-subtransaction.hxx @@ -0,0 +1,20 @@ +#include <pqxx/internal/callgate.hxx> + +namespace pqxx +{ +namespace internal +{ +namespace gate +{ +class PQXX_PRIVATE transaction_subtransaction : callgate<transaction_base> +{ + friend class pqxx::subtransaction; + + transaction_subtransaction(reference x) : super(x) {} + + void add_reactivation_avoidance_count(int n) + { home().m_reactivation_avoidance.add(n); } +}; +} // namespace pqxx::internal::gate +} // namespace pqxx::internal +} // namespace pqxx diff --git a/contrib/libs/libpqxx/include/pqxx/internal/gates/transaction-tablereader.hxx b/contrib/libs/libpqxx/include/pqxx/internal/gates/transaction-tablereader.hxx new file mode 100644 index 0000000000..6946d36391 --- /dev/null +++ b/contrib/libs/libpqxx/include/pqxx/internal/gates/transaction-tablereader.hxx @@ -0,0 +1,23 @@ +#include <pqxx/internal/callgate.hxx> + +namespace pqxx +{ +namespace internal +{ +namespace gate +{ +class PQXX_PRIVATE transaction_tablereader : callgate<transaction_base> +{ + friend class pqxx::tablereader; + + transaction_tablereader(reference x) : super(x) {} + + void BeginCopyRead(const std::string &table, const std::string &columns) + { home().BeginCopyRead(table, columns); } + + bool read_copy_line(std::string &line) + { return home().read_copy_line(line); } +}; +} // namespace pqxx::internal::gate +} // namespace pqxx::internal +} // namespace pqxx diff --git a/contrib/libs/libpqxx/include/pqxx/internal/gates/transaction-tablewriter.hxx b/contrib/libs/libpqxx/include/pqxx/internal/gates/transaction-tablewriter.hxx new file mode 100644 index 0000000000..3256090a2f --- /dev/null +++ b/contrib/libs/libpqxx/include/pqxx/internal/gates/transaction-tablewriter.hxx @@ -0,0 +1,27 @@ +#include <pqxx/internal/callgate.hxx> + +namespace pqxx +{ +namespace internal +{ +namespace gate +{ +class PQXX_PRIVATE transaction_tablewriter : callgate<transaction_base> +{ + friend class pqxx::tablewriter; + + transaction_tablewriter(reference x) : super(x) {} + + void BeginCopyWrite( + const std::string &table, + const std::string &columns = std::string{}) + { home().BeginCopyWrite(table, columns); } + + void write_copy_line(const std::string &line) + { home().write_copy_line(line); } + + void end_copy_write() { home().end_copy_write(); } +}; +} // namespace pqxx::internal::gate +} // namespace pqxx::internal +} // namespace pqxx diff --git a/contrib/libs/libpqxx/include/pqxx/internal/gates/transaction-transactionfocus.hxx b/contrib/libs/libpqxx/include/pqxx/internal/gates/transaction-transactionfocus.hxx new file mode 100644 index 0000000000..9ea117a2ea --- /dev/null +++ b/contrib/libs/libpqxx/include/pqxx/internal/gates/transaction-transactionfocus.hxx @@ -0,0 +1,23 @@ +#include <pqxx/internal/callgate.hxx> + +namespace pqxx +{ +namespace internal +{ +namespace gate +{ +class PQXX_PRIVATE transaction_transactionfocus : callgate<transaction_base> +{ + friend class pqxx::internal::transactionfocus; + + transaction_transactionfocus(reference x) : super(x) {} + + void register_focus(transactionfocus *focus) { home().register_focus(focus); } + void unregister_focus(transactionfocus *focus) noexcept + { home().unregister_focus(focus); } + void register_pending_error(const std::string &error) + { home().register_pending_error(error); } +}; +} // namespace pqxx::internal::gate +} // namespace pqxx::internal +} // namespace pqxx diff --git a/contrib/libs/libpqxx/include/pqxx/internal/ignore-deprecated-post.hxx b/contrib/libs/libpqxx/include/pqxx/internal/ignore-deprecated-post.hxx new file mode 100644 index 0000000000..32a84b2751 --- /dev/null +++ b/contrib/libs/libpqxx/include/pqxx/internal/ignore-deprecated-post.hxx @@ -0,0 +1,6 @@ +/// End a code block started by "ignore-deprecated-pre.hxx". +#if defined(__GNUC__) + +#pragma GCC diagnostic pop + +#endif // __GNUC__ diff --git a/contrib/libs/libpqxx/include/pqxx/internal/ignore-deprecated-pre.hxx b/contrib/libs/libpqxx/include/pqxx/internal/ignore-deprecated-pre.hxx new file mode 100644 index 0000000000..9ada1b7205 --- /dev/null +++ b/contrib/libs/libpqxx/include/pqxx/internal/ignore-deprecated-pre.hxx @@ -0,0 +1,19 @@ +/** Start a block of deprecated code which may call other deprecated code. + * + * Most compilers will emit warnings when deprecated code is invoked from + * non-deprecated code. But some compilers (notably gcc) will always emit the + * warning, even when the calling code is also deprecated. + * + * This header starts a block where those warnings are suppressed. It can be + * included inside a code block. + * + * Always match the #include with a closing #include of + * "ignore-deprecated-post.hxx". To avoid mistakes, keep the enclosed area as + * small as possible. + */ +#if defined(__GNUC__) + +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wdeprecated-declarations" + +#endif // __GNUC__ diff --git a/contrib/libs/libpqxx/include/pqxx/internal/libpq-forward.hxx b/contrib/libs/libpqxx/include/pqxx/internal/libpq-forward.hxx new file mode 100644 index 0000000000..394f3068b2 --- /dev/null +++ b/contrib/libs/libpqxx/include/pqxx/internal/libpq-forward.hxx @@ -0,0 +1,34 @@ +/** Minimal forward declarations of libpq types needed in libpqxx headers. + * + * DO NOT INCLUDE THIS FILE when building client programs. + * + * 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. + */ +extern "C" +{ +struct pg_conn; +struct pg_result; +struct pgNotify; +} + +namespace pqxx +{ +namespace internal +{ +/// Forward declarations of libpq types as needed in libpqxx headers +namespace pq +{ +using PGconn = pg_conn; +using PGresult = pg_result; +using PGnotify = pgNotify; +using PQnoticeProcessor = void (*)(void *, const char *); +} +} + +/// PostgreSQL database row identifier +using oid = unsigned int; +} // extern "C" diff --git a/contrib/libs/libpqxx/include/pqxx/internal/sql_cursor.hxx b/contrib/libs/libpqxx/include/pqxx/internal/sql_cursor.hxx new file mode 100644 index 0000000000..828f9d3e6e --- /dev/null +++ b/contrib/libs/libpqxx/include/pqxx/internal/sql_cursor.hxx @@ -0,0 +1,122 @@ +/** Internal wrapper for SQL cursors. Supports higher-level cursor classes. + * + * DO NOT INCLUDE THIS FILE DIRECTLY. Other headers include it for you. + * + * 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_SQL_CURSOR +#define PQXX_H_SQL_CURSOR + +namespace pqxx +{ +namespace internal +{ +/// Cursor with SQL positioning semantics. +/** Thin wrapper around an SQL cursor, with SQL's ideas of positioning. + * + * SQL cursors have pre-increment/pre-decrement semantics, with on either end of + * the result set a special position that does not repesent a row. This class + * models SQL cursors for the purpose of implementing more C++-like semantics on + * top. + * + * Positions of actual rows are numbered starting at 1. Position 0 exists but + * does not refer to a row. There is a similar non-row position at the end of + * the result set. + * + * Don't use this at home. You deserve better. Use the stateles_cursor + * instead. + */ +class PQXX_LIBEXPORT sql_cursor : public cursor_base +{ +public: + sql_cursor( + transaction_base &t, + const std::string &query, + const std::string &cname, + cursor_base::accesspolicy ap, + cursor_base::updatepolicy up, + cursor_base::ownershippolicy op, + bool hold, + result_format format = result_format::text); + + sql_cursor( + transaction_base &t, + const std::string &cname, + cursor_base::ownershippolicy op); + + ~sql_cursor() noexcept { close(); } + + result fetch(difference_type rows, difference_type &displacement); + result fetch(difference_type rows) + { difference_type d=0; return fetch(rows, d); } + difference_type move(difference_type rows, difference_type &displacement); + difference_type move(difference_type rows) + { difference_type d=0; return move(rows, d); } + + /// Current position, or -1 for unknown + /** + * The starting position, just before the first row, counts as position zero. + * + * Position may be unknown if (and only if) this cursor was adopted, and has + * never hit its starting position (position zero). + */ + difference_type pos() const noexcept { return m_pos; } + + /// End position, or -1 for unknown + /** + * Returns the final position, just after the last row in the result set. The + * starting position, just before the first row, counts as position zero. + * + * End position is unknown until it is encountered during use. + */ + difference_type endpos() const noexcept { return m_endpos; } + + /// Return zero-row result for this cursor + const result &empty_result() const noexcept { return m_empty_result; } + + void close() noexcept; + +private: + difference_type adjust(difference_type hoped, difference_type actual); + static std::string stridestring(difference_type); + /// Initialize cached empty result. Call only at beginning or end! + void init_empty_result(transaction_base &); + + /// Connection this cursor lives in + connection_base &m_home; + + /// Zero-row result from this cursor (or plain empty one if cursor is adopted) + result m_empty_result; + + result m_cached_current_row; + + /// Is this cursor adopted (as opposed to created by this cursor object)? + bool m_adopted; + + /// Will this cursor object destroy its SQL cursor when it dies? + cursor_base::ownershippolicy m_ownership; + + /// At starting position (-1), somewhere in the middle (0), or past end (1) + int m_at_end; + + /// Position, or -1 for unknown + difference_type m_pos; + + /// End position, or -1 for unknown + difference_type m_endpos = -1; +}; + + +PQXX_LIBEXPORT result_size_type obtain_stateless_cursor_size(sql_cursor &); +PQXX_LIBEXPORT result stateless_cursor_retrieve( + sql_cursor &, + result::difference_type size, + result::difference_type begin_pos, + result::difference_type end_pos); +} // namespace internal +} // namespace pqxx +#endif diff --git a/contrib/libs/libpqxx/include/pqxx/internal/statement_parameters.hxx b/contrib/libs/libpqxx/include/pqxx/internal/statement_parameters.hxx new file mode 100644 index 0000000000..8c80f6df48 --- /dev/null +++ b/contrib/libs/libpqxx/include/pqxx/internal/statement_parameters.hxx @@ -0,0 +1,227 @@ +/** Common implementation for statement parameter lists. + * + * These are used for both prepared statements and parameterized statements. + * + * DO NOT INCLUDE THIS FILE DIRECTLY. Other headers include it for you. + * + * 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_STATEMENT_PARAMETER +#define PQXX_H_STATEMENT_PARAMETER + +#include "pqxx/compiler-public.hxx" +#include "pqxx/compiler-internal-pre.hxx" + +#include <cstring> +#include <iterator> +#include <string> +#include <vector> + +#include "pqxx/binarystring" +#include "pqxx/strconv" +#include "pqxx/util" + +#include "pqxx/internal/type_utils.hxx" + + +namespace pqxx +{ +namespace internal +{ +/// Marker type: pass a dynamically-determined number of statement parameters. +/** Normally when invoking a prepared or parameterised statement, the number + * of parameters is known at compile time. For instance, + * @c t.exec_prepared("foo", 1, "x"); executes statement @c foo with two + * parameters, an @c int and a C string. + * + * But sometimes you may want to pass a number of parameters known only at run + * time. In those cases, a @c dynamic_params encodes a dynamically + * determined number of parameters. + */ +template<typename IT> class dynamic_params +{ +public: + /// Wrap a sequence of pointers or iterators. + dynamic_params(IT begin, IT end) : m_begin(begin), m_end(end) {} + + /// Wrap a container. + template<typename C> explicit dynamic_params(const C &container) : + m_begin(std::begin(container)), + m_end(std::end(container)) + {} + + IT begin() const { return m_begin; } + IT end() const { return m_end; } + +private: + const IT m_begin, m_end; +}; + + +class PQXX_LIBEXPORT statement_parameters +{ +protected: + statement_parameters() =default; + statement_parameters &operator=(const statement_parameters &) =delete; + + void add_param() { this->add_checked_param("", false, false); } + template<typename T> void add_param(const T &v, bool nonnull) + { + nonnull = (nonnull && not pqxx::string_traits<T>::is_null(v)); + this->add_checked_param( + (nonnull ? pqxx::to_string(v) : ""), + nonnull, + false); + } + void add_binary_param(const binarystring &b, bool nonnull) + { this->add_checked_param(b.str(), nonnull, true); } + + /// Marshall parameter values into C-compatible arrays for passing to libpq. + int marshall( + std::vector<const char *> &values, + std::vector<int> &lengths, + std::vector<int> &binaries) const; + +private: + void add_checked_param(const std::string &value, bool nonnull, bool binary); + + std::vector<std::string> m_values; + std::vector<bool> m_nonnull; + std::vector<bool> m_binary; +}; + + +/// Internal type: encode statement parameters. +/** Compiles arguments for prepared statements and parameterised queries into + * a format that can be passed into libpq. + * + * Objects of this type are meant to be short-lived. If you pass in a non-null + * pointer as a parameter, it may simply use that pointer as a parameter value. + */ +struct params +{ + /// Construct directly from a series of statement arguments. + /** The arrays all default to zero, null, and empty strings. + */ + template<typename ...Args> params(Args && ... args) + { + strings.reserve(sizeof...(args)); + lengths.reserve(sizeof...(args)); + nonnulls.reserve(sizeof...(args)); + binaries.reserve(sizeof...(args)); + + // Start recursively storing parameters. + add_fields(std::forward<Args>(args)...); + } + + /// Compose a vector of pointers to parameter string values. + std::vector<const char *> get_pointers() const + { + const std::size_t num_fields = lengths.size(); + std::size_t cur_string = 0, cur_bin_string = 0; + std::vector<const char *> pointers(num_fields); + for (std::size_t index = 0; index < num_fields; index++) + { + const char *value; + if (binaries[index]) + { + value = bin_strings[cur_bin_string].get(); + cur_bin_string++; + } + else if (nonnulls[index]) + { + value = strings[cur_string].c_str(); + cur_string++; + } + else + { + value = nullptr; + } + pointers[index] = value; + } + return pointers; + } + + /// String values, for string parameters. + std::vector<std::string> strings; + /// As used by libpq: lengths of non-null arguments, in bytes. + std::vector<int> lengths; + /// As used by libpq: boolean "is this parameter non-null?" + std::vector<int> nonnulls; + /// As used by libpq: boolean "is this parameter in binary format?" + std::vector<int> binaries; + /// Binary string values, for binary parameters. + std::vector<pqxx::binarystring> bin_strings; + +private: + /// Add a non-null string field. + void add_field(std::string str) + { + lengths.push_back(int(str.size())); + nonnulls.push_back(1); + binaries.push_back(0); + strings.emplace_back(std::move(str)); + } + + /// Compile one argument (specialised for null pointer, a null value). + void add_field(std::nullptr_t) + { + lengths.push_back(0); + nonnulls.push_back(0); + binaries.push_back(0); + } + + /// Compile one argument (specialised for binarystring). + void add_field(const binarystring &arg) + { + lengths.push_back(int(arg.size())); + nonnulls.push_back(1); + binaries.push_back(1); + bin_strings.push_back(arg); + } + + /// Compile one argument (default, generic implementation). + /** Uses string_traits to represent the argument as a std::string. + */ + template<typename Arg> void add_field(const Arg &arg) + { + if (string_traits<Arg>::is_null(arg)) add_field(nullptr); + else add_field(to_string(arg)); + } + + /// Compile a dynamic_params object into a dynamic number of parameters. + template<typename IT> void add_field(const dynamic_params<IT> ¶meters) + { + for (auto param: parameters) add_field(param); + } + + /// Compile argument list. + /** This recursively "peels off" the next remaining element, compiles its + * information into its final form, and calls itself for the rest of the + * list. + * + * @param arg Current argument to be compiled. + * @param args Optional remaining arguments, to be compiled recursively. + */ + template<typename Arg, typename ...More> + void add_fields(Arg &&arg, More && ... args) + { + add_field(std::forward<Arg>(arg)); + // Compile remaining arguments, if any. + add_fields(std::forward<More>(args)...); + } + + /// Terminating version of add_fields, at the end of the list. + /** Recursion in add_fields ends with this call. + */ + void add_fields() {} +}; +} // namespace pqxx::internal +} // namespace pqxx + +#include "pqxx/compiler-internal-post.hxx" +#endif diff --git a/contrib/libs/libpqxx/include/pqxx/internal/type_utils.hxx b/contrib/libs/libpqxx/include/pqxx/internal/type_utils.hxx new file mode 100644 index 0000000000..7bf5528018 --- /dev/null +++ b/contrib/libs/libpqxx/include/pqxx/internal/type_utils.hxx @@ -0,0 +1,211 @@ +/** Type/template metaprogramming utilities for use internally in libpqxx + * + * 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_TYPE_UTILS +#define PQXX_H_TYPE_UTILS + +#include <memory> +#include <type_traits> + +#if defined(PQXX_HAVE_OPTIONAL) +#include <optional> +#elif defined(PQXX_HAVE_EXP_OPTIONAL) && !defined(PQXX_HIDE_EXP_OPTIONAL) +#error #include <experimental/optional> +#endif + +#include "pqxx/strconv" + +namespace pqxx +{ +namespace internal +{ + +/// Replicate std::void_t<> (available in C++17). +template<typename... T> using void_t = void; + +/// Extract the content type held by an `optional`-like wrapper type. +/* Replace nested `std::remove_*`s with `std::remove_cvref` in C++20 */ +template<typename T> using inner_type = typename std::remove_cv< + typename std::remove_reference< + decltype(*std::declval<T>()) + >::type +>::type; + +/// Does the given type have an `operator *()`? +template<typename T, typename = void> struct is_derefable : std::false_type {}; +template<typename T> struct is_derefable<T, void_t< + // Disable for arrays so they don't erroneously decay to pointers. + inner_type<typename std::enable_if<not std::is_array<T>::value, T>::type> +>> : std::true_type {}; + +/// Should the given type be treated as an optional-value wrapper type? +template<typename T, typename = void> struct is_optional : std::false_type {}; +template<typename T> struct is_optional<T, typename std::enable_if<( + is_derefable<T>::value + // Check if an `explicit operator bool` exists for this type + && std::is_constructible<bool, T>::value +)>::type> : std::true_type {}; + +/// Can `nullopt_t` implicitly convert to type T? +template< + typename T, + typename = void +> struct takes_std_nullopt : std::false_type {}; +#if defined(PQXX_HAVE_OPTIONAL) +template<typename T> struct takes_std_nullopt< + T, + typename std::enable_if<std::is_assignable<T, std::nullopt_t>::value>::type +> : std::true_type {}; +#elif defined(PQXX_HAVE_EXP_OPTIONAL) && !defined(PQXX_HIDE_EXP_OPTIONAL) +template<typename T> struct takes_std_nullopt< + T, + typename std::enable_if< + std::is_assignable<T, std::experimental::nullopt_t>::value + >::type +> : std::true_type {}; +#endif + +/// Is type T a `std::tuple<>`? +template<typename T, typename = void> struct is_tuple : std::false_type {}; +template<typename T> struct is_tuple< + T, + typename std::enable_if<(std::tuple_size<T>::value >= 0)>::type +> : std::true_type {}; + +/// Is type T an iterable container? +template<typename T, typename = void> struct is_container : std::false_type {}; +template<typename T> struct is_container< + T, + void_t< + decltype(std::begin(std::declval<T>())), + decltype(std::end(std::declval<T>())), + // Some people might implement a `std::tuple<>` specialization that is + // iterable when all the contained types are the same ;) + typename std::enable_if<not is_tuple<T>::value>::type + > +> : std::true_type {}; + +/// Get an appropriate null value for the given type. +/** + * pointer types `nullptr` + * `std::optional<>`-like `std::nullopt` + * `std::experimental::optional<>`-like `std::experimental::nullopt` + * other types `pqxx::string_traits<>::null()` + * Users may add support for their own wrapper types following this pattern. + */ +template<typename T> constexpr auto null_value() + -> typename std::enable_if< + ( + is_optional<T>::value + && not takes_std_nullopt<T>::value + && std::is_assignable<T, std::nullptr_t>::value + ), + std::nullptr_t + >::type +{ return nullptr; } +template<typename T> constexpr auto null_value() + -> typename std::enable_if< + (not is_optional<T>::value && not takes_std_nullopt<T>::value), + decltype(pqxx::string_traits<T>::null()) + >::type +{ return pqxx::string_traits<T>::null(); } +#if defined(PQXX_HAVE_OPTIONAL) +template<typename T> constexpr auto null_value() + -> typename std::enable_if< + takes_std_nullopt<T>::value, + std::nullopt_t + >::type +{ return std::nullopt; } +#elif defined(PQXX_HAVE_EXP_OPTIONAL) && !defined(PQXX_HIDE_EXP_OPTIONAL) +template<typename T> constexpr auto null_value() + -> typename std::enable_if< + takes_std_nullopt<T>::value, + std::experimental::nullopt_t + >::type +{ return std::experimental::nullopt; } +#endif + +/// Construct an optional-like type from the stored type. +/** + * While these may seem redundant, they are necessary to support smart pointers + * as optional storage types in a generic manner. It is suggested NOT to + * provide a version for `inner_type<T>*` as that will almost certainly leak + * memory. + * Users may add support for their own wrapper types following this pattern. + */ +// Enabled if the wrapper type can be directly constructed from the wrapped type +// (e.g. `std::optional<>`); explicitly disabled for raw pointers in case the +// inner type is convertible to a pointer (e.g. `int`) +template<typename T, typename V> constexpr auto make_optional(V&& v) + -> typename std::enable_if< + not std::is_same<T, inner_type<T>*>::value, + decltype(T(std::forward<V>(v))) + >::type +{ return T(std::forward<V>(v)); } +// Enabled if T is a specialization of `std::unique_ptr<>`. +template<typename T, typename V> constexpr auto make_optional(V&& v) + -> typename std::enable_if< + std::is_same<T, std::unique_ptr<inner_type<T>>>::value, + std::unique_ptr<inner_type<T>> + >::type +{ + return std::unique_ptr<inner_type<T>>(new inner_type<T>(std::forward<V>(v))); +} +// Enabled if T is a specialization of `std::shared_ptr<>`. +template<typename T, typename V> constexpr auto make_optional(V&& v) + -> typename std::enable_if< + std::is_same<T, std::shared_ptr<inner_type<T>>>::value, + std::shared_ptr<inner_type<T>> + >::type +{ return std::make_shared<inner_type<T>>(std::forward<V>(v)); } + +} // namespace pqxx::internal +} // namespace pqxx + + +// TODO: Move? +namespace pqxx +{ + +/// Meta `pqxx::string_traits` for std::optional-like types. +template<typename T> struct string_traits< + T, + typename std::enable_if<internal::is_optional<T>::value>::type +> +{ +private: + using I = internal::inner_type<T>; +public: + static constexpr const char *name() noexcept + { return string_traits<I>::name(); } + static constexpr bool has_null() noexcept { return true; } + static bool is_null(const T& v) + { return (not v || string_traits<I>::is_null(*v)); } + static constexpr T null() { return internal::null_value<T>(); } + static void from_string(const char Str[], T &Obj) + { + if (not Str) Obj = null(); + else + { + I inner; + string_traits<I>::from_string(Str, inner); + // Utilize existing memory if possible (e.g. for pointer types). + if (Obj) *Obj = inner; + // Important to assign to set valid flag for smart optional types. + else Obj = internal::make_optional<T>(inner); + } + } + static std::string to_string(const T& Obj) + { + if (is_null(Obj)) internal::throw_null_conversion(name()); + return string_traits<I>::to_string(*Obj); + } +}; + +} // namespace pqxx +#endif diff --git a/contrib/libs/libpqxx/include/pqxx/isolation.hxx b/contrib/libs/libpqxx/include/pqxx/isolation.hxx new file mode 100644 index 0000000000..fbabb994ed --- /dev/null +++ b/contrib/libs/libpqxx/include/pqxx/isolation.hxx @@ -0,0 +1,87 @@ +/** Definitions of transaction isolation levels. + * + * Policies and traits describing SQL transaction isolation levels + * + * DO NOT INCLUDE THIS FILE DIRECTLY; include pqxx/isolation 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_ISOLATION +#define PQXX_H_ISOLATION + +#include "pqxx/compiler-public.hxx" +#include "pqxx/compiler-internal-pre.hxx" + +#include "pqxx/util.hxx" + +namespace pqxx +{ + +/// Transaction isolation levels. +/** These are as defined in the SQL standard. But there are a few notes + * specific to PostgreSQL. + * + * First, postgres does not support "read uncommitted." The lowest level you + * can get is "read committed," which is better. PostgreSQL is built on the + * MVCC paradigm, which guarantees "read committed" isolation without any + * additional performance overhead, so there was no point in providing the + * lower level. + * + * Second, "repeatable read" also makes more isolation guarantees than the + * standard requires. According to the standard, this level prevents "dirty + * reads" and "nonrepeatable reads," but not "phantom reads." In postgres, + * it actually prevents all three. + * + * Third, "serializable" is only properly supported starting at postgres 9.1. + * If you request "serializable" isolation on an older backend, you will get + * the same isolation as in "repeatable read." It's better than the "repeatable + * read" defined in the SQL standard, but not a complete implementation of the + * standard's "serializable" isolation level. + * + * In general, a lower isolation level will allow more surprising interactions + * between ongoing transactions, but improve performance. A higher level + * gives you more protection from subtle concurrency bugs, but sometimes it + * may not be possible to complete your transaction without avoiding paradoxes + * in the data. In that case a transaction may fail, and the application will + * have to re-do the whole thing based on the latest state of the database. + * (If you want to retry your code in that situation, have a look at the + * transactor framework.) + * + * Study the levels and design your application with the right level in mind. + */ +enum isolation_level +{ + // read_uncommitted, + read_committed, + repeatable_read, + serializable +}; + +/// Traits class to describe an isolation level; primarly for libpqxx's own use +template<isolation_level LEVEL> struct isolation_traits +{ + static constexpr isolation_level level() noexcept { return LEVEL; } + static constexpr const char *name() noexcept; +}; + + +template<> +inline constexpr const char *isolation_traits<read_committed>::name() noexcept + { return "READ COMMITTED"; } + +template<> +inline constexpr const char *isolation_traits<repeatable_read>::name() noexcept + { return "REPEATABLE READ"; } + +template<> +inline constexpr const char *isolation_traits<serializable>::name() noexcept + { return "SERIALIZABLE"; } + +} + +#include "pqxx/compiler-internal-post.hxx" +#endif diff --git a/contrib/libs/libpqxx/include/pqxx/largeobject b/contrib/libs/libpqxx/include/pqxx/largeobject new file mode 100644 index 0000000000..b1dedd597a --- /dev/null +++ b/contrib/libs/libpqxx/include/pqxx/largeobject @@ -0,0 +1,6 @@ +/** Large Objects interface. + * + * Supports direct access to large objects, as well as through I/O streams + */ +// Actual definitions in .hxx file so editors and such recognize file type. +#include "pqxx/largeobject.hxx" diff --git a/contrib/libs/libpqxx/include/pqxx/largeobject.hxx b/contrib/libs/libpqxx/include/pqxx/largeobject.hxx new file mode 100644 index 0000000000..f2f7c0e7fe --- /dev/null +++ b/contrib/libs/libpqxx/include/pqxx/largeobject.hxx @@ -0,0 +1,672 @@ +/** Large Objects interface. + * + * Allows access to large objects directly, or through I/O streams. + * + * DO NOT INCLUDE THIS FILE DIRECTLY; include pqxx/largeobject 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_LARGEOBJECT +#define PQXX_H_LARGEOBJECT + +#include "pqxx/compiler-public.hxx" +#include "pqxx/compiler-internal-pre.hxx" + +#include <streambuf> + +#include "pqxx/dbtransaction.hxx" + + +namespace pqxx +{ +/// Identity of a large object +/** This class encapsulates the identity of a large object. To access the + * contents of the object, create a largeobjectaccess, a largeobject_streambuf, + * or an ilostream, an olostream or a lostream around the largeobject. + * + * A largeobject must be accessed only from within a backend transaction, but + * the object's identity remains valid as long as the object exists. + */ +class PQXX_LIBEXPORT largeobject +{ +public: + using size_type = large_object_size_type; + + /// Refer to a nonexistent large object (similar to what a null pointer does) + largeobject() noexcept =default; //[t48] + + /// Create new large object + /** @param T Backend transaction in which the object is to be created + */ + explicit largeobject(dbtransaction &T); //[t48] + + /// Wrap object with given oid + /** Convert combination of a transaction and object identifier into a + * large object identity. Does not affect the database. + * @param O Object identifier for the given object + */ + explicit largeobject(oid O) noexcept : m_id{O} {} //[t48] + + /// Import large object from a local file + /** Creates a large object containing the data found in the given file. + * @param T Backend transaction in which the large object is to be created + * @param File A filename on the client program's filesystem + */ + largeobject(dbtransaction &T, const std::string &File); //[t53] + + /// Take identity of an opened large object + /** Copy identity of already opened large object. Note that this may be done + * as an implicit conversion. + * @param O Already opened large object to copy identity from + */ + largeobject(const largeobjectaccess &O) noexcept; //[t50] + + /// Object identifier + /** The number returned by this function identifies the large object in the + * database we're connected to (or oid_none is returned if we refer to the + * null object). + */ + oid id() const noexcept { return m_id; } //[t48] + + /** + * @name Identity comparisons + * + * These operators compare the object identifiers of large objects. This has + * nothing to do with the objects' actual contents; use them only for keeping + * track of containers of references to large objects and such. + */ + //@{ + /// Compare object identities + /** @warning Only valid between large objects in the same database. */ + bool operator==(const largeobject &other) const //[t51] + { return m_id == other.m_id; } + /// Compare object identities + /** @warning Only valid between large objects in the same database. */ + bool operator!=(const largeobject &other) const //[t51] + { return m_id != other.m_id; } + /// Compare object identities + /** @warning Only valid between large objects in the same database. */ + bool operator<=(const largeobject &other) const //[t51] + { return m_id <= other.m_id; } + /// Compare object identities + /** @warning Only valid between large objects in the same database. */ + bool operator>=(const largeobject &other) const //[t51] + { return m_id >= other.m_id; } + /// Compare object identities + /** @warning Only valid between large objects in the same database. */ + bool operator<(const largeobject &other) const //[t51] + { return m_id < other.m_id; } + /// Compare object identities + /** @warning Only valid between large objects in the same database. */ + bool operator>(const largeobject &other) const //[t51] + { return m_id > other.m_id; } + //@} + + /// Export large object's contents to a local file + /** Writes the data stored in the large object to the given file. + * @param T Transaction in which the object is to be accessed + * @param File A filename on the client's filesystem + */ + void to_file(dbtransaction &T, const std::string &File) const; //[t52] + + /// Delete large object from database + /** Unlike its low-level equivalent cunlink, this will throw an exception if + * deletion fails. + * @param T Transaction in which the object is to be deleted + */ + void remove(dbtransaction &T) const; //[t48] + +protected: + PQXX_PURE static internal::pq::PGconn *raw_connection( + const dbtransaction &T); + + PQXX_PRIVATE std::string reason(const connection_base &, int err) const; + +private: + oid m_id = oid_none; +}; + + +// TODO: New hierarchy with separate read / write / mixed-mode access + +/// Accessor for large object's contents. +class PQXX_LIBEXPORT largeobjectaccess : private largeobject +{ +public: + using largeobject::size_type; + using off_type = long; + using pos_type = size_type; + + /// Open mode: @c in, @c out (can be combined with the "or" operator) + /** According to the C++ standard, these should be in @c std::ios_base. We + * take them from @c std::ios instead, which should be safe because it + * inherits the same definition, to accommodate gcc 2.95 & 2.96. + */ + using openmode = std::ios::openmode; + + /// Seek direction: @c beg, @c cur, @c end + /** According to the C++ standard, these should be in @c std::ios_base. We + * take them from @c std::ios instead, which should be safe because it + * inherits the same definition, to accommodate gcc 2.95 & 2.96. + */ + using seekdir = std::ios::seekdir; + + /// Create new large object and open it + /** + * @param T Backend transaction in which the object is to be created + * @param mode Access mode, defaults to ios_base::in | ios_base::out + */ + explicit largeobjectaccess( //[t51] + dbtransaction &T, + openmode mode=std::ios::in|std::ios::out); + + /// Open large object with given oid + /** Convert combination of a transaction and object identifier into a + * large object identity. Does not affect the database. + * @param T Transaction in which the object is to be accessed + * @param O Object identifier for the given object + * @param mode Access mode, defaults to ios_base::in | ios_base::out + */ + largeobjectaccess( //[t52] + dbtransaction &T, + oid O, + openmode mode=std::ios::in|std::ios::out); + + /// Open given large object + /** Open a large object with the given identity for reading and/or writing + * @param T Transaction in which the object is to be accessed + * @param O Identity for the large object to be accessed + * @param mode Access mode, defaults to ios_base::in | ios_base::out + */ + largeobjectaccess( //[t50] + dbtransaction &T, + largeobject O, + openmode mode=std::ios::in|std::ios::out); + + /// Import large object from a local file and open it + /** Creates a large object containing the data found in the given file. + * @param T Backend transaction in which the large object is to be created + * @param File A filename on the client program's filesystem + * @param mode Access mode, defaults to ios_base::in | ios_base::out + */ + largeobjectaccess( //[t55] + dbtransaction &T, + const std::string &File, + openmode mode=std::ios::in|std::ios::out); + + ~largeobjectaccess() noexcept { close(); } + + /// Object identifier + /** The number returned by this function uniquely identifies the large object + * in the context of the database we're connected to. + */ + using largeobject::id; + + /// Export large object's contents to a local file + /** Writes the data stored in the large object to the given file. + * @param File A filename on the client's filesystem + */ + void to_file(const std::string &File) const //[t54] + { largeobject::to_file(m_trans, File); } + + using largeobject::to_file; + + /** + * @name High-level access to object contents + */ + //@{ + /// Write data to large object + /** If not all bytes could be written, an exception is thrown. + * @param Buf Data to write + * @param Len Number of bytes from Buf to write + */ + void write(const char Buf[], size_type Len); //[t51] + + /// Write string to large object + /** If not all bytes could be written, an exception is thrown. + * @param Buf Data to write; no terminating zero is written + */ + void write(const std::string &Buf) //[t50] + { write(Buf.c_str(), static_cast<size_type>(Buf.size())); } + + /// Read data from large object + /** Throws an exception if an error occurs while reading. + * @param Buf Location to store the read data in + * @param Len Number of bytes to try and read + * @return Number of bytes read, which may be less than the number requested + * if the end of the large object is reached + */ + size_type read(char Buf[], size_type Len); //[t50] + + /// Seek in large object's data stream + /** Throws an exception if an error occurs. + * @return The new position in the large object + */ + size_type seek(size_type dest, seekdir dir); //[t51] + + /// Report current position in large object's data stream + /** Throws an exception if an error occurs. + * @return The current position in the large object + */ + size_type tell() const; //[t50] + //@} + + /** + * @name Low-level access to object contents + * + * These functions provide a more "C-like" access interface, returning special + * values instead of throwing exceptions on error. These functions are + * generally best avoided in favour of the high-level access functions, which + * behave more like C++ functions should. + */ + //@{ + /// Seek in large object's data stream + /** Does not throw exception in case of error; inspect return value and + * @c errno instead. + * @param dest Offset to go to + * @param dir Origin to which dest is relative: ios_base::beg (from beginning + * of the object), ios_base::cur (from current access position), or + * ios_base;:end (from end of object) + * @return New position in large object, or -1 if an error occurred. + */ + pos_type cseek(off_type dest, seekdir dir) noexcept; //[t50] + + /// Write to large object's data stream + /** Does not throw exception in case of error; inspect return value and + * @c errno instead. + * @param Buf Data to write + * @param Len Number of bytes to write + * @return Number of bytes actually written, or -1 if an error occurred. + */ + off_type cwrite(const char Buf[], size_type Len) noexcept; //[t50] + + /// Read from large object's data stream + /** Does not throw exception in case of error; inspect return value and + * @c errno instead. + * @param Buf Area where incoming bytes should be stored + * @param Len Number of bytes to read + * @return Number of bytes actually read, or -1 if an error occurred. + */ + off_type cread(char Buf[], size_type Len) noexcept; //[t50] + + /// Report current position in large object's data stream + /** Does not throw exception in case of error; inspect return value and + * @c errno instead. + * @return Current position in large object, of -1 if an error occurred. + */ + pos_type ctell() const noexcept; //[t50] + //@} + + /** + * @name Error/warning output + */ + //@{ + /// Issue message to transaction's notice processor + void process_notice(const std::string &) noexcept; //[t50] + //@} + + using largeobject::remove; + + using largeobject::operator==; + using largeobject::operator!=; + using largeobject::operator<; + using largeobject::operator<=; + using largeobject::operator>; + using largeobject::operator>=; + +private: + PQXX_PRIVATE std::string reason(int err) const; + internal::pq::PGconn *raw_connection() const + { return largeobject::raw_connection(m_trans); } + + PQXX_PRIVATE void open(openmode mode); + void close() noexcept; + + dbtransaction &m_trans; + int m_fd = -1; + + largeobjectaccess() =delete; + largeobjectaccess(const largeobjectaccess &) =delete; + largeobjectaccess operator=(const largeobjectaccess &) =delete; +}; + + +/// Streambuf to use large objects in standard I/O streams +/** The standard streambuf classes provide uniform access to data storage such + * as files or string buffers, so they can be accessed using standard input or + * output streams. This streambuf implementation provides similar access to + * large objects, so they can be read and written using the same stream classes. + * + * @warning This class may not work properly in compiler environments that don't + * fully support Standard-compliant streambufs, such as g++ 2.95 or older. + */ +template<typename CHAR=char, typename TRAITS=std::char_traits<CHAR>> + class largeobject_streambuf : + public std::basic_streambuf<CHAR, TRAITS> +{ + using size_type = long; +public: + using char_type = CHAR; + using traits_type = TRAITS; + using int_type = typename traits_type::int_type; + using pos_type = typename traits_type::pos_type; + using off_type = typename traits_type::off_type; + using openmode = largeobjectaccess::openmode; + using seekdir = largeobjectaccess::seekdir; + + largeobject_streambuf( //[t48] + dbtransaction &T, + largeobject O, + openmode mode=std::ios::in|std::ios::out, + size_type BufSize=512) : + m_bufsize{BufSize}, + m_obj{T, O, mode}, + m_g{nullptr}, + m_p{nullptr} + { initialize(mode); } + + largeobject_streambuf( //[t48] + dbtransaction &T, + oid O, + openmode mode=std::ios::in|std::ios::out, + size_type BufSize=512) : + m_bufsize{BufSize}, + m_obj{T, O, mode}, + m_g{nullptr}, + m_p{nullptr} + { initialize(mode); } + + virtual ~largeobject_streambuf() noexcept + { delete [] m_p; delete [] m_g; } + + + /// For use by large object stream classes + void process_notice(const std::string &s) { m_obj.process_notice(s); } + +protected: + virtual int sync() override + { + // setg() sets eback, gptr, egptr + this->setg(this->eback(), this->eback(), this->egptr()); + return overflow(EoF()); + } + + virtual pos_type seekoff( + off_type offset, + seekdir dir, + openmode) + override + { + return AdjustEOF(m_obj.cseek(largeobjectaccess::off_type(offset), dir)); + } + + virtual pos_type seekpos(pos_type pos, openmode) override + { + const largeobjectaccess::pos_type newpos = m_obj.cseek( + largeobjectaccess::off_type(pos), + std::ios::beg); + return AdjustEOF(newpos); + } + + virtual int_type overflow(int_type ch = EoF()) override + { + char *const pp = this->pptr(); + if (pp == nullptr) return EoF(); + char *const pb = this->pbase(); + int_type res = 0; + + if (pp > pb) res = int_type(AdjustEOF(m_obj.cwrite(pb, pp-pb))); + this->setp(m_p, m_p + m_bufsize); + + // Write that one more character, if it's there. + if (ch != EoF()) + { + *this->pptr() = char(ch); + this->pbump(1); + } + return res; + } + + virtual int_type underflow() override + { + if (this->gptr() == nullptr) return EoF(); + char *const eb = this->eback(); + const int_type res(static_cast<int_type>( + AdjustEOF(m_obj.cread(this->eback(), m_bufsize)))); + this->setg(eb, eb, eb + ((res==EoF()) ? 0 : res)); + return ((res == 0) or (res == EoF())) ? EoF() : *eb; + } + +private: + /// Shortcut for traits_type::eof(). + static int_type EoF() { return traits_type::eof(); } + + /// Helper: change error position of -1 to EOF (probably a no-op). + template<typename INTYPE> + static std::streampos AdjustEOF(INTYPE pos) + { return (pos==-1) ? std::streampos(EoF()) : std::streampos(pos); } + + void initialize(openmode mode) + { + if (mode & std::ios::in) + { + m_g = new char_type[unsigned(m_bufsize)]; + this->setg(m_g, m_g, m_g); + } + if (mode & std::ios::out) + { + m_p = new char_type[unsigned(m_bufsize)]; + this->setp(m_p, m_p + m_bufsize); + } + } + + const size_type m_bufsize; + largeobjectaccess m_obj; + + /// Get & put buffers. + char_type *m_g, *m_p; +}; + + +/// Input stream that gets its data from a large object. +/** Use this class exactly as you would any other istream to read data from a + * large object. All formatting and streaming operations of @c std::istream are + * supported. What you'll typically want to use, however, is the ilostream + * alias (which defines a basic_ilostream for @c char). This is similar to + * how e.g. @c std::ifstream relates to @c std::basic_ifstream. + * + * Currently only works for <tt><char, std::char_traits<char>></tt>. + */ +template<typename CHAR=char, typename TRAITS=std::char_traits<CHAR>> + class basic_ilostream : + public std::basic_istream<CHAR, TRAITS> +{ + using super = std::basic_istream<CHAR, TRAITS>; + +public: + using char_type = CHAR; + using traits_type = TRAITS; + using int_type = typename traits_type::int_type; + using pos_type = typename traits_type::pos_type; + using off_type = typename traits_type::off_type; + + /// Create a basic_ilostream + /** + * @param T Transaction in which this stream is to exist + * @param O Large object to access + * @param BufSize Size of buffer to use internally (optional) + */ + basic_ilostream( //[t57] + dbtransaction &T, + largeobject O, + largeobject::size_type BufSize=512) : + super{nullptr}, + m_buf{T, O, std::ios::in, BufSize} + { super::init(&m_buf); } + + /// Create a basic_ilostream + /** + * @param T Transaction in which this stream is to exist + * @param O Identifier of a large object to access + * @param BufSize Size of buffer to use internally (optional) + */ + basic_ilostream( //[t48] + dbtransaction &T, + oid O, + largeobject::size_type BufSize=512) : + super{nullptr}, + m_buf{T, O, std::ios::in, BufSize} + { super::init(&m_buf); } + +private: + largeobject_streambuf<CHAR,TRAITS> m_buf; +}; + +using ilostream = basic_ilostream<char>; + + +/// Output stream that writes data back to a large object +/** Use this class exactly as you would any other ostream to write data to a + * large object. All formatting and streaming operations of @c std::ostream are + * supported. What you'll typically want to use, however, is the olostream + * alias (which defines a basic_olostream for @c char). This is similar to + * how e.g. @c std::ofstream is related to @c std::basic_ofstream. + * + * Currently only works for <tt><char, std::char_traits<char>></tt>. + */ +template<typename CHAR=char, typename TRAITS=std::char_traits<CHAR>> + class basic_olostream : + public std::basic_ostream<CHAR, TRAITS> +{ + using super = std::basic_ostream<CHAR, TRAITS>; +public: + using char_type = CHAR; + using traits_type = TRAITS; + using int_type = typename traits_type::int_type; + using pos_type = typename traits_type::pos_type; + using off_type = typename traits_type::off_type; + + /// Create a basic_olostream + /** + * @param T transaction in which this stream is to exist + * @param O a large object to access + * @param BufSize size of buffer to use internally (optional) + */ + basic_olostream( //[t48] + dbtransaction &T, + largeobject O, + largeobject::size_type BufSize=512) : + super{nullptr}, + m_buf{T, O, std::ios::out, BufSize} + { super::init(&m_buf); } + + /// Create a basic_olostream + /** + * @param T transaction in which this stream is to exist + * @param O a large object to access + * @param BufSize size of buffer to use internally (optional) + */ + basic_olostream( //[t57] + dbtransaction &T, + oid O, + largeobject::size_type BufSize=512) : + super{nullptr}, + m_buf{T, O, std::ios::out, BufSize} + { super::init(&m_buf); } + + ~basic_olostream() + { + try + { + m_buf.pubsync(); m_buf.pubsync(); + } + catch (const std::exception &e) + { + m_buf.process_notice(e.what()); + } + } + +private: + largeobject_streambuf<CHAR,TRAITS> m_buf; +}; + +using olostream = basic_olostream<char>; + + +/// Stream that reads and writes a large object +/** Use this class exactly as you would a std::iostream to read data from, or + * write data to a large object. All formatting and streaming operations of + * @c std::iostream are supported. What you'll typically want to use, however, + * is the lostream alias (which defines a basic_lostream for @c char). This + * is similar to how e.g. @c std::fstream is related to @c std::basic_fstream. + * + * Currently only works for <tt><char, std::char_traits<char>></tt>. + */ +template<typename CHAR=char, typename TRAITS=std::char_traits<CHAR>> + class basic_lostream : + public std::basic_iostream<CHAR, TRAITS> +{ + using super = std::basic_iostream<CHAR, TRAITS>; + +public: + using char_type = CHAR; + using traits_type = TRAITS; + using int_type = typename traits_type::int_type; + using pos_type = typename traits_type::pos_type; + using off_type = typename traits_type::off_type; + + /// Create a basic_lostream + /** + * @param T Transaction in which this stream is to exist + * @param O Large object to access + * @param BufSize Size of buffer to use internally (optional) + */ + basic_lostream( //[t59] + dbtransaction &T, + largeobject O, + largeobject::size_type BufSize=512) : + super{nullptr}, + m_buf{T, O, std::ios::in | std::ios::out, BufSize} + { super::init(&m_buf); } + + /// Create a basic_lostream + /** + * @param T Transaction in which this stream is to exist + * @param O Large object to access + * @param BufSize Size of buffer to use internally (optional) + */ + basic_lostream( //[t59] + dbtransaction &T, + oid O, + largeobject::size_type BufSize=512) : + super{nullptr}, + m_buf{T, O, std::ios::in | std::ios::out, BufSize} + { super::init(&m_buf); } + + ~basic_lostream() + { + try + { + m_buf.pubsync(); m_buf.pubsync(); + } + catch (const std::exception &e) + { + m_buf.process_notice(e.what()); + } + } + +private: + largeobject_streambuf<CHAR,TRAITS> m_buf; +}; + +using lostream = basic_lostream<char>; + +} // namespace pqxx + +#include "pqxx/compiler-internal-post.hxx" + +#endif diff --git a/contrib/libs/libpqxx/include/pqxx/nontransaction b/contrib/libs/libpqxx/include/pqxx/nontransaction new file mode 100644 index 0000000000..e62ebdbc0b --- /dev/null +++ b/contrib/libs/libpqxx/include/pqxx/nontransaction @@ -0,0 +1,6 @@ +/** pqxx::nontransaction class. + * + * pqxx::nontransaction provides nontransactional database access. + */ +// Actual definitions in .hxx file so editors and such recognize file type. +#include "pqxx/nontransaction.hxx" diff --git a/contrib/libs/libpqxx/include/pqxx/nontransaction.hxx b/contrib/libs/libpqxx/include/pqxx/nontransaction.hxx new file mode 100644 index 0000000000..40fb1331cf --- /dev/null +++ b/contrib/libs/libpqxx/include/pqxx/nontransaction.hxx @@ -0,0 +1,80 @@ +/** Definition of the pqxx::nontransaction class. + * + * pqxx::nontransaction provides nontransactional database access + * + * DO NOT INCLUDE THIS FILE DIRECTLY; include pqxx/nontransaction 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_NONTRANSACTION +#define PQXX_H_NONTRANSACTION + +#include "pqxx/compiler-public.hxx" +#include "pqxx/compiler-internal-pre.hxx" + +#include "pqxx/connection_base.hxx" +#include "pqxx/result.hxx" +#include "pqxx/transaction_base.hxx" + +// Methods tested in eg. test module test01 are marked with "//[t01]". + +namespace pqxx +{ + +/// Simple "transaction" class offering no transactional integrity. +/** + * @ingroup transaction + * + * nontransaction, like transaction or any other transaction_base-derived class, + * provides access to a database through a connection. Unlike its siblings, + * however, nontransaction does not maintain any kind of transactional + * integrity. This may be useful eg. for read-only access to the database that + * does not require a consistent, atomic view on its data; or for operations + * that are not allowed within a backend transaction, such as creating tables. + * + * For queries that update the database, however, a real transaction is likely + * to be faster unless the transaction consists of only a single record update. + * + * Also, you can keep a nontransaction open for as long as you like. Actual + * back-end transactions are limited in lifespan, and will sometimes fail just + * because they took too long to execute or were left idle for too long. This + * will not happen with a nontransaction (although the connection may still time + * out, e.g. when the network is unavailable for a very long time). + * + * Any query executed in a nontransaction is committed immediately, and neither + * commit() nor abort() has any effect. + * + * Database features that require a backend transaction, such as cursors or + * large objects, will not work in a nontransaction. + */ +class PQXX_LIBEXPORT nontransaction : public transaction_base +{ +public: + /// Constructor. + /** Create a "dummy" transaction. + * @param C Connection that this "transaction" will operate on. + * @param Name Optional name for the transaction, beginning with a letter + * and containing only letters and digits. + */ + explicit nontransaction( //[t14] + connection_base &C, + const std::string &Name=std::string{}) : + namedclass{"nontransaction", Name}, transaction_base{C} { Begin(); } + + virtual ~nontransaction(); //[t14] + +private: + virtual void do_begin() override {} //[t14] + virtual result do_exec(const char C[]) override; //[t14] + virtual void do_commit() override {} //[t14] + virtual void do_abort() override {} //[t14] +}; + +} // namespace pqxx + +#include "pqxx/compiler-internal-post.hxx" +#endif diff --git a/contrib/libs/libpqxx/include/pqxx/notification b/contrib/libs/libpqxx/include/pqxx/notification new file mode 100644 index 0000000000..025b220baf --- /dev/null +++ b/contrib/libs/libpqxx/include/pqxx/notification @@ -0,0 +1,6 @@ +/** pqxx::notification_receiver functor interface. + * + * pqxx::notification_receiver handles incoming notifications. + */ +// Actual definitions in .hxx file so editors and such recognize file type. +#include "pqxx/notification.hxx" diff --git a/contrib/libs/libpqxx/include/pqxx/notification.hxx b/contrib/libs/libpqxx/include/pqxx/notification.hxx new file mode 100644 index 0000000000..77e818e009 --- /dev/null +++ b/contrib/libs/libpqxx/include/pqxx/notification.hxx @@ -0,0 +1,91 @@ +/** Definition of the pqxx::notification_receiver functor interface. + * + * pqxx::notification_receiver handles incoming notifications. + * + * DO NOT INCLUDE THIS FILE DIRECTLY; include pqxx/notification 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_NOTIFICATION +#define PQXX_H_NOTIFICATION + +#include "pqxx/compiler-public.hxx" +#include "pqxx/compiler-internal-pre.hxx" + +#include <string> + +#include "pqxx/types.hxx" + + +namespace pqxx +{ +/// "Observer" base class for notifications. +/** @addtogroup notification Notifications and Receivers + * + * To listen on a notification issued using the NOTIFY command, derive your own + * class from notification_receiver and define its function-call operator to + * perform whatever action you wish to take when the given notification arrives. + * Then create an object of that class and pass it to your connection. DO NOT + * use raw SQL to listen for notifications, or your attempts to listen won't be + * resumed when a connection fails--and you'll have no way to notice. + * + * Notifications never arrive inside a transaction, not even in a + * nontransaction. Therefore, you are free to open a transaction of your own + * inside your receiver's function invocation operator. + * + * Notifications you are listening for may arrive anywhere within libpqxx code, + * but be aware that @b PostgreSQL @b defers @b notifications @b occurring + * @b inside @b transactions. (This was done for excellent reasons; just think + * about what happens if the transaction where you happen to handle an incoming + * notification is later rolled back for other reasons). So if you're keeping a + * transaction open, don't expect any of your receivers on the same connection + * to be notified. + * + * (For very similar reasons, outgoing notifications are also not sent until the + * transaction that sends them commits.) + * + * Multiple receivers on the same connection may listen on a notification of the + * same name. An incoming notification is processed by invoking all receivers + * (zero or more) of the same name. + */ +class PQXX_LIBEXPORT PQXX_NOVTABLE notification_receiver +{ +public: + /// Register the receiver with a connection. + /** + * @param c Connnection to operate on. + * @param channel Name of the notification to listen for. + */ + notification_receiver(connection_base &c, const std::string &channel); + notification_receiver(const notification_receiver &) =delete; + notification_receiver &operator=(const notification_receiver &) =delete; + virtual ~notification_receiver(); + + /// The channel that this receiver listens on. + const std::string &channel() const { return m_channel; } + + /// Overridable: action to invoke when notification arrives. + /** + * @param payload On PostgreSQL 9.0 or later, an optional string that may have + * been passed to the NOTIFY command. + * @param backend_pid Process ID of the database backend process that served + * our connection when the notification arrived. The actual process ID behind + * the connection may have changed by the time this method is called. + */ + virtual void operator()(const std::string &payload, int backend_pid) =0; + +protected: + connection_base &conn() const noexcept { return m_conn; } + +private: + connection_base &m_conn; + std::string m_channel; +}; +} + +#include "pqxx/compiler-internal-post.hxx" +#endif diff --git a/contrib/libs/libpqxx/include/pqxx/pipeline b/contrib/libs/libpqxx/include/pqxx/pipeline new file mode 100644 index 0000000000..6029f14622 --- /dev/null +++ b/contrib/libs/libpqxx/include/pqxx/pipeline @@ -0,0 +1,6 @@ +/** pqxx::pipeline class. + * + * Throughput-optimized query interface. + */ +// Actual definitions in .hxx file so editors and such recognize file type. +#include "pqxx/pipeline.hxx" diff --git a/contrib/libs/libpqxx/include/pqxx/pipeline.hxx b/contrib/libs/libpqxx/include/pqxx/pipeline.hxx new file mode 100644 index 0000000000..25a5dea6a6 --- /dev/null +++ b/contrib/libs/libpqxx/include/pqxx/pipeline.hxx @@ -0,0 +1,210 @@ +/** Definition of the pqxx::pipeline class. + * + * Throughput-optimized query manager + * + * DO NOT INCLUDE THIS FILE DIRECTLY; include pqxx/pipeline 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_PIPELINE +#define PQXX_H_PIPELINE + +#include "pqxx/compiler-public.hxx" +#include "pqxx/compiler-internal-pre.hxx" + +#include <limits> +#include <map> +#include <string> + +#include "pqxx/transaction_base.hxx" + + +// Methods tested in eg. test module test01 are marked with "//[t01]". + +namespace pqxx +{ + +/// Processes several queries in FIFO manner, optimized for high throughput +/** Use a pipeline if you want to execute queries without always sitting still + * while they execute. Result retrieval is decoupled from execution request; + * queries "go in at the front" and results "come out the back." Actually + * results may be retrieved in any order, if you want. + * + * Feel free to pump as many queries into the pipeline as possible, even if they + * were generated after looking at a result from the same pipeline. To get the + * best possible throughput, try to make insertion of queries run as far ahead + * of results retrieval as possible; issue each query as early as possible and + * retrieve their results as late as possible, so the pipeline has as many + * ongoing queries as possible at any given time. In other words, keep it busy! + * + * One warning: if any of the queries you insert leads to a syntactic error, the + * error may be returned as if it were generated by an older query. Future + * versions may try to work around this if working in a nontransaction. + */ +class PQXX_LIBEXPORT pipeline : public internal::transactionfocus +{ +public: + using query_id = long; + + pipeline(const pipeline &) =delete; + pipeline &operator=(const pipeline &) =delete; + + explicit pipeline( //[t69] + transaction_base &, + const std::string &Name=std::string{}); + + ~pipeline() noexcept; + + /// Add query to the pipeline. + /** Queries are accumulated in the pipeline and sent to the backend in a + * concatenated format, separated by semicolons. The queries you insert must + * not use this construct themselves, or the pipeline will get hopelessly + * confused! + * @return Identifier for this query, unique only within this pipeline + */ + query_id insert(const std::string &); //[t69] + + /// Wait for all ongoing or pending operations to complete. + /** Detaches from the transaction when done. */ + void complete(); //[t71] + + /// Forget all ongoing or pending operations and retrieved results + /** Queries already sent to the backend may still be completed, depending + * on implementation and timing. + * + * Any error state (unless caused by an internal error) will also be cleared. + * This is mostly useful in a nontransaction, since a backend transaction is + * aborted automatically when an error occurs. + * + * Detaches from the transaction when done. + */ + void flush(); //[t70] + + /// Cancel ongoing query, if any. + /** May cancel any or all of the queries that have been inserted at this point + * whose results have not yet been retrieved. If the pipeline lives in a + * backend transaction, that transaction may be left in a nonfunctional state + * in which it can only be aborted. + * + * Therefore, either use this function in a nontransaction, or abort the + * transaction after calling it. + */ + void cancel(); + + /// Is result for given query available? + bool is_finished(query_id) const; //[t71] + + /// Retrieve result for given query. + /** If the query failed for whatever reason, this will throw an exception. + * The function will block if the query has not finished yet. + * @warning If results are retrieved out-of-order, i.e. in a different order + * than the one in which their queries were inserted, errors may "propagate" + * to subsequent queries. + */ + result retrieve(query_id qid) //[t71] + { return retrieve(m_queries.find(qid)).second; } + + /// Retrieve oldest unretrieved result (possibly wait for one) + /** @return The query's identifier and its result set */ + std::pair<query_id, result> retrieve(); //[t69] + + bool empty() const noexcept { return m_queries.empty(); } //[t69] + + /// Set maximum number of queries to retain before issuing them to the backend + /** The pipeline will perform better if multiple queries are issued at once, + * but retaining queries until the results are needed (as opposed to issuing + * them to the backend immediately) may negate any performance benefits the + * pipeline can offer. + * + * Recommended practice is to set this value no higher than the number of + * queries you intend to insert at a time. + * @param retain_max A nonnegative "retention capacity;" passing zero will + * cause queries to be issued immediately + * @return Old retention capacity + */ + int retain(int retain_max=2); //[t70] + + + /// Resume retained query emission (harmless when not needed) + void resume(); //[t70] + +private: + class PQXX_PRIVATE Query + { + public: + explicit Query(const std::string &q) : m_query{q}, m_res{} {} + + const result &get_result() const noexcept { return m_res; } + void set_result(const result &r) noexcept { m_res = r; } + const std::string &get_query() const noexcept { return m_query; } + + private: + std::string m_query; + result m_res; + }; + + using QueryMap = std::map<query_id,Query>; + + void attach(); + void detach(); + + /// Upper bound to query id's + static constexpr query_id qid_limit() noexcept + { + // Parenthesise this to work around an eternal Visual C++ problem: + // Without the extra parentheses, unless NOMINMAX is defined, the + // preprocessor will mistake this "max" for its annoying built-in macro + // of the same name. + return (std::numeric_limits<query_id>::max)(); + } + + /// Create new query_id + PQXX_PRIVATE query_id generate_id(); + + bool have_pending() const noexcept + { return m_issuedrange.second != m_issuedrange.first; } + + PQXX_PRIVATE void issue(); + + /// The given query failed; never issue anything beyond that + void set_error_at(query_id qid) noexcept + { if (qid < m_error) m_error = qid; } + + /// Throw pqxx::internal_error. + [[noreturn]] PQXX_PRIVATE void internal_error(const std::string &err); + + PQXX_PRIVATE bool obtain_result(bool expect_none=false); + + PQXX_PRIVATE void obtain_dummy(); + PQXX_PRIVATE void get_further_available_results(); + PQXX_PRIVATE void check_end_results(); + + /// Receive any results that happen to be available; it's not urgent + PQXX_PRIVATE void receive_if_available(); + + /// Receive results, up to stop if possible + PQXX_PRIVATE void receive(pipeline::QueryMap::const_iterator stop); + std::pair<pipeline::query_id, result> + retrieve(pipeline::QueryMap::iterator); + + QueryMap m_queries; + std::pair<QueryMap::iterator,QueryMap::iterator> m_issuedrange; + int m_retain = 0; + int m_num_waiting = 0; + query_id m_q_id = 0; + + /// Is there a "dummy query" pending? + bool m_dummy_pending = false; + + /// Point at which an error occurred; no results beyond it will be available + query_id m_error = qid_limit(); +}; + +} // namespace + +#include "pqxx/compiler-internal-post.hxx" +#endif diff --git a/contrib/libs/libpqxx/include/pqxx/pqxx b/contrib/libs/libpqxx/include/pqxx/pqxx new file mode 100644 index 0000000000..9cc33ad121 --- /dev/null +++ b/contrib/libs/libpqxx/include/pqxx/pqxx @@ -0,0 +1,19 @@ +/// Convenience header: include all libpqxx definitions. +#include "pqxx/array" +#include "pqxx/binarystring" +#include "pqxx/connection" +#include "pqxx/cursor" +#include "pqxx/errorhandler" +#include "pqxx/except" +#include "pqxx/largeobject" +#include "pqxx/nontransaction" +#include "pqxx/notification" +#include "pqxx/pipeline" +#include "pqxx/prepared_statement" +#include "pqxx/result" +#include "pqxx/robusttransaction" +#include "pqxx/stream_from" +#include "pqxx/stream_to" +#include "pqxx/subtransaction" +#include "pqxx/transaction" +#include "pqxx/transactor" diff --git a/contrib/libs/libpqxx/include/pqxx/prepared_statement b/contrib/libs/libpqxx/include/pqxx/prepared_statement new file mode 100644 index 0000000000..20c645f301 --- /dev/null +++ b/contrib/libs/libpqxx/include/pqxx/prepared_statement @@ -0,0 +1,6 @@ +/** Helper classes for defining and executing prepared statements. + * + * See the connection_base hierarchy for more about prepared statements + */ +// Actual definitions in .hxx file so editors and such recognize file type. +#include "pqxx/prepared_statement.hxx" diff --git a/contrib/libs/libpqxx/include/pqxx/prepared_statement.hxx b/contrib/libs/libpqxx/include/pqxx/prepared_statement.hxx new file mode 100644 index 0000000000..604d40665a --- /dev/null +++ b/contrib/libs/libpqxx/include/pqxx/prepared_statement.hxx @@ -0,0 +1,177 @@ +/** Helper classes for defining and executing prepared statements. + * + * See the connection_base hierarchy for more about prepared statements. + * + * 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_PREPARED_STATEMENT +#define PQXX_H_PREPARED_STATEMENT + +#include "pqxx/compiler-public.hxx" +#include "pqxx/compiler-internal-pre.hxx" + +#include "pqxx/types.hxx" +#include "pqxx/internal/statement_parameters.hxx" + + + +namespace pqxx +{ +/// Dedicated namespace for helper types related to prepared statements. +namespace prepare +{ +/// Pass a number of statement parameters only known at runtime. +/** When you call any of the @c exec_params functions, the number of arguments + * is normally known at compile time. This helper function supports the case + * where it is not. + * + * Use this function to pass a variable number of parameters, based on a + * sequence ranging from @c begin to @c end exclusively. + * + * The technique combines with the regular static parameters. You can use it + * to insert dynamic parameter lists in any place, or places, among the call's + * parameters. You can even insert multiple dynamic sequences. + * + * @param begin A pointer or iterator for iterating parameters. + * @param end A pointer or iterator for iterating parameters. + * @return An object representing the parameters. + */ +template<typename IT> inline pqxx::internal::dynamic_params<IT> +make_dynamic_params(IT begin, IT end) +{ + return pqxx::internal::dynamic_params<IT>(begin, end); +} + + +/// Pass a number of statement parameters only known at runtime. +/** When you call any of the @c exec_params functions, the number of arguments + * is normally known at compile time. This helper function supports the case + * where it is not. + * + * Use this function to pass a variable number of parameters, based on a + * container of parameter values. + * + * The technique combines with the regular static parameters. You can use it + * to insert dynamic parameter lists in any place, or places, among the call's + * parameters. You can even insert multiple dynamic containers. + * + * @param container A container of parameter values. + * @return An object representing the parameters. + */ +template<typename C> +inline pqxx::internal::dynamic_params<typename C::const_iterator> +make_dynamic_params(const C &container) +{ + return pqxx::internal::dynamic_params<typename C::const_iterator>(container); +} +} // namespace prepare +} // namespace pqxx + +namespace pqxx +{ +namespace prepare +{ +/// Helper class for passing parameters to, and executing, prepared statements +/** @deprecated As of 6.0, use @c transaction_base::exec_prepared and friends. + */ +class PQXX_LIBEXPORT invocation : internal::statement_parameters +{ +public: + PQXX_DEPRECATED invocation(transaction_base &, const std::string &statement); + invocation &operator=(const invocation &) =delete; + + /// Execute! + result exec() const; + + /// Execute and return result in binary format + result exec_binary() const; + + /// Has a statement of this name been defined? + bool exists() const; + + /// Pass null parameter. + invocation &operator()() { add_param(); return *this; } + + /// Pass parameter value. + /** + * @param v parameter value; will be represented as a string internally. + */ + template<typename T> invocation &operator()(const T &v) + { add_param(v, true); return *this; } + + /// Pass binary parameter value for a BYTEA field. + /** + * @param v binary string; will be passed on directly in binary form. + */ + invocation &operator()(const binarystring &v) + { add_binary_param(v, true); return *this; } + + /// Pass parameter value. + /** + * @param v parameter value (will be represented as a string internally). + * @param nonnull replaces value with null if set to false. + */ + template<typename T> invocation &operator()(const T &v, bool nonnull) + { add_param(v, nonnull); return *this; } + + /// Pass binary parameter value for a BYTEA field. + /** + * @param v binary string; will be passed on directly in binary form. + * @param nonnull determines whether to pass a real value, or nullptr. + */ + invocation &operator()(const binarystring &v, bool nonnull) + { add_binary_param(v, nonnull); return *this; } + + /// Pass C-style parameter string, or null if pointer is null. + /** + * This version is for passing C-style strings; it's a template, so any + * pointer type that @c to_string accepts will do. + * + * @param v parameter value (will be represented as a C++ string internally) + * @param nonnull replaces value with null if set to @c false + */ + template<typename T> invocation &operator()(T *v, bool nonnull=true) + { add_param(v, nonnull); return *this; } + + /// Pass C-style string parameter, or null if pointer is null. + /** This duplicates the pointer-to-template-argument-type version of the + * operator, but helps compilers with less advanced template implementations + * disambiguate calls where C-style strings are passed. + */ + invocation &operator()(const char *v, bool nonnull=true) + { add_param(v, nonnull); return *this; } + +private: + transaction_base &m_home; + const std::string m_statement; + + invocation &setparam(const std::string &, bool nonnull); + + result internal_exec(result_format format) const; +}; + + +namespace internal +{ +/// Internal representation of a prepared statement definition. +struct PQXX_LIBEXPORT prepared_def +{ + /// Text of prepared query. + std::string definition; + /// Has this prepared statement been prepared in the current session? + bool registered = false; + + prepared_def() =default; + explicit prepared_def(const std::string &); +}; + +} // namespace pqxx::prepare::internal +} // namespace pqxx::prepare +} // namespace pqxx + +#include "pqxx/compiler-internal-post.hxx" +#endif diff --git a/contrib/libs/libpqxx/include/pqxx/result b/contrib/libs/libpqxx/include/pqxx/result new file mode 100644 index 0000000000..d61e588681 --- /dev/null +++ b/contrib/libs/libpqxx/include/pqxx/result @@ -0,0 +1,11 @@ +/** pqxx::result class and support classes. + * + * pqxx::result represents the set of result rows from a database query. + */ +// Actual definitions in .hxx file so editors and such recognize file type. +#include "pqxx/result.hxx" + +// Now include some types which depend on result, but which the user will +// expect to see defined after including this header. +#include "pqxx/result_iterator.hxx" +#include "pqxx/field.hxx" diff --git a/contrib/libs/libpqxx/include/pqxx/result.hxx b/contrib/libs/libpqxx/include/pqxx/result.hxx new file mode 100644 index 0000000000..b1f5ce3f4c --- /dev/null +++ b/contrib/libs/libpqxx/include/pqxx/result.hxx @@ -0,0 +1,249 @@ +/** Definitions for the pqxx::result class and support classes. + * + * pqxx::result represents the set of result rows from a database query. + * + * DO NOT INCLUDE THIS FILE DIRECTLY; include pqxx/result 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_RESULT +#define PQXX_H_RESULT + +#include "pqxx/compiler-public.hxx" +#include "pqxx/compiler-internal-pre.hxx" + +#include <ios> +#include <memory> +#include <stdexcept> + +#include "pqxx/except.hxx" +#include "pqxx/types.hxx" +#include "pqxx/util.hxx" + +#include "pqxx/internal/encodings.hxx" + + +// Methods tested in eg. test module test01 are marked with "//[t01]". + +namespace pqxx +{ +namespace internal +{ +PQXX_LIBEXPORT void clear_result(const pq::PGresult *); + +namespace gate +{ +class result_connection; +class result_creation; +class result_row; +class result_sql_cursor; +} // namespace internal::gate +} // namespace internal + + +enum class result_format +{ + text = 0, + binary = 1 +}; + + +/// Result set containing data returned by a query or command. +/** This behaves as a container (as defined by the C++ standard library) and + * provides random access const iterators to iterate over its rows. A row + * can also be accessed by indexing a result R by the row's zero-based + * number: + * + * @code + * for (result::size_type i=0; i < R.size(); ++i) Process(R[i]); + * @endcode + * + * Result sets in libpqxx are lightweight, reference-counted wrapper objects + * which are relatively small and cheap to copy. Think of a result object as + * a "smart pointer" to an underlying result set. + * + * @warning The result set that a result object points to is not thread-safe. + * If you copy a result object, it still refers to the same underlying result + * set. So never copy, destroy, query, or otherwise access a result while + * another thread may be copying, destroying, querying, or otherwise accessing + * the same result set--even if it is doing so through a different result + * object! + */ +class PQXX_LIBEXPORT result +{ +public: + using size_type = result_size_type; + using difference_type = result_difference_type; + using reference = row; + using const_iterator = const_result_iterator; + using pointer = const_iterator; + using iterator = const_iterator; + using const_reverse_iterator = const_reverse_result_iterator; + using reverse_iterator = const_reverse_iterator; + + result() noexcept : //[t03] + m_data(make_data_pointer()), + m_query(), + m_encoding(internal::encoding_group::MONOBYTE) + {} + result(const result &rhs) noexcept =default; //[t01] + + result &operator=(const result &rhs) noexcept =default; //[t10] + + /** + * @name Comparisons + */ + //@{ + bool operator==(const result &) const noexcept; //[t70] + bool operator!=(const result &rhs) const noexcept //[t70] + { return not operator==(rhs); } + //@} + + const_reverse_iterator rbegin() const; //[t75] + const_reverse_iterator crbegin() const; + const_reverse_iterator rend() const; //[t75] + const_reverse_iterator crend() const; + + const_iterator begin() const noexcept; //[t01] + const_iterator cbegin() const noexcept; + inline const_iterator end() const noexcept; //[t01] + inline const_iterator cend() const noexcept; + + reference front() const noexcept; //[t74] + reference back() const noexcept; //[t75] + + PQXX_PURE size_type size() const noexcept; //[t02] + PQXX_PURE bool empty() const noexcept; //[t11] + size_type capacity() const noexcept { return size(); } //[t20] + + void swap(result &) noexcept; //[t77] + + const row operator[](size_type i) const noexcept; //[t02] + const row at(size_type) const; //[t10] + + void clear() noexcept { m_data.reset(); m_query = nullptr; } //[t20] + + /** + * @name Column information + */ + //@{ + /// Number of columns in result. + PQXX_PURE row_size_type columns() const noexcept; //[t11] + + /// Number of given column (throws exception if it doesn't exist). + row_size_type column_number(const char ColName[]) const; //[t11] + + /// Number of given column (throws exception if it doesn't exist). + row_size_type column_number(const std::string &Name) const //[t11] + {return column_number(Name.c_str());} + + /// Name of column with this number (throws exception if it doesn't exist) + const char *column_name(row_size_type Number) const; //[t11] + + /// Type of given column + oid column_type(row_size_type ColNum) const; //[t07] + /// Type of given column + oid column_type(int ColNum) const //[t07] + { return column_type(row_size_type(ColNum)); } + + /// Type of given column + oid column_type(const std::string &ColName) const //[t07] + { return column_type(column_number(ColName)); } + + /// Type of given column + oid column_type(const char ColName[]) const //[t07] + { return column_type(column_number(ColName)); } + + /// What table did this column come from? + oid column_table(row_size_type ColNum) const; //[t02] + + /// What table did this column come from? + oid column_table(int ColNum) const //[t02] + { return column_table(row_size_type(ColNum)); } + + /// What table did this column come from? + oid column_table(const std::string &ColName) const //[t02] + { return column_table(column_number(ColName)); } + + /// What column in its table did this column come from? + row_size_type table_column(row_size_type ColNum) const; //[t93] + + /// What column in its table did this column come from? + row_size_type table_column(int ColNum) const //[t93] + { return table_column(row_size_type(ColNum)); } + + /// What column in its table did this column come from? + row_size_type table_column(const std::string &ColName) const //[t93] + { return table_column(column_number(ColName)); } + //@} + + /// Query that produced this result, if available (empty string otherwise) + PQXX_PURE const std::string &query() const noexcept; //[t70] + + /// If command was @c INSERT of 1 row, return oid of inserted row + /** @return Identifier of inserted row if exactly one row was inserted, or + * oid_none otherwise. + */ + PQXX_PURE oid inserted_oid() const; //[t13] + + /// If command was @c INSERT, @c UPDATE, or @c DELETE: number of affected rows + /** @return Number of affected rows if last command was @c INSERT, @c UPDATE, + * or @c DELETE; zero for all other commands. + */ + PQXX_PURE size_type affected_rows() const; //[t07] + + +private: + using data_pointer = std::shared_ptr<const internal::pq::PGresult>; + + /// Underlying libpq result set. + data_pointer m_data; + + /// Factory for data_pointer. + static data_pointer make_data_pointer( + const internal::pq::PGresult *res=nullptr) + { return data_pointer{res, internal::clear_result}; } + + /// Query string. + std::shared_ptr<std::string> m_query; + + internal::encoding_group m_encoding; + + static const std::string s_empty_string; + + friend class pqxx::field; + PQXX_PURE const char *GetValue(size_type Row, row_size_type Col) const; + PQXX_PURE bool get_is_null(size_type Row, row_size_type Col) const; + PQXX_PURE field_size_type get_length( + size_type, + row_size_type) const noexcept; + + friend class pqxx::internal::gate::result_creation; + result( + internal::pq::PGresult *rhs, + const std::string &Query, + internal::encoding_group enc); + + PQXX_PRIVATE void check_status() const; + + friend class pqxx::internal::gate::result_connection; + friend class pqxx::internal::gate::result_row; + bool operator!() const noexcept { return not m_data.get(); } + operator bool() const noexcept { return m_data.get() != nullptr; } + + [[noreturn]] PQXX_PRIVATE void ThrowSQLError( + const std::string &Err, + const std::string &Query) const; + PQXX_PRIVATE PQXX_PURE int errorposition() const; + PQXX_PRIVATE std::string StatusError() const; + + friend class pqxx::internal::gate::result_sql_cursor; + PQXX_PURE const char *cmd_status() const noexcept; +}; +} // namespace pqxx +#include "pqxx/compiler-internal-post.hxx" +#endif diff --git a/contrib/libs/libpqxx/include/pqxx/result_iterator.hxx b/contrib/libs/libpqxx/include/pqxx/result_iterator.hxx new file mode 100644 index 0000000000..b8e54d23ec --- /dev/null +++ b/contrib/libs/libpqxx/include/pqxx/result_iterator.hxx @@ -0,0 +1,245 @@ +/** Definitions for the pqxx::result class and support classes. + * + * pqxx::result represents the set of result rows from a database query. + * + * DO NOT INCLUDE THIS FILE DIRECTLY; include pqxx/result 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_RESULT_ITERATOR +#define PQXX_H_RESULT_ITERATOR + +#include "pqxx/compiler-public.hxx" +#include "pqxx/compiler-internal-pre.hxx" + +#include "pqxx/row.hxx" + + +/* Result iterator. + * + * Don't include this header from your own application; it is included for you + * by other libpqxx headers. + */ + +namespace pqxx +{ +/// Iterator for rows in a result. Use as result::const_iterator. +/** A result, once obtained, cannot be modified. Therefore there is no + * plain iterator type for result. However its const_iterator type can be + * used to inspect its rows without changing them. + */ +class PQXX_LIBEXPORT const_result_iterator : public row +{ +public: + using iterator_category = std::random_access_iterator_tag; + using value_type = const row; + using pointer = const row *; + using reference = row; + using size_type = result_size_type; + using difference_type = result_difference_type; + + const_result_iterator() noexcept : row{result(), 0} {} + const_result_iterator(const row &t) noexcept : row{t} {} + + /** + * @name Dereferencing operators + */ + //@{ + /** The iterator "points to" its own row, which is also itself. This + * allows a result to be addressed as a two-dimensional container without + * going through the intermediate step of dereferencing the iterator. I + * hope this works out to be similar to C pointer/array semantics in useful + * cases. + * + * IIRC Alex Stepanov, the inventor of the STL, once remarked that having + * this as standard behaviour for pointers would be useful in some + * algorithms. So even if this makes me look foolish, I would seem to be in + * distinguished company. + */ + pointer operator->() const { return this; } //[t12] + reference operator*() const { return row{*this}; } //[t12] + //@} + + /** + * @name Manipulations + */ + //@{ + const_result_iterator operator++(int); //[t12] + const_result_iterator &operator++() { ++m_index; return *this; } //[t01] + const_result_iterator operator--(int); //[t12] + const_result_iterator &operator--() { --m_index; return *this; } //[t12] + + const_result_iterator &operator+=(difference_type i) //[t12] + { m_index += i; return *this; } + const_result_iterator &operator-=(difference_type i) //[t12] + { m_index -= i; return *this; } + //@} + + /** + * @name Comparisons + */ + //@{ + bool operator==(const const_result_iterator &i) const //[t12] + {return m_index==i.m_index;} + bool operator!=(const const_result_iterator &i) const //[t12] + {return m_index!=i.m_index;} + bool operator<(const const_result_iterator &i) const //[t12] + {return m_index<i.m_index;} + bool operator<=(const const_result_iterator &i) const //[t12] + {return m_index<=i.m_index;} + bool operator>(const const_result_iterator &i) const //[t12] + {return m_index>i.m_index;} + bool operator>=(const const_result_iterator &i) const //[t12] + {return m_index>=i.m_index;} + //@} + + /** + * @name Arithmetic operators + */ + //@{ + inline const_result_iterator operator+(difference_type) const; //[t12] + friend const_result_iterator operator+( //[t12] + difference_type, + const_result_iterator); + inline const_result_iterator operator-(difference_type) const; //[t12] + inline difference_type operator-(const_result_iterator) const; //[t12] + //@} + +private: + friend class pqxx::result; + const_result_iterator(const pqxx::result *r, result_size_type i) noexcept : + row{*r, i} {} +}; + + +/// Reverse iterator for result. Use as result::const_reverse_iterator. +class PQXX_LIBEXPORT const_reverse_result_iterator : + private const_result_iterator +{ +public: + using super = const_result_iterator; + using iterator_type = const_result_iterator; + using iterator_type::iterator_category; + using iterator_type::difference_type; + using iterator_type::pointer; + using value_type = iterator_type::value_type; + using reference = iterator_type::reference; + + const_reverse_result_iterator( //[t75] + const const_reverse_result_iterator &rhs) : + const_result_iterator{rhs} {} + explicit const_reverse_result_iterator( //[t75] + const const_result_iterator &rhs) : + const_result_iterator{rhs} { super::operator--(); } + + PQXX_PURE const_result_iterator base() const noexcept; //[t75] + + /** + * @name Dereferencing operators + */ + //@{ + using const_result_iterator::operator->; //[t75] + using const_result_iterator::operator*; //[t75] + //@} + + /** + * @name Manipulations + */ + //@{ + const_reverse_result_iterator &operator=( //[t75] + const const_reverse_result_iterator &r) + { iterator_type::operator=(r); return *this; } + const_reverse_result_iterator &operator++() //[t75] + { iterator_type::operator--(); return *this; } + const_reverse_result_iterator operator++(int); //[t75] + const_reverse_result_iterator &operator--() //[t75] + { iterator_type::operator++(); return *this; } + const_reverse_result_iterator operator--(int); //[t75] + const_reverse_result_iterator &operator+=(difference_type i) //[t75] + { iterator_type::operator-=(i); return *this; } + const_reverse_result_iterator &operator-=(difference_type i) //[t75] + { iterator_type::operator+=(i); return *this; } + //@} + + /** + * @name Arithmetic operators + */ + //@{ + const_reverse_result_iterator operator+(difference_type i) const //[t75] + { return const_reverse_result_iterator(base() - i); } + const_reverse_result_iterator operator-(difference_type i) //[t75] + { return const_reverse_result_iterator(base() + i); } + difference_type operator-( //[t75] + const const_reverse_result_iterator &rhs) const + { return rhs.const_result_iterator::operator-(*this); } + //@} + + /** + * @name Comparisons + */ + //@{ + bool operator==( //[t75] + const const_reverse_result_iterator &rhs) const noexcept + { return iterator_type::operator==(rhs); } + bool operator!=( //[t75] + const const_reverse_result_iterator &rhs) const noexcept + { return not operator==(rhs); } + + bool operator<(const const_reverse_result_iterator &rhs) const //[t75] + { return iterator_type::operator>(rhs); } + bool operator<=(const const_reverse_result_iterator &rhs) const //[t75] + { return iterator_type::operator>=(rhs); } + bool operator>(const const_reverse_result_iterator &rhs) const //[t75] + { return iterator_type::operator<(rhs); } + bool operator>=(const const_reverse_result_iterator &rhs) const //[t75] + { return iterator_type::operator<=(rhs); } + //@} +}; + + +inline const_result_iterator +const_result_iterator::operator+(result::difference_type o) const +{ + return const_result_iterator{ + &m_result, size_type(result::difference_type(m_index) + o)}; +} + +inline const_result_iterator +operator+(result::difference_type o, const_result_iterator i) + { return i + o; } + +inline const_result_iterator +const_result_iterator::operator-(result::difference_type o) const +{ + return const_result_iterator{ + &m_result, + result_size_type(result::difference_type(m_index) - o)}; +} + +inline result::difference_type +const_result_iterator::operator-(const_result_iterator i) const + { return result::difference_type(num() - i.num()); } + +inline const_result_iterator result::end() const noexcept + { return const_result_iterator{this, size()}; } + + +inline const_result_iterator result::cend() const noexcept + { return end(); } + + +inline const_reverse_result_iterator +operator+( + result::difference_type n, + const const_reverse_result_iterator &i) + { return const_reverse_result_iterator{i.base() - n}; } + +} // namespace pqxx + +#include "pqxx/compiler-internal-post.hxx" + +#endif diff --git a/contrib/libs/libpqxx/include/pqxx/robusttransaction b/contrib/libs/libpqxx/include/pqxx/robusttransaction new file mode 100644 index 0000000000..4d8c99fc33 --- /dev/null +++ b/contrib/libs/libpqxx/include/pqxx/robusttransaction @@ -0,0 +1,6 @@ +/** pqxx::robusttransaction class. + * + * pqxx::robusttransaction is a slower but safer transaction class. + */ +// Actual definitions in .hxx file so editors and such recognize file type. +#include "pqxx/robusttransaction.hxx" diff --git a/contrib/libs/libpqxx/include/pqxx/robusttransaction.hxx b/contrib/libs/libpqxx/include/pqxx/robusttransaction.hxx new file mode 100644 index 0000000000..c4c16323b1 --- /dev/null +++ b/contrib/libs/libpqxx/include/pqxx/robusttransaction.hxx @@ -0,0 +1,168 @@ +/** Definition of the pqxx::robusttransaction class. + * + * pqxx::robusttransaction is a slower but safer transaction class. + * + * DO NOT INCLUDE THIS FILE DIRECTLY; include pqxx/robusttransaction 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_ROBUSTTRANSACTION +#define PQXX_H_ROBUSTTRANSACTION + +#include "pqxx/compiler-public.hxx" +#include "pqxx/compiler-internal-pre.hxx" + +#include "pqxx/dbtransaction.hxx" + + +// Methods tested in eg. test module test01 are marked with "//[t01]". + +namespace pqxx +{ + +namespace internal +{ +/// Helper base class for the @c robusttransaction class template. +class PQXX_LIBEXPORT PQXX_NOVTABLE basic_robusttransaction : + public dbtransaction +{ +public: + /// Isolation level is read_committed by default. + using isolation_tag = isolation_traits<read_committed>; + + virtual ~basic_robusttransaction() =0; //[t16] + +protected: + basic_robusttransaction( + connection_base &C, + const std::string &IsolationLevel, + const std::string &table_name=std::string{}); //[t16] + +private: + using IDType = unsigned long; + IDType m_record_id = 0; + std::string m_xid; + std::string m_log_table; + std::string m_sequence; + int m_backendpid = -1; + + virtual void do_begin() override; //[t18] + virtual void do_commit() override; //[t16] + virtual void do_abort() override; //[t18] + + PQXX_PRIVATE void CreateLogTable(); + PQXX_PRIVATE void CreateTransactionRecord(); + PQXX_PRIVATE std::string sql_delete() const; + PQXX_PRIVATE void DeleteTransactionRecord() noexcept; + PQXX_PRIVATE bool CheckTransactionRecord(); +}; +} // namespace internal + + +/** + * @ingroup transaction + * + * @{ + */ + +/// Slightly slower, better-fortified version of transaction +/** robusttransaction is similar to transaction, but spends more effort (and + * performance!) to deal with the hopefully rare case that the connection to + * the backend is lost just as the current transaction is being committed. In + * this case, there is no way to determine whether the backend managed to + * commit the transaction before noticing the loss of connection. + * + * In such cases, this class tries to reconnect to the database and figure out + * what happened. It will need to store and manage some information (pretty + * much a user-level transaction log) in the back-end for each and every + * transaction just on the off chance that this problem might occur. + * This service level was made optional since you may not want to pay this + * overhead where it is not necessary. Certainly the use of this class makes + * no sense for local connections, or for transactions that read the database + * but never modify it, or for noncritical database manipulations. + * + * Besides being slower, it's theoretically possible that robusttransaction + * actually fails more instead of less often than a normal transaction. This is + * due to the added work and complexity. What robusttransaction tries to + * achieve is to be more deterministic, not more successful per se. + * + * When a user first uses a robusttransaction in a database, the class will + * attempt to create a log table there to keep vital transaction-related state + * information in. This table, located in that same database, will be called + * pqxxlog_*user*, where *user* is the PostgreSQL username for that user. If + * the log table can not be created, the transaction fails immediately. + * + * If the user does not have permission to create the log table, the database + * administrator may create one for him beforehand, and give ownership (or at + * least full insert/update rights) to the user. The table must contain two + * non-unique fields (which will never be null): "name" (of text type, + * @c varchar(256) by default) and "date" (of @c timestamp type). Older + * versions of robusttransaction also added a unique "id" field; this field is + * now obsolete and the log table's implicit oids are used instead. The log + * tables' names may be made configurable in a future version of libpqxx. + * + * The transaction log table contains records describing unfinished + * transactions, i.e. ones that have been started but not, as far as the client + * knows, committed or aborted. This can mean any of the following: + * + * <ol> + * <li> The transaction is in progress. Since backend transactions can't run + * for extended periods of time, this can only be the case if the log record's + * timestamp (compared to the server's clock) is not very old, provided of + * course that the server's system clock hasn't just made a radical jump. + * <li> The client's connection to the server was lost, just when the client was + * committing the transaction, and the client so far has not been able to + * re-establish the connection to verify whether the transaction was actually + * completed or rolled back by the server. This is a serious (and luckily a + * rare) condition and requires manual inspection of the database to determine + * what happened. The robusttransaction will emit clear and specific warnings + * to this effect, and will identify the log record describing the transaction + * in question. + * <li> The transaction was completed (either by commit or by rollback), but the + * client's connection was durably lost just as it tried to clean up the log + * record. Again, robusttransaction will emit a clear and specific warning to + * tell you about this and request that the record be deleted as soon as + * possible. + * <li> The client has gone offline at any time while in one of the preceding + * states. This also requires manual intervention, but the client obviously is + * not able to issue a warning. + * </ol> + * + * It is safe to drop a log table when it is not in use (ie., it is empty or all + * records in it represent states 2-4 above). Each robusttransaction will + * attempt to recreate the table at its next time of use. + */ +template<isolation_level ISOLATIONLEVEL=read_committed> +class robusttransaction : public internal::basic_robusttransaction +{ +public: + using isolation_tag = isolation_traits<ISOLATIONLEVEL>; + + /// Constructor + /** Creates robusttransaction of given name + * @param C Connection that this robusttransaction should live inside. + * @param Name optional human-readable name for this transaction + */ + explicit robusttransaction( + connection_base &C, + const std::string &Name=std::string{}) : + namedclass{fullname("robusttransaction",isolation_tag::name()), Name}, + internal::basic_robusttransaction(C, isolation_tag::name()) + { Begin(); } + + virtual ~robusttransaction() noexcept + { End(); } +}; + +/** + * @} + */ + +} // namespace pqxx + +#include "pqxx/compiler-internal-post.hxx" +#endif diff --git a/contrib/libs/libpqxx/include/pqxx/row.hxx b/contrib/libs/libpqxx/include/pqxx/row.hxx new file mode 100644 index 0000000000..2d8543795f --- /dev/null +++ b/contrib/libs/libpqxx/include/pqxx/row.hxx @@ -0,0 +1,403 @@ +/** Definitions for the pqxx::result class and support classes. + * + * pqxx::result represents the set of result rows from a database query. + * + * DO NOT INCLUDE THIS FILE DIRECTLY; include pqxx/result 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_ROW +#define PQXX_H_ROW + +#include "pqxx/compiler-public.hxx" +#include "pqxx/compiler-internal-pre.hxx" + +#include "pqxx/except.hxx" +#include "pqxx/field.hxx" +#include "pqxx/result.hxx" + + +// Methods tested in eg. test module test01 are marked with "//[t01]". + +namespace pqxx +{ +/// Reference to one row in a result. +/** A row represents one row (also called a row) in a query result set. + * It also acts as a container mapping column numbers or names to field + * values (see below): + * + * @code + * cout << row["date"].c_str() << ": " << row["name"].c_str() << endl; + * @endcode + * + * The row itself acts like a (non-modifyable) container, complete with its + * own const_iterator and const_reverse_iterator. + */ +class PQXX_LIBEXPORT row +{ +public: + using size_type = row_size_type; + using difference_type = row_difference_type; + using const_iterator = const_row_iterator; + using iterator = const_iterator; + using reference = field; + using pointer = const_row_iterator; + using const_reverse_iterator = const_reverse_row_iterator; + using reverse_iterator = const_reverse_iterator; + + row() =default; + + /// @deprecated Do not use this constructor. It will become private. + row(result r, size_t i) noexcept; + + ~row() noexcept =default; // Yes Scott Meyers, you're absolutely right[1] + + /** + * @name Comparison + */ + //@{ + PQXX_PURE bool operator==(const row &) const noexcept; //[t75] + bool operator!=(const row &rhs) const noexcept //[t75] + { return not operator==(rhs); } + //@} + + const_iterator begin() const noexcept; //[t82] + const_iterator cbegin() const noexcept; + const_iterator end() const noexcept; //[t82] + const_iterator cend() const noexcept; + + /** + * @name Field access + */ + //@{ + reference front() const noexcept; //[t74] + reference back() const noexcept; //[t75] + + const_reverse_row_iterator rbegin() const; //[t82] + const_reverse_row_iterator crbegin() const; + const_reverse_row_iterator rend() const; //[t82] + const_reverse_row_iterator crend() const; + + reference operator[](size_type) const noexcept; //[t11] + reference operator[](int) const noexcept; //[t02] + /** Address field by name. + * @warning This is much slower than indexing by number, or iterating. + */ + reference operator[](const char[]) const; //[t11] + /** Address field by name. + * @warning This is much slower than indexing by number, or iterating. + */ + reference operator[](const std::string &) const; //[t11] + reference at(size_type) const; //[t11] + reference at(int) const; //[t11] + /** Address field by name. + * @warning This is much slower than indexing by number, or iterating. + */ + reference at(const char[]) const; //[t11] + /** Address field by name. + * @warning This is much slower than indexing by number, or iterating. + */ + reference at(const std::string &) const; //[t11] + //@} + + size_type size() const noexcept //[t11] + { return m_end-m_begin; } + + void swap(row &) noexcept; //[t11] + + /// Row number, assuming this is a real row and not end()/rend(). + size_t rownumber() const noexcept { return size_t(m_index); } //[t11] + + /** + * @name Column information + */ + //@{ + /// Number of given column (throws exception if it doesn't exist) + size_type column_number(const std::string &ColName) const //[t30] + { return column_number(ColName.c_str()); } + + /// Number of given column (throws exception if it doesn't exist) + size_type column_number(const char[]) const; //[t30] + + /// Type of given column + oid column_type(size_type) const; //[t07] + + /// Type of given column + oid column_type(int ColNum) const //[t07] + { return column_type(size_type(ColNum)); } + + /// Type of given column + oid column_type(const std::string &ColName) const //[t07] + { return column_type(column_number(ColName)); } + + /// Type of given column + oid column_type(const char ColName[]) const //[t07] + { return column_type(column_number(ColName)); } + + /// What table did this column come from? + oid column_table(size_type ColNum) const; //[t02] + + /// What table did this column come from? + oid column_table(int ColNum) const //[t02] + { return column_table(size_type(ColNum)); } + /// What table did this column come from? + oid column_table(const std::string &ColName) const //[t02] + { return column_table(column_number(ColName)); } + + /// What column number in its table did this result column come from? + /** A meaningful answer can be given only if the column in question comes + * directly from a column in a table. If the column is computed in any + * other way, a logic_error will be thrown. + * + * @param ColNum a zero-based column number in this result set + * @return a zero-based column number in originating table + */ + size_type table_column(size_type) const; //[t93] + + /// What column number in its table did this result column come from? + size_type table_column(int ColNum) const //[t93] + { return table_column(size_type(ColNum)); } + + /// What column number in its table did this result column come from? + size_type table_column(const std::string &ColName) const //[t93] + { return table_column(column_number(ColName)); } + //@} + + size_t num() const { return rownumber(); } //[t01] + + /** Produce a slice of this row, containing the given range of columns. + * + * The slice runs from the range's starting column to the range's end + * column, exclusive. It looks just like a normal result row, except + * slices can be empty. + * + * @warning Slicing is a relatively new feature, and not all software may be + * prepared to deal with empty slices. If there is any chance that your + * program might be creating empty slices and passing them to code that may + * not be designed with the possibility of empty rows in mind, be sure to + * test for that case. + */ + row slice(size_type Begin, size_type End) const; + + // Is this an empty slice? + PQXX_PURE bool empty() const noexcept; + +protected: + friend class field; + /// Result set of which this is one row. + result m_result; + /// Row number. + /** + * You'd expect this to be a size_t, but due to the way reverse iterators + * are related to regular iterators, it must be allowed to underflow to -1. + */ + long m_index = 0; + /// First column in slice. This row ignores lower-numbered columns. + size_type m_begin = 0; + /// End column in slice. This row only sees lower-numbered columns. + size_type m_end = 0; +}; + + +/// Iterator for fields in a row. Use as row::const_iterator. +class PQXX_LIBEXPORT const_row_iterator : public field +{ +public: + using iterator_category = std::random_access_iterator_tag; + using value_type = const field; + using pointer = const field *; + using size_type = row_size_type; + using difference_type = row_difference_type; + using reference = field; + + const_row_iterator(const row &T, row_size_type C) noexcept : //[t82] + field{T, C} {} + const_row_iterator(const field &F) noexcept : field{F} {} //[t82] + + /** + * @name Dereferencing operators + */ + //@{ + pointer operator->() const { return this; } //[t82] + reference operator*() const { return field{*this}; } //[t82] + //@} + + /** + * @name Manipulations + */ + //@{ + const_row_iterator operator++(int); //[t82] + const_row_iterator &operator++() { ++m_col; return *this; } //[t82] + const_row_iterator operator--(int); //[t82] + const_row_iterator &operator--() { --m_col; return *this; } //[t82] + + const_row_iterator &operator+=(difference_type i) //[t82] + { m_col = size_type(difference_type(m_col) + i); return *this; } + const_row_iterator &operator-=(difference_type i) //[t82] + { m_col = size_type(difference_type(m_col) - i); return *this; } + //@} + + /** + * @name Comparisons + */ + //@{ + bool operator==(const const_row_iterator &i) const //[t82] + {return col()==i.col();} + bool operator!=(const const_row_iterator &i) const //[t82] + {return col()!=i.col();} + bool operator<(const const_row_iterator &i) const //[t82] + {return col()<i.col();} + bool operator<=(const const_row_iterator &i) const //[t82] + {return col()<=i.col();} + bool operator>(const const_row_iterator &i) const //[t82] + {return col()>i.col();} + bool operator>=(const const_row_iterator &i) const //[t82] + {return col()>=i.col();} + //@} + + /** + * @name Arithmetic operators + */ + //@{ + inline const_row_iterator operator+(difference_type) const; //[t82] + + friend const_row_iterator operator+( //[t82] + difference_type, + const_row_iterator); + + inline const_row_iterator operator-(difference_type) const; //[t82] + inline difference_type operator-(const_row_iterator) const; //[t82] + //@} +}; + + +/// Reverse iterator for a row. Use as row::const_reverse_iterator. +class PQXX_LIBEXPORT const_reverse_row_iterator : private const_row_iterator +{ +public: + using super = const_row_iterator; + using iterator_type = const_row_iterator; + using iterator_type::iterator_category; + using iterator_type::difference_type; + using iterator_type::pointer; + using value_type = iterator_type::value_type; + using reference = iterator_type::reference; + + const_reverse_row_iterator(const const_reverse_row_iterator &r) : //[t82] + const_row_iterator{r} {} + explicit + const_reverse_row_iterator(const super &rhs) noexcept : //[t82] + const_row_iterator{rhs} { super::operator--(); } + + PQXX_PURE iterator_type base() const noexcept; //[t82] + + /** + * @name Dereferencing operators + */ + //@{ + using iterator_type::operator->; //[t82] + using iterator_type::operator*; //[t82] + //@} + + /** + * @name Manipulations + */ + //@{ + const_reverse_row_iterator & + operator=(const const_reverse_row_iterator &r) //[t82] + { iterator_type::operator=(r); return *this; } + const_reverse_row_iterator operator++() //[t82] + { iterator_type::operator--(); return *this; } + const_reverse_row_iterator operator++(int); //[t82] + const_reverse_row_iterator &operator--() //[t82] + { iterator_type::operator++(); return *this; } + const_reverse_row_iterator operator--(int); //[t82] + const_reverse_row_iterator &operator+=(difference_type i) //[t82] + { iterator_type::operator-=(i); return *this; } + const_reverse_row_iterator &operator-=(difference_type i) //[t82] + { iterator_type::operator+=(i); return *this; } + //@} + + /** + * @name Arithmetic operators + */ + //@{ + const_reverse_row_iterator operator+(difference_type i) const //[t82] + { return const_reverse_row_iterator{base()-i}; } + const_reverse_row_iterator operator-(difference_type i) //[t82] + { return const_reverse_row_iterator{base()+i}; } + difference_type + operator-(const const_reverse_row_iterator &rhs) const //[t82] + { return rhs.const_row_iterator::operator-(*this); } + //@} + + /** + * @name Comparisons + */ + //@{ + bool operator==(const const_reverse_row_iterator &rhs) const noexcept //[t82] + { return iterator_type::operator==(rhs); } + bool operator!=(const const_reverse_row_iterator &rhs) const noexcept //[t82] + { return !operator==(rhs); } + + bool operator<(const const_reverse_row_iterator &rhs) const //[t82] + { return iterator_type::operator>(rhs); } + bool operator<=(const const_reverse_row_iterator &rhs) const //[t82] + { return iterator_type::operator>=(rhs); } + bool operator>(const const_reverse_row_iterator &rhs) const //[t82] + { return iterator_type::operator<(rhs); } + bool operator>=(const const_reverse_row_iterator &rhs) const //[t82] + { return iterator_type::operator<=(rhs); } + //@} +}; + + +inline const_row_iterator +const_row_iterator::operator+(difference_type o) const +{ + return const_row_iterator{ + row(home(), idx()), + size_type(difference_type(col()) + o)}; +} + +inline const_row_iterator +operator+(const_row_iterator::difference_type o, const_row_iterator i) + { return i + o; } + +inline const_row_iterator +const_row_iterator::operator-(difference_type o) const +{ + return const_row_iterator{ + row(home(), idx()), + size_type(difference_type(col()) - o)}; +} + +inline const_row_iterator::difference_type +const_row_iterator::operator-(const_row_iterator i) const + { return difference_type(num() - i.num()); } + + +} // namespace pqxx + + +/* +[1] Scott Meyers, in one of his essential books, "Effective C++" and "More +Effective C++", points out that it is good style to have any class containing +a member of pointer type define a destructor--just to show that it knows what +it is doing with the pointer. This helps prevent nasty memory leak / double +deletion bugs typically resulting from programmers' omission to deal with such +issues in their destructors. + +The @c -Weffc++ option in gcc generates warnings for noncompliance with Scott's +style guidelines, and hence necessitates the definition of this destructor, +trivial as it may be. +*/ + + +#include "pqxx/compiler-internal-post.hxx" + +#endif diff --git a/contrib/libs/libpqxx/include/pqxx/strconv b/contrib/libs/libpqxx/include/pqxx/strconv new file mode 100644 index 0000000000..b70bf39bf4 --- /dev/null +++ b/contrib/libs/libpqxx/include/pqxx/strconv @@ -0,0 +1,4 @@ +/** String conversion definitions. + */ +// Actual definitions in .hxx file so editors and such recognize file type. +#include "pqxx/strconv.hxx" diff --git a/contrib/libs/libpqxx/include/pqxx/strconv.hxx b/contrib/libs/libpqxx/include/pqxx/strconv.hxx new file mode 100644 index 0000000000..0cb120d876 --- /dev/null +++ b/contrib/libs/libpqxx/include/pqxx/strconv.hxx @@ -0,0 +1,341 @@ +/** String conversion definitions. + * + * DO NOT INCLUDE THIS FILE DIRECTLY; include pqxx/stringconv 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_STRINGCONV +#define PQXX_H_STRINGCONV + +#include "pqxx/compiler-public.hxx" + +#include <limits> +#include <sstream> +#include <stdexcept> + + +namespace pqxx +{ + +/** + * @defgroup stringconversion String conversion + * + * The PostgreSQL server accepts and represents data in string form. It has + * its own formats for various data types. The string conversions define how + * various C++ types translate to and from their respective PostgreSQL text + * representations. + * + * Each conversion is defined by a specialisation of the @c string_traits + * template. This template implements some basic functions to support the + * conversion, ideally in both directions. + * + * If you need to convert a type which is not supported out of the box, define + * your own @c string_traits specialisation for that type, similar to the ones + * defined here. Any conversion code which "sees" your specialisation will now + * support your conversion. In particular, you'll be able to read result + * fields into a variable of the new type. + * + * There is a macro to help you define conversions for individual enumeration + * types. The conversion will represent enumeration values as numeric strings. + */ +//@{ + +/// Traits class for use in string conversions +/** Specialize this template for a type that you wish to add to_string and + * from_string support for. + */ +template<typename T, typename = void> struct string_traits; + +namespace internal +{ +/// Throw exception for attempt to convert null to given type. +[[noreturn]] PQXX_LIBEXPORT void throw_null_conversion( + const std::string &type); + +/// Give a human-readable name for a type, at compile time. +/** Each instantiation contains a static member called @c value which is the + * type's name, as a string. + * + * This template should not be around for long. C++14's variable templates + * make it easier (eliminating the cumbersome struct) and C++20's introspection + * should obviate it completely. + */ +template<typename TYPE> struct type_name; +#define PQXX_DECLARE_TYPE_NAME(TYPE) \ + template<> struct type_name<TYPE> \ + { static constexpr const char *value = #TYPE; } + +PQXX_DECLARE_TYPE_NAME(bool); +PQXX_DECLARE_TYPE_NAME(short); +PQXX_DECLARE_TYPE_NAME(unsigned short); +PQXX_DECLARE_TYPE_NAME(int); +PQXX_DECLARE_TYPE_NAME(unsigned int); +PQXX_DECLARE_TYPE_NAME(long); +PQXX_DECLARE_TYPE_NAME(unsigned long); +PQXX_DECLARE_TYPE_NAME(long long); +PQXX_DECLARE_TYPE_NAME(unsigned long long); +PQXX_DECLARE_TYPE_NAME(float); +PQXX_DECLARE_TYPE_NAME(double); +PQXX_DECLARE_TYPE_NAME(long double); +PQXX_DECLARE_TYPE_NAME(char *); +PQXX_DECLARE_TYPE_NAME(const char *); +PQXX_DECLARE_TYPE_NAME(std::string); +PQXX_DECLARE_TYPE_NAME(const std::string); +PQXX_DECLARE_TYPE_NAME(std::stringstream); +#undef PQXX_DECLARE_TYPE_NAME + +template<size_t N> struct type_name<char[N]> +{ static constexpr const char *value = "char[]"; }; + + +/// Helper: string traits implementation for built-in types. +/** These types all look much alike, so they can share much of their traits + * classes (though templatised, of course). + * + * The actual `to_string` and `from_string` are implemented in the library, + * but the rest is defined inline. + */ +template<typename TYPE> struct PQXX_LIBEXPORT builtin_traits +{ + static constexpr const char *name() noexcept + { return internal::type_name<TYPE>::value; } + static constexpr bool has_null() noexcept { return false; } + static bool is_null(TYPE) { return false; } + [[noreturn]] static TYPE null() { throw_null_conversion(name()); } + static void from_string(const char Str[], TYPE &Obj); + static std::string to_string(TYPE Obj); +}; +} // namespace pqxx::internal + + +/// Helper: declare a string_traits specialisation for a builtin type. +#define PQXX_DECLARE_STRING_TRAITS_SPECIALIZATION(TYPE) \ + template<> struct PQXX_LIBEXPORT string_traits<TYPE> : \ + internal::builtin_traits<TYPE> {}; + +PQXX_DECLARE_STRING_TRAITS_SPECIALIZATION(bool) + +PQXX_DECLARE_STRING_TRAITS_SPECIALIZATION(short) +PQXX_DECLARE_STRING_TRAITS_SPECIALIZATION(unsigned short) +PQXX_DECLARE_STRING_TRAITS_SPECIALIZATION(int) +PQXX_DECLARE_STRING_TRAITS_SPECIALIZATION(unsigned int) +PQXX_DECLARE_STRING_TRAITS_SPECIALIZATION(long) +PQXX_DECLARE_STRING_TRAITS_SPECIALIZATION(unsigned long) +PQXX_DECLARE_STRING_TRAITS_SPECIALIZATION(long long) +PQXX_DECLARE_STRING_TRAITS_SPECIALIZATION(unsigned long long) + +PQXX_DECLARE_STRING_TRAITS_SPECIALIZATION(float) +PQXX_DECLARE_STRING_TRAITS_SPECIALIZATION(double) +PQXX_DECLARE_STRING_TRAITS_SPECIALIZATION(long double) + +#undef PQXX_DECLARE_STRING_TRAITS_SPECIALIZATION + + +/// Helper class for defining enum conversions. +/** The conversion will convert enum values to numeric strings, and vice versa. + * + * To define a string conversion for an enum type, derive a @c string_traits + * specialisation for the enum from this struct. + * + * There's usually an easier way though: the @c PQXX_DECLARE_ENUM_CONVERSION + * macro. Use @c enum_traits manually only if you need to customise your + * traits type in more detail, e.g. if your enum has a "null" value built in. + */ +template<typename ENUM> +struct enum_traits +{ + using underlying_type = typename std::underlying_type<ENUM>::type; + using underlying_traits = string_traits<underlying_type>; + + static constexpr bool has_null() noexcept { return false; } + [[noreturn]] static ENUM null() + { internal::throw_null_conversion("enum type"); } + + static void from_string(const char Str[], ENUM &Obj) + { + underlying_type tmp; + underlying_traits::from_string(Str, tmp); + Obj = ENUM(tmp); + } + + static std::string to_string(ENUM Obj) + { return underlying_traits::to_string(underlying_type(Obj)); } +}; + + +/// Macro: Define a string conversion for an enum type. +/** This specialises the @c pqxx::string_traits template, so use it in the + * @c ::pqxx namespace. + * + * For example: + * + * #include <iostream> + * #include <pqxx/strconv> + * enum X { xa, xb }; + * namespace pqxx { PQXX_DECLARE_ENUM_CONVERSION(x); } + * int main() { std::cout << to_string(xa) << std::endl; } + */ +#define PQXX_DECLARE_ENUM_CONVERSION(ENUM) \ +template<> \ +struct string_traits<ENUM> : pqxx::enum_traits<ENUM> \ +{ \ + static constexpr const char *name() noexcept { return #ENUM; } \ + [[noreturn]] static ENUM null() \ + { internal::throw_null_conversion(name()); } \ +} + + +/// String traits for C-style string ("pointer to const char") +template<> struct PQXX_LIBEXPORT string_traits<const char *> +{ + static constexpr const char *name() noexcept { return "const char *"; } + static constexpr bool has_null() noexcept { return true; } + static bool is_null(const char *t) { return t == nullptr; } + static const char *null() { return nullptr; } + static void from_string(const char Str[], const char *&Obj) { Obj = Str; } + static std::string to_string(const char *Obj) { return Obj; } +}; + +/// String traits for non-const C-style string ("pointer to char") +template<> struct PQXX_LIBEXPORT string_traits<char *> +{ + static constexpr const char *name() noexcept { return "char *"; } + static constexpr bool has_null() noexcept { return true; } + static bool is_null(const char *t) { return t == nullptr; } + static const char *null() { return nullptr; } + + // Don't allow this conversion since it breaks const-safety. + // static void from_string(const char Str[], char *&Obj); + + static std::string to_string(char *Obj) { return Obj; } +}; + +/// String traits for C-style string constant ("array of char") +template<size_t N> struct PQXX_LIBEXPORT string_traits<char[N]> +{ + static constexpr const char *name() noexcept { return "char[]"; } + static constexpr bool has_null() noexcept { return true; } + static bool is_null(const char t[]) { return t == nullptr; } + static const char *null() { return nullptr; } + static std::string to_string(const char Obj[]) { return Obj; } +}; + +template<> struct PQXX_LIBEXPORT string_traits<std::string> +{ + static constexpr const char *name() noexcept { return "string"; } + static constexpr bool has_null() noexcept { return false; } + static bool is_null(const std::string &) { return false; } + [[noreturn]] static std::string null() + { internal::throw_null_conversion(name()); } + static void from_string(const char Str[], std::string &Obj) { Obj=Str; } + static std::string to_string(const std::string &Obj) { return Obj; } +}; + +template<> struct PQXX_LIBEXPORT string_traits<const std::string> +{ + static constexpr const char *name() noexcept { return "const string"; } + static constexpr bool has_null() noexcept { return false; } + static bool is_null(const std::string &) { return false; } + [[noreturn]] static const std::string null() + { internal::throw_null_conversion(name()); } + static const std::string to_string(const std::string &Obj) { return Obj; } +}; + +template<> struct PQXX_LIBEXPORT string_traits<std::stringstream> +{ + static constexpr const char *name() noexcept { return "stringstream"; } + static constexpr bool has_null() noexcept { return false; } + static bool is_null(const std::stringstream &) { return false; } + [[noreturn]] static std::stringstream null() + { internal::throw_null_conversion(name()); } + static void from_string(const char Str[], std::stringstream &Obj) + { Obj.clear(); Obj << Str; } + static std::string to_string(const std::stringstream &Obj) + { return Obj.str(); } +}; + + +// TODO: Implement date conversions. + +/// Attempt to convert postgres-generated string to given built-in type +/** If the form of the value found in the string does not match the expected + * type, e.g. if a decimal point is found when converting to an integer type, + * the conversion fails. Overflows (e.g. converting "9999999999" to a 16-bit + * C++ type) are also treated as errors. If in some cases this behaviour should + * be inappropriate, convert to something bigger such as @c long @c int first + * and then truncate the resulting value. + * + * Only the simplest possible conversions are supported. No fancy features + * such as hexadecimal or octal, spurious signs, or exponent notation will work. + * No whitespace is stripped away. Only the kinds of strings that come out of + * PostgreSQL and out of to_string() can be converted. + */ +template<typename T> + inline void from_string(const char Str[], T &Obj) +{ + if (Str == nullptr) throw std::runtime_error{"Attempt to read null string."}; + string_traits<T>::from_string(Str, Obj); +} + + +/// Conversion with known string length (for strings that may contain nuls) +/** This is only used for strings, where embedded nul bytes should not determine + * the end of the string. + * + * For all other types, this just uses the regular, nul-terminated version of + * from_string(). + */ +template<typename T> inline void from_string(const char Str[], T &Obj, size_t) +{ + return from_string(Str, Obj); +} + +template<> + inline void from_string<std::string>( //[t00] + const char Str[], + std::string &Obj, + size_t len) +{ + if (Str == nullptr) throw std::runtime_error{"Attempt to read null string."}; + Obj.assign(Str, len); +} + +template<typename T> + inline void from_string(const std::string &Str, T &Obj) //[t45] + { from_string(Str.c_str(), Obj); } + +template<typename T> + inline void from_string(const std::stringstream &Str, T &Obj) //[t00] + { from_string(Str.str(), Obj); } + +template<> inline void +from_string(const std::string &Str, std::string &Obj) //[t46] + { Obj = Str; } + + +namespace internal +{ +/// Compute numeric value of given textual digit (assuming that it is a digit) +constexpr int digit_to_number(char c) noexcept { return c-'0'; } +constexpr char number_to_digit(int i) noexcept + { return static_cast<char>(i+'0'); } +} // namespace pqxx::internal + + +/// Convert built-in type to a readable string that PostgreSQL will understand +/** No special formatting is done, and any locale settings are ignored. The + * resulting string will be human-readable and in a format suitable for use in + * SQL queries. + */ +template<typename T> inline std::string to_string(const T &Obj) + { return string_traits<T>::to_string(Obj); } + +//@} + +} // namespace pqxx + +#endif diff --git a/contrib/libs/libpqxx/include/pqxx/stream_base.hxx b/contrib/libs/libpqxx/include/pqxx/stream_base.hxx new file mode 100644 index 0000000000..d4af37fb07 --- /dev/null +++ b/contrib/libs/libpqxx/include/pqxx/stream_base.hxx @@ -0,0 +1,62 @@ +/** Definition of the pqxx::stream_base class. + * + * pqxx::stream_base provides optimized batch access to a database table. + * + * DO NOT INCLUDE THIS FILE DIRECTLY; include pqxx/stream_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_STREAM_BASE +#define PQXX_H_STREAM_BASE + +#include "pqxx/compiler-public.hxx" +#include "pqxx/compiler-internal-pre.hxx" +#include "pqxx/transaction_base.hxx" +#include "pqxx/util.hxx" + +#include <string> + + +namespace pqxx +{ + +class PQXX_LIBEXPORT PQXX_NOVTABLE stream_base : + public internal::transactionfocus +{ +public: + explicit stream_base(transaction_base &); + // TODO: Can we get rid of the vtable? + virtual ~stream_base() noexcept =default; + virtual void complete() = 0; + operator bool() const noexcept; + bool operator!() const noexcept; +protected: + bool m_finished; + virtual void close(); + template<typename C> static std::string columnlist(const C &); + template<typename I> static std::string columnlist(I begin, I end); +private: + stream_base(); + stream_base(const stream_base&); + stream_base & operator=(const stream_base &); +}; + +template<typename C> std::string stream_base::columnlist(const C &c) +{ + return columnlist(std::begin(c), std::end(c)); +} + +template<typename I> std::string stream_base::columnlist(I begin, I end) +{ + return separated_list(",", begin, end); +} + +} // namespace pqxx + + +#include "pqxx/compiler-internal-post.hxx" +#endif diff --git a/contrib/libs/libpqxx/include/pqxx/stream_from b/contrib/libs/libpqxx/include/pqxx/stream_from new file mode 100644 index 0000000000..71dbb7dfe7 --- /dev/null +++ b/contrib/libs/libpqxx/include/pqxx/stream_from @@ -0,0 +1,6 @@ +/** pqxx::stream_from class. + * + * pqxx::stream_from enables optimized batch reads from a database table. + */ +// Actual definitions in .hxx file so editors and such recognize file type. +#include "pqxx/stream_from.hxx" diff --git a/contrib/libs/libpqxx/include/pqxx/stream_from.hxx b/contrib/libs/libpqxx/include/pqxx/stream_from.hxx new file mode 100644 index 0000000000..bc6bcc7231 --- /dev/null +++ b/contrib/libs/libpqxx/include/pqxx/stream_from.hxx @@ -0,0 +1,210 @@ +/** Definition of the pqxx::stream_from class. + * + * pqxx::stream_from enables optimized batch reads from a database table. + * + * DO NOT INCLUDE THIS FILE DIRECTLY; include pqxx/stream_from 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_STREAM_FROM +#define PQXX_H_STREAM_FROM + +#include "pqxx/compiler-public.hxx" +#include "pqxx/compiler-internal-pre.hxx" +#include "pqxx/transaction_base.hxx" +#include "pqxx/stream_base.hxx" +#include "pqxx/internal/type_utils.hxx" + +#include <string> + + +namespace pqxx +{ + +/// Efficiently pull data directly out of a table. +class PQXX_LIBEXPORT stream_from : public stream_base +{ +public: + stream_from( + transaction_base &, + const std::string &table_name + ); + template<typename Columns> stream_from( + transaction_base &, + const std::string &table_name, + const Columns& columns + ); + template<typename Iter> stream_from( + transaction_base &, + const std::string &table_name, + Iter columns_begin, + Iter columns_end + ); + + ~stream_from() noexcept; + + void complete() override; + + bool get_raw_line(std::string &); + template<typename Tuple> stream_from & operator>>(Tuple &); + +private: + internal::encoding_group m_copy_encoding; + std::string m_current_line; + bool m_retry_line; + + void set_up(transaction_base &, const std::string &table_name); + void set_up( + transaction_base &, + const std::string &table_name, + const std::string &columns + ); + + void close() override; + + bool extract_field( + const std::string &, + std::string::size_type &, + std::string & + ) const; + + template<typename Tuple, std::size_t I> auto tokenize_ith( + const std::string &, + Tuple &, + std::string::size_type, + std::string & + ) const -> typename std::enable_if<( + std::tuple_size<Tuple>::value > I + )>::type; + template<typename Tuple, std::size_t I> auto tokenize_ith( + const std::string &, + Tuple &, + std::string::size_type, + std::string & + ) const -> typename std::enable_if<( + std::tuple_size<Tuple>::value <= I + )>::type; + + template<typename T> void extract_value( + const std::string &line, + T& t, + std::string::size_type &here, + std::string &workspace + ) const; +}; + + +template<typename Columns> stream_from::stream_from( + transaction_base &tb, + const std::string &table_name, + const Columns& columns +) : stream_from{ + tb, + table_name, + std::begin(columns), + std::end(columns) +} {} + + +template<typename Iter> stream_from::stream_from( + transaction_base &tb, + const std::string &table_name, + Iter columns_begin, + Iter columns_end +) : + namedclass{"stream_from", table_name}, + stream_base{tb} +{ + set_up( + tb, + table_name, + columnlist(columns_begin, columns_end) + ); +} + + +template<typename Tuple> stream_from & stream_from::operator>>( + Tuple &t +) +{ + if (m_retry_line or get_raw_line(m_current_line)) + { + std::string workspace; + try + { + tokenize_ith<Tuple, 0>(m_current_line, t, 0, workspace); + m_retry_line = false; + } + catch (...) + { + m_retry_line = true; + throw; + } + } + return *this; +} + + +template<typename Tuple, std::size_t I> auto stream_from::tokenize_ith( + const std::string &line, + Tuple &t, + std::string::size_type here, + std::string &workspace +) const -> typename std::enable_if<( + std::tuple_size<Tuple>::value > I +)>::type +{ + if (here >= line.size()) + throw usage_error{"Too few fields to extract from stream_from line."}; + + extract_value(line, std::get<I>(t), here, workspace); + tokenize_ith<Tuple, I+1>(line, t, here, workspace); +} + + +template<typename Tuple, std::size_t I> auto stream_from::tokenize_ith( + const std::string &line, + Tuple & /* t */, + std::string::size_type here, + std::string & /* workspace */ +) const -> typename std::enable_if<( + std::tuple_size<Tuple>::value <= I +)>::type +{ + // Zero-column line may still have a trailing newline + if ( + here < line.size() and + not (here == line.size() - 1 and line[here] == '\n')) + throw usage_error{"Not all fields extracted from stream_from line"}; +} + + +template<typename T> void stream_from::extract_value( + const std::string &line, + T& t, + std::string::size_type &here, + std::string &workspace +) const +{ + if (extract_field(line, here, workspace)) + from_string<T>(workspace, t); + else + t = internal::null_value<T>(); +} + +template<> void stream_from::extract_value<std::nullptr_t>( + const std::string &line, + std::nullptr_t&, + std::string::size_type &here, + std::string &workspace +) const; + +} // namespace pqxx + + +#include "pqxx/compiler-internal-post.hxx" +#endif diff --git a/contrib/libs/libpqxx/include/pqxx/stream_to b/contrib/libs/libpqxx/include/pqxx/stream_to new file mode 100644 index 0000000000..a5100969d0 --- /dev/null +++ b/contrib/libs/libpqxx/include/pqxx/stream_to @@ -0,0 +1,6 @@ +/** pqxx::stream_to class. + * + * pqxx::stream_to enables optimized batch updates to a database table. + */ +// Actual definitions in .hxx file so editors and such recognize file type. +#include "pqxx/stream_to.hxx" diff --git a/contrib/libs/libpqxx/include/pqxx/stream_to.hxx b/contrib/libs/libpqxx/include/pqxx/stream_to.hxx new file mode 100644 index 0000000000..cf23f980f5 --- /dev/null +++ b/contrib/libs/libpqxx/include/pqxx/stream_to.hxx @@ -0,0 +1,192 @@ +/** Definition of the pqxx::stream_to class. + * + * pqxx::stream_to enables optimized batch updates to a database table. + * + * DO NOT INCLUDE THIS FILE DIRECTLY; include pqxx/stream_to.hxx 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_STREAM_TO +#define PQXX_H_STREAM_TO + +#include "pqxx/compiler-public.hxx" +#include "pqxx/compiler-internal-pre.hxx" +#include "pqxx/transaction_base.hxx" +#include "pqxx/stream_base.hxx" +#include "pqxx/stream_from.hxx" +#include "pqxx/internal/type_utils.hxx" + +#include <string> + + +namespace pqxx +{ + +/// Efficiently write data directly to a database table. +/** If you wish to insert rows of data into a table, you can compose INSERT + * statements and execute them. But it's slow and tedious, and you need to + * worry about quoting and escaping the data. + * + * If you're just inserting a single row, it probably won't matter much. You + * can use prepared or parameterised statements to take care of the escaping + * for you. But if you're inserting large numbers of rows you will want + * something better. + * + * Inserting rows one by one tends to take a lot of time, especially when you + * are working with a remote database server over the network. Every single + * row involves sending the data over the network, and waiting for a reply. + * Do it "in bulk" using @c stream_to, and you may find that it goes many times + * faster, sometimes even by orders of magnitude. + * + * Here's how it works: you create a @c stream_to stream to start writing to + * your table. You will probably want to specify the columns. Then, you + * feed your data into the stream one row at a time. And finally, you call the + * stream's @c complete() to tell it to finalise the operation, wait for + * completion, and check for errors. + * + * You insert data using the @c << ("shift-left") operator. Each row must be + * something that can be iterated in order to get its constituent fields: a + * @c std::tuple, a @c std::vector, or anything else with a @c begin and + * @c end. It could be a class of your own. Of course the fields have to + * match the columns you specified when creating the stream. + * + * There is also a matching stream_from for reading data in bulk. + */ +class PQXX_LIBEXPORT stream_to : public stream_base +{ +public: + /// Create a stream, without specifying columns. + /** Fields will be inserted in whatever order the columns have in the + * database. + * + * You'll probably want to specify the columns, so that the mapping between + * your data fields and the table is explicit in your code, and not hidden + * in an "implicit contract" between your code and your schema. + */ + stream_to(transaction_base &, const std::string &table_name); + + /// Create a stream, specifying column names as a container of strings. + template<typename Columns> stream_to( + transaction_base &, + const std::string &table_name, + const Columns& columns + ); + + /// Create a stream, specifying column names as a sequence of strings. + template<typename Iter> stream_to( + transaction_base &, + const std::string &table_name, + Iter columns_begin, + Iter columns_end + ); + + ~stream_to() noexcept; + + /// Complete the operation, and check for errors. + /** Always call this to close the stream in an orderly fashion, even after + * an error. (In the case of an error, abort the transaction afterwards.) + * + * The only circumstance where it's safe to skip this is after an error, if + * you're discarding the entire connection right away. + */ + void complete() override; + + /// Insert a row of data. + /** The data can be any type that can be iterated. Each iterated item + * becomes a field in the row, in the same order as the columns you + * specified when creating the stream. + * + * Each field will be converted into the database's format using + * @c pqxx::to_string. + */ + template<typename Tuple> stream_to & operator<<(const Tuple &); + + /// Stream a `stream_from` straight into a `stream_to`. + /** This can be useful when copying between different databases. If the + * source and the destination are on the same database, you'll get better + * performance doing it all in a regular query. + */ + stream_to &operator<<(stream_from &); + +private: + /// Write a row of data, as a line of text. + void write_raw_line(const std::string &); + + void set_up(transaction_base &, const std::string &table_name); + void set_up( + transaction_base &, + const std::string &table_name, + const std::string &columns + ); + + void close() override; +}; + + +template<typename Columns> inline stream_to::stream_to( + transaction_base &tb, + const std::string &table_name, + const Columns& columns +) : stream_to{ + tb, + table_name, + std::begin(columns), + std::end(columns) +} +{} + + +template<typename Iter> inline stream_to::stream_to( + transaction_base &tb, + const std::string &table_name, + Iter columns_begin, + Iter columns_end +) : + namedclass{"stream_from", table_name}, + stream_base{tb} +{ + set_up( + tb, + table_name, + columnlist(columns_begin, columns_end) + ); +} + + +namespace internal +{ + +class PQXX_LIBEXPORT TypedCopyEscaper +{ + static std::string escape(const std::string &); +public: + template<typename T> std::string operator()(const T* t) const + { + return string_traits<T>::is_null(*t) ? "\\N" : escape(to_string(*t)); + } +}; + +// Explicit specialization so we don't need a string_traits<> for nullptr_t +template<> inline std::string TypedCopyEscaper::operator()<std::nullptr_t>( + const std::nullptr_t* +) const +{ return "\\N"; } + +} // namespace pqxx::internal + + +template<typename Tuple> stream_to & stream_to::operator<<(const Tuple &t) +{ + write_raw_line(separated_list("\t", t, internal::TypedCopyEscaper())); + return *this; +} + +} // namespace pqxx + + +#include "pqxx/compiler-internal-post.hxx" +#endif diff --git a/contrib/libs/libpqxx/include/pqxx/subtransaction b/contrib/libs/libpqxx/include/pqxx/subtransaction new file mode 100644 index 0000000000..364ccab3fc --- /dev/null +++ b/contrib/libs/libpqxx/include/pqxx/subtransaction @@ -0,0 +1,6 @@ +/** pqxx::subtransaction class. + * + * pqxx::subtransaction is a nested transaction, i.e. one inside a transaction. + */ +// Actual definitions in .hxx file so editors and such recognize file type. +#include "pqxx/subtransaction.hxx" diff --git a/contrib/libs/libpqxx/include/pqxx/subtransaction.hxx b/contrib/libs/libpqxx/include/pqxx/subtransaction.hxx new file mode 100644 index 0000000000..2b353e63db --- /dev/null +++ b/contrib/libs/libpqxx/include/pqxx/subtransaction.hxx @@ -0,0 +1,105 @@ +/** Definition of the pqxx::subtransaction class. + * + * pqxx::subtransaction is a nested transaction, i.e. one within a transaction. + * + * DO NOT INCLUDE THIS FILE DIRECTLY; include pqxx/subtransaction 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_SUBTRANSACTION +#define PQXX_H_SUBTRANSACTION + +#include "pqxx/compiler-public.hxx" +#include "pqxx/compiler-internal-pre.hxx" + +#include "pqxx/dbtransaction.hxx" + + +/* Methods tested in eg. self-test program test1 are marked with "//[t01]" + */ + + +namespace pqxx +{ + +/** + * @ingroup transaction + */ +/// "Transaction" nested within another transaction +/** A subtransaction can be executed inside a backend transaction, or inside + * another subtransaction. This can be useful when, for example, statements in + * a transaction may harmlessly fail and you don't want them to abort the entire + * transaction. Here's an example of how a temporary table may be dropped + * before re-creating it, without failing if the table did not exist: + * + * @code + * void do_job(connection_base &C) + * { + * const string temptable = "fleetingtable"; + * + * // Since we're dealing with a temporary table here, disallow automatic + * // recovery of the connection in case it breaks. + * C.inhibit_reactivation(true); + * + * work W(C, "do_job"); + * do_firstpart(W); + * + * // Attempt to delete our temporary table if it already existed + * try + * { + * subtransaction S(W, "droptemp"); + * S.exec0("DROP TABLE " + temptable); + * S.commit(); + * } + * catch (const undefined_table &) + * { + * // Table did not exist. Which is what we were hoping to achieve anyway. + * // Carry on without regrets. + * } + * + * // S may have gone into a failed state and been destroyed, but the + * // upper-level transaction W is still fine. We can continue to use it. + * W.exec("CREATE TEMP TABLE " + temptable + "(bar integer, splat varchar)"); + * + * do_lastpart(W); + * } + * @endcode + * + * (This is just an example. If you really wanted to do drop a table without an + * error if it doesn't exist, you'd use DROP TABLE IF EXISTS.) + * + * There are no isolation levels inside a transaction. They are not needed + * because all actions within the same backend transaction are always performed + * sequentially anyway. + */ +class PQXX_LIBEXPORT subtransaction : + public internal::transactionfocus, + public dbtransaction +{ +public: + /// Nest a subtransaction nested in another transaction. + explicit subtransaction( //[t88] + dbtransaction &T, const std::string &Name=std::string{}); + + /// Nest a subtransaction in another subtransaction. + explicit subtransaction( + subtransaction &T, const std::string &Name=std::string{}); + + virtual ~subtransaction() noexcept + { End(); } + +private: + virtual void do_begin() override; //[t88] + virtual void do_commit() override; //[t88] + virtual void do_abort() override; //[t88] + + dbtransaction &m_parent; +}; +} + +#include "pqxx/compiler-internal-post.hxx" +#endif diff --git a/contrib/libs/libpqxx/include/pqxx/tablereader b/contrib/libs/libpqxx/include/pqxx/tablereader new file mode 100644 index 0000000000..daa5ec93e8 --- /dev/null +++ b/contrib/libs/libpqxx/include/pqxx/tablereader @@ -0,0 +1,6 @@ +/** pqxx::tablereader class. + * + * pqxx::tablereader enables optimized batch reads from a database table. + */ +// Actual definitions in .hxx file so editors and such recognize file type. +#include "pqxx/tablereader.hxx" diff --git a/contrib/libs/libpqxx/include/pqxx/tablereader.hxx b/contrib/libs/libpqxx/include/pqxx/tablereader.hxx new file mode 100644 index 0000000000..f5300cbeb0 --- /dev/null +++ b/contrib/libs/libpqxx/include/pqxx/tablereader.hxx @@ -0,0 +1,118 @@ +/** Definition of the pqxx::tablereader class. + * + * pqxx::tablereader enables optimized batch reads from a database table. + * + * DO NOT INCLUDE THIS FILE DIRECTLY; include pqxx/tablereader 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_TABLEREADER +#define PQXX_H_TABLEREADER + +#include "pqxx/compiler-public.hxx" +#include "pqxx/compiler-internal-pre.hxx" +#include "pqxx/result.hxx" +#include "pqxx/tablestream.hxx" + + +namespace pqxx +{ +/// @deprecated Use stream_from instead. +/** Efficiently pull data directly out of a table. + * @warning This class does not work reliably with multibyte encodings. Using + * it with some multi-byte encodings may pose a security risk. + */ +class PQXX_LIBEXPORT tablereader : public tablestream +{ +public: + PQXX_DEPRECATED tablereader( + transaction_base &, + const std::string &Name, + const std::string &Null=std::string{}); + template<typename ITER> + PQXX_DEPRECATED tablereader( + transaction_base &, + const std::string &Name, + ITER begincolumns, + ITER endcolumns); + template<typename ITER> + PQXX_DEPRECATED tablereader( + transaction_base &, + const std::string &Name, + ITER begincolumns, + ITER endcolumns, + const std::string &Null); + ~tablereader() noexcept; + template<typename TUPLE> tablereader &operator>>(TUPLE &); + operator bool() const noexcept { return not m_done; } + bool operator!() const noexcept { return m_done; } + bool get_raw_line(std::string &Line); + template<typename TUPLE> + void tokenize(std::string, TUPLE &) const; + virtual void complete() override; +private: + void set_up( + transaction_base &T, + const std::string &RName, + const std::string &Columns=std::string{}); + PQXX_PRIVATE void reader_close(); + std::string extract_field( + const std::string &, + std::string::size_type &) const; + bool m_done; +}; + + +template<typename ITER> inline +tablereader::tablereader( + transaction_base &T, + const std::string &Name, + ITER begincolumns, + ITER endcolumns) : + namedclass{Name, "tablereader"}, + tablestream{T, std::string{}}, + m_done{true} +{ + set_up(T, Name, columnlist(begincolumns, endcolumns)); +} + + +template<typename ITER> inline +tablereader::tablereader( + transaction_base &T, + const std::string &Name, + ITER begincolumns, + ITER endcolumns, + const std::string &Null) : + namedclass{Name, "tablereader"}, + tablestream{T, Null}, + m_done{true} +{ + set_up(T, Name, columnlist(begincolumns, endcolumns)); +} + + +template<typename TUPLE> +inline void tablereader::tokenize(std::string Line, TUPLE &T) const +{ + std::back_insert_iterator<TUPLE> ins = std::back_inserter(T); + std::string::size_type here = 0; + while (here < Line.size()) *ins++ = extract_field(Line, here); +} + + +template<typename TUPLE> +inline tablereader &pqxx::tablereader::operator>>(TUPLE &T) +{ + std::string Line; + if (get_raw_line(Line)) tokenize(Line, T); + return *this; +} +} // namespace pqxx + +#include "pqxx/compiler-internal-post.hxx" +#endif diff --git a/contrib/libs/libpqxx/include/pqxx/tablestream b/contrib/libs/libpqxx/include/pqxx/tablestream new file mode 100644 index 0000000000..57d700e800 --- /dev/null +++ b/contrib/libs/libpqxx/include/pqxx/tablestream @@ -0,0 +1,6 @@ +/** pqxx::tablestream class. + * + * pqxx::tablestream provides optimized batch access to a database table. + */ +// Actual definitions in .hxx file so editors and such recognize file type. +#include "pqxx/tablestream.hxx" diff --git a/contrib/libs/libpqxx/include/pqxx/tablestream.hxx b/contrib/libs/libpqxx/include/pqxx/tablestream.hxx new file mode 100644 index 0000000000..1803604bec --- /dev/null +++ b/contrib/libs/libpqxx/include/pqxx/tablestream.hxx @@ -0,0 +1,59 @@ +/** Definition of the pqxx::tablestream class. + * + * pqxx::tablestream provides optimized batch access to a database table. + * + * DO NOT INCLUDE THIS FILE DIRECTLY; include pqxx/tablestream 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_TABLESTREAM +#define PQXX_H_TABLESTREAM + +#include "pqxx/compiler-public.hxx" +#include "pqxx/compiler-internal-pre.hxx" +#include "pqxx/transaction_base.hxx" + + +namespace pqxx +{ +/// Base class for obsolete tablereader/tablewriter classes. +/** @deprecated Use stream_from and stream_to instead. + */ +class PQXX_LIBEXPORT PQXX_NOVTABLE tablestream : + public internal::transactionfocus +{ +public: + explicit tablestream( + transaction_base &Trans, + const std::string &Null=std::string{}); + virtual ~tablestream() noexcept =0; + virtual void complete() =0; +protected: + const std::string &NullStr() const { return m_null; } + bool is_finished() const noexcept { return m_finished; } + void base_close(); + template<typename ITER> + static std::string columnlist(ITER colbegin, ITER colend); +private: + std::string m_null; + bool m_finished = false; + + tablestream() =delete; + tablestream(const tablestream &) =delete; + tablestream &operator=(const tablestream &) =delete; +}; + + +template<typename ITER> inline +std::string tablestream::columnlist(ITER colbegin, ITER colend) +{ + return separated_list(",", colbegin, colend); +} +} // namespace pqxx + +#include "pqxx/compiler-internal-post.hxx" +#endif diff --git a/contrib/libs/libpqxx/include/pqxx/tablewriter b/contrib/libs/libpqxx/include/pqxx/tablewriter new file mode 100644 index 0000000000..80bdf59b2b --- /dev/null +++ b/contrib/libs/libpqxx/include/pqxx/tablewriter @@ -0,0 +1,6 @@ +/** pqxx::tablewriter class. + * + * pqxx::tablewriter enables optimized batch updates to a database table. + */ +// Actual definitions in .hxx file so editors and such recognize file type. +#include "pqxx/tablewriter.hxx" diff --git a/contrib/libs/libpqxx/include/pqxx/tablewriter.hxx b/contrib/libs/libpqxx/include/pqxx/tablewriter.hxx new file mode 100644 index 0000000000..32e7a98b7c --- /dev/null +++ b/contrib/libs/libpqxx/include/pqxx/tablewriter.hxx @@ -0,0 +1,209 @@ +/** Definition of the pqxx::tablewriter class. + * + * pqxx::tablewriter enables optimized batch updates to a database table. + * + * DO NOT INCLUDE THIS FILE DIRECTLY; include pqxx/tablewriter.hxx 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_TABLEWRITER +#define PQXX_H_TABLEWRITER + +#include <iterator> + +#include "pqxx/compiler-public.hxx" +#include "pqxx/compiler-internal-pre.hxx" + +#include "pqxx/tablestream.hxx" + + +namespace pqxx +{ +/// @deprecated Use stream_to instead. +/** Efficiently write data directly to a database table. + * @warning This class does not work reliably with multibyte encodings. Using + * it with some multi-byte encodings may pose a security risk. + */ +class PQXX_LIBEXPORT tablewriter : public tablestream +{ +public: + PQXX_DEPRECATED tablewriter( + transaction_base &, + const std::string &WName, + const std::string &Null=std::string{}); + template<typename ITER> + PQXX_DEPRECATED tablewriter( + transaction_base &, + const std::string &WName, + ITER begincolumns, + ITER endcolumns); + template<typename ITER> + PQXX_DEPRECATED tablewriter( + transaction_base &T, + const std::string &WName, + ITER begincolumns, + ITER endcolumns, + const std::string &Null); + ~tablewriter() noexcept; + template<typename IT> void insert(IT Begin, IT End); + template<typename TUPLE> void insert(const TUPLE &); + template<typename IT> void push_back(IT Begin, IT End); + template<typename TUPLE> void push_back(const TUPLE &); + template<typename SIZE> void reserve(SIZE) {} + template<typename TUPLE> tablewriter &operator<<(const TUPLE &); + tablewriter &operator<<(tablereader &); + template<typename IT> std::string generate(IT Begin, IT End) const; + template<typename TUPLE> std::string generate(const TUPLE &) const; + virtual void complete() override; + void write_raw_line(const std::string &); +private: + void set_up( + transaction_base &, + const std::string &WName, + const std::string &Columns = std::string{}); + PQXX_PRIVATE void writer_close(); +}; +} // namespace pqxx + + +namespace std +{ +template<> + class back_insert_iterator<pqxx::tablewriter> +{ +public: + using iterator_category = output_iterator_tag; + + explicit back_insert_iterator(pqxx::tablewriter &W) noexcept : + m_writer{&W} {} + + back_insert_iterator & + operator=(const back_insert_iterator &rhs) noexcept + { + m_writer = rhs.m_writer; + return *this; + } + + template<typename TUPLE> + back_insert_iterator &operator=(const TUPLE &T) + { + m_writer->insert(T); + return *this; + } + + back_insert_iterator &operator++() { return *this; } + back_insert_iterator &operator++(int) { return *this; } + back_insert_iterator &operator*() { return *this; } + +private: + pqxx::tablewriter *m_writer; +}; +} // namespace std + + +namespace pqxx +{ +template<typename ITER> inline tablewriter::tablewriter( + transaction_base &T, + const std::string &WName, + ITER begincolumns, + ITER endcolumns) : + namedclass{"tablewriter", WName}, + tablestream{T, std::string{}} +{ + set_up(T, WName, columnlist(begincolumns, endcolumns)); +} + + +template<typename ITER> inline tablewriter::tablewriter( + transaction_base &T, + const std::string &WName, + ITER begincolumns, + ITER endcolumns, + const std::string &Null) : + namedclass{"tablewriter", WName}, + tablestream{T, Null} +{ + set_up(T, WName, columnlist(begincolumns, endcolumns)); +} + + +namespace internal +{ +PQXX_LIBEXPORT std::string escape( + const std::string &s, + const std::string &null); + +inline std::string escape_any( + const std::string &s, + const std::string &null) +{ return escape(s, null); } + +inline std::string escape_any( + const char s[], + const std::string &null) +{ return s ? escape(std::string{s}, null) : "\\N"; } + +template<typename T> inline std::string escape_any( + const T &t, + const std::string &null) +{ return escape(to_string(t), null); } + + +template<typename IT> class Escaper +{ + const std::string &m_null; +public: + explicit Escaper(const std::string &null) : m_null{null} {} + std::string operator()(IT i) const { return escape_any(*i, m_null); } +}; +} + + +template<typename IT> +inline std::string tablewriter::generate(IT Begin, IT End) const +{ + return separated_list("\t", Begin, End, internal::Escaper<IT>{NullStr()}); +} +template<typename TUPLE> +inline std::string tablewriter::generate(const TUPLE &T) const +{ + return generate(std::begin(T), std::end(T)); +} + +template<typename IT> inline void tablewriter::insert(IT Begin, IT End) +{ + write_raw_line(generate(Begin, End)); +} + +template<typename TUPLE> inline void tablewriter::insert(const TUPLE &T) +{ + insert(std::begin(T), std::end(T)); +} + +template<typename IT> +inline void tablewriter::push_back(IT Begin, IT End) +{ + insert(Begin, End); +} + +template<typename TUPLE> +inline void tablewriter::push_back(const TUPLE &T) +{ + insert(std::begin(T), std::end(T)); +} + +template<typename TUPLE> +inline tablewriter &tablewriter::operator<<(const TUPLE &T) +{ + insert(T); + return *this; +} + +} // namespace pqxx +#include "pqxx/compiler-internal-post.hxx" +#endif diff --git a/contrib/libs/libpqxx/include/pqxx/transaction b/contrib/libs/libpqxx/include/pqxx/transaction new file mode 100644 index 0000000000..755cd4179b --- /dev/null +++ b/contrib/libs/libpqxx/include/pqxx/transaction @@ -0,0 +1,6 @@ +/** pqxx::transaction class. + * + * pqxx::transaction represents a standard database transaction. + */ +// Actual definitions in .hxx file so editors and such recognize file type. +#include "pqxx/transaction.hxx" diff --git a/contrib/libs/libpqxx/include/pqxx/transaction.hxx b/contrib/libs/libpqxx/include/pqxx/transaction.hxx new file mode 100644 index 0000000000..6c0b1da0b2 --- /dev/null +++ b/contrib/libs/libpqxx/include/pqxx/transaction.hxx @@ -0,0 +1,116 @@ +/** Definition of the pqxx::transaction class. + * pqxx::transaction represents a standard database transaction. + * + * DO NOT INCLUDE THIS FILE DIRECTLY; include pqxx/transaction 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_TRANSACTION +#define PQXX_H_TRANSACTION + +#include "pqxx/compiler-public.hxx" +#include "pqxx/compiler-internal-pre.hxx" + +#include "pqxx/dbtransaction.hxx" + + +/* Methods tested in eg. self-test program test1 are marked with "//[t01]" + */ + + +namespace pqxx +{ + +namespace internal +{ +/// Helper base class for the @c transaction class template. +class PQXX_LIBEXPORT basic_transaction : public dbtransaction +{ +protected: + basic_transaction( //[t01] + connection_base &C, + const std::string &IsolationLevel, + readwrite_policy); + +private: + virtual void do_commit() override; //[t01] +}; +} // namespace internal + + +/** + * @ingroup transaction + */ +//@{ + +/// Standard back-end transaction, templatized on isolation level +/** This is the type you'll normally want to use to represent a transaction on + * the database. + * + * While you may choose to create your own transaction object to interface to + * the database backend, it is recommended that you wrap your transaction code + * into a transactor code instead and let the transaction be created for you. + * @see pqxx/transactor.hxx + * + * If you should find that using a transactor makes your code less portable or + * too complex, go ahead, create your own transaction anyway. + * + * Usage example: double all wages + * + * @code + * extern connection C; + * work T(C); + * try + * { + * T.exec("UPDATE employees SET wage=wage*2"); + * T.commit(); // NOTE: do this inside try block + * } + * catch (const exception &e) + * { + * cerr << e.what() << endl; + * T.abort(); // Usually not needed; same happens when T's life ends. + * } + * @endcode + */ +template< + isolation_level ISOLATIONLEVEL=read_committed, + readwrite_policy READWRITE=read_write> +class transaction : public internal::basic_transaction +{ +public: + using isolation_tag = isolation_traits<ISOLATIONLEVEL>; + + /// Create a transaction. + /** + * @param C Connection for this transaction to operate on + * @param TName Optional name for transaction; must begin with a letter and + * may contain letters and digits only + */ + explicit transaction(connection_base &C, const std::string &TName): //[t01] + namedclass{fullname("transaction", isolation_tag::name()), TName}, + internal::basic_transaction(C, isolation_tag::name(), READWRITE) + { Begin(); } + + explicit transaction(connection_base &C) : //[t01] + transaction(C, "") {} + + virtual ~transaction() noexcept + { End(); } +}; + + +/// The default transaction type. +using work = transaction<>; + +/// Read-only transaction. +using read_transaction = transaction<read_committed, read_only>; + +//@} +} + +#include "pqxx/compiler-internal-post.hxx" +#endif diff --git a/contrib/libs/libpqxx/include/pqxx/transaction_base b/contrib/libs/libpqxx/include/pqxx/transaction_base new file mode 100644 index 0000000000..929c50d226 --- /dev/null +++ b/contrib/libs/libpqxx/include/pqxx/transaction_base @@ -0,0 +1,7 @@ +/** Base for the transaction classes. + * + * pqxx::transaction_base defines the interface for any abstract class that + * represents a database transaction. + */ +// Actual definitions in .hxx file so editors and such recognize file type. +#include "pqxx/transaction_base.hxx" diff --git a/contrib/libs/libpqxx/include/pqxx/transaction_base.hxx b/contrib/libs/libpqxx/include/pqxx/transaction_base.hxx new file mode 100644 index 0000000000..06c2788d5a --- /dev/null +++ b/contrib/libs/libpqxx/include/pqxx/transaction_base.hxx @@ -0,0 +1,664 @@ +/** Common code and definitions for the transaction classes. + * + * pqxx::transaction_base defines the interface for any abstract class that + * represents a database transaction. + * + * DO NOT INCLUDE THIS FILE DIRECTLY; include pqxx/transaction_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_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; +}; + + +/// Helper class to construct an invocation of a parameterised statement. +/** @deprecated Use @c exec_params and friends instead. + */ +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: + /// Not allowed + 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 + + +/** + * @defgroup transaction Transaction classes + * + * All database access goes through instances of these classes. + * However, not all implementations of this interface need to provide + * full transactional integrity. + * + * Several implementations of this interface are shipped with libpqxx, including + * the plain transaction class, the entirely unprotected nontransaction, and the + * more cautious robusttransaction. + */ + +/// Interface definition (and common code) for "transaction" classes. +/** + * @ingroup transaction + * + * Abstract base class for all transaction types. + */ +class PQXX_LIBEXPORT PQXX_NOVTABLE transaction_base : + public virtual internal::namedclass +{ +public: + /// If nothing else is known, our isolation level is at least read_committed + 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] + + /// Commit the transaction + /** Unless this function is called explicitly, the transaction will not be + * committed (actually the nontransaction implementation breaks this rule, + * hence the name). + * + * Once this function returns, the whole transaction will typically be + * irrevocably completed in the database. There is also, however, a minute + * risk that the connection to the database may be lost at just the wrong + * moment. In that case, libpqxx may be unable to determine whether the + * transaction was completed or aborted and an in_doubt_error will be thrown + * to make this fact known to the caller. The robusttransaction + * implementation takes some special precautions to reduce this risk. + */ + void commit(); //[t01] + + /// Abort the transaction + /** No special effort is required to call this function; it will be called + * implicitly when the transaction is destructed. + */ + void abort(); //[t10] + + /** + * @ingroup escaping-functions + */ + //@{ + /// Escape string for use as SQL string literal in this transaction + std::string esc(const char str[]) const { return conn().esc(str); } + /// Escape string for use as SQL string literal in this transaction + std::string esc(const char str[], size_t maxlen) const + { return conn().esc(str, maxlen); } + /// Escape string for use as SQL string literal in this transaction + std::string esc(const std::string &str) const { return conn().esc(str); } + + /// Escape binary data for use as SQL string literal in this transaction + /** Raw, binary data is treated differently from regular strings. Binary + * strings are never interpreted as text, so they may safely include byte + * values or byte sequences that don't happen to represent valid characters in + * the character encoding being used. + * + * The binary string does not stop at the first zero byte, as is the case with + * textual strings. Instead, they may contain zero bytes anywhere. If it + * happens to contain bytes that look like quote characters, or other things + * that can disrupt their use in SQL queries, they will be replaced with + * special escape sequences. + */ + std::string esc_raw(const unsigned char data[], size_t len) const //[t62] + { return conn().esc_raw(data, len); } + /// Escape binary data for use as SQL string literal in this transaction + std::string esc_raw(const std::string &) const; //[t62] + + /// 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) const + { return conn().unesc_raw(text); } + + /// 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) const + { return conn().unesc_raw(text); } + + /// 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) const + { return conn().quote(t); } + + /// Binary-escape and quote a binarystring for use as an SQL constant. + 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; + + /// Escape an SQL identifier for use in a query. + std::string quote_name(const std::string &identifier) const + { return conn().quote_name(identifier); } + + /// Escape string for literal LIKE match. + std::string esc_like(const std::string &str, char escape_char='\\') const + { return conn().esc_like(str, escape_char); } + //@} + + /// Execute query + /** Perform a query in this transaction. + * + * This is one of the most important functions in libpqxx. + * + * Most libpqxx exceptions can be thrown from here, including sql_error, + * broken_connection, and many sql_error subtypes such as + * feature_not_supported or insufficient_privilege. But any exception thrown + * by the C++ standard library may also occur here. All exceptions will be + * derived from std::exception, however, and all libpqxx-specific exception + * types are derived from pqxx::pqxx_exception. + * + * @param Query Query or command to execute + * @param Desc Optional identifier for query, to help pinpoint SQL errors + * @return A result set describing the query's or command's result + */ + 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); } + + /// Execute query, which should zero rows of data. + /** Works like exec, but fails if the result contains data. It still returns + * a result, however, which may contain useful metadata. + * + * @throw unexpected_rows If the query returned the wrong number of rows. + */ + result exec0( + const std::string &Query, + const std::string &Desc=std::string{}) + { return exec_n(0, Query, Desc); } + + /// Execute query returning a single row of data. + /** Works like exec, but requires the result to contain exactly one row. + * The row can be addressed directly, without the need to find the first row + * in a result set. + * + * @throw unexpected_rows If the query returned the wrong number of rows. + */ + row exec1(const std::string &Query, const std::string &Desc=std::string{}) + { return exec_n(1, Query, Desc).front(); } + + /// Execute query, expect given number of rows. + /** Works like exec, but checks that the number of rows is exactly what's + * expected. + * + * @throw unexpected_rows If the query returned the wrong number of rows. + */ + result exec_n( + size_t rows, + const std::string &Query, + const std::string &Desc=std::string{}); + + /** + * @name Parameterized statements + * + * You'll often need parameters in the queries you execute: "select the + * car with this licence plate." If the parameter is a string, you need to + * quote it and escape any special characters inside it, or it may become a + * target for an SQL injection attack. If it's an integer (for example), + * you need to convert it to a string, but in the database's format, without + * locale-specific niceties like "," separators between the thousands. + * + * Parameterised statements are an easier and safer way to do this. They're + * like prepared statements, but for a single use. You don't need to name + * them, and you don't need to prepare them first. + * + * Your query will include placeholders like @c $1 and $2 etc. in the places + * where you want the arguments to go. Then, you pass the argument values + * and the actual query is constructed for you. + * + * Pass the exact right number of parameters, and in the right order. The + * parameters in the query don't have to be neatly ordered from @c $1 to + * @c $2 to @c $3 - but you must pass the argument for @c $1 first, the one + * for @c $2 second, etc. + * + * @warning Beware of "nul" bytes. Any string you pass as a parameter will + * end at the first char with value zero. If you pass a @c std::string that + * contains a zero byte, the last byte in the value will be the one just + * before the zero. + */ + //@{ + /// Execute an SQL statement with parameters. + 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. + /** @throw unexpected_rows if the result does not consist of exactly one row. + */ + 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. + /** @throw unexpected_rows if the result contains 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. + /** @throw unexpected_rows if the result contains the wrong 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; + } + + /// Parameterize a statement. @deprecated Use @c exec_params instead. + /* 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); + //@} + + /** + * @name Prepared statements + * + * These are very similar to parameterised statements. The difference is + * that you prepare them in advance, giving them identifying names. You can + * then call them by these names, passing in the argument values appropriate + * for that call. + * + * You prepare a statement on the connection, using + * @c pqxx::connection_base::prepare(). But you then call the statement in a + * transaction, using the functions you see here. + * + * Never try to prepare, execute, or unprepare a prepared statement manually + * using direct SQL queries. Always use the functions provided by libpqxx. + * + * See \ref prepared for a full discussion. + * + * @warning Beware of "nul" bytes. Any string you pass as a parameter will + * end at the first char with value zero. If you pass a @c std::string that + * contains a zero byte, the last byte in the value will be the one just + * before the zero. If you need a zero byte, consider using + * pqxx::binarystring and/or SQL's @c bytea type. + */ + //@{ + + /// Execute a prepared statement, with optional arguments. + template<typename ...Args> + result exec_prepared(const std::string &statement, Args&&... args) + { + return internal_exec_prepared( + statement, internal::params(std::forward<Args>(args)...), result_format::text); + } + + /// Execute a prepared statement, with optional arguments. + template<typename ...Args> + result exec_prepared_binary(const std::string &statement, Args&&... args) + { + return internal_exec_prepared( + statement, internal::params(std::forward<Args>(args)...), result_format::binary); + } + + /// Execute a prepared statement, and expect a single-row result. + /** @throw pqxx::unexpected_rows if the result was not exactly 1 row. + */ + template<typename ...Args> + row exec_prepared1(const std::string &statement, Args&&... args) + { + return exec_prepared_n(1, statement, std::forward<Args>(args)...).front(); + } + + /// Execute a prepared statement, and expect a result with zero rows. + /** @throw pqxx::unexpected_rows if the result contained rows. + */ + template<typename ...Args> + result exec_prepared0(const std::string &statement, Args&&... args) + { + return exec_prepared_n(0, statement, std::forward<Args>(args)...); + } + + /// Execute a prepared statement, expect a result with given number of rows. + /** @throw pqxx::unexpected_rows if the result did not contain exactly the + * given number of rows. + */ + 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; + } + + /// Execute prepared statement. @deprecated Use exec_prepared instead. + /** Just like param_declaration is a helper class that lets you tag parameter + * declarations onto the statement declaration, the invocation class returned + * here lets you tag parameter values onto the call: + * + * @code + * result run_mystatement(transaction_base &T) + * { + * return T.exec_prepared("mystatement", "param1", 2, nullptr, 4); + * } + * @endcode + * + * Here, parameter 1 (written as "<tt>$1</tt>" in the statement's body) is a + * string that receives the value "param1"; the second parameter is an integer + * with the value 2; the third receives a null, making its type irrelevant; + * and number 4 again is an integer. The ultimate invocation of exec() is + * essential; if you forget this, nothing happens. + * + * To see whether any prepared statement has been defined under a given name, + * use: + * + * @code + * T.prepared("mystatement").exists() + * @endcode + * + * @warning Do not try to execute a prepared statement manually through direct + * SQL statements. This is likely not to work, and even if it does, is likely + * to be slower than using the proper libpqxx functions. Also, libpqxx knows + * how to emulate prepared statements if some part of the infrastructure does + * not support them. + * + * @warning Actual definition of the prepared statement on the backend may be + * deferred until its first use, which means that any errors in the prepared + * statement may not show up until it is executed--and perhaps abort the + * ongoing transaction in the process. + * + * If you leave out the statement name, the call refers to the nameless + * statement instead. + */ + PQXX_DEPRECATED prepare::invocation + prepared(const std::string &statement=std::string{}); + + //@} + + /** + * @name Error/warning output + */ + //@{ + /// Have connection process warning message + void process_notice(const char Msg[]) const //[t14] + { m_conn.process_notice(Msg); } + /// Have connection process warning message + void process_notice(const std::string &Msg) const //[t14] + { m_conn.process_notice(Msg); } + //@} + + /// Connection this transaction is running in + connection_base &conn() const { return m_conn; } //[t04] + + /// Set session variable in this connection + /** The new value is typically forgotten if the transaction aborts. + * However nontransaction is an exception to this rule: in that case the set + * value will be kept regardless. Also, if the connection ever needs to be + * recovered, a value you set in a nontransaction will not be restored. + * @param Var The variable to set + * @param Val The new value to store in the variable + */ + void set_variable(const std::string &Var, const std::string &Val); //[t61] + + /// Get currently applicable value of variable + /** First consults an internal cache of variables that have been set (whether + * in the ongoing transaction or in the connection) using the set_variable + * functions. If it is not found there, the database is queried. + * + * @warning Do not mix the set_variable with raw "SET" queries, and do not + * try to set or get variables while a pipeline or table stream is active. + * + * @warning This function used to be declared as @c const but isn't anymore. + */ + std::string get_variable(const std::string &); //[t61] + +protected: + /// Create a transaction (to be called by implementation classes only) + /** The optional name, if nonempty, must begin with a letter and may contain + * letters and digits only. + * + * @param c The connection that this transaction is to act on. + * @param direct Running directly in connection context (i.e. not nested)? + */ + explicit transaction_base(connection_base &c, bool direct=true); + + /// Begin transaction (to be called by implementing class) + /** Will typically be called from implementing class' constructor. + */ + void Begin(); + + /// End transaction. To be called by implementing class' destructor + void End() noexcept; + + /// To be implemented by derived implementation class: start transaction + virtual void do_begin() =0; + /// To be implemented by derived implementation class: perform query + virtual result do_exec(const char Query[]) =0; + /// To be implemented by derived implementation class: commit transaction + virtual void do_commit() =0; + /// To be implemented by derived implementation class: abort transaction + virtual void do_abort() =0; + + // For use by implementing class: + + /// Execute query on connection directly + /** + * @param C Query or command to execute + * @param Retries Number of times to retry the query if it fails. Be + * extremely careful with this option; if you retry in the middle of a + * transaction, you may be setting up a new connection transparently and + * executing the latter part of the transaction without a backend transaction + * being active (and with the former part aborted). + */ + result direct_exec(const char C[], int Retries=0); + + /// Forget about any reactivation-blocking resources we tried to allocate + void reactivation_avoidance_clear() noexcept + {m_reactivation_avoidance.clear();} + +protected: + /// Resources allocated in this transaction that make reactivation impossible + /** This number may be negative! + */ + 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 + }; + + /// Make sure transaction is opened on backend, if appropriate + 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_format format); + + result internal_exec_params( + const std::string &query, + const internal::params &args); + + /// Throw unexpected_rows if prepared statement returned wrong no. of rows. + void check_rowcount_prepared( + const std::string &statement, + size_t expected_rows, + size_t actual_rows); + + /// Throw unexpected_rows if wrong row count from parameterised statement. + 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 diff --git a/contrib/libs/libpqxx/include/pqxx/transactor b/contrib/libs/libpqxx/include/pqxx/transactor new file mode 100644 index 0000000000..658551f9b6 --- /dev/null +++ b/contrib/libs/libpqxx/include/pqxx/transactor @@ -0,0 +1,6 @@ +/** pqxx::transactor class. + * + * pqxx::transactor is a framework-style wrapper for safe transactions. + */ +// Actual definitions in .hxx file so editors and such recognize file type. +#include "pqxx/transactor.hxx" diff --git a/contrib/libs/libpqxx/include/pqxx/transactor.hxx b/contrib/libs/libpqxx/include/pqxx/transactor.hxx new file mode 100644 index 0000000000..5aba0193cb --- /dev/null +++ b/contrib/libs/libpqxx/include/pqxx/transactor.hxx @@ -0,0 +1,274 @@ +/* Transactor framework, a wrapper for safely retryable transactions. + * + * DO NOT INCLUDE THIS FILE DIRECTLY; include pqxx/transactor 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_TRANSACTOR +#define PQXX_H_TRANSACTOR + +#include "pqxx/compiler-public.hxx" +#include "pqxx/compiler-internal-pre.hxx" + +#include "pqxx/connection_base.hxx" +#include "pqxx/transaction.hxx" + + +// Methods tested in eg. test module test01 are marked with "//[t01]". + +namespace pqxx +{ +/** + * @defgroup transactor Transactor framework + * + * Sometimes a transaction can fail for completely transient reasons, such as a + * conflict with another transaction in SERIALIZABLE isolation. The right way + * to handle those failures is often just to re-run the transaction from + * scratch. + * + * For example, your REST API might be handling each HTTP request in its own + * database transaction, and if this kind of transient failure happens, you + * simply want to "replay" the whole request, in a fresh transaction. + * + * You won't necessarily want to execute the exact same SQL commands with the + * exact same data. Some of your SQL statements may depend on state that can + * vary between retries. So instead of dumbly replaying the SQL, you re-run + * the same application code that produced those SQL commands. + * + * The transactor framework makes it a little easier for you to do this safely, + * and avoid typical pitfalls. You encapsulate the work that you want to do + * into a callable that you pass to the @c perform function. + * + * Here's how it works. You write your transaction code as a lambda or + * function, which creates its own transaction object, does its work, and + * commits at the end. You pass that callback to @c pqxx::perform, which runs + * it for you. + * + * If there's a failure inside your callback, there will be an exception. Your + * transaction object goes out of scope and gets destroyed, so that it aborts + * implicitly. Seeing this, @c perform tries running your callback again. It + * stops doing that when the callback succeeds, or when it has failed too many + * times, or when there's an error that leaves the database in an unknown + * state, such as a lost connection just while we're waiting for the database + * to confirm a commit. It all depends on the type of exception. + * + * The callback takes no arguments. If you're using lambdas, the easy way to + * pass arguments is for the lambda to "capture" them from your variables. Or, + * if you're using functions, you may want to use @c std::bind. + * + * Once your callback succeeds, it can return a result, and @c perform will + * return that result back to you. + */ +//@{ + +/// Simple way to execute a transaction with automatic retry. +/** + * Executes your transaction code as a callback. Repeats it until it completes + * normally, or it throws an error other than the few libpqxx-generated + * exceptions that the framework understands, or after a given number of failed + * attempts, or if the transaction ends in an "in-doubt" state. + * + * (An in-doubt state is one where libpqxx cannot determine whether the server + * finally committed a transaction or not. This can happen if the network + * connection to the server is lost just while we're waiting for its reply to + * a "commit" statement. The server may have completed the commit, or not, but + * it can't tell you because there's no longer a connection. + * + * Using this still takes a bit of care. If your callback makes use of data + * from the database, you'll probably have to query that data within your + * callback. If the attempt to perform your callback fails, and the framework + * tries again, you'll be in a new transaction and the data in the database may + * have changed under your feet. + * + * Also be careful about changing variables or data structures from within + * your callback. The run may still fail, and perhaps get run again. The + * ideal way to do it (in most cases) is to return your result from your + * callback, and change your program's data state only after @c perform + * completes successfully. + * + * @param callback Transaction code that can be called with no arguments. + * @param attempts Maximum number of times to attempt performing callback. + * Must be greater than zero. + * @return Whatever your callback returns. + */ +template<typename TRANSACTION_CALLBACK> +inline auto perform(const TRANSACTION_CALLBACK &callback, int attempts=3) + -> decltype(callback()) +{ + if (attempts <= 0) + throw std::invalid_argument{ + "Zero or negative number of attempts passed to pqxx::perform()."}; + + for (; attempts > 0; --attempts) + { + try + { + return callback(); + } + catch (const in_doubt_error &) + { + // Not sure whether transaction went through or not. The last thing in + // the world that we should do now is try again! + throw; + } + catch (const statement_completion_unknown &) + { + // Not sure whether our last statement succeeded. Don't risk running it + // again. + throw; + } + catch (const broken_connection &) + { + // Connection failed. Definitely worth retrying. + if (attempts <= 1) throw; + continue; + } + catch (const transaction_rollback &) + { + // Some error that may well be transient, such as serialization failure + // or deadlock. Worth retrying. + if (attempts <= 1) throw; + continue; + } + } + throw pqxx::internal_error{"No outcome reached on perform()."}; +} + +/// @deprecated Pre-C++11 wrapper for automatically retrying transactions. +/** + * Pass an object of your transactor-based class to connection_base::perform() + * to execute the transaction code embedded in it. + * + * connection_base::perform() is actually a template, specializing itself to any + * transactor type you pass to it. This means you will have to pass it a + * reference of your object's ultimate static type; runtime polymorphism is + * not allowed. Hence the absence of virtual methods in transactor. The + * exact methods to be called at runtime *must* be resolved at compile time. + * + * Your transactor-derived class must define a copy constructor. This will be + * used to create a "clean" copy of your transactor for every attempt that + * perform() makes to run it. + */ +template<typename TRANSACTION=transaction<read_committed>> class transactor +{ +public: + using argument_type = TRANSACTION; + PQXX_DEPRECATED explicit transactor( //[t04] + const std::string &TName="transactor") : + m_name{TName} { } + + /// Overridable transaction definition; insert your database code here + /** The operation will be retried if the connection to the backend is lost or + * the operation fails, but not if the connection is broken in such a way as + * to leave the library in doubt as to whether the operation succeeded. In + * that case, an in_doubt_error will be thrown. + * + * Recommended practice is to allow this operator to modify only the + * transactor itself, and the dedicated transaction object it is passed as an + * argument. This is what makes side effects, retrying etc. controllable in + * the transactor framework. + * @param T Dedicated transaction context created to perform this operation. + */ + void operator()(TRANSACTION &T); //[t04] + + // Overridable member functions, called by connection_base::perform() if an + // attempt to run transaction fails/succeeds, respectively, or if the + // connection is lost at just the wrong moment, goes into an indeterminate + // state. Use these to patch up runtime state to match events, if needed, or + // to report failure conditions. + + /// Optional overridable function to be called if transaction is aborted + /** This need not imply complete failure; the transactor will automatically + * retry the operation a number of times before giving up. on_abort() will be + * called for each of the failed attempts. + * + * One parameter is passed in by the framework: an error string describing why + * the transaction failed. This will also be logged to the connection's + * notice processor. + */ + void on_abort(const char[]) noexcept {} //[t13] + + /// Optional overridable function to be called after successful commit + /** If your on_commit() throws an exception, the actual back-end transaction + * will remain committed, so any changes in the database remain regardless of + * how this function terminates. + */ + void on_commit() {} //[t07] + + /// Overridable function to be called when "in doubt" about outcome + /** This may happen if the connection to the backend is lost while attempting + * to commit. In that case, the backend may have committed the transaction + * but is unable to confirm this to the frontend; or the transaction may have + * failed, causing it to be rolled back, but again without acknowledgement to + * the client program. The best way to deal with this situation is typically + * to wave red flags in the user's face and ask him to investigate. + * + * The robusttransaction class is intended to reduce the chances of this + * error occurring, at a certain cost in performance. + * @see robusttransaction + */ + void on_doubt() noexcept {} //[t13] + + /// The transactor's name. + std::string name() const { return m_name; } //[t13] + +private: + std::string m_name; +}; + + +template<typename TRANSACTOR> +inline void connection_base::perform( + const TRANSACTOR &T, + int Attempts) +{ + if (Attempts <= 0) return; + + bool Done = false; + + // Make attempts to perform T + do + { + --Attempts; + + // Work on a copy of T2 so we can restore the starting situation if need be + TRANSACTOR T2{T}; + try + { + typename TRANSACTOR::argument_type X{*this, T2.name()}; + T2(X); + X.commit(); + Done = true; + } + catch (const in_doubt_error &) + { + // Not sure whether transaction went through or not. The last thing in + // the world that we should do now is retry. + T2.on_doubt(); + throw; + } + catch (const std::exception &e) + { + // Could be any kind of error. + T2.on_abort(e.what()); + if (Attempts <= 0) throw; + continue; + } + catch (...) + { + // Don't try to forge ahead if we don't even know what happened + T2.on_abort("Unknown exception"); + throw; + } + + T2.on_commit(); + } while (not Done); +} +} // namespace pqxx +//@} +#include "pqxx/compiler-internal-post.hxx" +#endif diff --git a/contrib/libs/libpqxx/include/pqxx/types.hxx b/contrib/libs/libpqxx/include/pqxx/types.hxx new file mode 100644 index 0000000000..49d1a0d1f0 --- /dev/null +++ b/contrib/libs/libpqxx/include/pqxx/types.hxx @@ -0,0 +1,57 @@ +/** + * Basic type aliases and forward declarations. + * + * 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_TYPES +#define PQXX_H_TYPES + +#include <cstddef> + +namespace pqxx +{ +/// Number of rows in a result set. +using result_size_type = unsigned long; + +/// Difference between result sizes. +using result_difference_type = signed long; + +/// Number of fields in a row of database data. +using row_size_type = unsigned int; + +/// Difference between row sizes. +using row_difference_type = signed int; + +/// Number of bytes in a field of database data. +using field_size_type = std::size_t; + +/// Number of bytes in a large object. (Unusual: it's signed.) +using large_object_size_type = long; + + +// Forward declarations, to help break compilation dependencies. +// These won't necessarily include all classes in libpqxx. +class binarystring; +class connectionpolicy; +class connection_base; +class const_result_iterator; +class const_reverse_result_iterator; +class const_reverse_row_iterator; +class const_row_iterator; +class dbtransaction; +class field; +class largeobjectaccess; +class notification_receiver; +class range_error; +class result; +class row; +class tablereader; +class transaction_base; + +} // namespace pqxx + +#endif diff --git a/contrib/libs/libpqxx/include/pqxx/util b/contrib/libs/libpqxx/include/pqxx/util new file mode 100644 index 0000000000..6ec38ac111 --- /dev/null +++ b/contrib/libs/libpqxx/include/pqxx/util @@ -0,0 +1,5 @@ +/** Various utility definitions for libpqxx. + */ +// Actual definitions in .hxx file so editors and such recognize file type +#include "pqxx/util.hxx" + diff --git a/contrib/libs/libpqxx/include/pqxx/util.hxx b/contrib/libs/libpqxx/include/pqxx/util.hxx new file mode 100644 index 0000000000..86a9134c38 --- /dev/null +++ b/contrib/libs/libpqxx/include/pqxx/util.hxx @@ -0,0 +1,309 @@ +/** Various utility definitions for libpqxx. + * + * DO NOT INCLUDE THIS FILE DIRECTLY; include pqxx/util 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_UTIL +#define PQXX_H_UTIL + +#include "pqxx/compiler-public.hxx" + +#include <cstdio> +#include <cctype> +#include <iterator> +#include <memory> +#include <stdexcept> +#include <string> +#include <type_traits> +#include <typeinfo> +#include <vector> + +#include "pqxx/strconv.hxx" + + +/// The home of all libpqxx classes, functions, templates, etc. +namespace pqxx {} + +#include <pqxx/internal/libpq-forward.hxx> + + +namespace pqxx +{ +/// Suppress compiler warning about an unused item. +template<typename T> inline void ignore_unused(T) {} + + +/// Descriptor of library's thread-safety model. +/** This describes what the library knows about various risks to thread-safety. + */ +struct PQXX_LIBEXPORT thread_safety_model +{ + /// @deprecated Is error reporting thread-safe? Now always true. + bool have_safe_strerror = true; + + /// Is the underlying libpq build thread-safe? + bool safe_libpq; + + /// @deprecated Query cancel is always thread-safe now. + bool safe_query_cancel = true; + + /// @deprecated Always thread-safe to copy a 'result' or 'binarystring' now. + bool safe_result_copy = true; + + /// Is Kerberos thread-safe? + /** @warning Is currently always @c false. + * + * If your application uses Kerberos, all accesses to libpqxx or Kerberos must + * be serialized. Confine their use to a single thread, or protect it with a + * global lock. + */ + bool safe_kerberos; + + /// A human-readable description of any thread-safety issues. + std::string description; +}; + + +/// Describe thread safety available in this build. +PQXX_LIBEXPORT thread_safety_model describe_thread_safety() noexcept; + + +/// The "null" oid. +constexpr oid oid_none = 0; + + +/** + * @defgroup utility Utility functions + */ +//@{ + +/// Represent sequence of values as a string, joined by a given separator. +/** + * Use this to turn e.g. the numbers 1, 2, and 3 into a string "1, 2, 3". + * + * @param sep separator string (to be placed between items) + * @param begin beginning of items sequence + * @param end end of items sequence + * @param access functor defining how to dereference sequence elements + */ +template<typename ITER, typename ACCESS> inline +std::string separated_list( //[t00] + const std::string &sep, + ITER begin, + ITER end, + ACCESS access) +{ + std::string result; + if (begin != end) + { + result = to_string(access(begin)); + for (++begin; begin != end; ++begin) + { + result += sep; + result += to_string(access(begin)); + } + } + return result; +} + + +/// Render sequence as a string, using given separator between items. +template<typename ITER> inline std::string +separated_list(const std::string &sep, ITER begin, ITER end) //[t00] + { return separated_list(sep, begin, end, [](ITER i){ return *i; }); } + + +/// Render items in a container as a string, using given separator. +template<typename CONTAINER> inline auto +separated_list(const std::string &sep, const CONTAINER &c) //[t10] + /* + Always std::string; necessary because SFINAE doesn't work with the + contents of function bodies, so the check for iterability has to be in + the signature. + */ + -> typename std::enable_if< + ( + not std::is_void<decltype(std::begin(c))>::value + and not std::is_void<decltype(std::end(c))>::value + ), + std::string + >::type +{ + return separated_list(sep, std::begin(c), std::end(c)); +} + + +/// Render items in a tuple as a string, using given separator. +template< + typename TUPLE, + std::size_t INDEX=0, + typename ACCESS, + typename std::enable_if< + (INDEX == std::tuple_size<TUPLE>::value-1), + int + >::type=0 +> +inline std::string +separated_list( + const std::string & /* sep */, + const TUPLE &t, + const ACCESS& access +) +{ + return to_string(access(&std::get<INDEX>(t))); +} + +template< + typename TUPLE, + std::size_t INDEX=0, + typename ACCESS, + typename std::enable_if< + (INDEX < std::tuple_size<TUPLE>::value-1), + int + >::type=0 +> +inline std::string +separated_list(const std::string &sep, const TUPLE &t, const ACCESS& access) +{ + return + to_string(access(&std::get<INDEX>(t))) + + sep + + separated_list<TUPLE, INDEX+1>(sep, t, access); +} + +template< + typename TUPLE, + std::size_t INDEX=0, + typename std::enable_if< + (INDEX <= std::tuple_size<TUPLE>::value), + int + >::type=0 +> +inline std::string +separated_list(const std::string &sep, const TUPLE &t) +{ + return separated_list(sep, t, [](const TUPLE &tup){return *tup;}); +} +//@} + + +/// Private namespace for libpqxx's internal use; do not access. +/** This namespace hides definitions internal to libpqxx. These are not + * supposed to be used by client programs, and they may change at any time + * without notice. + * + * Conversely, if you find something in this namespace tremendously useful, by + * all means do lodge a request for its publication. + * + * @warning Here be dragons! + */ +namespace internal +{ +PQXX_LIBEXPORT void freepqmem(const void *) noexcept; +template<typename P> inline void freepqmem_templated(P *p) noexcept +{ + freepqmem(p); +} + +PQXX_LIBEXPORT void freemallocmem(const void *) noexcept; +template<typename P> inline void freemallocmem_templated(P *p) noexcept +{ + freemallocmem(p); +} + + +/// Helper base class: object descriptions for error messages and such. +/** + * Classes derived from namedclass have a class name (such as "transaction"), + * an optional object name (such as "delete-old-logs"), and a description + * generated from the two names (such as "transaction delete-old-logs"). + * + * The class name is dynamic here, in order to support inheritance hierarchies + * where the exact class name may not be known statically. + * + * In inheritance hierarchies, make namedclass a virtual base class so that + * each class in the hierarchy can specify its own class name in its + * constructors. + */ +class PQXX_LIBEXPORT namedclass +{ +public: + explicit namedclass(const std::string &Classname) : + m_classname{Classname}, + m_name{} + { + } + + namedclass(const std::string &Classname, const std::string &Name) : + m_classname{Classname}, + m_name{Name} + { + } + + /// Object name, or the empty string if no name was given. + const std::string &name() const noexcept { return m_name; } //[t01] + + /// Class name. + const std::string &classname() const noexcept //[t73] + { return m_classname; } + + /// Combination of class name and object name; or just class name. + std::string description() const; + +private: + std::string m_classname, m_name; +}; + + +PQXX_PRIVATE void CheckUniqueRegistration( + const namedclass *New, const namedclass *Old); +PQXX_PRIVATE void CheckUniqueUnregistration( + const namedclass *New, const namedclass *Old); + + +/// Ensure proper opening/closing of GUEST objects related to a "host" object +/** Only a single GUEST may exist for a single host at any given time. GUEST + * must be derived from namedclass. + */ +template<typename GUEST> +class unique +{ +public: + unique() =default; + unique(const unique &) =delete; + unique &operator=(const unique &) =delete; + + GUEST *get() const noexcept { return m_guest; } + + void register_guest(GUEST *G) + { + CheckUniqueRegistration(G, m_guest); + m_guest = G; + } + + void unregister_guest(GUEST *G) + { + CheckUniqueUnregistration(G, m_guest); + m_guest = nullptr; + } + +private: + GUEST *m_guest = nullptr; +}; + + +/// Sleep for the given number of seconds +/** May return early, e.g. when interrupted by a signal. Completes instantly if + * a zero or negative sleep time is requested. + */ +PQXX_LIBEXPORT void sleep_seconds(int); + +} // namespace internal +} // namespace pqxx + +#endif diff --git a/contrib/libs/libpqxx/include/pqxx/version b/contrib/libs/libpqxx/include/pqxx/version new file mode 100644 index 0000000000..5f7ab6a14e --- /dev/null +++ b/contrib/libs/libpqxx/include/pqxx/version @@ -0,0 +1,4 @@ +/** libpqxx version info. + */ +// Actual definitions in .hxx file so editors and such recognize file type. +#include "pqxx/version.hxx" diff --git a/contrib/libs/libpqxx/include/pqxx/version.hxx b/contrib/libs/libpqxx/include/pqxx/version.hxx new file mode 100644 index 0000000000..6fe982d433 --- /dev/null +++ b/contrib/libs/libpqxx/include/pqxx/version.hxx @@ -0,0 +1,57 @@ +/** Version info for libpqxx. + * + * DO NOT INCLUDE THIS FILE DIRECTLY; include pqxx/version 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_VERSION + +#include "pqxx/compiler-public.hxx" +#include "pqxx/compiler-internal-pre.hxx" + +/// Full libpqxx version string. +#define PQXX_VERSION "6.4.4" +/// Library ABI version. +#define PQXX_ABI "6.4" + +/// Major version number. +#define PQXX_VERSION_MAJOR 6 +/// Minor version number. +#define PQXX_VERSION_MINOR 4 + +namespace pqxx +{ +namespace internal +{ +/// Library version check stub. +/** Helps detect version mismatches between libpqxx headers and the libpqxx + * library binary. + * + * Sometimes users run into trouble linking their code against libpqxx because + * they build their own libpqxx, but the system also has a different version + * installed. The declarations in the headers against which they compile their + * code will differ from the ones used to build the libpqxx version they're + * using, leading to confusing link errors. The solution is to generate a link + * error when the libpqxx binary is not the same version as the libpqxx headers + * used to compile the code. + * + * This is a template declaration, but its only actual definition is a + * sepcialisation for the current library version. The definition is in the + * libpqxx binary, so it's based on the version as found in the binary. The + * headers contain a call to the function, specialised on the libpqxx version + * as found in the headers. (The library build process will use its own local + * headers even if another version of the headers is installed on the system.) + * + * If the libpqxx binary was compiled for a different version than the user's + * code, linking will fail with an error: @c check_library_version will not + * exist for the given version number. + */ +template<int, int> PQXX_LIBEXPORT int check_library_version() noexcept; +} +} +#include "pqxx/compiler-internal-post.hxx" +#endif |