{"diffoscope-json-version": 1, "source1": "/srv/reproducible-results/rbuild-debian/r-b-build.iluNnoWW/b1/libpqxx_7.8.1-2.1_i386.changes", "source2": "/srv/reproducible-results/rbuild-debian/r-b-build.iluNnoWW/b2/libpqxx_7.8.1-2.1_i386.changes", "unified_diff": null, "details": [{"source1": "Files", "source2": "Files", "unified_diff": "@@ -1,5 +1,5 @@\n \n 2744bd5d0894480ab584379c07a0c612 2214824 debug optional libpqxx-7.8t64-dbgsym_7.8.1-2.1_i386.deb\n 1d52d2ac08a94957c14478b04ceca920 205092 libs optional libpqxx-7.8t64_7.8.1-2.1_i386.deb\n f1699c5e0a4d2df2d02b408c09808e5f 365604 libdevel optional libpqxx-dev_7.8.1-2.1_i386.deb\n- 6e13fdade9757b6b19f4e6b2b3b287a6 1821260 doc optional libpqxx-doc_7.8.1-2.1_all.deb\n+ baa4834b8cea2d862dc144000bb39b5c 1821420 doc optional libpqxx-doc_7.8.1-2.1_all.deb\n"}, {"source1": "libpqxx-doc_7.8.1-2.1_all.deb", "source2": "libpqxx-doc_7.8.1-2.1_all.deb", "unified_diff": null, "details": [{"source1": "file list", "source2": "file list", "unified_diff": "@@ -1,3 +1,3 @@\n -rw-r--r-- 0 0 0 4 2024-02-28 19:39:58.000000 debian-binary\n--rw-r--r-- 0 0 0 16352 2024-02-28 19:39:58.000000 control.tar.xz\n--rw-r--r-- 0 0 0 1804716 2024-02-28 19:39:58.000000 data.tar.xz\n+-rw-r--r-- 0 0 0 16380 2024-02-28 19:39:58.000000 control.tar.xz\n+-rw-r--r-- 0 0 0 1804848 2024-02-28 19:39:58.000000 data.tar.xz\n"}, {"source1": "control.tar.xz", "source2": "control.tar.xz", "unified_diff": null, "details": [{"source1": "control.tar", "source2": "control.tar", "unified_diff": null, "details": [{"source1": "./md5sums", "source2": "./md5sums", "unified_diff": null, "details": [{"source1": "./md5sums", "source2": "./md5sums", "comments": ["Files differ"], "unified_diff": null}, {"source1": "line order", "source2": "line order", "unified_diff": "@@ -81,15 +81,15 @@\n usr/share/doc/libpqxx-doc/html/a00101_source.html\n usr/share/doc/libpqxx-doc/html/a00104_source.html\n usr/share/doc/libpqxx-doc/html/a00107_source.html\n usr/share/doc/libpqxx-doc/html/a00110_source.html\n usr/share/doc/libpqxx-doc/html/a00113_source.html\n usr/share/doc/libpqxx-doc/html/a00116_source.html\n usr/share/doc/libpqxx-doc/html/a00119_source.html\n-usr/share/doc/libpqxx-doc/html/a00221_source.html\n+usr/share/doc/libpqxx-doc/html/a00191_source.html\n usr/share/doc/libpqxx-doc/html/a00239.html\n usr/share/doc/libpqxx-doc/html/a00240.html\n usr/share/doc/libpqxx-doc/html/a00240.js\n usr/share/doc/libpqxx-doc/html/a00241.html\n usr/share/doc/libpqxx-doc/html/a00242.html\n usr/share/doc/libpqxx-doc/html/a00243.html\n usr/share/doc/libpqxx-doc/html/a00243.js\n"}]}]}]}, {"source1": "data.tar.xz", "source2": "data.tar.xz", "unified_diff": null, "details": [{"source1": "data.tar", "source2": "data.tar", "unified_diff": null, "details": [{"source1": "file list", "source2": "file list", "unified_diff": "@@ -47,55 +47,55 @@\n -rw-r--r-- 0 root (0) root (0) 1972 2023-07-26 14:42:33.000000 ./usr/share/doc/libpqxx-doc/examples/test87.cxx\n -rw-r--r-- 0 root (0) root (0) 2990 2023-07-26 14:42:33.000000 ./usr/share/doc/libpqxx-doc/examples/test88.cxx\n -rw-r--r-- 0 root (0) root (0) 1022 2023-07-26 14:42:33.000000 ./usr/share/doc/libpqxx-doc/examples/test89.cxx\n -rw-r--r-- 0 root (0) root (0) 436 2023-07-26 14:42:33.000000 ./usr/share/doc/libpqxx-doc/examples/test90.cxx\n -rw-r--r-- 0 root (0) root (0) 17732 2023-07-26 14:42:33.000000 ./usr/share/doc/libpqxx-doc/examples/test_helpers.hxx\n -rw-r--r-- 0 root (0) root (0) 5510 2023-07-26 14:42:33.000000 ./usr/share/doc/libpqxx-doc/examples/test_types.hxx\n drwxr-xr-x 0 root (0) root (0) 0 2024-02-28 19:39:58.000000 ./usr/share/doc/libpqxx-doc/html/\n--rw-r--r-- 0 root (0) root (0) 35409 2024-02-28 19:39:58.000000 ./usr/share/doc/libpqxx-doc/html/a00002_source.html\n--rw-r--r-- 0 root (0) root (0) 144300 2024-02-28 19:39:58.000000 ./usr/share/doc/libpqxx-doc/html/a00005_source.html\n--rw-r--r-- 0 root (0) root (0) 91868 2024-02-28 19:39:58.000000 ./usr/share/doc/libpqxx-doc/html/a00008_source.html\n--rw-r--r-- 0 root (0) root (0) 14410 2024-02-28 19:39:58.000000 ./usr/share/doc/libpqxx-doc/html/a00011_source.html\n--rw-r--r-- 0 root (0) root (0) 12125 2024-02-28 19:39:58.000000 ./usr/share/doc/libpqxx-doc/html/a00014_source.html\n--rw-r--r-- 0 root (0) root (0) 3659 2024-02-28 19:39:58.000000 ./usr/share/doc/libpqxx-doc/html/a00017_source.html\n--rw-r--r-- 0 root (0) root (0) 8440 2024-02-28 19:39:58.000000 ./usr/share/doc/libpqxx-doc/html/a00020_source.html\n--rw-r--r-- 0 root (0) root (0) 92920 2024-02-28 19:39:58.000000 ./usr/share/doc/libpqxx-doc/html/a00023_source.html\n--rw-r--r-- 0 root (0) root (0) 137425 2024-02-28 19:39:58.000000 ./usr/share/doc/libpqxx-doc/html/a00026_source.html\n--rw-r--r-- 0 root (0) root (0) 4546 2024-02-28 19:39:58.000000 ./usr/share/doc/libpqxx-doc/html/a00029_source.html\n--rw-r--r-- 0 root (0) root (0) 17615 2024-02-28 19:39:58.000000 ./usr/share/doc/libpqxx-doc/html/a00032_source.html\n--rw-r--r-- 0 root (0) root (0) 25736 2024-02-28 19:39:58.000000 ./usr/share/doc/libpqxx-doc/html/a00035_source.html\n--rw-r--r-- 0 root (0) root (0) 51677 2024-02-28 19:39:58.000000 ./usr/share/doc/libpqxx-doc/html/a00038_source.html\n--rw-r--r-- 0 root (0) root (0) 113680 2024-02-28 19:39:58.000000 ./usr/share/doc/libpqxx-doc/html/a00041_source.html\n--rw-r--r-- 0 root (0) root (0) 12205 2024-02-28 19:39:58.000000 ./usr/share/doc/libpqxx-doc/html/a00044_source.html\n--rw-r--r-- 0 root (0) root (0) 4221 2024-02-28 19:39:58.000000 ./usr/share/doc/libpqxx-doc/html/a00047_source.html\n--rw-r--r-- 0 root (0) root (0) 29915 2024-02-28 19:39:58.000000 ./usr/share/doc/libpqxx-doc/html/a00050_source.html\n--rw-r--r-- 0 root (0) root (0) 3609 2024-02-28 19:39:58.000000 ./usr/share/doc/libpqxx-doc/html/a00053_source.html\n--rw-r--r-- 0 root (0) root (0) 60709 2024-02-28 19:39:58.000000 ./usr/share/doc/libpqxx-doc/html/a00056_source.html\n--rw-r--r-- 0 root (0) root (0) 84065 2024-02-28 19:39:58.000000 ./usr/share/doc/libpqxx-doc/html/a00059_source.html\n--rw-r--r-- 0 root (0) root (0) 49711 2024-02-28 19:39:58.000000 ./usr/share/doc/libpqxx-doc/html/a00062_source.html\n--rw-r--r-- 0 root (0) root (0) 57531 2024-02-28 19:39:58.000000 ./usr/share/doc/libpqxx-doc/html/a00065_source.html\n--rw-r--r-- 0 root (0) root (0) 115169 2024-02-28 19:39:58.000000 ./usr/share/doc/libpqxx-doc/html/a00068_source.html\n--rw-r--r-- 0 root (0) root (0) 115762 2024-02-28 19:39:58.000000 ./usr/share/doc/libpqxx-doc/html/a00071_source.html\n--rw-r--r-- 0 root (0) root (0) 50782 2024-02-28 19:39:58.000000 ./usr/share/doc/libpqxx-doc/html/a00074_source.html\n--rw-r--r-- 0 root (0) root (0) 19201 2024-02-28 19:39:58.000000 ./usr/share/doc/libpqxx-doc/html/a00077_source.html\n--rw-r--r-- 0 root (0) root (0) 19625 2024-02-28 19:39:58.000000 ./usr/share/doc/libpqxx-doc/html/a00080_source.html\n+-rw-r--r-- 0 root (0) root (0) 51677 2024-02-28 19:39:58.000000 ./usr/share/doc/libpqxx-doc/html/a00002_source.html\n+-rw-r--r-- 0 root (0) root (0) 29915 2024-02-28 19:39:58.000000 ./usr/share/doc/libpqxx-doc/html/a00005_source.html\n+-rw-r--r-- 0 root (0) root (0) 25867 2024-02-28 19:39:58.000000 ./usr/share/doc/libpqxx-doc/html/a00008_source.html\n+-rw-r--r-- 0 root (0) root (0) 50782 2024-02-28 19:39:58.000000 ./usr/share/doc/libpqxx-doc/html/a00011_source.html\n+-rw-r--r-- 0 root (0) root (0) 49711 2024-02-28 19:39:58.000000 ./usr/share/doc/libpqxx-doc/html/a00014_source.html\n+-rw-r--r-- 0 root (0) root (0) 113680 2024-02-28 19:39:58.000000 ./usr/share/doc/libpqxx-doc/html/a00017_source.html\n+-rw-r--r-- 0 root (0) root (0) 92920 2024-02-28 19:39:58.000000 ./usr/share/doc/libpqxx-doc/html/a00020_source.html\n+-rw-r--r-- 0 root (0) root (0) 17615 2024-02-28 19:39:58.000000 ./usr/share/doc/libpqxx-doc/html/a00023_source.html\n+-rw-r--r-- 0 root (0) root (0) 60709 2024-02-28 19:39:58.000000 ./usr/share/doc/libpqxx-doc/html/a00026_source.html\n+-rw-r--r-- 0 root (0) root (0) 3609 2024-02-28 19:39:58.000000 ./usr/share/doc/libpqxx-doc/html/a00029_source.html\n+-rw-r--r-- 0 root (0) root (0) 31542 2024-02-28 19:39:58.000000 ./usr/share/doc/libpqxx-doc/html/a00032_source.html\n+-rw-r--r-- 0 root (0) root (0) 73883 2024-02-28 19:39:58.000000 ./usr/share/doc/libpqxx-doc/html/a00035_source.html\n+-rw-r--r-- 0 root (0) root (0) 12101 2024-02-28 19:39:58.000000 ./usr/share/doc/libpqxx-doc/html/a00038_source.html\n+-rw-r--r-- 0 root (0) root (0) 115169 2024-02-28 19:39:58.000000 ./usr/share/doc/libpqxx-doc/html/a00041_source.html\n+-rw-r--r-- 0 root (0) root (0) 4546 2024-02-28 19:39:58.000000 ./usr/share/doc/libpqxx-doc/html/a00044_source.html\n+-rw-r--r-- 0 root (0) root (0) 144300 2024-02-28 19:39:58.000000 ./usr/share/doc/libpqxx-doc/html/a00047_source.html\n+-rw-r--r-- 0 root (0) root (0) 4221 2024-02-28 19:39:58.000000 ./usr/share/doc/libpqxx-doc/html/a00050_source.html\n+-rw-r--r-- 0 root (0) root (0) 11715 2024-02-28 19:39:58.000000 ./usr/share/doc/libpqxx-doc/html/a00053_source.html\n+-rw-r--r-- 0 root (0) root (0) 3659 2024-02-28 19:39:58.000000 ./usr/share/doc/libpqxx-doc/html/a00056_source.html\n+-rw-r--r-- 0 root (0) root (0) 110355 2024-02-28 19:39:58.000000 ./usr/share/doc/libpqxx-doc/html/a00059_source.html\n+-rw-r--r-- 0 root (0) root (0) 35409 2024-02-28 19:39:58.000000 ./usr/share/doc/libpqxx-doc/html/a00062_source.html\n+-rw-r--r-- 0 root (0) root (0) 137425 2024-02-28 19:39:58.000000 ./usr/share/doc/libpqxx-doc/html/a00065_source.html\n+-rw-r--r-- 0 root (0) root (0) 19201 2024-02-28 19:39:58.000000 ./usr/share/doc/libpqxx-doc/html/a00068_source.html\n+-rw-r--r-- 0 root (0) root (0) 4789 2024-02-28 19:39:58.000000 ./usr/share/doc/libpqxx-doc/html/a00071_source.html\n+-rw-r--r-- 0 root (0) root (0) 16864 2024-02-28 19:39:58.000000 ./usr/share/doc/libpqxx-doc/html/a00074_source.html\n+-rw-r--r-- 0 root (0) root (0) 19625 2024-02-28 19:39:58.000000 ./usr/share/doc/libpqxx-doc/html/a00077_source.html\n+-rw-r--r-- 0 root (0) root (0) 91868 2024-02-28 19:39:58.000000 ./usr/share/doc/libpqxx-doc/html/a00080_source.html\n -rw-r--r-- 0 root (0) root (0) 16501 2024-02-28 19:39:58.000000 ./usr/share/doc/libpqxx-doc/html/a00083_source.html\n--rw-r--r-- 0 root (0) root (0) 25867 2024-02-28 19:39:58.000000 ./usr/share/doc/libpqxx-doc/html/a00086_source.html\n+-rw-r--r-- 0 root (0) root (0) 8440 2024-02-28 19:39:58.000000 ./usr/share/doc/libpqxx-doc/html/a00086_source.html\n -rw-r--r-- 0 root (0) root (0) 26859 2024-02-28 19:39:58.000000 ./usr/share/doc/libpqxx-doc/html/a00089_source.html\n--rw-r--r-- 0 root (0) root (0) 59524 2024-02-28 19:39:58.000000 ./usr/share/doc/libpqxx-doc/html/a00092_source.html\n--rw-r--r-- 0 root (0) root (0) 110355 2024-02-28 19:39:58.000000 ./usr/share/doc/libpqxx-doc/html/a00095_source.html\n--rw-r--r-- 0 root (0) root (0) 31542 2024-02-28 19:39:58.000000 ./usr/share/doc/libpqxx-doc/html/a00098_source.html\n--rw-r--r-- 0 root (0) root (0) 16864 2024-02-28 19:39:58.000000 ./usr/share/doc/libpqxx-doc/html/a00101_source.html\n--rw-r--r-- 0 root (0) root (0) 73883 2024-02-28 19:39:58.000000 ./usr/share/doc/libpqxx-doc/html/a00104_source.html\n--rw-r--r-- 0 root (0) root (0) 4789 2024-02-28 19:39:58.000000 ./usr/share/doc/libpqxx-doc/html/a00107_source.html\n--rw-r--r-- 0 root (0) root (0) 29095 2024-02-28 19:39:58.000000 ./usr/share/doc/libpqxx-doc/html/a00110_source.html\n--rw-r--r-- 0 root (0) root (0) 11715 2024-02-28 19:39:58.000000 ./usr/share/doc/libpqxx-doc/html/a00113_source.html\n--rw-r--r-- 0 root (0) root (0) 12101 2024-02-28 19:39:58.000000 ./usr/share/doc/libpqxx-doc/html/a00116_source.html\n--rw-r--r-- 0 root (0) root (0) 12552 2024-02-28 19:39:58.000000 ./usr/share/doc/libpqxx-doc/html/a00119_source.html\n--rw-r--r-- 0 root (0) root (0) 7709 2024-02-28 19:39:58.000000 ./usr/share/doc/libpqxx-doc/html/a00221_source.html\n+-rw-r--r-- 0 root (0) root (0) 84065 2024-02-28 19:39:58.000000 ./usr/share/doc/libpqxx-doc/html/a00092_source.html\n+-rw-r--r-- 0 root (0) root (0) 14410 2024-02-28 19:39:58.000000 ./usr/share/doc/libpqxx-doc/html/a00095_source.html\n+-rw-r--r-- 0 root (0) root (0) 115762 2024-02-28 19:39:58.000000 ./usr/share/doc/libpqxx-doc/html/a00098_source.html\n+-rw-r--r-- 0 root (0) root (0) 12125 2024-02-28 19:39:58.000000 ./usr/share/doc/libpqxx-doc/html/a00101_source.html\n+-rw-r--r-- 0 root (0) root (0) 12552 2024-02-28 19:39:58.000000 ./usr/share/doc/libpqxx-doc/html/a00104_source.html\n+-rw-r--r-- 0 root (0) root (0) 59524 2024-02-28 19:39:58.000000 ./usr/share/doc/libpqxx-doc/html/a00107_source.html\n+-rw-r--r-- 0 root (0) root (0) 12205 2024-02-28 19:39:58.000000 ./usr/share/doc/libpqxx-doc/html/a00110_source.html\n+-rw-r--r-- 0 root (0) root (0) 25736 2024-02-28 19:39:58.000000 ./usr/share/doc/libpqxx-doc/html/a00113_source.html\n+-rw-r--r-- 0 root (0) root (0) 57531 2024-02-28 19:39:58.000000 ./usr/share/doc/libpqxx-doc/html/a00116_source.html\n+-rw-r--r-- 0 root (0) root (0) 29095 2024-02-28 19:39:58.000000 ./usr/share/doc/libpqxx-doc/html/a00119_source.html\n+-rw-r--r-- 0 root (0) root (0) 7709 2024-02-28 19:39:58.000000 ./usr/share/doc/libpqxx-doc/html/a00191_source.html\n -rw-r--r-- 0 root (0) root (0) 17165 2024-02-28 19:39:58.000000 ./usr/share/doc/libpqxx-doc/html/a00239.html\n -rw-r--r-- 0 root (0) root (0) 5619 2024-02-28 19:39:58.000000 ./usr/share/doc/libpqxx-doc/html/a00240.html\n -rw-r--r-- 0 root (0) root (0) 3091 2024-02-28 19:39:58.000000 ./usr/share/doc/libpqxx-doc/html/a00240.js\n -rw-r--r-- 0 root (0) root (0) 2780 2024-02-28 19:39:58.000000 ./usr/share/doc/libpqxx-doc/html/a00241.html\n -rw-r--r-- 0 root (0) root (0) 4284 2024-02-28 19:39:58.000000 ./usr/share/doc/libpqxx-doc/html/a00242.html\n -rw-r--r-- 0 root (0) root (0) 6079 2024-02-28 19:39:58.000000 ./usr/share/doc/libpqxx-doc/html/a00243.html\n -rw-r--r-- 0 root (0) root (0) 6050 2024-02-28 19:39:58.000000 ./usr/share/doc/libpqxx-doc/html/a00243.js\n"}, {"source1": "./usr/share/doc/libpqxx-doc/html/a00002_source.html", "source2": "./usr/share/doc/libpqxx-doc/html/a00002_source.html", "unified_diff": "@@ -1,15 +1,15 @@\n \n \n \n \n \n \n \n-libpqxx: blob.hxx Source File\n+libpqxx: stream_from.hxx Source File\n \n \n \n \n \n \n \n@@ -60,233 +60,310 @@\n \n
\n
\n-
blob.hxx
\n+
stream_from.hxx
\n
\n
\n-
1/* Binary Large Objects interface.
\n+
1/* Definition of the pqxx::stream_from class.
\n
2 *
\n-
3 * Read or write large objects, stored in their own storage on the server.
\n+
3 * pqxx::stream_from enables optimized batch reads from a database table.
\n
4 *
\n-
5 * DO NOT INCLUDE THIS FILE DIRECTLY; include pqxx/largeobject instead.
\n+
5 * DO NOT INCLUDE THIS FILE DIRECTLY; include pqxx/stream_from instead.
\n
6 *
\n
7 * Copyright (c) 2000-2023, Jeroen T. Vermeulen.
\n
8 *
\n
9 * See COPYING for copyright license. If you did not receive a file called
\n
10 * COPYING with this source code, please notify the distributor of this
\n
11 * mistake, or contact the author.
\n
12 */
\n-
13#ifndef PQXX_H_BLOB
\n-
14#define PQXX_H_BLOB
\n+
13#ifndef PQXX_H_STREAM_FROM
\n+
14#define PQXX_H_STREAM_FROM
\n
15
\n
16#if !defined(PQXX_HEADER_PRE)
\n
17# error "Include libpqxx headers as <pqxx/header>, not <pqxx/header.hxx>."
\n
18#endif
\n
19
\n-
20#include <cstdint>
\n-
21
\n-
22#if defined(PQXX_HAVE_PATH)
\n-
23# include <filesystem>
\n-
24#endif
\n-
25
\n-
26#if defined(PQXX_HAVE_RANGES) && __has_include(<ranges>)
\n-
27# include <ranges>
\n-
28#endif
\n-
29
\n-
30#if defined(PQXX_HAVE_SPAN) && __has_include(<span>)
\n-
31# include <span>
\n-
32#endif
\n-
33
\n-
34#include "pqxx/dbtransaction.hxx"
\n+
20#include <cassert>
\n+
21#include <variant>
\n+
22
\n+
23#include "pqxx/connection.hxx"
\n+
24#include "pqxx/except.hxx"
\n+
25#include "pqxx/internal/concat.hxx"
\n+
26#include "pqxx/internal/encoding_group.hxx"
\n+
27#include "pqxx/internal/stream_iterator.hxx"
\n+
28#include "pqxx/separated_list.hxx"
\n+
29#include "pqxx/transaction_focus.hxx"
\n+
30
\n+
31
\n+
32namespace pqxx
\n+
33{
\n+
34class transaction_base;
\n
35
\n
36
\n-
37namespace pqxx
\n-
38{
\n-
\n-
52class PQXX_LIBEXPORT blob
\n-
53{
\n-
54public:
\n-
56
\n-
60 [[nodiscard]] static oid create(dbtransaction &, oid = 0);
\n-
61
\n-
63 static void remove(dbtransaction &, oid);
\n-
64
\n-
66 [[nodiscard]] static blob open_r(dbtransaction &, oid);
\n-
67 // Open blob for writing. Any attempt to read from it will fail.
\n-
68 [[nodiscard]] static blob open_w(dbtransaction &, oid);
\n-
69 // Open blob for reading and/or writing.
\n-
70 [[nodiscard]] static blob open_rw(dbtransaction &, oid);
\n-
71
\n-
73
\n-
76 blob() = default;
\n-
77
\n-
79 blob(blob &&);
\n-
81 blob &operator=(blob &&);
\n-
82
\n-
83 blob(blob const &) = delete;
\n-
84 blob &operator=(blob const &) = delete;
\n-
85 ~blob();
\n+
38
\n+\n+
42
\n+\n+
45
\n+
46
\n+
48
\n+
\n+
78class PQXX_LIBEXPORT stream_from : transaction_focus
\n+
79{
\n+
80public:
\n+
81 using raw_line =
\n+
82 std::pair<std::unique_ptr<char, void (*)(void const *)>, std::size_t>;
\n+
83
\n+\n+\n
86
\n
88
\n-
94 static constexpr std::size_t chunk_limit = 0x7fffffff;
\n-
95
\n-
97
\n-
105 std::size_t read(std::basic_string<std::byte> &buf, std::size_t size);
\n-
106
\n-
107#if defined(PQXX_HAVE_SPAN)
\n-
109
\n-
114 template<std::size_t extent = std::dynamic_extent>
\n-
115 std::span<std::byte> read(std::span<std::byte, extent> buf)
\n-
116 {
\n-
117 return buf.subspan(0, raw_read(std::data(buf), std::size(buf)));
\n-
118 }
\n-
119#endif // PQXX_HAVE_SPAN
\n-
120
\n-
121#if defined(PQXX_HAVE_CONCEPTS) && defined(PQXX_HAVE_SPAN)
\n-
123
\n-
128 template<binary DATA> std::span<std::byte> read(DATA &buf)
\n-
129 {
\n-
130 return {std::data(buf), raw_read(std::data(buf), std::size(buf))};
\n-
131 }
\n-
132#else // PQXX_HAVE_CONCEPTS && PQXX_HAVE_SPAN
\n-
134
\n-
146 template<typename ALLOC>
\n-
\n-
147 std::basic_string_view<std::byte> read(std::vector<std::byte, ALLOC> &buf)
\n-
148 {
\n-
149 return {std::data(buf), raw_read(std::data(buf), std::size(buf))};
\n-
150 }
\n+
97 [[deprecated("Use transaction_base::stream instead.")]] static stream_from
\n+
\n+
98 query(transaction_base &tx, std::string_view q)
\n+
99 {
\n+
100#include "pqxx/internal/ignore-deprecated-pre.hxx"
\n+
101 return {tx, from_query, q};
\n+
102#include "pqxx/internal/ignore-deprecated-post.hxx"
\n+
103 }
\n
\n-
151#endif // PQXX_HAVE_CONCEPTS && PQXX_HAVE_SPAN
\n+
104
\n+
115
\n+
117
\n+
133 [[deprecated("Use transaction_base::stream instead.")]] static stream_from
\n+
134 raw_table(
\n+
135 transaction_base &tx, std::string_view path,
\n+
136 std::string_view columns = ""sv);
\n+
137
\n+
139
\n+
141 [[deprecated("Use transaction_base::stream instead.")]] static stream_from
\n+
142 table(
\n+\n+
144 std::initializer_list<std::string_view> columns = {});
\n+
146
\n+
148
\n+
150 [[deprecated("Use transaction_base::stream instead.")]] stream_from(
\n+
151 transaction_base &, from_query_t, std::string_view query);
\n
152
\n-
153#if defined(PQXX_HAVE_CONCEPTS)
\n-
155
\n-
173 template<binary DATA> void write(DATA const &data)
\n-
174 {
\n-
175 raw_write(std::data(data), std::size(data));
\n-
176 }
\n-
177#else
\n-
179
\n-
\n-
197 template<typename DATA> void write(DATA const &data)
\n-
198 {
\n-
199 raw_write(std::data(data), std::size(data));
\n-
200 }
\n-
\n-
201#endif
\n-
202
\n-
204
\n-
210 void resize(std::int64_t size);
\n-
211
\n-
213 [[nodiscard]] std::int64_t tell() const;
\n-
214
\n-
216
\n-
217 std::int64_t seek_abs(std::int64_t offset = 0);
\n+
154
\n+
156 [[deprecated("Use transaction_base::stream instead.")]] stream_from(
\n+
157 transaction_base &, from_table_t, std::string_view table);
\n+
158
\n+
160
\n+
162 template<typename Iter>
\n+
163 [[deprecated("Use transaction_base::stream instead.")]] stream_from(
\n+
164 transaction_base &, from_table_t, std::string_view table,
\n+
165 Iter columns_begin, Iter columns_end);
\n+
166
\n+
168
\n+
170 template<typename Columns>
\n+
171 [[deprecated("Use transaction_base::stream() instead.")]] stream_from(
\n+
172 transaction_base &tx, from_table_t, std::string_view table,
\n+
173 Columns const &columns);
\n+
174
\n+
175#include "pqxx/internal/ignore-deprecated-pre.hxx"
\n+
\n+
177 [[deprecated("Use transaction_base::stream instead.")]] stream_from(
\n+
178 transaction_base &tx, std::string_view table) :
\n+
179 stream_from{tx, from_table, table}
\n+
180 {}
\n+
\n+
181#include "pqxx/internal/ignore-deprecated-post.hxx"
\n+
182
\n+
184 template<typename Columns>
\n+
\n+
185 [[deprecated("Use transaction_base::stream instead.")]] stream_from(
\n+
186 transaction_base &tx, std::string_view table, Columns const &columns) :
\n+
187 stream_from{tx, from_table, table, columns}
\n+
188 {}
\n+
\n+
189
\n+
191 template<typename Iter>
\n+
192 [[deprecated("Use transaction_base::stream instead.")]] stream_from(
\n+
193 transaction_base &, std::string_view table, Iter columns_begin,
\n+
194 Iter columns_end);
\n+
195
\n+
196 ~stream_from() noexcept;
\n+
197
\n+
\n+
199 [[nodiscard]] constexpr operator bool() const noexcept
\n+
200 {
\n+
201 return not m_finished;
\n+
202 }
\n+
\n+
\n+
204 [[nodiscard]] constexpr bool operator!() const noexcept
\n+
205 {
\n+
206 return m_finished;
\n+
207 }
\n+
\n+
208
\n+
210
\n+
216 void complete();
\n+
217
\n
219
\n-
223 std::int64_t seek_rel(std::int64_t offset = 0);
\n-
225
\n-
229 std::int64_t seek_end(std::int64_t offset = 0);
\n-
230
\n-
232
\n-
235 static oid from_buf(
\n-
236 dbtransaction &tx, std::basic_string_view<std::byte> data, oid id = 0);
\n-
237
\n-
239
\n-
241 static void append_from_buf(
\n-
242 dbtransaction &tx, std::basic_string_view<std::byte> data, oid id);
\n+
226 template<typename Tuple> stream_from &operator>>(Tuple &);
\n+
227
\n+
229 template<typename... Vs>
\n+
230 stream_from &operator>>(std::variant<Vs...> &) = delete;
\n+
231
\n+
233
\n+
\n+
237 template<typename... TYPE> [[nodiscard]] auto iter() &
\n+
238 {
\n+
239 return pqxx::internal::stream_input_iteration<TYPE...>{*this};
\n+
240 }
\n+
\n+
241
\n
243
\n-
245 [[nodiscard]] static oid from_file(dbtransaction &, char const path[]);
\n-
246
\n-
247#if defined(PQXX_HAVE_PATH) && !defined(_WIN32)
\n-
249
\n-
252 [[nodiscard]] static oid
\n-
253 from_file(dbtransaction &tx, std::filesystem::path const &path)
\n-
254 {
\n-
255 return from_file(tx, path.c_str());
\n-
256 }
\n-
257#endif
\n-
258
\n+
259 std::vector<zview> const *read_row() &;
\n
260
\n-
263 static oid from_file(dbtransaction &, char const path[], oid);
\n+
262
\n+
263 raw_line get_raw_line();
\n
264
\n-
265#if defined(PQXX_HAVE_PATH) && !defined(_WIN32)
\n-
267
\n-
273 static oid
\n-
274 from_file(dbtransaction &tx, std::filesystem::path const &path, oid id)
\n-
275 {
\n-
276 return from_file(tx, path.c_str(), id);
\n-
277 }
\n-
278#endif
\n-
279
\n-
281
\n-
284 static void to_buf(
\n-
285 dbtransaction &, oid, std::basic_string<std::byte> &,
\n-
286 std::size_t max_size);
\n-
287
\n-
289
\n-
295 static std::size_t append_to_buf(
\n-
296 dbtransaction &tx, oid id, std::int64_t offset,
\n-
297 std::basic_string<std::byte> &buf, std::size_t append_max);
\n+
265private:
\n+
266 // TODO: Clean up this signature once we cull the deprecated constructors.
\n+\n+
269 transaction_base &tx, std::string_view table, std::string_view columns,
\n+\n+
271
\n+
272 // TODO: Clean up this signature once we cull the deprecated constructors.
\n+\n+
275 transaction_base &, std::string_view unquoted_table,
\n+
276 std::string_view columns, from_table_t, int);
\n+
277
\n+
278 template<typename Tuple, std::size_t... indexes>
\n+
279 void extract_fields(Tuple &t, std::index_sequence<indexes...>) const
\n+
280 {
\n+
281 (extract_value<Tuple, indexes>(t), ...);
\n+
282 }
\n+
283
\n+
284 pqxx::internal::char_finder_func *m_char_finder;
\n+
285
\n+
287 std::string m_row;
\n+
288
\n+
290 std::vector<zview> m_fields;
\n+
291
\n+
292 bool m_finished = false;
\n+
293
\n+
294 void close();
\n+
295
\n+
296 template<typename Tuple, std::size_t index>
\n+
297 void extract_value(Tuple &) const;
\n
298
\n-
300 static void to_file(dbtransaction &, oid, char const path[]);
\n-
301
\n-
302#if defined(PQXX_HAVE_PATH) && !defined(_WIN32)
\n-
304
\n-
307 static void
\n-
308 to_file(dbtransaction &tx, oid id, std::filesystem::path const &path)
\n-
309 {
\n-
310 to_file(tx, id, path.c_str());
\n-
311 }
\n-
312#endif
\n-
313
\n-
315
\n-
326 void close();
\n-
327
\n-
328private:
\n-
329 PQXX_PRIVATE blob(connection &conn, int fd) noexcept :
\n-
330 m_conn{&conn}, m_fd{fd}
\n-
331 {}
\n-
332 static PQXX_PRIVATE blob open_internal(dbtransaction &, oid, int);
\n-
333 static PQXX_PRIVATE pqxx::internal::pq::PGconn *
\n-
334 raw_conn(pqxx::connection *) noexcept;
\n-
335 static PQXX_PRIVATE pqxx::internal::pq::PGconn *
\n-
336 raw_conn(pqxx::dbtransaction const &) noexcept;
\n-
337 static PQXX_PRIVATE std::string errmsg(connection const *);
\n-
338 static PQXX_PRIVATE std::string errmsg(dbtransaction const &tx)
\n-
339 {
\n-
340 return errmsg(&tx.conn());
\n-
341 }
\n-
342 PQXX_PRIVATE std::string errmsg() const { return errmsg(m_conn); }
\n-
343 PQXX_PRIVATE std::int64_t seek(std::int64_t offset, int whence);
\n-
344 std::size_t raw_read(std::byte buf[], std::size_t size);
\n-
345 void raw_write(std::byte const buf[], std::size_t size);
\n-
346
\n-
347 connection *m_conn = nullptr;
\n-
348 int m_fd = -1;
\n-
349};
\n+
300 void parse_line();
\n+
301};
\n+
\n+
302
\n+
303
\n+
304template<typename Columns>
\n+
\n+\n+
306 transaction_base &tx, from_table_t, std::string_view table_name,
\n+
307 Columns const &columns) :
\n+\n+
309 tx, from_table, table_name, std::begin(columns), std::end(columns)}
\n+
310{}
\n+
\n+
311
\n+
312
\n+
313template<typename Iter>
\n+
\n+\n+
315 transaction_base &tx, from_table_t, std::string_view table,
\n+
316 Iter columns_begin, Iter columns_end) :
\n+\n+
318 tx, table, separated_list(",", columns_begin, columns_end),
\n+
319 from_table, 1}
\n+
320{}
\n+
\n+
321
\n+
322
\n+
\n+
323template<typename Tuple> inline stream_from &stream_from::operator>>(Tuple &t)
\n+
324{
\n+
325 if (m_finished)
\n+
326 PQXX_UNLIKELY return *this;
\n+
327 static constexpr auto tup_size{std::tuple_size_v<Tuple>};
\n+
328 m_fields.reserve(tup_size);
\n+
329 parse_line();
\n+
330 if (m_finished)
\n+
331 PQXX_UNLIKELY return *this;
\n+
332
\n+
333 if (std::size(m_fields) != tup_size)
\n+
334 throw usage_error{internal::concat(
\n+
335 "Tried to extract ", tup_size, " field(s) from a stream of ",
\n+
336 std::size(m_fields), ".")};
\n+
337
\n+
338 extract_fields(t, std::make_index_sequence<tup_size>{});
\n+
339 return *this;
\n+
340}
\n
\n-
350} // namespace pqxx
\n-
351#endif
\n+
341
\n+
342
\n+
343template<typename Tuple, std::size_t index>
\n+
344inline void stream_from::extract_value(Tuple &t) const
\n+
345{
\n+
346 using field_type = strip_t<decltype(std::get<index>(t))>;
\n+
347 using nullity = nullness<field_type>;
\n+
348 assert(index < std::size(m_fields));
\n+
349 if constexpr (nullity::always_null)
\n+
350 {
\n+
351 if (std::data(m_fields[index]) != nullptr)
\n+
352 throw conversion_error{"Streaming non-null value into null field."};
\n+
353 }
\n+
354 else if (std::data(m_fields[index]) == nullptr)
\n+
355 {
\n+
356 if constexpr (nullity::has_null)
\n+
357 std::get<index>(t) = nullity::null();
\n+
358 else
\n+
359 internal::throw_null_conversion(type_name<field_type>);
\n+
360 }
\n+
361 else
\n+
362 {
\n+
363 // Don't ever try to convert a non-null value to nullptr_t!
\n+
364 std::get<index>(t) = from_string<field_type>(m_fields[index]);
\n+
365 }
\n+
366}
\n+
367} // namespace pqxx
\n+
368#endif
\n
The home of all libpqxx classes, functions, templates, etc.
Definition array.hxx:33
\n-
Definition blob.hxx:53
\n-
void write(DATA const &data)
Write data large object, at the current position.
Definition blob.hxx:197
\n-
blob(blob const &)=delete
\n-
blob()=default
You can default-construct a blob, but it won't do anything useful.
\n-
std::basic_string_view< std::byte > read(std::vector< std::byte, ALLOC > &buf)
Read up to std::size(buf) bytes from the object.
Definition blob.hxx:147
\n-
blob & operator=(blob const &)=delete
\n-
Connection to a database.
Definition connection.hxx:253
\n-
Abstract transaction base class: bracket transactions on the database.
Definition dbtransaction.hxx:54
\n+
std::string separated_list(std::string_view sep, ITER begin, ITER end, ACCESS access)
Represent sequence of values as a string, joined by a given separator.
Definition separated_list.hxx:44
\n+
std::remove_cv_t< std::remove_reference_t< TYPE > > strip_t
Remove any constness, volatile, and reference-ness from a type.
Definition types.hxx:91
\n+
constexpr from_query_t from_query
Pass this to a stream_from constructor to stream query results.
Definition stream_from.hxx:44
\n+
constexpr from_table_t from_table
Pass this to a stream_from constructor to stream table contents.
Definition stream_from.hxx:40
\n+
std::initializer_list< std::string_view > table_path
Representation of a PostgreSQL table path.
Definition connection.hxx:188
\n+
void PQXX_COLD throw_null_conversion(std::string const &type)
Definition strconv.cxx:253
\n+
Error in usage of libpqxx library, similar to std::logic_error.
Definition except.hxx:249
\n+
Value conversion failed, e.g. when converting "Hello" to int.
Definition except.hxx:283
\n+
Traits describing a type's "null value," if any.
Definition strconv.hxx:93
\n+
Stream data from the database.
Definition stream_from.hxx:79
\n+
static stream_from query(transaction_base &tx, std::string_view q)
Factory: Execute query, and stream the results.
Definition stream_from.hxx:98
\n+
stream_from & operator>>(std::variant< Vs... > &)=delete
Doing this with a std::variant is going to be horrifically borked.
\n+
stream_from & operator>>(Tuple &)
Read one row into a tuple.
Definition stream_from.hxx:323
\n+
stream_from(transaction_base &tx, std::string_view table, Columns const &columns)
Definition stream_from.hxx:185
\n+
std::pair< std::unique_ptr< char, void(*)(void const *)>, std::size_t > raw_line
Definition stream_from.hxx:82
\n+
stream_from(stream_from &&)=delete
\n+
stream_from(transaction_base &, std::string_view table, Iter columns_begin, Iter columns_end)
\n+
stream_from & operator=(stream_from &&)=delete
\n+
stream_from(transaction_base &tx, std::string_view table)
Definition stream_from.hxx:177
\n+
auto iter() &
Iterate over this stream. Supports range-based "for" loops.
Definition stream_from.hxx:237
\n+
constexpr bool operator!() const noexcept
Has this stream produced all the data it is going to produce?
Definition stream_from.hxx:204
\n+
Interface definition (and common code) for "transaction" classes.
Definition transaction_base.hxx:88
\n+
Base class for things that monopolise a transaction's attention.
Definition transaction_focus.hxx:29
\n+
Marker for stream_from constructors: "stream from table.".
Definition types.hxx:68
\n+
Marker for stream_from constructors: "stream from query.".
Definition types.hxx:74
\n
\n
\n \n
\n \n
\n \n \n", "details": [{"source1": "html2text {}", "source2": "html2text {}", "unified_diff": "@@ -1,235 +1,344 @@\n \n \n \n \n \n libpqxx\u00a07.8.1\n \n-blob.hxx\n- 1/* Binary Large Objects interface.\n+stream_from.hxx\n+ 1/* Definition of the pqxx::stream_from class.\n 2 *\n- 3 * Read or write large objects, stored in their own storage on the server.\n+ 3 * pqxx::stream_from enables optimized batch reads from a database table.\n 4 *\n- 5 * DO NOT INCLUDE THIS FILE DIRECTLY; include pqxx/largeobject instead.\n+ 5 * DO NOT INCLUDE THIS FILE DIRECTLY; include pqxx/stream_from instead.\n 6 *\n 7 * Copyright (c) 2000-2023, Jeroen T. Vermeulen.\n 8 *\n 9 * See COPYING for copyright license. If you did not receive a file called\n 10 * COPYING with this source code, please notify the distributor of this\n 11 * mistake, or contact the author.\n 12 */\n- 13#ifndef PQXX_H_BLOB\n- 14#define PQXX_H_BLOB\n+ 13#ifndef PQXX_H_STREAM_FROM\n+ 14#define PQXX_H_STREAM_FROM\n 15\n 16#if !defined(PQXX_HEADER_PRE)\n 17# error \"Include libpqxx headers as , not .\"\n 18#endif\n 19\n- 20#include \n- 21\n- 22#if defined(PQXX_HAVE_PATH)\n- 23# include \n- 24#endif\n- 25\n- 26#if defined(PQXX_HAVE_RANGES) && __has_include()\n- 27# include \n- 28#endif\n- 29\n- 30#if defined(PQXX_HAVE_SPAN) && __has_include()\n- 31# include \n- 32#endif\n- 33\n- 34#include \"pqxx/dbtransaction.hxx\"\n+ 20#include \n+ 21#include \n+ 22\n+ 23#include \"pqxx/connection.hxx\"\n+ 24#include \"pqxx/except.hxx\"\n+ 25#include \"pqxx/internal/concat.hxx\"\n+ 26#include \"pqxx/internal/encoding_group.hxx\"\n+ 27#include \"pqxx/internal/stream_iterator.hxx\"\n+ 28#include \"pqxx/separated_list.hxx\"\n+ 29#include \"pqxx/transaction_focus.hxx\"\n+ 30\n+ 31\n+ 32namespace pqxx\n+ 33{\n+ 34class transaction_base;\n 35\n 36\n- 37namespace pqxx\n- 38{\n-52class PQXX_LIBEXPORT blob\n- 53{\n- 54public:\n- 56\n- 60 [[nodiscard]] static oid create(dbtransaction &, oid = 0);\n- 61\n- 63 static void remove(dbtransaction &, oid);\n- 64\n- 66 [[nodiscard]] static blob open_r(dbtransaction &, oid);\n- 67 // Open blob for writing. Any attempt to read from it will fail.\n- 68 [[nodiscard]] static blob open_w(dbtransaction &, oid);\n- 69 // Open blob for reading and/or writing.\n- 70 [[nodiscard]] static blob open_rw(dbtransaction &, oid);\n- 71\n- 73\n-76 blob() = default;\n- 77\n- 79 blob(blob &&);\n- 81 blob &operator=(blob &&);\n- 82\n-83 blob(blob const &) = delete;\n-84 blob &operator=(blob const &) = delete;\n- 85 ~blob();\n+ 38\n+40constexpr from_table_t from_table;\n+ 42\n+44constexpr from_query_t from_query;\n+ 45\n+ 46\n+ 48\n+78class PQXX_LIBEXPORT stream_from : transaction_focus\n+ 79{\n+ 80public:\n+81 using raw_line =\n+ 82 std::pair, std::size_t>;\n+ 83\n+84 stream_from(stream_from &&) = delete;\n+85 stream_from &operator=(stream_from &&) = delete;\n 86\n 88\n-94 static constexpr std::size_t chunk_limit = 0x7fffffff;\n- 95\n- 97\n- 105 std::size_t read(std::basic_string &buf, std::size_t size);\n- 106\n- 107#if defined(PQXX_HAVE_SPAN)\n- 109\n- 114 template\n- 115 std::span read(std::span buf)\n- 116 {\n- 117 return buf.subspan(0, raw_read(std::data(buf), std::size(buf)));\n- 118 }\n- 119#endif // PQXX_HAVE_SPAN\n- 120\n- 121#if defined(PQXX_HAVE_CONCEPTS) && defined(PQXX_HAVE_SPAN)\n- 123\n- 128 template std::span read(DATA &buf)\n- 129 {\n- 130 return {std::data(buf), raw_read(std::data(buf), std::size(buf))};\n- 131 }\n- 132#else // PQXX_HAVE_CONCEPTS && PQXX_HAVE_SPAN\n- 134\n- 146 template\n-147 std::basic_string_view read(std::vector &buf)\n- 148 {\n- 149 return {std::data(buf), raw_read(std::data(buf), std::size(buf))};\n- 150 }\n- 151#endif // PQXX_HAVE_CONCEPTS && PQXX_HAVE_SPAN\n+ 97 [[deprecated(\"Use transaction_base::stream instead.\")]] static stream_from\n+98 query(transaction_base &tx, std::string_view q)\n+ 99 {\n+ 100#include \"pqxx/internal/ignore-deprecated-pre.hxx\"\n+ 101 return {tx, from_query, q};\n+ 102#include \"pqxx/internal/ignore-deprecated-post.hxx\"\n+ 103 }\n+ 104\n+ 115\n+ 117\n+ 133 [[deprecated(\"Use transaction_base::stream instead.\")]] static stream_from\n+ 134 raw_table(\n+ 135 transaction_base &tx, std::string_view path,\n+ 136 std::string_view columns = \"\"sv);\n+ 137\n+ 139\n+ 141 [[deprecated(\"Use transaction_base::stream instead.\")]] static stream_from\n+ 142 table(\n+ 143 transaction_base &tx, table_path path,\n+ 144 std::initializer_list columns = {});\n+ 146\n+ 148\n+ 150 [[deprecated(\"Use transaction_base::stream instead.\")]] stream_from(\n+ 151 transaction_base &, from_query_t, std::string_view query);\n 152\n- 153#if defined(PQXX_HAVE_CONCEPTS)\n- 155\n- 173 template void write(DATA const &data)\n- 174 {\n- 175 raw_write(std::data(data), std::size(data));\n- 176 }\n- 177#else\n- 179\n-197 template void write(DATA const &data)\n- 198 {\n- 199 raw_write(std::data(data), std::size(data));\n- 200 }\n- 201#endif\n- 202\n- 204\n- 210 void resize(std::int64_t size);\n- 211\n- 213 [[nodiscard]] std::int64_t tell() const;\n- 214\n- 216\n- 217 std::int64_t seek_abs(std::int64_t offset = 0);\n+ 154\n+ 156 [[deprecated(\"Use transaction_base::stream instead.\")]] stream_from(\n+ 157 transaction_base &, from_table_t, std::string_view table);\n+ 158\n+ 160\n+ 162 template\n+ 163 [[deprecated(\"Use transaction_base::stream instead.\")]] stream_from(\n+ 164 transaction_base &, from_table_t, std::string_view table,\n+ 165 Iter columns_begin, Iter columns_end);\n+ 166\n+ 168\n+ 170 template\n+ 171 [[deprecated(\"Use transaction_base::stream() instead.\")]] stream_from(\n+ 172 transaction_base &tx, from_table_t, std::string_view table,\n+ 173 Columns const &columns);\n+ 174\n+ 175#include \"pqxx/internal/ignore-deprecated-pre.hxx\"\n+177 [[deprecated(\"Use transaction_base::stream instead.\")]] stream_from(\n+ 178 transaction_base &tx, std::string_view table) :\n+ 179 stream_from{tx, from_table, table}\n+ 180 {}\n+ 181#include \"pqxx/internal/ignore-deprecated-post.hxx\"\n+ 182\n+ 184 template\n+185 [[deprecated(\"Use transaction_base::stream instead.\")]] stream_from(\n+ 186 transaction_base &tx, std::string_view table, Columns const &columns) :\n+ 187 stream_from{tx, from_table, table, columns}\n+ 188 {}\n+ 189\n+ 191 template\n+192 [[deprecated(\"Use transaction_base::stream instead.\")]] stream_from(\n+ 193 transaction_base &, std::string_view table, Iter columns_begin,\n+ 194 Iter columns_end);\n+ 195\n+ 196 ~stream_from() noexcept;\n+ 197\n+199 [[nodiscard]] constexpr operator bool() const noexcept\n+ 200 {\n+ 201 return not m_finished;\n+ 202 }\n+204 [[nodiscard]] constexpr bool operator!() const noexcept\n+ 205 {\n+ 206 return m_finished;\n+ 207 }\n+ 208\n+ 210\n+ 216 void complete();\n+ 217\n 219\n- 223 std::int64_t seek_rel(std::int64_t offset = 0);\n- 225\n- 229 std::int64_t seek_end(std::int64_t offset = 0);\n- 230\n- 232\n- 235 static oid from_buf(\n- 236 dbtransaction &tx, std::basic_string_view data, oid id = 0);\n- 237\n- 239\n- 241 static void append_from_buf(\n- 242 dbtransaction &tx, std::basic_string_view data, oid id);\n+ 226 template stream_from &operator>>(Tuple &);\n+ 227\n+ 229 template\n+230 stream_from &operator>>(std::variant &) = delete;\n+ 231\n+ 233\n+237 template [[nodiscard]] auto iter() &\n+ 238 {\n+ 239 return pqxx::internal::stream_input_iteration{*this};\n+ 240 }\n+ 241\n 243\n- 245 [[nodiscard]] static oid from_file(dbtransaction &, char const path[]);\n- 246\n- 247#if defined(PQXX_HAVE_PATH) && !defined(_WIN32)\n- 249\n- 252 [[nodiscard]] static oid\n- 253 from_file(dbtransaction &tx, std::filesystem::path const &path)\n- 254 {\n- 255 return from_file(tx, path.c_str());\n- 256 }\n- 257#endif\n- 258\n+ 259 std::vector const *read_row() &;\n 260\n- 263 static oid from_file(dbtransaction &, char const path[], oid);\n+ 262\n+ 263 raw_line get_raw_line();\n 264\n- 265#if defined(PQXX_HAVE_PATH) && !defined(_WIN32)\n- 267\n- 273 static oid\n- 274 from_file(dbtransaction &tx, std::filesystem::path const &path, oid id)\n- 275 {\n- 276 return from_file(tx, path.c_str(), id);\n- 277 }\n- 278#endif\n- 279\n- 281\n- 284 static void to_buf(\n- 285 dbtransaction &, oid, std::basic_string &,\n- 286 std::size_t max_size);\n- 287\n- 289\n- 295 static std::size_t append_to_buf(\n- 296 dbtransaction &tx, oid id, std::int64_t offset,\n- 297 std::basic_string &buf, std::size_t append_max);\n+ 265private:\n+ 266 // TODO: Clean up this signature once we cull the deprecated constructors.\n+ 268 stream_from(\n+ 269 transaction_base &tx, std::string_view table, std::string_view columns,\n+ 270 from_table_t);\n+ 271\n+ 272 // TODO: Clean up this signature once we cull the deprecated constructors.\n+ 274 stream_from(\n+ 275 transaction_base &, std::string_view unquoted_table,\n+ 276 std::string_view columns, from_table_t, int);\n+ 277\n+ 278 template\n+ 279 void extract_fields(Tuple &t, std::index_sequence) const\n+ 280 {\n+ 281 (extract_value(t), ...);\n+ 282 }\n+ 283\n+ 284 pqxx::internal::char_finder_func *m_char_finder;\n+ 285\n+ 287 std::string m_row;\n+ 288\n+ 290 std::vector m_fields;\n+ 291\n+ 292 bool m_finished = false;\n+ 293\n+ 294 void close();\n+ 295\n+ 296 template\n+ 297 void extract_value(Tuple &) const;\n 298\n- 300 static void to_file(dbtransaction &, oid, char const path[]);\n- 301\n- 302#if defined(PQXX_HAVE_PATH) && !defined(_WIN32)\n- 304\n- 307 static void\n- 308 to_file(dbtransaction &tx, oid id, std::filesystem::path const &path)\n- 309 {\n- 310 to_file(tx, id, path.c_str());\n- 311 }\n- 312#endif\n- 313\n- 315\n- 326 void close();\n- 327\n- 328private:\n- 329 PQXX_PRIVATE blob(connection &conn, int fd) noexcept :\n- 330 m_conn{&conn}, m_fd{fd}\n- 331 {}\n- 332 static PQXX_PRIVATE blob open_internal(dbtransaction &, oid, int);\n- 333 static PQXX_PRIVATE pqxx::internal::pq::PGconn *\n- 334 raw_conn(pqxx::connection *) noexcept;\n- 335 static PQXX_PRIVATE pqxx::internal::pq::PGconn *\n- 336 raw_conn(pqxx::dbtransaction const &) noexcept;\n- 337 static PQXX_PRIVATE std::string errmsg(connection const *);\n- 338 static PQXX_PRIVATE std::string errmsg(dbtransaction const &tx)\n- 339 {\n- 340 return errmsg(&tx.conn());\n- 341 }\n- 342 PQXX_PRIVATE std::string errmsg() const { return errmsg(m_conn); }\n- 343 PQXX_PRIVATE std::int64_t seek(std::int64_t offset, int whence);\n- 344 std::size_t raw_read(std::byte buf[], std::size_t size);\n- 345 void raw_write(std::byte const buf[], std::size_t size);\n- 346\n- 347 connection *m_conn = nullptr;\n- 348 int m_fd = -1;\n- 349};\n- 350} // namespace pqxx\n- 351#endif\n+ 300 void parse_line();\n+ 301};\n+ 302\n+ 303\n+ 304template\n+305inline stream_from::stream_from(\n+ 306 transaction_base &tx, from_table_t, std::string_view table_name,\n+ 307 Columns const &columns) :\n+ 308 stream_from{\n+ 309 tx, from_table, table_name, std::begin(columns), std::end(columns)}\n+ 310{}\n+ 311\n+ 312\n+ 313template\n+314inline stream_from::stream_from(\n+ 315 transaction_base &tx, from_table_t, std::string_view table,\n+ 316 Iter columns_begin, Iter columns_end) :\n+ 317 stream_from{\n+ 318 tx, table, separated_list(\",\", columns_begin, columns_end),\n+ 319 from_table, 1}\n+ 320{}\n+ 321\n+ 322\n+323template inline stream_from &stream_from::operator>>(Tuple\n+&t)\n+ 324{\n+ 325 if (m_finished)\n+ 326 PQXX_UNLIKELY return *this;\n+ 327 static constexpr auto tup_size{std::tuple_size_v};\n+ 328 m_fields.reserve(tup_size);\n+ 329 parse_line();\n+ 330 if (m_finished)\n+ 331 PQXX_UNLIKELY return *this;\n+ 332\n+ 333 if (std::size(m_fields) != tup_size)\n+ 334 throw usage_error{internal::concat(\n+ 335 \"Tried to extract \", tup_size, \" field(s) from a stream of \",\n+ 336 std::size(m_fields), \".\")};\n+ 337\n+ 338 extract_fields(t, std::make_index_sequence{});\n+ 339 return *this;\n+ 340}\n+ 341\n+ 342\n+ 343template\n+ 344inline void stream_from::extract_value(Tuple &t) const\n+ 345{\n+ 346 using field_type = strip_t(t))>;\n+ 347 using nullity = nullness;\n+ 348 assert(index < std::size(m_fields));\n+ 349 if constexpr (nullity::always_null)\n+ 350 {\n+ 351 if (std::data(m_fields[index]) != nullptr)\n+ 352 throw conversion_error{\"Streaming non-null value into null field.\"};\n+ 353 }\n+ 354 else if (std::data(m_fields[index]) == nullptr)\n+ 355 {\n+ 356 if constexpr (nullity::has_null)\n+ 357 std::get(t) = nullity::null();\n+ 358 else\n+ 359 internal::throw_null_conversion(type_name);\n+ 360 }\n+ 361 else\n+ 362 {\n+ 363 // Don't ever try to convert a non-null value to nullptr_t!\n+ 364 std::get(t) = from_string(m_fields[index]);\n+ 365 }\n+ 366}\n+ 367} // namespace pqxx\n+ 368#endif\n pqxx\n The home of all libpqxx classes, functions, templates, etc.\n Definition array.hxx:33\n-pqxx::blob\n-Definition blob.hxx:53\n-pqxx::blob::write\n-void write(DATA const &data)\n-Write data large object, at the current position.\n-Definition blob.hxx:197\n-pqxx::blob::blob\n-blob(blob const &)=delete\n-pqxx::blob::blob\n-blob()=default\n-You can default-construct a blob, but it won't do anything useful.\n-pqxx::blob::read\n-std::basic_string_view< std::byte > read(std::vector< std::byte, ALLOC > &buf)\n-Read up to std::size(buf) bytes from the object.\n-Definition blob.hxx:147\n-pqxx::blob::operator=\n-blob & operator=(blob const &)=delete\n-pqxx::connection\n-Connection to a database.\n-Definition connection.hxx:253\n-pqxx::dbtransaction\n-Abstract transaction base class: bracket transactions on the database.\n-Definition dbtransaction.hxx:54\n+pqxx::separated_list\n+std::string separated_list(std::string_view sep, ITER begin, ITER end, ACCESS\n+access)\n+Represent sequence of values as a string, joined by a given separator.\n+Definition separated_list.hxx:44\n+pqxx::strip_t\n+std::remove_cv_t< std::remove_reference_t< TYPE > > strip_t\n+Remove any constness, volatile, and reference-ness from a type.\n+Definition types.hxx:91\n+pqxx::from_query\n+constexpr from_query_t from_query\n+Pass this to a stream_from constructor to stream query results.\n+Definition stream_from.hxx:44\n+pqxx::from_table\n+constexpr from_table_t from_table\n+Pass this to a stream_from constructor to stream table contents.\n+Definition stream_from.hxx:40\n+pqxx::table_path\n+std::initializer_list< std::string_view > table_path\n+Representation of a PostgreSQL table path.\n+Definition connection.hxx:188\n+pqxx::internal::throw_null_conversion\n+void PQXX_COLD throw_null_conversion(std::string const &type)\n+Definition strconv.cxx:253\n+pqxx::usage_error\n+Error in usage of libpqxx library, similar to std::logic_error.\n+Definition except.hxx:249\n+pqxx::conversion_error\n+Value conversion failed, e.g. when converting \"Hello\" to int.\n+Definition except.hxx:283\n+pqxx::nullness\n+Traits describing a type's \"null value,\" if any.\n+Definition strconv.hxx:93\n+pqxx::stream_from\n+Stream data from the database.\n+Definition stream_from.hxx:79\n+pqxx::stream_from::query\n+static stream_from query(transaction_base &tx, std::string_view q)\n+Factory: Execute query, and stream the results.\n+Definition stream_from.hxx:98\n+pqxx::stream_from::operator>>\n+stream_from & operator>>(std::variant< Vs... > &)=delete\n+Doing this with a std::variant is going to be horrifically borked.\n+pqxx::stream_from::operator>>\n+stream_from & operator>>(Tuple &)\n+Read one row into a tuple.\n+Definition stream_from.hxx:323\n+pqxx::stream_from::stream_from\n+stream_from(transaction_base &tx, std::string_view table, Columns const\n+&columns)\n+Definition stream_from.hxx:185\n+pqxx::stream_from::raw_line\n+std::pair< std::unique_ptr< char, void(*)(void const *)>, std::size_t >\n+raw_line\n+Definition stream_from.hxx:82\n+pqxx::stream_from::stream_from\n+stream_from(stream_from &&)=delete\n+pqxx::stream_from::stream_from\n+stream_from(transaction_base &, std::string_view table, Iter columns_begin,\n+Iter columns_end)\n+pqxx::stream_from::operator=\n+stream_from & operator=(stream_from &&)=delete\n+pqxx::stream_from::stream_from\n+stream_from(transaction_base &tx, std::string_view table)\n+Definition stream_from.hxx:177\n+pqxx::stream_from::iter\n+auto iter() &\n+Iterate over this stream. Supports range-based \"for\" loops.\n+Definition stream_from.hxx:237\n+pqxx::stream_from::operator!\n+constexpr bool operator!() const noexcept\n+Has this stream produced all the data it is going to produce?\n+Definition stream_from.hxx:204\n+pqxx::transaction_base\n+Interface definition (and common code) for \"transaction\" classes.\n+Definition transaction_base.hxx:88\n+pqxx::transaction_focus\n+Base class for things that monopolise a transaction's attention.\n+Definition transaction_focus.hxx:29\n+pqxx::from_table_t\n+Marker for stream_from constructors: \"stream from table.\".\n+Definition types.hxx:68\n+pqxx::from_query_t\n+Marker for stream_from constructors: \"stream from query.\".\n+Definition types.hxx:74\n * include\n * pqxx\n- * blob.hxx\n+ * stream_from.hxx\n * Generated by [doxygen] 1.9.8\n"}]}, {"source1": "./usr/share/doc/libpqxx-doc/html/a00005_source.html", "source2": "./usr/share/doc/libpqxx-doc/html/a00005_source.html", "unified_diff": "@@ -1,15 +1,15 @@\n \n \n \n \n \n \n \n-libpqxx: except.hxx Source File\n+libpqxx: pipeline.hxx Source File\n \n \n \n \n \n \n \n@@ -60,938 +60,199 @@\n \n
\n
\n-
except.hxx
\n+
pipeline.hxx
\n
\n
\n-
1/* Definition of libpqxx exception classes.
\n+
1/* Definition of the pqxx::pipeline class.
\n
2 *
\n-
3 * pqxx::sql_error, pqxx::broken_connection, pqxx::in_doubt_error, ...
\n+
3 * Throughput-optimized mechanism for executing queries.
\n
4 *
\n-
5 * DO NOT INCLUDE THIS FILE DIRECTLY; include pqxx/except instead.
\n+
5 * DO NOT INCLUDE THIS FILE DIRECTLY; include pqxx/pipeline instead.
\n
6 *
\n
7 * Copyright (c) 2000-2023, Jeroen T. Vermeulen.
\n
8 *
\n
9 * See COPYING for copyright license. If you did not receive a file called
\n
10 * COPYING with this source code, please notify the distributor of this
\n
11 * mistake, or contact the author.
\n
12 */
\n-
13#ifndef PQXX_H_EXCEPT
\n-
14#define PQXX_H_EXCEPT
\n+
13#ifndef PQXX_H_PIPELINE
\n+
14#define PQXX_H_PIPELINE
\n
15
\n
16#if !defined(PQXX_HEADER_PRE)
\n
17# error "Include libpqxx headers as <pqxx/header>, not <pqxx/header.hxx>."
\n
18#endif
\n
19
\n-
20#if pqxx_have_source_location
\n-
21# include <source_location>
\n-
22#endif
\n+
20#include <limits>
\n+
21#include <map>
\n+
22#include <string>
\n
23
\n-
24#include <stdexcept>
\n-
25#include <string>
\n+
24#include "pqxx/transaction_base.hxx"
\n+
25
\n
26
\n-
27
\n-
28namespace pqxx
\n-
29{
\n-
\n-
47struct PQXX_LIBEXPORT failure : std::runtime_error
\n-
48{
\n-
49#if pqxx_have_source_location
\n-
50 explicit failure(
\n-
51 std::string const &,
\n-
52 std::source_location = std::source_location::current());
\n-
53 std::source_location location;
\n-
54#else
\n-
55 explicit failure(std::string const &);
\n-
56#endif
\n-
57};
\n-
\n-
58
\n-
59
\n+
27namespace pqxx
\n+
28{
\n+
29// TODO: libpq 14 introduced a similar "pipeline mode." Can we use that?
\n+
30
\n+
32
\n+
\n+
50class PQXX_LIBEXPORT pipeline : public transaction_focus
\n+
51{
\n+
52public:
\n+
54 using query_id = long;
\n+
55
\n+
56 pipeline(pipeline const &) = delete;
\n+
57 pipeline &operator=(pipeline const &) = delete;
\n+
58 pipeline(pipeline &&) = delete;
\n+\n+
60
\n
61
\n-
\n-
80struct PQXX_LIBEXPORT broken_connection : failure
\n-
81{
\n-\n-
83 explicit broken_connection(
\n-
84 std::string const &
\n-
85#if pqxx_have_source_location
\n-
86 ,
\n-
87 std::source_location = std::source_location::current()
\n-
88#endif
\n-
89 );
\n-
90};
\n-
\n-
91
\n-
92
\n+
\n+
63 explicit pipeline(transaction_base &t) : transaction_focus{t, s_classname}
\n+
64 {
\n+
65 init();
\n+
66 }
\n+
\n+
\n+
68 pipeline(transaction_base &t, std::string_view tname) :
\n+
69 transaction_focus{t, s_classname, tname}
\n+
70 {
\n+
71 init();
\n+
72 }
\n+
\n+
73
\n+
75 ~pipeline() noexcept;
\n+
76
\n+
78
\n+
84 query_id insert(std::string_view) &;
\n+
85
\n+
87
\n+
93 void complete();
\n
94
\n-
\n-\n-
103{
\n-
104 explicit protocol_violation(
\n-
105 std::string const &
\n-
106#if pqxx_have_source_location
\n-
107 ,
\n-
108 std::source_location = std::source_location::current()
\n-
109#endif
\n-
110 );
\n-
111};
\n-
\n-
112
\n-
113
\n-
\n-
115struct PQXX_LIBEXPORT variable_set_to_null : failure
\n-
116{
\n-
117 explicit variable_set_to_null(
\n-
118 std::string const &
\n-
119#if pqxx_have_source_location
\n-
120 ,
\n-
121 std::source_location = std::source_location::current()
\n-
122#endif
\n-
123 );
\n-
124};
\n-
\n-
125
\n-
126
\n-
128
\n-
\n-
131class PQXX_LIBEXPORT sql_error : public failure
\n-
132{
\n-
134 std::string const m_query;
\n-
136 std::string const m_sqlstate;
\n-
137
\n-
138public:
\n-
139 explicit sql_error(
\n-
140 std::string const &whatarg = "", std::string const &Q = "",
\n-
141 char const sqlstate[] = nullptr
\n-
142#if pqxx_have_source_location
\n-
143 ,
\n-
144 std::source_location = std::source_location::current()
\n-
145#endif
\n-
146 );
\n-
147 virtual ~sql_error() noexcept override;
\n-
148
\n-
150 [[nodiscard]] PQXX_PURE std::string const &query() const noexcept;
\n-
151
\n-
153 [[nodiscard]] PQXX_PURE std::string const &sqlstate() const noexcept;
\n-
154};
\n-
\n-
155
\n-
156
\n-
158
\n-
\n-
164struct PQXX_LIBEXPORT in_doubt_error : failure
\n-
165{
\n-
166 explicit in_doubt_error(
\n-
167 std::string const &
\n-
168#if pqxx_have_source_location
\n-
169 ,
\n-
170 std::source_location = std::source_location::current()
\n-
171#endif
\n-
172 );
\n-
173};
\n-
\n+
96
\n+
105 void flush();
\n+
106
\n+
108
\n+
116 void cancel();
\n+
117
\n+
119 [[nodiscard]] bool is_finished(query_id) const;
\n+
120
\n+
122
\n+
\n+
128 result retrieve(query_id qid)
\n+
129 {
\n+
130 return retrieve(m_queries.find(qid)).second;
\n+
131 }
\n+
\n+
132
\n+
134
\n+
135 std::pair<query_id, result> retrieve();
\n+
136
\n+
137 [[nodiscard]] bool empty() const noexcept { return std::empty(m_queries); }
\n+
138
\n+
141
\n+
152 int retain(int retain_max = 2) &;
\n+
153
\n+
154
\n+
156 void resume() &;
\n+
157
\n+
158private:
\n+
159 struct PQXX_PRIVATE Query
\n+
160 {
\n+
161 explicit Query(std::string_view q) :
\n+
162 query{std::make_shared<std::string>(q)}
\n+
163 {}
\n+
164
\n+
165 std::shared_ptr<std::string> query;
\n+
166 result res;
\n+
167 };
\n+
168
\n+
169 using QueryMap = std::map<query_id, Query>;
\n+
170
\n+
171 void init();
\n+
172 void attach();
\n+
173 void detach();
\n
174
\n-
175
\n-
\n-
177struct PQXX_LIBEXPORT transaction_rollback : sql_error
\n-
178{
\n-
179 explicit transaction_rollback(
\n-
180 std::string const &whatarg, std::string const &q = "",
\n-
181 char const sqlstate[] = nullptr
\n-
182#if pqxx_have_source_location
\n-
183 ,
\n-
184 std::source_location = std::source_location::current()
\n-
185#endif
\n-
186 );
\n-
187};
\n-
\n-
188
\n-
189
\n-
191
\n-
\n-\n-
200{
\n-
201 explicit serialization_failure(
\n-
202 std::string const &whatarg, std::string const &q,
\n-
203 char const sqlstate[] = nullptr
\n-
204#if pqxx_have_source_location
\n-
205 ,
\n-
206 std::source_location = std::source_location::current()
\n-
207#endif
\n-
208 );
\n-
209};
\n-
\n-
210
\n+
176 static constexpr query_id qid_limit() noexcept
\n+
177 {
\n+
178 // Parenthesise this to work around an eternal Visual C++ problem:
\n+
179 // Without the extra parentheses, unless NOMINMAX is defined, the
\n+
180 // preprocessor will mistake this "max" for its annoying built-in macro
\n+
181 // of the same name.
\n+
182 return (std::numeric_limits<query_id>::max)();
\n+
183 }
\n+
184
\n+
186 PQXX_PRIVATE query_id generate_id();
\n+
187
\n+
188 bool have_pending() const noexcept
\n+
189 {
\n+
190 return m_issuedrange.second != m_issuedrange.first;
\n+
191 }
\n+
192
\n+
193 PQXX_PRIVATE void issue();
\n+
194
\n+
196 void set_error_at(query_id qid) noexcept
\n+
197 {
\n+
198 PQXX_UNLIKELY
\n+
199 if (qid < m_error)
\n+
200 m_error = qid;
\n+
201 }
\n+
202
\n+
204 [[noreturn]] PQXX_PRIVATE void internal_error(std::string const &err);
\n+
205
\n+
206 PQXX_PRIVATE bool obtain_result(bool expect_none = false);
\n+
207
\n+
208 PQXX_PRIVATE void obtain_dummy();
\n+
209 PQXX_PRIVATE void get_further_available_results();
\n+
210 PQXX_PRIVATE void check_end_results();
\n
211
\n-
\n-\n-
214{
\n-\n-
216 std::string const &whatarg, std::string const &q,
\n-
217 char const sqlstate[] = nullptr
\n-
218#if pqxx_have_source_location
\n-
219 ,
\n-
220 std::source_location = std::source_location::current()
\n-
221#endif
\n-
222 );
\n-
223};
\n-
\n+
213 PQXX_PRIVATE void receive_if_available();
\n+
214
\n+
216 PQXX_PRIVATE void receive(pipeline::QueryMap::const_iterator stop);
\n+
217 std::pair<pipeline::query_id, result> retrieve(pipeline::QueryMap::iterator);
\n+
218
\n+
219 QueryMap m_queries;
\n+
220 std::pair<QueryMap::iterator, QueryMap::iterator> m_issuedrange;
\n+
221 int m_retain = 0;
\n+
222 int m_num_waiting = 0;
\n+
223 query_id m_q_id = 0;
\n
224
\n-
225
\n-
\n-\n-
228{
\n-
229 explicit deadlock_detected(
\n-
230 std::string const &whatarg, std::string const &q,
\n-
231 char const sqlstate[] = nullptr
\n-
232#if pqxx_have_source_location
\n-
233 ,
\n-
234 std::source_location = std::source_location::current()
\n-
235#endif
\n-
236 );
\n-
237};
\n-
\n-
238
\n-
239
\n-
\n-
241struct PQXX_LIBEXPORT internal_error : std::logic_error
\n-
242{
\n-
243 explicit internal_error(std::string const &);
\n-
244};
\n-
\n-
245
\n-
246
\n-
\n-
248struct PQXX_LIBEXPORT usage_error : std::logic_error
\n-
249{
\n-
250 explicit usage_error(
\n-
251 std::string const &
\n-
252#if pqxx_have_source_location
\n-
253 ,
\n-
254 std::source_location = std::source_location::current()
\n-
255#endif
\n-
256 );
\n-
257
\n-
258#if pqxx_have_source_location
\n-
259 std::source_location location;
\n-
260#endif
\n-
261};
\n-
\n-
262
\n-
263
\n-
\n-
265struct PQXX_LIBEXPORT argument_error : std::invalid_argument
\n-
266{
\n-
267 explicit argument_error(
\n-
268 std::string const &
\n-
269#if pqxx_have_source_location
\n-
270 ,
\n-
271 std::source_location = std::source_location::current()
\n-
272#endif
\n-
273 );
\n-
274
\n-
275#if pqxx_have_source_location
\n-
276 std::source_location location;
\n-
277#endif
\n-
278};
\n-
\n-
279
\n-
280
\n-
\n-
282struct PQXX_LIBEXPORT conversion_error : std::domain_error
\n-
283{
\n-
284 explicit conversion_error(
\n-
285 std::string const &
\n-
286#if pqxx_have_source_location
\n-
287 ,
\n-
288 std::source_location = std::source_location::current()
\n-
289#endif
\n-
290 );
\n-
291
\n-
292#if pqxx_have_source_location
\n-
293 std::source_location location;
\n-
294#endif
\n-
295};
\n-
\n-
296
\n-
297
\n-
\n-
299struct PQXX_LIBEXPORT unexpected_null : conversion_error
\n-
300{
\n-
301 explicit unexpected_null(
\n-
302 std::string const &
\n-
303#if pqxx_have_source_location
\n-
304 ,
\n-
305 std::source_location = std::source_location::current()
\n-
306#endif
\n-
307 );
\n-
308};
\n-
\n-
309
\n-
310
\n-
\n-\n-
313{
\n-
314 explicit conversion_overrun(
\n-
315 std::string const &
\n-
316#if pqxx_have_source_location
\n-
317 ,
\n-
318 std::source_location = std::source_location::current()
\n-
319#endif
\n-
320 );
\n-
321};
\n-
\n-
322
\n-
323
\n-
\n-
325struct PQXX_LIBEXPORT range_error : std::out_of_range
\n-
326{
\n-
327 explicit range_error(
\n-
328 std::string const &
\n-
329#if pqxx_have_source_location
\n-
330 ,
\n-
331 std::source_location = std::source_location::current()
\n-
332#endif
\n-
333 );
\n-
334
\n-
335#if pqxx_have_source_location
\n-
336 std::source_location location;
\n-
337#endif
\n-
338};
\n-
\n-
339
\n-
340
\n-
\n-
342struct PQXX_LIBEXPORT unexpected_rows : public range_error
\n-
343{
\n-
344#if pqxx_have_source_location
\n-
345 explicit unexpected_rows(
\n-
346 std::string const &msg,
\n-
347 std::source_location loc = std::source_location::current()) :
\n-
348 range_error{msg, loc}
\n-
349 {}
\n-
350#else
\n-
351 explicit unexpected_rows(std::string const &msg) : range_error{msg} {}
\n-
352#endif
\n-
353};
\n-
\n-
354
\n-
355
\n-
\n-
357struct PQXX_LIBEXPORT feature_not_supported : sql_error
\n-
358{
\n-
359#if pqxx_have_source_location
\n-
360 explicit feature_not_supported(
\n-
361 std::string const &err, std::string const &Q = "",
\n-
362 char const sqlstate[] = nullptr,
\n-
363 std::source_location loc = std::source_location::current()) :
\n-
364 sql_error{err, Q, sqlstate, loc}
\n-
365 {}
\n-
366#else
\n-
\n-\n-
368 std::string const &err, std::string const &Q = "",
\n-
369 char const sqlstate[] = nullptr) :
\n-
370 sql_error{err, Q, sqlstate}
\n-
371 {}
\n-
\n-
372#endif
\n-
373};
\n-
\n-
374
\n-
\n-
376struct PQXX_LIBEXPORT data_exception : sql_error
\n-
377{
\n-
378#if pqxx_have_source_location
\n-
379 explicit data_exception(
\n-
380 std::string const &err, std::string const &Q = "",
\n-
381 char const sqlstate[] = nullptr,
\n-
382 std::source_location loc = std::source_location::current()) :
\n-
383 sql_error{err, Q, sqlstate, loc}
\n-
384 {}
\n-
385#else
\n-
\n-\n-
387 std::string const &err, std::string const &Q = "",
\n-
388 char const sqlstate[] = nullptr) :
\n-
389 sql_error{err, Q, sqlstate}
\n-
390 {}
\n-
\n-
391#endif
\n-
392};
\n-
\n-
393
\n-
\n-\n-
395{
\n-
396#if pqxx_have_source_location
\n-\n-
398 std::string const &err, std::string const &Q = "",
\n-
399 char const sqlstate[] = nullptr,
\n-
400 std::source_location loc = std::source_location::current()) :
\n-
401 sql_error{err, Q, sqlstate, loc}
\n-
402 {}
\n-
403#else
\n-
\n-\n-
405 std::string const &err, std::string const &Q = "",
\n-
406 char const sqlstate[] = nullptr) :
\n-
407 sql_error{err, Q, sqlstate}
\n-
408 {}
\n-
\n-
409#endif
\n-
410};
\n-
\n-
411
\n-
\n-\n-
413{
\n-
414#if pqxx_have_source_location
\n-
415 explicit restrict_violation(
\n-
416 std::string const &err, std::string const &Q = "",
\n-
417 char const sqlstate[] = nullptr,
\n-
418 std::source_location loc = std::source_location::current()) :
\n-
419 integrity_constraint_violation{err, Q, sqlstate, loc}
\n-
420 {}
\n-
421#else
\n-
\n-\n-
423 std::string const &err, std::string const &Q = "",
\n-
424 char const sqlstate[] = nullptr) :
\n-
425 integrity_constraint_violation{err, Q, sqlstate}
\n-
426 {}
\n-
\n-
427#endif
\n-
428};
\n-
\n-
429
\n-
\n-\n-
431{
\n-
432#if pqxx_have_source_location
\n-
433 explicit not_null_violation(
\n-
434 std::string const &err, std::string const &Q = "",
\n-
435 char const sqlstate[] = nullptr,
\n-
436 std::source_location loc = std::source_location::current()) :
\n-
437 integrity_constraint_violation{err, Q, sqlstate, loc}
\n-
438 {}
\n-
439#else
\n-
\n-\n-
441 std::string const &err, std::string const &Q = "",
\n-
442 char const sqlstate[] = nullptr) :
\n-
443 integrity_constraint_violation{err, Q, sqlstate}
\n-
444 {}
\n-
\n-
445#endif
\n-
446};
\n-
\n-
447
\n-
\n-\n-
449{
\n-
450#if pqxx_have_source_location
\n-
451 explicit foreign_key_violation(
\n-
452 std::string const &err, std::string const &Q = "",
\n-
453 char const sqlstate[] = nullptr,
\n-
454 std::source_location loc = std::source_location::current()) :
\n-
455 integrity_constraint_violation{err, Q, sqlstate, loc}
\n-
456 {}
\n-
457#else
\n-
\n-\n-
459 std::string const &err, std::string const &Q = "",
\n-
460 char const sqlstate[] = nullptr) :
\n-
461 integrity_constraint_violation{err, Q, sqlstate}
\n-
462 {}
\n-
\n-
463#endif
\n-
464};
\n-
\n-
465
\n-
\n-\n-
467{
\n-
468#if pqxx_have_source_location
\n-
469 explicit unique_violation(
\n-
470 std::string const &err, std::string const &Q = "",
\n-
471 char const sqlstate[] = nullptr,
\n-
472 std::source_location loc = std::source_location::current()) :
\n-
473 integrity_constraint_violation{err, Q, sqlstate, loc}
\n-
474 {}
\n-
475#else
\n-
\n-\n-
477 std::string const &err, std::string const &Q = "",
\n-
478 char const sqlstate[] = nullptr) :
\n-
479 integrity_constraint_violation{err, Q, sqlstate}
\n-
480 {}
\n-
\n-
481#endif
\n-
482};
\n-
\n-
483
\n-
\n-\n-
485{
\n-
486#if pqxx_have_source_location
\n-
487 explicit check_violation(
\n-
488 std::string const &err, std::string const &Q = "",
\n-
489 char const sqlstate[] = nullptr,
\n-
490 std::source_location loc = std::source_location::current()) :
\n-
491 integrity_constraint_violation{err, Q, sqlstate, loc}
\n-
492 {}
\n-
493#else
\n-
\n-\n-
495 std::string const &err, std::string const &Q = "",
\n-
496 char const sqlstate[] = nullptr) :
\n-
497 integrity_constraint_violation{err, Q, sqlstate}
\n-
498 {}
\n-
\n-
499#endif
\n-
500};
\n-
\n-
501
\n-
\n-
502struct PQXX_LIBEXPORT invalid_cursor_state : sql_error
\n-
503{
\n-
504#if pqxx_have_source_location
\n-
505 explicit invalid_cursor_state(
\n-
506 std::string const &err, std::string const &Q = "",
\n-
507 char const sqlstate[] = nullptr,
\n-
508 std::source_location loc = std::source_location::current()) :
\n-
509 sql_error{err, Q, sqlstate, loc}
\n-
510 {}
\n-
511#else
\n-
\n-\n-
513 std::string const &err, std::string const &Q = "",
\n-
514 char const sqlstate[] = nullptr) :
\n-
515 sql_error{err, Q, sqlstate}
\n-
516 {}
\n-
\n-
517#endif
\n-
518};
\n-
\n-
519
\n-
\n-\n-
521{
\n-
522#if pqxx_have_source_location
\n-\n-
524 std::string const &err, std::string const &Q = "",
\n-
525 char const sqlstate[] = nullptr,
\n-
526 std::source_location loc = std::source_location::current()) :
\n-
527 sql_error{err, Q, sqlstate, loc}
\n-
528 {}
\n-
529#else
\n-
\n-\n-
531 std::string const &err, std::string const &Q = "",
\n-
532 char const sqlstate[] = nullptr) :
\n-
533 sql_error{err, Q, sqlstate}
\n-
534 {}
\n-
\n-
535#endif
\n-
536};
\n-
\n-
537
\n-
\n-
538struct PQXX_LIBEXPORT invalid_cursor_name : sql_error
\n-
539{
\n-
540#if pqxx_have_source_location
\n-
541 explicit invalid_cursor_name(
\n-
542 std::string const &err, std::string const &Q = "",
\n-
543 char const sqlstate[] = nullptr,
\n-
544 std::source_location loc = std::source_location::current()) :
\n-
545 sql_error{err, Q, sqlstate, loc}
\n-
546 {}
\n-
547#else
\n-
\n-\n-
549 std::string const &err, std::string const &Q = "",
\n-
550 char const sqlstate[] = nullptr) :
\n-
551 sql_error{err, Q, sqlstate}
\n-
552 {}
\n-
\n-
553#endif
\n-
554};
\n-
\n-
555
\n-
\n-
556struct PQXX_LIBEXPORT syntax_error : sql_error
\n-
557{
\n-
559 int const error_position;
\n-
560
\n-
561#if pqxx_have_source_location
\n-
562 explicit syntax_error(
\n-
563 std::string const &err, std::string const &Q = "",
\n-
564 char const sqlstate[] = nullptr, int pos = -1,
\n-
565 std::source_location loc = std::source_location::current()) :
\n-
566 sql_error{err, Q, sqlstate, loc}, error_position{pos}
\n-
567 {}
\n-
568#else
\n-
\n-
569 explicit syntax_error(
\n-
570 std::string const &err, std::string const &Q = "",
\n-
571 char const sqlstate[] = nullptr, int pos = -1) :
\n-
572 sql_error{err, Q, sqlstate}, error_position{pos}
\n-
573 {}
\n-
\n-
574#endif
\n-
575};
\n-
\n-
576
\n-
\n-
577struct PQXX_LIBEXPORT undefined_column : syntax_error
\n-
578{
\n-
579#if pqxx_have_source_location
\n-
580 explicit undefined_column(
\n-
581 std::string const &err, std::string const &Q = "",
\n-
582 char const sqlstate[] = nullptr,
\n-
583 std::source_location loc = std::source_location::current()) :
\n-
584 // TODO: Can we get the column?
\n-
585 syntax_error{err, Q, sqlstate, -1, loc}
\n-
586 {}
\n-
587#else
\n-
\n-\n-
589 std::string const &err, std::string const &Q = "",
\n-
590 char const sqlstate[] = nullptr) :
\n-
591 syntax_error{err, Q, sqlstate}
\n-
592 {}
\n-
\n-
593#endif
\n-
594};
\n-
\n-
595
\n-
\n-
596struct PQXX_LIBEXPORT undefined_function : syntax_error
\n-
597{
\n-
598#if pqxx_have_source_location
\n-
599 explicit undefined_function(
\n-
600 std::string const &err, std::string const &Q = "",
\n-
601 char const sqlstate[] = nullptr,
\n-
602 std::source_location loc = std::source_location::current()) :
\n-
603 // TODO: Can we get the column?
\n-
604 syntax_error{err, Q, sqlstate, -1, loc}
\n-
605 {}
\n-
606#else
\n-
\n-\n-
608 std::string const &err, std::string const &Q = "",
\n-
609 char const sqlstate[] = nullptr) :
\n-
610 syntax_error{err, Q, sqlstate}
\n-
611 {}
\n-
\n-
612#endif
\n-
613};
\n-
\n-
614
\n-
\n-
615struct PQXX_LIBEXPORT undefined_table : syntax_error
\n-
616{
\n-
617#if pqxx_have_source_location
\n-
618 explicit undefined_table(
\n-
619 std::string const &err, std::string const &Q = "",
\n-
620 char const sqlstate[] = nullptr,
\n-
621 std::source_location loc = std::source_location::current()) :
\n-
622 // TODO: Can we get the column?
\n-
623 syntax_error{err, Q, sqlstate, -1, loc}
\n-
624 {}
\n-
625#else
\n-
\n-\n-
627 std::string const &err, std::string const &Q = "",
\n-
628 char const sqlstate[] = nullptr) :
\n-
629 syntax_error{err, Q, sqlstate}
\n-
630 {}
\n-
\n-
631#endif
\n-
632};
\n-
\n-
633
\n-
\n-
634struct PQXX_LIBEXPORT insufficient_privilege : sql_error
\n-
635{
\n-
636#if pqxx_have_source_location
\n-
637 explicit insufficient_privilege(
\n-
638 std::string const &err, std::string const &Q = "",
\n-
639 char const sqlstate[] = nullptr,
\n-
640 std::source_location loc = std::source_location::current()) :
\n-
641 sql_error{err, Q, sqlstate, loc}
\n-
642 {}
\n-
643#else
\n-
\n-\n-
645 std::string const &err, std::string const &Q = "",
\n-
646 char const sqlstate[] = nullptr) :
\n-
647 sql_error{err, Q, sqlstate}
\n-
648 {}
\n-
\n-
649#endif
\n-
650};
\n-
\n-
651
\n-
\n-
653struct PQXX_LIBEXPORT insufficient_resources : sql_error
\n-
654{
\n-
655#if pqxx_have_source_location
\n-
656 explicit insufficient_resources(
\n-
657 std::string const &err, std::string const &Q = "",
\n-
658 char const sqlstate[] = nullptr,
\n-
659 std::source_location loc = std::source_location::current()) :
\n-
660 sql_error{err, Q, sqlstate, loc}
\n-
661 {}
\n-
662#else
\n-
\n-\n-
664 std::string const &err, std::string const &Q = "",
\n-
665 char const sqlstate[] = nullptr) :
\n-
666 sql_error{err, Q, sqlstate}
\n-
667 {}
\n-
\n-
668#endif
\n-
669};
\n-
\n-
670
\n-
\n-
671struct PQXX_LIBEXPORT disk_full : insufficient_resources
\n-
672{
\n-
673#if pqxx_have_source_location
\n-
674 explicit disk_full(
\n-
675 std::string const &err, std::string const &Q = "",
\n-
676 char const sqlstate[] = nullptr,
\n-
677 std::source_location loc = std::source_location::current()) :
\n-
678 insufficient_resources{err, Q, sqlstate, loc}
\n-
679 {}
\n-
680#else
\n-
\n-
681 explicit disk_full(
\n-
682 std::string const &err, std::string const &Q = "",
\n-
683 char const sqlstate[] = nullptr) :
\n-
684 insufficient_resources{err, Q, sqlstate}
\n-
685 {}
\n-
\n-
686#endif
\n-
687};
\n-
\n-
688
\n-
\n-\n-
690{
\n-
691#if pqxx_have_source_location
\n-
692 explicit out_of_memory(
\n-
693 std::string const &err, std::string const &Q = "",
\n-
694 char const sqlstate[] = nullptr,
\n-
695 std::source_location loc = std::source_location::current()) :
\n-
696 insufficient_resources{err, Q, sqlstate, loc}
\n-
697 {}
\n-
698#else
\n-
\n-\n-
700 std::string const &err, std::string const &Q = "",
\n-
701 char const sqlstate[] = nullptr) :
\n-
702 insufficient_resources{err, Q, sqlstate}
\n-
703 {}
\n-
\n-
704#endif
\n-
705};
\n-
\n-
706
\n-
\n-\n-
708{
\n-
709#if pqxx_have_source_location
\n-
710 explicit too_many_connections(
\n-
711 std::string const &err,
\n-
712 std::source_location loc = std::source_location::current()) :
\n-
713 broken_connection{err, loc}
\n-
714 {}
\n-
715#else
\n-
\n-
716 explicit too_many_connections(std::string const &err) :
\n-\n-
718 {}
\n-
\n-
719#endif
\n-
720};
\n-
\n-
721
\n-
723
\n-
\n-
725struct PQXX_LIBEXPORT plpgsql_error : sql_error
\n-
726{
\n-
727#if pqxx_have_source_location
\n-
728 explicit plpgsql_error(
\n-
729 std::string const &err, std::string const &Q = "",
\n-
730 char const sqlstate[] = nullptr,
\n-
731 std::source_location loc = std::source_location::current()) :
\n-
732 sql_error{err, Q, sqlstate, loc}
\n-
733 {}
\n-
734#else
\n-
\n-\n-
736 std::string const &err, std::string const &Q = "",
\n-
737 char const sqlstate[] = nullptr) :
\n-
738 sql_error{err, Q, sqlstate}
\n-
739 {}
\n-
\n-
740#endif
\n-
741};
\n-
\n-
742
\n-
\n-
744struct PQXX_LIBEXPORT plpgsql_raise : plpgsql_error
\n-
745{
\n-
746#if pqxx_have_source_location
\n-
747 explicit plpgsql_raise(
\n-
748 std::string const &err, std::string const &Q = "",
\n-
749 char const sqlstate[] = nullptr,
\n-
750 std::source_location loc = std::source_location::current()) :
\n-
751 plpgsql_error{err, Q, sqlstate, loc}
\n-
752 {}
\n-
753#else
\n-
\n-\n-
755 std::string const &err, std::string const &Q = "",
\n-
756 char const sqlstate[] = nullptr) :
\n-
757 plpgsql_error{err, Q, sqlstate}
\n-
758 {}
\n-
\n-
759#endif
\n-
760};
\n-
\n-
761
\n-
\n-\n-
763{
\n-
764#if pqxx_have_source_location
\n-
765 explicit plpgsql_no_data_found(
\n-
766 std::string const &err, std::string const &Q = "",
\n-
767 char const sqlstate[] = nullptr,
\n-
768 std::source_location loc = std::source_location::current()) :
\n-
769 plpgsql_error{err, Q, sqlstate, loc}
\n-
770 {}
\n-
771#else
\n-
\n-\n-
773 std::string const &err, std::string const &Q = "",
\n-
774 char const sqlstate[] = nullptr) :
\n-
775 plpgsql_error{err, Q, sqlstate}
\n-
776 {}
\n-
\n-
777#endif
\n-
778};
\n-
\n-
779
\n-
\n-\n-
781{
\n-
782#if pqxx_have_source_location
\n-
783 explicit plpgsql_too_many_rows(
\n-
784 std::string const &err, std::string const &Q = "",
\n-
785 char const sqlstate[] = nullptr,
\n-
786 std::source_location loc = std::source_location::current()) :
\n-
787 plpgsql_error{err, Q, sqlstate, loc}
\n-
788 {}
\n-
789#else
\n-
\n-\n-
791 std::string const &err, std::string const &Q = "",
\n-
792 char const sqlstate[] = nullptr) :
\n-
793 plpgsql_error{err, Q, sqlstate}
\n-
794 {}
\n-
\n-
795#endif
\n-
796};
\n+
226 bool m_dummy_pending = false;
\n+
227
\n+
229 query_id m_error = qid_limit();
\n+
230
\n+
232
\n+
235 internal::encoding_group m_encoding;
\n+
236
\n+
237 static constexpr std::string_view s_classname{"pipeline"};
\n+
238};
\n
\n-
797
\n-
801} // namespace pqxx
\n-
802#endif
\n+
239} // namespace pqxx
\n+
240#endif
\n
The home of all libpqxx classes, functions, templates, etc.
Definition array.hxx:33
\n-
Run-time failure encountered by libpqxx, similar to std::runtime_error.
Definition except.hxx:48
\n-
Exception class for lost or failed backend connection.
Definition except.hxx:81
\n-
Exception class for micommunication with the server.
Definition except.hxx:103
\n-
The caller attempted to set a variable to null, which is not allowed.
Definition except.hxx:116
\n-
Exception class for failed queries.
Definition except.hxx:132
\n-
virtual ~sql_error() noexcept override
\n-
"Help, I don't know whether transaction was committed successfully!"
Definition except.hxx:165
\n-
The backend saw itself forced to roll back the ongoing transaction.
Definition except.hxx:178
\n-
Transaction failed to serialize. Please retry it.
Definition except.hxx:200
\n-
We can't tell whether our last statement succeeded.
Definition except.hxx:214
\n-
The ongoing transaction has deadlocked. Retrying it may help.
Definition except.hxx:228
\n-
Internal error in libpqxx library.
Definition except.hxx:242
\n-
Error in usage of libpqxx library, similar to std::logic_error.
Definition except.hxx:249
\n-
Invalid argument passed to libpqxx, similar to std::invalid_argument.
Definition except.hxx:266
\n-
Value conversion failed, e.g. when converting "Hello" to int.
Definition except.hxx:283
\n-
Could not convert null value: target type does not support null.
Definition except.hxx:300
\n-
Could not convert value to string: not enough buffer space.
Definition except.hxx:313
\n-
Something is out of range, similar to std::out_of_range.
Definition except.hxx:326
\n-
Query returned an unexpected number of rows.
Definition except.hxx:343
\n-
unexpected_rows(std::string const &msg)
Definition except.hxx:351
\n-
Database feature not supported in current setup.
Definition except.hxx:358
\n-
feature_not_supported(std::string const &err, std::string const &Q="", char const sqlstate[]=nullptr)
Definition except.hxx:367
\n-
Error in data provided to SQL statement.
Definition except.hxx:377
\n-
data_exception(std::string const &err, std::string const &Q="", char const sqlstate[]=nullptr)
Definition except.hxx:386
\n-
Definition except.hxx:395
\n-
integrity_constraint_violation(std::string const &err, std::string const &Q="", char const sqlstate[]=nullptr)
Definition except.hxx:404
\n-
Definition except.hxx:413
\n-
restrict_violation(std::string const &err, std::string const &Q="", char const sqlstate[]=nullptr)
Definition except.hxx:422
\n-
Definition except.hxx:431
\n-
not_null_violation(std::string const &err, std::string const &Q="", char const sqlstate[]=nullptr)
Definition except.hxx:440
\n-
Definition except.hxx:449
\n-
foreign_key_violation(std::string const &err, std::string const &Q="", char const sqlstate[]=nullptr)
Definition except.hxx:458
\n-
Definition except.hxx:467
\n-
unique_violation(std::string const &err, std::string const &Q="", char const sqlstate[]=nullptr)
Definition except.hxx:476
\n-
Definition except.hxx:485
\n-
check_violation(std::string const &err, std::string const &Q="", char const sqlstate[]=nullptr)
Definition except.hxx:494
\n-
Definition except.hxx:503
\n-
invalid_cursor_state(std::string const &err, std::string const &Q="", char const sqlstate[]=nullptr)
Definition except.hxx:512
\n-
Definition except.hxx:521
\n-
invalid_sql_statement_name(std::string const &err, std::string const &Q="", char const sqlstate[]=nullptr)
Definition except.hxx:530
\n-
Definition except.hxx:539
\n-
invalid_cursor_name(std::string const &err, std::string const &Q="", char const sqlstate[]=nullptr)
Definition except.hxx:548
\n-
Definition except.hxx:557
\n-
syntax_error(std::string const &err, std::string const &Q="", char const sqlstate[]=nullptr, int pos=-1)
Definition except.hxx:569
\n-
int const error_position
Approximate position in string where error occurred, or -1 if unknown.
Definition except.hxx:559
\n-
Definition except.hxx:578
\n-
undefined_column(std::string const &err, std::string const &Q="", char const sqlstate[]=nullptr)
Definition except.hxx:588
\n-
Definition except.hxx:597
\n-
undefined_function(std::string const &err, std::string const &Q="", char const sqlstate[]=nullptr)
Definition except.hxx:607
\n-
Definition except.hxx:616
\n-
undefined_table(std::string const &err, std::string const &Q="", char const sqlstate[]=nullptr)
Definition except.hxx:626
\n-
Definition except.hxx:635
\n-
insufficient_privilege(std::string const &err, std::string const &Q="", char const sqlstate[]=nullptr)
Definition except.hxx:644
\n-
Resource shortage on the server.
Definition except.hxx:654
\n-
insufficient_resources(std::string const &err, std::string const &Q="", char const sqlstate[]=nullptr)
Definition except.hxx:663
\n-
Definition except.hxx:672
\n-
disk_full(std::string const &err, std::string const &Q="", char const sqlstate[]=nullptr)
Definition except.hxx:681
\n-
Definition except.hxx:690
\n-
out_of_memory(std::string const &err, std::string const &Q="", char const sqlstate[]=nullptr)
Definition except.hxx:699
\n-
Definition except.hxx:708
\n-
too_many_connections(std::string const &err)
Definition except.hxx:716
\n-
PL/pgSQL error.
Definition except.hxx:726
\n-
plpgsql_error(std::string const &err, std::string const &Q="", char const sqlstate[]=nullptr)
Definition except.hxx:735
\n-
Exception raised in PL/pgSQL procedure.
Definition except.hxx:745
\n-
plpgsql_raise(std::string const &err, std::string const &Q="", char const sqlstate[]=nullptr)
Definition except.hxx:754
\n-
Definition except.hxx:763
\n-
plpgsql_no_data_found(std::string const &err, std::string const &Q="", char const sqlstate[]=nullptr)
Definition except.hxx:772
\n-
Definition except.hxx:781
\n-
plpgsql_too_many_rows(std::string const &err, std::string const &Q="", char const sqlstate[]=nullptr)
Definition except.hxx:790
\n+
Processes several queries in FIFO manner, optimized for high throughput.
Definition pipeline.hxx:51
\n+
pipeline(transaction_base &t)
Start a pipeline.
Definition pipeline.hxx:63
\n+
pipeline & operator=(pipeline &&)=delete
\n+
bool empty() const noexcept
Definition pipeline.hxx:137
\n+
pipeline & operator=(pipeline const &)=delete
\n+
pipeline(transaction_base &t, std::string_view tname)
Start a pipeline. Assign it a name, for more helpful error messages.
Definition pipeline.hxx:68
\n+
pipeline(pipeline &&)=delete
\n+
pipeline(pipeline const &)=delete
\n+
long query_id
Identifying numbers for queries.
Definition pipeline.hxx:54
\n+
Result set containing data returned by a query or command.
Definition result.hxx:73
\n+
Interface definition (and common code) for "transaction" classes.
Definition transaction_base.hxx:88
\n+
Base class for things that monopolise a transaction's attention.
Definition transaction_focus.hxx:29
\n
\n
\n \n
\n \n
\n \n \n", "details": [{"source1": "html2text {}", "source2": "html2text {}", "unified_diff": "@@ -1,941 +1,208 @@\n \n \n \n \n \n libpqxx\u00a07.8.1\n \n-except.hxx\n- 1/* Definition of libpqxx exception classes.\n+pipeline.hxx\n+ 1/* Definition of the pqxx::pipeline class.\n 2 *\n- 3 * pqxx::sql_error, pqxx::broken_connection, pqxx::in_doubt_error, ...\n+ 3 * Throughput-optimized mechanism for executing queries.\n 4 *\n- 5 * DO NOT INCLUDE THIS FILE DIRECTLY; include pqxx/except instead.\n+ 5 * DO NOT INCLUDE THIS FILE DIRECTLY; include pqxx/pipeline instead.\n 6 *\n 7 * Copyright (c) 2000-2023, Jeroen T. Vermeulen.\n 8 *\n 9 * See COPYING for copyright license. If you did not receive a file called\n 10 * COPYING with this source code, please notify the distributor of this\n 11 * mistake, or contact the author.\n 12 */\n- 13#ifndef PQXX_H_EXCEPT\n- 14#define PQXX_H_EXCEPT\n+ 13#ifndef PQXX_H_PIPELINE\n+ 14#define PQXX_H_PIPELINE\n 15\n 16#if !defined(PQXX_HEADER_PRE)\n 17# error \"Include libpqxx headers as , not .\"\n 18#endif\n 19\n- 20#if pqxx_have_source_location\n- 21# include \n- 22#endif\n+ 20#include \n+ 21#include \n+ 22#include \n 23\n- 24#include \n- 25#include \n+ 24#include \"pqxx/transaction_base.hxx\"\n+ 25\n 26\n- 27\n- 28namespace pqxx\n- 29{\n-47struct PQXX_LIBEXPORT failure : std::runtime_error\n- 48{\n- 49#if pqxx_have_source_location\n- 50 explicit failure(\n- 51 std::string const &,\n- 52 std::source_location = std::source_location::current());\n- 53 std::source_location location;\n- 54#else\n- 55 explicit failure(std::string const &);\n- 56#endif\n- 57};\n- 58\n- 59\n+ 27namespace pqxx\n+ 28{\n+ 29// TODO: libpq 14 introduced a similar \"pipeline mode.\" Can we use that?\n+ 30\n+ 32\n+50class PQXX_LIBEXPORT pipeline : public transaction_focus\n+ 51{\n+ 52public:\n+54 using query_id = long;\n+ 55\n+56 pipeline(pipeline const &) = delete;\n+57 pipeline &operator=(pipeline const &) = delete;\n+58 pipeline(pipeline &&) = delete;\n+59 pipeline &operator=(pipeline &&) = delete;\n+ 60\n 61\n-80struct PQXX_LIBEXPORT broken_connection : failure\n- 81{\n- 82 broken_connection();\n- 83 explicit broken_connection(\n- 84 std::string const &\n- 85#if pqxx_have_source_location\n- 86 ,\n- 87 std::source_location = std::source_location::current()\n- 88#endif\n- 89 );\n- 90};\n- 91\n- 92\n+63 explicit pipeline(transaction_base &t) : transaction_focus{t, s_classname}\n+ 64 {\n+ 65 init();\n+ 66 }\n+68 pipeline(transaction_base &t, std::string_view tname) :\n+ 69 transaction_focus{t, s_classname, tname}\n+ 70 {\n+ 71 init();\n+ 72 }\n+ 73\n+ 75 ~pipeline() noexcept;\n+ 76\n+ 78\n+ 84 query_id insert(std::string_view) &;\n+ 85\n+ 87\n+ 93 void complete();\n 94\n-102struct PQXX_LIBEXPORT protocol_violation : broken_connection\n- 103{\n- 104 explicit protocol_violation(\n- 105 std::string const &\n- 106#if pqxx_have_source_location\n- 107 ,\n- 108 std::source_location = std::source_location::current()\n- 109#endif\n- 110 );\n- 111};\n- 112\n- 113\n-115struct PQXX_LIBEXPORT variable_set_to_null : failure\n- 116{\n- 117 explicit variable_set_to_null(\n- 118 std::string const &\n- 119#if pqxx_have_source_location\n- 120 ,\n- 121 std::source_location = std::source_location::current()\n- 122#endif\n- 123 );\n- 124};\n- 125\n- 126\n- 128\n-131class PQXX_LIBEXPORT sql_error : public failure\n- 132{\n- 134 std::string const m_query;\n- 136 std::string const m_sqlstate;\n- 137\n- 138public:\n- 139 explicit sql_error(\n- 140 std::string const &whatarg = \"\", std::string const &Q = \"\",\n- 141 char const sqlstate[] = nullptr\n- 142#if pqxx_have_source_location\n- 143 ,\n- 144 std::source_location = std::source_location::current()\n- 145#endif\n- 146 );\n-147 virtual ~sql_error() noexcept override;\n- 148\n- 150 [[nodiscard]] PQXX_PURE std::string const &query() const noexcept;\n- 151\n- 153 [[nodiscard]] PQXX_PURE std::string const &sqlstate() const noexcept;\n- 154};\n- 155\n- 156\n- 158\n-164struct PQXX_LIBEXPORT in_doubt_error : failure\n- 165{\n- 166 explicit in_doubt_error(\n- 167 std::string const &\n- 168#if pqxx_have_source_location\n- 169 ,\n- 170 std::source_location = std::source_location::current()\n- 171#endif\n- 172 );\n- 173};\n+ 96\n+ 105 void flush();\n+ 106\n+ 108\n+ 116 void cancel();\n+ 117\n+ 119 [[nodiscard]] bool is_finished(query_id) const;\n+ 120\n+ 122\n+128 result retrieve(query_id qid)\n+ 129 {\n+ 130 return retrieve(m_queries.find(qid)).second;\n+ 131 }\n+ 132\n+ 134\n+ 135 std::pair retrieve();\n+ 136\n+137 [[nodiscard]] bool empty() const noexcept { return std::empty(m_queries); }\n+ 138\n+ 141\n+ 152 int retain(int retain_max = 2) &;\n+ 153\n+ 154\n+ 156 void resume() &;\n+ 157\n+ 158private:\n+ 159 struct PQXX_PRIVATE Query\n+ 160 {\n+ 161 explicit Query(std::string_view q) :\n+ 162 query{std::make_shared(q)}\n+ 163 {}\n+ 164\n+ 165 std::shared_ptr query;\n+ 166 result res;\n+ 167 };\n+ 168\n+ 169 using QueryMap = std::map;\n+ 170\n+ 171 void init();\n+ 172 void attach();\n+ 173 void detach();\n 174\n- 175\n-177struct PQXX_LIBEXPORT transaction_rollback : sql_error\n- 178{\n- 179 explicit transaction_rollback(\n- 180 std::string const &whatarg, std::string const &q = \"\",\n- 181 char const sqlstate[] = nullptr\n- 182#if pqxx_have_source_location\n- 183 ,\n- 184 std::source_location = std::source_location::current()\n- 185#endif\n- 186 );\n- 187};\n- 188\n- 189\n- 191\n-199struct PQXX_LIBEXPORT serialization_failure : transaction_rollback\n- 200{\n- 201 explicit serialization_failure(\n- 202 std::string const &whatarg, std::string const &q,\n- 203 char const sqlstate[] = nullptr\n- 204#if pqxx_have_source_location\n- 205 ,\n- 206 std::source_location = std::source_location::current()\n- 207#endif\n- 208 );\n- 209};\n- 210\n+ 176 static constexpr query_id qid_limit() noexcept\n+ 177 {\n+ 178 // Parenthesise this to work around an eternal Visual C++ problem:\n+ 179 // Without the extra parentheses, unless NOMINMAX is defined, the\n+ 180 // preprocessor will mistake this \"max\" for its annoying built-in macro\n+ 181 // of the same name.\n+ 182 return (std::numeric_limits::max)();\n+ 183 }\n+ 184\n+ 186 PQXX_PRIVATE query_id generate_id();\n+ 187\n+ 188 bool have_pending() const noexcept\n+ 189 {\n+ 190 return m_issuedrange.second != m_issuedrange.first;\n+ 191 }\n+ 192\n+ 193 PQXX_PRIVATE void issue();\n+ 194\n+ 196 void set_error_at(query_id qid) noexcept\n+ 197 {\n+ 198 PQXX_UNLIKELY\n+ 199 if (qid < m_error)\n+ 200 m_error = qid;\n+ 201 }\n+ 202\n+ 204 [[noreturn]] PQXX_PRIVATE void internal_error(std::string const &err);\n+ 205\n+ 206 PQXX_PRIVATE bool obtain_result(bool expect_none = false);\n+ 207\n+ 208 PQXX_PRIVATE void obtain_dummy();\n+ 209 PQXX_PRIVATE void get_further_available_results();\n+ 210 PQXX_PRIVATE void check_end_results();\n 211\n-213struct PQXX_LIBEXPORT statement_completion_unknown : transaction_rollback\n- 214{\n- 215 explicit statement_completion_unknown(\n- 216 std::string const &whatarg, std::string const &q,\n- 217 char const sqlstate[] = nullptr\n- 218#if pqxx_have_source_location\n- 219 ,\n- 220 std::source_location = std::source_location::current()\n- 221#endif\n- 222 );\n- 223};\n+ 213 PQXX_PRIVATE void receive_if_available();\n+ 214\n+ 216 PQXX_PRIVATE void receive(pipeline::QueryMap::const_iterator stop);\n+ 217 std::pair retrieve(pipeline::QueryMap::\n+iterator);\n+ 218\n+ 219 QueryMap m_queries;\n+ 220 std::pair m_issuedrange;\n+ 221 int m_retain = 0;\n+ 222 int m_num_waiting = 0;\n+ 223 query_id m_q_id = 0;\n 224\n- 225\n-227struct PQXX_LIBEXPORT deadlock_detected : transaction_rollback\n- 228{\n- 229 explicit deadlock_detected(\n- 230 std::string const &whatarg, std::string const &q,\n- 231 char const sqlstate[] = nullptr\n- 232#if pqxx_have_source_location\n- 233 ,\n- 234 std::source_location = std::source_location::current()\n- 235#endif\n- 236 );\n- 237};\n- 238\n- 239\n-241struct PQXX_LIBEXPORT internal_error : std::logic_error\n- 242{\n- 243 explicit internal_error(std::string const &);\n- 244};\n- 245\n- 246\n-248struct PQXX_LIBEXPORT usage_error : std::logic_error\n- 249{\n- 250 explicit usage_error(\n- 251 std::string const &\n- 252#if pqxx_have_source_location\n- 253 ,\n- 254 std::source_location = std::source_location::current()\n- 255#endif\n- 256 );\n- 257\n- 258#if pqxx_have_source_location\n- 259 std::source_location location;\n- 260#endif\n- 261};\n- 262\n- 263\n-265struct PQXX_LIBEXPORT argument_error : std::invalid_argument\n- 266{\n- 267 explicit argument_error(\n- 268 std::string const &\n- 269#if pqxx_have_source_location\n- 270 ,\n- 271 std::source_location = std::source_location::current()\n- 272#endif\n- 273 );\n- 274\n- 275#if pqxx_have_source_location\n- 276 std::source_location location;\n- 277#endif\n- 278};\n- 279\n- 280\n-282struct PQXX_LIBEXPORT conversion_error : std::domain_error\n- 283{\n- 284 explicit conversion_error(\n- 285 std::string const &\n- 286#if pqxx_have_source_location\n- 287 ,\n- 288 std::source_location = std::source_location::current()\n- 289#endif\n- 290 );\n- 291\n- 292#if pqxx_have_source_location\n- 293 std::source_location location;\n- 294#endif\n- 295};\n- 296\n- 297\n-299struct PQXX_LIBEXPORT unexpected_null : conversion_error\n- 300{\n- 301 explicit unexpected_null(\n- 302 std::string const &\n- 303#if pqxx_have_source_location\n- 304 ,\n- 305 std::source_location = std::source_location::current()\n- 306#endif\n- 307 );\n- 308};\n- 309\n- 310\n-312struct PQXX_LIBEXPORT conversion_overrun : conversion_error\n- 313{\n- 314 explicit conversion_overrun(\n- 315 std::string const &\n- 316#if pqxx_have_source_location\n- 317 ,\n- 318 std::source_location = std::source_location::current()\n- 319#endif\n- 320 );\n- 321};\n- 322\n- 323\n-325struct PQXX_LIBEXPORT range_error : std::out_of_range\n- 326{\n- 327 explicit range_error(\n- 328 std::string const &\n- 329#if pqxx_have_source_location\n- 330 ,\n- 331 std::source_location = std::source_location::current()\n- 332#endif\n- 333 );\n- 334\n- 335#if pqxx_have_source_location\n- 336 std::source_location location;\n- 337#endif\n- 338};\n- 339\n- 340\n-342struct PQXX_LIBEXPORT unexpected_rows : public range_error\n- 343{\n- 344#if pqxx_have_source_location\n- 345 explicit unexpected_rows(\n- 346 std::string const &msg,\n- 347 std::source_location loc = std::source_location::current()) :\n- 348 range_error{msg, loc}\n- 349 {}\n- 350#else\n-351 explicit unexpected_rows(std::string const &msg) : range_error{msg} {}\n- 352#endif\n- 353};\n- 354\n- 355\n-357struct PQXX_LIBEXPORT feature_not_supported : sql_error\n- 358{\n- 359#if pqxx_have_source_location\n- 360 explicit feature_not_supported(\n- 361 std::string const &err, std::string const &Q = \"\",\n- 362 char const sqlstate[] = nullptr,\n- 363 std::source_location loc = std::source_location::current()) :\n- 364 sql_error{err, Q, sqlstate, loc}\n- 365 {}\n- 366#else\n-367 explicit feature_not_supported(\n- 368 std::string const &err, std::string const &Q = \"\",\n- 369 char const sqlstate[] = nullptr) :\n- 370 sql_error{err, Q, sqlstate}\n- 371 {}\n- 372#endif\n- 373};\n- 374\n-376struct PQXX_LIBEXPORT data_exception : sql_error\n- 377{\n- 378#if pqxx_have_source_location\n- 379 explicit data_exception(\n- 380 std::string const &err, std::string const &Q = \"\",\n- 381 char const sqlstate[] = nullptr,\n- 382 std::source_location loc = std::source_location::current()) :\n- 383 sql_error{err, Q, sqlstate, loc}\n- 384 {}\n- 385#else\n-386 explicit data_exception(\n- 387 std::string const &err, std::string const &Q = \"\",\n- 388 char const sqlstate[] = nullptr) :\n- 389 sql_error{err, Q, sqlstate}\n- 390 {}\n- 391#endif\n- 392};\n- 393\n-394struct PQXX_LIBEXPORT integrity_constraint_violation : sql_error\n- 395{\n- 396#if pqxx_have_source_location\n- 397 explicit integrity_constraint_violation(\n- 398 std::string const &err, std::string const &Q = \"\",\n- 399 char const sqlstate[] = nullptr,\n- 400 std::source_location loc = std::source_location::current()) :\n- 401 sql_error{err, Q, sqlstate, loc}\n- 402 {}\n- 403#else\n-404 explicit integrity_constraint_violation(\n- 405 std::string const &err, std::string const &Q = \"\",\n- 406 char const sqlstate[] = nullptr) :\n- 407 sql_error{err, Q, sqlstate}\n- 408 {}\n- 409#endif\n- 410};\n- 411\n-412struct PQXX_LIBEXPORT restrict_violation : integrity_constraint_violation\n- 413{\n- 414#if pqxx_have_source_location\n- 415 explicit restrict_violation(\n- 416 std::string const &err, std::string const &Q = \"\",\n- 417 char const sqlstate[] = nullptr,\n- 418 std::source_location loc = std::source_location::current()) :\n- 419 integrity_constraint_violation{err, Q, sqlstate, loc}\n- 420 {}\n- 421#else\n-422 explicit restrict_violation(\n- 423 std::string const &err, std::string const &Q = \"\",\n- 424 char const sqlstate[] = nullptr) :\n- 425 integrity_constraint_violation{err, Q, sqlstate}\n- 426 {}\n- 427#endif\n- 428};\n- 429\n-430struct PQXX_LIBEXPORT not_null_violation : integrity_constraint_violation\n- 431{\n- 432#if pqxx_have_source_location\n- 433 explicit not_null_violation(\n- 434 std::string const &err, std::string const &Q = \"\",\n- 435 char const sqlstate[] = nullptr,\n- 436 std::source_location loc = std::source_location::current()) :\n- 437 integrity_constraint_violation{err, Q, sqlstate, loc}\n- 438 {}\n- 439#else\n-440 explicit not_null_violation(\n- 441 std::string const &err, std::string const &Q = \"\",\n- 442 char const sqlstate[] = nullptr) :\n- 443 integrity_constraint_violation{err, Q, sqlstate}\n- 444 {}\n- 445#endif\n- 446};\n- 447\n-448struct PQXX_LIBEXPORT foreign_key_violation : integrity_constraint_violation\n- 449{\n- 450#if pqxx_have_source_location\n- 451 explicit foreign_key_violation(\n- 452 std::string const &err, std::string const &Q = \"\",\n- 453 char const sqlstate[] = nullptr,\n- 454 std::source_location loc = std::source_location::current()) :\n- 455 integrity_constraint_violation{err, Q, sqlstate, loc}\n- 456 {}\n- 457#else\n-458 explicit foreign_key_violation(\n- 459 std::string const &err, std::string const &Q = \"\",\n- 460 char const sqlstate[] = nullptr) :\n- 461 integrity_constraint_violation{err, Q, sqlstate}\n- 462 {}\n- 463#endif\n- 464};\n- 465\n-466struct PQXX_LIBEXPORT unique_violation : integrity_constraint_violation\n- 467{\n- 468#if pqxx_have_source_location\n- 469 explicit unique_violation(\n- 470 std::string const &err, std::string const &Q = \"\",\n- 471 char const sqlstate[] = nullptr,\n- 472 std::source_location loc = std::source_location::current()) :\n- 473 integrity_constraint_violation{err, Q, sqlstate, loc}\n- 474 {}\n- 475#else\n-476 explicit unique_violation(\n- 477 std::string const &err, std::string const &Q = \"\",\n- 478 char const sqlstate[] = nullptr) :\n- 479 integrity_constraint_violation{err, Q, sqlstate}\n- 480 {}\n- 481#endif\n- 482};\n- 483\n-484struct PQXX_LIBEXPORT check_violation : integrity_constraint_violation\n- 485{\n- 486#if pqxx_have_source_location\n- 487 explicit check_violation(\n- 488 std::string const &err, std::string const &Q = \"\",\n- 489 char const sqlstate[] = nullptr,\n- 490 std::source_location loc = std::source_location::current()) :\n- 491 integrity_constraint_violation{err, Q, sqlstate, loc}\n- 492 {}\n- 493#else\n-494 explicit check_violation(\n- 495 std::string const &err, std::string const &Q = \"\",\n- 496 char const sqlstate[] = nullptr) :\n- 497 integrity_constraint_violation{err, Q, sqlstate}\n- 498 {}\n- 499#endif\n- 500};\n- 501\n-502struct PQXX_LIBEXPORT invalid_cursor_state : sql_error\n- 503{\n- 504#if pqxx_have_source_location\n- 505 explicit invalid_cursor_state(\n- 506 std::string const &err, std::string const &Q = \"\",\n- 507 char const sqlstate[] = nullptr,\n- 508 std::source_location loc = std::source_location::current()) :\n- 509 sql_error{err, Q, sqlstate, loc}\n- 510 {}\n- 511#else\n-512 explicit invalid_cursor_state(\n- 513 std::string const &err, std::string const &Q = \"\",\n- 514 char const sqlstate[] = nullptr) :\n- 515 sql_error{err, Q, sqlstate}\n- 516 {}\n- 517#endif\n- 518};\n- 519\n-520struct PQXX_LIBEXPORT invalid_sql_statement_name : sql_error\n- 521{\n- 522#if pqxx_have_source_location\n- 523 explicit invalid_sql_statement_name(\n- 524 std::string const &err, std::string const &Q = \"\",\n- 525 char const sqlstate[] = nullptr,\n- 526 std::source_location loc = std::source_location::current()) :\n- 527 sql_error{err, Q, sqlstate, loc}\n- 528 {}\n- 529#else\n-530 explicit invalid_sql_statement_name(\n- 531 std::string const &err, std::string const &Q = \"\",\n- 532 char const sqlstate[] = nullptr) :\n- 533 sql_error{err, Q, sqlstate}\n- 534 {}\n- 535#endif\n- 536};\n- 537\n-538struct PQXX_LIBEXPORT invalid_cursor_name : sql_error\n- 539{\n- 540#if pqxx_have_source_location\n- 541 explicit invalid_cursor_name(\n- 542 std::string const &err, std::string const &Q = \"\",\n- 543 char const sqlstate[] = nullptr,\n- 544 std::source_location loc = std::source_location::current()) :\n- 545 sql_error{err, Q, sqlstate, loc}\n- 546 {}\n- 547#else\n-548 explicit invalid_cursor_name(\n- 549 std::string const &err, std::string const &Q = \"\",\n- 550 char const sqlstate[] = nullptr) :\n- 551 sql_error{err, Q, sqlstate}\n- 552 {}\n- 553#endif\n- 554};\n- 555\n-556struct PQXX_LIBEXPORT syntax_error : sql_error\n- 557{\n-559 int const error_position;\n- 560\n- 561#if pqxx_have_source_location\n- 562 explicit syntax_error(\n- 563 std::string const &err, std::string const &Q = \"\",\n- 564 char const sqlstate[] = nullptr, int pos = -1,\n- 565 std::source_location loc = std::source_location::current()) :\n- 566 sql_error{err, Q, sqlstate, loc}, error_position{pos}\n- 567 {}\n- 568#else\n-569 explicit syntax_error(\n- 570 std::string const &err, std::string const &Q = \"\",\n- 571 char const sqlstate[] = nullptr, int pos = -1) :\n- 572 sql_error{err, Q, sqlstate}, error_position{pos}\n- 573 {}\n- 574#endif\n- 575};\n- 576\n-577struct PQXX_LIBEXPORT undefined_column : syntax_error\n- 578{\n- 579#if pqxx_have_source_location\n- 580 explicit undefined_column(\n- 581 std::string const &err, std::string const &Q = \"\",\n- 582 char const sqlstate[] = nullptr,\n- 583 std::source_location loc = std::source_location::current()) :\n- 584 // TODO: Can we get the column?\n- 585 syntax_error{err, Q, sqlstate, -1, loc}\n- 586 {}\n- 587#else\n-588 explicit undefined_column(\n- 589 std::string const &err, std::string const &Q = \"\",\n- 590 char const sqlstate[] = nullptr) :\n- 591 syntax_error{err, Q, sqlstate}\n- 592 {}\n- 593#endif\n- 594};\n- 595\n-596struct PQXX_LIBEXPORT undefined_function : syntax_error\n- 597{\n- 598#if pqxx_have_source_location\n- 599 explicit undefined_function(\n- 600 std::string const &err, std::string const &Q = \"\",\n- 601 char const sqlstate[] = nullptr,\n- 602 std::source_location loc = std::source_location::current()) :\n- 603 // TODO: Can we get the column?\n- 604 syntax_error{err, Q, sqlstate, -1, loc}\n- 605 {}\n- 606#else\n-607 explicit undefined_function(\n- 608 std::string const &err, std::string const &Q = \"\",\n- 609 char const sqlstate[] = nullptr) :\n- 610 syntax_error{err, Q, sqlstate}\n- 611 {}\n- 612#endif\n- 613};\n- 614\n-615struct PQXX_LIBEXPORT undefined_table : syntax_error\n- 616{\n- 617#if pqxx_have_source_location\n- 618 explicit undefined_table(\n- 619 std::string const &err, std::string const &Q = \"\",\n- 620 char const sqlstate[] = nullptr,\n- 621 std::source_location loc = std::source_location::current()) :\n- 622 // TODO: Can we get the column?\n- 623 syntax_error{err, Q, sqlstate, -1, loc}\n- 624 {}\n- 625#else\n-626 explicit undefined_table(\n- 627 std::string const &err, std::string const &Q = \"\",\n- 628 char const sqlstate[] = nullptr) :\n- 629 syntax_error{err, Q, sqlstate}\n- 630 {}\n- 631#endif\n- 632};\n- 633\n-634struct PQXX_LIBEXPORT insufficient_privilege : sql_error\n- 635{\n- 636#if pqxx_have_source_location\n- 637 explicit insufficient_privilege(\n- 638 std::string const &err, std::string const &Q = \"\",\n- 639 char const sqlstate[] = nullptr,\n- 640 std::source_location loc = std::source_location::current()) :\n- 641 sql_error{err, Q, sqlstate, loc}\n- 642 {}\n- 643#else\n-644 explicit insufficient_privilege(\n- 645 std::string const &err, std::string const &Q = \"\",\n- 646 char const sqlstate[] = nullptr) :\n- 647 sql_error{err, Q, sqlstate}\n- 648 {}\n- 649#endif\n- 650};\n- 651\n-653struct PQXX_LIBEXPORT insufficient_resources : sql_error\n- 654{\n- 655#if pqxx_have_source_location\n- 656 explicit insufficient_resources(\n- 657 std::string const &err, std::string const &Q = \"\",\n- 658 char const sqlstate[] = nullptr,\n- 659 std::source_location loc = std::source_location::current()) :\n- 660 sql_error{err, Q, sqlstate, loc}\n- 661 {}\n- 662#else\n-663 explicit insufficient_resources(\n- 664 std::string const &err, std::string const &Q = \"\",\n- 665 char const sqlstate[] = nullptr) :\n- 666 sql_error{err, Q, sqlstate}\n- 667 {}\n- 668#endif\n- 669};\n- 670\n-671struct PQXX_LIBEXPORT disk_full : insufficient_resources\n- 672{\n- 673#if pqxx_have_source_location\n- 674 explicit disk_full(\n- 675 std::string const &err, std::string const &Q = \"\",\n- 676 char const sqlstate[] = nullptr,\n- 677 std::source_location loc = std::source_location::current()) :\n- 678 insufficient_resources{err, Q, sqlstate, loc}\n- 679 {}\n- 680#else\n-681 explicit disk_full(\n- 682 std::string const &err, std::string const &Q = \"\",\n- 683 char const sqlstate[] = nullptr) :\n- 684 insufficient_resources{err, Q, sqlstate}\n- 685 {}\n- 686#endif\n- 687};\n- 688\n-689struct PQXX_LIBEXPORT out_of_memory : insufficient_resources\n- 690{\n- 691#if pqxx_have_source_location\n- 692 explicit out_of_memory(\n- 693 std::string const &err, std::string const &Q = \"\",\n- 694 char const sqlstate[] = nullptr,\n- 695 std::source_location loc = std::source_location::current()) :\n- 696 insufficient_resources{err, Q, sqlstate, loc}\n- 697 {}\n- 698#else\n-699 explicit out_of_memory(\n- 700 std::string const &err, std::string const &Q = \"\",\n- 701 char const sqlstate[] = nullptr) :\n- 702 insufficient_resources{err, Q, sqlstate}\n- 703 {}\n- 704#endif\n- 705};\n- 706\n-707struct PQXX_LIBEXPORT too_many_connections : broken_connection\n- 708{\n- 709#if pqxx_have_source_location\n- 710 explicit too_many_connections(\n- 711 std::string const &err,\n- 712 std::source_location loc = std::source_location::current()) :\n- 713 broken_connection{err, loc}\n- 714 {}\n- 715#else\n-716 explicit too_many_connections(std::string const &err) :\n- 717 broken_connection{err}\n- 718 {}\n- 719#endif\n- 720};\n- 721\n- 723\n-725struct PQXX_LIBEXPORT plpgsql_error : sql_error\n- 726{\n- 727#if pqxx_have_source_location\n- 728 explicit plpgsql_error(\n- 729 std::string const &err, std::string const &Q = \"\",\n- 730 char const sqlstate[] = nullptr,\n- 731 std::source_location loc = std::source_location::current()) :\n- 732 sql_error{err, Q, sqlstate, loc}\n- 733 {}\n- 734#else\n-735 explicit plpgsql_error(\n- 736 std::string const &err, std::string const &Q = \"\",\n- 737 char const sqlstate[] = nullptr) :\n- 738 sql_error{err, Q, sqlstate}\n- 739 {}\n- 740#endif\n- 741};\n- 742\n-744struct PQXX_LIBEXPORT plpgsql_raise : plpgsql_error\n- 745{\n- 746#if pqxx_have_source_location\n- 747 explicit plpgsql_raise(\n- 748 std::string const &err, std::string const &Q = \"\",\n- 749 char const sqlstate[] = nullptr,\n- 750 std::source_location loc = std::source_location::current()) :\n- 751 plpgsql_error{err, Q, sqlstate, loc}\n- 752 {}\n- 753#else\n-754 explicit plpgsql_raise(\n- 755 std::string const &err, std::string const &Q = \"\",\n- 756 char const sqlstate[] = nullptr) :\n- 757 plpgsql_error{err, Q, sqlstate}\n- 758 {}\n- 759#endif\n- 760};\n- 761\n-762struct PQXX_LIBEXPORT plpgsql_no_data_found : plpgsql_error\n- 763{\n- 764#if pqxx_have_source_location\n- 765 explicit plpgsql_no_data_found(\n- 766 std::string const &err, std::string const &Q = \"\",\n- 767 char const sqlstate[] = nullptr,\n- 768 std::source_location loc = std::source_location::current()) :\n- 769 plpgsql_error{err, Q, sqlstate, loc}\n- 770 {}\n- 771#else\n-772 explicit plpgsql_no_data_found(\n- 773 std::string const &err, std::string const &Q = \"\",\n- 774 char const sqlstate[] = nullptr) :\n- 775 plpgsql_error{err, Q, sqlstate}\n- 776 {}\n- 777#endif\n- 778};\n- 779\n-780struct PQXX_LIBEXPORT plpgsql_too_many_rows : plpgsql_error\n- 781{\n- 782#if pqxx_have_source_location\n- 783 explicit plpgsql_too_many_rows(\n- 784 std::string const &err, std::string const &Q = \"\",\n- 785 char const sqlstate[] = nullptr,\n- 786 std::source_location loc = std::source_location::current()) :\n- 787 plpgsql_error{err, Q, sqlstate, loc}\n- 788 {}\n- 789#else\n-790 explicit plpgsql_too_many_rows(\n- 791 std::string const &err, std::string const &Q = \"\",\n- 792 char const sqlstate[] = nullptr) :\n- 793 plpgsql_error{err, Q, sqlstate}\n- 794 {}\n- 795#endif\n- 796};\n- 797\n- 801} // namespace pqxx\n- 802#endif\n+ 226 bool m_dummy_pending = false;\n+ 227\n+ 229 query_id m_error = qid_limit();\n+ 230\n+ 232\n+ 235 internal::encoding_group m_encoding;\n+ 236\n+ 237 static constexpr std::string_view s_classname{\"pipeline\"};\n+ 238};\n+ 239} // namespace pqxx\n+ 240#endif\n pqxx\n The home of all libpqxx classes, functions, templates, etc.\n Definition array.hxx:33\n-pqxx::failure\n-Run-time failure encountered by libpqxx, similar to std::runtime_error.\n-Definition except.hxx:48\n-pqxx::broken_connection\n-Exception class for lost or failed backend connection.\n-Definition except.hxx:81\n-pqxx::protocol_violation\n-Exception class for micommunication with the server.\n-Definition except.hxx:103\n-pqxx::variable_set_to_null\n-The caller attempted to set a variable to null, which is not allowed.\n-Definition except.hxx:116\n-pqxx::sql_error\n-Exception class for failed queries.\n-Definition except.hxx:132\n-pqxx::sql_error::~sql_error\n-virtual ~sql_error() noexcept override\n-pqxx::in_doubt_error\n-\"Help, I don't know whether transaction was committed successfully!\"\n-Definition except.hxx:165\n-pqxx::transaction_rollback\n-The backend saw itself forced to roll back the ongoing transaction.\n-Definition except.hxx:178\n-pqxx::serialization_failure\n-Transaction failed to serialize. Please retry it.\n-Definition except.hxx:200\n-pqxx::statement_completion_unknown\n-We can't tell whether our last statement succeeded.\n-Definition except.hxx:214\n-pqxx::deadlock_detected\n-The ongoing transaction has deadlocked. Retrying it may help.\n-Definition except.hxx:228\n-pqxx::internal_error\n-Internal error in libpqxx library.\n-Definition except.hxx:242\n-pqxx::usage_error\n-Error in usage of libpqxx library, similar to std::logic_error.\n-Definition except.hxx:249\n-pqxx::argument_error\n-Invalid argument passed to libpqxx, similar to std::invalid_argument.\n-Definition except.hxx:266\n-pqxx::conversion_error\n-Value conversion failed, e.g. when converting \"Hello\" to int.\n-Definition except.hxx:283\n-pqxx::unexpected_null\n-Could not convert null value: target type does not support null.\n-Definition except.hxx:300\n-pqxx::conversion_overrun\n-Could not convert value to string: not enough buffer space.\n-Definition except.hxx:313\n-pqxx::range_error\n-Something is out of range, similar to std::out_of_range.\n-Definition except.hxx:326\n-pqxx::unexpected_rows\n-Query returned an unexpected number of rows.\n-Definition except.hxx:343\n-pqxx::unexpected_rows::unexpected_rows\n-unexpected_rows(std::string const &msg)\n-Definition except.hxx:351\n-pqxx::feature_not_supported\n-Database feature not supported in current setup.\n-Definition except.hxx:358\n-pqxx::feature_not_supported::feature_not_supported\n-feature_not_supported(std::string const &err, std::string const &Q=\"\", char\n-const sqlstate[]=nullptr)\n-Definition except.hxx:367\n-pqxx::data_exception\n-Error in data provided to SQL statement.\n-Definition except.hxx:377\n-pqxx::data_exception::data_exception\n-data_exception(std::string const &err, std::string const &Q=\"\", char const\n-sqlstate[]=nullptr)\n-Definition except.hxx:386\n-pqxx::integrity_constraint_violation\n-Definition except.hxx:395\n-pqxx::integrity_constraint_violation::integrity_constraint_violation\n-integrity_constraint_violation(std::string const &err, std::string const &Q=\"\",\n-char const sqlstate[]=nullptr)\n-Definition except.hxx:404\n-pqxx::restrict_violation\n-Definition except.hxx:413\n-pqxx::restrict_violation::restrict_violation\n-restrict_violation(std::string const &err, std::string const &Q=\"\", char const\n-sqlstate[]=nullptr)\n-Definition except.hxx:422\n-pqxx::not_null_violation\n-Definition except.hxx:431\n-pqxx::not_null_violation::not_null_violation\n-not_null_violation(std::string const &err, std::string const &Q=\"\", char const\n-sqlstate[]=nullptr)\n-Definition except.hxx:440\n-pqxx::foreign_key_violation\n-Definition except.hxx:449\n-pqxx::foreign_key_violation::foreign_key_violation\n-foreign_key_violation(std::string const &err, std::string const &Q=\"\", char\n-const sqlstate[]=nullptr)\n-Definition except.hxx:458\n-pqxx::unique_violation\n-Definition except.hxx:467\n-pqxx::unique_violation::unique_violation\n-unique_violation(std::string const &err, std::string const &Q=\"\", char const\n-sqlstate[]=nullptr)\n-Definition except.hxx:476\n-pqxx::check_violation\n-Definition except.hxx:485\n-pqxx::check_violation::check_violation\n-check_violation(std::string const &err, std::string const &Q=\"\", char const\n-sqlstate[]=nullptr)\n-Definition except.hxx:494\n-pqxx::invalid_cursor_state\n-Definition except.hxx:503\n-pqxx::invalid_cursor_state::invalid_cursor_state\n-invalid_cursor_state(std::string const &err, std::string const &Q=\"\", char\n-const sqlstate[]=nullptr)\n-Definition except.hxx:512\n-pqxx::invalid_sql_statement_name\n-Definition except.hxx:521\n-pqxx::invalid_sql_statement_name::invalid_sql_statement_name\n-invalid_sql_statement_name(std::string const &err, std::string const &Q=\"\",\n-char const sqlstate[]=nullptr)\n-Definition except.hxx:530\n-pqxx::invalid_cursor_name\n-Definition except.hxx:539\n-pqxx::invalid_cursor_name::invalid_cursor_name\n-invalid_cursor_name(std::string const &err, std::string const &Q=\"\", char const\n-sqlstate[]=nullptr)\n-Definition except.hxx:548\n-pqxx::syntax_error\n-Definition except.hxx:557\n-pqxx::syntax_error::syntax_error\n-syntax_error(std::string const &err, std::string const &Q=\"\", char const\n-sqlstate[]=nullptr, int pos=-1)\n-Definition except.hxx:569\n-pqxx::syntax_error::error_position\n-int const error_position\n-Approximate position in string where error occurred, or -1 if unknown.\n-Definition except.hxx:559\n-pqxx::undefined_column\n-Definition except.hxx:578\n-pqxx::undefined_column::undefined_column\n-undefined_column(std::string const &err, std::string const &Q=\"\", char const\n-sqlstate[]=nullptr)\n-Definition except.hxx:588\n-pqxx::undefined_function\n-Definition except.hxx:597\n-pqxx::undefined_function::undefined_function\n-undefined_function(std::string const &err, std::string const &Q=\"\", char const\n-sqlstate[]=nullptr)\n-Definition except.hxx:607\n-pqxx::undefined_table\n-Definition except.hxx:616\n-pqxx::undefined_table::undefined_table\n-undefined_table(std::string const &err, std::string const &Q=\"\", char const\n-sqlstate[]=nullptr)\n-Definition except.hxx:626\n-pqxx::insufficient_privilege\n-Definition except.hxx:635\n-pqxx::insufficient_privilege::insufficient_privilege\n-insufficient_privilege(std::string const &err, std::string const &Q=\"\", char\n-const sqlstate[]=nullptr)\n-Definition except.hxx:644\n-pqxx::insufficient_resources\n-Resource shortage on the server.\n-Definition except.hxx:654\n-pqxx::insufficient_resources::insufficient_resources\n-insufficient_resources(std::string const &err, std::string const &Q=\"\", char\n-const sqlstate[]=nullptr)\n-Definition except.hxx:663\n-pqxx::disk_full\n-Definition except.hxx:672\n-pqxx::disk_full::disk_full\n-disk_full(std::string const &err, std::string const &Q=\"\", char const sqlstate\n-[]=nullptr)\n-Definition except.hxx:681\n-pqxx::out_of_memory\n-Definition except.hxx:690\n-pqxx::out_of_memory::out_of_memory\n-out_of_memory(std::string const &err, std::string const &Q=\"\", char const\n-sqlstate[]=nullptr)\n-Definition except.hxx:699\n-pqxx::too_many_connections\n-Definition except.hxx:708\n-pqxx::too_many_connections::too_many_connections\n-too_many_connections(std::string const &err)\n-Definition except.hxx:716\n-pqxx::plpgsql_error\n-PL/pgSQL error.\n-Definition except.hxx:726\n-pqxx::plpgsql_error::plpgsql_error\n-plpgsql_error(std::string const &err, std::string const &Q=\"\", char const\n-sqlstate[]=nullptr)\n-Definition except.hxx:735\n-pqxx::plpgsql_raise\n-Exception raised in PL/pgSQL procedure.\n-Definition except.hxx:745\n-pqxx::plpgsql_raise::plpgsql_raise\n-plpgsql_raise(std::string const &err, std::string const &Q=\"\", char const\n-sqlstate[]=nullptr)\n-Definition except.hxx:754\n-pqxx::plpgsql_no_data_found\n-Definition except.hxx:763\n-pqxx::plpgsql_no_data_found::plpgsql_no_data_found\n-plpgsql_no_data_found(std::string const &err, std::string const &Q=\"\", char\n-const sqlstate[]=nullptr)\n-Definition except.hxx:772\n-pqxx::plpgsql_too_many_rows\n-Definition except.hxx:781\n-pqxx::plpgsql_too_many_rows::plpgsql_too_many_rows\n-plpgsql_too_many_rows(std::string const &err, std::string const &Q=\"\", char\n-const sqlstate[]=nullptr)\n-Definition except.hxx:790\n+pqxx::pipeline\n+Processes several queries in FIFO manner, optimized for high throughput.\n+Definition pipeline.hxx:51\n+pqxx::pipeline::pipeline\n+pipeline(transaction_base &t)\n+Start a pipeline.\n+Definition pipeline.hxx:63\n+pqxx::pipeline::operator=\n+pipeline & operator=(pipeline &&)=delete\n+pqxx::pipeline::empty\n+bool empty() const noexcept\n+Definition pipeline.hxx:137\n+pqxx::pipeline::operator=\n+pipeline & operator=(pipeline const &)=delete\n+pqxx::pipeline::pipeline\n+pipeline(transaction_base &t, std::string_view tname)\n+Start a pipeline. Assign it a name, for more helpful error messages.\n+Definition pipeline.hxx:68\n+pqxx::pipeline::pipeline\n+pipeline(pipeline &&)=delete\n+pqxx::pipeline::pipeline\n+pipeline(pipeline const &)=delete\n+pqxx::pipeline::query_id\n+long query_id\n+Identifying numbers for queries.\n+Definition pipeline.hxx:54\n+pqxx::result\n+Result set containing data returned by a query or command.\n+Definition result.hxx:73\n+pqxx::transaction_base\n+Interface definition (and common code) for \"transaction\" classes.\n+Definition transaction_base.hxx:88\n+pqxx::transaction_focus\n+Base class for things that monopolise a transaction's attention.\n+Definition transaction_focus.hxx:29\n * include\n * pqxx\n- * except.hxx\n+ * pipeline.hxx\n * Generated by [doxygen] 1.9.8\n"}]}, {"source1": "./usr/share/doc/libpqxx-doc/html/a00008_source.html", "source2": "./usr/share/doc/libpqxx-doc/html/a00008_source.html", "unified_diff": "@@ -1,15 +1,15 @@\n \n \n \n \n \n \n \n-libpqxx: util.hxx Source File\n+libpqxx: separated_list.hxx Source File\n \n \n \n \n \n \n \n@@ -60,550 +60,165 @@\n \n
\n
\n-
util.hxx
\n+
separated_list.hxx
\n
\n
\n-
1/* Various utility definitions for libpqxx.
\n+
1/* Helper similar to Python's `str.join()`.
\n
2 *
\n-
3 * DO NOT INCLUDE THIS FILE DIRECTLY; include pqxx/util instead.
\n+
3 * DO NOT INCLUDE THIS FILE DIRECTLY; include pqxx/separated_list instead.
\n
4 *
\n
5 * Copyright (c) 2000-2023, Jeroen T. Vermeulen.
\n
6 *
\n
7 * See COPYING for copyright license. If you did not receive a file called
\n
8 * COPYING with this source code, please notify the distributor of this
\n
9 * mistake, or contact the author.
\n
10 */
\n-
11#ifndef PQXX_H_UTIL
\n-
12#define PQXX_H_UTIL
\n+
11#ifndef PQXX_H_SEPARATED_LIST
\n+
12#define PQXX_H_SEPARATED_LIST
\n
13
\n
14#if !defined(PQXX_HEADER_PRE)
\n
15# error "Include libpqxx headers as <pqxx/header>, not <pqxx/header.hxx>."
\n
16#endif
\n
17
\n-
18#include <cassert>
\n-
19#include <cctype>
\n-
20#include <cerrno>
\n-
21#include <cstdio>
\n-
22#include <cstring>
\n-
23#include <functional>
\n-
24#include <iterator>
\n-
25#include <limits>
\n-
26#include <memory>
\n-
27#include <stdexcept>
\n-
28#include <string>
\n-
29#include <string_view>
\n-
30#include <type_traits>
\n-
31#include <typeinfo>
\n-
32#include <utility>
\n-
33#include <vector>
\n+
18#include <algorithm>
\n+
19#include <numeric>
\n+
20
\n+
21#include "pqxx/strconv.hxx"
\n+
22
\n+
23// C++20: Simplify using std::ranges::range.
\n+
24// C++20: Optimise buffer allocation using random_access_range/iterator.
\n+
25// TODO: Can we pass separators at compile time?
\n+
26namespace pqxx
\n+
27{
\n+
32
\n
34
\n-
35#include "pqxx/except.hxx"
\n-
36#include "pqxx/types.hxx"
\n-
37#include "pqxx/version.hxx"
\n-
38
\n-
39
\n-
41namespace pqxx
\n-
42{}
\n-
43
\n-
44#include <pqxx/internal/libpq-forward.hxx>
\n-
45
\n-
46
\n-
47// C++23: Retire wrapper.
\n-
48#if pqxx_have_unreachable
\n-
50# define PQXX_UNREACHABLE std::unreachable()
\n-
51#else
\n-
52# define PQXX_UNREACHABLE assert(false)
\n-
53#endif
\n-
54
\n-
55
\n-
57namespace pqxx::internal
\n-
58{
\n-
59
\n-
60// C++20: Retire wrapper.
\n-
62template<typename LEFT, typename RIGHT>
\n-
\n-
63inline constexpr bool cmp_less(LEFT lhs, RIGHT rhs) noexcept
\n-
64{
\n-
65#if defined(PQXX_HAVE_CMP)
\n-
66 return std::cmp_less(lhs, rhs);
\n-
67#else
\n-
68 // We need a variable just because lgtm.com gives off a false positive
\n-
69 // warning when we compare the values directly. It considers that a
\n-
70 // "self-comparison."
\n-
71 constexpr bool left_signed{std::is_signed_v<LEFT>};
\n-
72 if constexpr (left_signed == std::is_signed_v<RIGHT>)
\n-
73 return lhs < rhs;
\n-
74 else if constexpr (std::is_signed_v<LEFT>)
\n-
75 return (lhs <= 0) ? true : (std::make_unsigned_t<LEFT>(lhs) < rhs);
\n-
76 else
\n-
77 return (rhs <= 0) ? false : (lhs < std::make_unsigned_t<RIGHT>(rhs));
\n-
78#endif
\n-
79}
\n-
\n-
80
\n-
81
\n-
82// C++20: Retire wrapper.
\n-
84template<typename LEFT, typename RIGHT>
\n-
\n-
85inline constexpr bool cmp_greater(LEFT lhs, RIGHT rhs) noexcept
\n-
86{
\n-
87#if defined(PQXX_HAVE_CMP)
\n-
88 return std::cmp_greater(lhs, rhs);
\n-
89#else
\n-
90 return cmp_less(rhs, lhs);
\n-
91#endif
\n-
92}
\n-
\n-
93
\n-
94
\n-
95// C++20: Retire wrapper.
\n-
97template<typename LEFT, typename RIGHT>
\n-
\n-
98inline constexpr bool cmp_less_equal(LEFT lhs, RIGHT rhs) noexcept
\n-
99{
\n-
100#if defined(PQXX_HAVE_CMP)
\n-
101 return std::cmp_less_equal(lhs, rhs);
\n-
102#else
\n-
103 return not cmp_less(rhs, lhs);
\n-
104#endif
\n+
42template<typename ITER, typename ACCESS>
\n+
43[[nodiscard]] inline std::string
\n+
\n+
44separated_list(std::string_view sep, ITER begin, ITER end, ACCESS access)
\n+
45{
\n+
46 if (end == begin)
\n+
47 return {};
\n+
48 auto next{begin};
\n+
49 ++next;
\n+
50 if (next == end)
\n+
51 return to_string(access(begin));
\n+
52
\n+
53 // From here on, we've got at least 2 elements -- meaning that we need sep.
\n+
54 using elt_type = strip_t<decltype(access(begin))>;
\n+
55 using traits = string_traits<elt_type>;
\n+
56
\n+
57 std::size_t budget{0};
\n+
58 for (ITER cnt{begin}; cnt != end; ++cnt)
\n+
59 budget += traits::size_buffer(access(cnt));
\n+
60 budget +=
\n+
61 static_cast<std::size_t>(std::distance(begin, end)) * std::size(sep);
\n+
62
\n+
63 std::string result;
\n+
64 result.resize(budget);
\n+
65
\n+
66 char *const data{result.data()};
\n+
67 char *here{data};
\n+
68 char *stop{data + budget};
\n+
69 here = traits::into_buf(here, stop, access(begin)) - 1;
\n+
70 for (++begin; begin != end; ++begin)
\n+
71 {
\n+
72 here += sep.copy(here, std::size(sep));
\n+
73 here = traits::into_buf(here, stop, access(begin)) - 1;
\n+
74 }
\n+
75 result.resize(static_cast<std::size_t>(here - data));
\n+
76 return result;
\n+
77}
\n+
\n+
78
\n+
79
\n+
81template<typename ITER>
\n+
82[[nodiscard]] inline std::string
\n+
\n+
83separated_list(std::string_view sep, ITER begin, ITER end)
\n+
84{
\n+
85 return separated_list(sep, begin, end, [](ITER i) { return *i; });
\n+
86}
\n+
\n+
87
\n+
88
\n+
89// C++20: Use a concept.
\n+
91template<typename CONTAINER>
\n+
92[[nodiscard]] inline auto
\n+
\n+
93separated_list(std::string_view sep, CONTAINER const &c)
\n+
94 /*
\n+
95 Always std::string; necessary because SFINAE doesn't work with the
\n+
96 contents of function bodies, so the check for iterability has to be in
\n+
97 the signature.
\n+
98 */
\n+
99 -> typename std::enable_if<
\n+
100 (not std::is_void<decltype(std::begin(c))>::value and
\n+
101 not std::is_void<decltype(std::end(c))>::value),
\n+
102 std::string>::type
\n+
103{
\n+
104 return separated_list(sep, std::begin(c), std::end(c));
\n
105}
\n
\n
106
\n
107
\n-
108// C++20: Retire wrapper.
\n-
110template<typename LEFT, typename RIGHT>
\n-
\n-
111inline constexpr bool cmp_greater_equal(LEFT lhs, RIGHT rhs) noexcept
\n-
112{
\n-
113#if defined(PQXX_HAVE_CMP)
\n-
114 return std::cmp_greater_equal(lhs, rhs);
\n-
115#else
\n-
116 return not cmp_less(lhs, rhs);
\n-
117#endif
\n-
118}
\n-
\n-
119
\n-
120
\n-
122
\n-
\n-
125[[nodiscard]] inline std::string cat2(std::string_view x, std::string_view y)
\n-
126{
\n-
127 std::string buf;
\n-
128 auto const xs{std::size(x)}, ys{std::size(y)};
\n-
129 buf.resize(xs + ys);
\n-
130 x.copy(std::data(buf), xs);
\n-
131 y.copy(std::data(buf) + xs, ys);
\n-
132 return buf;
\n-
133}
\n-
\n-
134} // namespace pqxx::internal
\n-
135
\n-
136
\n-
137namespace pqxx
\n+
109template<
\n+
110 typename TUPLE, std::size_t INDEX = 0, typename ACCESS,
\n+
111 typename std::enable_if<
\n+
112 (INDEX == std::tuple_size<TUPLE>::value - 1), int>::type = 0>
\n+
\n+
113[[nodiscard]] inline std::string separated_list(
\n+
114 std::string_view /* sep */, TUPLE const &t, ACCESS const &access)
\n+
115{
\n+
116 return to_string(access(&std::get<INDEX>(t)));
\n+
117}
\n+
\n+
118
\n+
119template<
\n+
120 typename TUPLE, std::size_t INDEX = 0, typename ACCESS,
\n+
121 typename std::enable_if<
\n+
122 (INDEX < std::tuple_size<TUPLE>::value - 1), int>::type = 0>
\n+
123[[nodiscard]] inline std::string
\n+
124separated_list(std::string_view sep, TUPLE const &t, ACCESS const &access)
\n+
125{
\n+
126 std::string out{to_string(access(&std::get<INDEX>(t)))};
\n+
127 out.append(sep);
\n+
128 out.append(separated_list<TUPLE, INDEX + 1>(sep, t, access));
\n+
129 return out;
\n+
130}
\n+
131
\n+
132template<
\n+
133 typename TUPLE, std::size_t INDEX = 0,
\n+
134 typename std::enable_if<
\n+
135 (INDEX <= std::tuple_size<TUPLE>::value), int>::type = 0>
\n+
136[[nodiscard]] inline std::string
\n+
\n+
137separated_list(std::string_view sep, TUPLE const &t)
\n
138{
\n-
139using namespace std::literals;
\n-
140
\n-
\n-
142template<typename... T> inline constexpr void ignore_unused(T &&...) noexcept
\n-
143{}
\n-
\n-
144
\n-
145
\n-
147
\n-
150template<typename TO, typename FROM>
\n-
\n-
151inline TO check_cast(FROM value, std::string_view description)
\n-
152{
\n-
153 static_assert(std::is_arithmetic_v<FROM>);
\n-
154 static_assert(std::is_arithmetic_v<TO>);
\n-
155 static_assert(std::is_integral_v<FROM> == std::is_integral_v<TO>);
\n-
156
\n-
157 // The rest of this code won't quite work for bool, but bool is trivially
\n-
158 // convertible to other arithmetic types as far as I can see.
\n-
159 if constexpr (std::is_same_v<FROM, bool>)
\n-
160 return static_cast<TO>(value);
\n-
161
\n-
162 // Depending on our "if constexpr" conditions, this parameter may not be
\n-
163 // needed. Some compilers will warn.
\n-
164 ignore_unused(description);
\n-
165
\n-
166 using from_limits = std::numeric_limits<decltype(value)>;
\n-
167 using to_limits = std::numeric_limits<TO>;
\n-
168 if constexpr (std::is_signed_v<FROM>)
\n-
169 {
\n-
170 if constexpr (std::is_signed_v<TO>)
\n-
171 {
\n-
172 if (value < to_limits::lowest())
\n-
173 throw range_error{internal::cat2("Cast underflow: "sv, description)};
\n-
174 }
\n-
175 else
\n-
176 {
\n-
177 // FROM is signed, but TO is not. Treat this as a special case, because
\n-
178 // there may not be a good broader type in which the compiler can even
\n-
179 // perform our check.
\n-
180 if (value < 0)
\n-\n-
182 "Casting negative value to unsigned type: "sv, description)};
\n-
183 }
\n-
184 }
\n-
185 else
\n-
186 {
\n-
187 // No need to check: the value is unsigned so can't fall below the range
\n-
188 // of the TO type.
\n-
189 }
\n-
190
\n-
191 if constexpr (std::is_integral_v<FROM>)
\n-
192 {
\n-
193 using unsigned_from = std::make_unsigned_t<FROM>;
\n-
194 using unsigned_to = std::make_unsigned_t<TO>;
\n-
195 constexpr auto from_max{static_cast<unsigned_from>((from_limits::max)())};
\n-
196 constexpr auto to_max{static_cast<unsigned_to>((to_limits::max)())};
\n-
197 if constexpr (from_max > to_max)
\n-
198 {
\n-
199 if (internal::cmp_greater(value, to_max))
\n-
200 throw range_error{internal::cat2("Cast overflow: "sv, description)};
\n-
201 }
\n-
202 }
\n-
203 else if constexpr ((from_limits::max)() > (to_limits::max)())
\n-
204 {
\n-
205 if (value > (to_limits::max)())
\n-
206 throw range_error{internal::cat2("Cast overflow: ", description)};
\n-
207 }
\n-
208
\n-
209 return static_cast<TO>(value);
\n-
210}
\n-
\n-
211
\n-
212
\n-
\n-
234inline PQXX_PRIVATE void check_version() noexcept
\n-
235{
\n-
236 // There is no particular reason to do this here in @ref connection, except
\n-
237 // to ensure that every meaningful libpqxx client will execute it. The call
\n-
238 // must be in the execution path somewhere or the compiler won't try to link
\n-
239 // it. We can't use it to initialise a global or class-static variable,
\n-
240 // because a smart compiler might resolve it at compile time.
\n-
241 //
\n-
242 // On the other hand, we don't want to make a useless function call too
\n-
243 // often for performance reasons. A local static variable is initialised
\n-
244 // only on the definition's first execution. Compilers will be well
\n-
245 // optimised for this behaviour, so there's a minimal one-time cost.
\n-
246 static auto const version_ok{internal::PQXX_VERSION_CHECK()};
\n-
247 ignore_unused(version_ok);
\n-
248}
\n-
\n-
249
\n-
250
\n-
252
\n-
\n-
254struct PQXX_LIBEXPORT thread_safety_model
\n-
255{
\n-
257 bool safe_libpq = false;
\n-
258
\n-
260
\n-
266 bool safe_kerberos = false;
\n-
267
\n-
269 std::string description;
\n-
270};
\n-
\n-
271
\n-
272
\n-
274[[nodiscard]] PQXX_LIBEXPORT thread_safety_model describe_thread_safety();
\n-
275
\n-
276
\n-
277#if defined(PQXX_HAVE_CONCEPTS)
\n-
278# define PQXX_POTENTIAL_BINARY_ARG pqxx::potential_binary
\n-
279#else
\n-
280# define PQXX_POTENTIAL_BINARY_ARG typename
\n-
281#endif
\n-
282
\n-
283
\n-
285
\n-
302template<PQXX_POTENTIAL_BINARY_ARG TYPE>
\n-
\n-
303std::basic_string_view<std::byte> binary_cast(TYPE const &data)
\n-
304{
\n-
305 static_assert(sizeof(value_type<TYPE>) == 1);
\n-
306 // C++20: Use std::as_bytes.
\n-
307 return {
\n-
308 reinterpret_cast<std::byte const *>(
\n-
309 const_cast<strip_t<decltype(*std::data(data))> const *>(
\n-
310 std::data(data))),
\n-
311 std::size(data)};
\n-
312}
\n-
\n-
313
\n-
314
\n-
315#if defined(PQXX_HAVE_CONCEPTS)
\n-
316template<typename CHAR>
\n-
317concept char_sized = (sizeof(CHAR) == 1);
\n-
318# define PQXX_CHAR_SIZED_ARG char_sized
\n-
319#else
\n-
320# define PQXX_CHAR_SIZED_ARG typename
\n-
321#endif
\n-
322
\n-
324
\n-
331template<PQXX_CHAR_SIZED_ARG CHAR, typename SIZE>
\n-
\n-
332std::basic_string_view<std::byte> binary_cast(CHAR const *data, SIZE size)
\n-
333{
\n-
334 static_assert(sizeof(CHAR) == 1);
\n-
335 return {
\n-
336 reinterpret_cast<std::byte const *>(data),
\n-
337 check_cast<std::size_t>(size, "binary data size")};
\n-
338}
\n-
\n-
339
\n-
340
\n-
342constexpr oid oid_none{0};
\n-
343} // namespace pqxx
\n-
344
\n-
345
\n-
347
\n-
356namespace pqxx::internal
\n-
357{
\n-
358using namespace std::literals;
\n-
359
\n-
360
\n-
362
\n-
\n-
366template<typename CHAR> inline constexpr bool is_digit(CHAR c) noexcept
\n-
367{
\n-
368 return (c >= '0') and (c <= '9');
\n-
369}
\n-
\n-
370
\n-
371
\n-
373
\n-
375[[nodiscard]] std::string
\n-
376describe_object(std::string_view class_name, std::string_view name);
\n-
377
\n-
378
\n-
380
\n-\n-
392 void const *old_guest, std::string_view old_class, std::string_view old_name,
\n-
393 void const *new_guest, std::string_view new_class,
\n-
394 std::string_view new_name);
\n-
395
\n-
396
\n-
398
\n-\n-
402 void const *old_guest, std::string_view old_class, std::string_view old_name,
\n-
403 void const *new_guest, std::string_view new_class,
\n-
404 std::string_view new_name);
\n-
405
\n-
406
\n-
408
\n-
\n-
411inline constexpr std::size_t size_esc_bin(std::size_t binary_bytes) noexcept
\n-
412{
\n-
413 return 2 + (2 * binary_bytes) + 1;
\n-
414}
\n-
\n-
415
\n-
416
\n-
418
\n-
\n-
420inline constexpr std::size_t size_unesc_bin(std::size_t escaped_bytes) noexcept
\n-
421{
\n-
422 return (escaped_bytes - 2) / 2;
\n-
423}
\n-
\n-
424
\n-
425
\n-
426// TODO: Use actual binary type for "data".
\n-
428
\n-
433void PQXX_LIBEXPORT
\n-
434esc_bin(std::basic_string_view<std::byte> binary_data, char buffer[]) noexcept;
\n-
435
\n-
436
\n-
438std::string PQXX_LIBEXPORT
\n-
439esc_bin(std::basic_string_view<std::byte> binary_data);
\n-
440
\n-
441
\n-
443void PQXX_LIBEXPORT
\n-
444unesc_bin(std::string_view escaped_data, std::byte buffer[]);
\n-
445
\n-
446
\n-
448std::basic_string<std::byte>
\n-
449 PQXX_LIBEXPORT unesc_bin(std::string_view escaped_data);
\n-
450
\n-
451
\n-
\n-
453template<typename T> auto ssize(T const &c)
\n-
454{
\n-
455#if pqxx_have_ssize
\n-
456 return std::ssize(c);
\n-
457#else
\n-
458 using signed_t = std::make_signed_t<decltype(std::size(c))>;
\n-
459 return static_cast<signed_t>(std::size(c));
\n-
460#endif // pqxx_have_ssize
\n-
461}
\n-
\n-
462
\n-
463
\n-
465
\n-
469template<typename RETURN, typename... ARGS>
\n-
470std::tuple<ARGS...> args_f(RETURN (&func)(ARGS...));
\n-
471
\n-
472
\n-
474
\n-
478template<typename RETURN, typename... ARGS>
\n-
479std::tuple<ARGS...> args_f(std::function<RETURN(ARGS...)> const &);
\n-
480
\n-
481
\n-
483
\n-
487template<typename CLASS, typename RETURN, typename... ARGS>
\n-
488std::tuple<ARGS...> member_args_f(RETURN (CLASS::*)(ARGS...));
\n-
489
\n-
490
\n-
492
\n-
496template<typename CLASS, typename RETURN, typename... ARGS>
\n-
497std::tuple<ARGS...> member_args_f(RETURN (CLASS::*)(ARGS...) const);
\n-
498
\n-
499
\n-
501
\n-
507template<typename CALLABLE>
\n-
508auto args_f(CALLABLE const &f)
\n-
509 -> decltype(member_args_f(&CALLABLE::operator()));
\n-
510
\n-
511
\n-
513template<typename CALLABLE>
\n-
514using args_t = decltype(args_f(std::declval<CALLABLE>()));
\n-
515
\n-
516
\n-
518
\n-
521template<typename... TYPES>
\n-
522std::tuple<strip_t<TYPES>...> strip_types(std::tuple<TYPES...> const &);
\n-
523
\n-
524
\n-
526template<typename... TYPES>
\n-
527using strip_types_t = decltype(strip_types(std::declval<TYPES...>()));
\n-
528
\n-
529
\n-
\n-
531inline constexpr char unescape_char(char escaped) noexcept
\n-
532{
\n-
533 switch (escaped)
\n-
534 {
\n-
535 case 'b': // Backspace.
\n-
536 PQXX_UNLIKELY return '\\b';
\n-
537 case 'f': // Form feed
\n-
538 PQXX_UNLIKELY return '\\f';
\n-
539 case 'n': // Line feed.
\n-
540 return '\\n';
\n-
541 case 'r': // Carriage return.
\n-
542 return '\\r';
\n-
543 case 't': // Horizontal tab.
\n-
544 return '\\t';
\n-
545 case 'v': // Vertical tab.
\n-
546 return '\\v';
\n-
547 default: break;
\n-
548 }
\n-
549 // Regular character ("self-escaped").
\n-
550 return escaped;
\n-
551}
\n-
\n-
552
\n-
553
\n-
554// C++20: std::span?
\n-
556template<std::size_t BYTES>
\n-
557char const *PQXX_COLD
\n-
\n-
558error_string(int err_num, std::array<char, BYTES> &buffer)
\n-
559{
\n-
560 // Not entirely clear whether strerror_s will be in std or global namespace.
\n-
561 using namespace std;
\n-
562
\n-
563#if defined(PQXX_HAVE_STERROR_S) || defined(PQXX_HAVE_STRERROR_R)
\n-
564# if defined(PQXX_HAVE_STRERROR_S)
\n-
565 auto const err_result{strerror_s(std::data(buffer), BYTES, err_num)};
\n-
566# else
\n-
567 auto const err_result{strerror_r(err_num, std::data(buffer), BYTES)};
\n-
568# endif
\n-
569 if constexpr (std::is_same_v<pqxx::strip_t<decltype(err_result)>, char *>)
\n-
570 {
\n-
571 // GNU version of strerror_r; returns the error string, which may or may
\n-
572 // not reside within buffer.
\n-
573 return err_result;
\n-
574 }
\n-
575 else
\n-
576 {
\n-
577 // Either strerror_s or POSIX strerror_r; returns an error code.
\n-
578 // Sorry for being lazy here: Not reporting error string for the case
\n-
579 // where we can't retrieve an error string.
\n-
580 if (err_result == 0)
\n-
581 return std::data(buffer);
\n-
582 else
\n-
583 return "Compound errors.";
\n-
584 }
\n-
585
\n-
586#else
\n-
587 // Fallback case, hopefully for no actual platforms out there.
\n-
588 pqxx::ignore_unused(err_num, buffer);
\n-
589 return "(No error information available.)";
\n-
590#endif
\n-
591}
\n-
\n-
592} // namespace pqxx::internal
\n-
593
\n-
594
\n-
\n-\n-
596{
\n-
598PQXX_LIBEXPORT void pqfreemem(void const *) noexcept;
\n-
599} // namespace pqxx::internal::pq
\n+
139 // TODO: Optimise allocation.
\n+
140 return separated_list(sep, t, [](TUPLE const &tup) { return *tup; });
\n+
141}
\n
\n-
600#endif
\n+
143} // namespace pqxx
\n+
144#endif
\n
The home of all libpqxx classes, functions, templates, etc.
Definition array.hxx:33
\n+
std::string separated_list(std::string_view sep, ITER begin, ITER end, ACCESS access)
Represent sequence of values as a string, joined by a given separator.
Definition separated_list.hxx:44
\n
std::remove_cv_t< std::remove_reference_t< TYPE > > strip_t
Remove any constness, volatile, and reference-ness from a type.
Definition types.hxx:91
\n-
std::basic_string_view< std::byte > binary_cast(TYPE const &data)
Cast binary data to a type that libpqxx will recognise as binary.
Definition util.hxx:303
\n-
strip_t< decltype(*std::begin(std::declval< CONTAINER >()))> value_type
The type of a container's elements.
Definition types.hxx:107
\n-
void check_version() noexcept
Definition util.hxx:234
\n-
thread_safety_model describe_thread_safety()
Describe thread safety available in this build.
Definition util.cxx:33
\n-
constexpr void ignore_unused(T &&...) noexcept
Suppress compiler warning about an unused item.
Definition util.hxx:142
\n-
constexpr oid oid_none
The "null" oid.
Definition util.hxx:342
\n-
TO check_cast(FROM value, std::string_view description)
Cast a numeric value to another type, or throw if it underflows/overflows.
Definition util.hxx:151
\n-
Internal items for libpqxx' own use. Do not use these yourself.
Definition composite.hxx:84
\n-
void unesc_bin(std::string_view escaped_data, std::byte buffer[])
Reconstitute binary data from its escaped version.
Definition util.cxx:158
\n-
int PQXX_VERSION_CHECK() noexcept
Library version check stub.
Definition version.cxx:23
\n-
char const *PQXX_COLD error_string(int err_num, std::array< char, BYTES > &buffer)
Get error string for a given errno value.
Definition util.hxx:558
\n-
void esc_bin(std::basic_string_view< std::byte > binary_data, char buffer[]) noexcept
Hex-escape binary data into a buffer.
Definition util.cxx:126
\n-
constexpr std::size_t size_esc_bin(std::size_t binary_bytes) noexcept
Compute buffer size needed to escape binary data for use as a BYTEA.
Definition util.hxx:411
\n-
std::tuple< ARGS... > member_args_f(RETURN(CLASS::*)(ARGS...))
Helper for determining a member function's parameter types.
\n-
constexpr bool cmp_less(LEFT lhs, RIGHT rhs) noexcept
Same as std::cmp_less, or a workaround where that's not available.
Definition util.hxx:63
\n-
void check_unique_unregister(void const *old_guest, std::string_view old_class, std::string_view old_name, void const *new_guest, std::string_view new_class, std::string_view new_name)
Like check_unique_register, but for un-registering a guest.
Definition util.cxx:78
\n-
decltype(strip_types(std::declval< TYPES... >())) strip_types_t
Take a tuple type and apply strip_t to its component types.
Definition util.hxx:527
\n-
void check_unique_register(void const *old_guest, std::string_view old_class, std::string_view old_name, void const *new_guest, std::string_view new_class, std::string_view new_name)
Check validity of registering a new "guest" in a "host.".
Definition util.cxx:61
\n-
std::tuple< strip_t< TYPES >... > strip_types(std::tuple< TYPES... > const &)
Helper: Apply strip_t to each of a tuple type's component types.
\n-
std::string describe_object(std::string_view class_name, std::string_view name)
Describe an object for humans, based on class name and optional name.
Definition util.cxx:51
\n-
std::tuple< ARGS... > args_f(RETURN(&func)(ARGS...))
Helper for determining a function's parameter types.
\n-
constexpr bool cmp_greater(LEFT lhs, RIGHT rhs) noexcept
C++20 std::cmp_greater, or workaround if not available.
Definition util.hxx:85
\n-
decltype(args_f(std::declval< CALLABLE >())) args_t
A callable's parameter types, as a tuple.
Definition util.hxx:514
\n-
constexpr bool is_digit(CHAR c) noexcept
A safer and more generic replacement for std::isdigit.
Definition util.hxx:366
\n-
constexpr char unescape_char(char escaped) noexcept
Return original byte for escaped character.
Definition util.hxx:531
\n-
constexpr bool cmp_greater_equal(LEFT lhs, RIGHT rhs) noexcept
C++20 std::cmp_greater_equal, or workaround if not available.
Definition util.hxx:111
\n-
std::string cat2(std::string_view x, std::string_view y)
Efficiently concatenate two strings.
Definition util.hxx:125
\n-
constexpr bool cmp_less_equal(LEFT lhs, RIGHT rhs) noexcept
C++20 std::cmp_less_equal, or workaround if not available.
Definition util.hxx:98
\n-
auto ssize(T const &c)
Transitional: std::ssize(), or custom implementation if not available.
Definition util.hxx:453
\n-
constexpr std::size_t size_unesc_bin(std::size_t escaped_bytes) noexcept
Compute binary size from the size of its escaped version.
Definition util.hxx:420
\n-
Definition util.hxx:596
\n-
void pqfreemem(void const *) noexcept
Wrapper for PQfreemem(), with C++ linkage.
Definition util.cxx:199
\n-
Something is out of range, similar to std::out_of_range.
Definition except.hxx:326
\n-
Descriptor of library's thread-safety model.
Definition util.hxx:255
\n-
std::string description
A human-readable description of any thread-safety issues.
Definition util.hxx:269
\n+
std::string to_string(field const &value)
Convert a field to a string.
Definition result.cxx:549
\n+
Result set containing data returned by a query or command.
Definition result.hxx:73
\n+
Traits class for use in string conversions.
Definition strconv.hxx:155
\n
\n
\n \n
\n \n
\n \n \n", "details": [{"source1": "html2text {}", "source2": "html2text {}", "unified_diff": "@@ -1,622 +1,162 @@\n \n \n \n \n \n libpqxx\u00a07.8.1\n \n-util.hxx\n- 1/* Various utility definitions for libpqxx.\n+separated_list.hxx\n+ 1/* Helper similar to Python's `str.join()`.\n 2 *\n- 3 * DO NOT INCLUDE THIS FILE DIRECTLY; include pqxx/util instead.\n+ 3 * DO NOT INCLUDE THIS FILE DIRECTLY; include pqxx/separated_list instead.\n 4 *\n 5 * Copyright (c) 2000-2023, Jeroen T. Vermeulen.\n 6 *\n 7 * See COPYING for copyright license. If you did not receive a file called\n 8 * COPYING with this source code, please notify the distributor of this\n 9 * mistake, or contact the author.\n 10 */\n- 11#ifndef PQXX_H_UTIL\n- 12#define PQXX_H_UTIL\n+ 11#ifndef PQXX_H_SEPARATED_LIST\n+ 12#define PQXX_H_SEPARATED_LIST\n 13\n 14#if !defined(PQXX_HEADER_PRE)\n 15# error \"Include libpqxx headers as , not .\"\n 16#endif\n 17\n- 18#include \n- 19#include \n- 20#include \n- 21#include \n- 22#include \n- 23#include \n- 24#include \n- 25#include \n- 26#include \n- 27#include \n- 28#include \n- 29#include \n- 30#include \n- 31#include \n- 32#include \n- 33#include \n+ 18#include \n+ 19#include \n+ 20\n+ 21#include \"pqxx/strconv.hxx\"\n+ 22\n+ 23// C++20: Simplify using std::ranges::range.\n+ 24// C++20: Optimise buffer allocation using random_access_range/iterator.\n+ 25// TODO: Can we pass separators at compile time?\n+ 26namespace pqxx\n+ 27{\n+ 32\n 34\n- 35#include \"pqxx/except.hxx\"\n- 36#include \"pqxx/types.hxx\"\n- 37#include \"pqxx/version.hxx\"\n- 38\n- 39\n- 41namespace pqxx\n- 42{}\n- 43\n- 44#include \n- 45\n- 46\n- 47// C++23: Retire wrapper.\n- 48#if pqxx_have_unreachable\n- 50# define PQXX_UNREACHABLE std::unreachable()\n- 51#else\n- 52# define PQXX_UNREACHABLE assert(false)\n- 53#endif\n- 54\n- 55\n- 57namespace pqxx::internal\n- 58{\n- 59\n- 60// C++20: Retire wrapper.\n- 62template\n-63inline constexpr bool cmp_less(LEFT lhs, RIGHT rhs) noexcept\n- 64{\n- 65#if defined(PQXX_HAVE_CMP)\n- 66 return std::cmp_less(lhs, rhs);\n- 67#else\n- 68 // We need a variable just because lgtm.com gives off a false positive\n- 69 // warning when we compare the values directly. It considers that a\n- 70 // \"self-comparison.\"\n- 71 constexpr bool left_signed{std::is_signed_v};\n- 72 if constexpr (left_signed == std::is_signed_v)\n- 73 return lhs < rhs;\n- 74 else if constexpr (std::is_signed_v)\n- 75 return (lhs <= 0) ? true : (std::make_unsigned_t(lhs) < rhs);\n- 76 else\n- 77 return (rhs <= 0) ? false : (lhs < std::make_unsigned_t(rhs));\n- 78#endif\n- 79}\n- 80\n- 81\n- 82// C++20: Retire wrapper.\n- 84template\n-85inline constexpr bool cmp_greater(LEFT lhs, RIGHT rhs) noexcept\n- 86{\n- 87#if defined(PQXX_HAVE_CMP)\n- 88 return std::cmp_greater(lhs, rhs);\n- 89#else\n- 90 return cmp_less(rhs, lhs);\n- 91#endif\n- 92}\n- 93\n- 94\n- 95// C++20: Retire wrapper.\n- 97template\n-98inline constexpr bool cmp_less_equal(LEFT lhs, RIGHT rhs) noexcept\n- 99{\n- 100#if defined(PQXX_HAVE_CMP)\n- 101 return std::cmp_less_equal(lhs, rhs);\n- 102#else\n- 103 return not cmp_less(rhs, lhs);\n- 104#endif\n+ 42template\n+ 43[[nodiscard]] inline std::string\n+44separated_list(std::string_view sep, ITER begin, ITER end, ACCESS access)\n+ 45{\n+ 46 if (end == begin)\n+ 47 return {};\n+ 48 auto next{begin};\n+ 49 ++next;\n+ 50 if (next == end)\n+ 51 return to_string(access(begin));\n+ 52\n+ 53 // From here on, we've got at least 2 elements -- meaning that we need sep.\n+ 54 using elt_type = strip_t;\n+ 55 using traits = string_traits;\n+ 56\n+ 57 std::size_t budget{0};\n+ 58 for (ITER cnt{begin}; cnt != end; ++cnt)\n+ 59 budget += traits::size_buffer(access(cnt));\n+ 60 budget +=\n+ 61 static_cast(std::distance(begin, end)) * std::size(sep);\n+ 62\n+ 63 std::string result;\n+ 64 result.resize(budget);\n+ 65\n+ 66 char *const data{result.data()};\n+ 67 char *here{data};\n+ 68 char *stop{data + budget};\n+ 69 here = traits::into_buf(here, stop, access(begin)) - 1;\n+ 70 for (++begin; begin != end; ++begin)\n+ 71 {\n+ 72 here += sep.copy(here, std::size(sep));\n+ 73 here = traits::into_buf(here, stop, access(begin)) - 1;\n+ 74 }\n+ 75 result.resize(static_cast(here - data));\n+ 76 return result;\n+ 77}\n+ 78\n+ 79\n+ 81template\n+ 82[[nodiscard]] inline std::string\n+83separated_list(std::string_view sep, ITER begin, ITER end)\n+ 84{\n+ 85 return separated_list(sep, begin, end, [](ITER i) { return *i; });\n+ 86}\n+ 87\n+ 88\n+ 89// C++20: Use a concept.\n+ 91template\n+ 92[[nodiscard]] inline auto\n+93separated_list(std::string_view sep, CONTAINER const &c)\n+ 94 /*\n+ 95 Always std::string; necessary because SFINAE doesn't work with the\n+ 96 contents of function bodies, so the check for iterability has to be in\n+ 97 the signature.\n+ 98 */\n+ 99 -> typename std::enable_if<\n+ 100 (not std::is_void::value and\n+ 101 not std::is_void::value),\n+ 102 std::string>::type\n+ 103{\n+ 104 return separated_list(sep, std::begin(c), std::end(c));\n 105}\n 106\n 107\n- 108// C++20: Retire wrapper.\n- 110template\n-111inline constexpr bool cmp_greater_equal(LEFT lhs, RIGHT rhs) noexcept\n- 112{\n- 113#if defined(PQXX_HAVE_CMP)\n- 114 return std::cmp_greater_equal(lhs, rhs);\n- 115#else\n- 116 return not cmp_less(lhs, rhs);\n- 117#endif\n- 118}\n- 119\n- 120\n- 122\n-125[[nodiscard]] inline std::string cat2(std::string_view x, std::string_view\n-y)\n- 126{\n- 127 std::string buf;\n- 128 auto const xs{std::size(x)}, ys{std::size(y)};\n- 129 buf.resize(xs + ys);\n- 130 x.copy(std::data(buf), xs);\n- 131 y.copy(std::data(buf) + xs, ys);\n- 132 return buf;\n- 133}\n- 134} // namespace pqxx::internal\n- 135\n- 136\n- 137namespace pqxx\n+ 109template<\n+ 110 typename TUPLE, std::size_t INDEX = 0, typename ACCESS,\n+ 111 typename std::enable_if<\n+ 112 (INDEX == std::tuple_size::value - 1), int>::type = 0>\n+113[[nodiscard]] inline std::string separated_list(\n+ 114 std::string_view /* sep */, TUPLE const &t, ACCESS const &access)\n+ 115{\n+ 116 return to_string(access(&std::get(t)));\n+ 117}\n+ 118\n+ 119template<\n+ 120 typename TUPLE, std::size_t INDEX = 0, typename ACCESS,\n+ 121 typename std::enable_if<\n+ 122 (INDEX < std::tuple_size::value - 1), int>::type = 0>\n+ 123[[nodiscard]] inline std::string\n+ 124separated_list(std::string_view sep, TUPLE const &t, ACCESS const &access)\n+ 125{\n+ 126 std::string out{to_string(access(&std::get(t)))};\n+ 127 out.append(sep);\n+ 128 out.append(separated_list(sep, t, access));\n+ 129 return out;\n+ 130}\n+ 131\n+ 132template<\n+ 133 typename TUPLE, std::size_t INDEX = 0,\n+ 134 typename std::enable_if<\n+ 135 (INDEX <= std::tuple_size::value), int>::type = 0>\n+ 136[[nodiscard]] inline std::string\n+137separated_list(std::string_view sep, TUPLE const &t)\n 138{\n- 139using namespace std::literals;\n- 140\n-142template inline constexpr void ignore_unused(T &&...)\n-noexcept\n- 143{}\n- 144\n- 145\n- 147\n- 150template\n-151inline TO check_cast(FROM value, std::string_view description)\n- 152{\n- 153 static_assert(std::is_arithmetic_v);\n- 154 static_assert(std::is_arithmetic_v);\n- 155 static_assert(std::is_integral_v == std::is_integral_v);\n- 156\n- 157 // The rest of this code won't quite work for bool, but bool is trivially\n- 158 // convertible to other arithmetic types as far as I can see.\n- 159 if constexpr (std::is_same_v)\n- 160 return static_cast(value);\n- 161\n- 162 // Depending on our \"if constexpr\" conditions, this parameter may not be\n- 163 // needed. Some compilers will warn.\n- 164 ignore_unused(description);\n- 165\n- 166 using from_limits = std::numeric_limits;\n- 167 using to_limits = std::numeric_limits;\n- 168 if constexpr (std::is_signed_v)\n- 169 {\n- 170 if constexpr (std::is_signed_v)\n- 171 {\n- 172 if (value < to_limits::lowest())\n- 173 throw range_error{internal::cat2(\"Cast underflow: \"sv, description)};\n- 174 }\n- 175 else\n- 176 {\n- 177 // FROM is signed, but TO is not. Treat this as a special case, because\n- 178 // there may not be a good broader type in which the compiler can even\n- 179 // perform our check.\n- 180 if (value < 0)\n- 181 throw range_error{internal::cat2(\n- 182 \"Casting negative value to unsigned type: \"sv, description)};\n- 183 }\n- 184 }\n- 185 else\n- 186 {\n- 187 // No need to check: the value is unsigned so can't fall below the range\n- 188 // of the TO type.\n- 189 }\n- 190\n- 191 if constexpr (std::is_integral_v)\n- 192 {\n- 193 using unsigned_from = std::make_unsigned_t;\n- 194 using unsigned_to = std::make_unsigned_t;\n- 195 constexpr auto from_max{static_cast((from_limits::max)())};\n- 196 constexpr auto to_max{static_cast((to_limits::max)())};\n- 197 if constexpr (from_max > to_max)\n- 198 {\n- 199 if (internal::cmp_greater(value, to_max))\n- 200 throw range_error{internal::cat2(\"Cast overflow: \"sv, description)};\n- 201 }\n- 202 }\n- 203 else if constexpr ((from_limits::max)() > (to_limits::max)())\n- 204 {\n- 205 if (value > (to_limits::max)())\n- 206 throw range_error{internal::cat2(\"Cast overflow: \", description)};\n- 207 }\n- 208\n- 209 return static_cast(value);\n- 210}\n- 211\n- 212\n-234inline PQXX_PRIVATE void check_version() noexcept\n- 235{\n- 236 // There is no particular reason to do this here in @ref connection,\n-except\n- 237 // to ensure that every meaningful libpqxx client will execute it. The\n-call\n- 238 // must be in the execution path somewhere or the compiler won't try to\n-link\n- 239 // it. We can't use it to initialise a global or class-static variable,\n- 240 // because a smart compiler might resolve it at compile time.\n- 241 //\n- 242 // On the other hand, we don't want to make a useless function call too\n- 243 // often for performance reasons. A local static variable is initialised\n- 244 // only on the definition's first execution. Compilers will be well\n- 245 // optimised for this behaviour, so there's a minimal one-time cost.\n- 246 static auto const version_ok{internal::PQXX_VERSION_CHECK()};\n- 247 ignore_unused(version_ok);\n- 248}\n- 249\n- 250\n- 252\n-254struct PQXX_LIBEXPORT thread_safety_model\n- 255{\n-257 bool safe_libpq = false;\n- 258\n- 260\n-266 bool safe_kerberos = false;\n- 267\n-269 std::string description;\n- 270};\n- 271\n- 272\n- 274[[nodiscard]] PQXX_LIBEXPORT thread_safety_model describe_thread_safety();\n- 275\n- 276\n- 277#if defined(PQXX_HAVE_CONCEPTS)\n- 278# define PQXX_POTENTIAL_BINARY_ARG pqxx::potential_binary\n- 279#else\n- 280# define PQXX_POTENTIAL_BINARY_ARG typename\n- 281#endif\n- 282\n- 283\n- 285\n- 302template\n-303std::basic_string_view binary_cast(TYPE const &data)\n- 304{\n- 305 static_assert(sizeof(value_type) == 1);\n- 306 // C++20: Use std::as_bytes.\n- 307 return {\n- 308 reinterpret_cast(\n- 309 const_cast const *>(\n- 310 std::data(data))),\n- 311 std::size(data)};\n- 312}\n- 313\n- 314\n- 315#if defined(PQXX_HAVE_CONCEPTS)\n- 316template\n- 317concept char_sized = (sizeof(CHAR) == 1);\n- 318# define PQXX_CHAR_SIZED_ARG char_sized\n- 319#else\n- 320# define PQXX_CHAR_SIZED_ARG typename\n- 321#endif\n- 322\n- 324\n- 331template\n-332std::basic_string_view binary_cast(CHAR const *data, SIZE size)\n- 333{\n- 334 static_assert(sizeof(CHAR) == 1);\n- 335 return {\n- 336 reinterpret_cast(data),\n- 337 check_cast(size, \"binary data size\")};\n- 338}\n- 339\n- 340\n-342constexpr oid oid_none{0};\n- 343} // namespace pqxx\n- 344\n- 345\n- 347\n- 356namespace pqxx::internal\n- 357{\n- 358using namespace std::literals;\n- 359\n- 360\n- 362\n-366template inline constexpr bool is_digit(CHAR c) noexcept\n- 367{\n- 368 return (c >= '0') and (c <= '9');\n- 369}\n- 370\n- 371\n- 373\n- 375[[nodiscard]] std::string\n- 376describe_object(std::string_view class_name, std::string_view name);\n- 377\n- 378\n- 380\n- 391void check_unique_register(\n- 392 void const *old_guest, std::string_view old_class, std::string_view\n-old_name,\n- 393 void const *new_guest, std::string_view new_class,\n- 394 std::string_view new_name);\n- 395\n- 396\n- 398\n- 401void check_unique_unregister(\n- 402 void const *old_guest, std::string_view old_class, std::string_view\n-old_name,\n- 403 void const *new_guest, std::string_view new_class,\n- 404 std::string_view new_name);\n- 405\n- 406\n- 408\n-411inline constexpr std::size_t size_esc_bin(std::size_t binary_bytes) noexcept\n- 412{\n- 413 return 2 + (2 * binary_bytes) + 1;\n- 414}\n- 415\n- 416\n- 418\n-420inline constexpr std::size_t size_unesc_bin(std::size_t escaped_bytes)\n-noexcept\n- 421{\n- 422 return (escaped_bytes - 2) / 2;\n- 423}\n- 424\n- 425\n- 426// TODO: Use actual binary type for \"data\".\n- 428\n- 433void PQXX_LIBEXPORT\n- 434esc_bin(std::basic_string_view binary_data, char buffer[])\n-noexcept;\n- 435\n- 436\n- 438std::string PQXX_LIBEXPORT\n- 439esc_bin(std::basic_string_view binary_data);\n- 440\n- 441\n- 443void PQXX_LIBEXPORT\n- 444unesc_bin(std::string_view escaped_data, std::byte buffer[]);\n- 445\n- 446\n- 448std::basic_string\n- 449 PQXX_LIBEXPORT unesc_bin(std::string_view escaped_data);\n- 450\n- 451\n-453template auto ssize(T const &c)\n- 454{\n- 455#if pqxx_have_ssize\n- 456 return std::ssize(c);\n- 457#else\n- 458 using signed_t = std::make_signed_t;\n- 459 return static_cast(std::size(c));\n- 460#endif // pqxx_have_ssize\n- 461}\n- 462\n- 463\n- 465\n- 469template\n-470std::tuple args_f(RETURN (&func)(ARGS...));\n- 471\n- 472\n- 474\n- 478template\n-479std::tuple args_f(std::function const &);\n- 480\n- 481\n- 483\n- 487template\n-488std::tuple member_args_f(RETURN (CLASS::*)(ARGS...));\n- 489\n- 490\n- 492\n- 496template\n- 497std::tuple member_args_f(RETURN (CLASS::*)(ARGS...) const);\n- 498\n- 499\n- 501\n- 507template\n-508auto args_f(CALLABLE const &f)\n- 509 -> decltype(member_args_f(&CALLABLE::operator()));\n- 510\n- 511\n- 513template\n-514using args_t = decltype(args_f(std::declval()));\n- 515\n- 516\n- 518\n- 521template\n-522std::tuple...> strip_types(std::tuple const &);\n- 523\n- 524\n- 526template\n-527using strip_types_t = decltype(strip_types(std::declval()));\n- 528\n- 529\n-531inline constexpr char unescape_char(char escaped) noexcept\n- 532{\n- 533 switch (escaped)\n- 534 {\n- 535 case 'b': // Backspace.\n- 536 PQXX_UNLIKELY return '\\b';\n- 537 case 'f': // Form feed\n- 538 PQXX_UNLIKELY return '\\f';\n- 539 case 'n': // Line feed.\n- 540 return '\\n';\n- 541 case 'r': // Carriage return.\n- 542 return '\\r';\n- 543 case 't': // Horizontal tab.\n- 544 return '\\t';\n- 545 case 'v': // Vertical tab.\n- 546 return '\\v';\n- 547 default: break;\n- 548 }\n- 549 // Regular character (\"self-escaped\").\n- 550 return escaped;\n- 551}\n- 552\n- 553\n- 554// C++20: std::span?\n- 556template\n- 557char const *PQXX_COLD\n-558error_string(int err_num, std::array &buffer)\n- 559{\n- 560 // Not entirely clear whether strerror_s will be in std or global\n-namespace.\n- 561 using namespace std;\n- 562\n- 563#if defined(PQXX_HAVE_STERROR_S) || defined(PQXX_HAVE_STRERROR_R)\n- 564# if defined(PQXX_HAVE_STRERROR_S)\n- 565 auto const err_result{strerror_s(std::data(buffer), BYTES, err_num)};\n- 566# else\n- 567 auto const err_result{strerror_r(err_num, std::data(buffer), BYTES)};\n- 568# endif\n- 569 if constexpr (std::is_same_v, char *>)\n- 570 {\n- 571 // GNU version of strerror_r; returns the error string, which may or may\n- 572 // not reside within buffer.\n- 573 return err_result;\n- 574 }\n- 575 else\n- 576 {\n- 577 // Either strerror_s or POSIX strerror_r; returns an error code.\n- 578 // Sorry for being lazy here: Not reporting error string for the case\n- 579 // where we can't retrieve an error string.\n- 580 if (err_result == 0)\n- 581 return std::data(buffer);\n- 582 else\n- 583 return \"Compound errors.\";\n- 584 }\n- 585\n- 586#else\n- 587 // Fallback case, hopefully for no actual platforms out there.\n- 588 pqxx::ignore_unused(err_num, buffer);\n- 589 return \"(No error information available.)\";\n- 590#endif\n- 591}\n- 592} // namespace pqxx::internal\n- 593\n- 594\n-595namespace pqxx::internal::pq\n- 596{\n- 598PQXX_LIBEXPORT void pqfreemem(void const *) noexcept;\n- 599} // namespace pqxx::internal::pq\n- 600#endif\n+ 139 // TODO: Optimise allocation.\n+ 140 return separated_list(sep, t, [](TUPLE const &tup) { return *tup; });\n+ 141}\n+ 143} // namespace pqxx\n+ 144#endif\n pqxx\n The home of all libpqxx classes, functions, templates, etc.\n Definition array.hxx:33\n+pqxx::separated_list\n+std::string separated_list(std::string_view sep, ITER begin, ITER end, ACCESS\n+access)\n+Represent sequence of values as a string, joined by a given separator.\n+Definition separated_list.hxx:44\n pqxx::strip_t\n std::remove_cv_t< std::remove_reference_t< TYPE > > strip_t\n Remove any constness, volatile, and reference-ness from a type.\n Definition types.hxx:91\n-pqxx::binary_cast\n-std::basic_string_view< std::byte > binary_cast(TYPE const &data)\n-Cast binary data to a type that libpqxx will recognise as binary.\n-Definition util.hxx:303\n-pqxx::value_type\n-strip_t< decltype(*std::begin(std::declval< CONTAINER >()))> value_type\n-The type of a container's elements.\n-Definition types.hxx:107\n-pqxx::check_version\n-void check_version() noexcept\n-Definition util.hxx:234\n-pqxx::describe_thread_safety\n-thread_safety_model describe_thread_safety()\n-Describe thread safety available in this build.\n-Definition util.cxx:33\n-pqxx::ignore_unused\n-constexpr void ignore_unused(T &&...) noexcept\n-Suppress compiler warning about an unused item.\n-Definition util.hxx:142\n-pqxx::oid_none\n-constexpr oid oid_none\n-The \"null\" oid.\n-Definition util.hxx:342\n-pqxx::check_cast\n-TO check_cast(FROM value, std::string_view description)\n-Cast a numeric value to another type, or throw if it underflows/overflows.\n-Definition util.hxx:151\n-pqxx::internal\n-Internal items for libpqxx' own use. Do not use these yourself.\n-Definition composite.hxx:84\n-pqxx::internal::unesc_bin\n-void unesc_bin(std::string_view escaped_data, std::byte buffer[])\n-Reconstitute binary data from its escaped version.\n-Definition util.cxx:158\n-pqxx::internal::PQXX_VERSION_CHECK\n-int PQXX_VERSION_CHECK() noexcept\n-Library version check stub.\n-Definition version.cxx:23\n-pqxx::internal::error_string\n-char const *PQXX_COLD error_string(int err_num, std::array< char, BYTES >\n-&buffer)\n-Get error string for a given errno value.\n-Definition util.hxx:558\n-pqxx::internal::esc_bin\n-void esc_bin(std::basic_string_view< std::byte > binary_data, char buffer[])\n-noexcept\n-Hex-escape binary data into a buffer.\n-Definition util.cxx:126\n-pqxx::internal::size_esc_bin\n-constexpr std::size_t size_esc_bin(std::size_t binary_bytes) noexcept\n-Compute buffer size needed to escape binary data for use as a BYTEA.\n-Definition util.hxx:411\n-pqxx::internal::member_args_f\n-std::tuple< ARGS... > member_args_f(RETURN(CLASS::*)(ARGS...))\n-Helper for determining a member function's parameter types.\n-pqxx::internal::cmp_less\n-constexpr bool cmp_less(LEFT lhs, RIGHT rhs) noexcept\n-Same as std::cmp_less, or a workaround where that's not available.\n-Definition util.hxx:63\n-pqxx::internal::check_unique_unregister\n-void check_unique_unregister(void const *old_guest, std::string_view old_class,\n-std::string_view old_name, void const *new_guest, std::string_view new_class,\n-std::string_view new_name)\n-Like check_unique_register, but for un-registering a guest.\n-Definition util.cxx:78\n-pqxx::internal::strip_types_t\n-decltype(strip_types(std::declval< TYPES... >())) strip_types_t\n-Take a tuple type and apply strip_t to its component types.\n-Definition util.hxx:527\n-pqxx::internal::check_unique_register\n-void check_unique_register(void const *old_guest, std::string_view old_class,\n-std::string_view old_name, void const *new_guest, std::string_view new_class,\n-std::string_view new_name)\n-Check validity of registering a new \"guest\" in a \"host.\".\n-Definition util.cxx:61\n-pqxx::internal::strip_types\n-std::tuple< strip_t< TYPES >... > strip_types(std::tuple< TYPES... > const &)\n-Helper: Apply strip_t to each of a tuple type's component types.\n-pqxx::internal::describe_object\n-std::string describe_object(std::string_view class_name, std::string_view name)\n-Describe an object for humans, based on class name and optional name.\n-Definition util.cxx:51\n-pqxx::internal::args_f\n-std::tuple< ARGS... > args_f(RETURN(&func)(ARGS...))\n-Helper for determining a function's parameter types.\n-pqxx::internal::cmp_greater\n-constexpr bool cmp_greater(LEFT lhs, RIGHT rhs) noexcept\n-C++20 std::cmp_greater, or workaround if not available.\n-Definition util.hxx:85\n-pqxx::internal::args_t\n-decltype(args_f(std::declval< CALLABLE >())) args_t\n-A callable's parameter types, as a tuple.\n-Definition util.hxx:514\n-pqxx::internal::is_digit\n-constexpr bool is_digit(CHAR c) noexcept\n-A safer and more generic replacement for std::isdigit.\n-Definition util.hxx:366\n-pqxx::internal::unescape_char\n-constexpr char unescape_char(char escaped) noexcept\n-Return original byte for escaped character.\n-Definition util.hxx:531\n-pqxx::internal::cmp_greater_equal\n-constexpr bool cmp_greater_equal(LEFT lhs, RIGHT rhs) noexcept\n-C++20 std::cmp_greater_equal, or workaround if not available.\n-Definition util.hxx:111\n-pqxx::internal::cat2\n-std::string cat2(std::string_view x, std::string_view y)\n-Efficiently concatenate two strings.\n-Definition util.hxx:125\n-pqxx::internal::cmp_less_equal\n-constexpr bool cmp_less_equal(LEFT lhs, RIGHT rhs) noexcept\n-C++20 std::cmp_less_equal, or workaround if not available.\n-Definition util.hxx:98\n-pqxx::internal::ssize\n-auto ssize(T const &c)\n-Transitional: std::ssize(), or custom implementation if not available.\n-Definition util.hxx:453\n-pqxx::internal::size_unesc_bin\n-constexpr std::size_t size_unesc_bin(std::size_t escaped_bytes) noexcept\n-Compute binary size from the size of its escaped version.\n-Definition util.hxx:420\n-pqxx::internal::pq\n-Definition util.hxx:596\n-pqxx::internal::pq::pqfreemem\n-void pqfreemem(void const *) noexcept\n-Wrapper for PQfreemem(), with C++ linkage.\n-Definition util.cxx:199\n-pqxx::range_error\n-Something is out of range, similar to std::out_of_range.\n-Definition except.hxx:326\n-pqxx::thread_safety_model\n-Descriptor of library's thread-safety model.\n-Definition util.hxx:255\n-pqxx::thread_safety_model::description\n-std::string description\n-A human-readable description of any thread-safety issues.\n-Definition util.hxx:269\n+pqxx::to_string\n+std::string to_string(field const &value)\n+Convert a field to a string.\n+Definition result.cxx:549\n+pqxx::result\n+Result set containing data returned by a query or command.\n+Definition result.hxx:73\n+pqxx::string_traits\n+Traits class for use in string conversions.\n+Definition strconv.hxx:155\n * include\n * pqxx\n- * util.hxx\n+ * separated_list.hxx\n * Generated by [doxygen] 1.9.8\n"}]}, {"source1": "./usr/share/doc/libpqxx-doc/html/a00011_source.html", "source2": "./usr/share/doc/libpqxx-doc/html/a00011_source.html", "unified_diff": "@@ -1,15 +1,15 @@\n \n \n \n \n \n \n \n-libpqxx: notification.hxx Source File\n+libpqxx: result.hxx Source File\n \n \n \n \n \n \n \n@@ -60,82 +60,280 @@\n \n
\n
\n-
notification.hxx
\n+
result.hxx
\n
\n
\n-
1/* Definition of the pqxx::notification_receiver functor interface.
\n+
1/* Definitions for the pqxx::result class and support classes.
\n
2 *
\n-
3 * pqxx::notification_receiver handles incoming notifications.
\n+
3 * pqxx::result represents the set of result rows from a database query.
\n
4 *
\n-
5 * DO NOT INCLUDE THIS FILE DIRECTLY; include pqxx/notification instead.
\n+
5 * DO NOT INCLUDE THIS FILE DIRECTLY; include pqxx/result instead.
\n
6 *
\n
7 * Copyright (c) 2000-2023, Jeroen T. Vermeulen.
\n
8 *
\n
9 * See COPYING for copyright license. If you did not receive a file called
\n
10 * COPYING with this source code, please notify the distributor of this
\n
11 * mistake, or contact the author.
\n
12 */
\n-
13#ifndef PQXX_H_NOTIFICATION
\n-
14#define PQXX_H_NOTIFICATION
\n+
13#ifndef PQXX_H_RESULT
\n+
14#define PQXX_H_RESULT
\n
15
\n
16#if !defined(PQXX_HEADER_PRE)
\n
17# error "Include libpqxx headers as <pqxx/header>, not <pqxx/header.hxx>."
\n
18#endif
\n
19
\n-
20#include <string>
\n-
21
\n-
22#include "pqxx/types.hxx"
\n-
23
\n+
20#include <functional>
\n+
21#include <ios>
\n+
22#include <memory>
\n+
23#include <stdexcept>
\n
24
\n-
25namespace pqxx
\n-
26{
\n-
28
\n-
\n-
56class PQXX_LIBEXPORT PQXX_NOVTABLE notification_receiver
\n-
57{
\n-
58public:
\n-
60
\n-
64 notification_receiver(connection &c, std::string_view channel);
\n-\n-\n-
70 virtual ~notification_receiver();
\n-
71
\n-
73 [[nodiscard]] std::string const &channel() const & { return m_channel; }
\n-
74
\n-
75 // TODO: Change API to take payload as zview instead of string ref.
\n-
77
\n-
84 virtual void operator()(std::string const &payload, int backend_pid) = 0;
\n-
85
\n-
86protected:
\n-
87 connection &conn() const noexcept { return m_conn; }
\n-
88
\n-
89private:
\n-
90 connection &m_conn;
\n-
91 std::string m_channel;
\n-
92};
\n+
25#include "pqxx/except.hxx"
\n+
26#include "pqxx/types.hxx"
\n+
27#include "pqxx/util.hxx"
\n+
28#include "pqxx/zview.hxx"
\n+
29
\n+
30#include "pqxx/internal/encodings.hxx"
\n+
31
\n+
32
\n+
33namespace pqxx::internal
\n+
34{
\n+
35PQXX_LIBEXPORT void clear_result(pq::PGresult const *) noexcept;
\n+
36} // namespace pqxx::internal
\n+
37
\n+
38
\n+\n+
40{
\n+
41class result_connection;
\n+
42class result_creation;
\n+
43class result_pipeline;
\n+
44class result_row;
\n+
45class result_sql_cursor;
\n+
46} // namespace pqxx::internal::gate
\n+
47
\n+
48
\n+
49namespace pqxx
\n+
50{
\n+
52
\n+
\n+
72class PQXX_LIBEXPORT result
\n+
73{
\n+
74public:
\n+\n+\n+
77 using reference = row;
\n+
78 using const_iterator = const_result_iterator;
\n+\n+\n+
81 using const_reverse_iterator = const_reverse_result_iterator;
\n+\n+
83
\n+
\n+
84 result() noexcept :
\n+
85 m_data{make_data_pointer()},
\n+
86 m_query{},
\n+
87 m_encoding{internal::encoding_group::MONOBYTE}
\n+
88 {}
\n
\n-
93} // namespace pqxx
\n-
94#endif
\n+
89
\n+
90 result(result const &rhs) noexcept = default;
\n+
91 result(result &&rhs) noexcept = default;
\n+
92
\n+
94
\n+
97 result &operator=(result const &rhs) noexcept = default;
\n+
98
\n+
100 result &operator=(result &&rhs) noexcept = default;
\n+
101
\n+
111 [[nodiscard]] bool operator==(result const &) const noexcept;
\n+
\n+
113 [[nodiscard]] bool operator!=(result const &rhs) const noexcept
\n+
114 {
\n+
115 return not operator==(rhs);
\n+
116 }
\n+
\n+
118
\n+
120
\n+
126 template<typename... TYPE> auto iter() const;
\n+
127
\n+
128 [[nodiscard]] const_reverse_iterator rbegin() const;
\n+
129 [[nodiscard]] const_reverse_iterator crbegin() const;
\n+
130 [[nodiscard]] const_reverse_iterator rend() const;
\n+
131 [[nodiscard]] const_reverse_iterator crend() const;
\n+
132
\n+
133 [[nodiscard]] const_iterator begin() const noexcept;
\n+
134 [[nodiscard]] const_iterator cbegin() const noexcept;
\n+
135 [[nodiscard]] inline const_iterator end() const noexcept;
\n+
136 [[nodiscard]] inline const_iterator cend() const noexcept;
\n+
137
\n+
138 [[nodiscard]] reference front() const noexcept;
\n+
139 [[nodiscard]] reference back() const noexcept;
\n+
140
\n+
141 [[nodiscard]] PQXX_PURE size_type size() const noexcept;
\n+
142 [[nodiscard]] PQXX_PURE bool empty() const noexcept;
\n+
143 [[nodiscard]] size_type capacity() const noexcept { return size(); }
\n+
144
\n+
146
\n+
150 void swap(result &) noexcept;
\n+
151
\n+
153
\n+
157 [[nodiscard]] row operator[](size_type i) const noexcept;
\n+
158
\n+
159#if pqxx_have_multidim
\n+
160 [[nodiscard]] field
\n+
161 operator[](size_type row_num, row_size_type col_num) const noexcept;
\n+
162#endif // pqxx_have_multidim
\n+
163
\n+
165 row at(size_type) const;
\n+
166
\n+
168 field at(size_type, row_size_type) const;
\n+
169
\n+
171
\n+
\n+
178 void clear() noexcept
\n+
179 {
\n+
180 m_data.reset();
\n+
181 m_query = nullptr;
\n+
182 }
\n+
\n+
183
\n+
189 [[nodiscard]] PQXX_PURE row_size_type columns() const noexcept;
\n+
190
\n+
192 [[nodiscard]] row_size_type column_number(zview name) const;
\n+
193
\n+
195 [[nodiscard]] char const *column_name(row_size_type number) const &;
\n+
196
\n+
198 [[nodiscard]] oid column_type(row_size_type col_num) const;
\n+
199
\n+
\n+
201 [[nodiscard]] oid column_type(zview col_name) const
\n+
202 {
\n+
203 return column_type(column_number(col_name));
\n+
204 }
\n+
\n+
205
\n+
207 [[nodiscard]] oid column_table(row_size_type col_num) const;
\n+
208
\n+
\n+
210 [[nodiscard]] oid column_table(zview col_name) const
\n+
211 {
\n+
212 return column_table(column_number(col_name));
\n+
213 }
\n+
\n+
214
\n+
216 [[nodiscard]] row_size_type table_column(row_size_type col_num) const;
\n+
217
\n+
\n+
219 [[nodiscard]] row_size_type table_column(zview col_name) const
\n+
220 {
\n+
221 return table_column(column_number(col_name));
\n+
222 }
\n+
\n+
224
\n+
226 [[nodiscard]] PQXX_PURE std::string const &query() const &noexcept;
\n+
227
\n+
229
\n+
232 [[nodiscard]] PQXX_PURE oid inserted_oid() const;
\n+
233
\n+
235
\n+
238 [[nodiscard]] PQXX_PURE size_type affected_rows() const;
\n+
239
\n+
240 // C++20: Concept like std::invocable, but without specifying param types.
\n+
242
\n+
276 template<typename CALLABLE> inline void for_each(CALLABLE &&func) const;
\n+
277
\n+
278private:
\n+
279 using data_pointer = std::shared_ptr<internal::pq::PGresult const>;
\n+
280
\n+
282 data_pointer m_data;
\n+
283
\n+
285 static data_pointer
\n+
286 make_data_pointer(internal::pq::PGresult const *res = nullptr) noexcept
\n+
287 {
\n+
288 return {res, internal::clear_result};
\n+
289 }
\n+
290
\n+
291 friend class pqxx::internal::gate::result_pipeline;
\n+
292 PQXX_PURE std::shared_ptr<std::string const> query_ptr() const noexcept
\n+
293 {
\n+
294 return m_query;
\n+
295 }
\n+
296
\n+
298 std::shared_ptr<std::string const> m_query;
\n+
299
\n+
300 internal::encoding_group m_encoding;
\n+
301
\n+
302 static std::string const s_empty_string;
\n+
303
\n+
304 friend class pqxx::field;
\n+
305 PQXX_PURE char const *
\n+
306 get_value(size_type row, row_size_type col) const noexcept;
\n+
307 PQXX_PURE bool get_is_null(size_type row, row_size_type col) const noexcept;
\n+
308 PQXX_PURE
\n+
309 field_size_type get_length(size_type, row_size_type) const noexcept;
\n+
310
\n+
311 friend class pqxx::internal::gate::result_creation;
\n+
312 result(
\n+
313 internal::pq::PGresult *rhs, std::shared_ptr<std::string> query,
\n+
314 internal::encoding_group enc);
\n+
315
\n+
316 PQXX_PRIVATE void check_status(std::string_view desc = ""sv) const;
\n+
317
\n+
318 friend class pqxx::internal::gate::result_connection;
\n+
319 friend class pqxx::internal::gate::result_row;
\n+
320 bool operator!() const noexcept { return m_data.get() == nullptr; }
\n+
321 operator bool() const noexcept { return m_data.get() != nullptr; }
\n+
322
\n+
323 [[noreturn]] PQXX_PRIVATE PQXX_COLD void
\n+
324 throw_sql_error(std::string const &Err, std::string const &Query) const;
\n+
325 PQXX_PRIVATE PQXX_PURE int errorposition() const;
\n+
326 PQXX_PRIVATE std::string status_error() const;
\n+
327
\n+
328 friend class pqxx::internal::gate::result_sql_cursor;
\n+
329 PQXX_PURE char const *cmd_status() const noexcept;
\n+
330};
\n+
\n+
331} // namespace pqxx
\n+
332#endif
\n
The home of all libpqxx classes, functions, templates, etc.
Definition array.hxx:33
\n-
Connection to a database.
Definition connection.hxx:253
\n-
Definition notification.hxx:57
\n-
notification_receiver(notification_receiver const &)=delete
Register the receiver with a connection.
\n-
std::string const & channel() const &
The channel that this receiver listens on.
Definition notification.hxx:73
\n-
virtual void operator()(std::string const &payload, int backend_pid)=0
Overridable: action to invoke when notification arrives.
\n-
connection & conn() const noexcept
Definition notification.hxx:87
\n-
notification_receiver & operator=(notification_receiver const &)=delete
Register the receiver with a connection.
\n+
int row_size_type
Number of fields in a row of database data.
Definition types.hxx:34
\n+
std::size_t field_size_type
Number of bytes in a field of database data.
Definition types.hxx:40
\n+
int result_difference_type
Difference between result sizes.
Definition types.hxx:31
\n+
int result_size_type
Number of rows in a result set.
Definition types.hxx:28
\n+
Internal items for libpqxx' own use. Do not use these yourself.
Definition composite.hxx:84
\n+
void clear_result(pq::PGresult const *) noexcept
C++ wrapper for libpq's PQclear.
Definition result.cxx:42
\n+
Definition connection.hxx:112
\n+
Reference to a field in a result set.
Definition field.hxx:35
\n+
Result set containing data returned by a query or command.
Definition result.hxx:73
\n+
const_reverse_result_iterator const_reverse_iterator
Definition result.hxx:81
\n+
result(result &&rhs) noexcept=default
\n+
row_size_type table_column(zview col_name) const
What column in its table did this column come from?
Definition result.hxx:219
\n+
result() noexcept
Definition result.hxx:84
\n+
result & operator=(result &&rhs) noexcept=default
Assign one result to another, invaliding the old one.
\n+
result_size_type size_type
Definition result.hxx:75
\n+
bool operator!=(result const &rhs) const noexcept
Compare two results for inequality.
Definition result.hxx:113
\n+
const_iterator pointer
Definition result.hxx:79
\n+
void clear() noexcept
Let go of the result's data.
Definition result.hxx:178
\n+
const_iterator iterator
Definition result.hxx:80
\n+
result_difference_type difference_type
Definition result.hxx:76
\n+
const_reverse_iterator reverse_iterator
Definition result.hxx:82
\n+
oid column_table(zview col_name) const
What table did this column come from?
Definition result.hxx:210
\n+
result & operator=(result const &rhs) noexcept=default
Assign one result to another.
\n+
const_result_iterator const_iterator
Definition result.hxx:78
\n+
result(result const &rhs) noexcept=default
\n+
auto iter() const
Iterate rows, reading them directly into a tuple of "TYPE...".
\n+
Reference to one row in a result.
Definition row.hxx:47
\n+
Marker-type wrapper: zero-terminated std::string_view.
Definition zview.hxx:38
\n
\n
\n \n
\n \n
\n \n \n", "details": [{"source1": "html2text {}", "source2": "html2text {}", "unified_diff": "@@ -1,87 +1,322 @@\n \n \n \n \n \n libpqxx\u00a07.8.1\n \n-notification.hxx\n- 1/* Definition of the pqxx::notification_receiver functor interface.\n+result.hxx\n+ 1/* Definitions for the pqxx::result class and support classes.\n 2 *\n- 3 * pqxx::notification_receiver handles incoming notifications.\n+ 3 * pqxx::result represents the set of result rows from a database query.\n 4 *\n- 5 * DO NOT INCLUDE THIS FILE DIRECTLY; include pqxx/notification instead.\n+ 5 * DO NOT INCLUDE THIS FILE DIRECTLY; include pqxx/result instead.\n 6 *\n 7 * Copyright (c) 2000-2023, Jeroen T. Vermeulen.\n 8 *\n 9 * See COPYING for copyright license. If you did not receive a file called\n 10 * COPYING with this source code, please notify the distributor of this\n 11 * mistake, or contact the author.\n 12 */\n- 13#ifndef PQXX_H_NOTIFICATION\n- 14#define PQXX_H_NOTIFICATION\n+ 13#ifndef PQXX_H_RESULT\n+ 14#define PQXX_H_RESULT\n 15\n 16#if !defined(PQXX_HEADER_PRE)\n 17# error \"Include libpqxx headers as , not .\"\n 18#endif\n 19\n- 20#include \n- 21\n- 22#include \"pqxx/types.hxx\"\n- 23\n+ 20#include \n+ 21#include \n+ 22#include \n+ 23#include \n 24\n- 25namespace pqxx\n- 26{\n- 28\n-56class PQXX_LIBEXPORT PQXX_NOVTABLE notification_receiver\n- 57{\n- 58public:\n- 60\n- 64 notification_receiver(connection &c, std::string_view channel);\n-66 notification_receiver(notification_receiver const &) = delete;\n-68 notification_receiver &operator=(notification_receiver const &) = delete;\n- 70 virtual ~notification_receiver();\n- 71\n-73 [[nodiscard]] std::string const &channel() const & { return m_channel; }\n- 74\n- 75 // TODO: Change API to take payload as zview instead of string ref.\n- 77\n-84 virtual void operator()(std::string const &payload, int backend_pid) = 0;\n- 85\n- 86protected:\n-87 connection &conn() const noexcept { return m_conn; }\n- 88\n- 89private:\n- 90 connection &m_conn;\n- 91 std::string m_channel;\n- 92};\n- 93} // namespace pqxx\n- 94#endif\n+ 25#include \"pqxx/except.hxx\"\n+ 26#include \"pqxx/types.hxx\"\n+ 27#include \"pqxx/util.hxx\"\n+ 28#include \"pqxx/zview.hxx\"\n+ 29\n+ 30#include \"pqxx/internal/encodings.hxx\"\n+ 31\n+ 32\n+ 33namespace pqxx::internal\n+ 34{\n+ 35PQXX_LIBEXPORT void clear_result(pq::PGresult const *) noexcept;\n+ 36} // namespace pqxx::internal\n+ 37\n+ 38\n+ 39namespace pqxx::internal::gate\n+ 40{\n+ 41class result_connection;\n+ 42class result_creation;\n+ 43class result_pipeline;\n+ 44class result_row;\n+ 45class result_sql_cursor;\n+ 46} // namespace pqxx::internal::gate\n+ 47\n+ 48\n+ 49namespace pqxx\n+ 50{\n+ 52\n+72class PQXX_LIBEXPORT result\n+ 73{\n+ 74public:\n+75 using size_type = result_size_type;\n+76 using difference_type = result_difference_type;\n+77 using reference = row;\n+78 using const_iterator = const_result_iterator;\n+79 using pointer = const_iterator;\n+80 using iterator = const_iterator;\n+81 using const_reverse_iterator = const_reverse_result_iterator;\n+82 using reverse_iterator = const_reverse_iterator;\n+ 83\n+84 result() noexcept :\n+ 85 m_data{make_data_pointer()},\n+ 86 m_query{},\n+ 87 m_encoding{internal::encoding_group::MONOBYTE}\n+ 88 {}\n+ 89\n+90 result(result const &rhs) noexcept = default;\n+91 result(result &&rhs) noexcept = default;\n+ 92\n+ 94\n+97 result &operator=(result const &rhs) noexcept = default;\n+ 98\n+100 result &operator=(result &&rhs) noexcept = default;\n+ 101\n+ 111 [[nodiscard]] bool operator==(result const &) const noexcept;\n+113 [[nodiscard]] bool operator!=(result const &rhs) const noexcept\n+ 114 {\n+ 115 return not operator==(rhs);\n+ 116 }\n+ 118\n+ 120\n+126 template auto iter() const;\n+ 127\n+ 128 [[nodiscard]] const_reverse_iterator rbegin() const;\n+ 129 [[nodiscard]] const_reverse_iterator crbegin() const;\n+ 130 [[nodiscard]] const_reverse_iterator rend() const;\n+ 131 [[nodiscard]] const_reverse_iterator crend() const;\n+ 132\n+ 133 [[nodiscard]] const_iterator begin() const noexcept;\n+ 134 [[nodiscard]] const_iterator cbegin() const noexcept;\n+135 [[nodiscard]] inline const_iterator end() const noexcept;\n+136 [[nodiscard]] inline const_iterator cend() const noexcept;\n+ 137\n+ 138 [[nodiscard]] reference front() const noexcept;\n+ 139 [[nodiscard]] reference back() const noexcept;\n+ 140\n+ 141 [[nodiscard]] PQXX_PURE size_type size() const noexcept;\n+ 142 [[nodiscard]] PQXX_PURE bool empty() const noexcept;\n+143 [[nodiscard]] size_type capacity() const noexcept { return size(); }\n+ 144\n+ 146\n+ 150 void swap(result &) noexcept;\n+ 151\n+ 153\n+ 157 [[nodiscard]] row operator[](size_type i) const noexcept;\n+ 158\n+ 159#if pqxx_have_multidim\n+ 160 [[nodiscard]] field\n+ 161 operator[](size_type row_num, row_size_type col_num) const noexcept;\n+ 162#endif // pqxx_have_multidim\n+ 163\n+ 165 row at(size_type) const;\n+ 166\n+ 168 field at(size_type, row_size_type) const;\n+ 169\n+ 171\n+178 void clear() noexcept\n+ 179 {\n+ 180 m_data.reset();\n+ 181 m_query = nullptr;\n+ 182 }\n+ 183\n+ 189 [[nodiscard]] PQXX_PURE row_size_type columns() const noexcept;\n+ 190\n+ 192 [[nodiscard]] row_size_type column_number(zview name) const;\n+ 193\n+ 195 [[nodiscard]] char const *column_name(row_size_type number) const &;\n+ 196\n+ 198 [[nodiscard]] oid column_type(row_size_type col_num) const;\n+ 199\n+201 [[nodiscard]] oid column_type(zview col_name) const\n+ 202 {\n+ 203 return column_type(column_number(col_name));\n+ 204 }\n+ 205\n+ 207 [[nodiscard]] oid column_table(row_size_type col_num) const;\n+ 208\n+210 [[nodiscard]] oid column_table(zview col_name) const\n+ 211 {\n+ 212 return column_table(column_number(col_name));\n+ 213 }\n+ 214\n+ 216 [[nodiscard]] row_size_type table_column(row_size_type col_num) const;\n+ 217\n+219 [[nodiscard]] row_size_type table_column(zview col_name) const\n+ 220 {\n+ 221 return table_column(column_number(col_name));\n+ 222 }\n+ 224\n+ 226 [[nodiscard]] PQXX_PURE std::string const &query() const &noexcept;\n+ 227\n+ 229\n+ 232 [[nodiscard]] PQXX_PURE oid inserted_oid() const;\n+ 233\n+ 235\n+ 238 [[nodiscard]] PQXX_PURE size_type affected_rows() const;\n+ 239\n+ 240 // C++20: Concept like std::invocable, but without specifying param types.\n+ 242\n+276 template inline void for_each(CALLABLE &&func) const;\n+ 277\n+ 278private:\n+ 279 using data_pointer = std::shared_ptr;\n+ 280\n+ 282 data_pointer m_data;\n+ 283\n+ 285 static data_pointer\n+ 286 make_data_pointer(internal::pq::PGresult const *res = nullptr) noexcept\n+ 287 {\n+ 288 return {res, internal::clear_result};\n+ 289 }\n+ 290\n+291 friend class pqxx::internal::gate::result_pipeline;\n+ 292 PQXX_PURE std::shared_ptr query_ptr() const noexcept\n+ 293 {\n+ 294 return m_query;\n+ 295 }\n+ 296\n+ 298 std::shared_ptr m_query;\n+ 299\n+ 300 internal::encoding_group m_encoding;\n+ 301\n+ 302 static std::string const s_empty_string;\n+ 303\n+304 friend class pqxx::field;\n+ 305 PQXX_PURE char const *\n+ 306 get_value(size_type row, row_size_type col) const noexcept;\n+ 307 PQXX_PURE bool get_is_null(size_type row, row_size_type col) const\n+noexcept;\n+ 308 PQXX_PURE\n+ 309 field_size_type get_length(size_type, row_size_type) const noexcept;\n+ 310\n+311 friend class pqxx::internal::gate::result_creation;\n+ 312 result(\n+ 313 internal::pq::PGresult *rhs, std::shared_ptr query,\n+ 314 internal::encoding_group enc);\n+ 315\n+ 316 PQXX_PRIVATE void check_status(std::string_view desc = \"\"sv) const;\n+ 317\n+318 friend class pqxx::internal::gate::result_connection;\n+319 friend class pqxx::internal::gate::result_row;\n+ 320 bool operator!() const noexcept { return m_data.get() == nullptr; }\n+ 321 operator bool() const noexcept { return m_data.get() != nullptr; }\n+ 322\n+ 323 [[noreturn]] PQXX_PRIVATE PQXX_COLD void\n+ 324 throw_sql_error(std::string const &Err, std::string const &Query) const;\n+ 325 PQXX_PRIVATE PQXX_PURE int errorposition() const;\n+ 326 PQXX_PRIVATE std::string status_error() const;\n+ 327\n+328 friend class pqxx::internal::gate::result_sql_cursor;\n+ 329 PQXX_PURE char const *cmd_status() const noexcept;\n+ 330};\n+ 331} // namespace pqxx\n+ 332#endif\n pqxx\n The home of all libpqxx classes, functions, templates, etc.\n Definition array.hxx:33\n-pqxx::connection\n-Connection to a database.\n-Definition connection.hxx:253\n-pqxx::notification_receiver\n-Definition notification.hxx:57\n-pqxx::notification_receiver::notification_receiver\n-notification_receiver(notification_receiver const &)=delete\n-Register the receiver with a connection.\n-pqxx::notification_receiver::channel\n-std::string const & channel() const &\n-The channel that this receiver listens on.\n-Definition notification.hxx:73\n-pqxx::notification_receiver::operator()\n-virtual void operator()(std::string const &payload, int backend_pid)=0\n-Overridable: action to invoke when notification arrives.\n-pqxx::notification_receiver::conn\n-connection & conn() const noexcept\n-Definition notification.hxx:87\n-pqxx::notification_receiver::operator=\n-notification_receiver & operator=(notification_receiver const &)=delete\n-Register the receiver with a connection.\n+pqxx::row_size_type\n+int row_size_type\n+Number of fields in a row of database data.\n+Definition types.hxx:34\n+pqxx::field_size_type\n+std::size_t field_size_type\n+Number of bytes in a field of database data.\n+Definition types.hxx:40\n+pqxx::result_difference_type\n+int result_difference_type\n+Difference between result sizes.\n+Definition types.hxx:31\n+pqxx::result_size_type\n+int result_size_type\n+Number of rows in a result set.\n+Definition types.hxx:28\n+pqxx::internal\n+Internal items for libpqxx' own use. Do not use these yourself.\n+Definition composite.hxx:84\n+pqxx::internal::clear_result\n+void clear_result(pq::PGresult const *) noexcept\n+C++ wrapper for libpq's PQclear.\n+Definition result.cxx:42\n+pqxx::internal::gate\n+Definition connection.hxx:112\n+pqxx::field\n+Reference to a field in a result set.\n+Definition field.hxx:35\n+pqxx::result\n+Result set containing data returned by a query or command.\n+Definition result.hxx:73\n+pqxx::result::const_reverse_iterator\n+const_reverse_result_iterator const_reverse_iterator\n+Definition result.hxx:81\n+pqxx::result::result\n+result(result &&rhs) noexcept=default\n+pqxx::result::table_column\n+row_size_type table_column(zview col_name) const\n+What column in its table did this column come from?\n+Definition result.hxx:219\n+pqxx::result::result\n+result() noexcept\n+Definition result.hxx:84\n+pqxx::result::operator=\n+result & operator=(result &&rhs) noexcept=default\n+Assign one result to another, invaliding the old one.\n+pqxx::result::size_type\n+result_size_type size_type\n+Definition result.hxx:75\n+pqxx::result::operator!=\n+bool operator!=(result const &rhs) const noexcept\n+Compare two results for inequality.\n+Definition result.hxx:113\n+pqxx::result::pointer\n+const_iterator pointer\n+Definition result.hxx:79\n+pqxx::result::clear\n+void clear() noexcept\n+Let go of the result's data.\n+Definition result.hxx:178\n+pqxx::result::iterator\n+const_iterator iterator\n+Definition result.hxx:80\n+pqxx::result::difference_type\n+result_difference_type difference_type\n+Definition result.hxx:76\n+pqxx::result::reverse_iterator\n+const_reverse_iterator reverse_iterator\n+Definition result.hxx:82\n+pqxx::result::column_table\n+oid column_table(zview col_name) const\n+What table did this column come from?\n+Definition result.hxx:210\n+pqxx::result::operator=\n+result & operator=(result const &rhs) noexcept=default\n+Assign one result to another.\n+pqxx::result::const_iterator\n+const_result_iterator const_iterator\n+Definition result.hxx:78\n+pqxx::result::result\n+result(result const &rhs) noexcept=default\n+pqxx::result::iter\n+auto iter() const\n+Iterate rows, reading them directly into a tuple of \"TYPE...\".\n+pqxx::row\n+Reference to one row in a result.\n+Definition row.hxx:47\n+pqxx::zview\n+Marker-type wrapper: zero-terminated std::string_view.\n+Definition zview.hxx:38\n * include\n * pqxx\n- * notification.hxx\n+ * result.hxx\n * Generated by [doxygen] 1.9.8\n"}]}, {"source1": "./usr/share/doc/libpqxx-doc/html/a00014_source.html", "source2": "./usr/share/doc/libpqxx-doc/html/a00014_source.html", "unified_diff": "@@ -1,15 +1,15 @@\n \n \n \n \n \n \n \n-libpqxx: dbtransaction.hxx Source File\n+libpqxx: params.hxx Source File\n \n \n \n \n \n \n \n@@ -60,73 +60,312 @@\n \n
\n
\n-
dbtransaction.hxx
\n+
params.hxx
\n
\n
\n-
1/* Definition of the pqxx::dbtransaction abstract base class.
\n+
1/* Helpers for prepared statements and parameterised statements.
\n
2 *
\n-
3 * pqxx::dbransaction defines a real transaction on the database.
\n+
3 * See the connection class for more about such statements.
\n
4 *
\n-
5 * DO NOT INCLUDE THIS FILE DIRECTLY; include pqxx/dbtransaction instead.
\n+
5 * Copyright (c) 2000-2023, Jeroen T. Vermeulen.
\n
6 *
\n-
7 * Copyright (c) 2000-2023, Jeroen T. Vermeulen.
\n-
8 *
\n-
9 * See COPYING for copyright license. If you did not receive a file called
\n-
10 * COPYING with this source code, please notify the distributor of this
\n-
11 * mistake, or contact the author.
\n-
12 */
\n-
13#ifndef PQXX_H_DBTRANSACTION
\n-
14#define PQXX_H_DBTRANSACTION
\n-
15
\n-
16#if !defined(PQXX_HEADER_PRE)
\n-
17# error "Include libpqxx headers as <pqxx/header>, not <pqxx/header.hxx>."
\n-
18#endif
\n+
7 * See COPYING for copyright license. If you did not receive a file called
\n+
8 * COPYING with this source code, please notify the distributor of this
\n+
9 * mistake, or contact the author.
\n+
10 */
\n+
11#ifndef PQXX_H_PARAMS
\n+
12#define PQXX_H_PARAMS
\n+
13
\n+
14#if !defined(PQXX_HEADER_PRE)
\n+
15# error "Include libpqxx headers as <pqxx/header>, not <pqxx/header.hxx>."
\n+
16#endif
\n+
17
\n+
18#include <array>
\n
19
\n-
20#include "pqxx/transaction_base.hxx"
\n-
21
\n-
22namespace pqxx
\n-
23{
\n-
25
\n-
\n-
53class PQXX_LIBEXPORT PQXX_NOVTABLE dbtransaction : public transaction_base
\n-
54{
\n-
55protected:
\n-\n-
\n-
59 dbtransaction(connection &c, std::string_view tname) :
\n-
60 transaction_base{c, tname}
\n-
61 {}
\n-
\n-
\n-\n-
64 connection &c, std::string_view tname,
\n-
65 std::shared_ptr<std::string> rollback_cmd) :
\n-
66 transaction_base{c, tname, rollback_cmd}
\n-
67 {}
\n+
20#include "pqxx/internal/concat.hxx"
\n+
21#include "pqxx/internal/statement_parameters.hxx"
\n+
22#include "pqxx/types.hxx"
\n+
23
\n+
24
\n+
\n+\n+
27{
\n+
29
\n+
46template<typename IT>
\n+
47[[deprecated("Use the params class instead.")]] constexpr inline auto
\n+
\n+
48make_dynamic_params(IT begin, IT end)
\n+
49{
\n+
50 return pqxx::internal::dynamic_params(begin, end);
\n+
51}
\n
\n-
68};
\n+
52
\n+
53
\n+
55
\n+
71template<typename C>
\n+
72[[deprecated("Use the params class instead.")]] constexpr inline auto
\n+
\n+
73make_dynamic_params(C const &container)
\n+
74{
\n+
75 using IT = typename C::const_iterator;
\n+
76#include "pqxx/internal/ignore-deprecated-pre.hxx"
\n+
77 return pqxx::internal::dynamic_params<IT>{container};
\n+
78#include "pqxx/internal/ignore-deprecated-post.hxx"
\n+
79}
\n
\n-
69} // namespace pqxx
\n-
70#endif
\n+
80
\n+
81
\n+
83
\n+
100template<typename C, typename ACCESSOR>
\n+
101[[deprecated("Use the params class instead.")]] constexpr inline auto
\n+
\n+
102make_dynamic_params(C &container, ACCESSOR accessor)
\n+
103{
\n+
104 using IT = decltype(std::begin(container));
\n+
105#include "pqxx/internal/ignore-deprecated-pre.hxx"
\n+
106 return pqxx::internal::dynamic_params<IT, ACCESSOR>{container, accessor};
\n+
107#include "pqxx/internal/ignore-deprecated-post.hxx"
\n+
108}
\n+
\n+
109} // namespace pqxx::prepare
\n+
\n+
110
\n+
111
\n+
112namespace pqxx
\n+
113{
\n+
115
\n+
\n+
125template<typename COUNTER = unsigned int> class placeholders
\n+
126{
\n+
127public:
\n+
\n+
129 static inline constexpr unsigned int max_params{
\n+
130 (std::numeric_limits<COUNTER>::max)()};
\n+
\n+
131
\n+
\n+\n+
133 {
\n+
134 static constexpr auto initial{"$1\\0"sv};
\n+
135 initial.copy(std::data(m_buf), std::size(initial));
\n+
136 }
\n+
\n+
137
\n+
139
\n+
\n+
142 constexpr zview view() const &noexcept
\n+
143 {
\n+
144 return zview{std::data(m_buf), m_len};
\n+
145 }
\n+
\n+
146
\n+
148
\n+
153 std::string get() const { return std::string(std::data(m_buf), m_len); }
\n+
154
\n+
\n+
156 void next() &
\n+
157 {
\n+
158 if (m_current >= max_params)
\n+
159 throw range_error{pqxx::internal::concat(
\n+
160 "Too many parameters in one statement: limit is ", max_params, ".")};
\n+
161 ++m_current;
\n+
162 if (m_current % 10 == 0)
\n+
163 {
\n+
164 // Carry the 1. Don't get too clever for this relatively rare
\n+
165 // case, just rewrite the entire number. Leave the $ in place
\n+
166 // though.
\n+
167 char *const data{std::data(m_buf)};
\n+
168 char *const end{string_traits<COUNTER>::into_buf(
\n+
169 data + 1, data + std::size(m_buf), m_current)};
\n+
170 // (Subtract because we don't include the trailing zero.)
\n+
171 m_len = check_cast<COUNTER>(end - data, "placeholders counter") - 1;
\n+
172 }
\n+
173 else
\n+
174 {
\n+
175 PQXX_LIKELY
\n+
176 // Shortcut for the common case: just increment that last digit.
\n+
177 ++m_buf[m_len - 1];
\n+
178 }
\n+
179 }
\n+
\n+
180
\n+
182 COUNTER count() const noexcept { return m_current; }
\n+
183
\n+
184private:
\n+
186 COUNTER m_current = 1;
\n+
187
\n+
189 COUNTER m_len = 2;
\n+
190
\n+
192
\n+
199 std::array<char, std::numeric_limits<COUNTER>::digits10 + 3> m_buf;
\n+
200};
\n+
\n+
201
\n+
202
\n+
204
\n+
\n+
219class PQXX_LIBEXPORT params
\n+
220{
\n+
221public:
\n+
222 params() = default;
\n+
223
\n+
\n+
225 template<typename... Args> constexpr params(Args &&...args)
\n+
226 {
\n+
227 reserve(sizeof...(args));
\n+
228 append_pack(std::forward<Args>(args)...);
\n+
229 }
\n+
\n+
230
\n+
232
\n+
238 void reserve(std::size_t n) &;
\n+
239
\n+
240 // C++20: constexpr.
\n+
242 [[nodiscard]] auto size() const noexcept { return m_params.size(); }
\n+
243
\n+
244 // C++20: Use the vector's ssize() directly and go noexcept+constexpr.
\n+
246
\n+
251 [[nodiscard]] auto ssize() const { return pqxx::internal::ssize(m_params); }
\n+
252
\n+
254 void append() &;
\n+
255
\n+
257
\n+
260 void append(zview) &;
\n+
261
\n+
263
\n+
266 void append(std::string const &) &;
\n+
267
\n+
269 void append(std::string &&) &;
\n+
270
\n+
272
\n+
275 void append(std::basic_string_view<std::byte>) &;
\n+
276
\n+
278
\n+
282 void append(std::basic_string<std::byte> const &) &;
\n+
283
\n+
284#if defined(PQXX_HAVE_CONCEPTS)
\n+
286
\n+
289 template<binary DATA> void append(DATA const &data) &
\n+
290 {
\n+
291 append(
\n+
292 std::basic_string_view<std::byte>{std::data(data), std::size(data)});
\n+
293 }
\n+
294#endif // PQXX_HAVE_CONCEPTS
\n+
295
\n+
297 void append(std::basic_string<std::byte> &&) &;
\n+
298
\n+
300
\n+
303 void append(binarystring const &value) &;
\n+
304
\n+
306 template<typename IT, typename ACCESSOR>
\n+
\n+
307 void append(pqxx::internal::dynamic_params<IT, ACCESSOR> const &value) &
\n+
308 {
\n+
309 for (auto &param : value) append(value.access(param));
\n+
310 }
\n+
\n+
311
\n+
312 void append(params const &value) &;
\n+
313
\n+
314 void append(params &&value) &;
\n+
315
\n+
\n+
318 template<typename TYPE> void append(TYPE const &value) &
\n+
319 {
\n+
320 // TODO: Pool storage for multiple string conversions in one buffer?
\n+
321 if constexpr (nullness<strip_t<TYPE>>::always_null)
\n+
322 {
\n+
323 ignore_unused(value);
\n+
324 m_params.emplace_back();
\n+
325 }
\n+
326 else if (is_null(value))
\n+
327 {
\n+
328 m_params.emplace_back();
\n+
329 }
\n+
330 else
\n+
331 {
\n+
332 m_params.emplace_back(entry{to_string(value)});
\n+
333 }
\n+
334 }
\n+
\n+
335
\n+
\n+
337 template<PQXX_RANGE_ARG RANGE> void append_multi(RANGE const &range) &
\n+
338 {
\n+
339#if defined(PQXX_HAVE_CONCEPTS)
\n+
340 if constexpr (std::ranges::sized_range<RANGE>)
\n+
341 reserve(std::size(*this) + std::size(range));
\n+
342#endif
\n+
343 for (auto &value : range) append(value);
\n+
344 }
\n+
\n+
345
\n+
347
\n+
356 pqxx::internal::c_params make_c_params() const;
\n+
357
\n+
358private:
\n+
360 template<typename Arg, typename... More>
\n+
361 void append_pack(Arg &&arg, More &&...args)
\n+
362 {
\n+
363 this->append(std::forward<Arg>(arg));
\n+
364 // Recurse for remaining args.
\n+
365 append_pack(std::forward<More>(args)...);
\n+
366 }
\n+
367
\n+
369 constexpr void append_pack() noexcept {}
\n+
370
\n+
371 // The way we store a parameter depends on whether it's binary or text
\n+
372 // (most types are text), and whether we're responsible for storing the
\n+
373 // contents.
\n+
374 using entry = std::variant<
\n+
375 std::nullptr_t, zview, std::string, std::basic_string_view<std::byte>,
\n+
376 std::basic_string<std::byte>>;
\n+
377 std::vector<entry> m_params;
\n+
378
\n+
379 static constexpr std::string_view s_overflow{
\n+
380 "Statement parameter length overflow."sv};
\n+
381};
\n+
\n+
382} // namespace pqxx
\n+
383#endif
\n
The home of all libpqxx classes, functions, templates, etc.
Definition array.hxx:33
\n-
Connection to a database.
Definition connection.hxx:253
\n-
Abstract transaction base class: bracket transactions on the database.
Definition dbtransaction.hxx:54
\n-
dbtransaction(connection &c, std::string_view tname, std::shared_ptr< std::string > rollback_cmd)
Begin transaction.
Definition dbtransaction.hxx:63
\n-
dbtransaction(connection &c)
Begin transaction.
Definition dbtransaction.hxx:57
\n-
dbtransaction(connection &c, std::string_view tname)
Begin transaction.
Definition dbtransaction.hxx:59
\n-
Interface definition (and common code) for "transaction" classes.
Definition transaction_base.hxx:88
\n+
constexpr void ignore_unused(T &&...) noexcept
Suppress compiler warning about an unused item.
Definition util.hxx:142
\n+
std::string to_string(field const &value)
Convert a field to a string.
Definition result.cxx:549
\n+
auto ssize(T const &c)
Transitional: std::ssize(), or custom implementation if not available.
Definition util.hxx:453
\n+
Definition params.hxx:27
\n+
constexpr auto make_dynamic_params(IT begin, IT end)
Pass a number of statement parameters only known at runtime.
Definition params.hxx:48
\n+
Something is out of range, similar to std::out_of_range.
Definition except.hxx:326
\n+
Generate parameter placeholders for use in an SQL statement.
Definition params.hxx:126
\n+
static constexpr unsigned int max_params
Maximum number of parameters we support.
Definition params.hxx:129
\n+
COUNTER count() const noexcept
Return the current placeholder number. The initial placeholder is 1.
Definition params.hxx:182
\n+
std::string get() const
Read the current placeholder text, as a std::string.
Definition params.hxx:153
\n+
placeholders()
Definition params.hxx:132
\n+
constexpr zview view() const &noexcept
Read an ephemeral version of the current placeholder text.
Definition params.hxx:142
\n+
void next() &
Move on to the next parameter.
Definition params.hxx:156
\n+
Build a parameter list for a parameterised or prepared statement.
Definition params.hxx:220
\n+
auto size() const noexcept
Get the number of parameters currently in this params.
Definition params.hxx:242
\n+
void append_multi(RANGE const &range) &
Append all elements of range as parameters.
Definition params.hxx:337
\n+
void append(TYPE const &value) &
Definition params.hxx:318
\n+
params()=default
\n+
auto ssize() const
Get the number of parameters (signed).
Definition params.hxx:251
\n+
void append(pqxx::internal::dynamic_params< IT, ACCESSOR > const &value) &
Append all parameters from value.
Definition params.hxx:307
\n+
constexpr params(Args &&...args)
Pre-populate a params with args. Feel free to add more later.
Definition params.hxx:225
\n+
A C++ equivalent to PostgreSQL's range types.
Definition range.hxx:234
\n+
Traits describing a type's "null value," if any.
Definition strconv.hxx:93
\n+
static char * into_buf(char *begin, char *end, TYPE const &value)
Write value's string representation into buffer at begin.
\n+
Marker-type wrapper: zero-terminated std::string_view.
Definition zview.hxx:38
\n
\n
\n \n
\n \n
\n \n \n", "details": [{"source1": "html2text {}", "source2": "html2text {}", "unified_diff": "@@ -1,76 +1,340 @@\n \n \n \n \n \n libpqxx\u00a07.8.1\n \n-dbtransaction.hxx\n- 1/* Definition of the pqxx::dbtransaction abstract base class.\n+params.hxx\n+ 1/* Helpers for prepared statements and parameterised statements.\n 2 *\n- 3 * pqxx::dbransaction defines a real transaction on the database.\n+ 3 * See the connection class for more about such statements.\n 4 *\n- 5 * DO NOT INCLUDE THIS FILE DIRECTLY; include pqxx/dbtransaction instead.\n+ 5 * Copyright (c) 2000-2023, Jeroen T. Vermeulen.\n 6 *\n- 7 * Copyright (c) 2000-2023, Jeroen T. Vermeulen.\n- 8 *\n- 9 * See COPYING for copyright license. If you did not receive a file called\n- 10 * COPYING with this source code, please notify the distributor of this\n- 11 * mistake, or contact the author.\n- 12 */\n- 13#ifndef PQXX_H_DBTRANSACTION\n- 14#define PQXX_H_DBTRANSACTION\n- 15\n- 16#if !defined(PQXX_HEADER_PRE)\n- 17# error \"Include libpqxx headers as , not .\"\n- 18#endif\n+ 7 * See COPYING for copyright license. If you did not receive a file called\n+ 8 * COPYING with this source code, please notify the distributor of this\n+ 9 * mistake, or contact the author.\n+ 10 */\n+ 11#ifndef PQXX_H_PARAMS\n+ 12#define PQXX_H_PARAMS\n+ 13\n+ 14#if !defined(PQXX_HEADER_PRE)\n+ 15# error \"Include libpqxx headers as , not .\"\n+ 16#endif\n+ 17\n+ 18#include \n 19\n- 20#include \"pqxx/transaction_base.hxx\"\n- 21\n- 22namespace pqxx\n- 23{\n- 25\n-53class PQXX_LIBEXPORT PQXX_NOVTABLE dbtransaction : public transaction_base\n- 54{\n- 55protected:\n-57 explicit dbtransaction(connection &c) : transaction_base{c} {}\n-59 dbtransaction(connection &c, std::string_view tname) :\n- 60 transaction_base{c, tname}\n- 61 {}\n-63 dbtransaction(\n- 64 connection &c, std::string_view tname,\n- 65 std::shared_ptr rollback_cmd) :\n- 66 transaction_base{c, tname, rollback_cmd}\n- 67 {}\n- 68};\n- 69} // namespace pqxx\n- 70#endif\n+ 20#include \"pqxx/internal/concat.hxx\"\n+ 21#include \"pqxx/internal/statement_parameters.hxx\"\n+ 22#include \"pqxx/types.hxx\"\n+ 23\n+ 24\n+26namespace pqxx::prepare\n+ 27{\n+ 29\n+ 46template\n+ 47[[deprecated(\"Use the params class instead.\")]] constexpr inline auto\n+48make_dynamic_params(IT begin, IT end)\n+ 49{\n+ 50 return pqxx::internal::dynamic_params(begin, end);\n+ 51}\n+ 52\n+ 53\n+ 55\n+ 71template\n+ 72[[deprecated(\"Use the params class instead.\")]] constexpr inline auto\n+73make_dynamic_params(C const &container)\n+ 74{\n+ 75 using IT = typename C::const_iterator;\n+ 76#include \"pqxx/internal/ignore-deprecated-pre.hxx\"\n+ 77 return pqxx::internal::dynamic_params{container};\n+ 78#include \"pqxx/internal/ignore-deprecated-post.hxx\"\n+ 79}\n+ 80\n+ 81\n+ 83\n+ 100template\n+ 101[[deprecated(\"Use the params class instead.\")]] constexpr inline auto\n+102make_dynamic_params(C &container, ACCESSOR accessor)\n+ 103{\n+ 104 using IT = decltype(std::begin(container));\n+ 105#include \"pqxx/internal/ignore-deprecated-pre.hxx\"\n+ 106 return pqxx::internal::dynamic_params{container, accessor};\n+ 107#include \"pqxx/internal/ignore-deprecated-post.hxx\"\n+ 108}\n+ 109} // namespace pqxx::prepare\n+ 110\n+ 111\n+ 112namespace pqxx\n+ 113{\n+ 115\n+125template class placeholders\n+ 126{\n+ 127public:\n+129 static inline constexpr unsigned int max_params{\n+ 130 (std::numeric_limits::max)()};\n+ 131\n+132 placeholders()\n+ 133 {\n+ 134 static constexpr auto initial{\"$1\\0\"sv};\n+ 135 initial.copy(std::data(m_buf), std::size(initial));\n+ 136 }\n+ 137\n+ 139\n+142 constexpr zview view() const &noexcept\n+ 143 {\n+ 144 return zview{std::data(m_buf), m_len};\n+ 145 }\n+ 146\n+ 148\n+153 std::string get() const { return std::string(std::data(m_buf), m_len); }\n+ 154\n+156 void next() &\n+ 157 {\n+ 158 if (m_current >= max_params)\n+ 159 throw range_error{pqxx::internal::concat(\n+ 160 \"Too many parameters in one statement: limit is \", max_params, \".\")};\n+ 161 ++m_current;\n+ 162 if (m_current % 10 == 0)\n+ 163 {\n+ 164 // Carry the 1. Don't get too clever for this relatively rare\n+ 165 // case, just rewrite the entire number. Leave the $ in place\n+ 166 // though.\n+ 167 char *const data{std::data(m_buf)};\n+ 168 char *const end{string_traits::into_buf(\n+ 169 data + 1, data + std::size(m_buf), m_current)};\n+ 170 // (Subtract because we don't include the trailing zero.)\n+ 171 m_len = check_cast(end - data, \"placeholders counter\") - 1;\n+ 172 }\n+ 173 else\n+ 174 {\n+ 175 PQXX_LIKELY\n+ 176 // Shortcut for the common case: just increment that last digit.\n+ 177 ++m_buf[m_len - 1];\n+ 178 }\n+ 179 }\n+ 180\n+182 COUNTER count() const noexcept { return m_current; }\n+ 183\n+ 184private:\n+ 186 COUNTER m_current = 1;\n+ 187\n+ 189 COUNTER m_len = 2;\n+ 190\n+ 192\n+ 199 std::array::digits10 + 3> m_buf;\n+ 200};\n+ 201\n+ 202\n+ 204\n+219class PQXX_LIBEXPORT params\n+ 220{\n+ 221public:\n+222 params() = default;\n+ 223\n+225 template constexpr params(Args &&...args)\n+ 226 {\n+ 227 reserve(sizeof...(args));\n+ 228 append_pack(std::forward(args)...);\n+ 229 }\n+ 230\n+ 232\n+ 238 void reserve(std::size_t n) &;\n+ 239\n+ 240 // C++20: constexpr.\n+242 [[nodiscard]] auto size() const noexcept { return m_params.size(); }\n+ 243\n+ 244 // C++20: Use the vector's ssize() directly and go noexcept+constexpr.\n+ 246\n+251 [[nodiscard]] auto ssize() const { return pqxx::internal::ssize(m_params);\n+}\n+ 252\n+ 254 void append() &;\n+ 255\n+ 257\n+ 260 void append(zview) &;\n+ 261\n+ 263\n+ 266 void append(std::string const &) &;\n+ 267\n+ 269 void append(std::string &&) &;\n+ 270\n+ 272\n+ 275 void append(std::basic_string_view) &;\n+ 276\n+ 278\n+ 282 void append(std::basic_string const &) &;\n+ 283\n+ 284#if defined(PQXX_HAVE_CONCEPTS)\n+ 286\n+ 289 template void append(DATA const &data) &\n+ 290 {\n+ 291 append(\n+ 292 std::basic_string_view{std::data(data), std::size(data)});\n+ 293 }\n+ 294#endif // PQXX_HAVE_CONCEPTS\n+ 295\n+ 297 void append(std::basic_string &&) &;\n+ 298\n+ 300\n+ 303 void append(binarystring const &value) &;\n+ 304\n+ 306 template\n+307 void append(pqxx::internal::dynamic_params const &value) &\n+ 308 {\n+ 309 for (auto ¶m : value) append(value.access(param));\n+ 310 }\n+ 311\n+ 312 void append(params const &value) &;\n+ 313\n+ 314 void append(params &&value) &;\n+ 315\n+318 template void append(TYPE const &value) &\n+ 319 {\n+ 320 // TODO: Pool storage for multiple string conversions in one buffer?\n+ 321 if constexpr (nullness>::always_null)\n+ 322 {\n+ 323 ignore_unused(value);\n+ 324 m_params.emplace_back();\n+ 325 }\n+ 326 else if (is_null(value))\n+ 327 {\n+ 328 m_params.emplace_back();\n+ 329 }\n+ 330 else\n+ 331 {\n+ 332 m_params.emplace_back(entry{to_string(value)});\n+ 333 }\n+ 334 }\n+ 335\n+337 template void append_multi(RANGE const &range) &\n+ 338 {\n+ 339#if defined(PQXX_HAVE_CONCEPTS)\n+ 340 if constexpr (std::ranges::sized_range)\n+ 341 reserve(std::size(*this) + std::size(range));\n+ 342#endif\n+ 343 for (auto &value : range) append(value);\n+ 344 }\n+ 345\n+ 347\n+ 356 pqxx::internal::c_params make_c_params() const;\n+ 357\n+ 358private:\n+ 360 template\n+ 361 void append_pack(Arg &&arg, More &&...args)\n+ 362 {\n+ 363 this->append(std::forward(arg));\n+ 364 // Recurse for remaining args.\n+ 365 append_pack(std::forward(args)...);\n+ 366 }\n+ 367\n+ 369 constexpr void append_pack() noexcept {}\n+ 370\n+ 371 // The way we store a parameter depends on whether it's binary or text\n+ 372 // (most types are text), and whether we're responsible for storing the\n+ 373 // contents.\n+ 374 using entry = std::variant<\n+ 375 std::nullptr_t, zview, std::string, std::basic_string_view,\n+ 376 std::basic_string>;\n+ 377 std::vector m_params;\n+ 378\n+ 379 static constexpr std::string_view s_overflow{\n+ 380 \"Statement parameter length overflow.\"sv};\n+ 381};\n+ 382} // namespace pqxx\n+ 383#endif\n pqxx\n The home of all libpqxx classes, functions, templates, etc.\n Definition array.hxx:33\n-pqxx::connection\n-Connection to a database.\n-Definition connection.hxx:253\n-pqxx::dbtransaction\n-Abstract transaction base class: bracket transactions on the database.\n-Definition dbtransaction.hxx:54\n-pqxx::dbtransaction::dbtransaction\n-dbtransaction(connection &c, std::string_view tname, std::shared_ptr< std::\n-string > rollback_cmd)\n-Begin transaction.\n-Definition dbtransaction.hxx:63\n-pqxx::dbtransaction::dbtransaction\n-dbtransaction(connection &c)\n-Begin transaction.\n-Definition dbtransaction.hxx:57\n-pqxx::dbtransaction::dbtransaction\n-dbtransaction(connection &c, std::string_view tname)\n-Begin transaction.\n-Definition dbtransaction.hxx:59\n-pqxx::transaction_base\n-Interface definition (and common code) for \"transaction\" classes.\n-Definition transaction_base.hxx:88\n+pqxx::ignore_unused\n+constexpr void ignore_unused(T &&...) noexcept\n+Suppress compiler warning about an unused item.\n+Definition util.hxx:142\n+pqxx::to_string\n+std::string to_string(field const &value)\n+Convert a field to a string.\n+Definition result.cxx:549\n+pqxx::internal::ssize\n+auto ssize(T const &c)\n+Transitional: std::ssize(), or custom implementation if not available.\n+Definition util.hxx:453\n+pqxx::prepare\n+Definition params.hxx:27\n+pqxx::prepare::make_dynamic_params\n+constexpr auto make_dynamic_params(IT begin, IT end)\n+Pass a number of statement parameters only known at runtime.\n+Definition params.hxx:48\n+pqxx::range_error\n+Something is out of range, similar to std::out_of_range.\n+Definition except.hxx:326\n+pqxx::placeholders\n+Generate parameter placeholders for use in an SQL statement.\n+Definition params.hxx:126\n+pqxx::placeholders::max_params\n+static constexpr unsigned int max_params\n+Maximum number of parameters we support.\n+Definition params.hxx:129\n+pqxx::placeholders::count\n+COUNTER count() const noexcept\n+Return the current placeholder number. The initial placeholder is 1.\n+Definition params.hxx:182\n+pqxx::placeholders::get\n+std::string get() const\n+Read the current placeholder text, as a std::string.\n+Definition params.hxx:153\n+pqxx::placeholders::placeholders\n+placeholders()\n+Definition params.hxx:132\n+pqxx::placeholders::view\n+constexpr zview view() const &noexcept\n+Read an ephemeral version of the current placeholder text.\n+Definition params.hxx:142\n+pqxx::placeholders::next\n+void next() &\n+Move on to the next parameter.\n+Definition params.hxx:156\n+pqxx::params\n+Build a parameter list for a parameterised or prepared statement.\n+Definition params.hxx:220\n+pqxx::params::size\n+auto size() const noexcept\n+Get the number of parameters currently in this params.\n+Definition params.hxx:242\n+pqxx::params::append_multi\n+void append_multi(RANGE const &range) &\n+Append all elements of range as parameters.\n+Definition params.hxx:337\n+pqxx::params::append\n+void append(TYPE const &value) &\n+Definition params.hxx:318\n+pqxx::params::params\n+params()=default\n+pqxx::params::ssize\n+auto ssize() const\n+Get the number of parameters (signed).\n+Definition params.hxx:251\n+pqxx::params::append\n+void append(pqxx::internal::dynamic_params< IT, ACCESSOR > const &value) &\n+Append all parameters from value.\n+Definition params.hxx:307\n+pqxx::params::params\n+constexpr params(Args &&...args)\n+Pre-populate a params with args. Feel free to add more later.\n+Definition params.hxx:225\n+pqxx::range\n+A C++ equivalent to PostgreSQL's range types.\n+Definition range.hxx:234\n+pqxx::nullness\n+Traits describing a type's \"null value,\" if any.\n+Definition strconv.hxx:93\n+pqxx::string_traits::into_buf\n+static char * into_buf(char *begin, char *end, TYPE const &value)\n+Write value's string representation into buffer at begin.\n+pqxx::zview\n+Marker-type wrapper: zero-terminated std::string_view.\n+Definition zview.hxx:38\n * include\n * pqxx\n- * dbtransaction.hxx\n+ * params.hxx\n * Generated by [doxygen] 1.9.8\n"}]}, {"source1": "./usr/share/doc/libpqxx-doc/html/a00017_source.html", "source2": "./usr/share/doc/libpqxx-doc/html/a00017_source.html", "unified_diff": "@@ -1,15 +1,15 @@\n \n \n \n \n \n \n \n-libpqxx: prepared_statement.hxx Source File\n+libpqxx: range.hxx Source File\n \n \n \n \n \n \n \n@@ -60,24 +60,631 @@\n \n
\n
\n-
prepared_statement.hxx
\n+
range.hxx
\n
\n
\n-
1
\n-
2
\n-
3#include "params.hxx"
\n+
1#ifndef PQXX_H_RANGE
\n+
2#define PQXX_H_RANGE
\n+
3
\n+
4#if !defined(PQXX_HEADER_PRE)
\n+
5# error "Include libpqxx headers as <pqxx/header>, not <pqxx/header.hxx>."
\n+
6#endif
\n+
7
\n+
8#include <utility>
\n+
9#include <variant>
\n+
10
\n+
11#include "pqxx/internal/array-composite.hxx"
\n+
12#include "pqxx/internal/concat.hxx"
\n+
13
\n+
14namespace pqxx
\n+
15{
\n+
17
\n+
\n+\n+
24{
\n+
25 template<typename TYPE>
\n+
\n+
26 constexpr bool extends_down_to(TYPE const &) const noexcept
\n+
27 {
\n+
28 return true;
\n+
29 }
\n+
\n+
30 template<typename TYPE>
\n+
\n+
31 constexpr bool extends_up_to(TYPE const &) const noexcept
\n+
32 {
\n+
33 return true;
\n+
34 }
\n+
\n+
35};
\n+
\n+
36
\n+
37
\n+
39
\n+
\n+
42template<typename TYPE> class inclusive_bound
\n+
43{
\n+
44 // (Putting private section first to work around bug in gcc < 10: see #665.)
\n+
45private:
\n+
46 TYPE m_value;
\n+
47
\n+
48public:
\n+
49 inclusive_bound() = delete;
\n+
\n+
50 constexpr explicit inclusive_bound(TYPE const &value) : m_value{value}
\n+
51 {
\n+
52 if (is_null(value))
\n+
53 throw argument_error{"Got null value as an inclusive range bound."};
\n+
54 }
\n+
\n+
55
\n+
56 [[nodiscard]] constexpr TYPE const &get() const &noexcept { return m_value; }
\n+
57
\n+
\n+
59 [[nodiscard]] constexpr bool extends_down_to(TYPE const &value) const
\n+
60 noexcept(noexcept(value < m_value))
\n+
61 {
\n+
62 return not(value < m_value);
\n+
63 }
\n+
\n+
64
\n+
\n+
66 [[nodiscard]] constexpr bool extends_up_to(TYPE const &value) const
\n+
67 noexcept(noexcept(value < m_value))
\n+
68 {
\n+
69 return not(m_value < value);
\n+
70 }
\n+
\n+
71};
\n+
\n+
72
\n+
73
\n+
75
\n+
\n+
78template<typename TYPE> class exclusive_bound
\n+
79{
\n+
80 // (Putting private section first to work around bug in gcc < 10: see #665.)
\n+
81private:
\n+
82 TYPE m_value;
\n+
83
\n+
84public:
\n+
85 exclusive_bound() = delete;
\n+
\n+
86 constexpr explicit exclusive_bound(TYPE const &value) : m_value{value}
\n+
87 {
\n+
88 if (is_null(value))
\n+
89 throw argument_error{"Got null value as an exclusive range bound."};
\n+
90 }
\n+
\n+
91
\n+
92 [[nodiscard]] constexpr TYPE const &get() const &noexcept { return m_value; }
\n+
93
\n+
\n+
95 [[nodiscard]] constexpr bool extends_down_to(TYPE const &value) const
\n+
96 noexcept(noexcept(m_value < value))
\n+
97 {
\n+
98 return m_value < value;
\n+
99 }
\n+
\n+
100
\n+
\n+
102 [[nodiscard]] constexpr bool extends_up_to(TYPE const &value) const
\n+
103 noexcept(noexcept(value < m_value))
\n+
104 {
\n+
105 return value < m_value;
\n+
106 }
\n+
\n+
107};
\n+
\n+
108
\n+
109
\n+
111
\n+
\n+
114template<typename TYPE> class range_bound
\n+
115{
\n+
116 // (Putting private section first to work around bug in gcc < 10: see #665.)
\n+
117private:
\n+
118 std::variant<no_bound, inclusive_bound<TYPE>, exclusive_bound<TYPE>> m_bound;
\n+
119
\n+
120public:
\n+
121 range_bound() = delete;
\n+
122 constexpr range_bound(no_bound) noexcept : m_bound{} {}
\n+
123
\n+
\n+
124 constexpr range_bound(inclusive_bound<TYPE> const &bound) noexcept(
\n+
125 noexcept(inclusive_bound<TYPE>{bound})) :
\n+
126 m_bound{bound}
\n+
127 {}
\n+
\n+
128
\n+
\n+
129 constexpr range_bound(exclusive_bound<TYPE> const &bound) noexcept(
\n+
130 noexcept(exclusive_bound{bound})) :
\n+
131 m_bound{bound}
\n+
132 {}
\n+
\n+
133
\n+
134 constexpr range_bound(range_bound const &) noexcept(
\n+
135 noexcept(inclusive_bound<TYPE>{
\n+
136 std::declval<inclusive_bound<TYPE> const &>()})
\n+
137 and noexcept(exclusive_bound<TYPE>{
\n+
138 std::declval<exclusive_bound<TYPE> const &>()})) = default;
\n+
139
\n+
140 constexpr range_bound(range_bound &&) = default;
\n+
141
\n+
\n+
142 constexpr bool operator==(range_bound const &rhs) const
\n+
143 noexcept(noexcept(*this->value() == *rhs.value()))
\n+
144 {
\n+
145 if (this->is_limited())
\n+
146 return (
\n+
147 rhs.is_limited() and (this->is_inclusive() == rhs.is_inclusive()) and
\n+
148 (*this->value() == *rhs.value()));
\n+
149 else
\n+
150 return not rhs.is_limited();
\n+
151 }
\n+
\n+
152
\n+
\n+
153 constexpr bool operator!=(range_bound const &rhs) const
\n+
154 noexcept(noexcept(*this == rhs))
\n+
155 {
\n+
156 return not(*this == rhs);
\n+
157 }
\n+
\n+
158 range_bound &operator=(range_bound const &) = default;
\n+\n+
160
\n+
\n+
162 constexpr bool is_limited() const noexcept
\n+
163 {
\n+
164 return not std::holds_alternative<no_bound>(m_bound);
\n+
165 }
\n+
\n+
166
\n+
\n+
168 constexpr bool is_inclusive() const noexcept
\n+
169 {
\n+
170 return std::holds_alternative<inclusive_bound<TYPE>>(m_bound);
\n+
171 }
\n+
\n+
172
\n+
\n+
174 constexpr bool is_exclusive() const noexcept
\n+
175 {
\n+
176 return std::holds_alternative<exclusive_bound<TYPE>>(m_bound);
\n+
177 }
\n+
\n+
178
\n+
\n+
180 constexpr bool extends_down_to(TYPE const &value) const
\n+
181 {
\n+
182 return std::visit(
\n+
183 [&value](auto const &bound) noexcept(noexcept(bound.extends_down_to(
\n+
184 value))) { return bound.extends_down_to(value); },
\n+
185 m_bound);
\n+
186 }
\n+
\n+
187
\n+
\n+
189 constexpr bool extends_up_to(TYPE const &value) const
\n+
190 {
\n+
191 return std::visit(
\n+
192 [&value](auto const &bound) noexcept(noexcept(
\n+
193 bound.extends_up_to(value))) { return bound.extends_up_to(value); },
\n+
194 m_bound);
\n+
195 }
\n+
\n+
196
\n+
\n+
198 [[nodiscard]] constexpr TYPE const *value() const &noexcept
\n+
199 {
\n+
200 return std::visit(
\n+
201 [](auto const &bound) noexcept {
\n+
202 using bound_t = std::decay_t<decltype(bound)>;
\n+
203 if constexpr (std::is_same_v<bound_t, no_bound>)
\n+
204 return static_cast<TYPE const *>(nullptr);
\n+
205 else
\n+
206 return &bound.get();
\n+
207 },
\n+
208 m_bound);
\n+
209 }
\n+
\n+
210};
\n+
\n+
211
\n+
212
\n+
213// C++20: Concepts for comparisons, construction, etc.
\n+
215
\n+
\n+
233template<typename TYPE> class range
\n+
234{
\n+
235 // (Putting private section first to work around bug in gcc < 10: see #665.)
\n+
236private:
\n+
237 range_bound<TYPE> m_lower, m_upper;
\n+
238
\n+
239public:
\n+
241
\n+
\n+
245 constexpr range(range_bound<TYPE> lower, range_bound<TYPE> upper) :
\n+
246 m_lower{lower}, m_upper{upper}
\n+
247 {
\n+
248 if (
\n+
249 lower.is_limited() and upper.is_limited() and
\n+
250 (*upper.value() < *lower.value()))
\n+
251 throw range_error{internal::concat(
\n+
252 "Range's lower bound (", *lower.value(),
\n+
253 ") is greater than its upper bound (", *upper.value(), ").")};
\n+
254 }
\n+
\n+
255
\n+
257
\n+
\n+
260 constexpr range() noexcept(noexcept(exclusive_bound<TYPE>{TYPE{}})) :
\n+
261 m_lower{exclusive_bound<TYPE>{TYPE{}}},
\n+
262 m_upper{exclusive_bound<TYPE>{TYPE{}}}
\n+
263 {}
\n+
\n+
264
\n+
\n+
265 constexpr bool operator==(range const &rhs) const
\n+
266 noexcept(noexcept(this->lower_bound() == rhs.lower_bound()) and noexcept(
\n+
267 this->upper_bound() == rhs.upper_bound()) and noexcept(this->empty()))
\n+
268 {
\n+
269 return (this->lower_bound() == rhs.lower_bound() and
\n+
270 this->upper_bound() == rhs.upper_bound()) or
\n+
271 (this->empty() and rhs.empty());
\n+
272 }
\n+
\n+
273
\n+
\n+
274 constexpr bool operator!=(range const &rhs) const
\n+
275 noexcept(noexcept(*this == rhs))
\n+
276 {
\n+
277 return not(*this == rhs);
\n+
278 }
\n+
\n+
279
\n+
280 range(range const &) = default;
\n+
281 range(range &&) = default;
\n+
282 range &operator=(range const &) = default;
\n+
283 range &operator=(range &&) = default;
\n+
284
\n+
286
\n+
\n+
294 constexpr bool empty() const
\n+
295 noexcept(noexcept(m_lower.is_exclusive()) and noexcept(
\n+
296 m_lower.is_limited()) and noexcept(*m_lower.value() < *m_upper.value()))
\n+
297 {
\n+
298 return (m_lower.is_exclusive() or m_upper.is_exclusive()) and
\n+
299 m_lower.is_limited() and m_upper.is_limited() and
\n+
300 not(*m_lower.value() < *m_upper.value());
\n+
301 }
\n+
\n+
302
\n+
\n+
304 constexpr bool contains(TYPE value) const noexcept(noexcept(
\n+
305 m_lower.extends_down_to(value)) and noexcept(m_upper.extends_up_to(value)))
\n+
306 {
\n+
307 return m_lower.extends_down_to(value) and m_upper.extends_up_to(value);
\n+
308 }
\n+
\n+
309
\n+
311
\n+
\n+
314 constexpr bool contains(range<TYPE> const &other) const
\n+
315 noexcept(noexcept((*this & other) == other))
\n+
316 {
\n+
317 return (*this & other) == other;
\n+
318 }
\n+
\n+
319
\n+
320 [[nodiscard]] constexpr range_bound<TYPE> const &
\n+
\n+
321 lower_bound() const &noexcept
\n+
322 {
\n+
323 return m_lower;
\n+
324 }
\n+
\n+
325 [[nodiscard]] constexpr range_bound<TYPE> const &
\n+
\n+
326 upper_bound() const &noexcept
\n+
327 {
\n+
328 return m_upper;
\n+
329 }
\n+
\n+
330
\n+
332
\n+
\n+
334 constexpr range operator&(range const &other) const
\n+
335 {
\n+\n+
337 if (not this->lower_bound().is_limited())
\n+
338 lower = other.lower_bound();
\n+
339 else if (not other.lower_bound().is_limited())
\n+
340 lower = this->lower_bound();
\n+
341 else if (*this->lower_bound().value() < *other.lower_bound().value())
\n+
342 lower = other.lower_bound();
\n+
343 else if (*other.lower_bound().value() < *this->lower_bound().value())
\n+
344 lower = this->lower_bound();
\n+
345 else if (this->lower_bound().is_exclusive())
\n+
346 lower = this->lower_bound();
\n+
347 else
\n+
348 lower = other.lower_bound();
\n+
349
\n+\n+
351 if (not this->upper_bound().is_limited())
\n+
352 upper = other.upper_bound();
\n+
353 else if (not other.upper_bound().is_limited())
\n+
354 upper = this->upper_bound();
\n+
355 else if (*other.upper_bound().value() < *this->upper_bound().value())
\n+
356 upper = other.upper_bound();
\n+
357 else if (*this->upper_bound().value() < *other.upper_bound().value())
\n+
358 upper = this->upper_bound();
\n+
359 else if (this->upper_bound().is_exclusive())
\n+
360 upper = this->upper_bound();
\n+
361 else
\n+
362 upper = other.upper_bound();
\n+
363
\n+
364 if (
\n+
365 lower.is_limited() and upper.is_limited() and
\n+
366 (*upper.value() < *lower.value()))
\n+
367 return {};
\n+
368 else
\n+
369 return {lower, upper};
\n+
370 }
\n+
\n+
371
\n+
\n+
373 template<typename DEST> operator range<DEST>() const
\n+
374 {
\n+
375 range_bound<DEST> lower{no_bound{}}, upper{no_bound{}};
\n+
376 if (lower_bound().is_inclusive())
\n+
377 lower = inclusive_bound<DEST>{*lower_bound().value()};
\n+
378 else if (lower_bound().is_exclusive())
\n+
379 lower = exclusive_bound<DEST>{*lower_bound().value()};
\n+
380
\n+
381 if (upper_bound().is_inclusive())
\n+
382 upper = inclusive_bound<DEST>{*upper_bound().value()};
\n+
383 else if (upper_bound().is_exclusive())
\n+
384 upper = exclusive_bound<DEST>{*upper_bound().value()};
\n+
385
\n+
386 return {lower, upper};
\n+
387 }
\n+
\n+
388};
\n+
\n+
389
\n+
390
\n+
392
\n+
\n+
395template<typename TYPE> struct string_traits<range<TYPE>>
\n+
396{
\n+
397 [[nodiscard]] static inline zview
\n+
\n+
398 to_buf(char *begin, char *end, range<TYPE> const &value)
\n+
399 {
\n+
400 return generic_to_buf(begin, end, value);
\n+
401 }
\n+
\n+
402
\n+
403 static inline char *
\n+
\n+
404 into_buf(char *begin, char *end, range<TYPE> const &value)
\n+
405 {
\n+
406 if (value.empty())
\n+
407 {
\n+
408 if ((end - begin) <= internal::ssize(s_empty))
\n+
409 throw conversion_overrun{s_overrun.c_str()};
\n+
410 char *here = begin + s_empty.copy(begin, std::size(s_empty));
\n+
411 *here++ = '\\0';
\n+
412 return here;
\n+
413 }
\n+
414 else
\n+
415 {
\n+
416 if (end - begin < 4)
\n+
417 throw conversion_overrun{s_overrun.c_str()};
\n+
418 char *here = begin;
\n+
419 *here++ =
\n+
420 (static_cast<char>(value.lower_bound().is_inclusive() ? '[' : '('));
\n+
421 TYPE const *lower{value.lower_bound().value()};
\n+
422 // Convert bound (but go back to overwrite that trailing zero).
\n+
423 if (lower != nullptr)
\n+
424 here = string_traits<TYPE>::into_buf(here, end, *lower) - 1;
\n+
425 *here++ = ',';
\n+
426 TYPE const *upper{value.upper_bound().value()};
\n+
427 // Convert bound (but go back to overwrite that trailing zero).
\n+
428 if (upper != nullptr)
\n+
429 here = string_traits<TYPE>::into_buf(here, end, *upper) - 1;
\n+
430 if ((end - here) < 2)
\n+
431 throw conversion_overrun{s_overrun.c_str()};
\n+
432 *here++ =
\n+
433 static_cast<char>(value.upper_bound().is_inclusive() ? ']' : ')');
\n+
434 *here++ = '\\0';
\n+
435 return here;
\n+
436 }
\n+
437 }
\n+
\n+
438
\n+
\n+
439 [[nodiscard]] static inline range<TYPE> from_string(std::string_view text)
\n+
440 {
\n+
441 if (std::size(text) < 3)
\n+
442 throw pqxx::conversion_error{err_bad_input(text)};
\n+
443 bool left_inc{false};
\n+
444 switch (text[0])
\n+
445 {
\n+
446 case '[': left_inc = true; break;
\n+
447
\n+
448 case '(': break;
\n+
449
\n+
450 case 'e':
\n+
451 case 'E':
\n+
452 if (
\n+
453 (std::size(text) != std::size(s_empty)) or
\n+
454 (text[1] != 'm' and text[1] != 'M') or
\n+
455 (text[2] != 'p' and text[2] != 'P') or
\n+
456 (text[3] != 't' and text[3] != 'T') or
\n+
457 (text[4] != 'y' and text[4] != 'Y'))
\n+
458 throw pqxx::conversion_error{err_bad_input(text)};
\n+
459 return {};
\n+
460 break;
\n+
461
\n+
462 default: throw pqxx::conversion_error{err_bad_input(text)};
\n+
463 }
\n+
464
\n+
465 // The field parser uses this to track which field it's parsing, and
\n+
466 // when not to expect a field separator.
\n+
467 std::size_t index{0};
\n+
468 // The last field we expect to see.
\n+
469 static constexpr std::size_t last{1};
\n+
470 // Current parsing position. We skip the opening parenthesis or bracket.
\n+
471 std::size_t pos{1};
\n+
472 // The string may leave out either bound to indicate that it's unlimited.
\n+
473 std::optional<TYPE> lower, upper;
\n+
474 // We reuse the same field parser we use for composite values and arrays.
\n+
475 auto const field_parser{
\n+
476 pqxx::internal::specialize_parse_composite_field<std::optional<TYPE>>(
\n+
477 pqxx::internal::encoding_group::UTF8)};
\n+
478 field_parser(index, text, pos, lower, last);
\n+
479 field_parser(index, text, pos, upper, last);
\n+
480
\n+
481 // We need one more character: the closing parenthesis or bracket.
\n+
482 if (pos != std::size(text))
\n+
483 throw pqxx::conversion_error{err_bad_input(text)};
\n+
484 char const closing{text[pos - 1]};
\n+
485 if (closing != ')' and closing != ']')
\n+
486 throw pqxx::conversion_error{err_bad_input(text)};
\n+
487 bool const right_inc{closing == ']'};
\n+
488
\n+
489 range_bound<TYPE> lower_bound{no_bound{}}, upper_bound{no_bound{}};
\n+
490 if (lower)
\n+
491 {
\n+
492 if (left_inc)
\n+
493 lower_bound = inclusive_bound{*lower};
\n+
494 else
\n+
495 lower_bound = exclusive_bound{*lower};
\n+
496 }
\n+
497 if (upper)
\n+
498 {
\n+
499 if (right_inc)
\n+
500 upper_bound = inclusive_bound{*upper};
\n+
501 else
\n+
502 upper_bound = exclusive_bound{*upper};
\n+
503 }
\n+
504
\n+
505 return {lower_bound, upper_bound};
\n+
506 }
\n+
\n+
507
\n+
508 [[nodiscard]] static inline constexpr std::size_t
\n+
\n+
509 size_buffer(range<TYPE> const &value) noexcept
\n+
510 {
\n+
511 TYPE const *lower{value.lower_bound().value()},
\n+
512 *upper{value.upper_bound().value()};
\n+
513 std::size_t const lsz{
\n+
514 lower == nullptr ? 0 : string_traits<TYPE>::size_buffer(*lower) - 1},
\n+
515 usz{upper == nullptr ? 0 : string_traits<TYPE>::size_buffer(*upper) - 1};
\n+
516
\n+
517 if (value.empty())
\n+
518 return std::size(s_empty) + 1;
\n+
519 else
\n+
520 return 1 + lsz + 1 + usz + 2;
\n+
521 }
\n+
\n+
522
\n+
523private:
\n+
524 static constexpr zview s_empty{"empty"_zv};
\n+
525 static constexpr auto s_overrun{"Not enough space in buffer for range."_zv};
\n+
526
\n+
528 static std::string err_bad_input(std::string_view text)
\n+
529 {
\n+
530 return internal::concat("Invalid range input: '", text, "'");
\n+
531 }
\n+
532};
\n+
\n+
533
\n+
534
\n+
\n+
536template<typename TYPE> struct nullness<range<TYPE>> : no_null<range<TYPE>>
\n+
537{};
\n+
\n+
538} // namespace pqxx
\n+
539#endif
\n+
The home of all libpqxx classes, functions, templates, etc.
Definition array.hxx:33
\n+\n+
Invalid argument passed to libpqxx, similar to std::invalid_argument.
Definition except.hxx:266
\n+
Value conversion failed, e.g. when converting "Hello" to int.
Definition except.hxx:283
\n+
Could not convert value to string: not enough buffer space.
Definition except.hxx:313
\n+
Something is out of range, similar to std::out_of_range.
Definition except.hxx:326
\n+
An unlimited boundary value to a pqxx::range.
Definition range.hxx:24
\n+
constexpr bool extends_down_to(TYPE const &) const noexcept
Definition range.hxx:26
\n+
constexpr bool extends_up_to(TYPE const &) const noexcept
Definition range.hxx:31
\n+
An inclusive boundary value to a pqxx::range.
Definition range.hxx:43
\n+
constexpr inclusive_bound(TYPE const &value)
Definition range.hxx:50
\n+
constexpr bool extends_down_to(TYPE const &value) const noexcept(noexcept(value< m_value))
Would this bound, as a lower bound, include value?
Definition range.hxx:59
\n+\n+
constexpr TYPE const & get() const &noexcept
Definition range.hxx:56
\n+
constexpr bool extends_up_to(TYPE const &value) const noexcept(noexcept(value< m_value))
Would this bound, as an upper bound, include value?
Definition range.hxx:66
\n+
An exclusive boundary value to a pqxx::range.
Definition range.hxx:79
\n+
constexpr bool extends_up_to(TYPE const &value) const noexcept(noexcept(value< m_value))
Would this bound, as an upper bound, include value?
Definition range.hxx:102
\n+\n+
constexpr exclusive_bound(TYPE const &value)
Definition range.hxx:86
\n+
constexpr TYPE const & get() const &noexcept
Definition range.hxx:92
\n+
constexpr bool extends_down_to(TYPE const &value) const noexcept(noexcept(m_value< value))
Would this bound, as a lower bound, include value?
Definition range.hxx:95
\n+
A range boundary value.
Definition range.hxx:115
\n+
constexpr bool extends_up_to(TYPE const &value) const
Would this bound, as an upper bound, include value?
Definition range.hxx:189
\n+
constexpr range_bound(range_bound const &) noexcept(noexcept(inclusive_bound< TYPE >{ std::declval< inclusive_bound< TYPE > const & >()}) and noexcept(exclusive_bound< TYPE >{ std::declval< exclusive_bound< TYPE > const & >()}))=default
\n+
constexpr bool is_exclusive() const noexcept
Is this boundary an exclusive one?
Definition range.hxx:174
\n+
constexpr range_bound(inclusive_bound< TYPE > const &bound) noexcept(noexcept(inclusive_bound< TYPE >{bound}))
Definition range.hxx:124
\n+
constexpr bool is_limited() const noexcept
Is this a finite bound?
Definition range.hxx:162
\n+
constexpr TYPE const * value() const &noexcept
Return bound value, or nullptr if it's not limited.
Definition range.hxx:198
\n+
constexpr bool operator!=(range_bound const &rhs) const noexcept(noexcept(*this==rhs))
Definition range.hxx:153
\n+
constexpr bool extends_down_to(TYPE const &value) const
Would this bound, as a lower bound, include value?
Definition range.hxx:180
\n+
range_bound()=delete
\n+
constexpr range_bound(no_bound) noexcept
Definition range.hxx:122
\n+
range_bound & operator=(range_bound const &)=default
\n+
constexpr bool operator==(range_bound const &rhs) const noexcept(noexcept(*this->value()== *rhs.value()))
Definition range.hxx:142
\n+
constexpr range_bound(exclusive_bound< TYPE > const &bound) noexcept(noexcept(exclusive_bound{bound}))
Definition range.hxx:129
\n+
constexpr bool is_inclusive() const noexcept
Is this boundary an inclusive one?
Definition range.hxx:168
\n+
range_bound & operator=(range_bound &&)=default
\n+
constexpr range_bound(range_bound &&)=default
\n+
A C++ equivalent to PostgreSQL's range types.
Definition range.hxx:234
\n+
constexpr range operator&(range const &other) const
Intersection of two ranges.
Definition range.hxx:334
\n+
constexpr bool operator==(range const &rhs) const noexcept(noexcept(this->lower_bound()==rhs.lower_bound()) and noexcept(this->upper_bound()==rhs.upper_bound()) and noexcept(this->empty()))
Definition range.hxx:265
\n+
constexpr bool contains(TYPE value) const noexcept(noexcept(m_lower.extends_down_to(value)) and noexcept(m_upper.extends_up_to(value)))
Does this range encompass value?
Definition range.hxx:304
\n+
constexpr bool contains(range< TYPE > const &other) const noexcept(noexcept((*this &other)==other))
Does this range encompass all of other?
Definition range.hxx:314
\n+
constexpr bool operator!=(range const &rhs) const noexcept(noexcept(*this==rhs))
Definition range.hxx:274
\n+
range(range &&)=default
\n+
range(range const &)=default
\n+
range & operator=(range &&)=default
\n+
range & operator=(range const &)=default
\n+
constexpr range(range_bound< TYPE > lower, range_bound< TYPE > upper)
Create a range.
Definition range.hxx:245
\n+
constexpr range_bound< TYPE > const & upper_bound() const &noexcept
Definition range.hxx:326
\n+
constexpr bool empty() const noexcept(noexcept(m_lower.is_exclusive()) and noexcept(m_lower.is_limited()) and noexcept(*m_lower.value()< *m_upper.value()))
Is this range clearly empty?
Definition range.hxx:294
\n+
constexpr range_bound< TYPE > const & lower_bound() const &noexcept
Definition range.hxx:321
\n+
constexpr range() noexcept(noexcept(exclusive_bound< TYPE >{TYPE{}}))
Create an empty range.
Definition range.hxx:260
\n+
static constexpr std::size_t size_buffer(range< TYPE > const &value) noexcept
Definition range.hxx:509
\n+
static char * into_buf(char *begin, char *end, range< TYPE > const &value)
Definition range.hxx:404
\n+
static zview to_buf(char *begin, char *end, range< TYPE > const &value)
Definition range.hxx:398
\n+
static range< TYPE > from_string(std::string_view text)
Definition range.hxx:439
\n+
Traits describing a type's "null value," if any.
Definition strconv.hxx:93
\n+
Nullness traits describing a type which does not have a null value.
Definition strconv.hxx:115
\n+
Traits class for use in string conversions.
Definition strconv.hxx:155
\n+
Marker-type wrapper: zero-terminated std::string_view.
Definition zview.hxx:38
\n
\n
\n \n
\n \n
\n \n \n", "details": [{"source1": "html2text {}", "source2": "html2text {}", "unified_diff": "@@ -1,15 +1,695 @@\n \n \n \n \n \n libpqxx\u00a07.8.1\n \n-prepared_statement.hxx\n- 1\n- 2\n- 3#include \"params.hxx\"\n+range.hxx\n+ 1#ifndef PQXX_H_RANGE\n+ 2#define PQXX_H_RANGE\n+ 3\n+ 4#if !defined(PQXX_HEADER_PRE)\n+ 5# error \"Include libpqxx headers as , not .\"\n+ 6#endif\n+ 7\n+ 8#include \n+ 9#include \n+ 10\n+ 11#include \"pqxx/internal/array-composite.hxx\"\n+ 12#include \"pqxx/internal/concat.hxx\"\n+ 13\n+ 14namespace pqxx\n+ 15{\n+ 17\n+23struct no_bound\n+ 24{\n+ 25 template\n+26 constexpr bool extends_down_to(TYPE const &) const noexcept\n+ 27 {\n+ 28 return true;\n+ 29 }\n+ 30 template\n+31 constexpr bool extends_up_to(TYPE const &) const noexcept\n+ 32 {\n+ 33 return true;\n+ 34 }\n+ 35};\n+ 36\n+ 37\n+ 39\n+42template class inclusive_bound\n+ 43{\n+ 44 // (Putting private section first to work around bug in gcc < 10: see\n+#665.)\n+ 45private:\n+ 46 TYPE m_value;\n+ 47\n+ 48public:\n+49 inclusive_bound() = delete;\n+50 constexpr explicit inclusive_bound(TYPE const &value) : m_value{value}\n+ 51 {\n+ 52 if (is_null(value))\n+ 53 throw argument_error{\"Got null value as an inclusive range bound.\"};\n+ 54 }\n+ 55\n+56 [[nodiscard]] constexpr TYPE const &get() const &noexcept { return m_value;\n+}\n+ 57\n+59 [[nodiscard]] constexpr bool extends_down_to(TYPE const &value) const\n+ 60 noexcept(noexcept(value < m_value))\n+ 61 {\n+ 62 return not(value < m_value);\n+ 63 }\n+ 64\n+66 [[nodiscard]] constexpr bool extends_up_to(TYPE const &value) const\n+ 67 noexcept(noexcept(value < m_value))\n+ 68 {\n+ 69 return not(m_value < value);\n+ 70 }\n+ 71};\n+ 72\n+ 73\n+ 75\n+78template class exclusive_bound\n+ 79{\n+ 80 // (Putting private section first to work around bug in gcc < 10: see\n+#665.)\n+ 81private:\n+ 82 TYPE m_value;\n+ 83\n+ 84public:\n+85 exclusive_bound() = delete;\n+86 constexpr explicit exclusive_bound(TYPE const &value) : m_value{value}\n+ 87 {\n+ 88 if (is_null(value))\n+ 89 throw argument_error{\"Got null value as an exclusive range bound.\"};\n+ 90 }\n+ 91\n+92 [[nodiscard]] constexpr TYPE const &get() const &noexcept { return m_value;\n+}\n+ 93\n+95 [[nodiscard]] constexpr bool extends_down_to(TYPE const &value) const\n+ 96 noexcept(noexcept(m_value < value))\n+ 97 {\n+ 98 return m_value < value;\n+ 99 }\n+ 100\n+102 [[nodiscard]] constexpr bool extends_up_to(TYPE const &value) const\n+ 103 noexcept(noexcept(value < m_value))\n+ 104 {\n+ 105 return value < m_value;\n+ 106 }\n+ 107};\n+ 108\n+ 109\n+ 111\n+114template class range_bound\n+ 115{\n+ 116 // (Putting private section first to work around bug in gcc < 10: see\n+#665.)\n+ 117private:\n+ 118 std::variant, exclusive_bound>\n+m_bound;\n+ 119\n+ 120public:\n+121 range_bound() = delete;\n+122 constexpr range_bound(no_bound) noexcept : m_bound{} {}\n+ 123\n+124 constexpr range_bound(inclusive_bound const &bound) noexcept(\n+ 125 noexcept(inclusive_bound{bound})) :\n+ 126 m_bound{bound}\n+ 127 {}\n+ 128\n+129 constexpr range_bound(exclusive_bound const &bound) noexcept(\n+ 130 noexcept(exclusive_bound{bound})) :\n+ 131 m_bound{bound}\n+ 132 {}\n+ 133\n+134 constexpr range_bound(range_bound const &) noexcept(\n+ 135 noexcept(inclusive_bound{\n+ 136 std::declval const &>()})\n+ 137 and noexcept(exclusive_bound{\n+ 138 std::declval const &>()})) = default;\n+ 139\n+140 constexpr range_bound(range_bound &&) = default;\n+ 141\n+142 constexpr bool operator==(range_bound const &rhs) const\n+ 143 noexcept(noexcept(*this->value() == *rhs.value()))\n+ 144 {\n+ 145 if (this->is_limited())\n+ 146 return (\n+ 147 rhs.is_limited() and (this->is_inclusive() == rhs.is_inclusive()) and\n+ 148 (*this->value() == *rhs.value()));\n+ 149 else\n+ 150 return not rhs.is_limited();\n+ 151 }\n+ 152\n+153 constexpr bool operator!=(range_bound const &rhs) const\n+ 154 noexcept(noexcept(*this == rhs))\n+ 155 {\n+ 156 return not(*this == rhs);\n+ 157 }\n+158 range_bound &operator=(range_bound const &) = default;\n+159 range_bound &operator=(range_bound &&) = default;\n+ 160\n+162 constexpr bool is_limited() const noexcept\n+ 163 {\n+ 164 return not std::holds_alternative(m_bound);\n+ 165 }\n+ 166\n+168 constexpr bool is_inclusive() const noexcept\n+ 169 {\n+ 170 return std::holds_alternative>(m_bound);\n+ 171 }\n+ 172\n+174 constexpr bool is_exclusive() const noexcept\n+ 175 {\n+ 176 return std::holds_alternative>(m_bound);\n+ 177 }\n+ 178\n+180 constexpr bool extends_down_to(TYPE const &value) const\n+ 181 {\n+ 182 return std::visit(\n+ 183 [&value](auto const &bound) noexcept(noexcept(bound.extends_down_to(\n+ 184 value))) { return bound.extends_down_to(value); },\n+ 185 m_bound);\n+ 186 }\n+ 187\n+189 constexpr bool extends_up_to(TYPE const &value) const\n+ 190 {\n+ 191 return std::visit(\n+ 192 [&value](auto const &bound) noexcept(noexcept(\n+ 193 bound.extends_up_to(value))) { return bound.extends_up_to(value); },\n+ 194 m_bound);\n+ 195 }\n+ 196\n+198 [[nodiscard]] constexpr TYPE const *value() const &noexcept\n+ 199 {\n+ 200 return std::visit(\n+ 201 [](auto const &bound) noexcept {\n+ 202 using bound_t = std::decay_t;\n+ 203 if constexpr (std::is_same_v)\n+ 204 return static_cast(nullptr);\n+ 205 else\n+ 206 return &bound.get();\n+ 207 },\n+ 208 m_bound);\n+ 209 }\n+ 210};\n+ 211\n+ 212\n+ 213// C++20: Concepts for comparisons, construction, etc.\n+ 215\n+233template class range\n+ 234{\n+ 235 // (Putting private section first to work around bug in gcc < 10: see\n+#665.)\n+ 236private:\n+ 237 range_bound m_lower, m_upper;\n+ 238\n+ 239public:\n+ 241\n+245 constexpr range(range_bound lower, range_bound upper) :\n+ 246 m_lower{lower}, m_upper{upper}\n+ 247 {\n+ 248 if (\n+ 249 lower.is_limited() and upper.is_limited() and\n+ 250 (*upper.value() < *lower.value()))\n+ 251 throw range_error{internal::concat(\n+ 252 \"Range's lower bound (\", *lower.value(),\n+ 253 \") is greater than its upper bound (\", *upper.value(), \").\")};\n+ 254 }\n+ 255\n+ 257\n+260 constexpr range() noexcept(noexcept(exclusive_bound{TYPE{}})) :\n+ 261 m_lower{exclusive_bound{TYPE{}}},\n+ 262 m_upper{exclusive_bound{TYPE{}}}\n+ 263 {}\n+ 264\n+265 constexpr bool operator==(range const &rhs) const\n+ 266 noexcept(noexcept(this->lower_bound() == rhs.lower_bound()) and noexcept(\n+ 267 this->upper_bound() == rhs.upper_bound()) and noexcept(this->empty()))\n+ 268 {\n+ 269 return (this->lower_bound() == rhs.lower_bound() and\n+ 270 this->upper_bound() == rhs.upper_bound()) or\n+ 271 (this->empty() and rhs.empty());\n+ 272 }\n+ 273\n+274 constexpr bool operator!=(range const &rhs) const\n+ 275 noexcept(noexcept(*this == rhs))\n+ 276 {\n+ 277 return not(*this == rhs);\n+ 278 }\n+ 279\n+280 range(range const &) = default;\n+281 range(range &&) = default;\n+282 range &operator=(range const &) = default;\n+283 range &operator=(range &&) = default;\n+ 284\n+ 286\n+294 constexpr bool empty() const\n+ 295 noexcept(noexcept(m_lower.is_exclusive()) and noexcept(\n+ 296 m_lower.is_limited()) and noexcept(*m_lower.value() < *m_upper.value()))\n+ 297 {\n+ 298 return (m_lower.is_exclusive() or m_upper.is_exclusive()) and\n+ 299 m_lower.is_limited() and m_upper.is_limited() and\n+ 300 not(*m_lower.value() < *m_upper.value());\n+ 301 }\n+ 302\n+304 constexpr bool contains(TYPE value) const noexcept(noexcept(\n+ 305 m_lower.extends_down_to(value)) and noexcept(m_upper.extends_up_to\n+(value)))\n+ 306 {\n+ 307 return m_lower.extends_down_to(value) and m_upper.extends_up_to(value);\n+ 308 }\n+ 309\n+ 311\n+314 constexpr bool contains(range const &other) const\n+ 315 noexcept(noexcept((*this & other) == other))\n+ 316 {\n+ 317 return (*this & other) == other;\n+ 318 }\n+ 319\n+ 320 [[nodiscard]] constexpr range_bound const &\n+321 lower_bound() const &noexcept\n+ 322 {\n+ 323 return m_lower;\n+ 324 }\n+ 325 [[nodiscard]] constexpr range_bound const &\n+326 upper_bound() const &noexcept\n+ 327 {\n+ 328 return m_upper;\n+ 329 }\n+ 330\n+ 332\n+334 constexpr range operator&(range const &other) const\n+ 335 {\n+ 336 range_bound lower{no_bound{}};\n+ 337 if (not this->lower_bound().is_limited())\n+ 338 lower = other.lower_bound();\n+ 339 else if (not other.lower_bound().is_limited())\n+ 340 lower = this->lower_bound();\n+ 341 else if (*this->lower_bound().value() < *other.lower_bound().value())\n+ 342 lower = other.lower_bound();\n+ 343 else if (*other.lower_bound().value() < *this->lower_bound().value())\n+ 344 lower = this->lower_bound();\n+ 345 else if (this->lower_bound().is_exclusive())\n+ 346 lower = this->lower_bound();\n+ 347 else\n+ 348 lower = other.lower_bound();\n+ 349\n+ 350 range_bound upper{no_bound{}};\n+ 351 if (not this->upper_bound().is_limited())\n+ 352 upper = other.upper_bound();\n+ 353 else if (not other.upper_bound().is_limited())\n+ 354 upper = this->upper_bound();\n+ 355 else if (*other.upper_bound().value() < *this->upper_bound().value())\n+ 356 upper = other.upper_bound();\n+ 357 else if (*this->upper_bound().value() < *other.upper_bound().value())\n+ 358 upper = this->upper_bound();\n+ 359 else if (this->upper_bound().is_exclusive())\n+ 360 upper = this->upper_bound();\n+ 361 else\n+ 362 upper = other.upper_bound();\n+ 363\n+ 364 if (\n+ 365 lower.is_limited() and upper.is_limited() and\n+ 366 (*upper.value() < *lower.value()))\n+ 367 return {};\n+ 368 else\n+ 369 return {lower, upper};\n+ 370 }\n+ 371\n+373 template operator range() const\n+ 374 {\n+ 375 range_bound lower{no_bound{}}, upper{no_bound{}};\n+ 376 if (lower_bound().is_inclusive())\n+ 377 lower = inclusive_bound{*lower_bound().value()};\n+ 378 else if (lower_bound().is_exclusive())\n+ 379 lower = exclusive_bound{*lower_bound().value()};\n+ 380\n+ 381 if (upper_bound().is_inclusive())\n+ 382 upper = inclusive_bound{*upper_bound().value()};\n+ 383 else if (upper_bound().is_exclusive())\n+ 384 upper = exclusive_bound{*upper_bound().value()};\n+ 385\n+ 386 return {lower, upper};\n+ 387 }\n+ 388};\n+ 389\n+ 390\n+ 392\n+395template struct string_traits>\n+ 396{\n+ 397 [[nodiscard]] static inline zview\n+398 to_buf(char *begin, char *end, range const &value)\n+ 399 {\n+ 400 return generic_to_buf(begin, end, value);\n+ 401 }\n+ 402\n+ 403 static inline char *\n+404 into_buf(char *begin, char *end, range const &value)\n+ 405 {\n+ 406 if (value.empty())\n+ 407 {\n+ 408 if ((end - begin) <= internal::ssize(s_empty))\n+ 409 throw conversion_overrun{s_overrun.c_str()};\n+ 410 char *here = begin + s_empty.copy(begin, std::size(s_empty));\n+ 411 *here++ = '\\0';\n+ 412 return here;\n+ 413 }\n+ 414 else\n+ 415 {\n+ 416 if (end - begin < 4)\n+ 417 throw conversion_overrun{s_overrun.c_str()};\n+ 418 char *here = begin;\n+ 419 *here++ =\n+ 420 (static_cast(value.lower_bound().is_inclusive() ? '[' : '('));\n+ 421 TYPE const *lower{value.lower_bound().value()};\n+ 422 // Convert bound (but go back to overwrite that trailing zero).\n+ 423 if (lower != nullptr)\n+ 424 here = string_traits::into_buf(here, end, *lower) - 1;\n+ 425 *here++ = ',';\n+ 426 TYPE const *upper{value.upper_bound().value()};\n+ 427 // Convert bound (but go back to overwrite that trailing zero).\n+ 428 if (upper != nullptr)\n+ 429 here = string_traits::into_buf(here, end, *upper) - 1;\n+ 430 if ((end - here) < 2)\n+ 431 throw conversion_overrun{s_overrun.c_str()};\n+ 432 *here++ =\n+ 433 static_cast(value.upper_bound().is_inclusive() ? ']' : ')');\n+ 434 *here++ = '\\0';\n+ 435 return here;\n+ 436 }\n+ 437 }\n+ 438\n+439 [[nodiscard]] static inline range from_string(std::string_view text)\n+ 440 {\n+ 441 if (std::size(text) < 3)\n+ 442 throw pqxx::conversion_error{err_bad_input(text)};\n+ 443 bool left_inc{false};\n+ 444 switch (text[0])\n+ 445 {\n+ 446 case '[': left_inc = true; break;\n+ 447\n+ 448 case '(': break;\n+ 449\n+ 450 case 'e':\n+ 451 case 'E':\n+ 452 if (\n+ 453 (std::size(text) != std::size(s_empty)) or\n+ 454 (text[1] != 'm' and text[1] != 'M') or\n+ 455 (text[2] != 'p' and text[2] != 'P') or\n+ 456 (text[3] != 't' and text[3] != 'T') or\n+ 457 (text[4] != 'y' and text[4] != 'Y'))\n+ 458 throw pqxx::conversion_error{err_bad_input(text)};\n+ 459 return {};\n+ 460 break;\n+ 461\n+ 462 default: throw pqxx::conversion_error{err_bad_input(text)};\n+ 463 }\n+ 464\n+ 465 // The field parser uses this to track which field it's parsing, and\n+ 466 // when not to expect a field separator.\n+ 467 std::size_t index{0};\n+ 468 // The last field we expect to see.\n+ 469 static constexpr std::size_t last{1};\n+ 470 // Current parsing position. We skip the opening parenthesis or bracket.\n+ 471 std::size_t pos{1};\n+ 472 // The string may leave out either bound to indicate that it's unlimited.\n+ 473 std::optional lower, upper;\n+ 474 // We reuse the same field parser we use for composite values and arrays.\n+ 475 auto const field_parser{\n+ 476 pqxx::internal::specialize_parse_composite_field>(\n+ 477 pqxx::internal::encoding_group::UTF8)};\n+ 478 field_parser(index, text, pos, lower, last);\n+ 479 field_parser(index, text, pos, upper, last);\n+ 480\n+ 481 // We need one more character: the closing parenthesis or bracket.\n+ 482 if (pos != std::size(text))\n+ 483 throw pqxx::conversion_error{err_bad_input(text)};\n+ 484 char const closing{text[pos - 1]};\n+ 485 if (closing != ')' and closing != ']')\n+ 486 throw pqxx::conversion_error{err_bad_input(text)};\n+ 487 bool const right_inc{closing == ']'};\n+ 488\n+ 489 range_bound lower_bound{no_bound{}}, upper_bound{no_bound{}};\n+ 490 if (lower)\n+ 491 {\n+ 492 if (left_inc)\n+ 493 lower_bound = inclusive_bound{*lower};\n+ 494 else\n+ 495 lower_bound = exclusive_bound{*lower};\n+ 496 }\n+ 497 if (upper)\n+ 498 {\n+ 499 if (right_inc)\n+ 500 upper_bound = inclusive_bound{*upper};\n+ 501 else\n+ 502 upper_bound = exclusive_bound{*upper};\n+ 503 }\n+ 504\n+ 505 return {lower_bound, upper_bound};\n+ 506 }\n+ 507\n+ 508 [[nodiscard]] static inline constexpr std::size_t\n+509 size_buffer(range const &value) noexcept\n+ 510 {\n+ 511 TYPE const *lower{value.lower_bound().value()},\n+ 512 *upper{value.upper_bound().value()};\n+ 513 std::size_t const lsz{\n+ 514 lower == nullptr ? 0 : string_traits::size_buffer(*lower) - 1},\n+ 515 usz{upper == nullptr ? 0 : string_traits::size_buffer(*upper) - 1};\n+ 516\n+ 517 if (value.empty())\n+ 518 return std::size(s_empty) + 1;\n+ 519 else\n+ 520 return 1 + lsz + 1 + usz + 2;\n+ 521 }\n+ 522\n+ 523private:\n+ 524 static constexpr zview s_empty{\"empty\"_zv};\n+ 525 static constexpr auto s_overrun{\"Not enough space in buffer for\n+range.\"_zv};\n+ 526\n+ 528 static std::string err_bad_input(std::string_view text)\n+ 529 {\n+ 530 return internal::concat(\"Invalid range input: '\", text, \"'\");\n+ 531 }\n+ 532};\n+ 533\n+ 534\n+536template struct nullness> : no_null>\n+ 537{};\n+ 538} // namespace pqxx\n+ 539#endif\n+pqxx\n+The home of all libpqxx classes, functions, templates, etc.\n+Definition array.hxx:33\n+pqxx::format::text\n+@ text\n+pqxx::argument_error\n+Invalid argument passed to libpqxx, similar to std::invalid_argument.\n+Definition except.hxx:266\n+pqxx::conversion_error\n+Value conversion failed, e.g. when converting \"Hello\" to int.\n+Definition except.hxx:283\n+pqxx::conversion_overrun\n+Could not convert value to string: not enough buffer space.\n+Definition except.hxx:313\n+pqxx::range_error\n+Something is out of range, similar to std::out_of_range.\n+Definition except.hxx:326\n+pqxx::no_bound\n+An unlimited boundary value to a pqxx::range.\n+Definition range.hxx:24\n+pqxx::no_bound::extends_down_to\n+constexpr bool extends_down_to(TYPE const &) const noexcept\n+Definition range.hxx:26\n+pqxx::no_bound::extends_up_to\n+constexpr bool extends_up_to(TYPE const &) const noexcept\n+Definition range.hxx:31\n+pqxx::inclusive_bound\n+An inclusive boundary value to a pqxx::range.\n+Definition range.hxx:43\n+pqxx::inclusive_bound::inclusive_bound\n+constexpr inclusive_bound(TYPE const &value)\n+Definition range.hxx:50\n+pqxx::inclusive_bound::extends_down_to\n+constexpr bool extends_down_to(TYPE const &value) const noexcept(noexcept\n+(value< m_value))\n+Would this bound, as a lower bound, include value?\n+Definition range.hxx:59\n+pqxx::inclusive_bound::inclusive_bound\n+inclusive_bound()=delete\n+pqxx::inclusive_bound::get\n+constexpr TYPE const & get() const &noexcept\n+Definition range.hxx:56\n+pqxx::inclusive_bound::extends_up_to\n+constexpr bool extends_up_to(TYPE const &value) const noexcept(noexcept(value<\n+m_value))\n+Would this bound, as an upper bound, include value?\n+Definition range.hxx:66\n+pqxx::exclusive_bound\n+An exclusive boundary value to a pqxx::range.\n+Definition range.hxx:79\n+pqxx::exclusive_bound::extends_up_to\n+constexpr bool extends_up_to(TYPE const &value) const noexcept(noexcept(value<\n+m_value))\n+Would this bound, as an upper bound, include value?\n+Definition range.hxx:102\n+pqxx::exclusive_bound::exclusive_bound\n+exclusive_bound()=delete\n+pqxx::exclusive_bound::exclusive_bound\n+constexpr exclusive_bound(TYPE const &value)\n+Definition range.hxx:86\n+pqxx::exclusive_bound::get\n+constexpr TYPE const & get() const &noexcept\n+Definition range.hxx:92\n+pqxx::exclusive_bound::extends_down_to\n+constexpr bool extends_down_to(TYPE const &value) const noexcept(noexcept\n+(m_value< value))\n+Would this bound, as a lower bound, include value?\n+Definition range.hxx:95\n+pqxx::range_bound\n+A range boundary value.\n+Definition range.hxx:115\n+pqxx::range_bound::extends_up_to\n+constexpr bool extends_up_to(TYPE const &value) const\n+Would this bound, as an upper bound, include value?\n+Definition range.hxx:189\n+pqxx::range_bound::range_bound\n+constexpr range_bound(range_bound const &) noexcept(noexcept(inclusive_bound<\n+TYPE >{ std::declval< inclusive_bound< TYPE > const & >()}) and noexcept\n+(exclusive_bound< TYPE >{ std::declval< exclusive_bound< TYPE > const & >\n+()}))=default\n+pqxx::range_bound::is_exclusive\n+constexpr bool is_exclusive() const noexcept\n+Is this boundary an exclusive one?\n+Definition range.hxx:174\n+pqxx::range_bound::range_bound\n+constexpr range_bound(inclusive_bound< TYPE > const &bound) noexcept(noexcept\n+(inclusive_bound< TYPE >{bound}))\n+Definition range.hxx:124\n+pqxx::range_bound::is_limited\n+constexpr bool is_limited() const noexcept\n+Is this a finite bound?\n+Definition range.hxx:162\n+pqxx::range_bound::value\n+constexpr TYPE const * value() const &noexcept\n+Return bound value, or nullptr if it's not limited.\n+Definition range.hxx:198\n+pqxx::range_bound::operator!=\n+constexpr bool operator!=(range_bound const &rhs) const noexcept(noexcept\n+(*this==rhs))\n+Definition range.hxx:153\n+pqxx::range_bound::extends_down_to\n+constexpr bool extends_down_to(TYPE const &value) const\n+Would this bound, as a lower bound, include value?\n+Definition range.hxx:180\n+pqxx::range_bound::range_bound\n+range_bound()=delete\n+pqxx::range_bound::range_bound\n+constexpr range_bound(no_bound) noexcept\n+Definition range.hxx:122\n+pqxx::range_bound::operator=\n+range_bound & operator=(range_bound const &)=default\n+pqxx::range_bound::operator==\n+constexpr bool operator==(range_bound const &rhs) const noexcept(noexcept\n+(*this->value()== *rhs.value()))\n+Definition range.hxx:142\n+pqxx::range_bound::range_bound\n+constexpr range_bound(exclusive_bound< TYPE > const &bound) noexcept(noexcept\n+(exclusive_bound{bound}))\n+Definition range.hxx:129\n+pqxx::range_bound::is_inclusive\n+constexpr bool is_inclusive() const noexcept\n+Is this boundary an inclusive one?\n+Definition range.hxx:168\n+pqxx::range_bound::operator=\n+range_bound & operator=(range_bound &&)=default\n+pqxx::range_bound::range_bound\n+constexpr range_bound(range_bound &&)=default\n+pqxx::range\n+A C++ equivalent to PostgreSQL's range types.\n+Definition range.hxx:234\n+pqxx::range::operator&\n+constexpr range operator&(range const &other) const\n+Intersection of two ranges.\n+Definition range.hxx:334\n+pqxx::range::operator==\n+constexpr bool operator==(range const &rhs) const noexcept(noexcept(this-\n+>lower_bound()==rhs.lower_bound()) and noexcept(this->upper_bound\n+()==rhs.upper_bound()) and noexcept(this->empty()))\n+Definition range.hxx:265\n+pqxx::range::contains\n+constexpr bool contains(TYPE value) const noexcept(noexcept\n+(m_lower.extends_down_to(value)) and noexcept(m_upper.extends_up_to(value)))\n+Does this range encompass value?\n+Definition range.hxx:304\n+pqxx::range::contains\n+constexpr bool contains(range< TYPE > const &other) const noexcept(noexcept(\n+(*this &other)==other))\n+Does this range encompass all of other?\n+Definition range.hxx:314\n+pqxx::range::operator!=\n+constexpr bool operator!=(range const &rhs) const noexcept(noexcept\n+(*this==rhs))\n+Definition range.hxx:274\n+pqxx::range::range\n+range(range &&)=default\n+pqxx::range::range\n+range(range const &)=default\n+pqxx::range::operator=\n+range & operator=(range &&)=default\n+pqxx::range::operator=\n+range & operator=(range const &)=default\n+pqxx::range::range\n+constexpr range(range_bound< TYPE > lower, range_bound< TYPE > upper)\n+Create a range.\n+Definition range.hxx:245\n+pqxx::range::upper_bound\n+constexpr range_bound< TYPE > const & upper_bound() const &noexcept\n+Definition range.hxx:326\n+pqxx::range::empty\n+constexpr bool empty() const noexcept(noexcept(m_lower.is_exclusive()) and\n+noexcept(m_lower.is_limited()) and noexcept(*m_lower.value()< *m_upper.value\n+()))\n+Is this range clearly empty?\n+Definition range.hxx:294\n+pqxx::range::lower_bound\n+constexpr range_bound< TYPE > const & lower_bound() const &noexcept\n+Definition range.hxx:321\n+pqxx::range::range\n+constexpr range() noexcept(noexcept(exclusive_bound< TYPE >{TYPE{}}))\n+Create an empty range.\n+Definition range.hxx:260\n+pqxx::string_traits<_range<_TYPE_>_>::size_buffer\n+static constexpr std::size_t size_buffer(range< TYPE > const &value) noexcept\n+Definition range.hxx:509\n+pqxx::string_traits<_range<_TYPE_>_>::into_buf\n+static char * into_buf(char *begin, char *end, range< TYPE > const &value)\n+Definition range.hxx:404\n+pqxx::string_traits<_range<_TYPE_>_>::to_buf\n+static zview to_buf(char *begin, char *end, range< TYPE > const &value)\n+Definition range.hxx:398\n+pqxx::string_traits<_range<_TYPE_>_>::from_string\n+static range< TYPE > from_string(std::string_view text)\n+Definition range.hxx:439\n+pqxx::nullness\n+Traits describing a type's \"null value,\" if any.\n+Definition strconv.hxx:93\n+pqxx::no_null\n+Nullness traits describing a type which does not have a null value.\n+Definition strconv.hxx:115\n+pqxx::string_traits\n+Traits class for use in string conversions.\n+Definition strconv.hxx:155\n+pqxx::zview\n+Marker-type wrapper: zero-terminated std::string_view.\n+Definition zview.hxx:38\n * include\n * pqxx\n- * prepared_statement.hxx\n+ * range.hxx\n * Generated by [doxygen] 1.9.8\n"}]}, {"source1": "./usr/share/doc/libpqxx-doc/html/a00020_source.html", "source2": "./usr/share/doc/libpqxx-doc/html/a00020_source.html", "unified_diff": "@@ -1,15 +1,15 @@\n \n \n \n \n \n \n \n-libpqxx: version.hxx Source File\n+libpqxx: field.hxx Source File\n \n \n \n \n \n \n \n@@ -60,54 +60,539 @@\n \n
\n
\n-
version.hxx
\n+
field.hxx
\n
\n
\n-
1/* Version info for libpqxx.
\n+
1/* Definitions for the pqxx::field class.
\n
2 *
\n-
3 * DO NOT INCLUDE THIS FILE DIRECTLY; include pqxx/version instead.
\n+
3 * pqxx::field refers to a field in a query result.
\n
4 *
\n-
5 * Copyright (c) 2000-2023, Jeroen T. Vermeulen.
\n+
5 * DO NOT INCLUDE THIS FILE DIRECTLY; include pqxx/field instead.
\n
6 *
\n-
7 * See COPYING for copyright license. If you did not receive a file called
\n-
8 * COPYING with this source code, please notify the distributor of this
\n-
9 * mistake, or contact the author.
\n-
10 */
\n-
11#if !defined(PQXX_H_VERSION)
\n-
12# define PQXX_H_VERSION
\n-
13
\n-
14# if !defined(PQXX_HEADER_PRE)
\n-
15# error "Include libpqxx headers as <pqxx/header>, not <pqxx/header.hxx>."
\n-
16# endif
\n-
17
\n-
19# define PQXX_VERSION "7.8.1"
\n-
21# define PQXX_ABI "7.8"
\n-
22
\n-
24# define PQXX_VERSION_MAJOR 7
\n-
26# define PQXX_VERSION_MINOR 8
\n+
7 * Copyright (c) 2000-2023, Jeroen T. Vermeulen.
\n+
8 *
\n+
9 * See COPYING for copyright license. If you did not receive a file called
\n+
10 * COPYING with this source code, please notify the distributor of this
\n+
11 * mistake, or contact the author.
\n+
12 */
\n+
13#ifndef PQXX_H_FIELD
\n+
14#define PQXX_H_FIELD
\n+
15
\n+
16#if !defined(PQXX_HEADER_PRE)
\n+
17# error "Include libpqxx headers as <pqxx/header>, not <pqxx/header.hxx>."
\n+
18#endif
\n+
19
\n+
20#include <optional>
\n+
21
\n+
22#include "pqxx/array.hxx"
\n+
23#include "pqxx/composite.hxx"
\n+
24#include "pqxx/result.hxx"
\n+
25#include "pqxx/strconv.hxx"
\n+
26#include "pqxx/types.hxx"
\n
27
\n-
28# define PQXX_VERSION_CHECK check_pqxx_version_7_8
\n-
29
\n-
30namespace pqxx::internal
\n-
31{
\n-
33
\n-
54PQXX_LIBEXPORT int PQXX_VERSION_CHECK() noexcept;
\n-
55} // namespace pqxx::internal
\n-
56#endif
\n-
Internal items for libpqxx' own use. Do not use these yourself.
Definition composite.hxx:84
\n-
int PQXX_VERSION_CHECK() noexcept
Library version check stub.
Definition version.cxx:23
\n+
28namespace pqxx
\n+
29{
\n+
31
\n+
\n+
34class PQXX_LIBEXPORT field
\n+
35{
\n+
36public:
\n+\n+
38
\n+
40
\n+
44 [[deprecated(
\n+
45 "Do not construct fields yourself. Get them from the row.")]] field(row const &r, row_size_type c) noexcept;
\n+
46
\n+
48 [[deprecated(
\n+
49 "Do not construct fields yourself. Get them from the "
\n+
50 "row.")]] field() noexcept = default;
\n+
51
\n+
57
\n+
73 [[nodiscard]] PQXX_PURE bool operator==(field const &) const noexcept;
\n+
74
\n+
76
\n+
\n+
78 [[nodiscard]] PQXX_PURE bool operator!=(field const &rhs) const noexcept
\n+
79 {
\n+
80 return not operator==(rhs);
\n+
81 }
\n+
\n+
83
\n+
89 [[nodiscard]] PQXX_PURE char const *name() const &;
\n+
90
\n+
92 [[nodiscard]] oid PQXX_PURE type() const;
\n+
93
\n+
95 [[nodiscard]] PQXX_PURE oid table() const;
\n+
96
\n+
98 PQXX_PURE constexpr row_size_type num() const noexcept { return col(); }
\n+
99
\n+
101 [[nodiscard]] PQXX_PURE row_size_type table_column() const;
\n+
103
\n+
109
\n+
\n+
113 [[nodiscard]] PQXX_PURE std::string_view view() const &
\n+
114 {
\n+
115 return std::string_view(c_str(), size());
\n+
116 }
\n+
\n+
117
\n+
119
\n+
128 [[nodiscard]] PQXX_PURE char const *c_str() const &;
\n+
129
\n+
131 [[nodiscard]] PQXX_PURE bool is_null() const noexcept;
\n+
132
\n+
134 [[nodiscard]] PQXX_PURE size_type size() const noexcept;
\n+
135
\n+
137
\n+
140 template<typename T>
\n+
\n+
141 auto to(T &obj) const -> typename std::enable_if_t<
\n+
142 (not std::is_pointer<T>::value or std::is_same<T, char const *>::value),
\n+
143 bool>
\n+
144 {
\n+
145 if (is_null())
\n+
146 {
\n+
147 return false;
\n+
148 }
\n+
149 else
\n+
150 {
\n+
151 auto const bytes{c_str()};
\n+
152 from_string(bytes, obj);
\n+
153 return true;
\n+
154 }
\n+
155 }
\n+
\n+
156
\n+
158
\n+
\n+
163 template<typename... T> bool composite_to(T &...fields) const
\n+
164 {
\n+
165 if (is_null())
\n+
166 {
\n+
167 return false;
\n+
168 }
\n+
169 else
\n+
170 {
\n+
171 parse_composite(m_home.m_encoding, view(), fields...);
\n+
172 return true;
\n+
173 }
\n+
174 }
\n+
\n+
175
\n+
177 template<typename T> bool operator>>(T &obj) const { return to(obj); }
\n+
178
\n+
180
\n+
190 template<typename T>
\n+
\n+
191 auto to(T &obj, T const &default_value) const -> typename std::enable_if_t<
\n+
192 (not std::is_pointer<T>::value or std::is_same<T, char const *>::value),
\n+
193 bool>
\n+
194 {
\n+
195 bool const null{is_null()};
\n+
196 if (null)
\n+
197 obj = default_value;
\n+
198 else
\n+
199 obj = from_string<T>(this->view());
\n+
200 return not null;
\n+
201 }
\n+
\n+
202
\n+
204
\n+
\n+
207 template<typename T> T as(T const &default_value) const
\n+
208 {
\n+
209 if (is_null())
\n+
210 return default_value;
\n+
211 else
\n+
212 return from_string<T>(this->view());
\n+
213 }
\n+
\n+
214
\n+
216
\n+
\n+
221 template<typename T> T as() const
\n+
222 {
\n+
223 if (is_null())
\n+
224 {
\n+
225 if constexpr (not nullness<T>::has_null)
\n+\n+
227 else
\n+
228 return nullness<T>::null();
\n+
229 }
\n+
230 else
\n+
231 {
\n+
232 return from_string<T>(this->view());
\n+
233 }
\n+
234 }
\n+
\n+
235
\n+
237
\n+
240 template<typename T, template<typename> class O = std::optional>
\n+
\n+
241 constexpr O<T> get() const
\n+
242 {
\n+
243 return as<O<T>>();
\n+
244 }
\n+
\n+
245
\n+
247
\n+
\n+
253 array_parser as_array() const &noexcept
\n+
254 {
\n+
255 return array_parser{c_str(), m_home.m_encoding};
\n+
256 }
\n+
\n+
258
\n+
259
\n+
260protected:
\n+
261 constexpr result const &home() const noexcept { return m_home; }
\n+
262 constexpr result::size_type idx() const noexcept { return m_row; }
\n+
263 constexpr row_size_type col() const noexcept { return m_col; }
\n+
264
\n+
265 // TODO: Create gates.
\n+
266 friend class pqxx::result;
\n+
267 friend class pqxx::row;
\n+
\n+\n+
269 result const &r, result_size_type row_num, row_size_type col_num) noexcept
\n+
270 :
\n+
271 m_col{col_num}, m_home{r}, m_row{row_num}
\n+
272 {}
\n+
\n+
273
\n+\n+
279
\n+
280private:
\n+
281 result m_home;
\n+
282 result::size_type m_row;
\n+
283};
\n+
\n+
284
\n+
285
\n+
\n+
286template<> inline bool field::to<std::string>(std::string &obj) const
\n+
287{
\n+
288 bool const null{is_null()};
\n+
289 if (not null)
\n+
290 obj = std::string{view()};
\n+
291 return not null;
\n+
292}
\n+
\n+
293
\n+
294
\n+
295template<>
\n+
\n+
296inline bool field::to<std::string>(
\n+
297 std::string &obj, std::string const &default_value) const
\n+
298{
\n+
299 bool const null{is_null()};
\n+
300 if (null)
\n+
301 obj = default_value;
\n+
302 else
\n+
303 obj = std::string{view()};
\n+
304 return not null;
\n+
305}
\n+
\n+
306
\n+
307
\n+
309
\n+
\n+
314template<> inline bool field::to<char const *>(char const *&obj) const
\n+
315{
\n+
316 bool const null{is_null()};
\n+
317 if (not null)
\n+
318 obj = c_str();
\n+
319 return not null;
\n+
320}
\n+
\n+
321
\n+
322
\n+
\n+
323template<> inline bool field::to<std::string_view>(std::string_view &obj) const
\n+
324{
\n+
325 bool const null{is_null()};
\n+
326 if (not null)
\n+
327 obj = view();
\n+
328 return not null;
\n+
329}
\n+
\n+
330
\n+
331
\n+
332template<>
\n+
\n+
333inline bool field::to<std::string_view>(
\n+
334 std::string_view &obj, std::string_view const &default_value) const
\n+
335{
\n+
336 bool const null{is_null()};
\n+
337 if (null)
\n+
338 obj = default_value;
\n+
339 else
\n+
340 obj = view();
\n+
341 return not null;
\n+
342}
\n+
\n+
343
\n+
344
\n+
\n+
345template<> inline std::string_view field::as<std::string_view>() const
\n+
346{
\n+
347 if (is_null())
\n+
348 PQXX_UNLIKELY
\n+
349 internal::throw_null_conversion(type_name<std::string_view>);
\n+
350 return view();
\n+
351}
\n+
\n+
352
\n+
353
\n+
354template<>
\n+
\n+
355inline std::string_view
\n+
356field::as<std::string_view>(std::string_view const &default_value) const
\n+
357{
\n+
358 return is_null() ? default_value : view();
\n+
359}
\n+
\n+
360
\n+
361
\n+
\n+
362template<> inline bool field::to<zview>(zview &obj) const
\n+
363{
\n+
364 bool const null{is_null()};
\n+
365 if (not null)
\n+
366 obj = zview{c_str(), size()};
\n+
367 return not null;
\n+
368}
\n+
\n+
369
\n+
370
\n+
371template<>
\n+
\n+
372inline bool field::to<zview>(zview &obj, zview const &default_value) const
\n+
373{
\n+
374 bool const null{is_null()};
\n+
375 if (null)
\n+
376 obj = default_value;
\n+
377 else
\n+
378 obj = zview{c_str(), size()};
\n+
379 return not null;
\n+
380}
\n+
\n+
381
\n+
382
\n+
\n+
383template<> inline zview field::as<zview>() const
\n+
384{
\n+
385 if (is_null())
\n+
386 PQXX_UNLIKELY
\n+
387 internal::throw_null_conversion(type_name<zview>);
\n+
388 return zview{c_str(), size()};
\n+
389}
\n+
\n+
390
\n+
391
\n+
\n+
392template<> inline zview field::as<zview>(zview const &default_value) const
\n+
393{
\n+
394 return is_null() ? default_value : zview{c_str(), size()};
\n+
395}
\n+
\n+
396
\n+
397
\n+
398template<typename CHAR = char, typename TRAITS = std::char_traits<CHAR>>
\n+
\n+
399class field_streambuf : public std::basic_streambuf<CHAR, TRAITS>
\n+
400{
\n+
401public:
\n+
402 using char_type = CHAR;
\n+
403 using traits_type = TRAITS;
\n+
404 using int_type = typename traits_type::int_type;
\n+
405 using pos_type = typename traits_type::pos_type;
\n+
406 using off_type = typename traits_type::off_type;
\n+
407 using openmode = std::ios::openmode;
\n+
408 using seekdir = std::ios::seekdir;
\n+
409
\n+
410 explicit field_streambuf(field const &f) : m_field{f} { initialize(); }
\n+
411
\n+
412protected:
\n+
413 virtual int sync() override { return traits_type::eof(); }
\n+
414
\n+
\n+\n+
416 {
\n+
417 return traits_type::eof();
\n+
418 }
\n+
\n+
\n+\n+
420 {
\n+
421 return traits_type::eof();
\n+
422 }
\n+
\n+
423 virtual int_type overflow(int_type) override { return traits_type::eof(); }
\n+
424 virtual int_type underflow() override { return traits_type::eof(); }
\n+
425
\n+
426private:
\n+
427 field const &m_field;
\n+
428
\n+
429 int_type initialize()
\n+
430 {
\n+
431 auto g{static_cast<char_type *>(const_cast<char *>(m_field.c_str()))};
\n+
432 this->setg(g, g, g + std::size(m_field));
\n+
433 return int_type(std::size(m_field));
\n+
434 }
\n+
435};
\n+
\n+
436
\n+
437
\n+
439
\n+
452template<typename CHAR = char, typename TRAITS = std::char_traits<CHAR>>
\n+
\n+
453class basic_fieldstream : public std::basic_istream<CHAR, TRAITS>
\n+
454{
\n+
455 using super = std::basic_istream<CHAR, TRAITS>;
\n+
456
\n+
457public:
\n+
458 using char_type = CHAR;
\n+
459 using traits_type = TRAITS;
\n+
460 using int_type = typename traits_type::int_type;
\n+
461 using pos_type = typename traits_type::pos_type;
\n+
462 using off_type = typename traits_type::off_type;
\n+
463
\n+
\n+
464 [[deprecated("Use field::as<...>() or field::c_str().")]] basic_fieldstream(
\n+
465 field const &f) :
\n+
466 super{nullptr}, m_buf{f}
\n+
467 {
\n+
468 super::init(&m_buf);
\n+
469 }
\n+
\n+
470
\n+
471private:
\n+\n+
473};
\n+
\n+
474
\n+
475
\n+\n+
478
\n+
479
\n+
481
\n+
505template<typename CHAR>
\n+
506[[deprecated(
\n+
507 "Do this by hand, probably with better error checking.")]] inline std::
\n+
508 basic_ostream<CHAR> &
\n+
509 operator<<(std::basic_ostream<CHAR> &s, field const &value)
\n+
510{
\n+
511 s.write(value.c_str(), std::streamsize(std::size(value)));
\n+
512 return s;
\n+
513}
\n+
514
\n+
515
\n+
517
\n+
\n+
520template<typename T> inline T from_string(field const &value)
\n+
521{
\n+
522 if (value.is_null())
\n+
523 {
\n+
524 if constexpr (nullness<T>::has_null)
\n+
525 return nullness<T>::null();
\n+
526 else
\n+\n+
528 }
\n+
529 else
\n+
530 {
\n+
531 return from_string<T>(value.view());
\n+
532 }
\n+
533}
\n+
\n+
534
\n+
535
\n+
537
\n+
543template<>
\n+
\n+
544inline std::nullptr_t from_string<std::nullptr_t>(field const &value)
\n+
545{
\n+
546 if (not value.is_null())
\n+
547 throw conversion_error{
\n+
548 "Extracting non-null field into nullptr_t variable."};
\n+
549 return nullptr;
\n+
550}
\n+
\n+
551
\n+
552
\n+
554template<> PQXX_LIBEXPORT std::string to_string(field const &value);
\n+
555} // namespace pqxx
\n+
556#endif
\n+
The home of all libpqxx classes, functions, templates, etc.
Definition array.hxx:33
\n+
std::basic_ostream< CHAR > & operator<<(std::basic_ostream< CHAR > &s, field const &value)
Write a result field to any type of stream.
Definition field.hxx:509
\n+
int row_size_type
Number of fields in a row of database data.
Definition types.hxx:34
\n+
std::size_t field_size_type
Number of bytes in a field of database data.
Definition types.hxx:40
\n+
int result_size_type
Number of rows in a result set.
Definition types.hxx:28
\n+
void parse_composite(pqxx::internal::encoding_group enc, std::string_view text, T &...fields)
Parse a string representation of a value of a composite type.
Definition composite.hxx:35
\n+
std::nullptr_t from_string< std::nullptr_t >(field const &value)
Convert a field's value to nullptr_t.
Definition field.hxx:544
\n+
std::string to_string(field const &value)
Convert a field to a string.
Definition result.cxx:549
\n+
T from_string(field const &value)
Convert a field's value to type T.
Definition field.hxx:520
\n+
void PQXX_COLD throw_null_conversion(std::string const &type)
Definition strconv.cxx:253
\n+
Low-level array parser.
Definition array.hxx:527
\n+
Value conversion failed, e.g. when converting "Hello" to int.
Definition except.hxx:283
\n+
Reference to a field in a result set.
Definition field.hxx:35
\n+
constexpr result const & home() const noexcept
Definition field.hxx:261
\n+
PQXX_PURE size_type size() const noexcept
Return number of bytes taken up by the field's value.
Definition field.cxx:77
\n+
T as(T const &default_value) const
Return value as object of given type, or default value if null.
Definition field.hxx:207
\n+
row_size_type m_col
Definition field.hxx:278
\n+
array_parser as_array() const &noexcept
Parse the field as an SQL array.
Definition field.hxx:253
\n+
auto to(T &obj, T const &default_value) const -> typename std::enable_if_t<(not std::is_pointer< T >::value or std::is_same< T, char const * >::value), bool >
Read value into obj; or if null, use default value and return false.
Definition field.hxx:191
\n+
field_size_type size_type
Definition field.hxx:37
\n+
bool operator>>(T &obj) const
Read value into obj; or leave obj untouched and return false if null.
Definition field.hxx:177
\n+
PQXX_PURE char const * c_str() const &
Read as plain C string.
Definition field.cxx:65
\n+
T as() const
Return value as object of given type, or throw exception if null.
Definition field.hxx:221
\n+
field(result const &r, result_size_type row_num, row_size_type col_num) noexcept
Definition field.hxx:268
\n+
constexpr row_size_type col() const noexcept
Definition field.hxx:263
\n+
PQXX_PURE std::string_view view() const &
Read as string_view, or an empty one if null.
Definition field.hxx:113
\n+
bool composite_to(T &...fields) const
Read field as a composite value, write its components into fields.
Definition field.hxx:163
\n+
field() noexcept=default
Constructor. Do not call this yourself; libpqxx will do it for you.
\n+
PQXX_PURE bool is_null() const noexcept
Is this field's value null?
Definition field.cxx:71
\n+
constexpr O< T > get() const
Return value wrapped in some optional type (empty for nulls).
Definition field.hxx:241
\n+
constexpr result::size_type idx() const noexcept
Definition field.hxx:262
\n+
Definition field.hxx:400
\n+
TRAITS traits_type
Definition field.hxx:403
\n+
typename traits_type::off_type off_type
Definition field.hxx:406
\n+
field_streambuf(field const &f)
Definition field.hxx:410
\n+
virtual pos_type seekoff(off_type, seekdir, openmode) override
Definition field.hxx:415
\n+
virtual pos_type seekpos(pos_type, openmode) override
Definition field.hxx:419
\n+
std::ios::openmode openmode
Definition field.hxx:407
\n+
virtual int_type overflow(int_type) override
Definition field.hxx:423
\n+
typename traits_type::pos_type pos_type
Definition field.hxx:405
\n+
virtual int sync() override
Definition field.hxx:413
\n+
typename traits_type::int_type int_type
Definition field.hxx:404
\n+
virtual int_type underflow() override
Definition field.hxx:424
\n+
CHAR char_type
Definition field.hxx:402
\n+
std::ios::seekdir seekdir
Definition field.hxx:408
\n+
Input stream that gets its data from a result field.
Definition field.hxx:454
\n+
TRAITS traits_type
Definition field.hxx:459
\n+
basic_fieldstream(field const &f)
Definition field.hxx:464
\n+
typename traits_type::pos_type pos_type
Definition field.hxx:461
\n+
typename traits_type::off_type off_type
Definition field.hxx:462
\n+
typename traits_type::int_type int_type
Definition field.hxx:460
\n+
CHAR char_type
Definition field.hxx:458
\n+
Result set containing data returned by a query or command.
Definition result.hxx:73
\n+
result_size_type size_type
Definition result.hxx:75
\n+
Reference to one row in a result.
Definition row.hxx:47
\n+
Traits describing a type's "null value," if any.
Definition strconv.hxx:93
\n+
static TYPE null()
Return a null value.
\n+
Marker-type wrapper: zero-terminated std::string_view.
Definition zview.hxx:38
\n
\n
\n \n
\n \n
\n \n \n", "details": [{"source1": "html2text {}", "source2": "html2text {}", "unified_diff": "@@ -1,50 +1,613 @@\n \n \n \n \n \n libpqxx\u00a07.8.1\n \n-version.hxx\n- 1/* Version info for libpqxx.\n+field.hxx\n+ 1/* Definitions for the pqxx::field class.\n 2 *\n- 3 * DO NOT INCLUDE THIS FILE DIRECTLY; include pqxx/version instead.\n+ 3 * pqxx::field refers to a field in a query result.\n 4 *\n- 5 * Copyright (c) 2000-2023, Jeroen T. Vermeulen.\n+ 5 * DO NOT INCLUDE THIS FILE DIRECTLY; include pqxx/field instead.\n 6 *\n- 7 * See COPYING for copyright license. If you did not receive a file called\n- 8 * COPYING with this source code, please notify the distributor of this\n- 9 * mistake, or contact the author.\n- 10 */\n- 11#if !defined(PQXX_H_VERSION)\n- 12# define PQXX_H_VERSION\n- 13\n- 14# if !defined(PQXX_HEADER_PRE)\n- 15# error \"Include libpqxx headers as , not .\"\n- 16# endif\n- 17\n- 19# define PQXX_VERSION \"7.8.1\"\n- 21# define PQXX_ABI \"7.8\"\n- 22\n- 24# define PQXX_VERSION_MAJOR 7\n- 26# define PQXX_VERSION_MINOR 8\n+ 7 * Copyright (c) 2000-2023, Jeroen T. Vermeulen.\n+ 8 *\n+ 9 * See COPYING for copyright license. If you did not receive a file called\n+ 10 * COPYING with this source code, please notify the distributor of this\n+ 11 * mistake, or contact the author.\n+ 12 */\n+ 13#ifndef PQXX_H_FIELD\n+ 14#define PQXX_H_FIELD\n+ 15\n+ 16#if !defined(PQXX_HEADER_PRE)\n+ 17# error \"Include libpqxx headers as , not .\"\n+ 18#endif\n+ 19\n+ 20#include \n+ 21\n+ 22#include \"pqxx/array.hxx\"\n+ 23#include \"pqxx/composite.hxx\"\n+ 24#include \"pqxx/result.hxx\"\n+ 25#include \"pqxx/strconv.hxx\"\n+ 26#include \"pqxx/types.hxx\"\n 27\n- 28# define PQXX_VERSION_CHECK check_pqxx_version_7_8\n- 29\n- 30namespace pqxx::internal\n- 31{\n- 33\n- 54PQXX_LIBEXPORT int PQXX_VERSION_CHECK() noexcept;\n- 55} // namespace pqxx::internal\n- 56#endif\n-pqxx::internal\n-Internal items for libpqxx' own use. Do not use these yourself.\n-Definition composite.hxx:84\n-pqxx::internal::PQXX_VERSION_CHECK\n-int PQXX_VERSION_CHECK() noexcept\n-Library version check stub.\n-Definition version.cxx:23\n+ 28namespace pqxx\n+ 29{\n+ 31\n+34class PQXX_LIBEXPORT field\n+ 35{\n+ 36public:\n+37 using size_type = field_size_type;\n+ 38\n+ 40\n+ 44 [[deprecated(\n+ 45 \"Do not construct fields yourself. Get them from the row.\")]] field(row\n+const &r, row_size_type c) noexcept;\n+ 46\n+ 48 [[deprecated(\n+ 49 \"Do not construct fields yourself. Get them from the \"\n+50 \"row.\")]] field() noexcept = default;\n+ 51\n+ 57\n+ 73 [[nodiscard]] PQXX_PURE bool operator==(field const &) const noexcept;\n+ 74\n+ 76\n+78 [[nodiscard]] PQXX_PURE bool operator!=(field const &rhs) const noexcept\n+ 79 {\n+ 80 return not operator==(rhs);\n+ 81 }\n+ 83\n+ 89 [[nodiscard]] PQXX_PURE char const *name() const &;\n+ 90\n+ 92 [[nodiscard]] oid PQXX_PURE type() const;\n+ 93\n+ 95 [[nodiscard]] PQXX_PURE oid table() const;\n+ 96\n+98 PQXX_PURE constexpr row_size_type num() const noexcept { return col(); }\n+ 99\n+ 101 [[nodiscard]] PQXX_PURE row_size_type table_column() const;\n+ 103\n+ 109\n+113 [[nodiscard]] PQXX_PURE std::string_view view() const &\n+ 114 {\n+ 115 return std::string_view(c_str(), size());\n+ 116 }\n+ 117\n+ 119\n+ 128 [[nodiscard]] PQXX_PURE char const *c_str() const &;\n+ 129\n+ 131 [[nodiscard]] PQXX_PURE bool is_null() const noexcept;\n+ 132\n+ 134 [[nodiscard]] PQXX_PURE size_type size() const noexcept;\n+ 135\n+ 137\n+ 140 template\n+141 auto to(T &obj) const -> typename std::enable_if_t<\n+ 142 (not std::is_pointer::value or std::is_same::value),\n+ 143 bool>\n+ 144 {\n+ 145 if (is_null())\n+ 146 {\n+ 147 return false;\n+ 148 }\n+ 149 else\n+ 150 {\n+ 151 auto const bytes{c_str()};\n+ 152 from_string(bytes, obj);\n+ 153 return true;\n+ 154 }\n+ 155 }\n+ 156\n+ 158\n+163 template bool composite_to(T &...fields) const\n+ 164 {\n+ 165 if (is_null())\n+ 166 {\n+ 167 return false;\n+ 168 }\n+ 169 else\n+ 170 {\n+ 171 parse_composite(m_home.m_encoding, view(), fields...);\n+ 172 return true;\n+ 173 }\n+ 174 }\n+ 175\n+177 template bool operator>>(T &obj) const { return to(obj); }\n+ 178\n+ 180\n+ 190 template\n+191 auto to(T &obj, T const &default_value) const -> typename std::enable_if_t<\n+ 192 (not std::is_pointer::value or std::is_same::value),\n+ 193 bool>\n+ 194 {\n+ 195 bool const null{is_null()};\n+ 196 if (null)\n+ 197 obj = default_value;\n+ 198 else\n+ 199 obj = from_string(this->view());\n+ 200 return not null;\n+ 201 }\n+ 202\n+ 204\n+207 template T as(T const &default_value) const\n+ 208 {\n+ 209 if (is_null())\n+ 210 return default_value;\n+ 211 else\n+ 212 return from_string(this->view());\n+ 213 }\n+ 214\n+ 216\n+221 template T as() const\n+ 222 {\n+ 223 if (is_null())\n+ 224 {\n+ 225 if constexpr (not nullness::has_null)\n+ 226 internal::throw_null_conversion(type_name);\n+ 227 else\n+ 228 return nullness::null();\n+ 229 }\n+ 230 else\n+ 231 {\n+ 232 return from_string(this->view());\n+ 233 }\n+ 234 }\n+ 235\n+ 237\n+ 240 template class O = std::optional>\n+241 constexpr O get() const\n+ 242 {\n+ 243 return as>();\n+ 244 }\n+ 245\n+ 247\n+253 array_parser as_array() const &noexcept\n+ 254 {\n+ 255 return array_parser{c_str(), m_home.m_encoding};\n+ 256 }\n+ 258\n+ 259\n+ 260protected:\n+261 constexpr result const &home() const noexcept { return m_home; }\n+262 constexpr result::size_type idx() const noexcept { return m_row; }\n+263 constexpr row_size_type col() const noexcept { return m_col; }\n+ 264\n+ 265 // TODO: Create gates.\n+266 friend class pqxx::result;\n+267 friend class pqxx::row;\n+268 field(\n+ 269 result const &r, result_size_type row_num, row_size_type col_num) noexcept\n+ 270 :\n+ 271 m_col{col_num}, m_home{r}, m_row{row_num}\n+ 272 {}\n+ 273\n+278 row_size_type m_col;\n+ 279\n+ 280private:\n+ 281 result m_home;\n+ 282 result::size_type m_row;\n+ 283};\n+ 284\n+ 285\n+286template<> inline bool field::to(std::string &obj) const\n+ 287{\n+ 288 bool const null{is_null()};\n+ 289 if (not null)\n+ 290 obj = std::string{view()};\n+ 291 return not null;\n+ 292}\n+ 293\n+ 294\n+ 295template<>\n+296inline bool field::to(\n+ 297 std::string &obj, std::string const &default_value) const\n+ 298{\n+ 299 bool const null{is_null()};\n+ 300 if (null)\n+ 301 obj = default_value;\n+ 302 else\n+ 303 obj = std::string{view()};\n+ 304 return not null;\n+ 305}\n+ 306\n+ 307\n+ 309\n+314template<> inline bool field::to(char const *&obj) const\n+ 315{\n+ 316 bool const null{is_null()};\n+ 317 if (not null)\n+ 318 obj = c_str();\n+ 319 return not null;\n+ 320}\n+ 321\n+ 322\n+323template<> inline bool field::to(std::string_view &obj)\n+const\n+ 324{\n+ 325 bool const null{is_null()};\n+ 326 if (not null)\n+ 327 obj = view();\n+ 328 return not null;\n+ 329}\n+ 330\n+ 331\n+ 332template<>\n+333inline bool field::to(\n+ 334 std::string_view &obj, std::string_view const &default_value) const\n+ 335{\n+ 336 bool const null{is_null()};\n+ 337 if (null)\n+ 338 obj = default_value;\n+ 339 else\n+ 340 obj = view();\n+ 341 return not null;\n+ 342}\n+ 343\n+ 344\n+345template<> inline std::string_view field::as() const\n+ 346{\n+ 347 if (is_null())\n+ 348 PQXX_UNLIKELY\n+ 349 internal::throw_null_conversion(type_name);\n+ 350 return view();\n+ 351}\n+ 352\n+ 353\n+ 354template<>\n+355inline std::string_view\n+ 356field::as(std::string_view const &default_value) const\n+ 357{\n+ 358 return is_null() ? default_value : view();\n+ 359}\n+ 360\n+ 361\n+362template<> inline bool field::to(zview &obj) const\n+ 363{\n+ 364 bool const null{is_null()};\n+ 365 if (not null)\n+ 366 obj = zview{c_str(), size()};\n+ 367 return not null;\n+ 368}\n+ 369\n+ 370\n+ 371template<>\n+372inline bool field::to(zview &obj, zview const &default_value) const\n+ 373{\n+ 374 bool const null{is_null()};\n+ 375 if (null)\n+ 376 obj = default_value;\n+ 377 else\n+ 378 obj = zview{c_str(), size()};\n+ 379 return not null;\n+ 380}\n+ 381\n+ 382\n+383template<> inline zview field::as() const\n+ 384{\n+ 385 if (is_null())\n+ 386 PQXX_UNLIKELY\n+ 387 internal::throw_null_conversion(type_name);\n+ 388 return zview{c_str(), size()};\n+ 389}\n+ 390\n+ 391\n+392template<> inline zview field::as(zview const &default_value) const\n+ 393{\n+ 394 return is_null() ? default_value : zview{c_str(), size()};\n+ 395}\n+ 396\n+ 397\n+ 398template>\n+399class field_streambuf : public std::basic_streambuf\n+ 400{\n+ 401public:\n+402 using char_type = CHAR;\n+403 using traits_type = TRAITS;\n+404 using int_type = typename traits_type::int_type;\n+405 using pos_type = typename traits_type::pos_type;\n+406 using off_type = typename traits_type::off_type;\n+407 using openmode = std::ios::openmode;\n+408 using seekdir = std::ios::seekdir;\n+ 409\n+410 explicit field_streambuf(field const &f) : m_field{f} { initialize(); }\n+ 411\n+ 412protected:\n+413 virtual int sync() override { return traits_type::eof(); }\n+ 414\n+415 virtual pos_type seekoff(off_type, seekdir, openmode) override\n+ 416 {\n+ 417 return traits_type::eof();\n+ 418 }\n+419 virtual pos_type seekpos(pos_type, openmode) override\n+ 420 {\n+ 421 return traits_type::eof();\n+ 422 }\n+423 virtual int_type overflow(int_type) override { return traits_type::eof(); }\n+424 virtual int_type underflow() override { return traits_type::eof(); }\n+ 425\n+ 426private:\n+ 427 field const &m_field;\n+ 428\n+ 429 int_type initialize()\n+ 430 {\n+ 431 auto g{static_cast(const_cast(m_field.c_str()))};\n+ 432 this->setg(g, g, g + std::size(m_field));\n+ 433 return int_type(std::size(m_field));\n+ 434 }\n+ 435};\n+ 436\n+ 437\n+ 439\n+ 452template>\n+453class basic_fieldstream : public std::basic_istream\n+ 454{\n+ 455 using super = std::basic_istream;\n+ 456\n+ 457public:\n+458 using char_type = CHAR;\n+459 using traits_type = TRAITS;\n+460 using int_type = typename traits_type::int_type;\n+461 using pos_type = typename traits_type::pos_type;\n+462 using off_type = typename traits_type::off_type;\n+ 463\n+464 [[deprecated(\"Use field::as<...>() or field::c_str().\")]] basic_fieldstream\n+(\n+ 465 field const &f) :\n+ 466 super{nullptr}, m_buf{f}\n+ 467 {\n+ 468 super::init(&m_buf);\n+ 469 }\n+ 470\n+ 471private:\n+ 472 field_streambuf m_buf;\n+ 473};\n+ 474\n+ 475\n+477using fieldstream = basic_fieldstream;\n+ 478\n+ 479\n+ 481\n+ 505template\n+ 506[[deprecated(\n+ 507 \"Do this by hand, probably with better error checking.\")]] inline std::\n+ 508 basic_ostream &\n+ 509 operator<<(std::basic_ostream &s, field const &value)\n+ 510{\n+ 511 s.write(value.c_str(), std::streamsize(std::size(value)));\n+ 512 return s;\n+ 513}\n+ 514\n+ 515\n+ 517\n+520template inline T from_string(field const &value)\n+ 521{\n+ 522 if (value.is_null())\n+ 523 {\n+ 524 if constexpr (nullness::has_null)\n+ 525 return nullness::null();\n+ 526 else\n+ 527 internal::throw_null_conversion(type_name);\n+ 528 }\n+ 529 else\n+ 530 {\n+ 531 return from_string(value.view());\n+ 532 }\n+ 533}\n+ 534\n+ 535\n+ 537\n+ 543template<>\n+544inline std::nullptr_t from_string(field const &value)\n+ 545{\n+ 546 if (not value.is_null())\n+ 547 throw conversion_error{\n+ 548 \"Extracting non-null field into nullptr_t variable.\"};\n+ 549 return nullptr;\n+ 550}\n+ 551\n+ 552\n+ 554template<> PQXX_LIBEXPORT std::string to_string(field const &value);\n+ 555} // namespace pqxx\n+ 556#endif\n+pqxx\n+The home of all libpqxx classes, functions, templates, etc.\n+Definition array.hxx:33\n+pqxx::operator<<\n+std::basic_ostream< CHAR > & operator<<(std::basic_ostream< CHAR > &s, field\n+const &value)\n+Write a result field to any type of stream.\n+Definition field.hxx:509\n+pqxx::row_size_type\n+int row_size_type\n+Number of fields in a row of database data.\n+Definition types.hxx:34\n+pqxx::field_size_type\n+std::size_t field_size_type\n+Number of bytes in a field of database data.\n+Definition types.hxx:40\n+pqxx::result_size_type\n+int result_size_type\n+Number of rows in a result set.\n+Definition types.hxx:28\n+pqxx::parse_composite\n+void parse_composite(pqxx::internal::encoding_group enc, std::string_view text,\n+T &...fields)\n+Parse a string representation of a value of a composite type.\n+Definition composite.hxx:35\n+pqxx::from_string<_std::nullptr_t_>\n+std::nullptr_t from_string< std::nullptr_t >(field const &value)\n+Convert a field's value to nullptr_t.\n+Definition field.hxx:544\n+pqxx::to_string\n+std::string to_string(field const &value)\n+Convert a field to a string.\n+Definition result.cxx:549\n+pqxx::from_string\n+T from_string(field const &value)\n+Convert a field's value to type T.\n+Definition field.hxx:520\n+pqxx::internal::throw_null_conversion\n+void PQXX_COLD throw_null_conversion(std::string const &type)\n+Definition strconv.cxx:253\n+pqxx::array_parser\n+Low-level array parser.\n+Definition array.hxx:527\n+pqxx::conversion_error\n+Value conversion failed, e.g. when converting \"Hello\" to int.\n+Definition except.hxx:283\n+pqxx::field\n+Reference to a field in a result set.\n+Definition field.hxx:35\n+pqxx::field::home\n+constexpr result const & home() const noexcept\n+Definition field.hxx:261\n+pqxx::field::size\n+PQXX_PURE size_type size() const noexcept\n+Return number of bytes taken up by the field's value.\n+Definition field.cxx:77\n+pqxx::field::as\n+T as(T const &default_value) const\n+Return value as object of given type, or default value if null.\n+Definition field.hxx:207\n+pqxx::field::m_col\n+row_size_type m_col\n+Definition field.hxx:278\n+pqxx::field::as_array\n+array_parser as_array() const &noexcept\n+Parse the field as an SQL array.\n+Definition field.hxx:253\n+pqxx::field::to\n+auto to(T &obj, T const &default_value) const -> typename std::enable_if_t<(not\n+std::is_pointer< T >::value or std::is_same< T, char const * >::value), bool >\n+Read value into obj; or if null, use default value and return false.\n+Definition field.hxx:191\n+pqxx::field::size_type\n+field_size_type size_type\n+Definition field.hxx:37\n+pqxx::field::operator>>\n+bool operator>>(T &obj) const\n+Read value into obj; or leave obj untouched and return false if null.\n+Definition field.hxx:177\n+pqxx::field::c_str\n+PQXX_PURE char const * c_str() const &\n+Read as plain C string.\n+Definition field.cxx:65\n+pqxx::field::as\n+T as() const\n+Return value as object of given type, or throw exception if null.\n+Definition field.hxx:221\n+pqxx::field::field\n+field(result const &r, result_size_type row_num, row_size_type col_num)\n+noexcept\n+Definition field.hxx:268\n+pqxx::field::col\n+constexpr row_size_type col() const noexcept\n+Definition field.hxx:263\n+pqxx::field::view\n+PQXX_PURE std::string_view view() const &\n+Read as string_view, or an empty one if null.\n+Definition field.hxx:113\n+pqxx::field::composite_to\n+bool composite_to(T &...fields) const\n+Read field as a composite value, write its components into fields.\n+Definition field.hxx:163\n+pqxx::field::field\n+field() noexcept=default\n+Constructor. Do not call this yourself; libpqxx will do it for you.\n+pqxx::field::is_null\n+PQXX_PURE bool is_null() const noexcept\n+Is this field's value null?\n+Definition field.cxx:71\n+pqxx::field::get\n+constexpr O< T > get() const\n+Return value wrapped in some optional type (empty for nulls).\n+Definition field.hxx:241\n+pqxx::field::idx\n+constexpr result::size_type idx() const noexcept\n+Definition field.hxx:262\n+pqxx::field_streambuf\n+Definition field.hxx:400\n+pqxx::field_streambuf::traits_type\n+TRAITS traits_type\n+Definition field.hxx:403\n+pqxx::field_streambuf::off_type\n+typename traits_type::off_type off_type\n+Definition field.hxx:406\n+pqxx::field_streambuf::field_streambuf\n+field_streambuf(field const &f)\n+Definition field.hxx:410\n+pqxx::field_streambuf::seekoff\n+virtual pos_type seekoff(off_type, seekdir, openmode) override\n+Definition field.hxx:415\n+pqxx::field_streambuf::seekpos\n+virtual pos_type seekpos(pos_type, openmode) override\n+Definition field.hxx:419\n+pqxx::field_streambuf::openmode\n+std::ios::openmode openmode\n+Definition field.hxx:407\n+pqxx::field_streambuf::overflow\n+virtual int_type overflow(int_type) override\n+Definition field.hxx:423\n+pqxx::field_streambuf::pos_type\n+typename traits_type::pos_type pos_type\n+Definition field.hxx:405\n+pqxx::field_streambuf::sync\n+virtual int sync() override\n+Definition field.hxx:413\n+pqxx::field_streambuf::int_type\n+typename traits_type::int_type int_type\n+Definition field.hxx:404\n+pqxx::field_streambuf::underflow\n+virtual int_type underflow() override\n+Definition field.hxx:424\n+pqxx::field_streambuf::char_type\n+CHAR char_type\n+Definition field.hxx:402\n+pqxx::field_streambuf::seekdir\n+std::ios::seekdir seekdir\n+Definition field.hxx:408\n+pqxx::basic_fieldstream\n+Input stream that gets its data from a result field.\n+Definition field.hxx:454\n+pqxx::basic_fieldstream::traits_type\n+TRAITS traits_type\n+Definition field.hxx:459\n+pqxx::basic_fieldstream::basic_fieldstream\n+basic_fieldstream(field const &f)\n+Definition field.hxx:464\n+pqxx::basic_fieldstream::pos_type\n+typename traits_type::pos_type pos_type\n+Definition field.hxx:461\n+pqxx::basic_fieldstream::off_type\n+typename traits_type::off_type off_type\n+Definition field.hxx:462\n+pqxx::basic_fieldstream::int_type\n+typename traits_type::int_type int_type\n+Definition field.hxx:460\n+pqxx::basic_fieldstream::char_type\n+CHAR char_type\n+Definition field.hxx:458\n+pqxx::result\n+Result set containing data returned by a query or command.\n+Definition result.hxx:73\n+pqxx::result::size_type\n+result_size_type size_type\n+Definition result.hxx:75\n+pqxx::row\n+Reference to one row in a result.\n+Definition row.hxx:47\n+pqxx::nullness\n+Traits describing a type's \"null value,\" if any.\n+Definition strconv.hxx:93\n+pqxx::nullness::null\n+static TYPE null()\n+Return a null value.\n+pqxx::zview\n+Marker-type wrapper: zero-terminated std::string_view.\n+Definition zview.hxx:38\n * include\n * pqxx\n- * version.hxx\n+ * field.hxx\n * Generated by [doxygen] 1.9.8\n"}]}, {"source1": "./usr/share/doc/libpqxx-doc/html/a00023_source.html", "source2": "./usr/share/doc/libpqxx-doc/html/a00023_source.html", "unified_diff": "@@ -1,15 +1,15 @@\n \n \n \n \n \n \n \n-libpqxx: field.hxx Source File\n+libpqxx: transactor.hxx Source File\n \n \n \n \n \n \n \n@@ -60,539 +60,111 @@\n \n
\n
\n-
field.hxx
\n+
transactor.hxx
\n
\n
\n-
1/* Definitions for the pqxx::field class.
\n+
1/* Transactor framework, a wrapper for safely retryable transactions.
\n
2 *
\n-
3 * pqxx::field refers to a field in a query result.
\n+
3 * DO NOT INCLUDE THIS FILE DIRECTLY; include pqxx/transactor instead.
\n
4 *
\n-
5 * DO NOT INCLUDE THIS FILE DIRECTLY; include pqxx/field instead.
\n+
5 * Copyright (c) 2000-2023, Jeroen T. Vermeulen.
\n
6 *
\n-
7 * Copyright (c) 2000-2023, Jeroen T. Vermeulen.
\n-
8 *
\n-
9 * See COPYING for copyright license. If you did not receive a file called
\n-
10 * COPYING with this source code, please notify the distributor of this
\n-
11 * mistake, or contact the author.
\n-
12 */
\n-
13#ifndef PQXX_H_FIELD
\n-
14#define PQXX_H_FIELD
\n-
15
\n-
16#if !defined(PQXX_HEADER_PRE)
\n-
17# error "Include libpqxx headers as <pqxx/header>, not <pqxx/header.hxx>."
\n-
18#endif
\n-
19
\n-
20#include <optional>
\n-
21
\n-
22#include "pqxx/array.hxx"
\n-
23#include "pqxx/composite.hxx"
\n-
24#include "pqxx/result.hxx"
\n-
25#include "pqxx/strconv.hxx"
\n-
26#include "pqxx/types.hxx"
\n-
27
\n-
28namespace pqxx
\n-
29{
\n-
31
\n-
\n-
34class PQXX_LIBEXPORT field
\n-
35{
\n-
36public:
\n-\n-
38
\n-
40
\n-
44 [[deprecated(
\n-
45 "Do not construct fields yourself. Get them from the row.")]] field(row const &r, row_size_type c) noexcept;
\n-
46
\n-
48 [[deprecated(
\n-
49 "Do not construct fields yourself. Get them from the "
\n-
50 "row.")]] field() noexcept = default;
\n-
51
\n-
57
\n-
73 [[nodiscard]] PQXX_PURE bool operator==(field const &) const noexcept;
\n-
74
\n-
76
\n-
\n-
78 [[nodiscard]] PQXX_PURE bool operator!=(field const &rhs) const noexcept
\n-
79 {
\n-
80 return not operator==(rhs);
\n-
81 }
\n+
7 * See COPYING for copyright license. If you did not receive a file called
\n+
8 * COPYING with this source code, please notify the distributor of this
\n+
9 * mistake, or contact the author.
\n+
10 */
\n+
11#ifndef PQXX_H_TRANSACTOR
\n+
12#define PQXX_H_TRANSACTOR
\n+
13
\n+
14#if !defined(PQXX_HEADER_PRE)
\n+
15# error "Include libpqxx headers as <pqxx/header>, not <pqxx/header.hxx>."
\n+
16#endif
\n+
17
\n+
18#include <functional>
\n+
19#include <type_traits>
\n+
20
\n+
21#include "pqxx/connection.hxx"
\n+
22#include "pqxx/transaction.hxx"
\n+
23
\n+
24namespace pqxx
\n+
25{
\n+
69
\n+
71
\n+
100template<typename TRANSACTION_CALLBACK>
\n+
\n+
101inline auto perform(TRANSACTION_CALLBACK &&callback, int attempts = 3)
\n+
102 -> std::invoke_result_t<TRANSACTION_CALLBACK>
\n+
103{
\n+
104 if (attempts <= 0)
\n+
105 throw std::invalid_argument{
\n+
106 "Zero or negative number of attempts passed to pqxx::perform()."};
\n+
107
\n+
108 for (; attempts > 0; --attempts)
\n+
109 {
\n+
110 try
\n+
111 {
\n+
112 return std::invoke(callback);
\n+
113 }
\n+
114 catch (in_doubt_error const &)
\n+
115 {
\n+
116 // Not sure whether transaction went through or not. The last thing in
\n+
117 // the world that we should do now is try again!
\n+
118 throw;
\n+
119 }
\n+
120 catch (statement_completion_unknown const &)
\n+
121 {
\n+
122 // Not sure whether our last statement succeeded. Don't risk running it
\n+
123 // again.
\n+
124 throw;
\n+
125 }
\n+
126 catch (protocol_violation const &)
\n+
127 {
\n+
128 // This is a subclass of broken_connection, but it's not one where
\n+
129 // retrying is likely to do us any good.
\n+
130 throw;
\n+
131 }
\n+
132 catch (broken_connection const &)
\n+
133 {
\n+
134 // Connection failed. May be worth retrying, if the transactor opens its
\n+
135 // own connection.
\n+
136 if (attempts <= 1)
\n+
137 throw;
\n+
138 continue;
\n+
139 }
\n+
140 catch (transaction_rollback const &)
\n+
141 {
\n+
142 // Some error that may well be transient, such as serialization failure
\n+
143 // or deadlock. Worth retrying.
\n+
144 if (attempts <= 1)
\n+
145 throw;
\n+
146 continue;
\n+
147 }
\n+
148 }
\n+
149 throw pqxx::internal_error{"No outcome reached on perform()."};
\n+
150}
\n
\n-
83
\n-
89 [[nodiscard]] PQXX_PURE char const *name() const &;
\n-
90
\n-
92 [[nodiscard]] oid PQXX_PURE type() const;
\n-
93
\n-
95 [[nodiscard]] PQXX_PURE oid table() const;
\n-
96
\n-
98 PQXX_PURE constexpr row_size_type num() const noexcept { return col(); }
\n-
99
\n-
101 [[nodiscard]] PQXX_PURE row_size_type table_column() const;
\n-
103
\n-
109
\n-
\n-
113 [[nodiscard]] PQXX_PURE std::string_view view() const &
\n-
114 {
\n-
115 return std::string_view(c_str(), size());
\n-
116 }
\n-
\n-
117
\n-
119
\n-
128 [[nodiscard]] PQXX_PURE char const *c_str() const &;
\n-
129
\n-
131 [[nodiscard]] PQXX_PURE bool is_null() const noexcept;
\n-
132
\n-
134 [[nodiscard]] PQXX_PURE size_type size() const noexcept;
\n-
135
\n-
137
\n-
140 template<typename T>
\n-
\n-
141 auto to(T &obj) const -> typename std::enable_if_t<
\n-
142 (not std::is_pointer<T>::value or std::is_same<T, char const *>::value),
\n-
143 bool>
\n-
144 {
\n-
145 if (is_null())
\n-
146 {
\n-
147 return false;
\n-
148 }
\n-
149 else
\n-
150 {
\n-
151 auto const bytes{c_str()};
\n-
152 from_string(bytes, obj);
\n-
153 return true;
\n-
154 }
\n-
155 }
\n-
\n-
156
\n-
158
\n-
\n-
163 template<typename... T> bool composite_to(T &...fields) const
\n-
164 {
\n-
165 if (is_null())
\n-
166 {
\n-
167 return false;
\n-
168 }
\n-
169 else
\n-
170 {
\n-
171 parse_composite(m_home.m_encoding, view(), fields...);
\n-
172 return true;
\n-
173 }
\n-
174 }
\n-
\n-
175
\n-
177 template<typename T> bool operator>>(T &obj) const { return to(obj); }
\n-
178
\n-
180
\n-
190 template<typename T>
\n-
\n-
191 auto to(T &obj, T const &default_value) const -> typename std::enable_if_t<
\n-
192 (not std::is_pointer<T>::value or std::is_same<T, char const *>::value),
\n-
193 bool>
\n-
194 {
\n-
195 bool const null{is_null()};
\n-
196 if (null)
\n-
197 obj = default_value;
\n-
198 else
\n-
199 obj = from_string<T>(this->view());
\n-
200 return not null;
\n-
201 }
\n-
\n-
202
\n-
204
\n-
\n-
207 template<typename T> T as(T const &default_value) const
\n-
208 {
\n-
209 if (is_null())
\n-
210 return default_value;
\n-
211 else
\n-
212 return from_string<T>(this->view());
\n-
213 }
\n-
\n-
214
\n-
216
\n-
\n-
221 template<typename T> T as() const
\n-
222 {
\n-
223 if (is_null())
\n-
224 {
\n-
225 if constexpr (not nullness<T>::has_null)
\n-\n-
227 else
\n-
228 return nullness<T>::null();
\n-
229 }
\n-
230 else
\n-
231 {
\n-
232 return from_string<T>(this->view());
\n-
233 }
\n-
234 }
\n-
\n-
235
\n-
237
\n-
240 template<typename T, template<typename> class O = std::optional>
\n-
\n-
241 constexpr O<T> get() const
\n-
242 {
\n-
243 return as<O<T>>();
\n-
244 }
\n-
\n-
245
\n-
247
\n-
\n-
253 array_parser as_array() const &noexcept
\n-
254 {
\n-
255 return array_parser{c_str(), m_home.m_encoding};
\n-
256 }
\n-
\n-
258
\n-
259
\n-
260protected:
\n-
261 constexpr result const &home() const noexcept { return m_home; }
\n-
262 constexpr result::size_type idx() const noexcept { return m_row; }
\n-
263 constexpr row_size_type col() const noexcept { return m_col; }
\n-
264
\n-
265 // TODO: Create gates.
\n-
266 friend class pqxx::result;
\n-
267 friend class pqxx::row;
\n-
\n-\n-
269 result const &r, result_size_type row_num, row_size_type col_num) noexcept
\n-
270 :
\n-
271 m_col{col_num}, m_home{r}, m_row{row_num}
\n-
272 {}
\n-
\n-
273
\n-\n-
279
\n-
280private:
\n-
281 result m_home;
\n-
282 result::size_type m_row;
\n-
283};
\n-
\n-
284
\n-
285
\n-
\n-
286template<> inline bool field::to<std::string>(std::string &obj) const
\n-
287{
\n-
288 bool const null{is_null()};
\n-
289 if (not null)
\n-
290 obj = std::string{view()};
\n-
291 return not null;
\n-
292}
\n-
\n-
293
\n-
294
\n-
295template<>
\n-
\n-
296inline bool field::to<std::string>(
\n-
297 std::string &obj, std::string const &default_value) const
\n-
298{
\n-
299 bool const null{is_null()};
\n-
300 if (null)
\n-
301 obj = default_value;
\n-
302 else
\n-
303 obj = std::string{view()};
\n-
304 return not null;
\n-
305}
\n-
\n-
306
\n-
307
\n-
309
\n-
\n-
314template<> inline bool field::to<char const *>(char const *&obj) const
\n-
315{
\n-
316 bool const null{is_null()};
\n-
317 if (not null)
\n-
318 obj = c_str();
\n-
319 return not null;
\n-
320}
\n-
\n-
321
\n-
322
\n-
\n-
323template<> inline bool field::to<std::string_view>(std::string_view &obj) const
\n-
324{
\n-
325 bool const null{is_null()};
\n-
326 if (not null)
\n-
327 obj = view();
\n-
328 return not null;
\n-
329}
\n-
\n-
330
\n-
331
\n-
332template<>
\n-
\n-
333inline bool field::to<std::string_view>(
\n-
334 std::string_view &obj, std::string_view const &default_value) const
\n-
335{
\n-
336 bool const null{is_null()};
\n-
337 if (null)
\n-
338 obj = default_value;
\n-
339 else
\n-
340 obj = view();
\n-
341 return not null;
\n-
342}
\n-
\n-
343
\n-
344
\n-
\n-
345template<> inline std::string_view field::as<std::string_view>() const
\n-
346{
\n-
347 if (is_null())
\n-
348 PQXX_UNLIKELY
\n-
349 internal::throw_null_conversion(type_name<std::string_view>);
\n-
350 return view();
\n-
351}
\n-
\n-
352
\n-
353
\n-
354template<>
\n-
\n-
355inline std::string_view
\n-
356field::as<std::string_view>(std::string_view const &default_value) const
\n-
357{
\n-
358 return is_null() ? default_value : view();
\n-
359}
\n-
\n-
360
\n-
361
\n-
\n-
362template<> inline bool field::to<zview>(zview &obj) const
\n-
363{
\n-
364 bool const null{is_null()};
\n-
365 if (not null)
\n-
366 obj = zview{c_str(), size()};
\n-
367 return not null;
\n-
368}
\n-
\n-
369
\n-
370
\n-
371template<>
\n-
\n-
372inline bool field::to<zview>(zview &obj, zview const &default_value) const
\n-
373{
\n-
374 bool const null{is_null()};
\n-
375 if (null)
\n-
376 obj = default_value;
\n-
377 else
\n-
378 obj = zview{c_str(), size()};
\n-
379 return not null;
\n-
380}
\n-
\n-
381
\n-
382
\n-
\n-
383template<> inline zview field::as<zview>() const
\n-
384{
\n-
385 if (is_null())
\n-
386 PQXX_UNLIKELY
\n-
387 internal::throw_null_conversion(type_name<zview>);
\n-
388 return zview{c_str(), size()};
\n-
389}
\n-
\n-
390
\n-
391
\n-
\n-
392template<> inline zview field::as<zview>(zview const &default_value) const
\n-
393{
\n-
394 return is_null() ? default_value : zview{c_str(), size()};
\n-
395}
\n-
\n-
396
\n-
397
\n-
398template<typename CHAR = char, typename TRAITS = std::char_traits<CHAR>>
\n-
\n-
399class field_streambuf : public std::basic_streambuf<CHAR, TRAITS>
\n-
400{
\n-
401public:
\n-
402 using char_type = CHAR;
\n-
403 using traits_type = TRAITS;
\n-
404 using int_type = typename traits_type::int_type;
\n-
405 using pos_type = typename traits_type::pos_type;
\n-
406 using off_type = typename traits_type::off_type;
\n-
407 using openmode = std::ios::openmode;
\n-
408 using seekdir = std::ios::seekdir;
\n-
409
\n-
410 explicit field_streambuf(field const &f) : m_field{f} { initialize(); }
\n-
411
\n-
412protected:
\n-
413 virtual int sync() override { return traits_type::eof(); }
\n-
414
\n-
\n-\n-
416 {
\n-
417 return traits_type::eof();
\n-
418 }
\n-
\n-
\n-\n-
420 {
\n-
421 return traits_type::eof();
\n-
422 }
\n-
\n-
423 virtual int_type overflow(int_type) override { return traits_type::eof(); }
\n-
424 virtual int_type underflow() override { return traits_type::eof(); }
\n-
425
\n-
426private:
\n-
427 field const &m_field;
\n-
428
\n-
429 int_type initialize()
\n-
430 {
\n-
431 auto g{static_cast<char_type *>(const_cast<char *>(m_field.c_str()))};
\n-
432 this->setg(g, g, g + std::size(m_field));
\n-
433 return int_type(std::size(m_field));
\n-
434 }
\n-
435};
\n-
\n-
436
\n-
437
\n-
439
\n-
452template<typename CHAR = char, typename TRAITS = std::char_traits<CHAR>>
\n-
\n-
453class basic_fieldstream : public std::basic_istream<CHAR, TRAITS>
\n-
454{
\n-
455 using super = std::basic_istream<CHAR, TRAITS>;
\n-
456
\n-
457public:
\n-
458 using char_type = CHAR;
\n-
459 using traits_type = TRAITS;
\n-
460 using int_type = typename traits_type::int_type;
\n-
461 using pos_type = typename traits_type::pos_type;
\n-
462 using off_type = typename traits_type::off_type;
\n-
463
\n-
\n-
464 [[deprecated("Use field::as<...>() or field::c_str().")]] basic_fieldstream(
\n-
465 field const &f) :
\n-
466 super{nullptr}, m_buf{f}
\n-
467 {
\n-
468 super::init(&m_buf);
\n-
469 }
\n-
\n-
470
\n-
471private:
\n-\n-
473};
\n-
\n-
474
\n-
475
\n-\n-
478
\n-
479
\n-
481
\n-
505template<typename CHAR>
\n-
506[[deprecated(
\n-
507 "Do this by hand, probably with better error checking.")]] inline std::
\n-
508 basic_ostream<CHAR> &
\n-
509 operator<<(std::basic_ostream<CHAR> &s, field const &value)
\n-
510{
\n-
511 s.write(value.c_str(), std::streamsize(std::size(value)));
\n-
512 return s;
\n-
513}
\n-
514
\n-
515
\n-
517
\n-
\n-
520template<typename T> inline T from_string(field const &value)
\n-
521{
\n-
522 if (value.is_null())
\n-
523 {
\n-
524 if constexpr (nullness<T>::has_null)
\n-
525 return nullness<T>::null();
\n-
526 else
\n-\n-
528 }
\n-
529 else
\n-
530 {
\n-
531 return from_string<T>(value.view());
\n-
532 }
\n-
533}
\n-
\n-
534
\n-
535
\n-
537
\n-
543template<>
\n-
\n-
544inline std::nullptr_t from_string<std::nullptr_t>(field const &value)
\n-
545{
\n-
546 if (not value.is_null())
\n-
547 throw conversion_error{
\n-
548 "Extracting non-null field into nullptr_t variable."};
\n-
549 return nullptr;
\n-
550}
\n-
\n-
551
\n-
552
\n-
554template<> PQXX_LIBEXPORT std::string to_string(field const &value);
\n-
555} // namespace pqxx
\n-
556#endif
\n+
151} // namespace pqxx
\n+
153#endif
\n
The home of all libpqxx classes, functions, templates, etc.
Definition array.hxx:33
\n-
std::basic_ostream< CHAR > & operator<<(std::basic_ostream< CHAR > &s, field const &value)
Write a result field to any type of stream.
Definition field.hxx:509
\n-
int row_size_type
Number of fields in a row of database data.
Definition types.hxx:34
\n-
std::size_t field_size_type
Number of bytes in a field of database data.
Definition types.hxx:40
\n-
int result_size_type
Number of rows in a result set.
Definition types.hxx:28
\n-
void parse_composite(pqxx::internal::encoding_group enc, std::string_view text, T &...fields)
Parse a string representation of a value of a composite type.
Definition composite.hxx:35
\n-
std::nullptr_t from_string< std::nullptr_t >(field const &value)
Convert a field's value to nullptr_t.
Definition field.hxx:544
\n-
std::string to_string(field const &value)
Convert a field to a string.
Definition result.cxx:549
\n-
T from_string(field const &value)
Convert a field's value to type T.
Definition field.hxx:520
\n-
void PQXX_COLD throw_null_conversion(std::string const &type)
Definition strconv.cxx:253
\n-
Low-level array parser.
Definition array.hxx:527
\n-
Value conversion failed, e.g. when converting "Hello" to int.
Definition except.hxx:283
\n-
Reference to a field in a result set.
Definition field.hxx:35
\n-
constexpr result const & home() const noexcept
Definition field.hxx:261
\n-
PQXX_PURE size_type size() const noexcept
Return number of bytes taken up by the field's value.
Definition field.cxx:77
\n-
T as(T const &default_value) const
Return value as object of given type, or default value if null.
Definition field.hxx:207
\n-
row_size_type m_col
Definition field.hxx:278
\n-
array_parser as_array() const &noexcept
Parse the field as an SQL array.
Definition field.hxx:253
\n-
auto to(T &obj, T const &default_value) const -> typename std::enable_if_t<(not std::is_pointer< T >::value or std::is_same< T, char const * >::value), bool >
Read value into obj; or if null, use default value and return false.
Definition field.hxx:191
\n-
field_size_type size_type
Definition field.hxx:37
\n-
bool operator>>(T &obj) const
Read value into obj; or leave obj untouched and return false if null.
Definition field.hxx:177
\n-
PQXX_PURE char const * c_str() const &
Read as plain C string.
Definition field.cxx:65
\n-
T as() const
Return value as object of given type, or throw exception if null.
Definition field.hxx:221
\n-
field(result const &r, result_size_type row_num, row_size_type col_num) noexcept
Definition field.hxx:268
\n-
constexpr row_size_type col() const noexcept
Definition field.hxx:263
\n-
PQXX_PURE std::string_view view() const &
Read as string_view, or an empty one if null.
Definition field.hxx:113
\n-
bool composite_to(T &...fields) const
Read field as a composite value, write its components into fields.
Definition field.hxx:163
\n-
field() noexcept=default
Constructor. Do not call this yourself; libpqxx will do it for you.
\n-
PQXX_PURE bool is_null() const noexcept
Is this field's value null?
Definition field.cxx:71
\n-
constexpr O< T > get() const
Return value wrapped in some optional type (empty for nulls).
Definition field.hxx:241
\n-
constexpr result::size_type idx() const noexcept
Definition field.hxx:262
\n-
Definition field.hxx:400
\n-
TRAITS traits_type
Definition field.hxx:403
\n-
typename traits_type::off_type off_type
Definition field.hxx:406
\n-
field_streambuf(field const &f)
Definition field.hxx:410
\n-
virtual pos_type seekoff(off_type, seekdir, openmode) override
Definition field.hxx:415
\n-
virtual pos_type seekpos(pos_type, openmode) override
Definition field.hxx:419
\n-
std::ios::openmode openmode
Definition field.hxx:407
\n-
virtual int_type overflow(int_type) override
Definition field.hxx:423
\n-
typename traits_type::pos_type pos_type
Definition field.hxx:405
\n-
virtual int sync() override
Definition field.hxx:413
\n-
typename traits_type::int_type int_type
Definition field.hxx:404
\n-
virtual int_type underflow() override
Definition field.hxx:424
\n-
CHAR char_type
Definition field.hxx:402
\n-
std::ios::seekdir seekdir
Definition field.hxx:408
\n-
Input stream that gets its data from a result field.
Definition field.hxx:454
\n-
TRAITS traits_type
Definition field.hxx:459
\n-
basic_fieldstream(field const &f)
Definition field.hxx:464
\n-
typename traits_type::pos_type pos_type
Definition field.hxx:461
\n-
typename traits_type::off_type off_type
Definition field.hxx:462
\n-
typename traits_type::int_type int_type
Definition field.hxx:460
\n-
CHAR char_type
Definition field.hxx:458
\n-
Result set containing data returned by a query or command.
Definition result.hxx:73
\n-
result_size_type size_type
Definition result.hxx:75
\n-
Reference to one row in a result.
Definition row.hxx:47
\n-
Traits describing a type's "null value," if any.
Definition strconv.hxx:93
\n-
static TYPE null()
Return a null value.
\n-
Marker-type wrapper: zero-terminated std::string_view.
Definition zview.hxx:38
\n+
auto perform(TRANSACTION_CALLBACK &&callback, int attempts=3) -> std::invoke_result_t< TRANSACTION_CALLBACK >
Simple way to execute a transaction with automatic retry.
Definition transactor.hxx:101
\n+
Exception class for lost or failed backend connection.
Definition except.hxx:81
\n+
Exception class for micommunication with the server.
Definition except.hxx:103
\n+
"Help, I don't know whether transaction was committed successfully!"
Definition except.hxx:165
\n+
The backend saw itself forced to roll back the ongoing transaction.
Definition except.hxx:178
\n+
We can't tell whether our last statement succeeded.
Definition except.hxx:214
\n+
Internal error in libpqxx library.
Definition except.hxx:242
\n
\n
\n \n
\n \n
\n \n \n", "details": [{"source1": "html2text {}", "source2": "html2text {}", "unified_diff": "@@ -1,613 +1,118 @@\n \n \n \n \n \n libpqxx\u00a07.8.1\n \n-field.hxx\n- 1/* Definitions for the pqxx::field class.\n+transactor.hxx\n+ 1/* Transactor framework, a wrapper for safely retryable transactions.\n 2 *\n- 3 * pqxx::field refers to a field in a query result.\n+ 3 * DO NOT INCLUDE THIS FILE DIRECTLY; include pqxx/transactor instead.\n 4 *\n- 5 * DO NOT INCLUDE THIS FILE DIRECTLY; include pqxx/field instead.\n+ 5 * Copyright (c) 2000-2023, Jeroen T. Vermeulen.\n 6 *\n- 7 * Copyright (c) 2000-2023, Jeroen T. Vermeulen.\n- 8 *\n- 9 * See COPYING for copyright license. If you did not receive a file called\n- 10 * COPYING with this source code, please notify the distributor of this\n- 11 * mistake, or contact the author.\n- 12 */\n- 13#ifndef PQXX_H_FIELD\n- 14#define PQXX_H_FIELD\n- 15\n- 16#if !defined(PQXX_HEADER_PRE)\n- 17# error \"Include libpqxx headers as , not .\"\n- 18#endif\n- 19\n- 20#include \n- 21\n- 22#include \"pqxx/array.hxx\"\n- 23#include \"pqxx/composite.hxx\"\n- 24#include \"pqxx/result.hxx\"\n- 25#include \"pqxx/strconv.hxx\"\n- 26#include \"pqxx/types.hxx\"\n- 27\n- 28namespace pqxx\n- 29{\n- 31\n-34class PQXX_LIBEXPORT field\n- 35{\n- 36public:\n-37 using size_type = field_size_type;\n- 38\n- 40\n- 44 [[deprecated(\n- 45 \"Do not construct fields yourself. Get them from the row.\")]] field(row\n-const &r, row_size_type c) noexcept;\n- 46\n- 48 [[deprecated(\n- 49 \"Do not construct fields yourself. Get them from the \"\n-50 \"row.\")]] field() noexcept = default;\n- 51\n- 57\n- 73 [[nodiscard]] PQXX_PURE bool operator==(field const &) const noexcept;\n- 74\n- 76\n-78 [[nodiscard]] PQXX_PURE bool operator!=(field const &rhs) const noexcept\n- 79 {\n- 80 return not operator==(rhs);\n- 81 }\n- 83\n- 89 [[nodiscard]] PQXX_PURE char const *name() const &;\n- 90\n- 92 [[nodiscard]] oid PQXX_PURE type() const;\n- 93\n- 95 [[nodiscard]] PQXX_PURE oid table() const;\n- 96\n-98 PQXX_PURE constexpr row_size_type num() const noexcept { return col(); }\n- 99\n- 101 [[nodiscard]] PQXX_PURE row_size_type table_column() const;\n- 103\n- 109\n-113 [[nodiscard]] PQXX_PURE std::string_view view() const &\n- 114 {\n- 115 return std::string_view(c_str(), size());\n- 116 }\n- 117\n- 119\n- 128 [[nodiscard]] PQXX_PURE char const *c_str() const &;\n- 129\n- 131 [[nodiscard]] PQXX_PURE bool is_null() const noexcept;\n- 132\n- 134 [[nodiscard]] PQXX_PURE size_type size() const noexcept;\n- 135\n- 137\n- 140 template\n-141 auto to(T &obj) const -> typename std::enable_if_t<\n- 142 (not std::is_pointer::value or std::is_same::value),\n- 143 bool>\n- 144 {\n- 145 if (is_null())\n- 146 {\n- 147 return false;\n+ 7 * See COPYING for copyright license. If you did not receive a file called\n+ 8 * COPYING with this source code, please notify the distributor of this\n+ 9 * mistake, or contact the author.\n+ 10 */\n+ 11#ifndef PQXX_H_TRANSACTOR\n+ 12#define PQXX_H_TRANSACTOR\n+ 13\n+ 14#if !defined(PQXX_HEADER_PRE)\n+ 15# error \"Include libpqxx headers as , not .\"\n+ 16#endif\n+ 17\n+ 18#include \n+ 19#include \n+ 20\n+ 21#include \"pqxx/connection.hxx\"\n+ 22#include \"pqxx/transaction.hxx\"\n+ 23\n+ 24namespace pqxx\n+ 25{\n+ 69\n+ 71\n+ 100template\n+101inline auto perform(TRANSACTION_CALLBACK &&callback, int attempts = 3)\n+ 102 -> std::invoke_result_t\n+ 103{\n+ 104 if (attempts <= 0)\n+ 105 throw std::invalid_argument{\n+ 106 \"Zero or negative number of attempts passed to pqxx::perform().\"};\n+ 107\n+ 108 for (; attempts > 0; --attempts)\n+ 109 {\n+ 110 try\n+ 111 {\n+ 112 return std::invoke(callback);\n+ 113 }\n+ 114 catch (in_doubt_error const &)\n+ 115 {\n+ 116 // Not sure whether transaction went through or not. The last thing in\n+ 117 // the world that we should do now is try again!\n+ 118 throw;\n+ 119 }\n+ 120 catch (statement_completion_unknown const &)\n+ 121 {\n+ 122 // Not sure whether our last statement succeeded. Don't risk running it\n+ 123 // again.\n+ 124 throw;\n+ 125 }\n+ 126 catch (protocol_violation const &)\n+ 127 {\n+ 128 // This is a subclass of broken_connection, but it's not one where\n+ 129 // retrying is likely to do us any good.\n+ 130 throw;\n+ 131 }\n+ 132 catch (broken_connection const &)\n+ 133 {\n+ 134 // Connection failed. May be worth retrying, if the transactor opens its\n+ 135 // own connection.\n+ 136 if (attempts <= 1)\n+ 137 throw;\n+ 138 continue;\n+ 139 }\n+ 140 catch (transaction_rollback const &)\n+ 141 {\n+ 142 // Some error that may well be transient, such as serialization failure\n+ 143 // or deadlock. Worth retrying.\n+ 144 if (attempts <= 1)\n+ 145 throw;\n+ 146 continue;\n+ 147 }\n 148 }\n- 149 else\n- 150 {\n- 151 auto const bytes{c_str()};\n- 152 from_string(bytes, obj);\n- 153 return true;\n- 154 }\n- 155 }\n- 156\n- 158\n-163 template bool composite_to(T &...fields) const\n- 164 {\n- 165 if (is_null())\n- 166 {\n- 167 return false;\n- 168 }\n- 169 else\n- 170 {\n- 171 parse_composite(m_home.m_encoding, view(), fields...);\n- 172 return true;\n- 173 }\n- 174 }\n- 175\n-177 template bool operator>>(T &obj) const { return to(obj); }\n- 178\n- 180\n- 190 template\n-191 auto to(T &obj, T const &default_value) const -> typename std::enable_if_t<\n- 192 (not std::is_pointer::value or std::is_same::value),\n- 193 bool>\n- 194 {\n- 195 bool const null{is_null()};\n- 196 if (null)\n- 197 obj = default_value;\n- 198 else\n- 199 obj = from_string(this->view());\n- 200 return not null;\n- 201 }\n- 202\n- 204\n-207 template T as(T const &default_value) const\n- 208 {\n- 209 if (is_null())\n- 210 return default_value;\n- 211 else\n- 212 return from_string(this->view());\n- 213 }\n- 214\n- 216\n-221 template T as() const\n- 222 {\n- 223 if (is_null())\n- 224 {\n- 225 if constexpr (not nullness::has_null)\n- 226 internal::throw_null_conversion(type_name);\n- 227 else\n- 228 return nullness::null();\n- 229 }\n- 230 else\n- 231 {\n- 232 return from_string(this->view());\n- 233 }\n- 234 }\n- 235\n- 237\n- 240 template class O = std::optional>\n-241 constexpr O get() const\n- 242 {\n- 243 return as>();\n- 244 }\n- 245\n- 247\n-253 array_parser as_array() const &noexcept\n- 254 {\n- 255 return array_parser{c_str(), m_home.m_encoding};\n- 256 }\n- 258\n- 259\n- 260protected:\n-261 constexpr result const &home() const noexcept { return m_home; }\n-262 constexpr result::size_type idx() const noexcept { return m_row; }\n-263 constexpr row_size_type col() const noexcept { return m_col; }\n- 264\n- 265 // TODO: Create gates.\n-266 friend class pqxx::result;\n-267 friend class pqxx::row;\n-268 field(\n- 269 result const &r, result_size_type row_num, row_size_type col_num) noexcept\n- 270 :\n- 271 m_col{col_num}, m_home{r}, m_row{row_num}\n- 272 {}\n- 273\n-278 row_size_type m_col;\n- 279\n- 280private:\n- 281 result m_home;\n- 282 result::size_type m_row;\n- 283};\n- 284\n- 285\n-286template<> inline bool field::to(std::string &obj) const\n- 287{\n- 288 bool const null{is_null()};\n- 289 if (not null)\n- 290 obj = std::string{view()};\n- 291 return not null;\n- 292}\n- 293\n- 294\n- 295template<>\n-296inline bool field::to(\n- 297 std::string &obj, std::string const &default_value) const\n- 298{\n- 299 bool const null{is_null()};\n- 300 if (null)\n- 301 obj = default_value;\n- 302 else\n- 303 obj = std::string{view()};\n- 304 return not null;\n- 305}\n- 306\n- 307\n- 309\n-314template<> inline bool field::to(char const *&obj) const\n- 315{\n- 316 bool const null{is_null()};\n- 317 if (not null)\n- 318 obj = c_str();\n- 319 return not null;\n- 320}\n- 321\n- 322\n-323template<> inline bool field::to(std::string_view &obj)\n-const\n- 324{\n- 325 bool const null{is_null()};\n- 326 if (not null)\n- 327 obj = view();\n- 328 return not null;\n- 329}\n- 330\n- 331\n- 332template<>\n-333inline bool field::to(\n- 334 std::string_view &obj, std::string_view const &default_value) const\n- 335{\n- 336 bool const null{is_null()};\n- 337 if (null)\n- 338 obj = default_value;\n- 339 else\n- 340 obj = view();\n- 341 return not null;\n- 342}\n- 343\n- 344\n-345template<> inline std::string_view field::as() const\n- 346{\n- 347 if (is_null())\n- 348 PQXX_UNLIKELY\n- 349 internal::throw_null_conversion(type_name);\n- 350 return view();\n- 351}\n- 352\n- 353\n- 354template<>\n-355inline std::string_view\n- 356field::as(std::string_view const &default_value) const\n- 357{\n- 358 return is_null() ? default_value : view();\n- 359}\n- 360\n- 361\n-362template<> inline bool field::to(zview &obj) const\n- 363{\n- 364 bool const null{is_null()};\n- 365 if (not null)\n- 366 obj = zview{c_str(), size()};\n- 367 return not null;\n- 368}\n- 369\n- 370\n- 371template<>\n-372inline bool field::to(zview &obj, zview const &default_value) const\n- 373{\n- 374 bool const null{is_null()};\n- 375 if (null)\n- 376 obj = default_value;\n- 377 else\n- 378 obj = zview{c_str(), size()};\n- 379 return not null;\n- 380}\n- 381\n- 382\n-383template<> inline zview field::as() const\n- 384{\n- 385 if (is_null())\n- 386 PQXX_UNLIKELY\n- 387 internal::throw_null_conversion(type_name);\n- 388 return zview{c_str(), size()};\n- 389}\n- 390\n- 391\n-392template<> inline zview field::as(zview const &default_value) const\n- 393{\n- 394 return is_null() ? default_value : zview{c_str(), size()};\n- 395}\n- 396\n- 397\n- 398template>\n-399class field_streambuf : public std::basic_streambuf\n- 400{\n- 401public:\n-402 using char_type = CHAR;\n-403 using traits_type = TRAITS;\n-404 using int_type = typename traits_type::int_type;\n-405 using pos_type = typename traits_type::pos_type;\n-406 using off_type = typename traits_type::off_type;\n-407 using openmode = std::ios::openmode;\n-408 using seekdir = std::ios::seekdir;\n- 409\n-410 explicit field_streambuf(field const &f) : m_field{f} { initialize(); }\n- 411\n- 412protected:\n-413 virtual int sync() override { return traits_type::eof(); }\n- 414\n-415 virtual pos_type seekoff(off_type, seekdir, openmode) override\n- 416 {\n- 417 return traits_type::eof();\n- 418 }\n-419 virtual pos_type seekpos(pos_type, openmode) override\n- 420 {\n- 421 return traits_type::eof();\n- 422 }\n-423 virtual int_type overflow(int_type) override { return traits_type::eof(); }\n-424 virtual int_type underflow() override { return traits_type::eof(); }\n- 425\n- 426private:\n- 427 field const &m_field;\n- 428\n- 429 int_type initialize()\n- 430 {\n- 431 auto g{static_cast(const_cast(m_field.c_str()))};\n- 432 this->setg(g, g, g + std::size(m_field));\n- 433 return int_type(std::size(m_field));\n- 434 }\n- 435};\n- 436\n- 437\n- 439\n- 452template>\n-453class basic_fieldstream : public std::basic_istream\n- 454{\n- 455 using super = std::basic_istream;\n- 456\n- 457public:\n-458 using char_type = CHAR;\n-459 using traits_type = TRAITS;\n-460 using int_type = typename traits_type::int_type;\n-461 using pos_type = typename traits_type::pos_type;\n-462 using off_type = typename traits_type::off_type;\n- 463\n-464 [[deprecated(\"Use field::as<...>() or field::c_str().\")]] basic_fieldstream\n-(\n- 465 field const &f) :\n- 466 super{nullptr}, m_buf{f}\n- 467 {\n- 468 super::init(&m_buf);\n- 469 }\n- 470\n- 471private:\n- 472 field_streambuf m_buf;\n- 473};\n- 474\n- 475\n-477using fieldstream = basic_fieldstream;\n- 478\n- 479\n- 481\n- 505template\n- 506[[deprecated(\n- 507 \"Do this by hand, probably with better error checking.\")]] inline std::\n- 508 basic_ostream &\n- 509 operator<<(std::basic_ostream &s, field const &value)\n- 510{\n- 511 s.write(value.c_str(), std::streamsize(std::size(value)));\n- 512 return s;\n- 513}\n- 514\n- 515\n- 517\n-520template inline T from_string(field const &value)\n- 521{\n- 522 if (value.is_null())\n- 523 {\n- 524 if constexpr (nullness::has_null)\n- 525 return nullness::null();\n- 526 else\n- 527 internal::throw_null_conversion(type_name);\n- 528 }\n- 529 else\n- 530 {\n- 531 return from_string(value.view());\n- 532 }\n- 533}\n- 534\n- 535\n- 537\n- 543template<>\n-544inline std::nullptr_t from_string(field const &value)\n- 545{\n- 546 if (not value.is_null())\n- 547 throw conversion_error{\n- 548 \"Extracting non-null field into nullptr_t variable.\"};\n- 549 return nullptr;\n- 550}\n- 551\n- 552\n- 554template<> PQXX_LIBEXPORT std::string to_string(field const &value);\n- 555} // namespace pqxx\n- 556#endif\n+ 149 throw pqxx::internal_error{\"No outcome reached on perform().\"};\n+ 150}\n+ 151} // namespace pqxx\n+ 153#endif\n pqxx\n The home of all libpqxx classes, functions, templates, etc.\n Definition array.hxx:33\n-pqxx::operator<<\n-std::basic_ostream< CHAR > & operator<<(std::basic_ostream< CHAR > &s, field\n-const &value)\n-Write a result field to any type of stream.\n-Definition field.hxx:509\n-pqxx::row_size_type\n-int row_size_type\n-Number of fields in a row of database data.\n-Definition types.hxx:34\n-pqxx::field_size_type\n-std::size_t field_size_type\n-Number of bytes in a field of database data.\n-Definition types.hxx:40\n-pqxx::result_size_type\n-int result_size_type\n-Number of rows in a result set.\n-Definition types.hxx:28\n-pqxx::parse_composite\n-void parse_composite(pqxx::internal::encoding_group enc, std::string_view text,\n-T &...fields)\n-Parse a string representation of a value of a composite type.\n-Definition composite.hxx:35\n-pqxx::from_string<_std::nullptr_t_>\n-std::nullptr_t from_string< std::nullptr_t >(field const &value)\n-Convert a field's value to nullptr_t.\n-Definition field.hxx:544\n-pqxx::to_string\n-std::string to_string(field const &value)\n-Convert a field to a string.\n-Definition result.cxx:549\n-pqxx::from_string\n-T from_string(field const &value)\n-Convert a field's value to type T.\n-Definition field.hxx:520\n-pqxx::internal::throw_null_conversion\n-void PQXX_COLD throw_null_conversion(std::string const &type)\n-Definition strconv.cxx:253\n-pqxx::array_parser\n-Low-level array parser.\n-Definition array.hxx:527\n-pqxx::conversion_error\n-Value conversion failed, e.g. when converting \"Hello\" to int.\n-Definition except.hxx:283\n-pqxx::field\n-Reference to a field in a result set.\n-Definition field.hxx:35\n-pqxx::field::home\n-constexpr result const & home() const noexcept\n-Definition field.hxx:261\n-pqxx::field::size\n-PQXX_PURE size_type size() const noexcept\n-Return number of bytes taken up by the field's value.\n-Definition field.cxx:77\n-pqxx::field::as\n-T as(T const &default_value) const\n-Return value as object of given type, or default value if null.\n-Definition field.hxx:207\n-pqxx::field::m_col\n-row_size_type m_col\n-Definition field.hxx:278\n-pqxx::field::as_array\n-array_parser as_array() const &noexcept\n-Parse the field as an SQL array.\n-Definition field.hxx:253\n-pqxx::field::to\n-auto to(T &obj, T const &default_value) const -> typename std::enable_if_t<(not\n-std::is_pointer< T >::value or std::is_same< T, char const * >::value), bool >\n-Read value into obj; or if null, use default value and return false.\n-Definition field.hxx:191\n-pqxx::field::size_type\n-field_size_type size_type\n-Definition field.hxx:37\n-pqxx::field::operator>>\n-bool operator>>(T &obj) const\n-Read value into obj; or leave obj untouched and return false if null.\n-Definition field.hxx:177\n-pqxx::field::c_str\n-PQXX_PURE char const * c_str() const &\n-Read as plain C string.\n-Definition field.cxx:65\n-pqxx::field::as\n-T as() const\n-Return value as object of given type, or throw exception if null.\n-Definition field.hxx:221\n-pqxx::field::field\n-field(result const &r, result_size_type row_num, row_size_type col_num)\n-noexcept\n-Definition field.hxx:268\n-pqxx::field::col\n-constexpr row_size_type col() const noexcept\n-Definition field.hxx:263\n-pqxx::field::view\n-PQXX_PURE std::string_view view() const &\n-Read as string_view, or an empty one if null.\n-Definition field.hxx:113\n-pqxx::field::composite_to\n-bool composite_to(T &...fields) const\n-Read field as a composite value, write its components into fields.\n-Definition field.hxx:163\n-pqxx::field::field\n-field() noexcept=default\n-Constructor. Do not call this yourself; libpqxx will do it for you.\n-pqxx::field::is_null\n-PQXX_PURE bool is_null() const noexcept\n-Is this field's value null?\n-Definition field.cxx:71\n-pqxx::field::get\n-constexpr O< T > get() const\n-Return value wrapped in some optional type (empty for nulls).\n-Definition field.hxx:241\n-pqxx::field::idx\n-constexpr result::size_type idx() const noexcept\n-Definition field.hxx:262\n-pqxx::field_streambuf\n-Definition field.hxx:400\n-pqxx::field_streambuf::traits_type\n-TRAITS traits_type\n-Definition field.hxx:403\n-pqxx::field_streambuf::off_type\n-typename traits_type::off_type off_type\n-Definition field.hxx:406\n-pqxx::field_streambuf::field_streambuf\n-field_streambuf(field const &f)\n-Definition field.hxx:410\n-pqxx::field_streambuf::seekoff\n-virtual pos_type seekoff(off_type, seekdir, openmode) override\n-Definition field.hxx:415\n-pqxx::field_streambuf::seekpos\n-virtual pos_type seekpos(pos_type, openmode) override\n-Definition field.hxx:419\n-pqxx::field_streambuf::openmode\n-std::ios::openmode openmode\n-Definition field.hxx:407\n-pqxx::field_streambuf::overflow\n-virtual int_type overflow(int_type) override\n-Definition field.hxx:423\n-pqxx::field_streambuf::pos_type\n-typename traits_type::pos_type pos_type\n-Definition field.hxx:405\n-pqxx::field_streambuf::sync\n-virtual int sync() override\n-Definition field.hxx:413\n-pqxx::field_streambuf::int_type\n-typename traits_type::int_type int_type\n-Definition field.hxx:404\n-pqxx::field_streambuf::underflow\n-virtual int_type underflow() override\n-Definition field.hxx:424\n-pqxx::field_streambuf::char_type\n-CHAR char_type\n-Definition field.hxx:402\n-pqxx::field_streambuf::seekdir\n-std::ios::seekdir seekdir\n-Definition field.hxx:408\n-pqxx::basic_fieldstream\n-Input stream that gets its data from a result field.\n-Definition field.hxx:454\n-pqxx::basic_fieldstream::traits_type\n-TRAITS traits_type\n-Definition field.hxx:459\n-pqxx::basic_fieldstream::basic_fieldstream\n-basic_fieldstream(field const &f)\n-Definition field.hxx:464\n-pqxx::basic_fieldstream::pos_type\n-typename traits_type::pos_type pos_type\n-Definition field.hxx:461\n-pqxx::basic_fieldstream::off_type\n-typename traits_type::off_type off_type\n-Definition field.hxx:462\n-pqxx::basic_fieldstream::int_type\n-typename traits_type::int_type int_type\n-Definition field.hxx:460\n-pqxx::basic_fieldstream::char_type\n-CHAR char_type\n-Definition field.hxx:458\n-pqxx::result\n-Result set containing data returned by a query or command.\n-Definition result.hxx:73\n-pqxx::result::size_type\n-result_size_type size_type\n-Definition result.hxx:75\n-pqxx::row\n-Reference to one row in a result.\n-Definition row.hxx:47\n-pqxx::nullness\n-Traits describing a type's \"null value,\" if any.\n-Definition strconv.hxx:93\n-pqxx::nullness::null\n-static TYPE null()\n-Return a null value.\n-pqxx::zview\n-Marker-type wrapper: zero-terminated std::string_view.\n-Definition zview.hxx:38\n+pqxx::perform\n+auto perform(TRANSACTION_CALLBACK &&callback, int attempts=3) -> std::\n+invoke_result_t< TRANSACTION_CALLBACK >\n+Simple way to execute a transaction with automatic retry.\n+Definition transactor.hxx:101\n+pqxx::broken_connection\n+Exception class for lost or failed backend connection.\n+Definition except.hxx:81\n+pqxx::protocol_violation\n+Exception class for micommunication with the server.\n+Definition except.hxx:103\n+pqxx::in_doubt_error\n+\"Help, I don't know whether transaction was committed successfully!\"\n+Definition except.hxx:165\n+pqxx::transaction_rollback\n+The backend saw itself forced to roll back the ongoing transaction.\n+Definition except.hxx:178\n+pqxx::statement_completion_unknown\n+We can't tell whether our last statement succeeded.\n+Definition except.hxx:214\n+pqxx::internal_error\n+Internal error in libpqxx library.\n+Definition except.hxx:242\n * include\n * pqxx\n- * field.hxx\n+ * transactor.hxx\n * Generated by [doxygen] 1.9.8\n"}]}, {"source1": "./usr/share/doc/libpqxx-doc/html/a00026_source.html", "source2": "./usr/share/doc/libpqxx-doc/html/a00026_source.html", "unified_diff": "@@ -1,15 +1,15 @@\n \n \n \n \n \n \n \n-libpqxx: connection.hxx Source File\n+libpqxx: cursor.hxx Source File\n \n \n \n \n \n \n \n@@ -60,822 +60,373 @@\n \n
\n
\n-
connection.hxx
\n+
cursor.hxx
\n
\n
\n-
1/* Definition of the connection class.
\n+
1/* Definition of the iterator/container-style cursor classes.
\n
2 *
\n-
3 * pqxx::connection encapsulates a connection to a database.
\n+
3 * C++-style wrappers for SQL cursors.
\n
4 *
\n-
5 * DO NOT INCLUDE THIS FILE DIRECTLY; include pqxx/connection instead.
\n+
5 * DO NOT INCLUDE THIS FILE DIRECTLY; include pqxx/cursor instead.
\n
6 *
\n
7 * Copyright (c) 2000-2023, Jeroen T. Vermeulen.
\n
8 *
\n
9 * See COPYING for copyright license. If you did not receive a file called
\n
10 * COPYING with this source code, please notify the distributor of this
\n
11 * mistake, or contact the author.
\n
12 */
\n-
13#ifndef PQXX_H_CONNECTION
\n-
14#define PQXX_H_CONNECTION
\n+
13#ifndef PQXX_H_CURSOR
\n+
14#define PQXX_H_CURSOR
\n
15
\n
16#if !defined(PQXX_HEADER_PRE)
\n
17# error "Include libpqxx headers as <pqxx/header>, not <pqxx/header.hxx>."
\n
18#endif
\n
19
\n-
20#include <cstddef>
\n-
21#include <ctime>
\n-
22#include <initializer_list>
\n-
23#include <list>
\n-
24#include <map>
\n-
25#include <memory>
\n-
26#include <string_view>
\n-
27#include <tuple>
\n-
28
\n-
29// Double-check in order to suppress an overzealous Visual C++ warning (#418).
\n-
30#if defined(PQXX_HAVE_CONCEPTS) && __has_include(<ranges>)
\n-
31# include <ranges>
\n-
32#endif
\n-
33
\n-
34#include "pqxx/errorhandler.hxx"
\n-
35#include "pqxx/except.hxx"
\n-
36#include "pqxx/internal/concat.hxx"
\n-
37#include "pqxx/params.hxx"
\n-
38#include "pqxx/separated_list.hxx"
\n-
39#include "pqxx/strconv.hxx"
\n-
40#include "pqxx/types.hxx"
\n-
41#include "pqxx/util.hxx"
\n-
42#include "pqxx/zview.hxx"
\n-
43
\n-
44
\n-
75namespace pqxx::internal
\n-
76{
\n-
77class sql_cursor;
\n-
78
\n-
79#if defined(PQXX_HAVE_CONCEPTS)
\n-
81template<typename T>
\n-
82concept ZKey_ZValues =
\n-
83 std::ranges::input_range<T> and
\n-
84 requires(T t) {
\n-
85 {
\n-
86 std::cbegin(t)
\n-
87 };
\n-
88 {
\n-
89 std::get<0>(*std::cbegin(t))
\n-
90 } -> ZString;
\n-
91 {
\n-
92 std::get<1>(*std::cbegin(t))
\n-
93 } -> ZString;
\n-
94 } and
\n-
95 std::tuple_size_v<typename std::ranges::iterator_t<T>::value_type> == 2;
\n-
96#endif // PQXX_HAVE_CONCEPTS
\n-
97
\n+
20#include <limits>
\n+
21#include <stdexcept>
\n+
22
\n+
23#include "pqxx/result.hxx"
\n+
24#include "pqxx/transaction_base.hxx"
\n+
25
\n+
26
\n+
27namespace pqxx
\n+
28{
\n+
30
\n+
\n+
41class PQXX_LIBEXPORT cursor_base
\n+
42{
\n+
43public:
\n+\n+\n+
46
\n+
48
\n+
\n+\n+
52 {
\n+\n+
56 random_access
\n+
57 };
\n+
\n+
58
\n+
60
\n+
\n+\n+
64 {
\n+\n+
68 update
\n+
69 };
\n+
\n+
70
\n+
72
\n+
\n+\n+
88 {
\n+\n+
92 loose
\n+
93 };
\n+
\n+
94
\n+
95 cursor_base() = delete;
\n+
96 cursor_base(cursor_base const &) = delete;
\n+
97 cursor_base &operator=(cursor_base const &) = delete;
\n
98
\n-
100
\n-
107void PQXX_COLD PQXX_LIBEXPORT skip_init_ssl(int flags) noexcept;
\n-
108} // namespace pqxx::internal
\n-
109
\n-
110
\n-
\n-\n-
112{
\n-
113class connection_dbtransaction;
\n-
114class connection_errorhandler;
\n-
115class connection_largeobject;
\n-
116class connection_notification_receiver;
\n-
117class connection_pipeline;
\n-
118class connection_sql_cursor;
\n-
119struct connection_stream_from;
\n-
120class connection_stream_to;
\n-
121class connection_transaction;
\n-
122class const_connection_largeobject;
\n-
123} // namespace pqxx::internal::gate
\n+
103
\n+
105
\n+
\n+
108 [[nodiscard]] static constexpr difference_type all() noexcept
\n+
109 {
\n+
110 return (std::numeric_limits<int>::max)() - 1;
\n+
111 }
\n+
\n+
112
\n+
114
\n+
116 [[nodiscard]] static constexpr difference_type next() noexcept { return 1; }
\n+
117
\n+
119
\n+
\n+
121 [[nodiscard]] static constexpr difference_type prior() noexcept
\n+
122 {
\n+
123 return -1;
\n+
124 }
\n
\n-
124
\n
125
\n-
126namespace pqxx
\n-
127{
\n-
129
\n-
\n-
136enum skip_init : int
\n-
137{
\n-\n-
140
\n-\n-
143
\n-\n-
146};
\n-
\n-
147
\n-
148
\n-
150
\n-
\n-
173template<skip_init... SKIP> inline void skip_init_ssl() noexcept
\n-
174{
\n-
175 // (Normalise skip flags to one per.)
\n-
176 pqxx::internal::skip_init_ssl(((1 << SKIP) | ...));
\n-
177}
\n-
\n-
178
\n-
179
\n-
181
\n-
188using table_path = std::initializer_list<std::string_view>;
\n-
189
\n+
127
\n+
\n+
129 [[nodiscard]] static constexpr difference_type backward_all() noexcept
\n+
130 {
\n+
131 return (std::numeric_limits<int>::min)() + 1;
\n+
132 }
\n+
\n+
133
\n+
135
\n+
137
\n+
\n+
142 [[nodiscard]] constexpr std::string const &name() const noexcept
\n+
143 {
\n+
144 return m_name;
\n+
145 }
\n+
\n+
146
\n+
147protected:
\n+
148 cursor_base(connection &, std::string_view Name, bool embellish_name = true);
\n+
149
\n+
150 std::string const m_name;
\n+
151};
\n+
\n+
152} // namespace pqxx
\n+
153
\n+
154
\n+
155#include <pqxx/internal/sql_cursor.hxx>
\n+
156
\n+
157
\n+
158namespace pqxx
\n+
159{
\n+
161
\n+
167template<cursor_base::update_policy up, cursor_base::ownership_policy op>
\n+
\n+\n+
169{
\n+
170public:
\n+\n+\n+
173
\n+
175
\n+
\n+\n+
184 transaction_base &tx, std::string_view query, std::string_view cname,
\n+
185 bool hold) :
\n+
186 m_cur{tx, query, cname, cursor_base::random_access, up, op, hold}
\n+
187 {}
\n+
\n+
188
\n
190
\n-
192[[nodiscard,
\n-
193 deprecated("Use connection::encrypt_password instead.")]] std::string
\n-
194 PQXX_LIBEXPORT
\n-
195 encrypt_password(char const user[], char const password[]);
\n-
196
\n-
198[[nodiscard,
\n-
199 deprecated("Use connection::encrypt_password instead.")]] inline std::string
\n-
\n-\n-
201{
\n-
202#include "pqxx/internal/ignore-deprecated-pre.hxx"
\n-
203 return encrypt_password(user.c_str(), password.c_str());
\n-
204#include "pqxx/internal/ignore-deprecated-post.hxx"
\n-
205}
\n-
\n-
206
\n-
207
\n-
\n-
209enum class error_verbosity : int
\n-
210{
\n-
211 // These values must match those in libpq's PGVerbosity enum.
\n-
212 terse = 0,
\n-
213 normal = 1,
\n-
214 verbose = 2
\n-
215};
\n+
\n+
196 stateless_cursor(transaction_base &tx, std::string_view adopted_cursor) :
\n+
197 m_cur{tx, adopted_cursor, op}
\n+
198 {
\n+
199 // Put cursor in known position
\n+
200 m_cur.move(cursor_base::backward_all());
\n+
201 }
\n+
\n+
202
\n+
204
\n+
209 void close() noexcept { m_cur.close(); }
\n+
210
\n+
212
\n+
\n+
215 [[nodiscard]] size_type size()
\n+
216 {
\n+
217 return internal::obtain_stateless_cursor_size(m_cur);
\n+
218 }
\n
\n-
216
\n-
217
\n
219
\n-
\n-
252class PQXX_LIBEXPORT connection
\n-
253{
\n-
254public:
\n-\n-
256
\n-
\n-
258 explicit connection(char const options[])
\n-
259 {
\n-\n-
261 init(options);
\n-
262 }
\n-
\n+
221
\n+
\n+\n+
233 {
\n+
234 return internal::stateless_cursor_retrieve(
\n+
235 m_cur, result::difference_type(size()), begin_pos, end_pos);
\n+
236 }
\n+
\n+
237
\n+
\n+
239 [[nodiscard]] constexpr std::string const &name() const noexcept
\n+
240 {
\n+
241 return m_cur.name();
\n+
242 }
\n+
\n+
243
\n+
244private:
\n+
245 internal::sql_cursor m_cur;
\n+
246};
\n+
\n+
247
\n+
248
\n+
249class icursor_iterator;
\n+
250} // namespace pqxx
\n+
251
\n+
252
\n+
253namespace pqxx::internal::gate
\n+
254{
\n+
255class icursor_iterator_icursorstream;
\n+
256class icursorstream_icursor_iterator;
\n+
257} // namespace pqxx::internal::gate
\n+
258
\n+
259
\n+
260namespace pqxx
\n+
261{
\n
263
\n-
\n-
265 explicit connection(zview options) : connection{options.c_str()}
\n-
266 {
\n-
267 // (Delegates to other constructor which calls check_version for us.)
\n-
268 }
\n-
\n-
269
\n-
271
\n-
276 connection(connection &&rhs);
\n-
277
\n-
278#if defined(PQXX_HAVE_CONCEPTS)
\n-
280
\n-
295 template<internal::ZKey_ZValues MAPPING>
\n-
296 inline connection(MAPPING const &params);
\n-
297#endif // PQXX_HAVE_CONCEPTS
\n-
298
\n-
\n-\n-
300 {
\n-
301 try
\n-
302 {
\n-
303 close();
\n-
304 }
\n-
305 catch (std::exception const &)
\n-
306 {}
\n-
307 }
\n-
\n-
308
\n-
310
\n-
313 connection &operator=(connection &&rhs);
\n-
314
\n-
315 connection(connection const &) = delete;
\n-
316 connection &operator=(connection const &) = delete;
\n-
317
\n-
319
\n-
324 [[nodiscard]] bool PQXX_PURE is_open() const noexcept;
\n-
325
\n-
327 void process_notice(char const[]) noexcept;
\n-
329
\n-
332 void process_notice(zview) noexcept;
\n+
278class PQXX_LIBEXPORT icursorstream
\n+
279{
\n+
280public:
\n+
281 using size_type = cursor_base::size_type;
\n+
282 using difference_type = cursor_base::difference_type;
\n+
283
\n+
285
\n+
296 icursorstream(
\n+
297 transaction_base &context, std::string_view query,
\n+
298 std::string_view basename, difference_type sstride = 1);
\n+
299
\n+
301
\n+
325 icursorstream(
\n+
326 transaction_base &context, field const &cname, difference_type sstride = 1,
\n+\n+
328
\n+
330 constexpr operator bool() const &noexcept { return not m_done; }
\n+
331
\n
333
\n-
335 void trace(std::FILE *) noexcept;
\n-
336
\n-
348
\n-
349 [[nodiscard]] char const *dbname() const;
\n-
350
\n-
352
\n-
353 [[nodiscard]] char const *username() const;
\n-
354
\n+
341 icursorstream &get(result &res)
\n+
342 {
\n+
343 res = fetchblock();
\n+
344 return *this;
\n+
345 }
\n+
347
\n+
355 icursorstream &operator>>(result &res) { return get(res); }
\n
356
\n-
359 [[nodiscard]] char const *hostname() const;
\n-
360
\n-
362 [[nodiscard]] char const *port() const;
\n-
363
\n-
365 [[nodiscard]] int PQXX_PURE backendpid() const &noexcept;
\n-
366
\n-
368
\n-
378 [[nodiscard]] int PQXX_PURE sock() const &noexcept;
\n-
379
\n-
381
\n-
384 [[nodiscard]] int PQXX_PURE protocol_version() const noexcept;
\n+
358
\n+
364 icursorstream &ignore(std::streamsize n = 1) &;
\n+
365
\n+
367
\n+
370 void set_stride(difference_type stride) &;
\n+
371 [[nodiscard]] constexpr difference_type stride() const noexcept
\n+
372 {
\n+
373 return m_stride;
\n+
374 }
\n+
375
\n+
376private:
\n+
377 result fetchblock();
\n+
378
\n+
379 friend class internal::gate::icursorstream_icursor_iterator;
\n+
380 size_type forward(size_type n = 1);
\n+
381 void insert_iterator(icursor_iterator *) noexcept;
\n+
382 void remove_iterator(icursor_iterator *) const noexcept;
\n+
383
\n+
384 void service_iterators(difference_type);
\n
385
\n+
386 internal::sql_cursor m_cur;
\n
387
\n-
399 [[nodiscard]] int PQXX_PURE server_version() const noexcept;
\n-
401
\n-
403
\n-
424 [[nodiscard]] std::string get_client_encoding() const;
\n-
425
\n-
427
\n-
\n-
430 void set_client_encoding(zview encoding) &
\n-
431 {
\n-
432 set_client_encoding(encoding.c_str());
\n-
433 }
\n-
\n+
388 difference_type m_stride;
\n+
389 difference_type m_realpos, m_reqpos;
\n+
390
\n+
391 mutable icursor_iterator *m_iterators;
\n+
392
\n+
393 bool m_done;
\n+
394};
\n+
395
\n+
396
\n+
398
\n+
424class PQXX_LIBEXPORT icursor_iterator
\n+
425{
\n+
426public:
\n+
427 using iterator_category = std::input_iterator_tag;
\n+
428 using value_type = result;
\n+
429 using pointer = result const *;
\n+
430 using reference = result const &;
\n+
431 using istream_type = icursorstream;
\n+
432 using size_type = istream_type::size_type;
\n+
433 using difference_type = istream_type::difference_type;
\n
434
\n-
436
\n-
439 void set_client_encoding(char const encoding[]) &;
\n-
440
\n-
442 [[nodiscard]] int encoding_id() const;
\n-
443
\n-
445
\n-
447
\n-
460 [[deprecated("To set session variables, use set_session_var.")]] void
\n-
461 set_variable(std::string_view var, std::string_view value) &;
\n-
462
\n-
464
\n-
485 template<typename TYPE>
\n-
\n-
486 void set_session_var(std::string_view var, TYPE const &value) &
\n-
487 {
\n-
488 if constexpr (nullness<TYPE>::has_null)
\n-
489 {
\n-
490 if (nullness<TYPE>::is_null(value))
\n-\n-
492 internal::concat("Attempted to set variable ", var, " to null.")};
\n-
493 }
\n-
494 exec(internal::concat("SET ", quote_name(var), "=", quote(value)));
\n-
495 }
\n-
\n-
496
\n-
498
\n-
501 [[deprecated("Use get_var instead.")]] std::string
\n-
502 get_variable(std::string_view);
\n-
503
\n-
505
\n-
511 std::string get_var(std::string_view var);
\n-
512
\n-
514
\n-
\n-
520 template<typename TYPE> TYPE get_var_as(std::string_view var)
\n-
521 {
\n-
522 return from_string<TYPE>(get_var(var));
\n-
523 }
\n-
\n-
524
\n-
530
\n-
547 int get_notifs();
\n-
548
\n-
550
\n-
562 int await_notification();
\n-
563
\n-
565
\n-
577 int await_notification(std::time_t seconds, long microseconds);
\n-
579
\n-
611 [[nodiscard]] std::string
\n-
\n-
612 encrypt_password(zview user, zview password, zview algorithm)
\n-
613 {
\n-
614 return encrypt_password(user.c_str(), password.c_str(), algorithm.c_str());
\n-
615 }
\n-
\n-
617 [[nodiscard]] std::string encrypt_password(
\n-
618 char const user[], char const password[], char const *algorithm = nullptr);
\n-
620
\n-
663
\n-
665
\n-
\n-
669 void prepare(zview name, zview definition) &
\n-
670 {
\n-
671 prepare(name.c_str(), definition.c_str());
\n-
672 }
\n-
\n-
673
\n-
678 void prepare(char const name[], char const definition[]) &;
\n-
679
\n-
681
\n-
688 void prepare(char const definition[]) &;
\n-
689 void prepare(zview definition) & { return prepare(definition.c_str()); }
\n-
690
\n-
692 void unprepare(std::string_view name);
\n-
693
\n-
695
\n-
696 // C++20: constexpr. Breaks ABI.
\n-
698
\n-
701 [[nodiscard]] std::string adorn_name(std::string_view);
\n-
702
\n-
707
\n-
709
\n-
713 [[deprecated("Use std::string_view or pqxx:zview.")]] std::string
\n-
\n-
714 esc(char const text[], std::size_t maxlen) const
\n-
715 {
\n-
716 return esc(std::string_view{text, maxlen});
\n-
717 }
\n-
\n-
718
\n-
\n-
720 [[nodiscard]] std::string esc(char const text[]) const
\n-
721 {
\n-
722 return esc(std::string_view{text});
\n-
723 }
\n-
\n-
724
\n-
725#if defined(PQXX_HAVE_SPAN)
\n-
727
\n-
738 [[nodiscard]] std::string_view
\n-
739 esc(std::string_view text, std::span<char> buffer)
\n-
740 {
\n-
741 auto const size{std::size(text)}, space{std::size(buffer)};
\n-
742 auto const needed{2 * size + 1};
\n-
743 if (space < needed)
\n-
744 throw range_error{internal::concat(
\n-
745 "Not enough room to escape string of ", size, " byte(s): need ",
\n-
746 needed, " bytes of buffer space, but buffer size is ", space, ".")};
\n-
747 auto const data{buffer.data()};
\n-
748 return {data, esc_to_buf(text, data)};
\n-
749 }
\n-
750#endif
\n-
751
\n-
753
\n-
756 [[nodiscard]] std::string esc(std::string_view text) const;
\n-
757
\n-
758#if defined(PQXX_HAVE_CONCEPTS)
\n-
760
\n-
761 template<binary DATA> [[nodiscard]] std::string esc(DATA const &data) const
\n-
762 {
\n-
763 return esc_raw(data);
\n-
764 }
\n-
765#endif
\n-
766
\n-
767#if defined(PQXX_HAVE_CONCEPTS) && defined(PQXX_HAVE_SPAN)
\n-
769
\n-
780 template<binary DATA>
\n-
781 [[nodiscard]] zview esc(DATA const &data, std::span<char> buffer) const
\n-
782 {
\n-
783 auto const size{std::size(data)}, space{std::size(buffer)};
\n-
784 auto const needed{internal::size_esc_bin(std::size(data))};
\n-
785 if (space < needed)
\n-
786 throw range_error{internal::concat(
\n-
787 "Not enough room to escape binary string of ", size, " byte(s): need ",
\n-
788 needed, " bytes of buffer space, but buffer size is ", space, ".")};
\n-
789
\n-
790 std::basic_string_view<std::byte> view{std::data(data), std::size(data)};
\n-
791 auto const out{std::data(buffer)};
\n-
792 // Actually, in the modern format, we know beforehand exactly how many
\n-
793 // bytes we're going to fill. Just leave out the trailing zero.
\n-
794 internal::esc_bin(view, out);
\n-
795 return zview{out, needed - 1};
\n-
796 }
\n-
797#endif
\n-
798
\n-
800 [[deprecated("Use std::byte for binary data.")]] std::string
\n-
801 esc_raw(unsigned char const bin[], std::size_t len) const;
\n-
802
\n-
804
\n-
805 [[nodiscard]] std::string esc_raw(std::basic_string_view<std::byte>) const;
\n-
806
\n-
807#if defined(PQXX_HAVE_SPAN)
\n-
809
\n-
810 [[nodiscard]] std::string
\n-
811 esc_raw(std::basic_string_view<std::byte>, std::span<char> buffer) const;
\n-
812#endif
\n-
813
\n-
814#if defined(PQXX_HAVE_CONCEPTS)
\n-
816
\n-
817 template<binary DATA>
\n-
818 [[nodiscard]] std::string esc_raw(DATA const &data) const
\n-
819 {
\n-
820 return esc_raw(
\n-
821 std::basic_string_view<std::byte>{std::data(data), std::size(data)});
\n-
822 }
\n-
823#endif
\n-
824
\n-
825#if defined(PQXX_HAVE_CONCEPTS) && defined(PQXX_HAVE_SPAN)
\n-
827 template<binary DATA>
\n-
828 [[nodiscard]] zview esc_raw(DATA const &data, std::span<char> buffer) const
\n-
829 {
\n-
830 return this->esc(binary_cast(data), buffer);
\n-
831 }
\n-
832#endif
\n-
833
\n-
835
\n-
838 [[nodiscard, deprecated("Use unesc_bin() instead.")]] std::string
\n-
\n-\n-
840 {
\n-
841#include "pqxx/internal/ignore-deprecated-pre.hxx"
\n-
842 return unesc_raw(text.c_str());
\n-
843#include "pqxx/internal/ignore-deprecated-post.hxx"
\n-
844 }
\n-
\n-
845
\n-
847
\n-
850 [[nodiscard, deprecated("Use unesc_bin() instead.")]] std::string
\n-
851 unesc_raw(char const text[]) const;
\n-
852
\n-
853 // TODO: Make "into buffer" variant to eliminate a string allocation.
\n-
855
\n-
862 [[nodiscard]] std::basic_string<std::byte>
\n-
\n-
863 unesc_bin(std::string_view text) const
\n-
864 {
\n-
865 std::basic_string<std::byte> buf;
\n-
866 buf.resize(pqxx::internal::size_unesc_bin(std::size(text)));
\n-
867 pqxx::internal::unesc_bin(text, buf.data());
\n-
868 return buf;
\n-
869 }
\n-
\n-
870
\n-
872 [[deprecated("Use quote(std::basic_string_view<std::byte>).")]] std::string
\n-
873 quote_raw(unsigned char const bin[], std::size_t len) const;
\n-
874
\n-
876 std::string quote_raw(std::basic_string_view<std::byte>) const;
\n-
877
\n-
878#if defined(PQXX_HAVE_CONCEPTS)
\n-
880
\n-
881 template<binary DATA>
\n-
882 [[nodiscard]] std::string quote_raw(DATA const &data) const
\n-
883 {
\n-
884 return quote_raw(
\n-
885 std::basic_string_view<std::byte>{std::data(data), std::size(data)});
\n-
886 }
\n-
887#endif
\n-
888
\n-
889 // TODO: Make "into buffer" variant to eliminate a string allocation.
\n-
891 [[nodiscard]] std::string quote_name(std::string_view identifier) const;
\n-
892
\n-
893 // TODO: Make "into buffer" variant to eliminate a string allocation.
\n-
895
\n-
898 [[nodiscard]] std::string quote_table(std::string_view name) const;
\n-
899
\n-
900 // TODO: Make "into buffer" variant to eliminate a string allocation.
\n-
902
\n-
910 [[nodiscard]] std::string quote_table(table_path) const;
\n-
911
\n-
912 // TODO: Make "into buffer" variant to eliminate a string allocation.
\n-
914
\n-
921 template<PQXX_CHAR_STRINGS_ARG STRINGS>
\n-
922 inline std::string quote_columns(STRINGS const &columns) const;
\n-
923
\n-
924 // TODO: Make "into buffer" variant to eliminate a string allocation.
\n-
926
\n-
929 template<typename T>
\n-
930 [[nodiscard]] inline std::string quote(T const &t) const;
\n-
931
\n-
932 [[deprecated("Use std::byte for binary data.")]] std::string
\n-
933 quote(binarystring const &) const;
\n-
934
\n-
935 // TODO: Make "into buffer" variant to eliminate a string allocation.
\n-
937 [[nodiscard]] std::string
\n-
938 quote(std::basic_string_view<std::byte> bytes) const;
\n-
939
\n-
940 // TODO: Make "into buffer" variant to eliminate a string allocation.
\n-
942
\n-
967 [[nodiscard]] std::string
\n-
968 esc_like(std::string_view text, char escape_char = '\\\\') const;
\n-
970
\n-
972
\n-
976 void cancel_query();
\n-
977
\n-
978#if defined(_WIN32) || __has_include(<fcntl.h>)
\n-
980
\n-
984 void set_blocking(bool block) &;
\n-
985#endif // defined(_WIN32) || __has_include(<fcntl.h>)
\n-
986
\n-
988
\n-
997 void set_verbosity(error_verbosity verbosity) &noexcept;
\n-
998
\n-
1000
\n-
1012 [[nodiscard]] std::vector<errorhandler *> get_errorhandlers() const;
\n-
1013
\n-
1015
\n-
1021 [[nodiscard]] std::string connection_string() const;
\n-
1022
\n-
1024
\n-
1032 void close();
\n-
1033
\n-
1035
\n-
\n-
1041 static connection seize_raw_connection(internal::pq::PGconn *raw_conn)
\n-
1042 {
\n-
1043 return connection{raw_conn};
\n-
1044 }
\n-
\n-
1045
\n-
1047
\n-
\n-
1052 internal::pq::PGconn *release_raw_connection() &&
\n-
1053 {
\n-
1054 return std::exchange(m_conn, nullptr);
\n-
1055 }
\n-
\n-
1056
\n-
1057private:
\n-
1058 friend class connecting;
\n-
1059 enum connect_mode
\n-
1060 {
\n-
1061 connect_nonblocking
\n-
1062 };
\n-
1063 connection(connect_mode, zview connection_string);
\n-
1064
\n-
1066 explicit connection(internal::pq::PGconn *raw_conn) : m_conn{raw_conn} {}
\n-
1067
\n-
1069
\n-
1074 std::pair<bool, bool> poll_connect();
\n-
1075
\n-
1076 // Initialise based on connection string.
\n-
1077 void init(char const options[]);
\n-
1078 // Initialise based on parameter names and values.
\n-
1079 void init(char const *params[], char const *values[]);
\n-
1080 void complete_init();
\n-
1081
\n-
1082 result make_result(
\n-
1083 internal::pq::PGresult *pgr, std::shared_ptr<std::string> const &query,
\n-
1084 std::string_view desc = ""sv);
\n-
1085
\n-
1086 void PQXX_PRIVATE set_up_state();
\n-
1087
\n-
1088 int PQXX_PRIVATE PQXX_PURE status() const noexcept;
\n-
1089
\n-
1091
\n-
1095 std::size_t esc_to_buf(std::string_view text, char *buf) const;
\n-
1096
\n-
1097 friend class internal::gate::const_connection_largeobject;
\n-
1098 char const *PQXX_PURE err_msg() const noexcept;
\n-
1099
\n-
1100 void PQXX_PRIVATE process_notice_raw(char const msg[]) noexcept;
\n-
1101
\n-
1102 result exec_prepared(std::string_view statement, internal::c_params const &);
\n-
1103
\n-
1105 void check_movable() const;
\n-
1107 void check_overwritable() const;
\n-
1108
\n-
1109 friend class internal::gate::connection_errorhandler;
\n-
1110 void PQXX_PRIVATE register_errorhandler(errorhandler *);
\n-
1111 void PQXX_PRIVATE unregister_errorhandler(errorhandler *) noexcept;
\n-
1112
\n-
1113 friend class internal::gate::connection_transaction;
\n-
1114 result exec(std::string_view, std::string_view = ""sv);
\n-
1115 result
\n-
1116 PQXX_PRIVATE exec(std::shared_ptr<std::string>, std::string_view = ""sv);
\n-
1117 void PQXX_PRIVATE register_transaction(transaction_base *);
\n-
1118 void PQXX_PRIVATE unregister_transaction(transaction_base *) noexcept;
\n-
1119
\n-
1120 friend struct internal::gate::connection_stream_from;
\n-
1121 std::pair<std::unique_ptr<char, void (*)(void const *)>, std::size_t>
\n-
1122 read_copy_line();
\n-
1123
\n-
1124 friend class internal::gate::connection_stream_to;
\n-
1125 void PQXX_PRIVATE write_copy_line(std::string_view);
\n-
1126 void PQXX_PRIVATE end_copy_write();
\n-
1127
\n-
1128 friend class internal::gate::connection_largeobject;
\n-
1129 internal::pq::PGconn *raw_connection() const { return m_conn; }
\n-
1130
\n-
1131 friend class internal::gate::connection_notification_receiver;
\n-
1132 void add_receiver(notification_receiver *);
\n-
1133 void remove_receiver(notification_receiver *) noexcept;
\n-
1134
\n-
1135 friend class internal::gate::connection_pipeline;
\n-
1136 void PQXX_PRIVATE start_exec(char const query[]);
\n-
1137 bool PQXX_PRIVATE consume_input() noexcept;
\n-
1138 bool PQXX_PRIVATE is_busy() const noexcept;
\n-
1139 internal::pq::PGresult *get_result();
\n-
1140
\n-
1141 friend class internal::gate::connection_dbtransaction;
\n-
1142 friend class internal::gate::connection_sql_cursor;
\n-
1143
\n-
1144 result exec_params(std::string_view query, internal::c_params const &args);
\n-
1145
\n-
1147 internal::pq::PGconn *m_conn = nullptr;
\n-
1148
\n-
1150
\n-
1157 transaction_base const *m_trans = nullptr;
\n-
1158
\n-
1159 std::list<errorhandler *> m_errorhandlers;
\n-
1160
\n-
1161 using receiver_list =
\n-
1162 std::multimap<std::string, pqxx::notification_receiver *>;
\n-
1164 receiver_list m_receivers;
\n-
1165
\n-
1167 int m_unique_id = 0;
\n-
1168};
\n-
\n-
1169
\n-
1170
\n-\n-
1173
\n-
1174
\n-
1176
\n-
\n-
1219class PQXX_LIBEXPORT connecting
\n-
1220{
\n-
1221public:
\n-
1223 connecting(zview connection_string = ""_zv);
\n-
1224
\n-
1225 connecting(connecting const &) = delete;
\n-
1226 connecting(connecting &&) = default;
\n-
1227 connecting &operator=(connecting const &) = delete;
\n-\n-
1229
\n-
1231 [[nodiscard]] int sock() const &noexcept { return m_conn.sock(); }
\n-
1232
\n-
\n-
1234 [[nodiscard]] constexpr bool wait_to_read() const &noexcept
\n-
1235 {
\n-
1236 return m_reading;
\n-
1237 }
\n-
\n-
1238
\n-
\n-
1240 [[nodiscard]] constexpr bool wait_to_write() const &noexcept
\n-
1241 {
\n-
1242 return m_writing;
\n-
1243 }
\n-
\n-
1244
\n-
1246 void process() &;
\n-
1247
\n-
\n-
1249 [[nodiscard]] constexpr bool done() const &noexcept
\n-
1250 {
\n-
1251 return not m_reading and not m_writing;
\n-
1252 }
\n-
\n-
1253
\n-
1255
\n-
1263 [[nodiscard]] connection produce() &&;
\n-
1264
\n-
1265private:
\n-
1266 connection m_conn;
\n-
1267 bool m_reading{false};
\n-
1268 bool m_writing{true};
\n-
1269};
\n-
\n-
1270
\n-
1271
\n-
\n-
1272template<typename T> inline std::string connection::quote(T const &t) const
\n-
1273{
\n-
1274 if constexpr (nullness<T>::always_null)
\n-
1275 {
\n-
1276 return "NULL";
\n-
1277 }
\n-
1278 else
\n-
1279 {
\n-
1280 if (is_null(t))
\n-
1281 return "NULL";
\n-
1282 auto const text{to_string(t)};
\n-
1283
\n-
1284 // Okay, there's an easy way to do this and there's a hard way. The easy
\n-
1285 // way was "quote, esc(to_string(t)), quote". I'm going with the hard way
\n-
1286 // because it's going to save some string manipulation that will probably
\n-
1287 // incur some unnecessary memory allocations and deallocations.
\n-
1288 std::string buf{'\\''};
\n-
1289 buf.resize(2 + 2 * std::size(text) + 1);
\n-
1290 auto const content_bytes{esc_to_buf(text, buf.data() + 1)};
\n-
1291 auto const closing_quote{1 + content_bytes};
\n-
1292 buf[closing_quote] = '\\'';
\n-
1293 auto const end{closing_quote + 1};
\n-
1294 buf.resize(end);
\n-
1295 return buf;
\n-
1296 }
\n-
1297}
\n-
\n-
1298
\n-
1299
\n-
1300template<PQXX_CHAR_STRINGS_ARG STRINGS>
\n-
\n-
1301inline std::string connection::quote_columns(STRINGS const &columns) const
\n-
1302{
\n-
1303 return separated_list(
\n-
1304 ","sv, std::cbegin(columns), std::cend(columns),
\n-
1305 [this](auto col) { return this->quote_name(*col); });
\n-
1306}
\n-
\n-
1307
\n-
1308
\n-
1309#if defined(PQXX_HAVE_CONCEPTS)
\n-
1310template<internal::ZKey_ZValues MAPPING>
\n-
1311inline connection::connection(MAPPING const &params)
\n-
1312{
\n-
1313 check_version();
\n-
1314
\n-
1315 std::vector<char const *> keys, values;
\n-
1316 if constexpr (std::ranges::sized_range<MAPPING>)
\n-
1317 {
\n-
1318 auto const size{std::ranges::size(params) + 1};
\n-
1319 keys.reserve(size);
\n-
1320 values.reserve(size);
\n-
1321 }
\n-
1322 for (auto const &[key, value] : params)
\n-
1323 {
\n-
1324 keys.push_back(internal::as_c_string(key));
\n-
1325 values.push_back(internal::as_c_string(value));
\n-
1326 }
\n-
1327 keys.push_back(nullptr);
\n-
1328 values.push_back(nullptr);
\n-
1329 init(std::data(keys), std::data(values));
\n-
1330}
\n-
1331#endif // PQXX_HAVE_CONCEPTS
\n-
1332} // namespace pqxx
\n-
1333#endif
\n+
435 icursor_iterator() noexcept;
\n+
436 explicit icursor_iterator(istream_type &) noexcept;
\n+
437 icursor_iterator(icursor_iterator const &) noexcept;
\n+
438 ~icursor_iterator() noexcept;
\n+
439
\n+
440 result const &operator*() const
\n+
441 {
\n+
442 refresh();
\n+
443 return m_here;
\n+
444 }
\n+
445 result const *operator->() const
\n+
446 {
\n+
447 refresh();
\n+
448 return &m_here;
\n+
449 }
\n+
450 icursor_iterator &operator++();
\n+
451 icursor_iterator operator++(int);
\n+
452 icursor_iterator &operator+=(difference_type);
\n+
453 icursor_iterator &operator=(icursor_iterator const &) noexcept;
\n+
454
\n+
455 [[nodiscard]] bool operator==(icursor_iterator const &rhs) const;
\n+
456 [[nodiscard]] bool operator!=(icursor_iterator const &rhs) const noexcept
\n+
457 {
\n+
458 return not operator==(rhs);
\n+
459 }
\n+
460 [[nodiscard]] bool operator<(icursor_iterator const &rhs) const;
\n+
461 [[nodiscard]] bool operator>(icursor_iterator const &rhs) const
\n+
462 {
\n+
463 return rhs < *this;
\n+
464 }
\n+
465 [[nodiscard]] bool operator<=(icursor_iterator const &rhs) const
\n+
466 {
\n+
467 return not(*this > rhs);
\n+
468 }
\n+
469 [[nodiscard]] bool operator>=(icursor_iterator const &rhs) const
\n+
470 {
\n+
471 return not(*this < rhs);
\n+
472 }
\n+
473
\n+
474private:
\n+
475 void refresh() const;
\n+
476
\n+
477 friend class internal::gate::icursor_iterator_icursorstream;
\n+
478 difference_type pos() const noexcept { return m_pos; }
\n+
479 void fill(result const &);
\n+
480
\n+
481 icursorstream *m_stream{nullptr};
\n+
482 result m_here;
\n+
483 difference_type m_pos;
\n+
484 icursor_iterator *m_prev{nullptr}, *m_next{nullptr};
\n+
485};
\n+
486} // namespace pqxx
\n+
487#endif
\n
The home of all libpqxx classes, functions, templates, etc.
Definition array.hxx:33
\n-
std::string separated_list(std::string_view sep, ITER begin, ITER end, ACCESS access)
Represent sequence of values as a string, joined by a given separator.
Definition separated_list.hxx:44
\n-
std::string encrypt_password(char const user[], char const password[])
Encrypt a password.
Definition connection.cxx:94
\n-
std::basic_string_view< std::byte > binary_cast(TYPE const &data)
Cast binary data to a type that libpqxx will recognise as binary.
Definition util.hxx:303
\n-
void skip_init_ssl() noexcept
Control initialisation of OpenSSL and libcrypto libraries.
Definition connection.hxx:173
\n-
std::initializer_list< std::string_view > table_path
Representation of a PostgreSQL table path.
Definition connection.hxx:188
\n-
void check_version() noexcept
Definition util.hxx:234
\n-
std::string to_string(field const &value)
Convert a field to a string.
Definition result.cxx:549
\n-
skip_init
Flags for skipping initialisation of SSL-related libraries.
Definition connection.hxx:137
\n-
@ crypto
Skip initialisation of libcrypto.
Definition connection.hxx:145
\n-
@ openssl
Skip initialisation of OpenSSL library.
Definition connection.hxx:142
\n-
@ nothing
A do-nothing flag that does not affect anything.
Definition connection.hxx:139
\n-
error_verbosity
Error verbosity levels.
Definition connection.hxx:210
\n-\n-\n-\n-\n-
Internal items for libpqxx' own use. Do not use these yourself.
Definition composite.hxx:84
\n-
void PQXX_COLD skip_init_ssl(int flags) noexcept
Control OpenSSL/crypto library initialisation.
Definition connection.cxx:83
\n-
void unesc_bin(std::string_view escaped_data, std::byte buffer[])
Reconstitute binary data from its escaped version.
Definition util.cxx:158
\n-
void esc_bin(std::basic_string_view< std::byte > binary_data, char buffer[]) noexcept
Hex-escape binary data into a buffer.
Definition util.cxx:126
\n-
constexpr std::size_t size_esc_bin(std::size_t binary_bytes) noexcept
Compute buffer size needed to escape binary data for use as a BYTEA.
Definition util.hxx:411
\n-
constexpr char const * as_c_string(char const str[]) noexcept
Get a raw C string pointer.
Definition zview.hxx:145
\n-
constexpr std::size_t size_unesc_bin(std::size_t escaped_bytes) noexcept
Compute binary size from the size of its escaped version.
Definition util.hxx:420
\n+
int result_difference_type
Difference between result sizes.
Definition types.hxx:31
\n+
strip_t< decltype(*std::begin(std::declval< CONTAINER >()))> value_type
The type of a container's elements.
Definition types.hxx:107
\n+
int result_size_type
Number of rows in a result set.
Definition types.hxx:28
\n
Definition connection.hxx:112
\n
Connection to a database.
Definition connection.hxx:253
\n-
std::string encrypt_password(zview user, zview password, zview algorithm)
Encrypt a password for a given user.
Definition connection.hxx:612
\n-
void prepare(zview definition) &
Definition connection.hxx:689
\n-
connection(char const options[])
Connect to a database, using options string.
Definition connection.hxx:258
\n-
connection & operator=(connection const &)=delete
\n-
TYPE get_var_as(std::string_view var)
Read currently applicable value of a variable.
Definition connection.hxx:520
\n-
connection()
Definition connection.hxx:255
\n-
~connection()
Definition connection.hxx:299
\n-
std::string quote_columns(STRINGS const &columns) const
Quote and comma-separate a series of column names.
Definition connection.hxx:1301
\n-
connection(zview options)
Connect to a database, using options string.
Definition connection.hxx:265
\n-
internal::pq::PGconn * release_raw_connection() &&
Release the raw connection without closing it.
Definition connection.hxx:1052
\n-
static connection seize_raw_connection(internal::pq::PGconn *raw_conn)
Seize control of a raw libpq connection.
Definition connection.hxx:1041
\n-
std::basic_string< std::byte > unesc_bin(std::string_view text) const
Unescape binary data, e.g. from a table field or notification payload.
Definition connection.hxx:863
\n-
std::string esc(char const text[]) const
Escape string for use as SQL string literal on this connection.
Definition connection.hxx:720
\n-
std::string unesc_raw(zview text) const
Unescape binary data, e.g. from a table field or notification payload.
Definition connection.hxx:839
\n-
std::string esc(char const text[], std::size_t maxlen) const
Escape string for use as SQL string literal on this connection.
Definition connection.hxx:714
\n-
void prepare(zview name, zview definition) &
Define a prepared statement.
Definition connection.hxx:669
\n-
void set_session_var(std::string_view var, TYPE const &value) &
Set one of the session variables to a new value.
Definition connection.hxx:486
\n-
std::string quote(T const &t) const
Represent object as SQL string, including quoting & escaping.
Definition connection.hxx:1272
\n-
connection(connection const &)=delete
\n-
An ongoing, non-blocking stepping stone to a connection.
Definition connection.hxx:1220
\n-
connecting(connecting &&)=default
\n-
int sock() const &noexcept
Get the socket. The socket may change during the connection process.
Definition connection.hxx:1231
\n-
constexpr bool done() const &noexcept
Is our connection finished?
Definition connection.hxx:1249
\n-
connecting & operator=(connecting const &)=delete
\n-
connecting(connecting const &)=delete
\n-
constexpr bool wait_to_write() const &noexcept
Should we currently wait to be able to write to the socket?
Definition connection.hxx:1240
\n-
void process() &
Progress towards completion (but don't block).
\n-
connecting & operator=(connecting &&)=default
\n-
constexpr bool wait_to_read() const &noexcept
Should we currently wait to be able to read from the socket?
Definition connection.hxx:1234
\n-
connecting(zview connection_string=""_zv)
Start connecting.
\n-
connection produce() &&
Produce the completed connection object.
\n-
Base class for error-handler callbacks.
Definition errorhandler.hxx:54
\n-
The caller attempted to set a variable to null, which is not allowed.
Definition except.hxx:116
\n-
Definition notification.hxx:57
\n-
Build a parameter list for a parameterised or prepared statement.
Definition params.hxx:220
\n+
Common definitions for cursor types.
Definition cursor.hxx:42
\n+
cursor_base & operator=(cursor_base const &)=delete
\n+
constexpr std::string const & name() const noexcept
Name of underlying SQL cursor.
Definition cursor.hxx:142
\n+
result_size_type size_type
Definition cursor.hxx:44
\n+
static constexpr difference_type next() noexcept
Special value: read one row only.
Definition cursor.hxx:116
\n+
cursor_base(cursor_base const &)=delete
\n+
static constexpr difference_type all() noexcept
Special value: read until end.
Definition cursor.hxx:108
\n+
static constexpr difference_type prior() noexcept
Special value: read backwards, one row only.
Definition cursor.hxx:121
\n+
cursor_base()=delete
\n+
access_policy
Cursor access-pattern policy.
Definition cursor.hxx:52
\n+
@ forward_only
Cursor can move forward only.
Definition cursor.hxx:54
\n+
ownership_policy
Cursor destruction policy.
Definition cursor.hxx:88
\n+
@ owned
Destroy SQL cursor when cursor object is closed at end of transaction.
Definition cursor.hxx:90
\n+
update_policy
Cursor update policy.
Definition cursor.hxx:64
\n+
@ read_only
Cursor can be used to read data but not to write.
Definition cursor.hxx:66
\n+
result_difference_type difference_type
Definition cursor.hxx:45
\n+
std::string const m_name
Definition cursor.hxx:150
\n+
static constexpr difference_type backward_all() noexcept
Special value: read backwards from current position back to origin.
Definition cursor.hxx:129
\n+
"Stateless cursor" class: easy API for retrieving parts of result sets
Definition cursor.hxx:169
\n+
constexpr std::string const & name() const noexcept
Return this cursor's name.
Definition cursor.hxx:239
\n+
void close() noexcept
Close this cursor.
Definition cursor.hxx:209
\n+
result_size_type size_type
Definition cursor.hxx:171
\n+
result_difference_type difference_type
Definition cursor.hxx:172
\n+
result retrieve(difference_type begin_pos, difference_type end_pos)
Retrieve rows from begin_pos (inclusive) to end_pos (exclusive)
Definition cursor.hxx:232
\n+
stateless_cursor(transaction_base &tx, std::string_view query, std::string_view cname, bool hold)
Create cursor.
Definition cursor.hxx:183
\n+
size_type size()
Number of rows in cursor's result set.
Definition cursor.hxx:215
\n+
stateless_cursor(transaction_base &tx, std::string_view adopted_cursor)
Adopt an existing scrolling SQL cursor.
Definition cursor.hxx:196
\n
Result set containing data returned by a query or command.
Definition result.hxx:73
\n-
Traits describing a type's "null value," if any.
Definition strconv.hxx:93
\n+
result_difference_type difference_type
Definition result.hxx:76
\n
Interface definition (and common code) for "transaction" classes.
Definition transaction_base.hxx:88
\n-
Marker-type wrapper: zero-terminated std::string_view.
Definition zview.hxx:38
\n-
constexpr char const * c_str() const &noexcept
Either a null pointer, or a zero-terminated text buffer.
Definition zview.hxx:96
\n
\n
\n \n
\n \n
\n \n \n", "details": [{"source1": "html2text {}", "source2": "html2text {}", "unified_diff": "@@ -1,929 +1,428 @@\n \n \n \n \n \n libpqxx\u00a07.8.1\n \n-connection.hxx\n- 1/* Definition of the connection class.\n+cursor.hxx\n+ 1/* Definition of the iterator/container-style cursor classes.\n 2 *\n- 3 * pqxx::connection encapsulates a connection to a database.\n+ 3 * C++-style wrappers for SQL cursors.\n 4 *\n- 5 * DO NOT INCLUDE THIS FILE DIRECTLY; include pqxx/connection instead.\n+ 5 * DO NOT INCLUDE THIS FILE DIRECTLY; include pqxx/cursor instead.\n 6 *\n 7 * Copyright (c) 2000-2023, Jeroen T. Vermeulen.\n 8 *\n 9 * See COPYING for copyright license. If you did not receive a file called\n 10 * COPYING with this source code, please notify the distributor of this\n 11 * mistake, or contact the author.\n 12 */\n- 13#ifndef PQXX_H_CONNECTION\n- 14#define PQXX_H_CONNECTION\n+ 13#ifndef PQXX_H_CURSOR\n+ 14#define PQXX_H_CURSOR\n 15\n 16#if !defined(PQXX_HEADER_PRE)\n 17# error \"Include libpqxx headers as , not .\"\n 18#endif\n 19\n- 20#include \n- 21#include \n- 22#include \n- 23#include \n- 24#include \n- 25#include \n- 26#include \n- 27#include \n- 28\n- 29// Double-check in order to suppress an overzealous Visual C++ warning\n-(#418).\n- 30#if defined(PQXX_HAVE_CONCEPTS) && __has_include()\n- 31# include \n- 32#endif\n- 33\n- 34#include \"pqxx/errorhandler.hxx\"\n- 35#include \"pqxx/except.hxx\"\n- 36#include \"pqxx/internal/concat.hxx\"\n- 37#include \"pqxx/params.hxx\"\n- 38#include \"pqxx/separated_list.hxx\"\n- 39#include \"pqxx/strconv.hxx\"\n- 40#include \"pqxx/types.hxx\"\n- 41#include \"pqxx/util.hxx\"\n- 42#include \"pqxx/zview.hxx\"\n- 43\n- 44\n- 75namespace pqxx::internal\n- 76{\n- 77class sql_cursor;\n- 78\n- 79#if defined(PQXX_HAVE_CONCEPTS)\n- 81template\n- 82concept ZKey_ZValues =\n- 83 std::ranges::input_range and\n- 84 requires(T t) {\n- 85 {\n- 86 std::cbegin(t)\n- 87 };\n+ 20#include \n+ 21#include \n+ 22\n+ 23#include \"pqxx/result.hxx\"\n+ 24#include \"pqxx/transaction_base.hxx\"\n+ 25\n+ 26\n+ 27namespace pqxx\n+ 28{\n+ 30\n+41class PQXX_LIBEXPORT cursor_base\n+ 42{\n+ 43public:\n+44 using size_type = result_size_type;\n+45 using difference_type = result_difference_type;\n+ 46\n+ 48\n+51 enum access_policy\n+ 52 {\n+54 forward_only,\n+ 56 random_access\n+57 };\n+ 58\n+ 60\n+63 enum update_policy\n+ 64 {\n+66 read_only,\n+ 68 update\n+69 };\n+ 70\n+ 72\n+87 enum ownership_policy\n 88 {\n- 89 std::get<0>(*std::cbegin(t))\n- 90 } -> ZString;\n- 91 {\n- 92 std::get<1>(*std::cbegin(t))\n- 93 } -> ZString;\n- 94 } and\n- 95 std::tuple_size_v::value_type> == 2;\n- 96#endif // PQXX_HAVE_CONCEPTS\n- 97\n+90 owned,\n+ 92 loose\n+93 };\n+ 94\n+95 cursor_base() = delete;\n+96 cursor_base(cursor_base const &) = delete;\n+97 cursor_base &operator=(cursor_base const &) = delete;\n 98\n- 100\n- 107void PQXX_COLD PQXX_LIBEXPORT skip_init_ssl(int flags) noexcept;\n- 108} // namespace pqxx::internal\n- 109\n- 110\n-111namespace pqxx::internal::gate\n- 112{\n- 113class connection_dbtransaction;\n- 114class connection_errorhandler;\n- 115class connection_largeobject;\n- 116class connection_notification_receiver;\n- 117class connection_pipeline;\n- 118class connection_sql_cursor;\n- 119struct connection_stream_from;\n- 120class connection_stream_to;\n- 121class connection_transaction;\n- 122class const_connection_largeobject;\n- 123} // namespace pqxx::internal::gate\n- 124\n+ 103\n+ 105\n+108 [[nodiscard]] static constexpr difference_type all() noexcept\n+ 109 {\n+ 110 return (std::numeric_limits::max)() - 1;\n+ 111 }\n+ 112\n+ 114\n+116 [[nodiscard]] static constexpr difference_type next() noexcept { return 1;\n+}\n+ 117\n+ 119\n+121 [[nodiscard]] static constexpr difference_type prior() noexcept\n+ 122 {\n+ 123 return -1;\n+ 124 }\n 125\n- 126namespace pqxx\n- 127{\n- 129\n-136enum skip_init : int\n- 137{\n-139 nothing,\n- 140\n-142 openssl,\n- 143\n-145 crypto,\n- 146};\n- 147\n- 148\n- 150\n-173template inline void skip_init_ssl() noexcept\n- 174{\n- 175 // (Normalise skip flags to one per.)\n- 176 pqxx::internal::skip_init_ssl(((1 << SKIP) | ...));\n- 177}\n- 178\n- 179\n- 181\n-188using table_path = std::initializer_list;\n- 189\n+ 127\n+129 [[nodiscard]] static constexpr difference_type backward_all() noexcept\n+ 130 {\n+ 131 return (std::numeric_limits::min)() + 1;\n+ 132 }\n+ 133\n+ 135\n+ 137\n+142 [[nodiscard]] constexpr std::string const &name() const noexcept\n+ 143 {\n+ 144 return m_name;\n+ 145 }\n+ 146\n+ 147protected:\n+ 148 cursor_base(connection &, std::string_view Name, bool embellish_name =\n+true);\n+ 149\n+150 std::string const m_name;\n+ 151};\n+ 152} // namespace pqxx\n+ 153\n+ 154\n+ 155#include \n+ 156\n+ 157\n+ 158namespace pqxx\n+ 159{\n+ 161\n+ 167template\n+168class stateless_cursor\n+ 169{\n+ 170public:\n+171 using size_type = result_size_type;\n+172 using difference_type = result_difference_type;\n+ 173\n+ 175\n+183 stateless_cursor(\n+ 184 transaction_base &tx, std::string_view query, std::string_view cname,\n+ 185 bool hold) :\n+ 186 m_cur{tx, query, cname, cursor_base::random_access, up, op, hold}\n+ 187 {}\n+ 188\n 190\n- 192[[nodiscard,\n- 193 deprecated(\"Use connection::encrypt_password instead.\")]] std::string\n- 194 PQXX_LIBEXPORT\n- 195 encrypt_password(char const user[], char const password[]);\n- 196\n- 198[[nodiscard,\n- 199 deprecated(\"Use connection::encrypt_password instead.\")]] inline std::\n-string\n-200encrypt_password(zview user, zview password)\n- 201{\n- 202#include \"pqxx/internal/ignore-deprecated-pre.hxx\"\n- 203 return encrypt_password(user.c_str(), password.c_str());\n- 204#include \"pqxx/internal/ignore-deprecated-post.hxx\"\n- 205}\n- 206\n- 207\n-209enum class error_verbosity : int\n- 210{\n- 211 // These values must match those in libpq's PGVerbosity enum.\n- 212 terse = 0,\n- 213 normal = 1,\n- 214 verbose = 2\n- 215};\n- 216\n- 217\n+196 stateless_cursor(transaction_base &tx, std::string_view adopted_cursor) :\n+ 197 m_cur{tx, adopted_cursor, op}\n+ 198 {\n+ 199 // Put cursor in known position\n+ 200 m_cur.move(cursor_base::backward_all());\n+ 201 }\n+ 202\n+ 204\n+209 void close() noexcept { m_cur.close(); }\n+ 210\n+ 212\n+215 [[nodiscard]] size_type size()\n+ 216 {\n+ 217 return internal::obtain_stateless_cursor_size(m_cur);\n+ 218 }\n 219\n-252class PQXX_LIBEXPORT connection\n- 253{\n- 254public:\n-255 connection() : connection{\"\"} {}\n- 256\n-258 explicit connection(char const options[])\n- 259 {\n- 260 check_version();\n- 261 init(options);\n- 262 }\n+ 221\n+232 result retrieve(difference_type begin_pos, difference_type end_pos)\n+ 233 {\n+ 234 return internal::stateless_cursor_retrieve(\n+ 235 m_cur, result::difference_type(size()), begin_pos, end_pos);\n+ 236 }\n+ 237\n+239 [[nodiscard]] constexpr std::string const &name() const noexcept\n+ 240 {\n+ 241 return m_cur.name();\n+ 242 }\n+ 243\n+ 244private:\n+ 245 internal::sql_cursor m_cur;\n+ 246};\n+ 247\n+ 248\n+ 249class icursor_iterator;\n+ 250} // namespace pqxx\n+ 251\n+ 252\n+ 253namespace pqxx::internal::gate\n+ 254{\n+ 255class icursor_iterator_icursorstream;\n+ 256class icursorstream_icursor_iterator;\n+ 257} // namespace pqxx::internal::gate\n+ 258\n+ 259\n+ 260namespace pqxx\n+ 261{\n 263\n-265 explicit connection(zview options) : connection{options.c_str()}\n- 266 {\n- 267 // (Delegates to other constructor which calls check_version for us.)\n- 268 }\n- 269\n- 271\n- 276 connection(connection &&rhs);\n- 277\n- 278#if defined(PQXX_HAVE_CONCEPTS)\n- 280\n- 295 template\n- 296 inline connection(MAPPING const ¶ms);\n- 297#endif // PQXX_HAVE_CONCEPTS\n- 298\n-299 ~connection()\n- 300 {\n- 301 try\n- 302 {\n- 303 close();\n- 304 }\n- 305 catch (std::exception const &)\n- 306 {}\n- 307 }\n- 308\n- 310\n- 313 connection &operator=(connection &&rhs);\n- 314\n-315 connection(connection const &) = delete;\n-316 connection &operator=(connection const &) = delete;\n- 317\n- 319\n- 324 [[nodiscard]] bool PQXX_PURE is_open() const noexcept;\n- 325\n- 327 void process_notice(char const[]) noexcept;\n- 329\n- 332 void process_notice(zview) noexcept;\n+ 278class PQXX_LIBEXPORT icursorstream\n+ 279{\n+ 280public:\n+ 281 using size_type = cursor_base::size_type;\n+ 282 using difference_type = cursor_base::difference_type;\n+ 283\n+ 285\n+ 296 icursorstream(\n+ 297 transaction_base &context, std::string_view query,\n+ 298 std::string_view basename, difference_type sstride = 1);\n+ 299\n+ 301\n+ 325 icursorstream(\n+ 326 transaction_base &context, field const &cname, difference_type sstride =\n+1,\n+ 327 cursor_base::ownership_policy op = cursor_base::owned);\n+ 328\n+ 330 constexpr operator bool() const &noexcept { return not m_done; }\n+ 331\n 333\n- 335 void trace(std::FILE *) noexcept;\n- 336\n- 348\n- 349 [[nodiscard]] char const *dbname() const;\n- 350\n- 352\n- 353 [[nodiscard]] char const *username() const;\n- 354\n+ 341 icursorstream &get(result &res)\n+ 342 {\n+ 343 res = fetchblock();\n+ 344 return *this;\n+ 345 }\n+ 347\n+ 355 icursorstream &operator>>(result &res) { return get(res); }\n 356\n- 359 [[nodiscard]] char const *hostname() const;\n- 360\n- 362 [[nodiscard]] char const *port() const;\n- 363\n- 365 [[nodiscard]] int PQXX_PURE backendpid() const &noexcept;\n- 366\n- 368\n- 378 [[nodiscard]] int PQXX_PURE sock() const &noexcept;\n- 379\n- 381\n- 384 [[nodiscard]] int PQXX_PURE protocol_version() const noexcept;\n+ 358\n+ 364 icursorstream &ignore(std::streamsize n = 1) &;\n+ 365\n+ 367\n+ 370 void set_stride(difference_type stride) &;\n+ 371 [[nodiscard]] constexpr difference_type stride() const noexcept\n+ 372 {\n+ 373 return m_stride;\n+ 374 }\n+ 375\n+ 376private:\n+ 377 result fetchblock();\n+ 378\n+ 379 friend class internal::gate::icursorstream_icursor_iterator;\n+ 380 size_type forward(size_type n = 1);\n+ 381 void insert_iterator(icursor_iterator *) noexcept;\n+ 382 void remove_iterator(icursor_iterator *) const noexcept;\n+ 383\n+ 384 void service_iterators(difference_type);\n 385\n+ 386 internal::sql_cursor m_cur;\n 387\n- 399 [[nodiscard]] int PQXX_PURE server_version() const noexcept;\n- 401\n- 403\n- 424 [[nodiscard]] std::string get_client_encoding() const;\n- 425\n- 427\n-430 void set_client_encoding(zview encoding) &\n- 431 {\n- 432 set_client_encoding(encoding.c_str());\n- 433 }\n+ 388 difference_type m_stride;\n+ 389 difference_type m_realpos, m_reqpos;\n+ 390\n+ 391 mutable icursor_iterator *m_iterators;\n+ 392\n+ 393 bool m_done;\n+ 394};\n+ 395\n+ 396\n+ 398\n+ 424class PQXX_LIBEXPORT icursor_iterator\n+ 425{\n+ 426public:\n+ 427 using iterator_category = std::input_iterator_tag;\n+ 428 using value_type = result;\n+ 429 using pointer = result const *;\n+ 430 using reference = result const &;\n+ 431 using istream_type = icursorstream;\n+ 432 using size_type = istream_type::size_type;\n+ 433 using difference_type = istream_type::difference_type;\n 434\n- 436\n- 439 void set_client_encoding(char const encoding[]) &;\n- 440\n- 442 [[nodiscard]] int encoding_id() const;\n- 443\n- 445\n- 447\n- 460 [[deprecated(\"To set session variables, use set_session_var.\")]] void\n- 461 set_variable(std::string_view var, std::string_view value) &;\n- 462\n- 464\n- 485 template\n-486 void set_session_var(std::string_view var, TYPE const &value) &\n- 487 {\n- 488 if constexpr (nullness::has_null)\n- 489 {\n- 490 if (nullness::is_null(value))\n- 491 throw variable_set_to_null{\n- 492 internal::concat(\"Attempted to set variable \", var, \" to null.\")};\n- 493 }\n- 494 exec(internal::concat(\"SET \", quote_name(var), \"=\", quote(value)));\n- 495 }\n- 496\n- 498\n- 501 [[deprecated(\"Use get_var instead.\")]] std::string\n- 502 get_variable(std::string_view);\n- 503\n- 505\n- 511 std::string get_var(std::string_view var);\n- 512\n- 514\n-520 template TYPE get_var_as(std::string_view var)\n- 521 {\n- 522 return from_string(get_var(var));\n- 523 }\n- 524\n- 530\n- 547 int get_notifs();\n- 548\n- 550\n- 562 int await_notification();\n- 563\n- 565\n- 577 int await_notification(std::time_t seconds, long microseconds);\n- 579\n- 611 [[nodiscard]] std::string\n-612 encrypt_password(zview user, zview password, zview algorithm)\n- 613 {\n- 614 return encrypt_password(user.c_str(), password.c_str(), algorithm.c_str\n-());\n- 615 }\n- 617 [[nodiscard]] std::string encrypt_password(\n- 618 char const user[], char const password[], char const *algorithm =\n-nullptr);\n- 620\n- 663\n- 665\n-669 void prepare(zview name, zview definition) &\n- 670 {\n- 671 prepare(name.c_str(), definition.c_str());\n- 672 }\n- 673\n- 678 void prepare(char const name[], char const definition[]) &;\n- 679\n- 681\n- 688 void prepare(char const definition[]) &;\n-689 void prepare(zview definition) & { return prepare(definition.c_str()); }\n- 690\n- 692 void unprepare(std::string_view name);\n- 693\n- 695\n- 696 // C++20: constexpr. Breaks ABI.\n- 698\n- 701 [[nodiscard]] std::string adorn_name(std::string_view);\n- 702\n- 707\n- 709\n- 713 [[deprecated(\"Use std::string_view or pqxx:zview.\")]] std::string\n-714 esc(char const text[], std::size_t maxlen) const\n- 715 {\n- 716 return esc(std::string_view{text, maxlen});\n- 717 }\n- 718\n-720 [[nodiscard]] std::string esc(char const text[]) const\n- 721 {\n- 722 return esc(std::string_view{text});\n- 723 }\n- 724\n- 725#if defined(PQXX_HAVE_SPAN)\n- 727\n- 738 [[nodiscard]] std::string_view\n- 739 esc(std::string_view text, std::span buffer)\n- 740 {\n- 741 auto const size{std::size(text)}, space{std::size(buffer)};\n- 742 auto const needed{2 * size + 1};\n- 743 if (space < needed)\n- 744 throw range_error{internal::concat(\n- 745 \"Not enough room to escape string of \", size, \" byte(s): need \",\n- 746 needed, \" bytes of buffer space, but buffer size is \", space, \".\")};\n- 747 auto const data{buffer.data()};\n- 748 return {data, esc_to_buf(text, data)};\n- 749 }\n- 750#endif\n- 751\n- 753\n- 756 [[nodiscard]] std::string esc(std::string_view text) const;\n- 757\n- 758#if defined(PQXX_HAVE_CONCEPTS)\n- 760\n- 761 template [[nodiscard]] std::string esc(DATA const &data)\n-const\n- 762 {\n- 763 return esc_raw(data);\n- 764 }\n- 765#endif\n- 766\n- 767#if defined(PQXX_HAVE_CONCEPTS) && defined(PQXX_HAVE_SPAN)\n- 769\n- 780 template\n- 781 [[nodiscard]] zview esc(DATA const &data, std::span buffer) const\n- 782 {\n- 783 auto const size{std::size(data)}, space{std::size(buffer)};\n- 784 auto const needed{internal::size_esc_bin(std::size(data))};\n- 785 if (space < needed)\n- 786 throw range_error{internal::concat(\n- 787 \"Not enough room to escape binary string of \", size, \" byte(s): need \",\n- 788 needed, \" bytes of buffer space, but buffer size is \", space, \".\")};\n- 789\n- 790 std::basic_string_view view{std::data(data), std::size(data)};\n- 791 auto const out{std::data(buffer)};\n- 792 // Actually, in the modern format, we know beforehand exactly how many\n- 793 // bytes we're going to fill. Just leave out the trailing zero.\n- 794 internal::esc_bin(view, out);\n- 795 return zview{out, needed - 1};\n- 796 }\n- 797#endif\n- 798\n- 800 [[deprecated(\"Use std::byte for binary data.\")]] std::string\n- 801 esc_raw(unsigned char const bin[], std::size_t len) const;\n- 802\n- 804\n- 805 [[nodiscard]] std::string esc_raw(std::basic_string_view)\n-const;\n- 806\n- 807#if defined(PQXX_HAVE_SPAN)\n- 809\n- 810 [[nodiscard]] std::string\n- 811 esc_raw(std::basic_string_view, std::span buffer) const;\n- 812#endif\n- 813\n- 814#if defined(PQXX_HAVE_CONCEPTS)\n- 816\n- 817 template\n- 818 [[nodiscard]] std::string esc_raw(DATA const &data) const\n- 819 {\n- 820 return esc_raw(\n- 821 std::basic_string_view{std::data(data), std::size(data)});\n- 822 }\n- 823#endif\n- 824\n- 825#if defined(PQXX_HAVE_CONCEPTS) && defined(PQXX_HAVE_SPAN)\n- 827 template\n- 828 [[nodiscard]] zview esc_raw(DATA const &data, std::span buffer)\n-const\n- 829 {\n- 830 return this->esc(binary_cast(data), buffer);\n- 831 }\n- 832#endif\n- 833\n- 835\n- 838 [[nodiscard, deprecated(\"Use unesc_bin() instead.\")]] std::string\n-839 unesc_raw(zview text) const\n- 840 {\n- 841#include \"pqxx/internal/ignore-deprecated-pre.hxx\"\n- 842 return unesc_raw(text.c_str());\n- 843#include \"pqxx/internal/ignore-deprecated-post.hxx\"\n- 844 }\n- 845\n- 847\n- 850 [[nodiscard, deprecated(\"Use unesc_bin() instead.\")]] std::string\n- 851 unesc_raw(char const text[]) const;\n- 852\n- 853 // TODO: Make \"into buffer\" variant to eliminate a string allocation.\n- 855\n- 862 [[nodiscard]] std::basic_string\n-863 unesc_bin(std::string_view text) const\n- 864 {\n- 865 std::basic_string buf;\n- 866 buf.resize(pqxx::internal::size_unesc_bin(std::size(text)));\n- 867 pqxx::internal::unesc_bin(text, buf.data());\n- 868 return buf;\n- 869 }\n- 870\n- 872 [[deprecated(\"Use quote(std::basic_string_view).\")]] std::\n-string\n- 873 quote_raw(unsigned char const bin[], std::size_t len) const;\n- 874\n- 876 std::string quote_raw(std::basic_string_view) const;\n- 877\n- 878#if defined(PQXX_HAVE_CONCEPTS)\n- 880\n- 881 template\n- 882 [[nodiscard]] std::string quote_raw(DATA const &data) const\n- 883 {\n- 884 return quote_raw(\n- 885 std::basic_string_view{std::data(data), std::size(data)});\n- 886 }\n- 887#endif\n- 888\n- 889 // TODO: Make \"into buffer\" variant to eliminate a string allocation.\n- 891 [[nodiscard]] std::string quote_name(std::string_view identifier) const;\n- 892\n- 893 // TODO: Make \"into buffer\" variant to eliminate a string allocation.\n- 895\n- 898 [[nodiscard]] std::string quote_table(std::string_view name) const;\n- 899\n- 900 // TODO: Make \"into buffer\" variant to eliminate a string allocation.\n- 902\n- 910 [[nodiscard]] std::string quote_table(table_path) const;\n- 911\n- 912 // TODO: Make \"into buffer\" variant to eliminate a string allocation.\n- 914\n- 921 template\n- 922 inline std::string quote_columns(STRINGS const &columns) const;\n- 923\n- 924 // TODO: Make \"into buffer\" variant to eliminate a string allocation.\n- 926\n- 929 template\n- 930 [[nodiscard]] inline std::string quote(T const &t) const;\n- 931\n- 932 [[deprecated(\"Use std::byte for binary data.\")]] std::string\n- 933 quote(binarystring const &) const;\n- 934\n- 935 // TODO: Make \"into buffer\" variant to eliminate a string allocation.\n- 937 [[nodiscard]] std::string\n- 938 quote(std::basic_string_view bytes) const;\n- 939\n- 940 // TODO: Make \"into buffer\" variant to eliminate a string allocation.\n- 942\n- 967 [[nodiscard]] std::string\n- 968 esc_like(std::string_view text, char escape_char = '\\\\') const;\n- 970\n- 972\n- 976 void cancel_query();\n- 977\n- 978#if defined(_WIN32) || __has_include()\n- 980\n- 984 void set_blocking(bool block) &;\n- 985#endif // defined(_WIN32) || __has_include()\n- 986\n- 988\n- 997 void set_verbosity(error_verbosity verbosity) &noexcept;\n- 998\n- 1000\n- 1012 [[nodiscard]] std::vector get_errorhandlers() const;\n- 1013\n- 1015\n- 1021 [[nodiscard]] std::string connection_string() const;\n- 1022\n- 1024\n- 1032 void close();\n- 1033\n- 1035\n-1041 static connection seize_raw_connection(internal::pq::PGconn *raw_conn)\n- 1042 {\n- 1043 return connection{raw_conn};\n- 1044 }\n- 1045\n- 1047\n-1052 internal::pq::PGconn *release_raw_connection() &&\n- 1053 {\n- 1054 return std::exchange(m_conn, nullptr);\n- 1055 }\n- 1056\n- 1057private:\n-1058 friend class connecting;\n- 1059 enum connect_mode\n- 1060 {\n- 1061 connect_nonblocking\n- 1062 };\n- 1063 connection(connect_mode, zview connection_string);\n- 1064\n- 1066 explicit connection(internal::pq::PGconn *raw_conn) : m_conn{raw_conn} {}\n- 1067\n- 1069\n- 1074 std::pair poll_connect();\n- 1075\n- 1076 // Initialise based on connection string.\n- 1077 void init(char const options[]);\n- 1078 // Initialise based on parameter names and values.\n- 1079 void init(char const *params[], char const *values[]);\n- 1080 void complete_init();\n- 1081\n- 1082 result make_result(\n- 1083 internal::pq::PGresult *pgr, std::shared_ptr const &query,\n- 1084 std::string_view desc = \"\"sv);\n- 1085\n- 1086 void PQXX_PRIVATE set_up_state();\n- 1087\n- 1088 int PQXX_PRIVATE PQXX_PURE status() const noexcept;\n- 1089\n- 1091\n- 1095 std::size_t esc_to_buf(std::string_view text, char *buf) const;\n- 1096\n-1097 friend class internal::gate::const_connection_largeobject;\n- 1098 char const *PQXX_PURE err_msg() const noexcept;\n- 1099\n- 1100 void PQXX_PRIVATE process_notice_raw(char const msg[]) noexcept;\n- 1101\n- 1102 result exec_prepared(std::string_view statement, internal::c_params const\n-&);\n- 1103\n- 1105 void check_movable() const;\n- 1107 void check_overwritable() const;\n- 1108\n-1109 friend class internal::gate::connection_errorhandler;\n- 1110 void PQXX_PRIVATE register_errorhandler(errorhandler *);\n- 1111 void PQXX_PRIVATE unregister_errorhandler(errorhandler *) noexcept;\n- 1112\n-1113 friend class internal::gate::connection_transaction;\n- 1114 result exec(std::string_view, std::string_view = \"\"sv);\n- 1115 result\n- 1116 PQXX_PRIVATE exec(std::shared_ptr, std::string_view = \"\"sv);\n- 1117 void PQXX_PRIVATE register_transaction(transaction_base *);\n- 1118 void PQXX_PRIVATE unregister_transaction(transaction_base *) noexcept;\n- 1119\n-1120 friend struct internal::gate::connection_stream_from;\n- 1121 std::pair, std::size_t>\n- 1122 read_copy_line();\n- 1123\n-1124 friend class internal::gate::connection_stream_to;\n- 1125 void PQXX_PRIVATE write_copy_line(std::string_view);\n- 1126 void PQXX_PRIVATE end_copy_write();\n- 1127\n-1128 friend class internal::gate::connection_largeobject;\n- 1129 internal::pq::PGconn *raw_connection() const { return m_conn; }\n- 1130\n-1131 friend class internal::gate::connection_notification_receiver;\n- 1132 void add_receiver(notification_receiver *);\n- 1133 void remove_receiver(notification_receiver *) noexcept;\n- 1134\n-1135 friend class internal::gate::connection_pipeline;\n- 1136 void PQXX_PRIVATE start_exec(char const query[]);\n- 1137 bool PQXX_PRIVATE consume_input() noexcept;\n- 1138 bool PQXX_PRIVATE is_busy() const noexcept;\n- 1139 internal::pq::PGresult *get_result();\n- 1140\n-1141 friend class internal::gate::connection_dbtransaction;\n-1142 friend class internal::gate::connection_sql_cursor;\n- 1143\n- 1144 result exec_params(std::string_view query, internal::c_params const\n-&args);\n- 1145\n- 1147 internal::pq::PGconn *m_conn = nullptr;\n- 1148\n- 1150\n- 1157 transaction_base const *m_trans = nullptr;\n- 1158\n- 1159 std::list m_errorhandlers;\n- 1160\n- 1161 using receiver_list =\n- 1162 std::multimap;\n- 1164 receiver_list m_receivers;\n- 1165\n- 1167 int m_unique_id = 0;\n- 1168};\n- 1169\n- 1170\n-1172using connection_base = connection;\n- 1173\n- 1174\n- 1176\n-1219class PQXX_LIBEXPORT connecting\n- 1220{\n- 1221public:\n-1223 connecting(zview connection_string = \"\"_zv);\n- 1224\n-1225 connecting(connecting const &) = delete;\n-1226 connecting(connecting &&) = default;\n-1227 connecting &operator=(connecting const &) = delete;\n-1228 connecting &operator=(connecting &&) = default;\n- 1229\n-1231 [[nodiscard]] int sock() const &noexcept { return m_conn.sock(); }\n- 1232\n-1234 [[nodiscard]] constexpr bool wait_to_read() const &noexcept\n- 1235 {\n- 1236 return m_reading;\n- 1237 }\n- 1238\n-1240 [[nodiscard]] constexpr bool wait_to_write() const &noexcept\n- 1241 {\n- 1242 return m_writing;\n- 1243 }\n- 1244\n-1246 void process() &;\n- 1247\n-1249 [[nodiscard]] constexpr bool done() const &noexcept\n- 1250 {\n- 1251 return not m_reading and not m_writing;\n- 1252 }\n- 1253\n- 1255\n-1263 [[nodiscard]] connection produce() &&;\n- 1264\n- 1265private:\n- 1266 connection m_conn;\n- 1267 bool m_reading{false};\n- 1268 bool m_writing{true};\n- 1269};\n- 1270\n- 1271\n-1272template inline std::string connection::quote(T const &t) const\n- 1273{\n- 1274 if constexpr (nullness::always_null)\n- 1275 {\n- 1276 return \"NULL\";\n- 1277 }\n- 1278 else\n- 1279 {\n- 1280 if (is_null(t))\n- 1281 return \"NULL\";\n- 1282 auto const text{to_string(t)};\n- 1283\n- 1284 // Okay, there's an easy way to do this and there's a hard way. The easy\n- 1285 // way was \"quote, esc(to_string(t)), quote\". I'm going with the hard way\n- 1286 // because it's going to save some string manipulation that will probably\n- 1287 // incur some unnecessary memory allocations and deallocations.\n- 1288 std::string buf{'\\''};\n- 1289 buf.resize(2 + 2 * std::size(text) + 1);\n- 1290 auto const content_bytes{esc_to_buf(text, buf.data() + 1)};\n- 1291 auto const closing_quote{1 + content_bytes};\n- 1292 buf[closing_quote] = '\\'';\n- 1293 auto const end{closing_quote + 1};\n- 1294 buf.resize(end);\n- 1295 return buf;\n- 1296 }\n- 1297}\n- 1298\n- 1299\n- 1300template\n-1301inline std::string connection::quote_columns(STRINGS const &columns) const\n- 1302{\n- 1303 return separated_list(\n- 1304 \",\"sv, std::cbegin(columns), std::cend(columns),\n- 1305 [this](auto col) { return this->quote_name(*col); });\n- 1306}\n- 1307\n- 1308\n- 1309#if defined(PQXX_HAVE_CONCEPTS)\n- 1310template\n- 1311inline connection::connection(MAPPING const ¶ms)\n- 1312{\n- 1313 check_version();\n- 1314\n- 1315 std::vector keys, values;\n- 1316 if constexpr (std::ranges::sized_range)\n- 1317 {\n- 1318 auto const size{std::ranges::size(params) + 1};\n- 1319 keys.reserve(size);\n- 1320 values.reserve(size);\n- 1321 }\n- 1322 for (auto const &[key, value] : params)\n- 1323 {\n- 1324 keys.push_back(internal::as_c_string(key));\n- 1325 values.push_back(internal::as_c_string(value));\n- 1326 }\n- 1327 keys.push_back(nullptr);\n- 1328 values.push_back(nullptr);\n- 1329 init(std::data(keys), std::data(values));\n- 1330}\n- 1331#endif // PQXX_HAVE_CONCEPTS\n- 1332} // namespace pqxx\n- 1333#endif\n+ 435 icursor_iterator() noexcept;\n+ 436 explicit icursor_iterator(istream_type &) noexcept;\n+ 437 icursor_iterator(icursor_iterator const &) noexcept;\n+ 438 ~icursor_iterator() noexcept;\n+ 439\n+ 440 result const &operator*() const\n+ 441 {\n+ 442 refresh();\n+ 443 return m_here;\n+ 444 }\n+ 445 result const *operator->() const\n+ 446 {\n+ 447 refresh();\n+ 448 return &m_here;\n+ 449 }\n+ 450 icursor_iterator &operator++();\n+ 451 icursor_iterator operator++(int);\n+ 452 icursor_iterator &operator+=(difference_type);\n+ 453 icursor_iterator &operator=(icursor_iterator const &) noexcept;\n+ 454\n+ 455 [[nodiscard]] bool operator==(icursor_iterator const &rhs) const;\n+ 456 [[nodiscard]] bool operator!=(icursor_iterator const &rhs) const noexcept\n+ 457 {\n+ 458 return not operator==(rhs);\n+ 459 }\n+ 460 [[nodiscard]] bool operator<(icursor_iterator const &rhs) const;\n+ 461 [[nodiscard]] bool operator>(icursor_iterator const &rhs) const\n+ 462 {\n+ 463 return rhs < *this;\n+ 464 }\n+ 465 [[nodiscard]] bool operator<=(icursor_iterator const &rhs) const\n+ 466 {\n+ 467 return not(*this > rhs);\n+ 468 }\n+ 469 [[nodiscard]] bool operator>=(icursor_iterator const &rhs) const\n+ 470 {\n+ 471 return not(*this < rhs);\n+ 472 }\n+ 473\n+ 474private:\n+ 475 void refresh() const;\n+ 476\n+ 477 friend class internal::gate::icursor_iterator_icursorstream;\n+ 478 difference_type pos() const noexcept { return m_pos; }\n+ 479 void fill(result const &);\n+ 480\n+ 481 icursorstream *m_stream{nullptr};\n+ 482 result m_here;\n+ 483 difference_type m_pos;\n+ 484 icursor_iterator *m_prev{nullptr}, *m_next{nullptr};\n+ 485};\n+ 486} // namespace pqxx\n+ 487#endif\n pqxx\n The home of all libpqxx classes, functions, templates, etc.\n Definition array.hxx:33\n-pqxx::separated_list\n-std::string separated_list(std::string_view sep, ITER begin, ITER end, ACCESS\n-access)\n-Represent sequence of values as a string, joined by a given separator.\n-Definition separated_list.hxx:44\n-pqxx::encrypt_password\n-std::string encrypt_password(char const user[], char const password[])\n-Encrypt a password.\n-Definition connection.cxx:94\n-pqxx::binary_cast\n-std::basic_string_view< std::byte > binary_cast(TYPE const &data)\n-Cast binary data to a type that libpqxx will recognise as binary.\n-Definition util.hxx:303\n-pqxx::skip_init_ssl\n-void skip_init_ssl() noexcept\n-Control initialisation of OpenSSL and libcrypto libraries.\n-Definition connection.hxx:173\n-pqxx::table_path\n-std::initializer_list< std::string_view > table_path\n-Representation of a PostgreSQL table path.\n-Definition connection.hxx:188\n-pqxx::check_version\n-void check_version() noexcept\n-Definition util.hxx:234\n-pqxx::to_string\n-std::string to_string(field const &value)\n-Convert a field to a string.\n-Definition result.cxx:549\n-pqxx::skip_init\n-skip_init\n-Flags for skipping initialisation of SSL-related libraries.\n-Definition connection.hxx:137\n-pqxx::crypto\n-@ crypto\n-Skip initialisation of libcrypto.\n-Definition connection.hxx:145\n-pqxx::openssl\n-@ openssl\n-Skip initialisation of OpenSSL library.\n-Definition connection.hxx:142\n-pqxx::nothing\n-@ nothing\n-A do-nothing flag that does not affect anything.\n-Definition connection.hxx:139\n-pqxx::error_verbosity\n-error_verbosity\n-Error verbosity levels.\n-Definition connection.hxx:210\n-pqxx::error_verbosity::terse\n-@ terse\n-pqxx::error_verbosity::verbose\n-@ verbose\n-pqxx::error_verbosity::normal\n-@ normal\n-pqxx::format::text\n-@ text\n-pqxx::internal\n-Internal items for libpqxx' own use. Do not use these yourself.\n-Definition composite.hxx:84\n-pqxx::internal::skip_init_ssl\n-void PQXX_COLD skip_init_ssl(int flags) noexcept\n-Control OpenSSL/crypto library initialisation.\n-Definition connection.cxx:83\n-pqxx::internal::unesc_bin\n-void unesc_bin(std::string_view escaped_data, std::byte buffer[])\n-Reconstitute binary data from its escaped version.\n-Definition util.cxx:158\n-pqxx::internal::esc_bin\n-void esc_bin(std::basic_string_view< std::byte > binary_data, char buffer[])\n-noexcept\n-Hex-escape binary data into a buffer.\n-Definition util.cxx:126\n-pqxx::internal::size_esc_bin\n-constexpr std::size_t size_esc_bin(std::size_t binary_bytes) noexcept\n-Compute buffer size needed to escape binary data for use as a BYTEA.\n-Definition util.hxx:411\n-pqxx::internal::as_c_string\n-constexpr char const * as_c_string(char const str[]) noexcept\n-Get a raw C string pointer.\n-Definition zview.hxx:145\n-pqxx::internal::size_unesc_bin\n-constexpr std::size_t size_unesc_bin(std::size_t escaped_bytes) noexcept\n-Compute binary size from the size of its escaped version.\n-Definition util.hxx:420\n+pqxx::result_difference_type\n+int result_difference_type\n+Difference between result sizes.\n+Definition types.hxx:31\n+pqxx::value_type\n+strip_t< decltype(*std::begin(std::declval< CONTAINER >()))> value_type\n+The type of a container's elements.\n+Definition types.hxx:107\n+pqxx::result_size_type\n+int result_size_type\n+Number of rows in a result set.\n+Definition types.hxx:28\n pqxx::internal::gate\n Definition connection.hxx:112\n pqxx::connection\n Connection to a database.\n Definition connection.hxx:253\n-pqxx::connection::encrypt_password\n-std::string encrypt_password(zview user, zview password, zview algorithm)\n-Encrypt a password for a given user.\n-Definition connection.hxx:612\n-pqxx::connection::prepare\n-void prepare(zview definition) &\n-Definition connection.hxx:689\n-pqxx::connection::connection\n-connection(char const options[])\n-Connect to a database, using options string.\n-Definition connection.hxx:258\n-pqxx::connection::operator=\n-connection & operator=(connection const &)=delete\n-pqxx::connection::get_var_as\n-TYPE get_var_as(std::string_view var)\n-Read currently applicable value of a variable.\n-Definition connection.hxx:520\n-pqxx::connection::connection\n-connection()\n-Definition connection.hxx:255\n-pqxx::connection::~connection\n-~connection()\n-Definition connection.hxx:299\n-pqxx::connection::quote_columns\n-std::string quote_columns(STRINGS const &columns) const\n-Quote and comma-separate a series of column names.\n-Definition connection.hxx:1301\n-pqxx::connection::connection\n-connection(zview options)\n-Connect to a database, using options string.\n-Definition connection.hxx:265\n-pqxx::connection::release_raw_connection\n-internal::pq::PGconn * release_raw_connection() &&\n-Release the raw connection without closing it.\n-Definition connection.hxx:1052\n-pqxx::connection::seize_raw_connection\n-static connection seize_raw_connection(internal::pq::PGconn *raw_conn)\n-Seize control of a raw libpq connection.\n-Definition connection.hxx:1041\n-pqxx::connection::unesc_bin\n-std::basic_string< std::byte > unesc_bin(std::string_view text) const\n-Unescape binary data, e.g. from a table field or notification payload.\n-Definition connection.hxx:863\n-pqxx::connection::esc\n-std::string esc(char const text[]) const\n-Escape string for use as SQL string literal on this connection.\n-Definition connection.hxx:720\n-pqxx::connection::unesc_raw\n-std::string unesc_raw(zview text) const\n-Unescape binary data, e.g. from a table field or notification payload.\n-Definition connection.hxx:839\n-pqxx::connection::esc\n-std::string esc(char const text[], std::size_t maxlen) const\n-Escape string for use as SQL string literal on this connection.\n-Definition connection.hxx:714\n-pqxx::connection::prepare\n-void prepare(zview name, zview definition) &\n-Define a prepared statement.\n-Definition connection.hxx:669\n-pqxx::connection::set_session_var\n-void set_session_var(std::string_view var, TYPE const &value) &\n-Set one of the session variables to a new value.\n-Definition connection.hxx:486\n-pqxx::connection::quote\n-std::string quote(T const &t) const\n-Represent object as SQL string, including quoting & escaping.\n-Definition connection.hxx:1272\n-pqxx::connection::connection\n-connection(connection const &)=delete\n-pqxx::connecting\n-An ongoing, non-blocking stepping stone to a connection.\n-Definition connection.hxx:1220\n-pqxx::connecting::connecting\n-connecting(connecting &&)=default\n-pqxx::connecting::sock\n-int sock() const &noexcept\n-Get the socket. The socket may change during the connection process.\n-Definition connection.hxx:1231\n-pqxx::connecting::done\n-constexpr bool done() const &noexcept\n-Is our connection finished?\n-Definition connection.hxx:1249\n-pqxx::connecting::operator=\n-connecting & operator=(connecting const &)=delete\n-pqxx::connecting::connecting\n-connecting(connecting const &)=delete\n-pqxx::connecting::wait_to_write\n-constexpr bool wait_to_write() const &noexcept\n-Should we currently wait to be able to write to the socket?\n-Definition connection.hxx:1240\n-pqxx::connecting::process\n-void process() &\n-Progress towards completion (but don't block).\n-pqxx::connecting::operator=\n-connecting & operator=(connecting &&)=default\n-pqxx::connecting::wait_to_read\n-constexpr bool wait_to_read() const &noexcept\n-Should we currently wait to be able to read from the socket?\n-Definition connection.hxx:1234\n-pqxx::connecting::connecting\n-connecting(zview connection_string=\"\"_zv)\n-Start connecting.\n-pqxx::connecting::produce\n-connection produce() &&\n-Produce the completed connection object.\n-pqxx::errorhandler\n-Base class for error-handler callbacks.\n-Definition errorhandler.hxx:54\n-pqxx::variable_set_to_null\n-The caller attempted to set a variable to null, which is not allowed.\n-Definition except.hxx:116\n-pqxx::notification_receiver\n-Definition notification.hxx:57\n-pqxx::params\n-Build a parameter list for a parameterised or prepared statement.\n-Definition params.hxx:220\n+pqxx::cursor_base\n+Common definitions for cursor types.\n+Definition cursor.hxx:42\n+pqxx::cursor_base::operator=\n+cursor_base & operator=(cursor_base const &)=delete\n+pqxx::cursor_base::name\n+constexpr std::string const & name() const noexcept\n+Name of underlying SQL cursor.\n+Definition cursor.hxx:142\n+pqxx::cursor_base::size_type\n+result_size_type size_type\n+Definition cursor.hxx:44\n+pqxx::cursor_base::next\n+static constexpr difference_type next() noexcept\n+Special value: read one row only.\n+Definition cursor.hxx:116\n+pqxx::cursor_base::cursor_base\n+cursor_base(cursor_base const &)=delete\n+pqxx::cursor_base::all\n+static constexpr difference_type all() noexcept\n+Special value: read until end.\n+Definition cursor.hxx:108\n+pqxx::cursor_base::prior\n+static constexpr difference_type prior() noexcept\n+Special value: read backwards, one row only.\n+Definition cursor.hxx:121\n+pqxx::cursor_base::cursor_base\n+cursor_base()=delete\n+pqxx::cursor_base::access_policy\n+access_policy\n+Cursor access-pattern policy.\n+Definition cursor.hxx:52\n+pqxx::cursor_base::forward_only\n+@ forward_only\n+Cursor can move forward only.\n+Definition cursor.hxx:54\n+pqxx::cursor_base::ownership_policy\n+ownership_policy\n+Cursor destruction policy.\n+Definition cursor.hxx:88\n+pqxx::cursor_base::owned\n+@ owned\n+Destroy SQL cursor when cursor object is closed at end of transaction.\n+Definition cursor.hxx:90\n+pqxx::cursor_base::update_policy\n+update_policy\n+Cursor update policy.\n+Definition cursor.hxx:64\n+pqxx::cursor_base::read_only\n+@ read_only\n+Cursor can be used to read data but not to write.\n+Definition cursor.hxx:66\n+pqxx::cursor_base::difference_type\n+result_difference_type difference_type\n+Definition cursor.hxx:45\n+pqxx::cursor_base::m_name\n+std::string const m_name\n+Definition cursor.hxx:150\n+pqxx::cursor_base::backward_all\n+static constexpr difference_type backward_all() noexcept\n+Special value: read backwards from current position back to origin.\n+Definition cursor.hxx:129\n+pqxx::stateless_cursor\n+\"Stateless cursor\" class: easy API for retrieving parts of result sets\n+Definition cursor.hxx:169\n+pqxx::stateless_cursor::name\n+constexpr std::string const & name() const noexcept\n+Return this cursor's name.\n+Definition cursor.hxx:239\n+pqxx::stateless_cursor::close\n+void close() noexcept\n+Close this cursor.\n+Definition cursor.hxx:209\n+pqxx::stateless_cursor::size_type\n+result_size_type size_type\n+Definition cursor.hxx:171\n+pqxx::stateless_cursor::difference_type\n+result_difference_type difference_type\n+Definition cursor.hxx:172\n+pqxx::stateless_cursor::retrieve\n+result retrieve(difference_type begin_pos, difference_type end_pos)\n+Retrieve rows from begin_pos (inclusive) to end_pos (exclusive)\n+Definition cursor.hxx:232\n+pqxx::stateless_cursor::stateless_cursor\n+stateless_cursor(transaction_base &tx, std::string_view query, std::string_view\n+cname, bool hold)\n+Create cursor.\n+Definition cursor.hxx:183\n+pqxx::stateless_cursor::size\n+size_type size()\n+Number of rows in cursor's result set.\n+Definition cursor.hxx:215\n+pqxx::stateless_cursor::stateless_cursor\n+stateless_cursor(transaction_base &tx, std::string_view adopted_cursor)\n+Adopt an existing scrolling SQL cursor.\n+Definition cursor.hxx:196\n pqxx::result\n Result set containing data returned by a query or command.\n Definition result.hxx:73\n-pqxx::nullness\n-Traits describing a type's \"null value,\" if any.\n-Definition strconv.hxx:93\n+pqxx::result::difference_type\n+result_difference_type difference_type\n+Definition result.hxx:76\n pqxx::transaction_base\n Interface definition (and common code) for \"transaction\" classes.\n Definition transaction_base.hxx:88\n-pqxx::zview\n-Marker-type wrapper: zero-terminated std::string_view.\n-Definition zview.hxx:38\n-pqxx::zview::c_str\n-constexpr char const * c_str() const &noexcept\n-Either a null pointer, or a zero-terminated text buffer.\n-Definition zview.hxx:96\n * include\n * pqxx\n- * connection.hxx\n+ * cursor.hxx\n * Generated by [doxygen] 1.9.8\n"}]}, {"source1": "./usr/share/doc/libpqxx-doc/html/a00029_source.html", "source2": "./usr/share/doc/libpqxx-doc/html/a00029_source.html", "unified_diff": "@@ -1,15 +1,15 @@\n \n \n \n \n \n \n \n-libpqxx: config-internal-compiler.h Source File\n+libpqxx: config-public-autotools.h Source File\n \n \n \n \n \n \n \n@@ -60,29 +60,23 @@\n \n
\n
\n-
config-internal-compiler.h
\n+
config-public-autotools.h
\n
\n
\n-
1/* Automatically generated from config.h: internal/compiler config. */
\n+
1/* Automatically generated from config.h: public/autotools config. */
\n
2
\n-
3#define PQXX_HAVE_CHARCONV_FLOAT 1
\n-
4#define PQXX_HAVE_CHARCONV_INT 1
\n-
5#define PQXX_HAVE_CXA_DEMANGLE 1
\n-
6#define PQXX_HAVE_POLL 1
\n-
7#define PQXX_HAVE_SLEEP_FOR 1
\n-
8#define PQXX_HAVE_THREAD_LOCAL 1
\n
\n
\n \n
\n \n
\n \n \n", "details": [{"source1": "html2text {}", "source2": "html2text {}", "unified_diff": "@@ -1,20 +1,14 @@\n \n \n \n \n \n libpqxx\u00a07.8.1\n \n-config-internal-compiler.h\n- 1/* Automatically generated from config.h: internal/compiler config. */\n+config-public-autotools.h\n+ 1/* Automatically generated from config.h: public/autotools config. */\n 2\n- 3#define PQXX_HAVE_CHARCONV_FLOAT 1\n- 4#define PQXX_HAVE_CHARCONV_INT 1\n- 5#define PQXX_HAVE_CXA_DEMANGLE 1\n- 6#define PQXX_HAVE_POLL 1\n- 7#define PQXX_HAVE_SLEEP_FOR 1\n- 8#define PQXX_HAVE_THREAD_LOCAL 1\n * include\n * pqxx\n- * config-internal-compiler.h\n+ * config-public-autotools.h\n * Generated by [doxygen] 1.9.8\n"}]}, {"source1": "./usr/share/doc/libpqxx-doc/html/a00032_source.html", "source2": "./usr/share/doc/libpqxx-doc/html/a00032_source.html", "unified_diff": "@@ -1,15 +1,15 @@\n \n \n \n \n \n \n \n-libpqxx: transactor.hxx Source File\n+libpqxx: types.hxx Source File\n \n \n \n \n \n \n \n@@ -60,111 +60,185 @@\n \n
\n
\n-
transactor.hxx
\n+
types.hxx
\n
\n
\n-
1/* Transactor framework, a wrapper for safely retryable transactions.
\n+
1/* Basic type aliases and forward declarations.
\n
2 *
\n-
3 * DO NOT INCLUDE THIS FILE DIRECTLY; include pqxx/transactor instead.
\n+
3 * Copyright (c) 2000-2023, Jeroen T. Vermeulen
\n
4 *
\n-
5 * Copyright (c) 2000-2023, Jeroen T. Vermeulen.
\n-
6 *
\n-
7 * See COPYING for copyright license. If you did not receive a file called
\n-
8 * COPYING with this source code, please notify the distributor of this
\n-
9 * mistake, or contact the author.
\n-
10 */
\n-
11#ifndef PQXX_H_TRANSACTOR
\n-
12#define PQXX_H_TRANSACTOR
\n-
13
\n-
14#if !defined(PQXX_HEADER_PRE)
\n-
15# error "Include libpqxx headers as <pqxx/header>, not <pqxx/header.hxx>."
\n-
16#endif
\n-
17
\n-
18#include <functional>
\n-
19#include <type_traits>
\n-
20
\n-
21#include "pqxx/connection.hxx"
\n-
22#include "pqxx/transaction.hxx"
\n+
5 * See COPYING for copyright license. If you did not receive a file called
\n+
6 * COPYING with this source code, please notify the distributor of this
\n+
7 * mistake, or contact the author.
\n+
8 */
\n+
9#ifndef PQXX_H_TYPES
\n+
10#define PQXX_H_TYPES
\n+
11
\n+
12#if !defined(PQXX_HEADER_PRE)
\n+
13# error "Include libpqxx headers as <pqxx/header>, not <pqxx/header.hxx>."
\n+
14#endif
\n+
15
\n+
16#include <cstddef>
\n+
17#include <cstdint>
\n+
18#include <iterator>
\n+
19
\n+
20#if defined(PQXX_HAVE_CONCEPTS) && __has_include(<ranges>)
\n+
21# include <ranges>
\n+
22#endif
\n
23
\n-
24namespace pqxx
\n-
25{
\n+
24
\n+
25namespace pqxx
\n+
26{
\n+
28using result_size_type = int;
\n+
29
\n+\n+
32
\n+
34using row_size_type = int;
\n+
35
\n+\n+
38
\n+
40using field_size_type = std::size_t;
\n+
41
\n+
43using large_object_size_type = int64_t;
\n+
44
\n+
45
\n+
46// Forward declarations, to help break compilation dependencies.
\n+
47// These won't necessarily include all classes in libpqxx.
\n+
48class binarystring;
\n+
49class connection;
\n+
50class const_result_iterator;
\n+
51class const_reverse_result_iterator;
\n+\n+\n+
54class dbtransaction;
\n+
55class field;
\n+\n+\n+
58struct range_error;
\n+
59class result;
\n+
60class row;
\n+
61class stream_from;
\n+\n+
63
\n+
65
\n+
\n+\n+
68{};
\n+
\n
69
\n
71
\n-
100template<typename TRANSACTION_CALLBACK>
\n-
\n-
101inline auto perform(TRANSACTION_CALLBACK &&callback, int attempts = 3)
\n-
102 -> std::invoke_result_t<TRANSACTION_CALLBACK>
\n-
103{
\n-
104 if (attempts <= 0)
\n-
105 throw std::invalid_argument{
\n-
106 "Zero or negative number of attempts passed to pqxx::perform()."};
\n-
107
\n-
108 for (; attempts > 0; --attempts)
\n-
109 {
\n-
110 try
\n-
111 {
\n-
112 return std::invoke(callback);
\n-
113 }
\n-
114 catch (in_doubt_error const &)
\n-
115 {
\n-
116 // Not sure whether transaction went through or not. The last thing in
\n-
117 // the world that we should do now is try again!
\n-
118 throw;
\n-
119 }
\n-
120 catch (statement_completion_unknown const &)
\n-
121 {
\n-
122 // Not sure whether our last statement succeeded. Don't risk running it
\n-
123 // again.
\n-
124 throw;
\n-
125 }
\n-
126 catch (protocol_violation const &)
\n-
127 {
\n-
128 // This is a subclass of broken_connection, but it's not one where
\n-
129 // retrying is likely to do us any good.
\n-
130 throw;
\n-
131 }
\n-
132 catch (broken_connection const &)
\n-
133 {
\n-
134 // Connection failed. May be worth retrying, if the transactor opens its
\n-
135 // own connection.
\n-
136 if (attempts <= 1)
\n-
137 throw;
\n-
138 continue;
\n-
139 }
\n-
140 catch (transaction_rollback const &)
\n-
141 {
\n-
142 // Some error that may well be transient, such as serialization failure
\n-
143 // or deadlock. Worth retrying.
\n-
144 if (attempts <= 1)
\n-
145 throw;
\n-
146 continue;
\n-
147 }
\n-
148 }
\n-
149 throw pqxx::internal_error{"No outcome reached on perform()."};
\n-
150}
\n+
\n+\n+
74{};
\n+
\n+
75
\n+
76
\n+
78
\n+
\n+
80enum class format : int
\n+
81{
\n+
82 text = 0,
\n+
83 binary = 1,
\n+
84};
\n
\n-
151} // namespace pqxx
\n-
153#endif
\n+
85
\n+
86
\n+
88
\n+
90template<typename TYPE>
\n+
91using strip_t = std::remove_cv_t<std::remove_reference_t<TYPE>>;
\n+
92
\n+
93
\n+
94#if defined(PQXX_HAVE_CONCEPTS)
\n+
96
\n+
99template<std::ranges::range CONTAINER>
\n+\n+
101#else // PQXX_HAVE_CONCEPTS
\n+
103
\n+
106template<typename CONTAINER>
\n+\n+
108#endif // PQXX_HAVE_CONCEPTS
\n+
109
\n+
110
\n+
111#if defined(PQXX_HAVE_CONCEPTS)
\n+
113template<typename STRING>
\n+
114concept char_string = std::ranges::contiguous_range<STRING> and
\n+
115 std::same_as<strip_t<value_type<STRING>>, char>;
\n+
116
\n+
118template<typename RANGE>
\n+
119concept char_strings =
\n+
120 std::ranges::range<RANGE> and char_string<strip_t<value_type<RANGE>>>;
\n+
121
\n+
123template<typename DATA>
\n+
124concept potential_binary = std::ranges::contiguous_range<DATA> and
\n+
125 (sizeof(value_type<DATA>) == 1);
\n+
126#endif // PQXX_HAVE_CONCEPTS
\n+
127
\n+
128
\n+
129// C++20: Retire these compatibility definitions.
\n+
130#if defined(PQXX_HAVE_CONCEPTS)
\n+
131
\n+
133
\n+
136# define PQXX_RANGE_ARG std::ranges::range
\n+
137
\n+
139
\n+
142# define PQXX_CHAR_STRING_ARG pqxx::char_string
\n+
143
\n+
145
\n+
148# define PQXX_CHAR_STRINGS_ARG pqxx::char_strings
\n+
149
\n+
150#else // PQXX_HAVE_CONCEPTS
\n+
151
\n+
153
\n+
156# define PQXX_RANGE_ARG typename
\n+
157
\n+
159
\n+
162# define PQXX_CHAR_STRING_ARG typename
\n+
163
\n+
165
\n+
168# define PQXX_CHAR_STRINGS_ARG typename
\n+
169
\n+
170#endif // PQXX_HAVE_CONCEPTS
\n+
171} // namespace pqxx
\n+
172#endif
\n
The home of all libpqxx classes, functions, templates, etc.
Definition array.hxx:33
\n-
auto perform(TRANSACTION_CALLBACK &&callback, int attempts=3) -> std::invoke_result_t< TRANSACTION_CALLBACK >
Simple way to execute a transaction with automatic retry.
Definition transactor.hxx:101
\n-
Exception class for lost or failed backend connection.
Definition except.hxx:81
\n-
Exception class for micommunication with the server.
Definition except.hxx:103
\n-
"Help, I don't know whether transaction was committed successfully!"
Definition except.hxx:165
\n-
The backend saw itself forced to roll back the ongoing transaction.
Definition except.hxx:178
\n-
We can't tell whether our last statement succeeded.
Definition except.hxx:214
\n-
Internal error in libpqxx library.
Definition except.hxx:242
\n+
int row_size_type
Number of fields in a row of database data.
Definition types.hxx:34
\n+
std::remove_cv_t< std::remove_reference_t< TYPE > > strip_t
Remove any constness, volatile, and reference-ness from a type.
Definition types.hxx:91
\n+
int row_difference_type
Difference between row sizes.
Definition types.hxx:37
\n+
std::size_t field_size_type
Number of bytes in a field of database data.
Definition types.hxx:40
\n+
int result_difference_type
Difference between result sizes.
Definition types.hxx:31
\n+
strip_t< decltype(*std::begin(std::declval< CONTAINER >()))> value_type
The type of a container's elements.
Definition types.hxx:107
\n+
int result_size_type
Number of rows in a result set.
Definition types.hxx:28
\n+
int64_t large_object_size_type
Number of bytes in a large object.
Definition types.hxx:43
\n+
format
Format code: is data text or binary?
Definition types.hxx:81
\n+\n+\n+
Binary data corresponding to PostgreSQL's "BYTEA" binary-string type.
Definition binarystring.hxx:59
\n+
Connection to a database.
Definition connection.hxx:253
\n+
Abstract transaction base class: bracket transactions on the database.
Definition dbtransaction.hxx:54
\n+
Something is out of range, similar to std::out_of_range.
Definition except.hxx:326
\n+
Reference to a field in a result set.
Definition field.hxx:35
\n+
Accessor for large object's contents.
Definition largeobject.hxx:154
\n+
Definition notification.hxx:57
\n+
Result set containing data returned by a query or command.
Definition result.hxx:73
\n+
Reference to one row in a result.
Definition row.hxx:47
\n+
Iterator for fields in a row. Use as row::const_iterator.
Definition row.hxx:283
\n+
Reverse iterator for a row. Use as row::const_reverse_iterator.
Definition row.hxx:398
\n+
Stream data from the database.
Definition stream_from.hxx:79
\n+
Interface definition (and common code) for "transaction" classes.
Definition transaction_base.hxx:88
\n+
Marker for stream_from constructors: "stream from table.".
Definition types.hxx:68
\n+
Marker for stream_from constructors: "stream from query.".
Definition types.hxx:74
\n
\n
\n \n
\n \n
\n \n \n", "details": [{"source1": "html2text {}", "source2": "html2text {}", "unified_diff": "@@ -1,118 +1,232 @@\n \n \n \n \n \n libpqxx\u00a07.8.1\n \n-transactor.hxx\n- 1/* Transactor framework, a wrapper for safely retryable transactions.\n+types.hxx\n+ 1/* Basic type aliases and forward declarations.\n 2 *\n- 3 * DO NOT INCLUDE THIS FILE DIRECTLY; include pqxx/transactor instead.\n+ 3 * Copyright (c) 2000-2023, Jeroen T. Vermeulen\n 4 *\n- 5 * Copyright (c) 2000-2023, Jeroen T. Vermeulen.\n- 6 *\n- 7 * See COPYING for copyright license. If you did not receive a file called\n- 8 * COPYING with this source code, please notify the distributor of this\n- 9 * mistake, or contact the author.\n- 10 */\n- 11#ifndef PQXX_H_TRANSACTOR\n- 12#define PQXX_H_TRANSACTOR\n- 13\n- 14#if !defined(PQXX_HEADER_PRE)\n- 15# error \"Include libpqxx headers as , not .\"\n- 16#endif\n- 17\n- 18#include \n- 19#include \n- 20\n- 21#include \"pqxx/connection.hxx\"\n- 22#include \"pqxx/transaction.hxx\"\n+ 5 * See COPYING for copyright license. If you did not receive a file called\n+ 6 * COPYING with this source code, please notify the distributor of this\n+ 7 * mistake, or contact the author.\n+ 8 */\n+ 9#ifndef PQXX_H_TYPES\n+ 10#define PQXX_H_TYPES\n+ 11\n+ 12#if !defined(PQXX_HEADER_PRE)\n+ 13# error \"Include libpqxx headers as , not .\"\n+ 14#endif\n+ 15\n+ 16#include \n+ 17#include \n+ 18#include \n+ 19\n+ 20#if defined(PQXX_HAVE_CONCEPTS) && __has_include()\n+ 21# include \n+ 22#endif\n 23\n- 24namespace pqxx\n- 25{\n+ 24\n+ 25namespace pqxx\n+ 26{\n+28using result_size_type = int;\n+ 29\n+31using result_difference_type = int;\n+ 32\n+34using row_size_type = int;\n+ 35\n+37using row_difference_type = int;\n+ 38\n+40using field_size_type = std::size_t;\n+ 41\n+43using large_object_size_type = int64_t;\n+ 44\n+ 45\n+ 46// Forward declarations, to help break compilation dependencies.\n+ 47// These won't necessarily include all classes in libpqxx.\n+ 48class binarystring;\n+ 49class connection;\n+ 50class const_result_iterator;\n+ 51class const_reverse_result_iterator;\n+ 52class const_reverse_row_iterator;\n+ 53class const_row_iterator;\n+ 54class dbtransaction;\n+ 55class field;\n+ 56class largeobjectaccess;\n+ 57class notification_receiver;\n+ 58struct range_error;\n+ 59class result;\n+ 60class row;\n+ 61class stream_from;\n+ 62class transaction_base;\n+ 63\n+ 65\n+67struct from_table_t\n+ 68{};\n 69\n 71\n- 100template\n-101inline auto perform(TRANSACTION_CALLBACK &&callback, int attempts = 3)\n- 102 -> std::invoke_result_t\n- 103{\n- 104 if (attempts <= 0)\n- 105 throw std::invalid_argument{\n- 106 \"Zero or negative number of attempts passed to pqxx::perform().\"};\n- 107\n- 108 for (; attempts > 0; --attempts)\n- 109 {\n- 110 try\n- 111 {\n- 112 return std::invoke(callback);\n- 113 }\n- 114 catch (in_doubt_error const &)\n- 115 {\n- 116 // Not sure whether transaction went through or not. The last thing in\n- 117 // the world that we should do now is try again!\n- 118 throw;\n- 119 }\n- 120 catch (statement_completion_unknown const &)\n- 121 {\n- 122 // Not sure whether our last statement succeeded. Don't risk running it\n- 123 // again.\n- 124 throw;\n- 125 }\n- 126 catch (protocol_violation const &)\n- 127 {\n- 128 // This is a subclass of broken_connection, but it's not one where\n- 129 // retrying is likely to do us any good.\n- 130 throw;\n- 131 }\n- 132 catch (broken_connection const &)\n- 133 {\n- 134 // Connection failed. May be worth retrying, if the transactor opens its\n- 135 // own connection.\n- 136 if (attempts <= 1)\n- 137 throw;\n- 138 continue;\n- 139 }\n- 140 catch (transaction_rollback const &)\n- 141 {\n- 142 // Some error that may well be transient, such as serialization failure\n- 143 // or deadlock. Worth retrying.\n- 144 if (attempts <= 1)\n- 145 throw;\n- 146 continue;\n- 147 }\n- 148 }\n- 149 throw pqxx::internal_error{\"No outcome reached on perform().\"};\n- 150}\n- 151} // namespace pqxx\n- 153#endif\n+73struct from_query_t\n+ 74{};\n+ 75\n+ 76\n+ 78\n+80enum class format : int\n+ 81{\n+ 82 text = 0,\n+ 83 binary = 1,\n+ 84};\n+ 85\n+ 86\n+ 88\n+ 90template\n+91using strip_t = std::remove_cv_t>;\n+ 92\n+ 93\n+ 94#if defined(PQXX_HAVE_CONCEPTS)\n+ 96\n+ 99template\n+ 100using value_type = strip_t\n+()))>;\n+ 101#else // PQXX_HAVE_CONCEPTS\n+ 103\n+ 106template\n+107using value_type = strip_t\n+()))>;\n+ 108#endif // PQXX_HAVE_CONCEPTS\n+ 109\n+ 110\n+ 111#if defined(PQXX_HAVE_CONCEPTS)\n+ 113template\n+ 114concept char_string = std::ranges::contiguous_range and\n+ 115 std::same_as>, char>;\n+ 116\n+ 118template\n+ 119concept char_strings =\n+ 120 std::ranges::range and char_string>>;\n+ 121\n+ 123template\n+ 124concept potential_binary = std::ranges::contiguous_range and\n+ 125 (sizeof(value_type) == 1);\n+ 126#endif // PQXX_HAVE_CONCEPTS\n+ 127\n+ 128\n+ 129// C++20: Retire these compatibility definitions.\n+ 130#if defined(PQXX_HAVE_CONCEPTS)\n+ 131\n+ 133\n+ 136# define PQXX_RANGE_ARG std::ranges::range\n+ 137\n+ 139\n+ 142# define PQXX_CHAR_STRING_ARG pqxx::char_string\n+ 143\n+ 145\n+ 148# define PQXX_CHAR_STRINGS_ARG pqxx::char_strings\n+ 149\n+ 150#else // PQXX_HAVE_CONCEPTS\n+ 151\n+ 153\n+ 156# define PQXX_RANGE_ARG typename\n+ 157\n+ 159\n+ 162# define PQXX_CHAR_STRING_ARG typename\n+ 163\n+ 165\n+ 168# define PQXX_CHAR_STRINGS_ARG typename\n+ 169\n+ 170#endif // PQXX_HAVE_CONCEPTS\n+ 171} // namespace pqxx\n+ 172#endif\n pqxx\n The home of all libpqxx classes, functions, templates, etc.\n Definition array.hxx:33\n-pqxx::perform\n-auto perform(TRANSACTION_CALLBACK &&callback, int attempts=3) -> std::\n-invoke_result_t< TRANSACTION_CALLBACK >\n-Simple way to execute a transaction with automatic retry.\n-Definition transactor.hxx:101\n-pqxx::broken_connection\n-Exception class for lost or failed backend connection.\n-Definition except.hxx:81\n-pqxx::protocol_violation\n-Exception class for micommunication with the server.\n-Definition except.hxx:103\n-pqxx::in_doubt_error\n-\"Help, I don't know whether transaction was committed successfully!\"\n-Definition except.hxx:165\n-pqxx::transaction_rollback\n-The backend saw itself forced to roll back the ongoing transaction.\n-Definition except.hxx:178\n-pqxx::statement_completion_unknown\n-We can't tell whether our last statement succeeded.\n-Definition except.hxx:214\n-pqxx::internal_error\n-Internal error in libpqxx library.\n-Definition except.hxx:242\n+pqxx::row_size_type\n+int row_size_type\n+Number of fields in a row of database data.\n+Definition types.hxx:34\n+pqxx::strip_t\n+std::remove_cv_t< std::remove_reference_t< TYPE > > strip_t\n+Remove any constness, volatile, and reference-ness from a type.\n+Definition types.hxx:91\n+pqxx::row_difference_type\n+int row_difference_type\n+Difference between row sizes.\n+Definition types.hxx:37\n+pqxx::field_size_type\n+std::size_t field_size_type\n+Number of bytes in a field of database data.\n+Definition types.hxx:40\n+pqxx::result_difference_type\n+int result_difference_type\n+Difference between result sizes.\n+Definition types.hxx:31\n+pqxx::value_type\n+strip_t< decltype(*std::begin(std::declval< CONTAINER >()))> value_type\n+The type of a container's elements.\n+Definition types.hxx:107\n+pqxx::result_size_type\n+int result_size_type\n+Number of rows in a result set.\n+Definition types.hxx:28\n+pqxx::large_object_size_type\n+int64_t large_object_size_type\n+Number of bytes in a large object.\n+Definition types.hxx:43\n+pqxx::format\n+format\n+Format code: is data text or binary?\n+Definition types.hxx:81\n+pqxx::format::text\n+@ text\n+pqxx::format::binary\n+@ binary\n+pqxx::binarystring\n+Binary data corresponding to PostgreSQL's \"BYTEA\" binary-string type.\n+Definition binarystring.hxx:59\n+pqxx::connection\n+Connection to a database.\n+Definition connection.hxx:253\n+pqxx::dbtransaction\n+Abstract transaction base class: bracket transactions on the database.\n+Definition dbtransaction.hxx:54\n+pqxx::range_error\n+Something is out of range, similar to std::out_of_range.\n+Definition except.hxx:326\n+pqxx::field\n+Reference to a field in a result set.\n+Definition field.hxx:35\n+pqxx::largeobjectaccess\n+Accessor for large object's contents.\n+Definition largeobject.hxx:154\n+pqxx::notification_receiver\n+Definition notification.hxx:57\n+pqxx::result\n+Result set containing data returned by a query or command.\n+Definition result.hxx:73\n+pqxx::row\n+Reference to one row in a result.\n+Definition row.hxx:47\n+pqxx::const_row_iterator\n+Iterator for fields in a row. Use as row::const_iterator.\n+Definition row.hxx:283\n+pqxx::const_reverse_row_iterator\n+Reverse iterator for a row. Use as row::const_reverse_iterator.\n+Definition row.hxx:398\n+pqxx::stream_from\n+Stream data from the database.\n+Definition stream_from.hxx:79\n+pqxx::transaction_base\n+Interface definition (and common code) for \"transaction\" classes.\n+Definition transaction_base.hxx:88\n+pqxx::from_table_t\n+Marker for stream_from constructors: \"stream from table.\".\n+Definition types.hxx:68\n+pqxx::from_query_t\n+Marker for stream_from constructors: \"stream from query.\".\n+Definition types.hxx:74\n * include\n * pqxx\n- * transactor.hxx\n+ * types.hxx\n * Generated by [doxygen] 1.9.8\n"}]}, {"source1": "./usr/share/doc/libpqxx-doc/html/a00035_source.html", "source2": "./usr/share/doc/libpqxx-doc/html/a00035_source.html", "unified_diff": "@@ -1,15 +1,15 @@\n \n \n \n \n \n \n \n-libpqxx: transaction_focus.hxx Source File\n+libpqxx: strconv.hxx Source File\n \n \n \n \n \n \n \n@@ -60,154 +60,435 @@\n \n
\n
\n-
transaction_focus.hxx
\n+
strconv.hxx
\n
\n
\n-
1
\n-
9#ifndef PQXX_H_TRANSACTION_FOCUS
\n-
10#define PQXX_H_TRANSACTION_FOCUS
\n-
11
\n-
12#if !defined(PQXX_HEADER_PRE)
\n-
13# error "Include libpqxx headers as <pqxx/header>, not <pqxx/header.hxx>."
\n-
14#endif
\n-
15
\n-
16#include "pqxx/util.hxx"
\n+
1/* String conversion definitions.
\n+
2 *
\n+
3 * DO NOT INCLUDE THIS FILE DIRECTLY; include pqxx/stringconv instead.
\n+
4 *
\n+
5 * Copyright (c) 2000-2023, Jeroen T. Vermeulen.
\n+
6 *
\n+
7 * See COPYING for copyright license. If you did not receive a file called
\n+
8 * COPYING with this source code, please notify the distributor of this
\n+
9 * mistake, or contact the author.
\n+
10 */
\n+
11#ifndef PQXX_H_STRCONV
\n+
12#define PQXX_H_STRCONV
\n+
13
\n+
14#if !defined(PQXX_HEADER_PRE)
\n+
15# error "Include libpqxx headers as <pqxx/header>, not <pqxx/header.hxx>."
\n+
16#endif
\n
17
\n-
18namespace pqxx
\n-
19{
\n-
21
\n-
\n-
28class PQXX_LIBEXPORT transaction_focus
\n-
29{
\n-
30public:
\n-
\n-\n-
32 transaction_base &t, std::string_view cname, std::string_view oname) :
\n-
33 m_trans{&t}, m_classname{cname}, m_name{oname}
\n-
34 {}
\n-
\n-
35
\n-
\n-\n-
37 transaction_base &t, std::string_view cname, std::string &&oname) :
\n-
38 m_trans{&t}, m_classname{cname}, m_name{std::move(oname)}
\n-
39 {}
\n-
\n-
40
\n-
\n-
41 transaction_focus(transaction_base &t, std::string_view cname) :
\n-
42 m_trans{&t}, m_classname{cname}
\n-
43 {}
\n-
\n+
18#include <algorithm>
\n+
19#include <cstring>
\n+
20#include <limits>
\n+
21#include <sstream>
\n+
22#include <stdexcept>
\n+
23#include <typeinfo>
\n+
24
\n+
25#if __has_include(<charconv>)
\n+
26# include <charconv>
\n+
27#endif
\n+
28
\n+
29#if defined(PQXX_HAVE_RANGES) && __has_include(<ranges>)
\n+
30# include <ranges>
\n+
31#endif
\n+
32
\n+
33#include "pqxx/except.hxx"
\n+
34#include "pqxx/util.hxx"
\n+
35#include "pqxx/zview.hxx"
\n+
36
\n+
37
\n+
38namespace pqxx::internal
\n+
39{
\n+
41PQXX_LIBEXPORT std::string demangle_type_name(char const[]);
\n+
42} // namespace pqxx::internal
\n+
43
\n
44
\n-\n-\n-\n-
48
\n-
\n-
50 [[nodiscard]] constexpr std::string_view classname() const noexcept
\n-
51 {
\n-
52 return m_classname;
\n-
53 }
\n-
\n-
54
\n-
56 [[nodiscard]] std::string_view name() const &noexcept { return m_name; }
\n-
57
\n-
\n-
58 [[nodiscard]] std::string description() const
\n-
59 {
\n-
60 return pqxx::internal::describe_object(m_classname, m_name);
\n-
61 }
\n-
\n-
62
\n-
\n-\n-
64 m_trans{other.m_trans},
\n-
65 m_registered{other.m_registered},
\n-
66 m_classname{other.m_classname},
\n-
67 // We can't move the name until later.
\n-
68 m_name{}
\n-
69 {
\n-
70 // This is a bit more complicated than you might expect. The transaction
\n-
71 // has a backpointer to the focus, and we need to transfer that to the new
\n-
72 // focus.
\n-
73 move_name_and_registration(other);
\n-
74 }
\n-
\n-
75
\n-
\n-\n-
77 {
\n-
78 if (&other != this)
\n-
79 {
\n-
80 if (m_registered)
\n-
81 unregister_me();
\n-
82 m_trans = other.m_trans;
\n-
83 m_classname = other.m_classname;
\n-
84 move_name_and_registration(other);
\n-
85 }
\n-
86 return *this;
\n-
87 }
\n-
\n-
88
\n-
89protected:
\n-
90 void register_me();
\n-
91 void unregister_me() noexcept;
\n-
92 void reg_pending_error(std::string const &) noexcept;
\n-
93 bool registered() const noexcept { return m_registered; }
\n-
94
\n-\n+
45namespace pqxx
\n+
46{
\n+
71
\n+
73
\n+
81template<typename TYPE>
\n+
82std::string const type_name{internal::demangle_type_name(typeid(TYPE).name())};
\n+
83
\n+
84
\n+
86
\n+
\n+
92template<typename TYPE, typename ENABLE = void> struct nullness
\n+
93{
\n+
95 static bool has_null;
\n
96
\n-
97private:
\n-
98 bool m_registered = false;
\n-
99 std::string_view m_classname;
\n-
100 std::string m_name;
\n-
101
\n-
103 void move_name_and_registration(transaction_focus &other)
\n-
104 {
\n-
105 bool const reg{other.m_registered};
\n-
106 // Unregister the original while it still owns its name.
\n-
107 if (reg)
\n-
108 other.unregister_me();
\n-
109 // Now! Quick! Steal that name.
\n-
110 m_name = std::move(other.m_name);
\n-
111 // Now that we own the name, register ourselves instead.
\n-
112 if (reg)
\n-
113 this->register_me();
\n-
114 }
\n-
115};
\n-
\n-
116} // namespace pqxx
\n-
117#endif
\n+
98 static bool always_null;
\n+
99
\n+
101 static bool is_null(TYPE const &value);
\n+
102
\n+
104
\n+
109 [[nodiscard]] static TYPE null();
\n+
110};
\n+
\n+
111
\n+
112
\n+
\n+
114template<typename TYPE> struct no_null
\n+
115{
\n+
117
\n+
127 static constexpr bool has_null = false;
\n+
128
\n+
130
\n+
133 static constexpr bool always_null = false;
\n+
134
\n+
136
\n+
\n+
140 [[nodiscard]] static constexpr bool is_null(TYPE const &) noexcept
\n+
141 {
\n+
142 return false;
\n+
143 }
\n+
\n+
144};
\n+
\n+
145
\n+
146
\n+
148
\n+
\n+
154template<typename TYPE> struct string_traits
\n+
155{
\n+
157
\n+
160 static constexpr bool converts_to_string{false};
\n+
161
\n+
163
\n+
166 static constexpr bool converts_from_string{false};
\n+
167
\n+
169
\n+
188 [[nodiscard]] static inline zview
\n+
189 to_buf(char *begin, char *end, TYPE const &value);
\n+
190
\n+
192 /* @warning A null value has no string representation. Do not pass a null.
\n+
193 *
\n+
194 * Writes value's string representation into the buffer, starting exactly at
\n+
195 * @c begin, and ensuring a trailing zero. Returns the address just beyond
\n+
196 * the trailing zero, so the caller could use it as the @c begin for another
\n+
197 * call to @c into_buf writing a next value.
\n+
198 */
\n+
199 static inline char *into_buf(char *begin, char *end, TYPE const &value);
\n+
200
\n+
202
\n+
207 [[nodiscard]] static inline TYPE from_string(std::string_view text);
\n+
208
\n+
209 // C++20: Can we make these all constexpr?
\n+
211
\n+
215 [[nodiscard]] static inline std::size_t
\n+
216 size_buffer(TYPE const &value) noexcept;
\n+
217
\n+
218 // TODO: Move is_unquoted_string into the traits after all?
\n+
219};
\n+
\n+
220
\n+
221
\n+
223
\n+
239template<typename TYPE> [[noreturn]] void oops_forbidden_conversion() noexcept;
\n+
240
\n+
241
\n+
243
\n+
\n+
248template<typename TYPE> struct forbidden_conversion
\n+
249{
\n+
250 static constexpr bool converts_to_string{false};
\n+
251 static constexpr bool converts_from_string{false};
\n+
\n+
252 [[noreturn]] static zview to_buf(char *, char *, TYPE const &)
\n+
253 {
\n+
254 oops_forbidden_conversion<TYPE>();
\n+
255 }
\n+
\n+
\n+
256 [[noreturn]] static char *into_buf(char *, char *, TYPE const &)
\n+
257 {
\n+
258 oops_forbidden_conversion<TYPE>();
\n+
259 }
\n+
\n+
\n+
260 [[noreturn]] static TYPE from_string(std::string_view)
\n+
261 {
\n+
262 oops_forbidden_conversion<TYPE>();
\n+
263 }
\n+
\n+
\n+
264 [[noreturn]] static std::size_t size_buffer(TYPE const &) noexcept
\n+
265 {
\n+
266 oops_forbidden_conversion<TYPE>();
\n+
267 }
\n+
\n+
268};
\n+
\n+
269
\n+
270
\n+
272
\n+
\n+
288template<> struct string_traits<char> : forbidden_conversion<char>
\n+
289{};
\n+
\n+
290
\n+
291
\n+
293
\n+
307template<>
\n+
\n+
308struct string_traits<unsigned char> : forbidden_conversion<unsigned char>
\n+
309{};
\n+
\n+
310
\n+
311
\n+
313
\n+
327template<>
\n+
\n+
328struct string_traits<signed char> : forbidden_conversion<signed char>
\n+
329{};
\n+
\n+
330
\n+
331
\n+
333
\n+
\n+
338template<> struct string_traits<std::byte> : forbidden_conversion<std::byte>
\n+
339{};
\n+
\n+
340
\n+
341
\n+
343template<typename ENUM>
\n+
\n+
344struct nullness<ENUM, std::enable_if_t<std::is_enum_v<ENUM>>> : no_null<ENUM>
\n+
345{};
\n+
\n+
346
\n+
347
\n+
348// C++20: Concepts for "converts from string" & "converts to string."
\n+
349} // namespace pqxx
\n+
350
\n+
351
\n+
352namespace pqxx::internal
\n+
353{
\n+
355
\n+
\n+
364template<typename ENUM> struct enum_traits
\n+
365{
\n+
366 using impl_type = std::underlying_type_t<ENUM>;
\n+\n+
368
\n+
369 static constexpr bool converts_to_string{true};
\n+
370 static constexpr bool converts_from_string{true};
\n+
371
\n+
372 [[nodiscard]] static constexpr zview
\n+
\n+
373 to_buf(char *begin, char *end, ENUM const &value)
\n+
374 {
\n+
375 return impl_traits::to_buf(begin, end, to_underlying(value));
\n+
376 }
\n+
\n+
377
\n+
\n+
378 static constexpr char *into_buf(char *begin, char *end, ENUM const &value)
\n+
379 {
\n+
380 return impl_traits::into_buf(begin, end, to_underlying(value));
\n+
381 }
\n+
\n+
382
\n+
\n+
383 [[nodiscard]] static ENUM from_string(std::string_view text)
\n+
384 {
\n+
385 return static_cast<ENUM>(impl_traits::from_string(text));
\n+
386 }
\n+
\n+
387
\n+
\n+
388 [[nodiscard]] static std::size_t size_buffer(ENUM const &value) noexcept
\n+
389 {
\n+
390 return impl_traits::size_buffer(to_underlying(value));
\n+
391 }
\n+
\n+
392
\n+
393private:
\n+
394 // C++23: Replace with std::to_underlying.
\n+
395 static constexpr impl_type to_underlying(ENUM const &value) noexcept
\n+
396 {
\n+
397 return static_cast<impl_type>(value);
\n+
398 }
\n+
399};
\n+
\n+
400} // namespace pqxx::internal
\n+
401
\n+
402
\n+
403// We used to inline type_name<ENUM>, but this triggered a "double free" error
\n+
404// on program exit, when libpqxx was built as a shared library on Debian with
\n+
405// gcc 12.
\n+
406
\n+
408
\n+
419#define PQXX_DECLARE_ENUM_CONVERSION(ENUM) \\
\n+
420 template<> struct string_traits<ENUM> : pqxx::internal::enum_traits<ENUM> \\
\n+
421 {}; \\
\n+
422 template<> inline std::string_view const type_name<ENUM> \\
\n+
423 { \\
\n+
424# ENUM \\
\n+
425 }
\n+
426
\n+
427
\n+
428namespace pqxx
\n+
429{
\n+
431
\n+
443template<typename TYPE>
\n+
444[[nodiscard]] inline TYPE from_string(std::string_view text)
\n+
445{
\n+\n+
447}
\n+
448
\n+
449
\n+
451
\n+
457template<>
\n+
458[[nodiscard]] inline std::string_view from_string(std::string_view text)
\n+
459{
\n+
460 return text;
\n+
461}
\n+
462
\n+
463
\n+
465
\n+
472template<typename T> inline void from_string(std::string_view text, T &value)
\n+
473{
\n+
474 value = from_string<T>(text);
\n+
475}
\n+
476
\n+
477
\n+
479
\n+
484template<typename TYPE> inline std::string to_string(TYPE const &value);
\n+
485
\n+
486
\n+
488
\n+
495template<typename... TYPE>
\n+
496[[nodiscard]] inline std::vector<std::string_view>
\n+
497to_buf(char *here, char const *end, TYPE... value)
\n+
498{
\n+
499 return {[&here, end](auto v) {
\n+
500 auto begin = here;
\n+
501 here = string_traits<decltype(v)>::into_buf(begin, end, v);
\n+
502 // Exclude the trailing zero out of the string_view.
\n+
503 auto len{static_cast<std::size_t>(here - begin) - 1};
\n+
504 return std::string_view{begin, len};
\n+
505 }(value)...};
\n+
506}
\n+
507
\n+
509
\n+
512template<typename TYPE>
\n+
513inline void into_string(TYPE const &value, std::string &out);
\n+
514
\n+
515
\n+
517template<typename TYPE>
\n+
518[[nodiscard]] inline constexpr bool is_null(TYPE const &value) noexcept
\n+
519{
\n+
520 return nullness<strip_t<TYPE>>::is_null(value);
\n+
521}
\n+
522
\n+
523
\n+
525
\n+
528template<typename... TYPE>
\n+
529[[nodiscard]] inline std::size_t size_buffer(TYPE const &...value) noexcept
\n+
530{
\n+
531 return (string_traits<strip_t<TYPE>>::size_buffer(value) + ...);
\n+
532}
\n+
533
\n+
534
\n+
536
\n+
542template<typename TYPE> inline constexpr bool is_sql_array{false};
\n+
543
\n+
544
\n+
546
\n+
558template<typename TYPE> inline constexpr bool is_unquoted_safe{false};
\n+
559
\n+
560
\n+
562template<typename T> inline constexpr char array_separator{','};
\n+
563
\n+
564
\n+
566
\n+
573template<typename TYPE> inline constexpr format param_format(TYPE const &)
\n+
574{
\n+
575 return format::text;
\n+
576}
\n+
577
\n+
578
\n+
580
\n+
589template<typename TYPE>
\n+
590inline zview generic_to_buf(char *begin, char *end, TYPE const &value)
\n+
591{
\n+
592 using traits = string_traits<TYPE>;
\n+
593 // The trailing zero does not count towards the zview's size, so subtract 1
\n+
594 // from the result we get from into_buf().
\n+
595 if (is_null(value))
\n+
596 return {};
\n+
597 else
\n+
598 return {begin, traits::into_buf(begin, end, value) - begin - 1};
\n+
599}
\n+
600
\n+
601
\n+
602#if defined(PQXX_HAVE_CONCEPTS)
\n+
604
\n+
610template<class TYPE>
\n+
611concept binary = std::ranges::contiguous_range<TYPE> and
\n+
612 std::is_same_v<strip_t<value_type<TYPE>>, std::byte>;
\n+
613#endif
\n+
615} // namespace pqxx
\n+
616
\n+
617
\n+
618#include "pqxx/internal/conversions.hxx"
\n+
619#endif
\n
The home of all libpqxx classes, functions, templates, etc.
Definition array.hxx:33
\n-
std::string describe_object(std::string_view class_name, std::string_view name)
Describe an object for humans, based on class name and optional name.
Definition util.cxx:51
\n-
Interface definition (and common code) for "transaction" classes.
Definition transaction_base.hxx:88
\n-
Base class for things that monopolise a transaction's attention.
Definition transaction_focus.hxx:29
\n-
std::string description() const
Definition transaction_focus.hxx:58
\n-\n-
transaction_focus(transaction_base &t, std::string_view cname)
Definition transaction_focus.hxx:41
\n-
void unregister_me() noexcept
Definition transaction_base.cxx:527
\n-
std::string_view name() const &noexcept
Name for this object, if the caller passed one; empty string otherwise.
Definition transaction_focus.hxx:56
\n-
constexpr std::string_view classname() const noexcept
Class name, for human consumption.
Definition transaction_focus.hxx:50
\n-
transaction_focus(transaction_base &t, std::string_view cname, std::string &&oname)
Definition transaction_focus.hxx:36
\n-
transaction_focus(transaction_focus const &)=delete
\n-
transaction_focus(transaction_focus &&other)
Definition transaction_focus.hxx:63
\n-
transaction_focus & operator=(transaction_focus &&other)
Definition transaction_focus.hxx:76
\n-
transaction_focus(transaction_base &t, std::string_view cname, std::string_view oname)
Definition transaction_focus.hxx:31
\n-
transaction_base * m_trans
Definition transaction_focus.hxx:95
\n-
transaction_focus & operator=(transaction_focus const &)=delete
\n+
std::string const type_name
A human-readable name for a type, used in error messages and such.
Definition strconv.hxx:82
\n+
void oops_forbidden_conversion() noexcept
Nonexistent function to indicate a disallowed type conversion.
\n+
std::string to_string(field const &value)
Convert a field to a string.
Definition result.cxx:549
\n+
T from_string(field const &value)
Convert a field's value to type T.
Definition field.hxx:520
\n+
format
Format code: is data text or binary?
Definition types.hxx:81
\n+\n+\n+
Internal items for libpqxx' own use. Do not use these yourself.
Definition composite.hxx:84
\n+
std::string demangle_type_name(char const[])
Attempt to demangle std::type_info::name() to something human-readable.
Definition strconv.cxx:230
\n+
Traits describing a type's "null value," if any.
Definition strconv.hxx:93
\n+
static bool is_null(TYPE const &value)
Is value a null?
\n+
static TYPE null()
Return a null value.
\n+
static bool has_null
Does this type have a null value?
Definition strconv.hxx:95
\n+
static bool always_null
Is this type always null?
Definition strconv.hxx:98
\n+
Nullness traits describing a type which does not have a null value.
Definition strconv.hxx:115
\n+
static constexpr bool always_null
Are all values of this type null?
Definition strconv.hxx:133
\n+
static constexpr bool has_null
Does TYPE have a "built-in null value"?
Definition strconv.hxx:127
\n+
static constexpr bool is_null(TYPE const &) noexcept
Does a given value correspond to an SQL null value?
Definition strconv.hxx:140
\n+
Traits class for use in string conversions.
Definition strconv.hxx:155
\n+
static std::size_t size_buffer(TYPE const &value) noexcept
Estimate how much buffer space is needed to represent value.
\n+
static zview to_buf(char *begin, char *end, TYPE const &value)
Return a string_view representing value, plus terminating zero.
\n+
static TYPE from_string(std::string_view text)
Parse a string representation of a TYPE value.
Definition strconv.cxx:740
\n+
static constexpr bool converts_to_string
Is conversion from TYPE to strings supported?
Definition strconv.hxx:160
\n+
static char * into_buf(char *begin, char *end, TYPE const &value)
Write value's string representation into buffer at begin.
\n+
static constexpr bool converts_from_string
Is conversion from string_view to TYPE supported?
Definition strconv.hxx:166
\n+
String traits for a forbidden type conversion.
Definition strconv.hxx:249
\n+
static char * into_buf(char *, char *, TYPE const &)
Definition strconv.hxx:256
\n+
static TYPE from_string(std::string_view)
Definition strconv.hxx:260
\n+
static std::size_t size_buffer(TYPE const &) noexcept
Definition strconv.hxx:264
\n+
static zview to_buf(char *, char *, TYPE const &)
Definition strconv.hxx:252
\n+
Helper class for defining enum conversions.
Definition strconv.hxx:365
\n+
static std::size_t size_buffer(ENUM const &value) noexcept
Definition strconv.hxx:388
\n+
static constexpr zview to_buf(char *begin, char *end, ENUM const &value)
Definition strconv.hxx:373
\n+
static constexpr bool converts_from_string
Definition strconv.hxx:370
\n+
std::underlying_type_t< ENUM > impl_type
Definition strconv.hxx:366
\n+
static ENUM from_string(std::string_view text)
Definition strconv.hxx:383
\n+
static constexpr char * into_buf(char *begin, char *end, ENUM const &value)
Definition strconv.hxx:378
\n+
static constexpr bool converts_to_string
Definition strconv.hxx:369
\n+
Marker-type wrapper: zero-terminated std::string_view.
Definition zview.hxx:38
\n
\n
\n \n
\n \n
\n \n \n", "details": [{"source1": "html2text {}", "source2": "html2text {}", "unified_diff": "@@ -1,165 +1,489 @@\n \n \n \n \n \n libpqxx\u00a07.8.1\n \n-transaction_focus.hxx\n- 1\n- 9#ifndef PQXX_H_TRANSACTION_FOCUS\n- 10#define PQXX_H_TRANSACTION_FOCUS\n- 11\n- 12#if !defined(PQXX_HEADER_PRE)\n- 13# error \"Include libpqxx headers as , not .\"\n- 14#endif\n- 15\n- 16#include \"pqxx/util.hxx\"\n+strconv.hxx\n+ 1/* String conversion definitions.\n+ 2 *\n+ 3 * DO NOT INCLUDE THIS FILE DIRECTLY; include pqxx/stringconv instead.\n+ 4 *\n+ 5 * Copyright (c) 2000-2023, Jeroen T. Vermeulen.\n+ 6 *\n+ 7 * See COPYING for copyright license. If you did not receive a file called\n+ 8 * COPYING with this source code, please notify the distributor of this\n+ 9 * mistake, or contact the author.\n+ 10 */\n+ 11#ifndef PQXX_H_STRCONV\n+ 12#define PQXX_H_STRCONV\n+ 13\n+ 14#if !defined(PQXX_HEADER_PRE)\n+ 15# error \"Include libpqxx headers as , not .\"\n+ 16#endif\n 17\n- 18namespace pqxx\n- 19{\n- 21\n-28class PQXX_LIBEXPORT transaction_focus\n- 29{\n- 30public:\n-31 transaction_focus(\n- 32 transaction_base &t, std::string_view cname, std::string_view oname) :\n- 33 m_trans{&t}, m_classname{cname}, m_name{oname}\n- 34 {}\n- 35\n-36 transaction_focus(\n- 37 transaction_base &t, std::string_view cname, std::string &&oname) :\n- 38 m_trans{&t}, m_classname{cname}, m_name{std::move(oname)}\n- 39 {}\n- 40\n-41 transaction_focus(transaction_base &t, std::string_view cname) :\n- 42 m_trans{&t}, m_classname{cname}\n- 43 {}\n+ 18#include \n+ 19#include \n+ 20#include \n+ 21#include \n+ 22#include \n+ 23#include \n+ 24\n+ 25#if __has_include()\n+ 26# include \n+ 27#endif\n+ 28\n+ 29#if defined(PQXX_HAVE_RANGES) && __has_include()\n+ 30# include \n+ 31#endif\n+ 32\n+ 33#include \"pqxx/except.hxx\"\n+ 34#include \"pqxx/util.hxx\"\n+ 35#include \"pqxx/zview.hxx\"\n+ 36\n+ 37\n+ 38namespace pqxx::internal\n+ 39{\n+ 41PQXX_LIBEXPORT std::string demangle_type_name(char const[]);\n+ 42} // namespace pqxx::internal\n+ 43\n 44\n-45 transaction_focus() = delete;\n-46 transaction_focus(transaction_focus const &) = delete;\n-47 transaction_focus &operator=(transaction_focus const &) = delete;\n- 48\n-50 [[nodiscard]] constexpr std::string_view classname() const noexcept\n- 51 {\n- 52 return m_classname;\n- 53 }\n- 54\n-56 [[nodiscard]] std::string_view name() const &noexcept { return m_name; }\n- 57\n-58 [[nodiscard]] std::string description() const\n- 59 {\n- 60 return pqxx::internal::describe_object(m_classname, m_name);\n- 61 }\n- 62\n-63 transaction_focus(transaction_focus &&other) :\n- 64 m_trans{other.m_trans},\n- 65 m_registered{other.m_registered},\n- 66 m_classname{other.m_classname},\n- 67 // We can't move the name until later.\n- 68 m_name{}\n- 69 {\n- 70 // This is a bit more complicated than you might expect. The transaction\n- 71 // has a backpointer to the focus, and we need to transfer that to the new\n- 72 // focus.\n- 73 move_name_and_registration(other);\n- 74 }\n- 75\n-76 transaction_focus &operator=(transaction_focus &&other)\n- 77 {\n- 78 if (&other != this)\n- 79 {\n- 80 if (m_registered)\n- 81 unregister_me();\n- 82 m_trans = other.m_trans;\n- 83 m_classname = other.m_classname;\n- 84 move_name_and_registration(other);\n- 85 }\n- 86 return *this;\n- 87 }\n- 88\n- 89protected:\n- 90 void register_me();\n- 91 void unregister_me() noexcept;\n- 92 void reg_pending_error(std::string const &) noexcept;\n-93 bool registered() const noexcept { return m_registered; }\n- 94\n-95 transaction_base *m_trans;\n+ 45namespace pqxx\n+ 46{\n+ 71\n+ 73\n+ 81template\n+82std::string const type_name{internal::demangle_type_name(typeid(TYPE).name\n+())};\n+ 83\n+ 84\n+ 86\n+92template struct nullness\n+ 93{\n+95 static bool has_null;\n 96\n- 97private:\n- 98 bool m_registered = false;\n- 99 std::string_view m_classname;\n- 100 std::string m_name;\n- 101\n- 103 void move_name_and_registration(transaction_focus &other)\n- 104 {\n- 105 bool const reg{other.m_registered};\n- 106 // Unregister the original while it still owns its name.\n- 107 if (reg)\n- 108 other.unregister_me();\n- 109 // Now! Quick! Steal that name.\n- 110 m_name = std::move(other.m_name);\n- 111 // Now that we own the name, register ourselves instead.\n- 112 if (reg)\n- 113 this->register_me();\n- 114 }\n- 115};\n- 116} // namespace pqxx\n- 117#endif\n+98 static bool always_null;\n+ 99\n+101 static bool is_null(TYPE const &value);\n+ 102\n+ 104\n+109 [[nodiscard]] static TYPE null();\n+ 110};\n+ 111\n+ 112\n+114template struct no_null\n+ 115{\n+ 117\n+127 static constexpr bool has_null = false;\n+ 128\n+ 130\n+133 static constexpr bool always_null = false;\n+ 134\n+ 136\n+140 [[nodiscard]] static constexpr bool is_null(TYPE const &) noexcept\n+ 141 {\n+ 142 return false;\n+ 143 }\n+ 144};\n+ 145\n+ 146\n+ 148\n+154template struct string_traits\n+ 155{\n+ 157\n+160 static constexpr bool converts_to_string{false};\n+ 161\n+ 163\n+166 static constexpr bool converts_from_string{false};\n+ 167\n+ 169\n+ 188 [[nodiscard]] static inline zview\n+189 to_buf(char *begin, char *end, TYPE const &value);\n+ 190\n+ 192 /* @warning A null value has no string representation. Do not pass a null.\n+ 193 *\n+ 194 * Writes value's string representation into the buffer, starting exactly\n+at\n+ 195 * @c begin, and ensuring a trailing zero. Returns the address just beyond\n+ 196 * the trailing zero, so the caller could use it as the @c begin for\n+another\n+ 197 * call to @c into_buf writing a next value.\n+ 198 */\n+199 static inline char *into_buf(char *begin, char *end, TYPE const &value);\n+ 200\n+ 202\n+ 207 [[nodiscard]] static inline TYPE from_string(std::string_view text);\n+ 208\n+ 209 // C++20: Can we make these all constexpr?\n+ 211\n+ 215 [[nodiscard]] static inline std::size_t\n+216 size_buffer(TYPE const &value) noexcept;\n+ 217\n+ 218 // TODO: Move is_unquoted_string into the traits after all?\n+ 219};\n+ 220\n+ 221\n+ 223\n+239template [[noreturn]] void oops_forbidden_conversion()\n+noexcept;\n+ 240\n+ 241\n+ 243\n+248template struct forbidden_conversion\n+ 249{\n+250 static constexpr bool converts_to_string{false};\n+251 static constexpr bool converts_from_string{false};\n+252 [[noreturn]] static zview to_buf(char *, char *, TYPE const &)\n+ 253 {\n+ 254 oops_forbidden_conversion();\n+ 255 }\n+256 [[noreturn]] static char *into_buf(char *, char *, TYPE const &)\n+ 257 {\n+ 258 oops_forbidden_conversion();\n+ 259 }\n+260 [[noreturn]] static TYPE from_string(std::string_view)\n+ 261 {\n+ 262 oops_forbidden_conversion();\n+ 263 }\n+264 [[noreturn]] static std::size_t size_buffer(TYPE const &) noexcept\n+ 265 {\n+ 266 oops_forbidden_conversion();\n+ 267 }\n+ 268};\n+ 269\n+ 270\n+ 272\n+288template<> struct string_traits : forbidden_conversion\n+ 289{};\n+ 290\n+ 291\n+ 293\n+ 307template<>\n+308struct string_traits : forbidden_conversion\n+ 309{};\n+ 310\n+ 311\n+ 313\n+ 327template<>\n+328struct string_traits : forbidden_conversion\n+ 329{};\n+ 330\n+ 331\n+ 333\n+338template<> struct string_traits : forbidden_conversion\n+ 339{};\n+ 340\n+ 341\n+ 343template\n+344struct nullness>> :\n+no_null\n+ 345{};\n+ 346\n+ 347\n+ 348// C++20: Concepts for \"converts from string\" & \"converts to string.\"\n+ 349} // namespace pqxx\n+ 350\n+ 351\n+ 352namespace pqxx::internal\n+ 353{\n+ 355\n+364template struct enum_traits\n+ 365{\n+366 using impl_type = std::underlying_type_t;\n+367 using impl_traits = string_traits;\n+ 368\n+369 static constexpr bool converts_to_string{true};\n+370 static constexpr bool converts_from_string{true};\n+ 371\n+ 372 [[nodiscard]] static constexpr zview\n+373 to_buf(char *begin, char *end, ENUM const &value)\n+ 374 {\n+ 375 return impl_traits::to_buf(begin, end, to_underlying(value));\n+ 376 }\n+ 377\n+378 static constexpr char *into_buf(char *begin, char *end, ENUM const &value)\n+ 379 {\n+ 380 return impl_traits::into_buf(begin, end, to_underlying(value));\n+ 381 }\n+ 382\n+383 [[nodiscard]] static ENUM from_string(std::string_view text)\n+ 384 {\n+ 385 return static_cast(impl_traits::from_string(text));\n+ 386 }\n+ 387\n+388 [[nodiscard]] static std::size_t size_buffer(ENUM const &value) noexcept\n+ 389 {\n+ 390 return impl_traits::size_buffer(to_underlying(value));\n+ 391 }\n+ 392\n+ 393private:\n+ 394 // C++23: Replace with std::to_underlying.\n+ 395 static constexpr impl_type to_underlying(ENUM const &value) noexcept\n+ 396 {\n+ 397 return static_cast(value);\n+ 398 }\n+ 399};\n+ 400} // namespace pqxx::internal\n+ 401\n+ 402\n+ 403// We used to inline type_name, but this triggered a \"double free\"\n+error\n+ 404// on program exit, when libpqxx was built as a shared library on Debian\n+with\n+ 405// gcc 12.\n+ 406\n+ 408\n+ 419#define PQXX_DECLARE_ENUM_CONVERSION(ENUM) \\\n+ 420 template<> struct string_traits : pqxx::internal::enum_traits\n+\\\n+ 421 {}; \\\n+ 422 template<> inline std::string_view const type_name \\\n+ 423 { \\\n+ 424# ENUM \\\n+ 425 }\n+ 426\n+ 427\n+ 428namespace pqxx\n+ 429{\n+ 431\n+ 443template\n+ 444[[nodiscard]] inline TYPE from_string(std::string_view text)\n+ 445{\n+ 446 return string_traits::from_string(text);\n+ 447}\n+ 448\n+ 449\n+ 451\n+ 457template<>\n+ 458[[nodiscard]] inline std::string_view from_string(std::string_view text)\n+ 459{\n+ 460 return text;\n+ 461}\n+ 462\n+ 463\n+ 465\n+ 472template inline void from_string(std::string_view text, T\n+&value)\n+ 473{\n+ 474 value = from_string(text);\n+ 475}\n+ 476\n+ 477\n+ 479\n+ 484template inline std::string to_string(TYPE const &value);\n+ 485\n+ 486\n+ 488\n+ 495template\n+ 496[[nodiscard]] inline std::vector\n+ 497to_buf(char *here, char const *end, TYPE... value)\n+ 498{\n+ 499 return {[&here, end](auto v) {\n+ 500 auto begin = here;\n+ 501 here = string_traits::into_buf(begin, end, v);\n+ 502 // Exclude the trailing zero out of the string_view.\n+ 503 auto len{static_cast(here - begin) - 1};\n+ 504 return std::string_view{begin, len};\n+ 505 }(value)...};\n+ 506}\n+ 507\n+ 509\n+ 512template\n+ 513inline void into_string(TYPE const &value, std::string &out);\n+ 514\n+ 515\n+ 517template\n+ 518[[nodiscard]] inline constexpr bool is_null(TYPE const &value) noexcept\n+ 519{\n+ 520 return nullness>::is_null(value);\n+ 521}\n+ 522\n+ 523\n+ 525\n+ 528template\n+ 529[[nodiscard]] inline std::size_t size_buffer(TYPE const &...value) noexcept\n+ 530{\n+ 531 return (string_traits>::size_buffer(value) + ...);\n+ 532}\n+ 533\n+ 534\n+ 536\n+ 542template inline constexpr bool is_sql_array{false};\n+ 543\n+ 544\n+ 546\n+ 558template inline constexpr bool is_unquoted_safe{false};\n+ 559\n+ 560\n+ 562template inline constexpr char array_separator{','};\n+ 563\n+ 564\n+ 566\n+ 573template inline constexpr format param_format(TYPE const &)\n+ 574{\n+ 575 return format::text;\n+ 576}\n+ 577\n+ 578\n+ 580\n+ 589template\n+ 590inline zview generic_to_buf(char *begin, char *end, TYPE const &value)\n+ 591{\n+ 592 using traits = string_traits;\n+ 593 // The trailing zero does not count towards the zview's size, so subtract\n+1\n+ 594 // from the result we get from into_buf().\n+ 595 if (is_null(value))\n+ 596 return {};\n+ 597 else\n+ 598 return {begin, traits::into_buf(begin, end, value) - begin - 1};\n+ 599}\n+ 600\n+ 601\n+ 602#if defined(PQXX_HAVE_CONCEPTS)\n+ 604\n+ 610template\n+ 611concept binary = std::ranges::contiguous_range and\n+ 612 std::is_same_v>, std::byte>;\n+ 613#endif\n+ 615} // namespace pqxx\n+ 616\n+ 617\n+ 618#include \"pqxx/internal/conversions.hxx\"\n+ 619#endif\n pqxx\n The home of all libpqxx classes, functions, templates, etc.\n Definition array.hxx:33\n-pqxx::internal::describe_object\n-std::string describe_object(std::string_view class_name, std::string_view name)\n-Describe an object for humans, based on class name and optional name.\n-Definition util.cxx:51\n-pqxx::transaction_base\n-Interface definition (and common code) for \"transaction\" classes.\n-Definition transaction_base.hxx:88\n-pqxx::transaction_focus\n-Base class for things that monopolise a transaction's attention.\n-Definition transaction_focus.hxx:29\n-pqxx::transaction_focus::description\n-std::string description() const\n-Definition transaction_focus.hxx:58\n-pqxx::transaction_focus::transaction_focus\n-transaction_focus()=delete\n-pqxx::transaction_focus::transaction_focus\n-transaction_focus(transaction_base &t, std::string_view cname)\n-Definition transaction_focus.hxx:41\n-pqxx::transaction_focus::unregister_me\n-void unregister_me() noexcept\n-Definition transaction_base.cxx:527\n-pqxx::transaction_focus::name\n-std::string_view name() const &noexcept\n-Name for this object, if the caller passed one; empty string otherwise.\n-Definition transaction_focus.hxx:56\n-pqxx::transaction_focus::classname\n-constexpr std::string_view classname() const noexcept\n-Class name, for human consumption.\n-Definition transaction_focus.hxx:50\n-pqxx::transaction_focus::transaction_focus\n-transaction_focus(transaction_base &t, std::string_view cname, std::string\n-&&oname)\n-Definition transaction_focus.hxx:36\n-pqxx::transaction_focus::transaction_focus\n-transaction_focus(transaction_focus const &)=delete\n-pqxx::transaction_focus::transaction_focus\n-transaction_focus(transaction_focus &&other)\n-Definition transaction_focus.hxx:63\n-pqxx::transaction_focus::operator=\n-transaction_focus & operator=(transaction_focus &&other)\n-Definition transaction_focus.hxx:76\n-pqxx::transaction_focus::transaction_focus\n-transaction_focus(transaction_base &t, std::string_view cname, std::string_view\n-oname)\n-Definition transaction_focus.hxx:31\n-pqxx::transaction_focus::m_trans\n-transaction_base * m_trans\n-Definition transaction_focus.hxx:95\n-pqxx::transaction_focus::operator=\n-transaction_focus & operator=(transaction_focus const &)=delete\n+pqxx::type_name\n+std::string const type_name\n+A human-readable name for a type, used in error messages and such.\n+Definition strconv.hxx:82\n+pqxx::oops_forbidden_conversion\n+void oops_forbidden_conversion() noexcept\n+Nonexistent function to indicate a disallowed type conversion.\n+pqxx::to_string\n+std::string to_string(field const &value)\n+Convert a field to a string.\n+Definition result.cxx:549\n+pqxx::from_string\n+T from_string(field const &value)\n+Convert a field's value to type T.\n+Definition field.hxx:520\n+pqxx::format\n+format\n+Format code: is data text or binary?\n+Definition types.hxx:81\n+pqxx::format::text\n+@ text\n+pqxx::format::binary\n+@ binary\n+pqxx::internal\n+Internal items for libpqxx' own use. Do not use these yourself.\n+Definition composite.hxx:84\n+pqxx::internal::demangle_type_name\n+std::string demangle_type_name(char const[])\n+Attempt to demangle std::type_info::name() to something human-readable.\n+Definition strconv.cxx:230\n+pqxx::nullness\n+Traits describing a type's \"null value,\" if any.\n+Definition strconv.hxx:93\n+pqxx::nullness::is_null\n+static bool is_null(TYPE const &value)\n+Is value a null?\n+pqxx::nullness::null\n+static TYPE null()\n+Return a null value.\n+pqxx::nullness::has_null\n+static bool has_null\n+Does this type have a null value?\n+Definition strconv.hxx:95\n+pqxx::nullness::always_null\n+static bool always_null\n+Is this type always null?\n+Definition strconv.hxx:98\n+pqxx::no_null\n+Nullness traits describing a type which does not have a null value.\n+Definition strconv.hxx:115\n+pqxx::no_null::always_null\n+static constexpr bool always_null\n+Are all values of this type null?\n+Definition strconv.hxx:133\n+pqxx::no_null::has_null\n+static constexpr bool has_null\n+Does TYPE have a \"built-in null value\"?\n+Definition strconv.hxx:127\n+pqxx::no_null::is_null\n+static constexpr bool is_null(TYPE const &) noexcept\n+Does a given value correspond to an SQL null value?\n+Definition strconv.hxx:140\n+pqxx::string_traits\n+Traits class for use in string conversions.\n+Definition strconv.hxx:155\n+pqxx::string_traits::size_buffer\n+static std::size_t size_buffer(TYPE const &value) noexcept\n+Estimate how much buffer space is needed to represent value.\n+pqxx::string_traits::to_buf\n+static zview to_buf(char *begin, char *end, TYPE const &value)\n+Return a string_view representing value, plus terminating zero.\n+pqxx::string_traits::from_string\n+static TYPE from_string(std::string_view text)\n+Parse a string representation of a TYPE value.\n+Definition strconv.cxx:740\n+pqxx::string_traits::converts_to_string\n+static constexpr bool converts_to_string\n+Is conversion from TYPE to strings supported?\n+Definition strconv.hxx:160\n+pqxx::string_traits::into_buf\n+static char * into_buf(char *begin, char *end, TYPE const &value)\n+Write value's string representation into buffer at begin.\n+pqxx::string_traits::converts_from_string\n+static constexpr bool converts_from_string\n+Is conversion from string_view to TYPE supported?\n+Definition strconv.hxx:166\n+pqxx::forbidden_conversion\n+String traits for a forbidden type conversion.\n+Definition strconv.hxx:249\n+pqxx::forbidden_conversion::into_buf\n+static char * into_buf(char *, char *, TYPE const &)\n+Definition strconv.hxx:256\n+pqxx::forbidden_conversion::from_string\n+static TYPE from_string(std::string_view)\n+Definition strconv.hxx:260\n+pqxx::forbidden_conversion::size_buffer\n+static std::size_t size_buffer(TYPE const &) noexcept\n+Definition strconv.hxx:264\n+pqxx::forbidden_conversion::to_buf\n+static zview to_buf(char *, char *, TYPE const &)\n+Definition strconv.hxx:252\n+pqxx::internal::enum_traits\n+Helper class for defining enum conversions.\n+Definition strconv.hxx:365\n+pqxx::internal::enum_traits::size_buffer\n+static std::size_t size_buffer(ENUM const &value) noexcept\n+Definition strconv.hxx:388\n+pqxx::internal::enum_traits::to_buf\n+static constexpr zview to_buf(char *begin, char *end, ENUM const &value)\n+Definition strconv.hxx:373\n+pqxx::internal::enum_traits::converts_from_string\n+static constexpr bool converts_from_string\n+Definition strconv.hxx:370\n+pqxx::internal::enum_traits::impl_type\n+std::underlying_type_t< ENUM > impl_type\n+Definition strconv.hxx:366\n+pqxx::internal::enum_traits::from_string\n+static ENUM from_string(std::string_view text)\n+Definition strconv.hxx:383\n+pqxx::internal::enum_traits::into_buf\n+static constexpr char * into_buf(char *begin, char *end, ENUM const &value)\n+Definition strconv.hxx:378\n+pqxx::internal::enum_traits::converts_to_string\n+static constexpr bool converts_to_string\n+Definition strconv.hxx:369\n+pqxx::zview\n+Marker-type wrapper: zero-terminated std::string_view.\n+Definition zview.hxx:38\n * include\n * pqxx\n- * transaction_focus.hxx\n+ * strconv.hxx\n * Generated by [doxygen] 1.9.8\n"}]}, {"source1": "./usr/share/doc/libpqxx-doc/html/a00038_source.html", "source2": "./usr/share/doc/libpqxx-doc/html/a00038_source.html", "unified_diff": "@@ -1,15 +1,15 @@\n \n \n \n \n \n \n \n-libpqxx: stream_from.hxx Source File\n+libpqxx: nontransaction.hxx Source File\n \n \n \n \n \n \n \n@@ -60,310 +60,76 @@\n \n
\n
\n-
stream_from.hxx
\n+
nontransaction.hxx
\n
\n
\n-
1/* Definition of the pqxx::stream_from class.
\n+
1/* Definition of the pqxx::nontransaction class.
\n
2 *
\n-
3 * pqxx::stream_from enables optimized batch reads from a database table.
\n+
3 * pqxx::nontransaction provides nontransactional database access
\n
4 *
\n-
5 * DO NOT INCLUDE THIS FILE DIRECTLY; include pqxx/stream_from instead.
\n+
5 * DO NOT INCLUDE THIS FILE DIRECTLY; include pqxx/nontransaction instead.
\n
6 *
\n
7 * Copyright (c) 2000-2023, Jeroen T. Vermeulen.
\n
8 *
\n
9 * See COPYING for copyright license. If you did not receive a file called
\n
10 * COPYING with this source code, please notify the distributor of this
\n
11 * mistake, or contact the author.
\n
12 */
\n-
13#ifndef PQXX_H_STREAM_FROM
\n-
14#define PQXX_H_STREAM_FROM
\n+
13#ifndef PQXX_H_NONTRANSACTION
\n+
14#define PQXX_H_NONTRANSACTION
\n
15
\n
16#if !defined(PQXX_HEADER_PRE)
\n
17# error "Include libpqxx headers as <pqxx/header>, not <pqxx/header.hxx>."
\n
18#endif
\n
19
\n-
20#include <cassert>
\n-
21#include <variant>
\n-
22
\n-
23#include "pqxx/connection.hxx"
\n-
24#include "pqxx/except.hxx"
\n-
25#include "pqxx/internal/concat.hxx"
\n-
26#include "pqxx/internal/encoding_group.hxx"
\n-
27#include "pqxx/internal/stream_iterator.hxx"
\n-
28#include "pqxx/separated_list.hxx"
\n-
29#include "pqxx/transaction_focus.hxx"
\n-
30
\n-
31
\n-
32namespace pqxx
\n-
33{
\n-
34class transaction_base;
\n-
35
\n-
36
\n-
38
\n-\n-
42
\n-\n-
45
\n-
46
\n-
48
\n-
\n-
78class PQXX_LIBEXPORT stream_from : transaction_focus
\n-
79{
\n-
80public:
\n-
81 using raw_line =
\n-
82 std::pair<std::unique_ptr<char, void (*)(void const *)>, std::size_t>;
\n-
83
\n-\n-\n-
86
\n-
88
\n-
97 [[deprecated("Use transaction_base::stream instead.")]] static stream_from
\n-
\n-
98 query(transaction_base &tx, std::string_view q)
\n-
99 {
\n-
100#include "pqxx/internal/ignore-deprecated-pre.hxx"
\n-
101 return {tx, from_query, q};
\n-
102#include "pqxx/internal/ignore-deprecated-post.hxx"
\n-
103 }
\n+
20#include "pqxx/connection.hxx"
\n+
21#include "pqxx/result.hxx"
\n+
22#include "pqxx/transaction.hxx"
\n+
23
\n+
24namespace pqxx
\n+
25{
\n+
26using namespace std::literals;
\n+
27
\n+
29
\n+
\n+
55class PQXX_LIBEXPORT nontransaction final : public transaction_base
\n+
56{
\n+
57public:
\n+
59
\n+
\n+
64 nontransaction(connection &c, std::string_view tname = ""sv) :
\n+
65 transaction_base{c, tname, std::shared_ptr<std::string>{}}
\n+
66 {
\n+
67 register_transaction();
\n+
68 }
\n+
\n+
69
\n+
70 virtual ~nontransaction() override { close(); }
\n+
71
\n+
72private:
\n+
73 virtual void do_commit() override {}
\n+
74};
\n
\n-
104
\n-
115
\n-
117
\n-
133 [[deprecated("Use transaction_base::stream instead.")]] static stream_from
\n-
134 raw_table(
\n-
135 transaction_base &tx, std::string_view path,
\n-
136 std::string_view columns = ""sv);
\n-
137
\n-
139
\n-
141 [[deprecated("Use transaction_base::stream instead.")]] static stream_from
\n-
142 table(
\n-\n-
144 std::initializer_list<std::string_view> columns = {});
\n-
146
\n-
148
\n-
150 [[deprecated("Use transaction_base::stream instead.")]] stream_from(
\n-
151 transaction_base &, from_query_t, std::string_view query);
\n-
152
\n-
154
\n-
156 [[deprecated("Use transaction_base::stream instead.")]] stream_from(
\n-
157 transaction_base &, from_table_t, std::string_view table);
\n-
158
\n-
160
\n-
162 template<typename Iter>
\n-
163 [[deprecated("Use transaction_base::stream instead.")]] stream_from(
\n-
164 transaction_base &, from_table_t, std::string_view table,
\n-
165 Iter columns_begin, Iter columns_end);
\n-
166
\n-
168
\n-
170 template<typename Columns>
\n-
171 [[deprecated("Use transaction_base::stream() instead.")]] stream_from(
\n-
172 transaction_base &tx, from_table_t, std::string_view table,
\n-
173 Columns const &columns);
\n-
174
\n-
175#include "pqxx/internal/ignore-deprecated-pre.hxx"
\n-
\n-
177 [[deprecated("Use transaction_base::stream instead.")]] stream_from(
\n-
178 transaction_base &tx, std::string_view table) :
\n-
179 stream_from{tx, from_table, table}
\n-
180 {}
\n-
\n-
181#include "pqxx/internal/ignore-deprecated-post.hxx"
\n-
182
\n-
184 template<typename Columns>
\n-
\n-
185 [[deprecated("Use transaction_base::stream instead.")]] stream_from(
\n-
186 transaction_base &tx, std::string_view table, Columns const &columns) :
\n-
187 stream_from{tx, from_table, table, columns}
\n-
188 {}
\n-
\n-
189
\n-
191 template<typename Iter>
\n-
192 [[deprecated("Use transaction_base::stream instead.")]] stream_from(
\n-
193 transaction_base &, std::string_view table, Iter columns_begin,
\n-
194 Iter columns_end);
\n-
195
\n-
196 ~stream_from() noexcept;
\n-
197
\n-
\n-
199 [[nodiscard]] constexpr operator bool() const noexcept
\n-
200 {
\n-
201 return not m_finished;
\n-
202 }
\n-
\n-
\n-
204 [[nodiscard]] constexpr bool operator!() const noexcept
\n-
205 {
\n-
206 return m_finished;
\n-
207 }
\n-
\n-
208
\n-
210
\n-
216 void complete();
\n-
217
\n-
219
\n-
226 template<typename Tuple> stream_from &operator>>(Tuple &);
\n-
227
\n-
229 template<typename... Vs>
\n-
230 stream_from &operator>>(std::variant<Vs...> &) = delete;
\n-
231
\n-
233
\n-
\n-
237 template<typename... TYPE> [[nodiscard]] auto iter() &
\n-
238 {
\n-
239 return pqxx::internal::stream_input_iteration<TYPE...>{*this};
\n-
240 }
\n-
\n-
241
\n-
243
\n-
259 std::vector<zview> const *read_row() &;
\n-
260
\n-
262
\n-
263 raw_line get_raw_line();
\n-
264
\n-
265private:
\n-
266 // TODO: Clean up this signature once we cull the deprecated constructors.
\n-\n-
269 transaction_base &tx, std::string_view table, std::string_view columns,
\n-\n-
271
\n-
272 // TODO: Clean up this signature once we cull the deprecated constructors.
\n-\n-
275 transaction_base &, std::string_view unquoted_table,
\n-
276 std::string_view columns, from_table_t, int);
\n-
277
\n-
278 template<typename Tuple, std::size_t... indexes>
\n-
279 void extract_fields(Tuple &t, std::index_sequence<indexes...>) const
\n-
280 {
\n-
281 (extract_value<Tuple, indexes>(t), ...);
\n-
282 }
\n-
283
\n-
284 pqxx::internal::char_finder_func *m_char_finder;
\n-
285
\n-
287 std::string m_row;
\n-
288
\n-
290 std::vector<zview> m_fields;
\n-
291
\n-
292 bool m_finished = false;
\n-
293
\n-
294 void close();
\n-
295
\n-
296 template<typename Tuple, std::size_t index>
\n-
297 void extract_value(Tuple &) const;
\n-
298
\n-
300 void parse_line();
\n-
301};
\n-
\n-
302
\n-
303
\n-
304template<typename Columns>
\n-
\n-\n-
306 transaction_base &tx, from_table_t, std::string_view table_name,
\n-
307 Columns const &columns) :
\n-\n-
309 tx, from_table, table_name, std::begin(columns), std::end(columns)}
\n-
310{}
\n-
\n-
311
\n-
312
\n-
313template<typename Iter>
\n-
\n-\n-
315 transaction_base &tx, from_table_t, std::string_view table,
\n-
316 Iter columns_begin, Iter columns_end) :
\n-\n-
318 tx, table, separated_list(",", columns_begin, columns_end),
\n-
319 from_table, 1}
\n-
320{}
\n-
\n-
321
\n-
322
\n-
\n-
323template<typename Tuple> inline stream_from &stream_from::operator>>(Tuple &t)
\n-
324{
\n-
325 if (m_finished)
\n-
326 PQXX_UNLIKELY return *this;
\n-
327 static constexpr auto tup_size{std::tuple_size_v<Tuple>};
\n-
328 m_fields.reserve(tup_size);
\n-
329 parse_line();
\n-
330 if (m_finished)
\n-
331 PQXX_UNLIKELY return *this;
\n-
332
\n-
333 if (std::size(m_fields) != tup_size)
\n-
334 throw usage_error{internal::concat(
\n-
335 "Tried to extract ", tup_size, " field(s) from a stream of ",
\n-
336 std::size(m_fields), ".")};
\n-
337
\n-
338 extract_fields(t, std::make_index_sequence<tup_size>{});
\n-
339 return *this;
\n-
340}
\n-
\n-
341
\n-
342
\n-
343template<typename Tuple, std::size_t index>
\n-
344inline void stream_from::extract_value(Tuple &t) const
\n-
345{
\n-
346 using field_type = strip_t<decltype(std::get<index>(t))>;
\n-
347 using nullity = nullness<field_type>;
\n-
348 assert(index < std::size(m_fields));
\n-
349 if constexpr (nullity::always_null)
\n-
350 {
\n-
351 if (std::data(m_fields[index]) != nullptr)
\n-
352 throw conversion_error{"Streaming non-null value into null field."};
\n-
353 }
\n-
354 else if (std::data(m_fields[index]) == nullptr)
\n-
355 {
\n-
356 if constexpr (nullity::has_null)
\n-
357 std::get<index>(t) = nullity::null();
\n-
358 else
\n-
359 internal::throw_null_conversion(type_name<field_type>);
\n-
360 }
\n-
361 else
\n-
362 {
\n-
363 // Don't ever try to convert a non-null value to nullptr_t!
\n-
364 std::get<index>(t) = from_string<field_type>(m_fields[index]);
\n-
365 }
\n-
366}
\n-
367} // namespace pqxx
\n-
368#endif
\n+
75} // namespace pqxx
\n+
76#endif
\n
The home of all libpqxx classes, functions, templates, etc.
Definition array.hxx:33
\n-
std::string separated_list(std::string_view sep, ITER begin, ITER end, ACCESS access)
Represent sequence of values as a string, joined by a given separator.
Definition separated_list.hxx:44
\n-
std::remove_cv_t< std::remove_reference_t< TYPE > > strip_t
Remove any constness, volatile, and reference-ness from a type.
Definition types.hxx:91
\n-
constexpr from_query_t from_query
Pass this to a stream_from constructor to stream query results.
Definition stream_from.hxx:44
\n-
constexpr from_table_t from_table
Pass this to a stream_from constructor to stream table contents.
Definition stream_from.hxx:40
\n-
std::initializer_list< std::string_view > table_path
Representation of a PostgreSQL table path.
Definition connection.hxx:188
\n-
void PQXX_COLD throw_null_conversion(std::string const &type)
Definition strconv.cxx:253
\n-
Error in usage of libpqxx library, similar to std::logic_error.
Definition except.hxx:249
\n-
Value conversion failed, e.g. when converting "Hello" to int.
Definition except.hxx:283
\n-
Traits describing a type's "null value," if any.
Definition strconv.hxx:93
\n-
Stream data from the database.
Definition stream_from.hxx:79
\n-
static stream_from query(transaction_base &tx, std::string_view q)
Factory: Execute query, and stream the results.
Definition stream_from.hxx:98
\n-
stream_from & operator>>(std::variant< Vs... > &)=delete
Doing this with a std::variant is going to be horrifically borked.
\n-
stream_from & operator>>(Tuple &)
Read one row into a tuple.
Definition stream_from.hxx:323
\n-
stream_from(transaction_base &tx, std::string_view table, Columns const &columns)
Definition stream_from.hxx:185
\n-
std::pair< std::unique_ptr< char, void(*)(void const *)>, std::size_t > raw_line
Definition stream_from.hxx:82
\n-
stream_from(stream_from &&)=delete
\n-
stream_from(transaction_base &, std::string_view table, Iter columns_begin, Iter columns_end)
\n-
stream_from & operator=(stream_from &&)=delete
\n-
stream_from(transaction_base &tx, std::string_view table)
Definition stream_from.hxx:177
\n-
auto iter() &
Iterate over this stream. Supports range-based "for" loops.
Definition stream_from.hxx:237
\n-
constexpr bool operator!() const noexcept
Has this stream produced all the data it is going to produce?
Definition stream_from.hxx:204
\n+
Connection to a database.
Definition connection.hxx:253
\n+
Simple "transaction" class offering no transactional integrity.
Definition nontransaction.hxx:56
\n+
nontransaction(connection &c, std::string_view tname=""sv)
Constructor.
Definition nontransaction.hxx:64
\n+
virtual ~nontransaction() override
Definition nontransaction.hxx:70
\n
Interface definition (and common code) for "transaction" classes.
Definition transaction_base.hxx:88
\n-
Base class for things that monopolise a transaction's attention.
Definition transaction_focus.hxx:29
\n-
Marker for stream_from constructors: "stream from table.".
Definition types.hxx:68
\n-
Marker for stream_from constructors: "stream from query.".
Definition types.hxx:74
\n
\n
\n \n
\n \n
\n \n \n", "details": [{"source1": "html2text {}", "source2": "html2text {}", "unified_diff": "@@ -1,344 +1,76 @@\n \n \n \n \n \n libpqxx\u00a07.8.1\n \n-stream_from.hxx\n- 1/* Definition of the pqxx::stream_from class.\n+nontransaction.hxx\n+ 1/* Definition of the pqxx::nontransaction class.\n 2 *\n- 3 * pqxx::stream_from enables optimized batch reads from a database table.\n+ 3 * pqxx::nontransaction provides nontransactional database access\n 4 *\n- 5 * DO NOT INCLUDE THIS FILE DIRECTLY; include pqxx/stream_from instead.\n+ 5 * DO NOT INCLUDE THIS FILE DIRECTLY; include pqxx/nontransaction instead.\n 6 *\n 7 * Copyright (c) 2000-2023, Jeroen T. Vermeulen.\n 8 *\n 9 * See COPYING for copyright license. If you did not receive a file called\n 10 * COPYING with this source code, please notify the distributor of this\n 11 * mistake, or contact the author.\n 12 */\n- 13#ifndef PQXX_H_STREAM_FROM\n- 14#define PQXX_H_STREAM_FROM\n+ 13#ifndef PQXX_H_NONTRANSACTION\n+ 14#define PQXX_H_NONTRANSACTION\n 15\n 16#if !defined(PQXX_HEADER_PRE)\n 17# error \"Include libpqxx headers as , not .\"\n 18#endif\n 19\n- 20#include \n- 21#include \n- 22\n- 23#include \"pqxx/connection.hxx\"\n- 24#include \"pqxx/except.hxx\"\n- 25#include \"pqxx/internal/concat.hxx\"\n- 26#include \"pqxx/internal/encoding_group.hxx\"\n- 27#include \"pqxx/internal/stream_iterator.hxx\"\n- 28#include \"pqxx/separated_list.hxx\"\n- 29#include \"pqxx/transaction_focus.hxx\"\n- 30\n- 31\n- 32namespace pqxx\n- 33{\n- 34class transaction_base;\n- 35\n- 36\n- 38\n-40constexpr from_table_t from_table;\n- 42\n-44constexpr from_query_t from_query;\n- 45\n- 46\n- 48\n-78class PQXX_LIBEXPORT stream_from : transaction_focus\n- 79{\n- 80public:\n-81 using raw_line =\n- 82 std::pair, std::size_t>;\n- 83\n-84 stream_from(stream_from &&) = delete;\n-85 stream_from &operator=(stream_from &&) = delete;\n- 86\n- 88\n- 97 [[deprecated(\"Use transaction_base::stream instead.\")]] static stream_from\n-98 query(transaction_base &tx, std::string_view q)\n- 99 {\n- 100#include \"pqxx/internal/ignore-deprecated-pre.hxx\"\n- 101 return {tx, from_query, q};\n- 102#include \"pqxx/internal/ignore-deprecated-post.hxx\"\n- 103 }\n- 104\n- 115\n- 117\n- 133 [[deprecated(\"Use transaction_base::stream instead.\")]] static stream_from\n- 134 raw_table(\n- 135 transaction_base &tx, std::string_view path,\n- 136 std::string_view columns = \"\"sv);\n- 137\n- 139\n- 141 [[deprecated(\"Use transaction_base::stream instead.\")]] static stream_from\n- 142 table(\n- 143 transaction_base &tx, table_path path,\n- 144 std::initializer_list columns = {});\n- 146\n- 148\n- 150 [[deprecated(\"Use transaction_base::stream instead.\")]] stream_from(\n- 151 transaction_base &, from_query_t, std::string_view query);\n- 152\n- 154\n- 156 [[deprecated(\"Use transaction_base::stream instead.\")]] stream_from(\n- 157 transaction_base &, from_table_t, std::string_view table);\n- 158\n- 160\n- 162 template\n- 163 [[deprecated(\"Use transaction_base::stream instead.\")]] stream_from(\n- 164 transaction_base &, from_table_t, std::string_view table,\n- 165 Iter columns_begin, Iter columns_end);\n- 166\n- 168\n- 170 template\n- 171 [[deprecated(\"Use transaction_base::stream() instead.\")]] stream_from(\n- 172 transaction_base &tx, from_table_t, std::string_view table,\n- 173 Columns const &columns);\n- 174\n- 175#include \"pqxx/internal/ignore-deprecated-pre.hxx\"\n-177 [[deprecated(\"Use transaction_base::stream instead.\")]] stream_from(\n- 178 transaction_base &tx, std::string_view table) :\n- 179 stream_from{tx, from_table, table}\n- 180 {}\n- 181#include \"pqxx/internal/ignore-deprecated-post.hxx\"\n- 182\n- 184 template\n-185 [[deprecated(\"Use transaction_base::stream instead.\")]] stream_from(\n- 186 transaction_base &tx, std::string_view table, Columns const &columns) :\n- 187 stream_from{tx, from_table, table, columns}\n- 188 {}\n- 189\n- 191 template\n-192 [[deprecated(\"Use transaction_base::stream instead.\")]] stream_from(\n- 193 transaction_base &, std::string_view table, Iter columns_begin,\n- 194 Iter columns_end);\n- 195\n- 196 ~stream_from() noexcept;\n- 197\n-199 [[nodiscard]] constexpr operator bool() const noexcept\n- 200 {\n- 201 return not m_finished;\n- 202 }\n-204 [[nodiscard]] constexpr bool operator!() const noexcept\n- 205 {\n- 206 return m_finished;\n- 207 }\n- 208\n- 210\n- 216 void complete();\n- 217\n- 219\n- 226 template stream_from &operator>>(Tuple &);\n- 227\n- 229 template\n-230 stream_from &operator>>(std::variant &) = delete;\n- 231\n- 233\n-237 template [[nodiscard]] auto iter() &\n- 238 {\n- 239 return pqxx::internal::stream_input_iteration{*this};\n- 240 }\n- 241\n- 243\n- 259 std::vector const *read_row() &;\n- 260\n- 262\n- 263 raw_line get_raw_line();\n- 264\n- 265private:\n- 266 // TODO: Clean up this signature once we cull the deprecated constructors.\n- 268 stream_from(\n- 269 transaction_base &tx, std::string_view table, std::string_view columns,\n- 270 from_table_t);\n- 271\n- 272 // TODO: Clean up this signature once we cull the deprecated constructors.\n- 274 stream_from(\n- 275 transaction_base &, std::string_view unquoted_table,\n- 276 std::string_view columns, from_table_t, int);\n- 277\n- 278 template\n- 279 void extract_fields(Tuple &t, std::index_sequence) const\n- 280 {\n- 281 (extract_value(t), ...);\n- 282 }\n- 283\n- 284 pqxx::internal::char_finder_func *m_char_finder;\n- 285\n- 287 std::string m_row;\n- 288\n- 290 std::vector m_fields;\n- 291\n- 292 bool m_finished = false;\n- 293\n- 294 void close();\n- 295\n- 296 template\n- 297 void extract_value(Tuple &) const;\n- 298\n- 300 void parse_line();\n- 301};\n- 302\n- 303\n- 304template\n-305inline stream_from::stream_from(\n- 306 transaction_base &tx, from_table_t, std::string_view table_name,\n- 307 Columns const &columns) :\n- 308 stream_from{\n- 309 tx, from_table, table_name, std::begin(columns), std::end(columns)}\n- 310{}\n- 311\n- 312\n- 313template\n-314inline stream_from::stream_from(\n- 315 transaction_base &tx, from_table_t, std::string_view table,\n- 316 Iter columns_begin, Iter columns_end) :\n- 317 stream_from{\n- 318 tx, table, separated_list(\",\", columns_begin, columns_end),\n- 319 from_table, 1}\n- 320{}\n- 321\n- 322\n-323template inline stream_from &stream_from::operator>>(Tuple\n-&t)\n- 324{\n- 325 if (m_finished)\n- 326 PQXX_UNLIKELY return *this;\n- 327 static constexpr auto tup_size{std::tuple_size_v};\n- 328 m_fields.reserve(tup_size);\n- 329 parse_line();\n- 330 if (m_finished)\n- 331 PQXX_UNLIKELY return *this;\n- 332\n- 333 if (std::size(m_fields) != tup_size)\n- 334 throw usage_error{internal::concat(\n- 335 \"Tried to extract \", tup_size, \" field(s) from a stream of \",\n- 336 std::size(m_fields), \".\")};\n- 337\n- 338 extract_fields(t, std::make_index_sequence{});\n- 339 return *this;\n- 340}\n- 341\n- 342\n- 343template\n- 344inline void stream_from::extract_value(Tuple &t) const\n- 345{\n- 346 using field_type = strip_t(t))>;\n- 347 using nullity = nullness;\n- 348 assert(index < std::size(m_fields));\n- 349 if constexpr (nullity::always_null)\n- 350 {\n- 351 if (std::data(m_fields[index]) != nullptr)\n- 352 throw conversion_error{\"Streaming non-null value into null field.\"};\n- 353 }\n- 354 else if (std::data(m_fields[index]) == nullptr)\n- 355 {\n- 356 if constexpr (nullity::has_null)\n- 357 std::get(t) = nullity::null();\n- 358 else\n- 359 internal::throw_null_conversion(type_name);\n- 360 }\n- 361 else\n- 362 {\n- 363 // Don't ever try to convert a non-null value to nullptr_t!\n- 364 std::get(t) = from_string(m_fields[index]);\n- 365 }\n- 366}\n- 367} // namespace pqxx\n- 368#endif\n+ 20#include \"pqxx/connection.hxx\"\n+ 21#include \"pqxx/result.hxx\"\n+ 22#include \"pqxx/transaction.hxx\"\n+ 23\n+ 24namespace pqxx\n+ 25{\n+ 26using namespace std::literals;\n+ 27\n+ 29\n+55class PQXX_LIBEXPORT nontransaction final : public transaction_base\n+ 56{\n+ 57public:\n+ 59\n+64 nontransaction(connection &c, std::string_view tname = \"\"sv) :\n+ 65 transaction_base{c, tname, std::shared_ptr{}}\n+ 66 {\n+ 67 register_transaction();\n+ 68 }\n+ 69\n+70 virtual ~nontransaction() override { close(); }\n+ 71\n+ 72private:\n+ 73 virtual void do_commit() override {}\n+ 74};\n+ 75} // namespace pqxx\n+ 76#endif\n pqxx\n The home of all libpqxx classes, functions, templates, etc.\n Definition array.hxx:33\n-pqxx::separated_list\n-std::string separated_list(std::string_view sep, ITER begin, ITER end, ACCESS\n-access)\n-Represent sequence of values as a string, joined by a given separator.\n-Definition separated_list.hxx:44\n-pqxx::strip_t\n-std::remove_cv_t< std::remove_reference_t< TYPE > > strip_t\n-Remove any constness, volatile, and reference-ness from a type.\n-Definition types.hxx:91\n-pqxx::from_query\n-constexpr from_query_t from_query\n-Pass this to a stream_from constructor to stream query results.\n-Definition stream_from.hxx:44\n-pqxx::from_table\n-constexpr from_table_t from_table\n-Pass this to a stream_from constructor to stream table contents.\n-Definition stream_from.hxx:40\n-pqxx::table_path\n-std::initializer_list< std::string_view > table_path\n-Representation of a PostgreSQL table path.\n-Definition connection.hxx:188\n-pqxx::internal::throw_null_conversion\n-void PQXX_COLD throw_null_conversion(std::string const &type)\n-Definition strconv.cxx:253\n-pqxx::usage_error\n-Error in usage of libpqxx library, similar to std::logic_error.\n-Definition except.hxx:249\n-pqxx::conversion_error\n-Value conversion failed, e.g. when converting \"Hello\" to int.\n-Definition except.hxx:283\n-pqxx::nullness\n-Traits describing a type's \"null value,\" if any.\n-Definition strconv.hxx:93\n-pqxx::stream_from\n-Stream data from the database.\n-Definition stream_from.hxx:79\n-pqxx::stream_from::query\n-static stream_from query(transaction_base &tx, std::string_view q)\n-Factory: Execute query, and stream the results.\n-Definition stream_from.hxx:98\n-pqxx::stream_from::operator>>\n-stream_from & operator>>(std::variant< Vs... > &)=delete\n-Doing this with a std::variant is going to be horrifically borked.\n-pqxx::stream_from::operator>>\n-stream_from & operator>>(Tuple &)\n-Read one row into a tuple.\n-Definition stream_from.hxx:323\n-pqxx::stream_from::stream_from\n-stream_from(transaction_base &tx, std::string_view table, Columns const\n-&columns)\n-Definition stream_from.hxx:185\n-pqxx::stream_from::raw_line\n-std::pair< std::unique_ptr< char, void(*)(void const *)>, std::size_t >\n-raw_line\n-Definition stream_from.hxx:82\n-pqxx::stream_from::stream_from\n-stream_from(stream_from &&)=delete\n-pqxx::stream_from::stream_from\n-stream_from(transaction_base &, std::string_view table, Iter columns_begin,\n-Iter columns_end)\n-pqxx::stream_from::operator=\n-stream_from & operator=(stream_from &&)=delete\n-pqxx::stream_from::stream_from\n-stream_from(transaction_base &tx, std::string_view table)\n-Definition stream_from.hxx:177\n-pqxx::stream_from::iter\n-auto iter() &\n-Iterate over this stream. Supports range-based \"for\" loops.\n-Definition stream_from.hxx:237\n-pqxx::stream_from::operator!\n-constexpr bool operator!() const noexcept\n-Has this stream produced all the data it is going to produce?\n-Definition stream_from.hxx:204\n+pqxx::connection\n+Connection to a database.\n+Definition connection.hxx:253\n+pqxx::nontransaction\n+Simple \"transaction\" class offering no transactional integrity.\n+Definition nontransaction.hxx:56\n+pqxx::nontransaction::nontransaction\n+nontransaction(connection &c, std::string_view tname=\"\"sv)\n+Constructor.\n+Definition nontransaction.hxx:64\n+pqxx::nontransaction::~nontransaction\n+virtual ~nontransaction() override\n+Definition nontransaction.hxx:70\n pqxx::transaction_base\n Interface definition (and common code) for \"transaction\" classes.\n Definition transaction_base.hxx:88\n-pqxx::transaction_focus\n-Base class for things that monopolise a transaction's attention.\n-Definition transaction_focus.hxx:29\n-pqxx::from_table_t\n-Marker for stream_from constructors: \"stream from table.\".\n-Definition types.hxx:68\n-pqxx::from_query_t\n-Marker for stream_from constructors: \"stream from query.\".\n-Definition types.hxx:74\n * include\n * pqxx\n- * stream_from.hxx\n+ * nontransaction.hxx\n * Generated by [doxygen] 1.9.8\n"}]}, {"source1": "./usr/share/doc/libpqxx-doc/html/a00041_source.html", "source2": "./usr/share/doc/libpqxx-doc/html/a00041_source.html", "unified_diff": "@@ -1,15 +1,15 @@\n \n \n \n \n \n \n \n-libpqxx: range.hxx Source File\n+libpqxx: transaction_base.hxx Source File\n \n \n \n \n \n \n \n@@ -60,631 +60,671 @@\n \n
\n
\n-
range.hxx
\n+
transaction_base.hxx
\n
\n
\n-
1#ifndef PQXX_H_RANGE
\n-
2#define PQXX_H_RANGE
\n-
3
\n-
4#if !defined(PQXX_HEADER_PRE)
\n-
5# error "Include libpqxx headers as <pqxx/header>, not <pqxx/header.hxx>."
\n-
6#endif
\n-
7
\n-
8#include <utility>
\n-
9#include <variant>
\n-
10
\n-
11#include "pqxx/internal/array-composite.hxx"
\n-
12#include "pqxx/internal/concat.hxx"
\n-
13
\n-
14namespace pqxx
\n-
15{
\n-
17
\n-
\n-\n-
24{
\n-
25 template<typename TYPE>
\n-
\n-
26 constexpr bool extends_down_to(TYPE const &) const noexcept
\n-
27 {
\n-
28 return true;
\n-
29 }
\n-
\n-
30 template<typename TYPE>
\n-
\n-
31 constexpr bool extends_up_to(TYPE const &) const noexcept
\n-
32 {
\n-
33 return true;
\n-
34 }
\n-
\n-
35};
\n-
\n-
36
\n-
37
\n-
39
\n-
\n-
42template<typename TYPE> class inclusive_bound
\n-
43{
\n-
44 // (Putting private section first to work around bug in gcc < 10: see #665.)
\n-
45private:
\n-
46 TYPE m_value;
\n-
47
\n-
48public:
\n-
49 inclusive_bound() = delete;
\n-
\n-
50 constexpr explicit inclusive_bound(TYPE const &value) : m_value{value}
\n-
51 {
\n-
52 if (is_null(value))
\n-
53 throw argument_error{"Got null value as an inclusive range bound."};
\n-
54 }
\n-
\n-
55
\n-
56 [[nodiscard]] constexpr TYPE const &get() const &noexcept { return m_value; }
\n+
1/* Common code and definitions for the transaction classes.
\n+
2 *
\n+
3 * pqxx::transaction_base defines the interface for any abstract class that
\n+
4 * represents a database transaction.
\n+
5 *
\n+
6 * DO NOT INCLUDE THIS FILE DIRECTLY; include pqxx/transaction_base instead.
\n+
7 *
\n+
8 * Copyright (c) 2000-2023, Jeroen T. Vermeulen.
\n+
9 *
\n+
10 * See COPYING for copyright license. If you did not receive a file called
\n+
11 * COPYING with this source code, please notify the distributor of this
\n+
12 * mistake, or contact the author.
\n+
13 */
\n+
14#ifndef PQXX_H_TRANSACTION_BASE
\n+
15#define PQXX_H_TRANSACTION_BASE
\n+
16
\n+
17#if !defined(PQXX_HEADER_PRE)
\n+
18# error "Include libpqxx headers as <pqxx/header>, not <pqxx/header.hxx>."
\n+
19#endif
\n+
20
\n+
21#include <string_view>
\n+
22
\n+
23/* End-user programs need not include this file, unless they define their own
\n+
24 * transaction classes. This is not something the typical program should want
\n+
25 * to do.
\n+
26 *
\n+
27 * However, reading this file is worthwhile because it defines the public
\n+
28 * interface for the available transaction classes such as transaction and
\n+
29 * nontransaction.
\n+
30 */
\n+
31
\n+
32#include "pqxx/connection.hxx"
\n+
33#include "pqxx/internal/concat.hxx"
\n+
34#include "pqxx/internal/encoding_group.hxx"
\n+
35#include "pqxx/internal/stream_query.hxx"
\n+
36#include "pqxx/isolation.hxx"
\n+
37#include "pqxx/result.hxx"
\n+
38#include "pqxx/row.hxx"
\n+
39#include "pqxx/util.hxx"
\n+
40
\n+\n+
42{
\n+
43class transaction_subtransaction;
\n+
44class transaction_sql_cursor;
\n+
45class transaction_stream_to;
\n+
46class transaction_transaction_focus;
\n+
47} // namespace pqxx::internal::gate
\n+
48
\n+
49
\n+
50namespace pqxx
\n+
51{
\n+
52using namespace std::literals;
\n+
53
\n+
54
\n+
55class transaction_focus;
\n+
56
\n
57
\n-
\n-
59 [[nodiscard]] constexpr bool extends_down_to(TYPE const &value) const
\n-
60 noexcept(noexcept(value < m_value))
\n-
61 {
\n-
62 return not(value < m_value);
\n-
63 }
\n-
\n-
64
\n-
\n-
66 [[nodiscard]] constexpr bool extends_up_to(TYPE const &value) const
\n-
67 noexcept(noexcept(value < m_value))
\n-
68 {
\n-
69 return not(m_value < value);
\n-
70 }
\n-
\n-
71};
\n-
\n-
72
\n-
73
\n-
75
\n-
\n-
78template<typename TYPE> class exclusive_bound
\n-
79{
\n-
80 // (Putting private section first to work around bug in gcc < 10: see #665.)
\n-
81private:
\n-
82 TYPE m_value;
\n-
83
\n-
84public:
\n-
85 exclusive_bound() = delete;
\n-
\n-
86 constexpr explicit exclusive_bound(TYPE const &value) : m_value{value}
\n-
87 {
\n-
88 if (is_null(value))
\n-
89 throw argument_error{"Got null value as an exclusive range bound."};
\n-
90 }
\n-
\n-
91
\n-
92 [[nodiscard]] constexpr TYPE const &get() const &noexcept { return m_value; }
\n-
93
\n-
\n-
95 [[nodiscard]] constexpr bool extends_down_to(TYPE const &value) const
\n-
96 noexcept(noexcept(m_value < value))
\n-
97 {
\n-
98 return m_value < value;
\n-
99 }
\n-
\n-
100
\n-
\n-
102 [[nodiscard]] constexpr bool extends_up_to(TYPE const &value) const
\n-
103 noexcept(noexcept(value < m_value))
\n-
104 {
\n-
105 return value < m_value;
\n-
106 }
\n-
\n-
107};
\n-
\n-
108
\n-
109
\n-
111
\n-
\n-
114template<typename TYPE> class range_bound
\n-
115{
\n-
116 // (Putting private section first to work around bug in gcc < 10: see #665.)
\n-
117private:
\n-
118 std::variant<no_bound, inclusive_bound<TYPE>, exclusive_bound<TYPE>> m_bound;
\n+
82
\n+
\n+
87class PQXX_LIBEXPORT PQXX_NOVTABLE transaction_base
\n+
88{
\n+
89public:
\n+
90 transaction_base() = delete;
\n+\n+\n+\n+\n+
95
\n+
96 virtual ~transaction_base() = 0;
\n+
97
\n+
99
\n+
112 void commit();
\n+
113
\n+
115
\n+
118 void abort();
\n
119
\n-
120public:
\n-
121 range_bound() = delete;
\n-
122 constexpr range_bound(no_bound) noexcept : m_bound{} {}
\n-
123
\n-
\n-
124 constexpr range_bound(inclusive_bound<TYPE> const &bound) noexcept(
\n-
125 noexcept(inclusive_bound<TYPE>{bound})) :
\n-
126 m_bound{bound}
\n-
127 {}
\n-
\n-
128
\n-
\n-
129 constexpr range_bound(exclusive_bound<TYPE> const &bound) noexcept(
\n-
130 noexcept(exclusive_bound{bound})) :
\n-
131 m_bound{bound}
\n-
132 {}
\n-
\n-
133
\n-
134 constexpr range_bound(range_bound const &) noexcept(
\n-
135 noexcept(inclusive_bound<TYPE>{
\n-
136 std::declval<inclusive_bound<TYPE> const &>()})
\n-
137 and noexcept(exclusive_bound<TYPE>{
\n-
138 std::declval<exclusive_bound<TYPE> const &>()})) = default;
\n-
139
\n-
140 constexpr range_bound(range_bound &&) = default;
\n-
141
\n-
\n-
142 constexpr bool operator==(range_bound const &rhs) const
\n-
143 noexcept(noexcept(*this->value() == *rhs.value()))
\n-
144 {
\n-
145 if (this->is_limited())
\n-
146 return (
\n-
147 rhs.is_limited() and (this->is_inclusive() == rhs.is_inclusive()) and
\n-
148 (*this->value() == *rhs.value()));
\n-
149 else
\n-
150 return not rhs.is_limited();
\n+
\n+
131 template<typename... ARGS> [[nodiscard]] auto esc(ARGS &&...args) const
\n+
132 {
\n+
133 return conn().esc(std::forward<ARGS>(args)...);
\n+
134 }
\n+
\n+
135
\n+
137
\n+
\n+
148 template<typename... ARGS> [[nodiscard]] auto esc_raw(ARGS &&...args) const
\n+
149 {
\n+
150 return conn().esc_raw(std::forward<ARGS>(args)...);
\n
151 }
\n
\n
152
\n-
\n-
153 constexpr bool operator!=(range_bound const &rhs) const
\n-
154 noexcept(noexcept(*this == rhs))
\n-
155 {
\n-
156 return not(*this == rhs);
\n-
157 }
\n-
\n-
158 range_bound &operator=(range_bound const &) = default;
\n-\n-
160
\n-
\n-
162 constexpr bool is_limited() const noexcept
\n-
163 {
\n-
164 return not std::holds_alternative<no_bound>(m_bound);
\n-
165 }
\n+
154
\n+
157 [[nodiscard, deprecated("Use unesc_bin() instead.")]] std::string
\n+
\n+\n+
159 {
\n+
160#include "pqxx/internal/ignore-deprecated-pre.hxx"
\n+
161 return conn().unesc_raw(text);
\n+
162#include "pqxx/internal/ignore-deprecated-post.hxx"
\n+
163 }
\n
\n+
164
\n
166
\n-
\n-
168 constexpr bool is_inclusive() const noexcept
\n-
169 {
\n-
170 return std::holds_alternative<inclusive_bound<TYPE>>(m_bound);
\n-
171 }
\n-
\n-
172
\n-
\n-
174 constexpr bool is_exclusive() const noexcept
\n-
175 {
\n-
176 return std::holds_alternative<exclusive_bound<TYPE>>(m_bound);
\n-
177 }
\n-
\n-
178
\n-
\n-
180 constexpr bool extends_down_to(TYPE const &value) const
\n-
181 {
\n-
182 return std::visit(
\n-
183 [&value](auto const &bound) noexcept(noexcept(bound.extends_down_to(
\n-
184 value))) { return bound.extends_down_to(value); },
\n-
185 m_bound);
\n-
186 }
\n+
\n+
169 [[nodiscard]] std::basic_string<std::byte> unesc_bin(zview text)
\n+
170 {
\n+
171 return conn().unesc_bin(text);
\n+
172 }
\n+
\n+
173
\n+
175
\n+
178 [[nodiscard, deprecated("Use unesc_bin() instead.")]] std::string
\n+
\n+
179 unesc_raw(char const *text) const
\n+
180 {
\n+
181#include "pqxx/internal/ignore-deprecated-pre.hxx"
\n+
182 return conn().unesc_raw(text);
\n+
183#include "pqxx/internal/ignore-deprecated-post.hxx"
\n+
184 }
\n
\n+
185
\n
187
\n-
\n-
189 constexpr bool extends_up_to(TYPE const &value) const
\n-
190 {
\n-
191 return std::visit(
\n-
192 [&value](auto const &bound) noexcept(noexcept(
\n-
193 bound.extends_up_to(value))) { return bound.extends_up_to(value); },
\n-
194 m_bound);
\n-
195 }
\n+
\n+
190 [[nodiscard]] std::basic_string<std::byte> unesc_bin(char const text[])
\n+
191 {
\n+
192 return conn().unesc_bin(text);
\n+
193 }
\n
\n+
194
\n
196
\n-
\n-
198 [[nodiscard]] constexpr TYPE const *value() const &noexcept
\n-
199 {
\n-
200 return std::visit(
\n-
201 [](auto const &bound) noexcept {
\n-
202 using bound_t = std::decay_t<decltype(bound)>;
\n-
203 if constexpr (std::is_same_v<bound_t, no_bound>)
\n-
204 return static_cast<TYPE const *>(nullptr);
\n-
205 else
\n-
206 return &bound.get();
\n-
207 },
\n-
208 m_bound);
\n-
209 }
\n-
\n-
210};
\n-
\n-
211
\n-
212
\n-
213// C++20: Concepts for comparisons, construction, etc.
\n+
\n+
197 template<typename T> [[nodiscard]] std::string quote(T const &t) const
\n+
198 {
\n+
199 return conn().quote(t);
\n+
200 }
\n+
\n+
201
\n+
202 [[deprecated(
\n+
203 "Use std::basic_string<std::byte> instead of binarystring.")]] std::string
\n+
\n+
204 quote(binarystring const &t) const
\n+
205 {
\n+
206 return conn().quote(t.bytes_view());
\n+
207 }
\n+
\n+
208
\n+
210 [[deprecated("Use quote(std::basic_string_view<std::byte>).")]] std::string
\n+
\n+
211 quote_raw(unsigned char const bin[], std::size_t len) const
\n+
212 {
\n+
213 return quote(binary_cast(bin, len));
\n+
214 }
\n+
\n
215
\n-
\n-
233template<typename TYPE> class range
\n-
234{
\n-
235 // (Putting private section first to work around bug in gcc < 10: see #665.)
\n-
236private:
\n-
237 range_bound<TYPE> m_lower, m_upper;
\n-
238
\n-
239public:
\n-
241
\n-
\n-
245 constexpr range(range_bound<TYPE> lower, range_bound<TYPE> upper) :
\n-
246 m_lower{lower}, m_upper{upper}
\n-
247 {
\n-
248 if (
\n-
249 lower.is_limited() and upper.is_limited() and
\n-
250 (*upper.value() < *lower.value()))
\n-
251 throw range_error{internal::concat(
\n-
252 "Range's lower bound (", *lower.value(),
\n-
253 ") is greater than its upper bound (", *upper.value(), ").")};
\n-
254 }
\n-
\n-
255
\n-
257
\n-
\n-
260 constexpr range() noexcept(noexcept(exclusive_bound<TYPE>{TYPE{}})) :
\n-
261 m_lower{exclusive_bound<TYPE>{TYPE{}}},
\n-
262 m_upper{exclusive_bound<TYPE>{TYPE{}}}
\n-
263 {}
\n-
\n-
264
\n-
\n-
265 constexpr bool operator==(range const &rhs) const
\n-
266 noexcept(noexcept(this->lower_bound() == rhs.lower_bound()) and noexcept(
\n-
267 this->upper_bound() == rhs.upper_bound()) and noexcept(this->empty()))
\n-
268 {
\n-
269 return (this->lower_bound() == rhs.lower_bound() and
\n-
270 this->upper_bound() == rhs.upper_bound()) or
\n-
271 (this->empty() and rhs.empty());
\n-
272 }
\n-
\n-
273
\n-
\n-
274 constexpr bool operator!=(range const &rhs) const
\n-
275 noexcept(noexcept(*this == rhs))
\n-
276 {
\n-
277 return not(*this == rhs);
\n-
278 }
\n-
\n-
279
\n-
280 range(range const &) = default;
\n-
281 range(range &&) = default;
\n-
282 range &operator=(range const &) = default;
\n-
283 range &operator=(range &&) = default;
\n-
284
\n-
286
\n-
\n-
294 constexpr bool empty() const
\n-
295 noexcept(noexcept(m_lower.is_exclusive()) and noexcept(
\n-
296 m_lower.is_limited()) and noexcept(*m_lower.value() < *m_upper.value()))
\n-
297 {
\n-
298 return (m_lower.is_exclusive() or m_upper.is_exclusive()) and
\n-
299 m_lower.is_limited() and m_upper.is_limited() and
\n-
300 not(*m_lower.value() < *m_upper.value());
\n-
301 }
\n-
\n-
302
\n-
\n-
304 constexpr bool contains(TYPE value) const noexcept(noexcept(
\n-
305 m_lower.extends_down_to(value)) and noexcept(m_upper.extends_up_to(value)))
\n-
306 {
\n-
307 return m_lower.extends_down_to(value) and m_upper.extends_up_to(value);
\n-
308 }
\n-
\n-
309
\n-
311
\n-
\n-
314 constexpr bool contains(range<TYPE> const &other) const
\n-
315 noexcept(noexcept((*this & other) == other))
\n+
217 [[deprecated("Use quote(std::basic_string_view<std::byte>).")]] std::string
\n+
218 quote_raw(zview bin) const;
\n+
219
\n+
220#if defined(PQXX_HAVE_CONCEPTS)
\n+
222
\n+
223 template<binary DATA>
\n+
224 [[nodiscard]] std::string quote_raw(DATA const &data) const
\n+
225 {
\n+
226 return conn().quote_raw(data);
\n+
227 }
\n+
228#endif
\n+
229
\n+
\n+
231 [[nodiscard]] std::string quote_name(std::string_view identifier) const
\n+
232 {
\n+
233 return conn().quote_name(identifier);
\n+
234 }
\n+
\n+
235
\n+
237 [[nodiscard]] std::string
\n+
\n+
238 esc_like(std::string_view bin, char escape_char = '\\\\') const
\n+
239 {
\n+
240 return conn().esc_like(bin, escape_char);
\n+
241 }
\n+
\n+
243
\n+
285
\n+
287
\n+
292 [[deprecated("The desc parameter is going away.")]] result
\n+
293 exec(std::string_view query, std::string_view desc);
\n+
294
\n+
296
\n+
\n+
300 result exec(std::string_view query)
\n+
301 {
\n+
302#include "pqxx/internal/ignore-deprecated-pre.hxx"
\n+
303 return exec(query, std::string_view{});
\n+
304#include "pqxx/internal/ignore-deprecated-post.hxx"
\n+
305 }
\n+
\n+
306
\n+
308
\n+
313 [[deprecated(
\n+
314 "Pass your query as a std::string_view, not stringstream.")]] result
\n+
\n+
315 exec(std::stringstream const &query, std::string_view desc)
\n
316 {
\n-
317 return (*this & other) == other;
\n-
318 }
\n-
\n-
319
\n-
320 [[nodiscard]] constexpr range_bound<TYPE> const &
\n-
\n-
321 lower_bound() const &noexcept
\n-
322 {
\n-
323 return m_lower;
\n-
324 }
\n-
\n-
325 [[nodiscard]] constexpr range_bound<TYPE> const &
\n-
\n-
326 upper_bound() const &noexcept
\n-
327 {
\n-
328 return m_upper;
\n-
329 }
\n-
\n-
330
\n-
332
\n-
\n-
334 constexpr range operator&(range const &other) const
\n-
335 {
\n-\n-
337 if (not this->lower_bound().is_limited())
\n-
338 lower = other.lower_bound();
\n-
339 else if (not other.lower_bound().is_limited())
\n-
340 lower = this->lower_bound();
\n-
341 else if (*this->lower_bound().value() < *other.lower_bound().value())
\n-
342 lower = other.lower_bound();
\n-
343 else if (*other.lower_bound().value() < *this->lower_bound().value())
\n-
344 lower = this->lower_bound();
\n-
345 else if (this->lower_bound().is_exclusive())
\n-
346 lower = this->lower_bound();
\n-
347 else
\n-
348 lower = other.lower_bound();
\n-
349
\n-\n-
351 if (not this->upper_bound().is_limited())
\n-
352 upper = other.upper_bound();
\n-
353 else if (not other.upper_bound().is_limited())
\n-
354 upper = this->upper_bound();
\n-
355 else if (*other.upper_bound().value() < *this->upper_bound().value())
\n-
356 upper = other.upper_bound();
\n-
357 else if (*this->upper_bound().value() < *other.upper_bound().value())
\n-
358 upper = this->upper_bound();
\n-
359 else if (this->upper_bound().is_exclusive())
\n-
360 upper = this->upper_bound();
\n-
361 else
\n-
362 upper = other.upper_bound();
\n-
363
\n-
364 if (
\n-
365 lower.is_limited() and upper.is_limited() and
\n-
366 (*upper.value() < *lower.value()))
\n-
367 return {};
\n-
368 else
\n-
369 return {lower, upper};
\n-
370 }
\n-
\n-
371
\n-
\n-
373 template<typename DEST> operator range<DEST>() const
\n-
374 {
\n-
375 range_bound<DEST> lower{no_bound{}}, upper{no_bound{}};
\n-
376 if (lower_bound().is_inclusive())
\n-
377 lower = inclusive_bound<DEST>{*lower_bound().value()};
\n-
378 else if (lower_bound().is_exclusive())
\n-
379 lower = exclusive_bound<DEST>{*lower_bound().value()};
\n-
380
\n-
381 if (upper_bound().is_inclusive())
\n-
382 upper = inclusive_bound<DEST>{*upper_bound().value()};
\n-
383 else if (upper_bound().is_exclusive())
\n-
384 upper = exclusive_bound<DEST>{*upper_bound().value()};
\n-
385
\n-
386 return {lower, upper};
\n-
387 }
\n-
\n-
388};
\n+
317#include "pqxx/internal/ignore-deprecated-pre.hxx"
\n+
318 return exec(query.str(), desc);
\n+
319#include "pqxx/internal/ignore-deprecated-post.hxx"
\n+
320 }
\n+
\n+
321
\n+
323
\n+
328 [[deprecated("The desc parameter is going away.")]] result
\n+
\n+
329 exec0(zview query, std::string_view desc)
\n+
330 {
\n+
331#include "pqxx/internal/ignore-deprecated-pre.hxx"
\n+
332 return exec_n(0, query, desc);
\n+
333#include "pqxx/internal/ignore-deprecated-post.hxx"
\n+
334 }
\n+
\n+
335
\n+
337
\n+
342 result exec0(zview query) { return exec_n(0, query); }
\n+
343
\n+
345
\n+
351 [[deprecated("The desc parameter is going away.")]] row
\n+
\n+
352 exec1(zview query, std::string_view desc)
\n+
353 {
\n+
354#include "pqxx/internal/ignore-deprecated-pre.hxx"
\n+
355 return exec_n(1, query, desc).front();
\n+
356#include "pqxx/internal/ignore-deprecated-post.hxx"
\n+
357 }
\n+
\n+
358
\n+
360
\n+
366 row exec1(zview query) { return exec_n(1, query).front(); }
\n+
367
\n+
369
\n+
374 [[deprecated("The desc parameter is going away.")]] result
\n+
375 exec_n(result::size_type rows, zview query, std::string_view desc);
\n+
376
\n+
378
\n+
\n+\n+
384 {
\n+
385#include "pqxx/internal/ignore-deprecated-pre.hxx"
\n+
386 return exec_n(rows, query, std::string_view{});
\n+
387#include "pqxx/internal/ignore-deprecated-post.hxx"
\n+
388 }
\n
\n
389
\n-
390
\n-
392
\n-
\n-
395template<typename TYPE> struct string_traits<range<TYPE>>
\n-
396{
\n-
397 [[nodiscard]] static inline zview
\n-
\n-
398 to_buf(char *begin, char *end, range<TYPE> const &value)
\n-
399 {
\n-
400 return generic_to_buf(begin, end, value);
\n-
401 }
\n-
\n-
402
\n-
403 static inline char *
\n-
\n-
404 into_buf(char *begin, char *end, range<TYPE> const &value)
\n-
405 {
\n-
406 if (value.empty())
\n-
407 {
\n-
408 if ((end - begin) <= internal::ssize(s_empty))
\n-
409 throw conversion_overrun{s_overrun.c_str()};
\n-
410 char *here = begin + s_empty.copy(begin, std::size(s_empty));
\n-
411 *here++ = '\\0';
\n-
412 return here;
\n-
413 }
\n-
414 else
\n-
415 {
\n-
416 if (end - begin < 4)
\n-
417 throw conversion_overrun{s_overrun.c_str()};
\n-
418 char *here = begin;
\n-
419 *here++ =
\n-
420 (static_cast<char>(value.lower_bound().is_inclusive() ? '[' : '('));
\n-
421 TYPE const *lower{value.lower_bound().value()};
\n-
422 // Convert bound (but go back to overwrite that trailing zero).
\n-
423 if (lower != nullptr)
\n-
424 here = string_traits<TYPE>::into_buf(here, end, *lower) - 1;
\n-
425 *here++ = ',';
\n-
426 TYPE const *upper{value.upper_bound().value()};
\n-
427 // Convert bound (but go back to overwrite that trailing zero).
\n-
428 if (upper != nullptr)
\n-
429 here = string_traits<TYPE>::into_buf(here, end, *upper) - 1;
\n-
430 if ((end - here) < 2)
\n-
431 throw conversion_overrun{s_overrun.c_str()};
\n-
432 *here++ =
\n-
433 static_cast<char>(value.upper_bound().is_inclusive() ? ']' : ')');
\n-
434 *here++ = '\\0';
\n-
435 return here;
\n-
436 }
\n-
437 }
\n+
391
\n+
394 template<typename TYPE>
\n+
395 [[deprecated("The desc parameter is going away.")]] TYPE
\n+
\n+
396 query_value(zview query, std::string_view desc)
\n+
397 {
\n+
398#include "pqxx/internal/ignore-deprecated-pre.hxx"
\n+
399 row const r{exec1(query, desc)};
\n+
400#include "pqxx/internal/ignore-deprecated-post.hxx"
\n+
401 if (std::size(r) != 1)
\n+
402 throw usage_error{internal::concat(
\n+
403 "Queried single value from result with ", std::size(r), " columns.")};
\n+
404 return r[0].as<TYPE>();
\n+
405 }
\n+
\n+
406
\n+
408
\n+
\n+
414 template<typename TYPE> TYPE query_value(zview query)
\n+
415 {
\n+
416 row const r{exec1(query)};
\n+
417 if (std::size(r) != 1)
\n+
418 throw usage_error{internal::concat(
\n+
419 "Queried single value from result with ", std::size(r), " columns.")};
\n+
420 return r[0].as<TYPE>();
\n+
421 }
\n+
\n+
422
\n+
424
\n+
431 template<typename... TYPE>
\n+
\n+
432 [[nodiscard]] std::tuple<TYPE...> query1(zview query)
\n+
433 {
\n+
434 return exec1(query).as<TYPE...>();
\n+
435 }
\n
\n+
436
\n
438
\n-
\n-
439 [[nodiscard]] static inline range<TYPE> from_string(std::string_view text)
\n-
440 {
\n-
441 if (std::size(text) < 3)
\n-
442 throw pqxx::conversion_error{err_bad_input(text)};
\n-
443 bool left_inc{false};
\n-
444 switch (text[0])
\n-
445 {
\n-
446 case '[': left_inc = true; break;
\n-
447
\n-
448 case '(': break;
\n-
449
\n-
450 case 'e':
\n-
451 case 'E':
\n-
452 if (
\n-
453 (std::size(text) != std::size(s_empty)) or
\n-
454 (text[1] != 'm' and text[1] != 'M') or
\n-
455 (text[2] != 'p' and text[2] != 'P') or
\n-
456 (text[3] != 't' and text[3] != 'T') or
\n-
457 (text[4] != 'y' and text[4] != 'Y'))
\n-
458 throw pqxx::conversion_error{err_bad_input(text)};
\n-
459 return {};
\n-
460 break;
\n-
461
\n-
462 default: throw pqxx::conversion_error{err_bad_input(text)};
\n-
463 }
\n-
464
\n-
465 // The field parser uses this to track which field it's parsing, and
\n-
466 // when not to expect a field separator.
\n-
467 std::size_t index{0};
\n-
468 // The last field we expect to see.
\n-
469 static constexpr std::size_t last{1};
\n-
470 // Current parsing position. We skip the opening parenthesis or bracket.
\n-
471 std::size_t pos{1};
\n-
472 // The string may leave out either bound to indicate that it's unlimited.
\n-
473 std::optional<TYPE> lower, upper;
\n-
474 // We reuse the same field parser we use for composite values and arrays.
\n-
475 auto const field_parser{
\n-
476 pqxx::internal::specialize_parse_composite_field<std::optional<TYPE>>(
\n-
477 pqxx::internal::encoding_group::UTF8)};
\n-
478 field_parser(index, text, pos, lower, last);
\n-
479 field_parser(index, text, pos, upper, last);
\n-
480
\n-
481 // We need one more character: the closing parenthesis or bracket.
\n-
482 if (pos != std::size(text))
\n-
483 throw pqxx::conversion_error{err_bad_input(text)};
\n-
484 char const closing{text[pos - 1]};
\n-
485 if (closing != ')' and closing != ']')
\n-
486 throw pqxx::conversion_error{err_bad_input(text)};
\n-
487 bool const right_inc{closing == ']'};
\n-
488
\n-
489 range_bound<TYPE> lower_bound{no_bound{}}, upper_bound{no_bound{}};
\n-
490 if (lower)
\n-
491 {
\n-
492 if (left_inc)
\n-
493 lower_bound = inclusive_bound{*lower};
\n-
494 else
\n-
495 lower_bound = exclusive_bound{*lower};
\n-
496 }
\n-
497 if (upper)
\n-
498 {
\n-
499 if (right_inc)
\n-
500 upper_bound = inclusive_bound{*upper};
\n-
501 else
\n-
502 upper_bound = exclusive_bound{*upper};
\n-
503 }
\n-
504
\n-
505 return {lower_bound, upper_bound};
\n-
506 }
\n-
\n-
507
\n-
508 [[nodiscard]] static inline constexpr std::size_t
\n-
\n-
509 size_buffer(range<TYPE> const &value) noexcept
\n-
510 {
\n-
511 TYPE const *lower{value.lower_bound().value()},
\n-
512 *upper{value.upper_bound().value()};
\n-
513 std::size_t const lsz{
\n-
514 lower == nullptr ? 0 : string_traits<TYPE>::size_buffer(*lower) - 1},
\n-
515 usz{upper == nullptr ? 0 : string_traits<TYPE>::size_buffer(*upper) - 1};
\n-
516
\n-
517 if (value.empty())
\n-
518 return std::size(s_empty) + 1;
\n-
519 else
\n-
520 return 1 + lsz + 1 + usz + 2;
\n-
521 }
\n-
\n-
522
\n-
523private:
\n-
524 static constexpr zview s_empty{"empty"_zv};
\n-
525 static constexpr auto s_overrun{"Not enough space in buffer for range."_zv};
\n-
526
\n-
528 static std::string err_bad_input(std::string_view text)
\n-
529 {
\n-
530 return internal::concat("Invalid range input: '", text, "'");
\n-
531 }
\n-
532};
\n-
\n-
533
\n-
534
\n-
\n-
536template<typename TYPE> struct nullness<range<TYPE>> : no_null<range<TYPE>>
\n-
537{};
\n+
445 template<typename... TYPE>
\n+
\n+
446 [[nodiscard]] std::optional<std::tuple<TYPE...>> query01(zview query)
\n+
447 {
\n+
448 result res{exec(query)};
\n+
449 auto const rows{std::size(res)};
\n+
450 switch (rows)
\n+
451 {
\n+
452 case 0: return {};
\n+
453 case 1: return {res[0].as<TYPE...>()};
\n+
454 default:
\n+
455 throw unexpected_rows{internal::concat(
\n+
456 "Expected at most one row of data, got "sv, rows, "."sv)};
\n+
457 }
\n+
458 }
\n
\n-
538} // namespace pqxx
\n-
539#endif
\n+
459
\n+
461
\n+
505 template<typename... TYPE>
\n+
\n+
506 [[nodiscard]] auto stream(std::string_view query) &
\n+
507 {
\n+
508 return pqxx::internal::stream_query<TYPE...>{*this, query};
\n+
509 }
\n+
\n+
510
\n+
511 // C++20: Concept like std::invocable, but without specifying param types.
\n+
513
\n+
537 template<typename CALLABLE>
\n+
\n+
538 auto for_stream(std::string_view query, CALLABLE &&func)
\n+
539 {
\n+
540 using param_types =
\n+\n+
542 param_types const *const sample{nullptr};
\n+
543 auto data_stream{stream_like(query, sample)};
\n+
544 for (auto const &fields : data_stream) std::apply(func, fields);
\n+
545 }
\n+
\n+
546
\n+
547 template<typename CALLABLE>
\n+
548 [[deprecated(
\n+
549 "pqxx::transaction_base::for_each is now called for_stream.")]] auto
\n+
\n+
550 for_each(std::string_view query, CALLABLE &&func)
\n+
551 {
\n+
552 return for_stream(query, std::forward<CALLABLE>(func));
\n+
553 }
\n+
\n+
554
\n+
556
\n+
\n+
587 template<typename... TYPE> auto query(zview query)
\n+
588 {
\n+
589 return exec(query).iter<TYPE...>();
\n+
590 }
\n+
\n+
591
\n+
593
\n+
\n+
601 template<typename... TYPE> auto query_n(result::size_type rows, zview query)
\n+
602 {
\n+
603 return exec_n(rows, query).iter<TYPE...>();
\n+
604 }
\n+
\n+
605
\n+
606 // C++20: Concept like std::invocable, but without specifying param types.
\n+
608
\n+
\n+
616 template<typename CALLABLE> void for_query(zview query, CALLABLE &&func)
\n+
617 {
\n+
618 exec(query).for_each(std::forward<CALLABLE>(func));
\n+
619 }
\n+
\n+
620
\n+
\n+
651 template<typename... Args> result exec_params(zview query, Args &&...args)
\n+
652 {
\n+
653 params pp(args...);
\n+
654 return internal_exec_params(query, pp.make_c_params());
\n+
655 }
\n+
\n+
656
\n+
657 // Execute parameterised statement, expect a single-row result.
\n+
\n+
660 template<typename... Args> row exec_params1(zview query, Args &&...args)
\n+
661 {
\n+
662 return exec_params_n(1, query, std::forward<Args>(args)...).front();
\n+
663 }
\n+
\n+
664
\n+
665 // Execute parameterised statement, expect a result with zero rows.
\n+
\n+
668 template<typename... Args> result exec_params0(zview query, Args &&...args)
\n+
669 {
\n+
670 return exec_params_n(0, query, std::forward<Args>(args)...);
\n+
671 }
\n+
\n+
672
\n+
673 // Execute parameterised statement, expect exactly a given number of rows.
\n+
676 template<typename... Args>
\n+
\n+
677 result exec_params_n(std::size_t rows, zview query, Args &&...args)
\n+
678 {
\n+
679 auto const r{exec_params(query, std::forward<Args>(args)...)};
\n+
680 check_rowcount_params(rows, std::size(r));
\n+
681 return r;
\n+
682 }
\n+
\n+
684
\n+
727
\n+
729 template<typename... Args>
\n+
\n+
730 result exec_prepared(zview statement, Args &&...args)
\n+
731 {
\n+
732 params pp(args...);
\n+
733 return internal_exec_prepared(statement, pp.make_c_params());
\n+
734 }
\n+
\n+
735
\n+
737
\n+
739 template<typename... Args>
\n+
\n+
740 row exec_prepared1(zview statement, Args &&...args)
\n+
741 {
\n+
742 return exec_prepared_n(1, statement, std::forward<Args>(args)...).front();
\n+
743 }
\n+
\n+
744
\n+
746
\n+
748 template<typename... Args>
\n+
\n+
749 result exec_prepared0(zview statement, Args &&...args)
\n+
750 {
\n+
751 return exec_prepared_n(0, statement, std::forward<Args>(args)...);
\n+
752 }
\n+
\n+
753
\n+
755
\n+
758 template<typename... Args>
\n+
759 result
\n+
\n+
760 exec_prepared_n(result::size_type rows, zview statement, Args &&...args)
\n+
761 {
\n+
762 auto const r{exec_prepared(statement, std::forward<Args>(args)...)};
\n+
763 check_rowcount_prepared(statement, rows, std::size(r));
\n+
764 return r;
\n+
765 }
\n+
\n+
766
\n+
768
\n+
774 void process_notice(char const msg[]) const { m_conn.process_notice(msg); }
\n+
776 void process_notice(zview msg) const { m_conn.process_notice(msg); }
\n+
778
\n+
780 [[nodiscard]] constexpr connection &conn() const noexcept { return m_conn; }
\n+
781
\n+
783
\n+
798 [[deprecated(
\n+
799 "Set transaction-local variables using SQL SET statements.")]] void
\n+
800 set_variable(std::string_view var, std::string_view value);
\n+
801
\n+
803
\n+
806 [[deprecated("Read variables using SQL SHOW statements.")]] std::string
\n+
807 get_variable(std::string_view);
\n+
808
\n+
809 // C++20: constexpr.
\n+
811 [[nodiscard]] std::string_view name() const &noexcept { return m_name; }
\n+
812
\n+
813protected:
\n+
815
\n+
\n+\n+
819 connection &c, std::string_view tname,
\n+
820 std::shared_ptr<std::string> rollback_cmd) :
\n+
821 m_conn{c}, m_name{tname}, m_rollback_cmd{rollback_cmd}
\n+
822 {}
\n+
\n+
823
\n+
825
\n+
830 transaction_base(connection &c, std::string_view tname);
\n+
831
\n+
833 explicit transaction_base(connection &c);
\n+
834
\n+
836 void register_transaction();
\n+
837
\n+
839 void close() noexcept;
\n+
840
\n+
842 virtual void do_commit() = 0;
\n+
843
\n+
845
\n+
848 virtual void do_abort();
\n+
849
\n+
\n+
851 void set_rollback_cmd(std::shared_ptr<std::string> cmd)
\n+
852 {
\n+
853 m_rollback_cmd = cmd;
\n+
854 }
\n+
\n+
855
\n+
857 result direct_exec(std::string_view, std::string_view desc = ""sv);
\n+
858 result
\n+
859 direct_exec(std::shared_ptr<std::string>, std::string_view desc = ""sv);
\n+
860
\n+
861private:
\n+
862 enum class status
\n+
863 {
\n+
864 active,
\n+
865 aborted,
\n+
866 committed,
\n+
867 in_doubt
\n+
868 };
\n+
869
\n+
870 PQXX_PRIVATE void check_pending_error();
\n+
871
\n+
872 result
\n+
873 internal_exec_prepared(zview statement, internal::c_params const &args);
\n+
874
\n+
875 result internal_exec_params(zview query, internal::c_params const &args);
\n+
876
\n+
878 void check_rowcount_prepared(
\n+
879 zview statement, result::size_type expected_rows,
\n+
880 result::size_type actual_rows);
\n+
881
\n+
883 void
\n+
884 check_rowcount_params(std::size_t expected_rows, std::size_t actual_rows);
\n+
885
\n+
887 [[nodiscard]] std::string description() const;
\n+
888
\n+
889 friend class pqxx::internal::gate::transaction_transaction_focus;
\n+
890 PQXX_PRIVATE void register_focus(transaction_focus *);
\n+
891 PQXX_PRIVATE void unregister_focus(transaction_focus *) noexcept;
\n+
892 PQXX_PRIVATE void register_pending_error(zview) noexcept;
\n+
893 PQXX_PRIVATE void register_pending_error(std::string &&) noexcept;
\n+
894
\n+
896 template<typename... ARGS>
\n+
897 auto stream_like(std::string_view query, std::tuple<ARGS...> const *)
\n+
898 {
\n+
899 return stream<ARGS...>(query);
\n+
900 }
\n+
901
\n+
902 connection &m_conn;
\n+
903
\n+
905
\n+
908 transaction_focus const *m_focus = nullptr;
\n+
909
\n+
910 status m_status = status::active;
\n+
911 bool m_registered = false;
\n+
912 std::string m_name;
\n+
913 std::string m_pending_error;
\n+
914
\n+
916 std::shared_ptr<std::string> m_rollback_cmd;
\n+
917
\n+
918 static constexpr std::string_view s_type_name{"transaction"sv};
\n+
919};
\n+
\n+
920
\n+
921
\n+
922// C++20: Can borrowed_range help?
\n+
924template<>
\n+
925std::string_view transaction_base::query_value<std::string_view>(
\n+
926 zview query, std::string_view desc) = delete;
\n+
928template<>
\n+
929zview transaction_base::query_value<zview>(
\n+
930 zview query, std::string_view desc) = delete;
\n+
931
\n+
932} // namespace pqxx
\n+
933
\n+
934
\n+
935namespace pqxx::internal
\n+
936{
\n+
938template<pqxx::isolation_level isolation, pqxx::write_policy rw>
\n+
939extern const zview begin_cmd;
\n+
940
\n+
941// These are not static members, so "constexpr" does not imply "inline".
\n+
942template<>
\n+
943inline constexpr zview begin_cmd<read_committed, write_policy::read_write>{
\n+
944 "BEGIN"_zv};
\n+
945template<>
\n+
946inline constexpr zview begin_cmd<read_committed, write_policy::read_only>{
\n+
947 "BEGIN READ ONLY"_zv};
\n+
948template<>
\n+
949inline constexpr zview begin_cmd<repeatable_read, write_policy::read_write>{
\n+
950 "BEGIN ISOLATION LEVEL REPEATABLE READ"_zv};
\n+
951template<>
\n+
952inline constexpr zview begin_cmd<repeatable_read, write_policy::read_only>{
\n+
953 "BEGIN ISOLATION LEVEL REPEATABLE READ READ ONLY"_zv};
\n+
954template<>
\n+
955inline constexpr zview begin_cmd<serializable, write_policy::read_write>{
\n+
956 "BEGIN ISOLATION LEVEL SERIALIZABLE"_zv};
\n+
957template<>
\n+
958inline constexpr zview begin_cmd<serializable, write_policy::read_only>{
\n+
959 "BEGIN ISOLATION LEVEL SERIALIZABLE READ ONLY"_zv};
\n+
960} // namespace pqxx::internal
\n+
961
\n+
962#include "pqxx/internal/stream_query_impl.hxx"
\n+
963#endif
\n+
auto esc(ARGS &&...args) const
Escape string for use as SQL string literal in this transaction.
Definition transaction_base.hxx:131
\n
The home of all libpqxx classes, functions, templates, etc.
Definition array.hxx:33
\n+
std::basic_string_view< std::byte > binary_cast(TYPE const &data)
Cast binary data to a type that libpqxx will recognise as binary.
Definition util.hxx:303
\n \n-
Invalid argument passed to libpqxx, similar to std::invalid_argument.
Definition except.hxx:266
\n-
Value conversion failed, e.g. when converting "Hello" to int.
Definition except.hxx:283
\n-
Could not convert value to string: not enough buffer space.
Definition except.hxx:313
\n-
Something is out of range, similar to std::out_of_range.
Definition except.hxx:326
\n-
An unlimited boundary value to a pqxx::range.
Definition range.hxx:24
\n-
constexpr bool extends_down_to(TYPE const &) const noexcept
Definition range.hxx:26
\n-
constexpr bool extends_up_to(TYPE const &) const noexcept
Definition range.hxx:31
\n-
An inclusive boundary value to a pqxx::range.
Definition range.hxx:43
\n-
constexpr inclusive_bound(TYPE const &value)
Definition range.hxx:50
\n-
constexpr bool extends_down_to(TYPE const &value) const noexcept(noexcept(value< m_value))
Would this bound, as a lower bound, include value?
Definition range.hxx:59
\n-\n-
constexpr TYPE const & get() const &noexcept
Definition range.hxx:56
\n-
constexpr bool extends_up_to(TYPE const &value) const noexcept(noexcept(value< m_value))
Would this bound, as an upper bound, include value?
Definition range.hxx:66
\n-
An exclusive boundary value to a pqxx::range.
Definition range.hxx:79
\n-
constexpr bool extends_up_to(TYPE const &value) const noexcept(noexcept(value< m_value))
Would this bound, as an upper bound, include value?
Definition range.hxx:102
\n-\n-
constexpr exclusive_bound(TYPE const &value)
Definition range.hxx:86
\n-
constexpr TYPE const & get() const &noexcept
Definition range.hxx:92
\n-
constexpr bool extends_down_to(TYPE const &value) const noexcept(noexcept(m_value< value))
Would this bound, as a lower bound, include value?
Definition range.hxx:95
\n-
A range boundary value.
Definition range.hxx:115
\n-
constexpr bool extends_up_to(TYPE const &value) const
Would this bound, as an upper bound, include value?
Definition range.hxx:189
\n-
constexpr range_bound(range_bound const &) noexcept(noexcept(inclusive_bound< TYPE >{ std::declval< inclusive_bound< TYPE > const & >()}) and noexcept(exclusive_bound< TYPE >{ std::declval< exclusive_bound< TYPE > const & >()}))=default
\n-
constexpr bool is_exclusive() const noexcept
Is this boundary an exclusive one?
Definition range.hxx:174
\n-
constexpr range_bound(inclusive_bound< TYPE > const &bound) noexcept(noexcept(inclusive_bound< TYPE >{bound}))
Definition range.hxx:124
\n-
constexpr bool is_limited() const noexcept
Is this a finite bound?
Definition range.hxx:162
\n-
constexpr TYPE const * value() const &noexcept
Return bound value, or nullptr if it's not limited.
Definition range.hxx:198
\n-
constexpr bool operator!=(range_bound const &rhs) const noexcept(noexcept(*this==rhs))
Definition range.hxx:153
\n-
constexpr bool extends_down_to(TYPE const &value) const
Would this bound, as a lower bound, include value?
Definition range.hxx:180
\n-
range_bound()=delete
\n-
constexpr range_bound(no_bound) noexcept
Definition range.hxx:122
\n-
range_bound & operator=(range_bound const &)=default
\n-
constexpr bool operator==(range_bound const &rhs) const noexcept(noexcept(*this->value()== *rhs.value()))
Definition range.hxx:142
\n-
constexpr range_bound(exclusive_bound< TYPE > const &bound) noexcept(noexcept(exclusive_bound{bound}))
Definition range.hxx:129
\n-
constexpr bool is_inclusive() const noexcept
Is this boundary an inclusive one?
Definition range.hxx:168
\n-
range_bound & operator=(range_bound &&)=default
\n-
constexpr range_bound(range_bound &&)=default
\n-
A C++ equivalent to PostgreSQL's range types.
Definition range.hxx:234
\n-
constexpr range operator&(range const &other) const
Intersection of two ranges.
Definition range.hxx:334
\n-
constexpr bool operator==(range const &rhs) const noexcept(noexcept(this->lower_bound()==rhs.lower_bound()) and noexcept(this->upper_bound()==rhs.upper_bound()) and noexcept(this->empty()))
Definition range.hxx:265
\n-
constexpr bool contains(TYPE value) const noexcept(noexcept(m_lower.extends_down_to(value)) and noexcept(m_upper.extends_up_to(value)))
Does this range encompass value?
Definition range.hxx:304
\n-
constexpr bool contains(range< TYPE > const &other) const noexcept(noexcept((*this &other)==other))
Does this range encompass all of other?
Definition range.hxx:314
\n-
constexpr bool operator!=(range const &rhs) const noexcept(noexcept(*this==rhs))
Definition range.hxx:274
\n-
range(range &&)=default
\n-
range(range const &)=default
\n-
range & operator=(range &&)=default
\n-
range & operator=(range const &)=default
\n-
constexpr range(range_bound< TYPE > lower, range_bound< TYPE > upper)
Create a range.
Definition range.hxx:245
\n-
constexpr range_bound< TYPE > const & upper_bound() const &noexcept
Definition range.hxx:326
\n-
constexpr bool empty() const noexcept(noexcept(m_lower.is_exclusive()) and noexcept(m_lower.is_limited()) and noexcept(*m_lower.value()< *m_upper.value()))
Is this range clearly empty?
Definition range.hxx:294
\n-
constexpr range_bound< TYPE > const & lower_bound() const &noexcept
Definition range.hxx:321
\n-
constexpr range() noexcept(noexcept(exclusive_bound< TYPE >{TYPE{}}))
Create an empty range.
Definition range.hxx:260
\n-
static constexpr std::size_t size_buffer(range< TYPE > const &value) noexcept
Definition range.hxx:509
\n-
static char * into_buf(char *begin, char *end, range< TYPE > const &value)
Definition range.hxx:404
\n-
static zview to_buf(char *begin, char *end, range< TYPE > const &value)
Definition range.hxx:398
\n-
static range< TYPE > from_string(std::string_view text)
Definition range.hxx:439
\n-
Traits describing a type's "null value," if any.
Definition strconv.hxx:93
\n-
Nullness traits describing a type which does not have a null value.
Definition strconv.hxx:115
\n-
Traits class for use in string conversions.
Definition strconv.hxx:155
\n+
Internal items for libpqxx' own use. Do not use these yourself.
Definition composite.hxx:84
\n+
decltype(strip_types(std::declval< TYPES... >())) strip_types_t
Take a tuple type and apply strip_t to its component types.
Definition util.hxx:527
\n+
Definition connection.hxx:112
\n+
Binary data corresponding to PostgreSQL's "BYTEA" binary-string type.
Definition binarystring.hxx:59
\n+
std::basic_string_view< std::byte > bytes_view() const
Read data as a std::basic_string_view<std::byte>.
Definition binarystring.hxx:178
\n+
Connection to a database.
Definition connection.hxx:253
\n+
Error in usage of libpqxx library, similar to std::logic_error.
Definition except.hxx:249
\n+
Query returned an unexpected number of rows.
Definition except.hxx:343
\n+
Build a parameter list for a parameterised or prepared statement.
Definition params.hxx:220
\n+
pqxx::internal::c_params make_c_params() const
For internal use: Generate a params object for use in calls.
Definition params.cxx:96
\n+
Result set containing data returned by a query or command.
Definition result.hxx:73
\n+
result_size_type size_type
Definition result.hxx:75
\n+
Reference to one row in a result.
Definition row.hxx:47
\n+
reference front() const noexcept
Definition row.cxx:60
\n+
Interface definition (and common code) for "transaction" classes.
Definition transaction_base.hxx:88
\n+
result exec_prepared(zview statement, Args &&...args)
Execute a prepared statement, with optional arguments.
Definition transaction_base.hxx:730
\n+
std::basic_string< std::byte > unesc_bin(zview text)
Unescape binary data, e.g. from a table field or notification payload.
Definition transaction_base.hxx:169
\n+
result exec0(zview query, std::string_view desc)
Execute command, which should return zero rows of data.
Definition transaction_base.hxx:329
\n+
constexpr connection & conn() const noexcept
The connection in which this transaction lives.
Definition transaction_base.hxx:780
\n+
auto for_each(std::string_view query, CALLABLE &&func)
Definition transaction_base.hxx:550
\n+
auto query(zview query)
Execute query, read full results, then iterate rows of data.
Definition transaction_base.hxx:587
\n+
void process_notice(zview msg) const
Have connection process a warning message.
Definition transaction_base.hxx:776
\n+
result exec0(zview query)
Execute command, which should return zero rows of data.
Definition transaction_base.hxx:342
\n+
auto query_n(result::size_type rows, zview query)
Perform query, expect given number of rows, iterate results.
Definition transaction_base.hxx:601
\n+
std::string unesc_raw(char const *text) const
Unescape binary data, e.g. from a table field or notification payload.
Definition transaction_base.hxx:179
\n+
TYPE query_value(zview query, std::string_view desc)
Perform query, expecting exactly 1 row with 1 field, and convert it.
Definition transaction_base.hxx:396
\n+
result exec_prepared_n(result::size_type rows, zview statement, Args &&...args)
Execute a prepared statement, expect a result with given number of rows.
Definition transaction_base.hxx:760
\n+
transaction_base(transaction_base const &)=delete
\n+
transaction_base(connection &c, std::string_view tname, std::shared_ptr< std::string > rollback_cmd)
Create a transaction (to be called by implementation classes only).
Definition transaction_base.hxx:818
\n+
std::string quote(T const &t) const
Represent object as SQL string, including quoting & escaping.
Definition transaction_base.hxx:197
\n+
row exec_params1(zview query, Args &&...args)
Definition transaction_base.hxx:660
\n+
TYPE query_value(zview query)
Perform query, expecting exactly 1 row with 1 field, and convert it.
Definition transaction_base.hxx:414
\n+
transaction_base & operator=(transaction_base const &)=delete
\n+
auto esc_raw(ARGS &&...args) const
Escape binary data for use as SQL string literal in this transaction.
Definition transaction_base.hxx:148
\n+
result exec(std::stringstream const &query, std::string_view desc)
Execute a command.
Definition transaction_base.hxx:315
\n+
std::string quote(binarystring const &t) const
Definition transaction_base.hxx:204
\n+
row exec1(zview query)
Execute command returning a single row of data.
Definition transaction_base.hxx:366
\n+
row exec1(zview query, std::string_view desc)
Execute command returning a single row of data.
Definition transaction_base.hxx:352
\n+
transaction_base(transaction_base &&)=delete
\n+
result exec_params(zview query, Args &&...args)
Execute an SQL statement with parameters.
Definition transaction_base.hxx:651
\n+
std::optional< std::tuple< TYPE... > > query01(zview query)
Query at most one row of data, and if there is one, convert it.
Definition transaction_base.hxx:446
\n+\n+
result exec_params0(zview query, Args &&...args)
Definition transaction_base.hxx:668
\n+
auto for_stream(std::string_view query, CALLABLE &&func)
Perform a streaming query, and for each result row, call func.
Definition transaction_base.hxx:538
\n+
std::string unesc_raw(zview text) const
Unescape binary data, e.g. from a table field or notification payload.
Definition transaction_base.hxx:158
\n+
result exec_prepared0(zview statement, Args &&...args)
Execute a prepared statement, and expect a result with zero rows.
Definition transaction_base.hxx:749
\n+
std::string esc_like(std::string_view bin, char escape_char='\\\\') const
Escape string for literal LIKE match.
Definition transaction_base.hxx:238
\n+
std::basic_string< std::byte > unesc_bin(char const text[])
Unescape binary data, e.g. from a table field or notification payload.
Definition transaction_base.hxx:190
\n+
transaction_base & operator=(transaction_base &&)=delete
\n+
result exec_n(result::size_type rows, zview query)
Execute command, expect given number of rows.
Definition transaction_base.hxx:383
\n+
std::tuple< TYPE... > query1(zview query)
Perform query returning exactly one row, and convert its fields.
Definition transaction_base.hxx:432
\n+
result exec(std::string_view query)
Execute a command.
Definition transaction_base.hxx:300
\n+
row exec_prepared1(zview statement, Args &&...args)
Execute a prepared statement, and expect a single-row result.
Definition transaction_base.hxx:740
\n+
std::string quote_name(std::string_view identifier) const
Escape an SQL identifier for use in a query.
Definition transaction_base.hxx:231
\n+
std::string quote_raw(unsigned char const bin[], std::size_t len) const
Binary-escape and quote a binary string for use as an SQL constant.
Definition transaction_base.hxx:211
\n+
std::string_view name() const &noexcept
Transaction name, if you passed one to the constructor; or empty string.
Definition transaction_base.hxx:811
\n+
result exec_params_n(std::size_t rows, zview query, Args &&...args)
Definition transaction_base.hxx:677
\n+
auto stream(std::string_view query) &
Execute a query, and loop over the results row by row.
Definition transaction_base.hxx:506
\n+
void for_query(zview query, CALLABLE &&func)
Execute a query, load the full result, and perform func for each row.
Definition transaction_base.hxx:616
\n+
void process_notice(char const msg[]) const
Have connection process a warning message.
Definition transaction_base.hxx:774
\n+
Base class for things that monopolise a transaction's attention.
Definition transaction_focus.hxx:29
\n
Marker-type wrapper: zero-terminated std::string_view.
Definition zview.hxx:38
\n
\n
\n \n
\n \n
\n \n \n", "details": [{"source1": "html2text {}", "source2": "html2text {}", "unified_diff": "@@ -1,695 +1,761 @@\n \n \n \n \n \n libpqxx\u00a07.8.1\n \n-range.hxx\n- 1#ifndef PQXX_H_RANGE\n- 2#define PQXX_H_RANGE\n- 3\n- 4#if !defined(PQXX_HEADER_PRE)\n- 5# error \"Include libpqxx headers as , not .\"\n- 6#endif\n- 7\n- 8#include \n- 9#include \n- 10\n- 11#include \"pqxx/internal/array-composite.hxx\"\n- 12#include \"pqxx/internal/concat.hxx\"\n- 13\n- 14namespace pqxx\n- 15{\n- 17\n-23struct no_bound\n- 24{\n- 25 template\n-26 constexpr bool extends_down_to(TYPE const &) const noexcept\n- 27 {\n- 28 return true;\n- 29 }\n- 30 template\n-31 constexpr bool extends_up_to(TYPE const &) const noexcept\n- 32 {\n- 33 return true;\n- 34 }\n- 35};\n- 36\n- 37\n- 39\n-42template class inclusive_bound\n- 43{\n- 44 // (Putting private section first to work around bug in gcc < 10: see\n-#665.)\n- 45private:\n- 46 TYPE m_value;\n- 47\n- 48public:\n-49 inclusive_bound() = delete;\n-50 constexpr explicit inclusive_bound(TYPE const &value) : m_value{value}\n- 51 {\n- 52 if (is_null(value))\n- 53 throw argument_error{\"Got null value as an inclusive range bound.\"};\n- 54 }\n- 55\n-56 [[nodiscard]] constexpr TYPE const &get() const &noexcept { return m_value;\n-}\n+transaction_base.hxx\n+ 1/* Common code and definitions for the transaction classes.\n+ 2 *\n+ 3 * pqxx::transaction_base defines the interface for any abstract class that\n+ 4 * represents a database transaction.\n+ 5 *\n+ 6 * DO NOT INCLUDE THIS FILE DIRECTLY; include pqxx/transaction_base instead.\n+ 7 *\n+ 8 * Copyright (c) 2000-2023, Jeroen T. Vermeulen.\n+ 9 *\n+ 10 * See COPYING for copyright license. If you did not receive a file called\n+ 11 * COPYING with this source code, please notify the distributor of this\n+ 12 * mistake, or contact the author.\n+ 13 */\n+ 14#ifndef PQXX_H_TRANSACTION_BASE\n+ 15#define PQXX_H_TRANSACTION_BASE\n+ 16\n+ 17#if !defined(PQXX_HEADER_PRE)\n+ 18# error \"Include libpqxx headers as , not .\"\n+ 19#endif\n+ 20\n+ 21#include \n+ 22\n+ 23/* End-user programs need not include this file, unless they define their\n+own\n+ 24 * transaction classes. This is not something the typical program should\n+want\n+ 25 * to do.\n+ 26 *\n+ 27 * However, reading this file is worthwhile because it defines the public\n+ 28 * interface for the available transaction classes such as transaction and\n+ 29 * nontransaction.\n+ 30 */\n+ 31\n+ 32#include \"pqxx/connection.hxx\"\n+ 33#include \"pqxx/internal/concat.hxx\"\n+ 34#include \"pqxx/internal/encoding_group.hxx\"\n+ 35#include \"pqxx/internal/stream_query.hxx\"\n+ 36#include \"pqxx/isolation.hxx\"\n+ 37#include \"pqxx/result.hxx\"\n+ 38#include \"pqxx/row.hxx\"\n+ 39#include \"pqxx/util.hxx\"\n+ 40\n+ 41namespace pqxx::internal::gate\n+ 42{\n+ 43class transaction_subtransaction;\n+ 44class transaction_sql_cursor;\n+ 45class transaction_stream_to;\n+ 46class transaction_transaction_focus;\n+ 47} // namespace pqxx::internal::gate\n+ 48\n+ 49\n+ 50namespace pqxx\n+ 51{\n+ 52using namespace std::literals;\n+ 53\n+ 54\n+ 55class transaction_focus;\n+ 56\n 57\n-59 [[nodiscard]] constexpr bool extends_down_to(TYPE const &value) const\n- 60 noexcept(noexcept(value < m_value))\n- 61 {\n- 62 return not(value < m_value);\n- 63 }\n- 64\n-66 [[nodiscard]] constexpr bool extends_up_to(TYPE const &value) const\n- 67 noexcept(noexcept(value < m_value))\n- 68 {\n- 69 return not(m_value < value);\n- 70 }\n- 71};\n- 72\n- 73\n- 75\n-78template class exclusive_bound\n- 79{\n- 80 // (Putting private section first to work around bug in gcc < 10: see\n-#665.)\n- 81private:\n- 82 TYPE m_value;\n- 83\n- 84public:\n-85 exclusive_bound() = delete;\n-86 constexpr explicit exclusive_bound(TYPE const &value) : m_value{value}\n- 87 {\n- 88 if (is_null(value))\n- 89 throw argument_error{\"Got null value as an exclusive range bound.\"};\n- 90 }\n- 91\n-92 [[nodiscard]] constexpr TYPE const &get() const &noexcept { return m_value;\n-}\n- 93\n-95 [[nodiscard]] constexpr bool extends_down_to(TYPE const &value) const\n- 96 noexcept(noexcept(m_value < value))\n- 97 {\n- 98 return m_value < value;\n- 99 }\n- 100\n-102 [[nodiscard]] constexpr bool extends_up_to(TYPE const &value) const\n- 103 noexcept(noexcept(value < m_value))\n- 104 {\n- 105 return value < m_value;\n- 106 }\n- 107};\n- 108\n- 109\n- 111\n-114template class range_bound\n- 115{\n- 116 // (Putting private section first to work around bug in gcc < 10: see\n-#665.)\n- 117private:\n- 118 std::variant, exclusive_bound>\n-m_bound;\n+ 82\n+87class PQXX_LIBEXPORT PQXX_NOVTABLE transaction_base\n+ 88{\n+ 89public:\n+90 transaction_base() = delete;\n+91 transaction_base(transaction_base const &) = delete;\n+92 transaction_base(transaction_base &&) = delete;\n+93 transaction_base &operator=(transaction_base const &) = delete;\n+94 transaction_base &operator=(transaction_base &&) = delete;\n+ 95\n+ 96 virtual ~transaction_base() = 0;\n+ 97\n+ 99\n+ 112 void commit();\n+ 113\n+ 115\n+ 118 void abort();\n 119\n- 120public:\n-121 range_bound() = delete;\n-122 constexpr range_bound(no_bound) noexcept : m_bound{} {}\n- 123\n-124 constexpr range_bound(inclusive_bound const &bound) noexcept(\n- 125 noexcept(inclusive_bound{bound})) :\n- 126 m_bound{bound}\n- 127 {}\n- 128\n-129 constexpr range_bound(exclusive_bound const &bound) noexcept(\n- 130 noexcept(exclusive_bound{bound})) :\n- 131 m_bound{bound}\n- 132 {}\n- 133\n-134 constexpr range_bound(range_bound const &) noexcept(\n- 135 noexcept(inclusive_bound{\n- 136 std::declval const &>()})\n- 137 and noexcept(exclusive_bound{\n- 138 std::declval const &>()})) = default;\n- 139\n-140 constexpr range_bound(range_bound &&) = default;\n- 141\n-142 constexpr bool operator==(range_bound const &rhs) const\n- 143 noexcept(noexcept(*this->value() == *rhs.value()))\n- 144 {\n- 145 if (this->is_limited())\n- 146 return (\n- 147 rhs.is_limited() and (this->is_inclusive() == rhs.is_inclusive()) and\n- 148 (*this->value() == *rhs.value()));\n- 149 else\n- 150 return not rhs.is_limited();\n+131 template [[nodiscard]] auto esc(ARGS &&...args) const\n+ 132 {\n+ 133 return conn().esc(std::forward(args)...);\n+ 134 }\n+ 135\n+ 137\n+148 template [[nodiscard]] auto esc_raw(ARGS &&...args) const\n+ 149 {\n+ 150 return conn().esc_raw(std::forward(args)...);\n 151 }\n 152\n-153 constexpr bool operator!=(range_bound const &rhs) const\n- 154 noexcept(noexcept(*this == rhs))\n- 155 {\n- 156 return not(*this == rhs);\n- 157 }\n-158 range_bound &operator=(range_bound const &) = default;\n-159 range_bound &operator=(range_bound &&) = default;\n- 160\n-162 constexpr bool is_limited() const noexcept\n- 163 {\n- 164 return not std::holds_alternative(m_bound);\n- 165 }\n+ 154\n+ 157 [[nodiscard, deprecated(\"Use unesc_bin() instead.\")]] std::string\n+158 unesc_raw(zview text) const\n+ 159 {\n+ 160#include \"pqxx/internal/ignore-deprecated-pre.hxx\"\n+ 161 return conn().unesc_raw(text);\n+ 162#include \"pqxx/internal/ignore-deprecated-post.hxx\"\n+ 163 }\n+ 164\n 166\n-168 constexpr bool is_inclusive() const noexcept\n- 169 {\n- 170 return std::holds_alternative>(m_bound);\n- 171 }\n- 172\n-174 constexpr bool is_exclusive() const noexcept\n- 175 {\n- 176 return std::holds_alternative>(m_bound);\n- 177 }\n- 178\n-180 constexpr bool extends_down_to(TYPE const &value) const\n- 181 {\n- 182 return std::visit(\n- 183 [&value](auto const &bound) noexcept(noexcept(bound.extends_down_to(\n- 184 value))) { return bound.extends_down_to(value); },\n- 185 m_bound);\n- 186 }\n+169 [[nodiscard]] std::basic_string unesc_bin(zview text)\n+ 170 {\n+ 171 return conn().unesc_bin(text);\n+ 172 }\n+ 173\n+ 175\n+ 178 [[nodiscard, deprecated(\"Use unesc_bin() instead.\")]] std::string\n+179 unesc_raw(char const *text) const\n+ 180 {\n+ 181#include \"pqxx/internal/ignore-deprecated-pre.hxx\"\n+ 182 return conn().unesc_raw(text);\n+ 183#include \"pqxx/internal/ignore-deprecated-post.hxx\"\n+ 184 }\n+ 185\n 187\n-189 constexpr bool extends_up_to(TYPE const &value) const\n- 190 {\n- 191 return std::visit(\n- 192 [&value](auto const &bound) noexcept(noexcept(\n- 193 bound.extends_up_to(value))) { return bound.extends_up_to(value); },\n- 194 m_bound);\n- 195 }\n+190 [[nodiscard]] std::basic_string unesc_bin(char const text[])\n+ 191 {\n+ 192 return conn().unesc_bin(text);\n+ 193 }\n+ 194\n 196\n-198 [[nodiscard]] constexpr TYPE const *value() const &noexcept\n- 199 {\n- 200 return std::visit(\n- 201 [](auto const &bound) noexcept {\n- 202 using bound_t = std::decay_t;\n- 203 if constexpr (std::is_same_v)\n- 204 return static_cast(nullptr);\n- 205 else\n- 206 return &bound.get();\n- 207 },\n- 208 m_bound);\n- 209 }\n- 210};\n- 211\n- 212\n- 213// C++20: Concepts for comparisons, construction, etc.\n+197 template [[nodiscard]] std::string quote(T const &t) const\n+ 198 {\n+ 199 return conn().quote(t);\n+ 200 }\n+ 201\n+ 202 [[deprecated(\n+ 203 \"Use std::basic_string instead of binarystring.\")]] std::string\n+204 quote(binarystring const &t) const\n+ 205 {\n+ 206 return conn().quote(t.bytes_view());\n+ 207 }\n+ 208\n+ 210 [[deprecated(\"Use quote(std::basic_string_view).\")]] std::\n+string\n+211 quote_raw(unsigned char const bin[], std::size_t len) const\n+ 212 {\n+ 213 return quote(binary_cast(bin, len));\n+ 214 }\n 215\n-233template class range\n- 234{\n- 235 // (Putting private section first to work around bug in gcc < 10: see\n-#665.)\n- 236private:\n- 237 range_bound m_lower, m_upper;\n- 238\n- 239public:\n- 241\n-245 constexpr range(range_bound lower, range_bound upper) :\n- 246 m_lower{lower}, m_upper{upper}\n- 247 {\n- 248 if (\n- 249 lower.is_limited() and upper.is_limited() and\n- 250 (*upper.value() < *lower.value()))\n- 251 throw range_error{internal::concat(\n- 252 \"Range's lower bound (\", *lower.value(),\n- 253 \") is greater than its upper bound (\", *upper.value(), \").\")};\n- 254 }\n- 255\n- 257\n-260 constexpr range() noexcept(noexcept(exclusive_bound{TYPE{}})) :\n- 261 m_lower{exclusive_bound{TYPE{}}},\n- 262 m_upper{exclusive_bound{TYPE{}}}\n- 263 {}\n- 264\n-265 constexpr bool operator==(range const &rhs) const\n- 266 noexcept(noexcept(this->lower_bound() == rhs.lower_bound()) and noexcept(\n- 267 this->upper_bound() == rhs.upper_bound()) and noexcept(this->empty()))\n- 268 {\n- 269 return (this->lower_bound() == rhs.lower_bound() and\n- 270 this->upper_bound() == rhs.upper_bound()) or\n- 271 (this->empty() and rhs.empty());\n- 272 }\n- 273\n-274 constexpr bool operator!=(range const &rhs) const\n- 275 noexcept(noexcept(*this == rhs))\n- 276 {\n- 277 return not(*this == rhs);\n- 278 }\n- 279\n-280 range(range const &) = default;\n-281 range(range &&) = default;\n-282 range &operator=(range const &) = default;\n-283 range &operator=(range &&) = default;\n- 284\n- 286\n-294 constexpr bool empty() const\n- 295 noexcept(noexcept(m_lower.is_exclusive()) and noexcept(\n- 296 m_lower.is_limited()) and noexcept(*m_lower.value() < *m_upper.value()))\n- 297 {\n- 298 return (m_lower.is_exclusive() or m_upper.is_exclusive()) and\n- 299 m_lower.is_limited() and m_upper.is_limited() and\n- 300 not(*m_lower.value() < *m_upper.value());\n- 301 }\n- 302\n-304 constexpr bool contains(TYPE value) const noexcept(noexcept(\n- 305 m_lower.extends_down_to(value)) and noexcept(m_upper.extends_up_to\n-(value)))\n- 306 {\n- 307 return m_lower.extends_down_to(value) and m_upper.extends_up_to(value);\n- 308 }\n- 309\n- 311\n-314 constexpr bool contains(range const &other) const\n- 315 noexcept(noexcept((*this & other) == other))\n+ 217 [[deprecated(\"Use quote(std::basic_string_view).\")]] std::\n+string\n+ 218 quote_raw(zview bin) const;\n+ 219\n+ 220#if defined(PQXX_HAVE_CONCEPTS)\n+ 222\n+ 223 template\n+ 224 [[nodiscard]] std::string quote_raw(DATA const &data) const\n+ 225 {\n+ 226 return conn().quote_raw(data);\n+ 227 }\n+ 228#endif\n+ 229\n+231 [[nodiscard]] std::string quote_name(std::string_view identifier) const\n+ 232 {\n+ 233 return conn().quote_name(identifier);\n+ 234 }\n+ 235\n+ 237 [[nodiscard]] std::string\n+238 esc_like(std::string_view bin, char escape_char = '\\\\') const\n+ 239 {\n+ 240 return conn().esc_like(bin, escape_char);\n+ 241 }\n+ 243\n+ 285\n+ 287\n+ 292 [[deprecated(\"The desc parameter is going away.\")]] result\n+ 293 exec(std::string_view query, std::string_view desc);\n+ 294\n+ 296\n+300 result exec(std::string_view query)\n+ 301 {\n+ 302#include \"pqxx/internal/ignore-deprecated-pre.hxx\"\n+ 303 return exec(query, std::string_view{});\n+ 304#include \"pqxx/internal/ignore-deprecated-post.hxx\"\n+ 305 }\n+ 306\n+ 308\n+ 313 [[deprecated(\n+ 314 \"Pass your query as a std::string_view, not stringstream.\")]] result\n+315 exec(std::stringstream const &query, std::string_view desc)\n 316 {\n- 317 return (*this & other) == other;\n- 318 }\n- 319\n- 320 [[nodiscard]] constexpr range_bound const &\n-321 lower_bound() const &noexcept\n- 322 {\n- 323 return m_lower;\n- 324 }\n- 325 [[nodiscard]] constexpr range_bound const &\n-326 upper_bound() const &noexcept\n- 327 {\n- 328 return m_upper;\n- 329 }\n- 330\n- 332\n-334 constexpr range operator&(range const &other) const\n- 335 {\n- 336 range_bound lower{no_bound{}};\n- 337 if (not this->lower_bound().is_limited())\n- 338 lower = other.lower_bound();\n- 339 else if (not other.lower_bound().is_limited())\n- 340 lower = this->lower_bound();\n- 341 else if (*this->lower_bound().value() < *other.lower_bound().value())\n- 342 lower = other.lower_bound();\n- 343 else if (*other.lower_bound().value() < *this->lower_bound().value())\n- 344 lower = this->lower_bound();\n- 345 else if (this->lower_bound().is_exclusive())\n- 346 lower = this->lower_bound();\n- 347 else\n- 348 lower = other.lower_bound();\n- 349\n- 350 range_bound upper{no_bound{}};\n- 351 if (not this->upper_bound().is_limited())\n- 352 upper = other.upper_bound();\n- 353 else if (not other.upper_bound().is_limited())\n- 354 upper = this->upper_bound();\n- 355 else if (*other.upper_bound().value() < *this->upper_bound().value())\n- 356 upper = other.upper_bound();\n- 357 else if (*this->upper_bound().value() < *other.upper_bound().value())\n- 358 upper = this->upper_bound();\n- 359 else if (this->upper_bound().is_exclusive())\n- 360 upper = this->upper_bound();\n- 361 else\n- 362 upper = other.upper_bound();\n- 363\n- 364 if (\n- 365 lower.is_limited() and upper.is_limited() and\n- 366 (*upper.value() < *lower.value()))\n- 367 return {};\n- 368 else\n- 369 return {lower, upper};\n- 370 }\n- 371\n-373 template operator range() const\n- 374 {\n- 375 range_bound lower{no_bound{}}, upper{no_bound{}};\n- 376 if (lower_bound().is_inclusive())\n- 377 lower = inclusive_bound{*lower_bound().value()};\n- 378 else if (lower_bound().is_exclusive())\n- 379 lower = exclusive_bound{*lower_bound().value()};\n- 380\n- 381 if (upper_bound().is_inclusive())\n- 382 upper = inclusive_bound{*upper_bound().value()};\n- 383 else if (upper_bound().is_exclusive())\n- 384 upper = exclusive_bound{*upper_bound().value()};\n- 385\n- 386 return {lower, upper};\n- 387 }\n- 388};\n+ 317#include \"pqxx/internal/ignore-deprecated-pre.hxx\"\n+ 318 return exec(query.str(), desc);\n+ 319#include \"pqxx/internal/ignore-deprecated-post.hxx\"\n+ 320 }\n+ 321\n+ 323\n+ 328 [[deprecated(\"The desc parameter is going away.\")]] result\n+329 exec0(zview query, std::string_view desc)\n+ 330 {\n+ 331#include \"pqxx/internal/ignore-deprecated-pre.hxx\"\n+ 332 return exec_n(0, query, desc);\n+ 333#include \"pqxx/internal/ignore-deprecated-post.hxx\"\n+ 334 }\n+ 335\n+ 337\n+342 result exec0(zview query) { return exec_n(0, query); }\n+ 343\n+ 345\n+ 351 [[deprecated(\"The desc parameter is going away.\")]] row\n+352 exec1(zview query, std::string_view desc)\n+ 353 {\n+ 354#include \"pqxx/internal/ignore-deprecated-pre.hxx\"\n+ 355 return exec_n(1, query, desc).front();\n+ 356#include \"pqxx/internal/ignore-deprecated-post.hxx\"\n+ 357 }\n+ 358\n+ 360\n+366 row exec1(zview query) { return exec_n(1, query).front(); }\n+ 367\n+ 369\n+ 374 [[deprecated(\"The desc parameter is going away.\")]] result\n+ 375 exec_n(result::size_type rows, zview query, std::string_view desc);\n+ 376\n+ 378\n+383 result exec_n(result::size_type rows, zview query)\n+ 384 {\n+ 385#include \"pqxx/internal/ignore-deprecated-pre.hxx\"\n+ 386 return exec_n(rows, query, std::string_view{});\n+ 387#include \"pqxx/internal/ignore-deprecated-post.hxx\"\n+ 388 }\n 389\n- 390\n- 392\n-395template struct string_traits>\n- 396{\n- 397 [[nodiscard]] static inline zview\n-398 to_buf(char *begin, char *end, range const &value)\n- 399 {\n- 400 return generic_to_buf(begin, end, value);\n- 401 }\n- 402\n- 403 static inline char *\n-404 into_buf(char *begin, char *end, range const &value)\n- 405 {\n- 406 if (value.empty())\n- 407 {\n- 408 if ((end - begin) <= internal::ssize(s_empty))\n- 409 throw conversion_overrun{s_overrun.c_str()};\n- 410 char *here = begin + s_empty.copy(begin, std::size(s_empty));\n- 411 *here++ = '\\0';\n- 412 return here;\n- 413 }\n- 414 else\n+ 391\n+ 394 template\n+ 395 [[deprecated(\"The desc parameter is going away.\")]] TYPE\n+396 query_value(zview query, std::string_view desc)\n+ 397 {\n+ 398#include \"pqxx/internal/ignore-deprecated-pre.hxx\"\n+ 399 row const r{exec1(query, desc)};\n+ 400#include \"pqxx/internal/ignore-deprecated-post.hxx\"\n+ 401 if (std::size(r) != 1)\n+ 402 throw usage_error{internal::concat(\n+ 403 \"Queried single value from result with \", std::size(r), \" columns.\")};\n+ 404 return r[0].as();\n+ 405 }\n+ 406\n+ 408\n+414 template TYPE query_value(zview query)\n 415 {\n- 416 if (end - begin < 4)\n- 417 throw conversion_overrun{s_overrun.c_str()};\n- 418 char *here = begin;\n- 419 *here++ =\n- 420 (static_cast(value.lower_bound().is_inclusive() ? '[' : '('));\n- 421 TYPE const *lower{value.lower_bound().value()};\n- 422 // Convert bound (but go back to overwrite that trailing zero).\n- 423 if (lower != nullptr)\n- 424 here = string_traits::into_buf(here, end, *lower) - 1;\n- 425 *here++ = ',';\n- 426 TYPE const *upper{value.upper_bound().value()};\n- 427 // Convert bound (but go back to overwrite that trailing zero).\n- 428 if (upper != nullptr)\n- 429 here = string_traits::into_buf(here, end, *upper) - 1;\n- 430 if ((end - here) < 2)\n- 431 throw conversion_overrun{s_overrun.c_str()};\n- 432 *here++ =\n- 433 static_cast(value.upper_bound().is_inclusive() ? ']' : ')');\n- 434 *here++ = '\\0';\n- 435 return here;\n- 436 }\n- 437 }\n+ 416 row const r{exec1(query)};\n+ 417 if (std::size(r) != 1)\n+ 418 throw usage_error{internal::concat(\n+ 419 \"Queried single value from result with \", std::size(r), \" columns.\")};\n+ 420 return r[0].as();\n+ 421 }\n+ 422\n+ 424\n+ 431 template\n+432 [[nodiscard]] std::tuple query1(zview query)\n+ 433 {\n+ 434 return exec1(query).as();\n+ 435 }\n+ 436\n 438\n-439 [[nodiscard]] static inline range from_string(std::string_view text)\n- 440 {\n- 441 if (std::size(text) < 3)\n- 442 throw pqxx::conversion_error{err_bad_input(text)};\n- 443 bool left_inc{false};\n- 444 switch (text[0])\n- 445 {\n- 446 case '[': left_inc = true; break;\n- 447\n- 448 case '(': break;\n- 449\n- 450 case 'e':\n- 451 case 'E':\n- 452 if (\n- 453 (std::size(text) != std::size(s_empty)) or\n- 454 (text[1] != 'm' and text[1] != 'M') or\n- 455 (text[2] != 'p' and text[2] != 'P') or\n- 456 (text[3] != 't' and text[3] != 'T') or\n- 457 (text[4] != 'y' and text[4] != 'Y'))\n- 458 throw pqxx::conversion_error{err_bad_input(text)};\n- 459 return {};\n- 460 break;\n+ 445 template\n+446 [[nodiscard]] std::optional> query01(zview query)\n+ 447 {\n+ 448 result res{exec(query)};\n+ 449 auto const rows{std::size(res)};\n+ 450 switch (rows)\n+ 451 {\n+ 452 case 0: return {};\n+ 453 case 1: return {res[0].as()};\n+ 454 default:\n+ 455 throw unexpected_rows{internal::concat(\n+ 456 \"Expected at most one row of data, got \"sv, rows, \".\"sv)};\n+ 457 }\n+ 458 }\n+ 459\n 461\n- 462 default: throw pqxx::conversion_error{err_bad_input(text)};\n- 463 }\n- 464\n- 465 // The field parser uses this to track which field it's parsing, and\n- 466 // when not to expect a field separator.\n- 467 std::size_t index{0};\n- 468 // The last field we expect to see.\n- 469 static constexpr std::size_t last{1};\n- 470 // Current parsing position. We skip the opening parenthesis or bracket.\n- 471 std::size_t pos{1};\n- 472 // The string may leave out either bound to indicate that it's unlimited.\n- 473 std::optional lower, upper;\n- 474 // We reuse the same field parser we use for composite values and arrays.\n- 475 auto const field_parser{\n- 476 pqxx::internal::specialize_parse_composite_field>(\n- 477 pqxx::internal::encoding_group::UTF8)};\n- 478 field_parser(index, text, pos, lower, last);\n- 479 field_parser(index, text, pos, upper, last);\n- 480\n- 481 // We need one more character: the closing parenthesis or bracket.\n- 482 if (pos != std::size(text))\n- 483 throw pqxx::conversion_error{err_bad_input(text)};\n- 484 char const closing{text[pos - 1]};\n- 485 if (closing != ')' and closing != ']')\n- 486 throw pqxx::conversion_error{err_bad_input(text)};\n- 487 bool const right_inc{closing == ']'};\n- 488\n- 489 range_bound lower_bound{no_bound{}}, upper_bound{no_bound{}};\n- 490 if (lower)\n- 491 {\n- 492 if (left_inc)\n- 493 lower_bound = inclusive_bound{*lower};\n- 494 else\n- 495 lower_bound = exclusive_bound{*lower};\n- 496 }\n- 497 if (upper)\n- 498 {\n- 499 if (right_inc)\n- 500 upper_bound = inclusive_bound{*upper};\n- 501 else\n- 502 upper_bound = exclusive_bound{*upper};\n- 503 }\n- 504\n- 505 return {lower_bound, upper_bound};\n- 506 }\n- 507\n- 508 [[nodiscard]] static inline constexpr std::size_t\n-509 size_buffer(range const &value) noexcept\n- 510 {\n- 511 TYPE const *lower{value.lower_bound().value()},\n- 512 *upper{value.upper_bound().value()};\n- 513 std::size_t const lsz{\n- 514 lower == nullptr ? 0 : string_traits::size_buffer(*lower) - 1},\n- 515 usz{upper == nullptr ? 0 : string_traits::size_buffer(*upper) - 1};\n- 516\n- 517 if (value.empty())\n- 518 return std::size(s_empty) + 1;\n- 519 else\n- 520 return 1 + lsz + 1 + usz + 2;\n- 521 }\n- 522\n- 523private:\n- 524 static constexpr zview s_empty{\"empty\"_zv};\n- 525 static constexpr auto s_overrun{\"Not enough space in buffer for\n-range.\"_zv};\n- 526\n- 528 static std::string err_bad_input(std::string_view text)\n- 529 {\n- 530 return internal::concat(\"Invalid range input: '\", text, \"'\");\n- 531 }\n- 532};\n- 533\n- 534\n-536template struct nullness> : no_null>\n- 537{};\n- 538} // namespace pqxx\n- 539#endif\n+ 505 template\n+506 [[nodiscard]] auto stream(std::string_view query) &\n+ 507 {\n+ 508 return pqxx::internal::stream_query{*this, query};\n+ 509 }\n+ 510\n+ 511 // C++20: Concept like std::invocable, but without specifying param types.\n+ 513\n+ 537 template\n+538 auto for_stream(std::string_view query, CALLABLE &&func)\n+ 539 {\n+ 540 using param_types =\n+ 541 pqxx::internal::strip_types_t>;\n+ 542 param_types const *const sample{nullptr};\n+ 543 auto data_stream{stream_like(query, sample)};\n+ 544 for (auto const &fields : data_stream) std::apply(func, fields);\n+ 545 }\n+ 546\n+ 547 template\n+ 548 [[deprecated(\n+ 549 \"pqxx::transaction_base::for_each is now called for_stream.\")]] auto\n+550 for_each(std::string_view query, CALLABLE &&func)\n+ 551 {\n+ 552 return for_stream(query, std::forward(func));\n+ 553 }\n+ 554\n+ 556\n+587 template auto query(zview query)\n+ 588 {\n+ 589 return exec(query).iter();\n+ 590 }\n+ 591\n+ 593\n+601 template auto query_n(result::size_type rows, zview\n+query)\n+ 602 {\n+ 603 return exec_n(rows, query).iter();\n+ 604 }\n+ 605\n+ 606 // C++20: Concept like std::invocable, but without specifying param types.\n+ 608\n+616 template void for_query(zview query, CALLABLE &&func)\n+ 617 {\n+ 618 exec(query).for_each(std::forward(func));\n+ 619 }\n+ 620\n+651 template result exec_params(zview query, Args &&...args)\n+ 652 {\n+ 653 params pp(args...);\n+ 654 return internal_exec_params(query, pp.make_c_params());\n+ 655 }\n+ 656\n+ 657 // Execute parameterised statement, expect a single-row result.\n+660 template row exec_params1(zview query, Args &&...args)\n+ 661 {\n+ 662 return exec_params_n(1, query, std::forward(args)...).front();\n+ 663 }\n+ 664\n+ 665 // Execute parameterised statement, expect a result with zero rows.\n+668 template result exec_params0(zview query, Args &&...args)\n+ 669 {\n+ 670 return exec_params_n(0, query, std::forward(args)...);\n+ 671 }\n+ 672\n+ 673 // Execute parameterised statement, expect exactly a given number of rows.\n+ 676 template\n+677 result exec_params_n(std::size_t rows, zview query, Args &&...args)\n+ 678 {\n+ 679 auto const r{exec_params(query, std::forward(args)...)};\n+ 680 check_rowcount_params(rows, std::size(r));\n+ 681 return r;\n+ 682 }\n+ 684\n+ 727\n+ 729 template\n+730 result exec_prepared(zview statement, Args &&...args)\n+ 731 {\n+ 732 params pp(args...);\n+ 733 return internal_exec_prepared(statement, pp.make_c_params());\n+ 734 }\n+ 735\n+ 737\n+ 739 template\n+740 row exec_prepared1(zview statement, Args &&...args)\n+ 741 {\n+ 742 return exec_prepared_n(1, statement, std::forward(args)...).front();\n+ 743 }\n+ 744\n+ 746\n+ 748 template\n+749 result exec_prepared0(zview statement, Args &&...args)\n+ 750 {\n+ 751 return exec_prepared_n(0, statement, std::forward(args)...);\n+ 752 }\n+ 753\n+ 755\n+ 758 template\n+ 759 result\n+760 exec_prepared_n(result::size_type rows, zview statement, Args &&...args)\n+ 761 {\n+ 762 auto const r{exec_prepared(statement, std::forward(args)...)};\n+ 763 check_rowcount_prepared(statement, rows, std::size(r));\n+ 764 return r;\n+ 765 }\n+ 766\n+ 768\n+774 void process_notice(char const msg[]) const { m_conn.process_notice(msg); }\n+776 void process_notice(zview msg) const { m_conn.process_notice(msg); }\n+ 778\n+780 [[nodiscard]] constexpr connection &conn() const noexcept { return m_conn;\n+}\n+ 781\n+ 783\n+ 798 [[deprecated(\n+ 799 \"Set transaction-local variables using SQL SET statements.\")]] void\n+ 800 set_variable(std::string_view var, std::string_view value);\n+ 801\n+ 803\n+ 806 [[deprecated(\"Read variables using SQL SHOW statements.\")]] std::string\n+ 807 get_variable(std::string_view);\n+ 808\n+ 809 // C++20: constexpr.\n+811 [[nodiscard]] std::string_view name() const &noexcept { return m_name; }\n+ 812\n+ 813protected:\n+ 815\n+818 transaction_base(\n+ 819 connection &c, std::string_view tname,\n+ 820 std::shared_ptr rollback_cmd) :\n+ 821 m_conn{c}, m_name{tname}, m_rollback_cmd{rollback_cmd}\n+ 822 {}\n+ 823\n+ 825\n+ 830 transaction_base(connection &c, std::string_view tname);\n+ 831\n+ 833 explicit transaction_base(connection &c);\n+ 834\n+ 836 void register_transaction();\n+ 837\n+ 839 void close() noexcept;\n+ 840\n+842 virtual void do_commit() = 0;\n+ 843\n+ 845\n+ 848 virtual void do_abort();\n+ 849\n+851 void set_rollback_cmd(std::shared_ptr cmd)\n+ 852 {\n+ 853 m_rollback_cmd = cmd;\n+ 854 }\n+ 855\n+ 857 result direct_exec(std::string_view, std::string_view desc = \"\"sv);\n+ 858 result\n+ 859 direct_exec(std::shared_ptr, std::string_view desc = \"\"sv);\n+ 860\n+ 861private:\n+ 862 enum class status\n+ 863 {\n+ 864 active,\n+ 865 aborted,\n+ 866 committed,\n+ 867 in_doubt\n+ 868 };\n+ 869\n+ 870 PQXX_PRIVATE void check_pending_error();\n+ 871\n+ 872 result\n+ 873 internal_exec_prepared(zview statement, internal::c_params const &args);\n+ 874\n+ 875 result internal_exec_params(zview query, internal::c_params const &args);\n+ 876\n+ 878 void check_rowcount_prepared(\n+ 879 zview statement, result::size_type expected_rows,\n+ 880 result::size_type actual_rows);\n+ 881\n+ 883 void\n+ 884 check_rowcount_params(std::size_t expected_rows, std::size_t actual_rows);\n+ 885\n+ 887 [[nodiscard]] std::string description() const;\n+ 888\n+889 friend class pqxx::internal::gate::transaction_transaction_focus;\n+ 890 PQXX_PRIVATE void register_focus(transaction_focus *);\n+ 891 PQXX_PRIVATE void unregister_focus(transaction_focus *) noexcept;\n+ 892 PQXX_PRIVATE void register_pending_error(zview) noexcept;\n+ 893 PQXX_PRIVATE void register_pending_error(std::string &&) noexcept;\n+ 894\n+ 896 template\n+ 897 auto stream_like(std::string_view query, std::tuple const *)\n+ 898 {\n+ 899 return stream(query);\n+ 900 }\n+ 901\n+ 902 connection &m_conn;\n+ 903\n+ 905\n+ 908 transaction_focus const *m_focus = nullptr;\n+ 909\n+ 910 status m_status = status::active;\n+ 911 bool m_registered = false;\n+ 912 std::string m_name;\n+ 913 std::string m_pending_error;\n+ 914\n+ 916 std::shared_ptr m_rollback_cmd;\n+ 917\n+ 918 static constexpr std::string_view s_type_name{\"transaction\"sv};\n+ 919};\n+ 920\n+ 921\n+ 922// C++20: Can borrowed_range help?\n+ 924template<>\n+925std::string_view transaction_base::query_value(\n+ 926 zview query, std::string_view desc) = delete;\n+ 928template<>\n+929zview transaction_base::query_value(\n+ 930 zview query, std::string_view desc) = delete;\n+ 931\n+ 932} // namespace pqxx\n+ 933\n+ 934\n+ 935namespace pqxx::internal\n+ 936{\n+ 938template\n+ 939extern const zview begin_cmd;\n+ 940\n+ 941// These are not static members, so \"constexpr\" does not imply \"inline\".\n+ 942template<>\n+ 943inline constexpr zview begin_cmd{\n+ 944 \"BEGIN\"_zv};\n+ 945template<>\n+ 946inline constexpr zview begin_cmd{\n+ 947 \"BEGIN READ ONLY\"_zv};\n+ 948template<>\n+ 949inline constexpr zview begin_cmd\n+{\n+ 950 \"BEGIN ISOLATION LEVEL REPEATABLE READ\"_zv};\n+ 951template<>\n+ 952inline constexpr zview begin_cmd{\n+ 953 \"BEGIN ISOLATION LEVEL REPEATABLE READ READ ONLY\"_zv};\n+ 954template<>\n+ 955inline constexpr zview begin_cmd{\n+ 956 \"BEGIN ISOLATION LEVEL SERIALIZABLE\"_zv};\n+ 957template<>\n+ 958inline constexpr zview begin_cmd{\n+ 959 \"BEGIN ISOLATION LEVEL SERIALIZABLE READ ONLY\"_zv};\n+ 960} // namespace pqxx::internal\n+ 961\n+ 962#include \"pqxx/internal/stream_query_impl.hxx\"\n+ 963#endif\n+pqxx::transaction_base::esc\n+auto esc(ARGS &&...args) const\n+Escape string for use as SQL string literal in this transaction.\n+Definition transaction_base.hxx:131\n pqxx\n The home of all libpqxx classes, functions, templates, etc.\n Definition array.hxx:33\n+pqxx::binary_cast\n+std::basic_string_view< std::byte > binary_cast(TYPE const &data)\n+Cast binary data to a type that libpqxx will recognise as binary.\n+Definition util.hxx:303\n pqxx::format::text\n @ text\n-pqxx::argument_error\n-Invalid argument passed to libpqxx, similar to std::invalid_argument.\n-Definition except.hxx:266\n-pqxx::conversion_error\n-Value conversion failed, e.g. when converting \"Hello\" to int.\n-Definition except.hxx:283\n-pqxx::conversion_overrun\n-Could not convert value to string: not enough buffer space.\n-Definition except.hxx:313\n-pqxx::range_error\n-Something is out of range, similar to std::out_of_range.\n-Definition except.hxx:326\n-pqxx::no_bound\n-An unlimited boundary value to a pqxx::range.\n-Definition range.hxx:24\n-pqxx::no_bound::extends_down_to\n-constexpr bool extends_down_to(TYPE const &) const noexcept\n-Definition range.hxx:26\n-pqxx::no_bound::extends_up_to\n-constexpr bool extends_up_to(TYPE const &) const noexcept\n-Definition range.hxx:31\n-pqxx::inclusive_bound\n-An inclusive boundary value to a pqxx::range.\n-Definition range.hxx:43\n-pqxx::inclusive_bound::inclusive_bound\n-constexpr inclusive_bound(TYPE const &value)\n-Definition range.hxx:50\n-pqxx::inclusive_bound::extends_down_to\n-constexpr bool extends_down_to(TYPE const &value) const noexcept(noexcept\n-(value< m_value))\n-Would this bound, as a lower bound, include value?\n-Definition range.hxx:59\n-pqxx::inclusive_bound::inclusive_bound\n-inclusive_bound()=delete\n-pqxx::inclusive_bound::get\n-constexpr TYPE const & get() const &noexcept\n-Definition range.hxx:56\n-pqxx::inclusive_bound::extends_up_to\n-constexpr bool extends_up_to(TYPE const &value) const noexcept(noexcept(value<\n-m_value))\n-Would this bound, as an upper bound, include value?\n-Definition range.hxx:66\n-pqxx::exclusive_bound\n-An exclusive boundary value to a pqxx::range.\n-Definition range.hxx:79\n-pqxx::exclusive_bound::extends_up_to\n-constexpr bool extends_up_to(TYPE const &value) const noexcept(noexcept(value<\n-m_value))\n-Would this bound, as an upper bound, include value?\n-Definition range.hxx:102\n-pqxx::exclusive_bound::exclusive_bound\n-exclusive_bound()=delete\n-pqxx::exclusive_bound::exclusive_bound\n-constexpr exclusive_bound(TYPE const &value)\n-Definition range.hxx:86\n-pqxx::exclusive_bound::get\n-constexpr TYPE const & get() const &noexcept\n-Definition range.hxx:92\n-pqxx::exclusive_bound::extends_down_to\n-constexpr bool extends_down_to(TYPE const &value) const noexcept(noexcept\n-(m_value< value))\n-Would this bound, as a lower bound, include value?\n-Definition range.hxx:95\n-pqxx::range_bound\n-A range boundary value.\n-Definition range.hxx:115\n-pqxx::range_bound::extends_up_to\n-constexpr bool extends_up_to(TYPE const &value) const\n-Would this bound, as an upper bound, include value?\n-Definition range.hxx:189\n-pqxx::range_bound::range_bound\n-constexpr range_bound(range_bound const &) noexcept(noexcept(inclusive_bound<\n-TYPE >{ std::declval< inclusive_bound< TYPE > const & >()}) and noexcept\n-(exclusive_bound< TYPE >{ std::declval< exclusive_bound< TYPE > const & >\n-()}))=default\n-pqxx::range_bound::is_exclusive\n-constexpr bool is_exclusive() const noexcept\n-Is this boundary an exclusive one?\n-Definition range.hxx:174\n-pqxx::range_bound::range_bound\n-constexpr range_bound(inclusive_bound< TYPE > const &bound) noexcept(noexcept\n-(inclusive_bound< TYPE >{bound}))\n-Definition range.hxx:124\n-pqxx::range_bound::is_limited\n-constexpr bool is_limited() const noexcept\n-Is this a finite bound?\n-Definition range.hxx:162\n-pqxx::range_bound::value\n-constexpr TYPE const * value() const &noexcept\n-Return bound value, or nullptr if it's not limited.\n-Definition range.hxx:198\n-pqxx::range_bound::operator!=\n-constexpr bool operator!=(range_bound const &rhs) const noexcept(noexcept\n-(*this==rhs))\n-Definition range.hxx:153\n-pqxx::range_bound::extends_down_to\n-constexpr bool extends_down_to(TYPE const &value) const\n-Would this bound, as a lower bound, include value?\n-Definition range.hxx:180\n-pqxx::range_bound::range_bound\n-range_bound()=delete\n-pqxx::range_bound::range_bound\n-constexpr range_bound(no_bound) noexcept\n-Definition range.hxx:122\n-pqxx::range_bound::operator=\n-range_bound & operator=(range_bound const &)=default\n-pqxx::range_bound::operator==\n-constexpr bool operator==(range_bound const &rhs) const noexcept(noexcept\n-(*this->value()== *rhs.value()))\n-Definition range.hxx:142\n-pqxx::range_bound::range_bound\n-constexpr range_bound(exclusive_bound< TYPE > const &bound) noexcept(noexcept\n-(exclusive_bound{bound}))\n-Definition range.hxx:129\n-pqxx::range_bound::is_inclusive\n-constexpr bool is_inclusive() const noexcept\n-Is this boundary an inclusive one?\n-Definition range.hxx:168\n-pqxx::range_bound::operator=\n-range_bound & operator=(range_bound &&)=default\n-pqxx::range_bound::range_bound\n-constexpr range_bound(range_bound &&)=default\n-pqxx::range\n-A C++ equivalent to PostgreSQL's range types.\n-Definition range.hxx:234\n-pqxx::range::operator&\n-constexpr range operator&(range const &other) const\n-Intersection of two ranges.\n-Definition range.hxx:334\n-pqxx::range::operator==\n-constexpr bool operator==(range const &rhs) const noexcept(noexcept(this-\n->lower_bound()==rhs.lower_bound()) and noexcept(this->upper_bound\n-()==rhs.upper_bound()) and noexcept(this->empty()))\n-Definition range.hxx:265\n-pqxx::range::contains\n-constexpr bool contains(TYPE value) const noexcept(noexcept\n-(m_lower.extends_down_to(value)) and noexcept(m_upper.extends_up_to(value)))\n-Does this range encompass value?\n-Definition range.hxx:304\n-pqxx::range::contains\n-constexpr bool contains(range< TYPE > const &other) const noexcept(noexcept(\n-(*this &other)==other))\n-Does this range encompass all of other?\n-Definition range.hxx:314\n-pqxx::range::operator!=\n-constexpr bool operator!=(range const &rhs) const noexcept(noexcept\n-(*this==rhs))\n-Definition range.hxx:274\n-pqxx::range::range\n-range(range &&)=default\n-pqxx::range::range\n-range(range const &)=default\n-pqxx::range::operator=\n-range & operator=(range &&)=default\n-pqxx::range::operator=\n-range & operator=(range const &)=default\n-pqxx::range::range\n-constexpr range(range_bound< TYPE > lower, range_bound< TYPE > upper)\n-Create a range.\n-Definition range.hxx:245\n-pqxx::range::upper_bound\n-constexpr range_bound< TYPE > const & upper_bound() const &noexcept\n-Definition range.hxx:326\n-pqxx::range::empty\n-constexpr bool empty() const noexcept(noexcept(m_lower.is_exclusive()) and\n-noexcept(m_lower.is_limited()) and noexcept(*m_lower.value()< *m_upper.value\n-()))\n-Is this range clearly empty?\n-Definition range.hxx:294\n-pqxx::range::lower_bound\n-constexpr range_bound< TYPE > const & lower_bound() const &noexcept\n-Definition range.hxx:321\n-pqxx::range::range\n-constexpr range() noexcept(noexcept(exclusive_bound< TYPE >{TYPE{}}))\n-Create an empty range.\n-Definition range.hxx:260\n-pqxx::string_traits<_range<_TYPE_>_>::size_buffer\n-static constexpr std::size_t size_buffer(range< TYPE > const &value) noexcept\n-Definition range.hxx:509\n-pqxx::string_traits<_range<_TYPE_>_>::into_buf\n-static char * into_buf(char *begin, char *end, range< TYPE > const &value)\n-Definition range.hxx:404\n-pqxx::string_traits<_range<_TYPE_>_>::to_buf\n-static zview to_buf(char *begin, char *end, range< TYPE > const &value)\n-Definition range.hxx:398\n-pqxx::string_traits<_range<_TYPE_>_>::from_string\n-static range< TYPE > from_string(std::string_view text)\n-Definition range.hxx:439\n-pqxx::nullness\n-Traits describing a type's \"null value,\" if any.\n-Definition strconv.hxx:93\n-pqxx::no_null\n-Nullness traits describing a type which does not have a null value.\n-Definition strconv.hxx:115\n-pqxx::string_traits\n-Traits class for use in string conversions.\n-Definition strconv.hxx:155\n+pqxx::internal\n+Internal items for libpqxx' own use. Do not use these yourself.\n+Definition composite.hxx:84\n+pqxx::internal::strip_types_t\n+decltype(strip_types(std::declval< TYPES... >())) strip_types_t\n+Take a tuple type and apply strip_t to its component types.\n+Definition util.hxx:527\n+pqxx::internal::gate\n+Definition connection.hxx:112\n+pqxx::binarystring\n+Binary data corresponding to PostgreSQL's \"BYTEA\" binary-string type.\n+Definition binarystring.hxx:59\n+pqxx::binarystring::bytes_view\n+std::basic_string_view< std::byte > bytes_view() const\n+Read data as a std::basic_string_view.\n+Definition binarystring.hxx:178\n+pqxx::connection\n+Connection to a database.\n+Definition connection.hxx:253\n+pqxx::usage_error\n+Error in usage of libpqxx library, similar to std::logic_error.\n+Definition except.hxx:249\n+pqxx::unexpected_rows\n+Query returned an unexpected number of rows.\n+Definition except.hxx:343\n+pqxx::params\n+Build a parameter list for a parameterised or prepared statement.\n+Definition params.hxx:220\n+pqxx::params::make_c_params\n+pqxx::internal::c_params make_c_params() const\n+For internal use: Generate a params object for use in calls.\n+Definition params.cxx:96\n+pqxx::result\n+Result set containing data returned by a query or command.\n+Definition result.hxx:73\n+pqxx::result::size_type\n+result_size_type size_type\n+Definition result.hxx:75\n+pqxx::row\n+Reference to one row in a result.\n+Definition row.hxx:47\n+pqxx::row::front\n+reference front() const noexcept\n+Definition row.cxx:60\n+pqxx::transaction_base\n+Interface definition (and common code) for \"transaction\" classes.\n+Definition transaction_base.hxx:88\n+pqxx::transaction_base::exec_prepared\n+result exec_prepared(zview statement, Args &&...args)\n+Execute a prepared statement, with optional arguments.\n+Definition transaction_base.hxx:730\n+pqxx::transaction_base::unesc_bin\n+std::basic_string< std::byte > unesc_bin(zview text)\n+Unescape binary data, e.g. from a table field or notification payload.\n+Definition transaction_base.hxx:169\n+pqxx::transaction_base::exec0\n+result exec0(zview query, std::string_view desc)\n+Execute command, which should return zero rows of data.\n+Definition transaction_base.hxx:329\n+pqxx::transaction_base::conn\n+constexpr connection & conn() const noexcept\n+The connection in which this transaction lives.\n+Definition transaction_base.hxx:780\n+pqxx::transaction_base::for_each\n+auto for_each(std::string_view query, CALLABLE &&func)\n+Definition transaction_base.hxx:550\n+pqxx::transaction_base::query\n+auto query(zview query)\n+Execute query, read full results, then iterate rows of data.\n+Definition transaction_base.hxx:587\n+pqxx::transaction_base::process_notice\n+void process_notice(zview msg) const\n+Have connection process a warning message.\n+Definition transaction_base.hxx:776\n+pqxx::transaction_base::exec0\n+result exec0(zview query)\n+Execute command, which should return zero rows of data.\n+Definition transaction_base.hxx:342\n+pqxx::transaction_base::query_n\n+auto query_n(result::size_type rows, zview query)\n+Perform query, expect given number of rows, iterate results.\n+Definition transaction_base.hxx:601\n+pqxx::transaction_base::unesc_raw\n+std::string unesc_raw(char const *text) const\n+Unescape binary data, e.g. from a table field or notification payload.\n+Definition transaction_base.hxx:179\n+pqxx::transaction_base::query_value\n+TYPE query_value(zview query, std::string_view desc)\n+Perform query, expecting exactly 1 row with 1 field, and convert it.\n+Definition transaction_base.hxx:396\n+pqxx::transaction_base::exec_prepared_n\n+result exec_prepared_n(result::size_type rows, zview statement, Args &&...args)\n+Execute a prepared statement, expect a result with given number of rows.\n+Definition transaction_base.hxx:760\n+pqxx::transaction_base::transaction_base\n+transaction_base(transaction_base const &)=delete\n+pqxx::transaction_base::transaction_base\n+transaction_base(connection &c, std::string_view tname, std::shared_ptr< std::\n+string > rollback_cmd)\n+Create a transaction (to be called by implementation classes only).\n+Definition transaction_base.hxx:818\n+pqxx::transaction_base::quote\n+std::string quote(T const &t) const\n+Represent object as SQL string, including quoting & escaping.\n+Definition transaction_base.hxx:197\n+pqxx::transaction_base::exec_params1\n+row exec_params1(zview query, Args &&...args)\n+Definition transaction_base.hxx:660\n+pqxx::transaction_base::query_value\n+TYPE query_value(zview query)\n+Perform query, expecting exactly 1 row with 1 field, and convert it.\n+Definition transaction_base.hxx:414\n+pqxx::transaction_base::operator=\n+transaction_base & operator=(transaction_base const &)=delete\n+pqxx::transaction_base::esc_raw\n+auto esc_raw(ARGS &&...args) const\n+Escape binary data for use as SQL string literal in this transaction.\n+Definition transaction_base.hxx:148\n+pqxx::transaction_base::exec\n+result exec(std::stringstream const &query, std::string_view desc)\n+Execute a command.\n+Definition transaction_base.hxx:315\n+pqxx::transaction_base::quote\n+std::string quote(binarystring const &t) const\n+Definition transaction_base.hxx:204\n+pqxx::transaction_base::exec1\n+row exec1(zview query)\n+Execute command returning a single row of data.\n+Definition transaction_base.hxx:366\n+pqxx::transaction_base::exec1\n+row exec1(zview query, std::string_view desc)\n+Execute command returning a single row of data.\n+Definition transaction_base.hxx:352\n+pqxx::transaction_base::transaction_base\n+transaction_base(transaction_base &&)=delete\n+pqxx::transaction_base::exec_params\n+result exec_params(zview query, Args &&...args)\n+Execute an SQL statement with parameters.\n+Definition transaction_base.hxx:651\n+pqxx::transaction_base::query01\n+std::optional< std::tuple< TYPE... > > query01(zview query)\n+Query at most one row of data, and if there is one, convert it.\n+Definition transaction_base.hxx:446\n+pqxx::transaction_base::transaction_base\n+transaction_base()=delete\n+pqxx::transaction_base::exec_params0\n+result exec_params0(zview query, Args &&...args)\n+Definition transaction_base.hxx:668\n+pqxx::transaction_base::for_stream\n+auto for_stream(std::string_view query, CALLABLE &&func)\n+Perform a streaming query, and for each result row, call func.\n+Definition transaction_base.hxx:538\n+pqxx::transaction_base::unesc_raw\n+std::string unesc_raw(zview text) const\n+Unescape binary data, e.g. from a table field or notification payload.\n+Definition transaction_base.hxx:158\n+pqxx::transaction_base::exec_prepared0\n+result exec_prepared0(zview statement, Args &&...args)\n+Execute a prepared statement, and expect a result with zero rows.\n+Definition transaction_base.hxx:749\n+pqxx::transaction_base::esc_like\n+std::string esc_like(std::string_view bin, char escape_char='\\\\') const\n+Escape string for literal LIKE match.\n+Definition transaction_base.hxx:238\n+pqxx::transaction_base::unesc_bin\n+std::basic_string< std::byte > unesc_bin(char const text[])\n+Unescape binary data, e.g. from a table field or notification payload.\n+Definition transaction_base.hxx:190\n+pqxx::transaction_base::operator=\n+transaction_base & operator=(transaction_base &&)=delete\n+pqxx::transaction_base::exec_n\n+result exec_n(result::size_type rows, zview query)\n+Execute command, expect given number of rows.\n+Definition transaction_base.hxx:383\n+pqxx::transaction_base::query1\n+std::tuple< TYPE... > query1(zview query)\n+Perform query returning exactly one row, and convert its fields.\n+Definition transaction_base.hxx:432\n+pqxx::transaction_base::exec\n+result exec(std::string_view query)\n+Execute a command.\n+Definition transaction_base.hxx:300\n+pqxx::transaction_base::exec_prepared1\n+row exec_prepared1(zview statement, Args &&...args)\n+Execute a prepared statement, and expect a single-row result.\n+Definition transaction_base.hxx:740\n+pqxx::transaction_base::quote_name\n+std::string quote_name(std::string_view identifier) const\n+Escape an SQL identifier for use in a query.\n+Definition transaction_base.hxx:231\n+pqxx::transaction_base::quote_raw\n+std::string quote_raw(unsigned char const bin[], std::size_t len) const\n+Binary-escape and quote a binary string for use as an SQL constant.\n+Definition transaction_base.hxx:211\n+pqxx::transaction_base::name\n+std::string_view name() const &noexcept\n+Transaction name, if you passed one to the constructor; or empty string.\n+Definition transaction_base.hxx:811\n+pqxx::transaction_base::exec_params_n\n+result exec_params_n(std::size_t rows, zview query, Args &&...args)\n+Definition transaction_base.hxx:677\n+pqxx::transaction_base::stream\n+auto stream(std::string_view query) &\n+Execute a query, and loop over the results row by row.\n+Definition transaction_base.hxx:506\n+pqxx::transaction_base::for_query\n+void for_query(zview query, CALLABLE &&func)\n+Execute a query, load the full result, and perform func for each row.\n+Definition transaction_base.hxx:616\n+pqxx::transaction_base::process_notice\n+void process_notice(char const msg[]) const\n+Have connection process a warning message.\n+Definition transaction_base.hxx:774\n+pqxx::transaction_focus\n+Base class for things that monopolise a transaction's attention.\n+Definition transaction_focus.hxx:29\n pqxx::zview\n Marker-type wrapper: zero-terminated std::string_view.\n Definition zview.hxx:38\n * include\n * pqxx\n- * range.hxx\n+ * transaction_base.hxx\n * Generated by [doxygen] 1.9.8\n"}]}, {"source1": "./usr/share/doc/libpqxx-doc/html/a00044_source.html", "source2": "./usr/share/doc/libpqxx-doc/html/a00044_source.html", "unified_diff": "@@ -1,15 +1,15 @@\n \n \n \n \n \n \n \n-libpqxx: time.hxx Source File\n+libpqxx: config-internal-compiler.h Source File\n \n \n \n \n \n \n \n@@ -60,80 +60,29 @@\n \n
\n
\n-
time.hxx
\n+
config-internal-compiler.h
\n
\n
\n-
1
\n-
5#ifndef PQXX_H_TIME
\n-
6#define PQXX_H_TIME
\n-
7
\n-
8#if !defined(PQXX_HEADER_PRE)
\n-
9# error "Include libpqxx headers as <pqxx/header>, not <pqxx/header.hxx>."
\n-
10#endif
\n-
11
\n-
12#include <chrono>
\n-
13#include <cstdlib>
\n-
14
\n-
15#include "pqxx/internal/concat.hxx"
\n-
16#include "pqxx/strconv.hxx"
\n-
17
\n-
18
\n-
19#if defined(PQXX_HAVE_YEAR_MONTH_DAY)
\n-
20
\n-
21namespace pqxx
\n-
22{
\n-
23using namespace std::literals;
\n-
24
\n-
25template<>
\n-
26struct nullness<std::chrono::year_month_day>
\n-
27 : no_null<std::chrono::year_month_day>
\n-
28{};
\n-
29
\n-
30
\n-
32
\n-
60template<> struct PQXX_LIBEXPORT string_traits<std::chrono::year_month_day>
\n-
61{
\n-
62 [[nodiscard]] static zview
\n-
63 to_buf(char *begin, char *end, std::chrono::year_month_day const &value)
\n-
64 {
\n-
65 return generic_to_buf(begin, end, value);
\n-
66 }
\n-
67
\n-
68 static char *
\n-
69 into_buf(char *begin, char *end, std::chrono::year_month_day const &value);
\n-
70
\n-
71 [[nodiscard]] static std::chrono::year_month_day
\n-
72 from_string(std::string_view text);
\n-
73
\n-
74 [[nodiscard]] static std::size_t
\n-
75 size_buffer(std::chrono::year_month_day const &) noexcept
\n-
76 {
\n-
77 static_assert(int{(std::chrono::year::min)()} >= -99999);
\n-
78 static_assert(int{(std::chrono::year::max)()} <= 99999);
\n-
79 return 5 + 1 + 2 + 1 + 2 + std::size(s_bc) + 1;
\n-
80 }
\n-
81
\n-
82private:
\n-
84 static constexpr std::string_view s_bc{" BC"sv};
\n-
85};
\n-
86} // namespace pqxx
\n-
87#endif // PQXX_HAVE_YEAR_MONTH_DAY
\n-
88#endif
\n-
The home of all libpqxx classes, functions, templates, etc.
Definition array.hxx:33
\n-
T from_string(field const &value)
Convert a field's value to type T.
Definition field.hxx:520
\n-\n+
1/* Automatically generated from config.h: internal/compiler config. */
\n+
2
\n+
3#define PQXX_HAVE_CHARCONV_FLOAT 1
\n+
4#define PQXX_HAVE_CHARCONV_INT 1
\n+
5#define PQXX_HAVE_CXA_DEMANGLE 1
\n+
6#define PQXX_HAVE_POLL 1
\n+
7#define PQXX_HAVE_SLEEP_FOR 1
\n+
8#define PQXX_HAVE_THREAD_LOCAL 1
\n
\n
\n \n
\n \n
\n \n \n", "details": [{"source1": "html2text {}", "source2": "html2text {}", "unified_diff": "@@ -1,77 +1,20 @@\n \n \n \n \n \n libpqxx\u00a07.8.1\n \n-time.hxx\n- 1\n- 5#ifndef PQXX_H_TIME\n- 6#define PQXX_H_TIME\n- 7\n- 8#if !defined(PQXX_HEADER_PRE)\n- 9# error \"Include libpqxx headers as , not .\"\n- 10#endif\n- 11\n- 12#include \n- 13#include \n- 14\n- 15#include \"pqxx/internal/concat.hxx\"\n- 16#include \"pqxx/strconv.hxx\"\n- 17\n- 18\n- 19#if defined(PQXX_HAVE_YEAR_MONTH_DAY)\n- 20\n- 21namespace pqxx\n- 22{\n- 23using namespace std::literals;\n- 24\n- 25template<>\n- 26struct nullness\n- 27 : no_null\n- 28{};\n- 29\n- 30\n- 32\n- 60template<> struct PQXX_LIBEXPORT string_traits\n- 61{\n- 62 [[nodiscard]] static zview\n- 63 to_buf(char *begin, char *end, std::chrono::year_month_day const &value)\n- 64 {\n- 65 return generic_to_buf(begin, end, value);\n- 66 }\n- 67\n- 68 static char *\n- 69 into_buf(char *begin, char *end, std::chrono::year_month_day const &value);\n- 70\n- 71 [[nodiscard]] static std::chrono::year_month_day\n- 72 from_string(std::string_view text);\n- 73\n- 74 [[nodiscard]] static std::size_t\n- 75 size_buffer(std::chrono::year_month_day const &) noexcept\n- 76 {\n- 77 static_assert(int{(std::chrono::year::min)()} >= -99999);\n- 78 static_assert(int{(std::chrono::year::max)()} <= 99999);\n- 79 return 5 + 1 + 2 + 1 + 2 + std::size(s_bc) + 1;\n- 80 }\n- 81\n- 82private:\n- 84 static constexpr std::string_view s_bc{\" BC\"sv};\n- 85};\n- 86} // namespace pqxx\n- 87#endif // PQXX_HAVE_YEAR_MONTH_DAY\n- 88#endif\n-pqxx\n-The home of all libpqxx classes, functions, templates, etc.\n-Definition array.hxx:33\n-pqxx::from_string\n-T from_string(field const &value)\n-Convert a field's value to type T.\n-Definition field.hxx:520\n-pqxx::format::text\n-@ text\n+config-internal-compiler.h\n+ 1/* Automatically generated from config.h: internal/compiler config. */\n+ 2\n+ 3#define PQXX_HAVE_CHARCONV_FLOAT 1\n+ 4#define PQXX_HAVE_CHARCONV_INT 1\n+ 5#define PQXX_HAVE_CXA_DEMANGLE 1\n+ 6#define PQXX_HAVE_POLL 1\n+ 7#define PQXX_HAVE_SLEEP_FOR 1\n+ 8#define PQXX_HAVE_THREAD_LOCAL 1\n * include\n * pqxx\n- * time.hxx\n+ * config-internal-compiler.h\n * Generated by [doxygen] 1.9.8\n"}]}, {"source1": "./usr/share/doc/libpqxx-doc/html/a00047_source.html", "source2": "./usr/share/doc/libpqxx-doc/html/a00047_source.html", "unified_diff": "@@ -1,15 +1,15 @@\n \n \n \n \n \n \n \n-libpqxx: config-public-compiler.h Source File\n+libpqxx: except.hxx Source File\n \n \n \n \n \n \n \n@@ -60,27 +60,938 @@\n \n
\n
\n-
config-public-compiler.h
\n+
except.hxx
\n
\n
\n-
1/* Automatically generated from config.h: public/compiler config. */
\n-
2
\n-
3#define PQXX_HAVE_GCC_PURE 1
\n-
4#define PQXX_HAVE_GCC_VISIBILITY 1
\n-
5#define PQXX_HAVE_PATH 1
\n-
6#define PQXX_HAVE_STRERROR_R 1
\n+
1/* Definition of libpqxx exception classes.
\n+
2 *
\n+
3 * pqxx::sql_error, pqxx::broken_connection, pqxx::in_doubt_error, ...
\n+
4 *
\n+
5 * DO NOT INCLUDE THIS FILE DIRECTLY; include pqxx/except instead.
\n+
6 *
\n+
7 * Copyright (c) 2000-2023, Jeroen T. Vermeulen.
\n+
8 *
\n+
9 * See COPYING for copyright license. If you did not receive a file called
\n+
10 * COPYING with this source code, please notify the distributor of this
\n+
11 * mistake, or contact the author.
\n+
12 */
\n+
13#ifndef PQXX_H_EXCEPT
\n+
14#define PQXX_H_EXCEPT
\n+
15
\n+
16#if !defined(PQXX_HEADER_PRE)
\n+
17# error "Include libpqxx headers as <pqxx/header>, not <pqxx/header.hxx>."
\n+
18#endif
\n+
19
\n+
20#if pqxx_have_source_location
\n+
21# include <source_location>
\n+
22#endif
\n+
23
\n+
24#include <stdexcept>
\n+
25#include <string>
\n+
26
\n+
27
\n+
28namespace pqxx
\n+
29{
\n+
\n+
47struct PQXX_LIBEXPORT failure : std::runtime_error
\n+
48{
\n+
49#if pqxx_have_source_location
\n+
50 explicit failure(
\n+
51 std::string const &,
\n+
52 std::source_location = std::source_location::current());
\n+
53 std::source_location location;
\n+
54#else
\n+
55 explicit failure(std::string const &);
\n+
56#endif
\n+
57};
\n+
\n+
58
\n+
59
\n+
61
\n+
\n+
80struct PQXX_LIBEXPORT broken_connection : failure
\n+
81{
\n+\n+
83 explicit broken_connection(
\n+
84 std::string const &
\n+
85#if pqxx_have_source_location
\n+
86 ,
\n+
87 std::source_location = std::source_location::current()
\n+
88#endif
\n+
89 );
\n+
90};
\n+
\n+
91
\n+
92
\n+
94
\n+
\n+\n+
103{
\n+
104 explicit protocol_violation(
\n+
105 std::string const &
\n+
106#if pqxx_have_source_location
\n+
107 ,
\n+
108 std::source_location = std::source_location::current()
\n+
109#endif
\n+
110 );
\n+
111};
\n+
\n+
112
\n+
113
\n+
\n+
115struct PQXX_LIBEXPORT variable_set_to_null : failure
\n+
116{
\n+
117 explicit variable_set_to_null(
\n+
118 std::string const &
\n+
119#if pqxx_have_source_location
\n+
120 ,
\n+
121 std::source_location = std::source_location::current()
\n+
122#endif
\n+
123 );
\n+
124};
\n+
\n+
125
\n+
126
\n+
128
\n+
\n+
131class PQXX_LIBEXPORT sql_error : public failure
\n+
132{
\n+
134 std::string const m_query;
\n+
136 std::string const m_sqlstate;
\n+
137
\n+
138public:
\n+
139 explicit sql_error(
\n+
140 std::string const &whatarg = "", std::string const &Q = "",
\n+
141 char const sqlstate[] = nullptr
\n+
142#if pqxx_have_source_location
\n+
143 ,
\n+
144 std::source_location = std::source_location::current()
\n+
145#endif
\n+
146 );
\n+
147 virtual ~sql_error() noexcept override;
\n+
148
\n+
150 [[nodiscard]] PQXX_PURE std::string const &query() const noexcept;
\n+
151
\n+
153 [[nodiscard]] PQXX_PURE std::string const &sqlstate() const noexcept;
\n+
154};
\n+
\n+
155
\n+
156
\n+
158
\n+
\n+
164struct PQXX_LIBEXPORT in_doubt_error : failure
\n+
165{
\n+
166 explicit in_doubt_error(
\n+
167 std::string const &
\n+
168#if pqxx_have_source_location
\n+
169 ,
\n+
170 std::source_location = std::source_location::current()
\n+
171#endif
\n+
172 );
\n+
173};
\n+
\n+
174
\n+
175
\n+
\n+
177struct PQXX_LIBEXPORT transaction_rollback : sql_error
\n+
178{
\n+
179 explicit transaction_rollback(
\n+
180 std::string const &whatarg, std::string const &q = "",
\n+
181 char const sqlstate[] = nullptr
\n+
182#if pqxx_have_source_location
\n+
183 ,
\n+
184 std::source_location = std::source_location::current()
\n+
185#endif
\n+
186 );
\n+
187};
\n+
\n+
188
\n+
189
\n+
191
\n+
\n+\n+
200{
\n+
201 explicit serialization_failure(
\n+
202 std::string const &whatarg, std::string const &q,
\n+
203 char const sqlstate[] = nullptr
\n+
204#if pqxx_have_source_location
\n+
205 ,
\n+
206 std::source_location = std::source_location::current()
\n+
207#endif
\n+
208 );
\n+
209};
\n+
\n+
210
\n+
211
\n+
\n+\n+
214{
\n+\n+
216 std::string const &whatarg, std::string const &q,
\n+
217 char const sqlstate[] = nullptr
\n+
218#if pqxx_have_source_location
\n+
219 ,
\n+
220 std::source_location = std::source_location::current()
\n+
221#endif
\n+
222 );
\n+
223};
\n+
\n+
224
\n+
225
\n+
\n+\n+
228{
\n+
229 explicit deadlock_detected(
\n+
230 std::string const &whatarg, std::string const &q,
\n+
231 char const sqlstate[] = nullptr
\n+
232#if pqxx_have_source_location
\n+
233 ,
\n+
234 std::source_location = std::source_location::current()
\n+
235#endif
\n+
236 );
\n+
237};
\n+
\n+
238
\n+
239
\n+
\n+
241struct PQXX_LIBEXPORT internal_error : std::logic_error
\n+
242{
\n+
243 explicit internal_error(std::string const &);
\n+
244};
\n+
\n+
245
\n+
246
\n+
\n+
248struct PQXX_LIBEXPORT usage_error : std::logic_error
\n+
249{
\n+
250 explicit usage_error(
\n+
251 std::string const &
\n+
252#if pqxx_have_source_location
\n+
253 ,
\n+
254 std::source_location = std::source_location::current()
\n+
255#endif
\n+
256 );
\n+
257
\n+
258#if pqxx_have_source_location
\n+
259 std::source_location location;
\n+
260#endif
\n+
261};
\n+
\n+
262
\n+
263
\n+
\n+
265struct PQXX_LIBEXPORT argument_error : std::invalid_argument
\n+
266{
\n+
267 explicit argument_error(
\n+
268 std::string const &
\n+
269#if pqxx_have_source_location
\n+
270 ,
\n+
271 std::source_location = std::source_location::current()
\n+
272#endif
\n+
273 );
\n+
274
\n+
275#if pqxx_have_source_location
\n+
276 std::source_location location;
\n+
277#endif
\n+
278};
\n+
\n+
279
\n+
280
\n+
\n+
282struct PQXX_LIBEXPORT conversion_error : std::domain_error
\n+
283{
\n+
284 explicit conversion_error(
\n+
285 std::string const &
\n+
286#if pqxx_have_source_location
\n+
287 ,
\n+
288 std::source_location = std::source_location::current()
\n+
289#endif
\n+
290 );
\n+
291
\n+
292#if pqxx_have_source_location
\n+
293 std::source_location location;
\n+
294#endif
\n+
295};
\n+
\n+
296
\n+
297
\n+
\n+
299struct PQXX_LIBEXPORT unexpected_null : conversion_error
\n+
300{
\n+
301 explicit unexpected_null(
\n+
302 std::string const &
\n+
303#if pqxx_have_source_location
\n+
304 ,
\n+
305 std::source_location = std::source_location::current()
\n+
306#endif
\n+
307 );
\n+
308};
\n+
\n+
309
\n+
310
\n+
\n+\n+
313{
\n+
314 explicit conversion_overrun(
\n+
315 std::string const &
\n+
316#if pqxx_have_source_location
\n+
317 ,
\n+
318 std::source_location = std::source_location::current()
\n+
319#endif
\n+
320 );
\n+
321};
\n+
\n+
322
\n+
323
\n+
\n+
325struct PQXX_LIBEXPORT range_error : std::out_of_range
\n+
326{
\n+
327 explicit range_error(
\n+
328 std::string const &
\n+
329#if pqxx_have_source_location
\n+
330 ,
\n+
331 std::source_location = std::source_location::current()
\n+
332#endif
\n+
333 );
\n+
334
\n+
335#if pqxx_have_source_location
\n+
336 std::source_location location;
\n+
337#endif
\n+
338};
\n+
\n+
339
\n+
340
\n+
\n+
342struct PQXX_LIBEXPORT unexpected_rows : public range_error
\n+
343{
\n+
344#if pqxx_have_source_location
\n+
345 explicit unexpected_rows(
\n+
346 std::string const &msg,
\n+
347 std::source_location loc = std::source_location::current()) :
\n+
348 range_error{msg, loc}
\n+
349 {}
\n+
350#else
\n+
351 explicit unexpected_rows(std::string const &msg) : range_error{msg} {}
\n+
352#endif
\n+
353};
\n+
\n+
354
\n+
355
\n+
\n+
357struct PQXX_LIBEXPORT feature_not_supported : sql_error
\n+
358{
\n+
359#if pqxx_have_source_location
\n+
360 explicit feature_not_supported(
\n+
361 std::string const &err, std::string const &Q = "",
\n+
362 char const sqlstate[] = nullptr,
\n+
363 std::source_location loc = std::source_location::current()) :
\n+
364 sql_error{err, Q, sqlstate, loc}
\n+
365 {}
\n+
366#else
\n+
\n+\n+
368 std::string const &err, std::string const &Q = "",
\n+
369 char const sqlstate[] = nullptr) :
\n+
370 sql_error{err, Q, sqlstate}
\n+
371 {}
\n+
\n+
372#endif
\n+
373};
\n+
\n+
374
\n+
\n+
376struct PQXX_LIBEXPORT data_exception : sql_error
\n+
377{
\n+
378#if pqxx_have_source_location
\n+
379 explicit data_exception(
\n+
380 std::string const &err, std::string const &Q = "",
\n+
381 char const sqlstate[] = nullptr,
\n+
382 std::source_location loc = std::source_location::current()) :
\n+
383 sql_error{err, Q, sqlstate, loc}
\n+
384 {}
\n+
385#else
\n+
\n+\n+
387 std::string const &err, std::string const &Q = "",
\n+
388 char const sqlstate[] = nullptr) :
\n+
389 sql_error{err, Q, sqlstate}
\n+
390 {}
\n+
\n+
391#endif
\n+
392};
\n+
\n+
393
\n+
\n+\n+
395{
\n+
396#if pqxx_have_source_location
\n+\n+
398 std::string const &err, std::string const &Q = "",
\n+
399 char const sqlstate[] = nullptr,
\n+
400 std::source_location loc = std::source_location::current()) :
\n+
401 sql_error{err, Q, sqlstate, loc}
\n+
402 {}
\n+
403#else
\n+
\n+\n+
405 std::string const &err, std::string const &Q = "",
\n+
406 char const sqlstate[] = nullptr) :
\n+
407 sql_error{err, Q, sqlstate}
\n+
408 {}
\n+
\n+
409#endif
\n+
410};
\n+
\n+
411
\n+
\n+\n+
413{
\n+
414#if pqxx_have_source_location
\n+
415 explicit restrict_violation(
\n+
416 std::string const &err, std::string const &Q = "",
\n+
417 char const sqlstate[] = nullptr,
\n+
418 std::source_location loc = std::source_location::current()) :
\n+
419 integrity_constraint_violation{err, Q, sqlstate, loc}
\n+
420 {}
\n+
421#else
\n+
\n+\n+
423 std::string const &err, std::string const &Q = "",
\n+
424 char const sqlstate[] = nullptr) :
\n+
425 integrity_constraint_violation{err, Q, sqlstate}
\n+
426 {}
\n+
\n+
427#endif
\n+
428};
\n+
\n+
429
\n+
\n+\n+
431{
\n+
432#if pqxx_have_source_location
\n+
433 explicit not_null_violation(
\n+
434 std::string const &err, std::string const &Q = "",
\n+
435 char const sqlstate[] = nullptr,
\n+
436 std::source_location loc = std::source_location::current()) :
\n+
437 integrity_constraint_violation{err, Q, sqlstate, loc}
\n+
438 {}
\n+
439#else
\n+
\n+\n+
441 std::string const &err, std::string const &Q = "",
\n+
442 char const sqlstate[] = nullptr) :
\n+
443 integrity_constraint_violation{err, Q, sqlstate}
\n+
444 {}
\n+
\n+
445#endif
\n+
446};
\n+
\n+
447
\n+
\n+\n+
449{
\n+
450#if pqxx_have_source_location
\n+
451 explicit foreign_key_violation(
\n+
452 std::string const &err, std::string const &Q = "",
\n+
453 char const sqlstate[] = nullptr,
\n+
454 std::source_location loc = std::source_location::current()) :
\n+
455 integrity_constraint_violation{err, Q, sqlstate, loc}
\n+
456 {}
\n+
457#else
\n+
\n+\n+
459 std::string const &err, std::string const &Q = "",
\n+
460 char const sqlstate[] = nullptr) :
\n+
461 integrity_constraint_violation{err, Q, sqlstate}
\n+
462 {}
\n+
\n+
463#endif
\n+
464};
\n+
\n+
465
\n+
\n+\n+
467{
\n+
468#if pqxx_have_source_location
\n+
469 explicit unique_violation(
\n+
470 std::string const &err, std::string const &Q = "",
\n+
471 char const sqlstate[] = nullptr,
\n+
472 std::source_location loc = std::source_location::current()) :
\n+
473 integrity_constraint_violation{err, Q, sqlstate, loc}
\n+
474 {}
\n+
475#else
\n+
\n+\n+
477 std::string const &err, std::string const &Q = "",
\n+
478 char const sqlstate[] = nullptr) :
\n+
479 integrity_constraint_violation{err, Q, sqlstate}
\n+
480 {}
\n+
\n+
481#endif
\n+
482};
\n+
\n+
483
\n+
\n+\n+
485{
\n+
486#if pqxx_have_source_location
\n+
487 explicit check_violation(
\n+
488 std::string const &err, std::string const &Q = "",
\n+
489 char const sqlstate[] = nullptr,
\n+
490 std::source_location loc = std::source_location::current()) :
\n+
491 integrity_constraint_violation{err, Q, sqlstate, loc}
\n+
492 {}
\n+
493#else
\n+
\n+\n+
495 std::string const &err, std::string const &Q = "",
\n+
496 char const sqlstate[] = nullptr) :
\n+
497 integrity_constraint_violation{err, Q, sqlstate}
\n+
498 {}
\n+
\n+
499#endif
\n+
500};
\n+
\n+
501
\n+
\n+
502struct PQXX_LIBEXPORT invalid_cursor_state : sql_error
\n+
503{
\n+
504#if pqxx_have_source_location
\n+
505 explicit invalid_cursor_state(
\n+
506 std::string const &err, std::string const &Q = "",
\n+
507 char const sqlstate[] = nullptr,
\n+
508 std::source_location loc = std::source_location::current()) :
\n+
509 sql_error{err, Q, sqlstate, loc}
\n+
510 {}
\n+
511#else
\n+
\n+\n+
513 std::string const &err, std::string const &Q = "",
\n+
514 char const sqlstate[] = nullptr) :
\n+
515 sql_error{err, Q, sqlstate}
\n+
516 {}
\n+
\n+
517#endif
\n+
518};
\n+
\n+
519
\n+
\n+\n+
521{
\n+
522#if pqxx_have_source_location
\n+\n+
524 std::string const &err, std::string const &Q = "",
\n+
525 char const sqlstate[] = nullptr,
\n+
526 std::source_location loc = std::source_location::current()) :
\n+
527 sql_error{err, Q, sqlstate, loc}
\n+
528 {}
\n+
529#else
\n+
\n+\n+
531 std::string const &err, std::string const &Q = "",
\n+
532 char const sqlstate[] = nullptr) :
\n+
533 sql_error{err, Q, sqlstate}
\n+
534 {}
\n+
\n+
535#endif
\n+
536};
\n+
\n+
537
\n+
\n+
538struct PQXX_LIBEXPORT invalid_cursor_name : sql_error
\n+
539{
\n+
540#if pqxx_have_source_location
\n+
541 explicit invalid_cursor_name(
\n+
542 std::string const &err, std::string const &Q = "",
\n+
543 char const sqlstate[] = nullptr,
\n+
544 std::source_location loc = std::source_location::current()) :
\n+
545 sql_error{err, Q, sqlstate, loc}
\n+
546 {}
\n+
547#else
\n+
\n+\n+
549 std::string const &err, std::string const &Q = "",
\n+
550 char const sqlstate[] = nullptr) :
\n+
551 sql_error{err, Q, sqlstate}
\n+
552 {}
\n+
\n+
553#endif
\n+
554};
\n+
\n+
555
\n+
\n+
556struct PQXX_LIBEXPORT syntax_error : sql_error
\n+
557{
\n+
559 int const error_position;
\n+
560
\n+
561#if pqxx_have_source_location
\n+
562 explicit syntax_error(
\n+
563 std::string const &err, std::string const &Q = "",
\n+
564 char const sqlstate[] = nullptr, int pos = -1,
\n+
565 std::source_location loc = std::source_location::current()) :
\n+
566 sql_error{err, Q, sqlstate, loc}, error_position{pos}
\n+
567 {}
\n+
568#else
\n+
\n+
569 explicit syntax_error(
\n+
570 std::string const &err, std::string const &Q = "",
\n+
571 char const sqlstate[] = nullptr, int pos = -1) :
\n+
572 sql_error{err, Q, sqlstate}, error_position{pos}
\n+
573 {}
\n+
\n+
574#endif
\n+
575};
\n+
\n+
576
\n+
\n+
577struct PQXX_LIBEXPORT undefined_column : syntax_error
\n+
578{
\n+
579#if pqxx_have_source_location
\n+
580 explicit undefined_column(
\n+
581 std::string const &err, std::string const &Q = "",
\n+
582 char const sqlstate[] = nullptr,
\n+
583 std::source_location loc = std::source_location::current()) :
\n+
584 // TODO: Can we get the column?
\n+
585 syntax_error{err, Q, sqlstate, -1, loc}
\n+
586 {}
\n+
587#else
\n+
\n+\n+
589 std::string const &err, std::string const &Q = "",
\n+
590 char const sqlstate[] = nullptr) :
\n+
591 syntax_error{err, Q, sqlstate}
\n+
592 {}
\n+
\n+
593#endif
\n+
594};
\n+
\n+
595
\n+
\n+
596struct PQXX_LIBEXPORT undefined_function : syntax_error
\n+
597{
\n+
598#if pqxx_have_source_location
\n+
599 explicit undefined_function(
\n+
600 std::string const &err, std::string const &Q = "",
\n+
601 char const sqlstate[] = nullptr,
\n+
602 std::source_location loc = std::source_location::current()) :
\n+
603 // TODO: Can we get the column?
\n+
604 syntax_error{err, Q, sqlstate, -1, loc}
\n+
605 {}
\n+
606#else
\n+
\n+\n+
608 std::string const &err, std::string const &Q = "",
\n+
609 char const sqlstate[] = nullptr) :
\n+
610 syntax_error{err, Q, sqlstate}
\n+
611 {}
\n+
\n+
612#endif
\n+
613};
\n+
\n+
614
\n+
\n+
615struct PQXX_LIBEXPORT undefined_table : syntax_error
\n+
616{
\n+
617#if pqxx_have_source_location
\n+
618 explicit undefined_table(
\n+
619 std::string const &err, std::string const &Q = "",
\n+
620 char const sqlstate[] = nullptr,
\n+
621 std::source_location loc = std::source_location::current()) :
\n+
622 // TODO: Can we get the column?
\n+
623 syntax_error{err, Q, sqlstate, -1, loc}
\n+
624 {}
\n+
625#else
\n+
\n+\n+
627 std::string const &err, std::string const &Q = "",
\n+
628 char const sqlstate[] = nullptr) :
\n+
629 syntax_error{err, Q, sqlstate}
\n+
630 {}
\n+
\n+
631#endif
\n+
632};
\n+
\n+
633
\n+
\n+
634struct PQXX_LIBEXPORT insufficient_privilege : sql_error
\n+
635{
\n+
636#if pqxx_have_source_location
\n+
637 explicit insufficient_privilege(
\n+
638 std::string const &err, std::string const &Q = "",
\n+
639 char const sqlstate[] = nullptr,
\n+
640 std::source_location loc = std::source_location::current()) :
\n+
641 sql_error{err, Q, sqlstate, loc}
\n+
642 {}
\n+
643#else
\n+
\n+\n+
645 std::string const &err, std::string const &Q = "",
\n+
646 char const sqlstate[] = nullptr) :
\n+
647 sql_error{err, Q, sqlstate}
\n+
648 {}
\n+
\n+
649#endif
\n+
650};
\n+
\n+
651
\n+
\n+
653struct PQXX_LIBEXPORT insufficient_resources : sql_error
\n+
654{
\n+
655#if pqxx_have_source_location
\n+
656 explicit insufficient_resources(
\n+
657 std::string const &err, std::string const &Q = "",
\n+
658 char const sqlstate[] = nullptr,
\n+
659 std::source_location loc = std::source_location::current()) :
\n+
660 sql_error{err, Q, sqlstate, loc}
\n+
661 {}
\n+
662#else
\n+
\n+\n+
664 std::string const &err, std::string const &Q = "",
\n+
665 char const sqlstate[] = nullptr) :
\n+
666 sql_error{err, Q, sqlstate}
\n+
667 {}
\n+
\n+
668#endif
\n+
669};
\n+
\n+
670
\n+
\n+
671struct PQXX_LIBEXPORT disk_full : insufficient_resources
\n+
672{
\n+
673#if pqxx_have_source_location
\n+
674 explicit disk_full(
\n+
675 std::string const &err, std::string const &Q = "",
\n+
676 char const sqlstate[] = nullptr,
\n+
677 std::source_location loc = std::source_location::current()) :
\n+
678 insufficient_resources{err, Q, sqlstate, loc}
\n+
679 {}
\n+
680#else
\n+
\n+
681 explicit disk_full(
\n+
682 std::string const &err, std::string const &Q = "",
\n+
683 char const sqlstate[] = nullptr) :
\n+
684 insufficient_resources{err, Q, sqlstate}
\n+
685 {}
\n+
\n+
686#endif
\n+
687};
\n+
\n+
688
\n+
\n+\n+
690{
\n+
691#if pqxx_have_source_location
\n+
692 explicit out_of_memory(
\n+
693 std::string const &err, std::string const &Q = "",
\n+
694 char const sqlstate[] = nullptr,
\n+
695 std::source_location loc = std::source_location::current()) :
\n+
696 insufficient_resources{err, Q, sqlstate, loc}
\n+
697 {}
\n+
698#else
\n+
\n+\n+
700 std::string const &err, std::string const &Q = "",
\n+
701 char const sqlstate[] = nullptr) :
\n+
702 insufficient_resources{err, Q, sqlstate}
\n+
703 {}
\n+
\n+
704#endif
\n+
705};
\n+
\n+
706
\n+
\n+\n+
708{
\n+
709#if pqxx_have_source_location
\n+
710 explicit too_many_connections(
\n+
711 std::string const &err,
\n+
712 std::source_location loc = std::source_location::current()) :
\n+
713 broken_connection{err, loc}
\n+
714 {}
\n+
715#else
\n+
\n+
716 explicit too_many_connections(std::string const &err) :
\n+\n+
718 {}
\n+
\n+
719#endif
\n+
720};
\n+
\n+
721
\n+
723
\n+
\n+
725struct PQXX_LIBEXPORT plpgsql_error : sql_error
\n+
726{
\n+
727#if pqxx_have_source_location
\n+
728 explicit plpgsql_error(
\n+
729 std::string const &err, std::string const &Q = "",
\n+
730 char const sqlstate[] = nullptr,
\n+
731 std::source_location loc = std::source_location::current()) :
\n+
732 sql_error{err, Q, sqlstate, loc}
\n+
733 {}
\n+
734#else
\n+
\n+\n+
736 std::string const &err, std::string const &Q = "",
\n+
737 char const sqlstate[] = nullptr) :
\n+
738 sql_error{err, Q, sqlstate}
\n+
739 {}
\n+
\n+
740#endif
\n+
741};
\n+
\n+
742
\n+
\n+
744struct PQXX_LIBEXPORT plpgsql_raise : plpgsql_error
\n+
745{
\n+
746#if pqxx_have_source_location
\n+
747 explicit plpgsql_raise(
\n+
748 std::string const &err, std::string const &Q = "",
\n+
749 char const sqlstate[] = nullptr,
\n+
750 std::source_location loc = std::source_location::current()) :
\n+
751 plpgsql_error{err, Q, sqlstate, loc}
\n+
752 {}
\n+
753#else
\n+
\n+\n+
755 std::string const &err, std::string const &Q = "",
\n+
756 char const sqlstate[] = nullptr) :
\n+
757 plpgsql_error{err, Q, sqlstate}
\n+
758 {}
\n+
\n+
759#endif
\n+
760};
\n+
\n+
761
\n+
\n+\n+
763{
\n+
764#if pqxx_have_source_location
\n+
765 explicit plpgsql_no_data_found(
\n+
766 std::string const &err, std::string const &Q = "",
\n+
767 char const sqlstate[] = nullptr,
\n+
768 std::source_location loc = std::source_location::current()) :
\n+
769 plpgsql_error{err, Q, sqlstate, loc}
\n+
770 {}
\n+
771#else
\n+
\n+\n+
773 std::string const &err, std::string const &Q = "",
\n+
774 char const sqlstate[] = nullptr) :
\n+
775 plpgsql_error{err, Q, sqlstate}
\n+
776 {}
\n+
\n+
777#endif
\n+
778};
\n+
\n+
779
\n+
\n+\n+
781{
\n+
782#if pqxx_have_source_location
\n+
783 explicit plpgsql_too_many_rows(
\n+
784 std::string const &err, std::string const &Q = "",
\n+
785 char const sqlstate[] = nullptr,
\n+
786 std::source_location loc = std::source_location::current()) :
\n+
787 plpgsql_error{err, Q, sqlstate, loc}
\n+
788 {}
\n+
789#else
\n+
\n+\n+
791 std::string const &err, std::string const &Q = "",
\n+
792 char const sqlstate[] = nullptr) :
\n+
793 plpgsql_error{err, Q, sqlstate}
\n+
794 {}
\n+
\n+
795#endif
\n+
796};
\n+
\n+
797
\n+
801} // namespace pqxx
\n+
802#endif
\n+
The home of all libpqxx classes, functions, templates, etc.
Definition array.hxx:33
\n+
Run-time failure encountered by libpqxx, similar to std::runtime_error.
Definition except.hxx:48
\n+
Exception class for lost or failed backend connection.
Definition except.hxx:81
\n+
Exception class for micommunication with the server.
Definition except.hxx:103
\n+
The caller attempted to set a variable to null, which is not allowed.
Definition except.hxx:116
\n+
Exception class for failed queries.
Definition except.hxx:132
\n+
virtual ~sql_error() noexcept override
\n+
"Help, I don't know whether transaction was committed successfully!"
Definition except.hxx:165
\n+
The backend saw itself forced to roll back the ongoing transaction.
Definition except.hxx:178
\n+
Transaction failed to serialize. Please retry it.
Definition except.hxx:200
\n+
We can't tell whether our last statement succeeded.
Definition except.hxx:214
\n+
The ongoing transaction has deadlocked. Retrying it may help.
Definition except.hxx:228
\n+
Internal error in libpqxx library.
Definition except.hxx:242
\n+
Error in usage of libpqxx library, similar to std::logic_error.
Definition except.hxx:249
\n+
Invalid argument passed to libpqxx, similar to std::invalid_argument.
Definition except.hxx:266
\n+
Value conversion failed, e.g. when converting "Hello" to int.
Definition except.hxx:283
\n+
Could not convert null value: target type does not support null.
Definition except.hxx:300
\n+
Could not convert value to string: not enough buffer space.
Definition except.hxx:313
\n+
Something is out of range, similar to std::out_of_range.
Definition except.hxx:326
\n+
Query returned an unexpected number of rows.
Definition except.hxx:343
\n+
unexpected_rows(std::string const &msg)
Definition except.hxx:351
\n+
Database feature not supported in current setup.
Definition except.hxx:358
\n+
feature_not_supported(std::string const &err, std::string const &Q="", char const sqlstate[]=nullptr)
Definition except.hxx:367
\n+
Error in data provided to SQL statement.
Definition except.hxx:377
\n+
data_exception(std::string const &err, std::string const &Q="", char const sqlstate[]=nullptr)
Definition except.hxx:386
\n+
Definition except.hxx:395
\n+
integrity_constraint_violation(std::string const &err, std::string const &Q="", char const sqlstate[]=nullptr)
Definition except.hxx:404
\n+
Definition except.hxx:413
\n+
restrict_violation(std::string const &err, std::string const &Q="", char const sqlstate[]=nullptr)
Definition except.hxx:422
\n+
Definition except.hxx:431
\n+
not_null_violation(std::string const &err, std::string const &Q="", char const sqlstate[]=nullptr)
Definition except.hxx:440
\n+
Definition except.hxx:449
\n+
foreign_key_violation(std::string const &err, std::string const &Q="", char const sqlstate[]=nullptr)
Definition except.hxx:458
\n+
Definition except.hxx:467
\n+
unique_violation(std::string const &err, std::string const &Q="", char const sqlstate[]=nullptr)
Definition except.hxx:476
\n+
Definition except.hxx:485
\n+
check_violation(std::string const &err, std::string const &Q="", char const sqlstate[]=nullptr)
Definition except.hxx:494
\n+
Definition except.hxx:503
\n+
invalid_cursor_state(std::string const &err, std::string const &Q="", char const sqlstate[]=nullptr)
Definition except.hxx:512
\n+
Definition except.hxx:521
\n+
invalid_sql_statement_name(std::string const &err, std::string const &Q="", char const sqlstate[]=nullptr)
Definition except.hxx:530
\n+
Definition except.hxx:539
\n+
invalid_cursor_name(std::string const &err, std::string const &Q="", char const sqlstate[]=nullptr)
Definition except.hxx:548
\n+
Definition except.hxx:557
\n+
syntax_error(std::string const &err, std::string const &Q="", char const sqlstate[]=nullptr, int pos=-1)
Definition except.hxx:569
\n+
int const error_position
Approximate position in string where error occurred, or -1 if unknown.
Definition except.hxx:559
\n+
Definition except.hxx:578
\n+
undefined_column(std::string const &err, std::string const &Q="", char const sqlstate[]=nullptr)
Definition except.hxx:588
\n+
Definition except.hxx:597
\n+
undefined_function(std::string const &err, std::string const &Q="", char const sqlstate[]=nullptr)
Definition except.hxx:607
\n+
Definition except.hxx:616
\n+
undefined_table(std::string const &err, std::string const &Q="", char const sqlstate[]=nullptr)
Definition except.hxx:626
\n+
Definition except.hxx:635
\n+
insufficient_privilege(std::string const &err, std::string const &Q="", char const sqlstate[]=nullptr)
Definition except.hxx:644
\n+
Resource shortage on the server.
Definition except.hxx:654
\n+
insufficient_resources(std::string const &err, std::string const &Q="", char const sqlstate[]=nullptr)
Definition except.hxx:663
\n+
Definition except.hxx:672
\n+
disk_full(std::string const &err, std::string const &Q="", char const sqlstate[]=nullptr)
Definition except.hxx:681
\n+
Definition except.hxx:690
\n+
out_of_memory(std::string const &err, std::string const &Q="", char const sqlstate[]=nullptr)
Definition except.hxx:699
\n+
Definition except.hxx:708
\n+
too_many_connections(std::string const &err)
Definition except.hxx:716
\n+
PL/pgSQL error.
Definition except.hxx:726
\n+
plpgsql_error(std::string const &err, std::string const &Q="", char const sqlstate[]=nullptr)
Definition except.hxx:735
\n+
Exception raised in PL/pgSQL procedure.
Definition except.hxx:745
\n+
plpgsql_raise(std::string const &err, std::string const &Q="", char const sqlstate[]=nullptr)
Definition except.hxx:754
\n+
Definition except.hxx:763
\n+
plpgsql_no_data_found(std::string const &err, std::string const &Q="", char const sqlstate[]=nullptr)
Definition except.hxx:772
\n+
Definition except.hxx:781
\n+
plpgsql_too_many_rows(std::string const &err, std::string const &Q="", char const sqlstate[]=nullptr)
Definition except.hxx:790
\n
\n
\n \n
\n \n
\n \n \n", "details": [{"source1": "html2text {}", "source2": "html2text {}", "unified_diff": "@@ -1,18 +1,941 @@\n \n \n \n \n \n libpqxx\u00a07.8.1\n \n-config-public-compiler.h\n- 1/* Automatically generated from config.h: public/compiler config. */\n- 2\n- 3#define PQXX_HAVE_GCC_PURE 1\n- 4#define PQXX_HAVE_GCC_VISIBILITY 1\n- 5#define PQXX_HAVE_PATH 1\n- 6#define PQXX_HAVE_STRERROR_R 1\n+except.hxx\n+ 1/* Definition of libpqxx exception classes.\n+ 2 *\n+ 3 * pqxx::sql_error, pqxx::broken_connection, pqxx::in_doubt_error, ...\n+ 4 *\n+ 5 * DO NOT INCLUDE THIS FILE DIRECTLY; include pqxx/except instead.\n+ 6 *\n+ 7 * Copyright (c) 2000-2023, Jeroen T. Vermeulen.\n+ 8 *\n+ 9 * See COPYING for copyright license. If you did not receive a file called\n+ 10 * COPYING with this source code, please notify the distributor of this\n+ 11 * mistake, or contact the author.\n+ 12 */\n+ 13#ifndef PQXX_H_EXCEPT\n+ 14#define PQXX_H_EXCEPT\n+ 15\n+ 16#if !defined(PQXX_HEADER_PRE)\n+ 17# error \"Include libpqxx headers as , not .\"\n+ 18#endif\n+ 19\n+ 20#if pqxx_have_source_location\n+ 21# include \n+ 22#endif\n+ 23\n+ 24#include \n+ 25#include \n+ 26\n+ 27\n+ 28namespace pqxx\n+ 29{\n+47struct PQXX_LIBEXPORT failure : std::runtime_error\n+ 48{\n+ 49#if pqxx_have_source_location\n+ 50 explicit failure(\n+ 51 std::string const &,\n+ 52 std::source_location = std::source_location::current());\n+ 53 std::source_location location;\n+ 54#else\n+ 55 explicit failure(std::string const &);\n+ 56#endif\n+ 57};\n+ 58\n+ 59\n+ 61\n+80struct PQXX_LIBEXPORT broken_connection : failure\n+ 81{\n+ 82 broken_connection();\n+ 83 explicit broken_connection(\n+ 84 std::string const &\n+ 85#if pqxx_have_source_location\n+ 86 ,\n+ 87 std::source_location = std::source_location::current()\n+ 88#endif\n+ 89 );\n+ 90};\n+ 91\n+ 92\n+ 94\n+102struct PQXX_LIBEXPORT protocol_violation : broken_connection\n+ 103{\n+ 104 explicit protocol_violation(\n+ 105 std::string const &\n+ 106#if pqxx_have_source_location\n+ 107 ,\n+ 108 std::source_location = std::source_location::current()\n+ 109#endif\n+ 110 );\n+ 111};\n+ 112\n+ 113\n+115struct PQXX_LIBEXPORT variable_set_to_null : failure\n+ 116{\n+ 117 explicit variable_set_to_null(\n+ 118 std::string const &\n+ 119#if pqxx_have_source_location\n+ 120 ,\n+ 121 std::source_location = std::source_location::current()\n+ 122#endif\n+ 123 );\n+ 124};\n+ 125\n+ 126\n+ 128\n+131class PQXX_LIBEXPORT sql_error : public failure\n+ 132{\n+ 134 std::string const m_query;\n+ 136 std::string const m_sqlstate;\n+ 137\n+ 138public:\n+ 139 explicit sql_error(\n+ 140 std::string const &whatarg = \"\", std::string const &Q = \"\",\n+ 141 char const sqlstate[] = nullptr\n+ 142#if pqxx_have_source_location\n+ 143 ,\n+ 144 std::source_location = std::source_location::current()\n+ 145#endif\n+ 146 );\n+147 virtual ~sql_error() noexcept override;\n+ 148\n+ 150 [[nodiscard]] PQXX_PURE std::string const &query() const noexcept;\n+ 151\n+ 153 [[nodiscard]] PQXX_PURE std::string const &sqlstate() const noexcept;\n+ 154};\n+ 155\n+ 156\n+ 158\n+164struct PQXX_LIBEXPORT in_doubt_error : failure\n+ 165{\n+ 166 explicit in_doubt_error(\n+ 167 std::string const &\n+ 168#if pqxx_have_source_location\n+ 169 ,\n+ 170 std::source_location = std::source_location::current()\n+ 171#endif\n+ 172 );\n+ 173};\n+ 174\n+ 175\n+177struct PQXX_LIBEXPORT transaction_rollback : sql_error\n+ 178{\n+ 179 explicit transaction_rollback(\n+ 180 std::string const &whatarg, std::string const &q = \"\",\n+ 181 char const sqlstate[] = nullptr\n+ 182#if pqxx_have_source_location\n+ 183 ,\n+ 184 std::source_location = std::source_location::current()\n+ 185#endif\n+ 186 );\n+ 187};\n+ 188\n+ 189\n+ 191\n+199struct PQXX_LIBEXPORT serialization_failure : transaction_rollback\n+ 200{\n+ 201 explicit serialization_failure(\n+ 202 std::string const &whatarg, std::string const &q,\n+ 203 char const sqlstate[] = nullptr\n+ 204#if pqxx_have_source_location\n+ 205 ,\n+ 206 std::source_location = std::source_location::current()\n+ 207#endif\n+ 208 );\n+ 209};\n+ 210\n+ 211\n+213struct PQXX_LIBEXPORT statement_completion_unknown : transaction_rollback\n+ 214{\n+ 215 explicit statement_completion_unknown(\n+ 216 std::string const &whatarg, std::string const &q,\n+ 217 char const sqlstate[] = nullptr\n+ 218#if pqxx_have_source_location\n+ 219 ,\n+ 220 std::source_location = std::source_location::current()\n+ 221#endif\n+ 222 );\n+ 223};\n+ 224\n+ 225\n+227struct PQXX_LIBEXPORT deadlock_detected : transaction_rollback\n+ 228{\n+ 229 explicit deadlock_detected(\n+ 230 std::string const &whatarg, std::string const &q,\n+ 231 char const sqlstate[] = nullptr\n+ 232#if pqxx_have_source_location\n+ 233 ,\n+ 234 std::source_location = std::source_location::current()\n+ 235#endif\n+ 236 );\n+ 237};\n+ 238\n+ 239\n+241struct PQXX_LIBEXPORT internal_error : std::logic_error\n+ 242{\n+ 243 explicit internal_error(std::string const &);\n+ 244};\n+ 245\n+ 246\n+248struct PQXX_LIBEXPORT usage_error : std::logic_error\n+ 249{\n+ 250 explicit usage_error(\n+ 251 std::string const &\n+ 252#if pqxx_have_source_location\n+ 253 ,\n+ 254 std::source_location = std::source_location::current()\n+ 255#endif\n+ 256 );\n+ 257\n+ 258#if pqxx_have_source_location\n+ 259 std::source_location location;\n+ 260#endif\n+ 261};\n+ 262\n+ 263\n+265struct PQXX_LIBEXPORT argument_error : std::invalid_argument\n+ 266{\n+ 267 explicit argument_error(\n+ 268 std::string const &\n+ 269#if pqxx_have_source_location\n+ 270 ,\n+ 271 std::source_location = std::source_location::current()\n+ 272#endif\n+ 273 );\n+ 274\n+ 275#if pqxx_have_source_location\n+ 276 std::source_location location;\n+ 277#endif\n+ 278};\n+ 279\n+ 280\n+282struct PQXX_LIBEXPORT conversion_error : std::domain_error\n+ 283{\n+ 284 explicit conversion_error(\n+ 285 std::string const &\n+ 286#if pqxx_have_source_location\n+ 287 ,\n+ 288 std::source_location = std::source_location::current()\n+ 289#endif\n+ 290 );\n+ 291\n+ 292#if pqxx_have_source_location\n+ 293 std::source_location location;\n+ 294#endif\n+ 295};\n+ 296\n+ 297\n+299struct PQXX_LIBEXPORT unexpected_null : conversion_error\n+ 300{\n+ 301 explicit unexpected_null(\n+ 302 std::string const &\n+ 303#if pqxx_have_source_location\n+ 304 ,\n+ 305 std::source_location = std::source_location::current()\n+ 306#endif\n+ 307 );\n+ 308};\n+ 309\n+ 310\n+312struct PQXX_LIBEXPORT conversion_overrun : conversion_error\n+ 313{\n+ 314 explicit conversion_overrun(\n+ 315 std::string const &\n+ 316#if pqxx_have_source_location\n+ 317 ,\n+ 318 std::source_location = std::source_location::current()\n+ 319#endif\n+ 320 );\n+ 321};\n+ 322\n+ 323\n+325struct PQXX_LIBEXPORT range_error : std::out_of_range\n+ 326{\n+ 327 explicit range_error(\n+ 328 std::string const &\n+ 329#if pqxx_have_source_location\n+ 330 ,\n+ 331 std::source_location = std::source_location::current()\n+ 332#endif\n+ 333 );\n+ 334\n+ 335#if pqxx_have_source_location\n+ 336 std::source_location location;\n+ 337#endif\n+ 338};\n+ 339\n+ 340\n+342struct PQXX_LIBEXPORT unexpected_rows : public range_error\n+ 343{\n+ 344#if pqxx_have_source_location\n+ 345 explicit unexpected_rows(\n+ 346 std::string const &msg,\n+ 347 std::source_location loc = std::source_location::current()) :\n+ 348 range_error{msg, loc}\n+ 349 {}\n+ 350#else\n+351 explicit unexpected_rows(std::string const &msg) : range_error{msg} {}\n+ 352#endif\n+ 353};\n+ 354\n+ 355\n+357struct PQXX_LIBEXPORT feature_not_supported : sql_error\n+ 358{\n+ 359#if pqxx_have_source_location\n+ 360 explicit feature_not_supported(\n+ 361 std::string const &err, std::string const &Q = \"\",\n+ 362 char const sqlstate[] = nullptr,\n+ 363 std::source_location loc = std::source_location::current()) :\n+ 364 sql_error{err, Q, sqlstate, loc}\n+ 365 {}\n+ 366#else\n+367 explicit feature_not_supported(\n+ 368 std::string const &err, std::string const &Q = \"\",\n+ 369 char const sqlstate[] = nullptr) :\n+ 370 sql_error{err, Q, sqlstate}\n+ 371 {}\n+ 372#endif\n+ 373};\n+ 374\n+376struct PQXX_LIBEXPORT data_exception : sql_error\n+ 377{\n+ 378#if pqxx_have_source_location\n+ 379 explicit data_exception(\n+ 380 std::string const &err, std::string const &Q = \"\",\n+ 381 char const sqlstate[] = nullptr,\n+ 382 std::source_location loc = std::source_location::current()) :\n+ 383 sql_error{err, Q, sqlstate, loc}\n+ 384 {}\n+ 385#else\n+386 explicit data_exception(\n+ 387 std::string const &err, std::string const &Q = \"\",\n+ 388 char const sqlstate[] = nullptr) :\n+ 389 sql_error{err, Q, sqlstate}\n+ 390 {}\n+ 391#endif\n+ 392};\n+ 393\n+394struct PQXX_LIBEXPORT integrity_constraint_violation : sql_error\n+ 395{\n+ 396#if pqxx_have_source_location\n+ 397 explicit integrity_constraint_violation(\n+ 398 std::string const &err, std::string const &Q = \"\",\n+ 399 char const sqlstate[] = nullptr,\n+ 400 std::source_location loc = std::source_location::current()) :\n+ 401 sql_error{err, Q, sqlstate, loc}\n+ 402 {}\n+ 403#else\n+404 explicit integrity_constraint_violation(\n+ 405 std::string const &err, std::string const &Q = \"\",\n+ 406 char const sqlstate[] = nullptr) :\n+ 407 sql_error{err, Q, sqlstate}\n+ 408 {}\n+ 409#endif\n+ 410};\n+ 411\n+412struct PQXX_LIBEXPORT restrict_violation : integrity_constraint_violation\n+ 413{\n+ 414#if pqxx_have_source_location\n+ 415 explicit restrict_violation(\n+ 416 std::string const &err, std::string const &Q = \"\",\n+ 417 char const sqlstate[] = nullptr,\n+ 418 std::source_location loc = std::source_location::current()) :\n+ 419 integrity_constraint_violation{err, Q, sqlstate, loc}\n+ 420 {}\n+ 421#else\n+422 explicit restrict_violation(\n+ 423 std::string const &err, std::string const &Q = \"\",\n+ 424 char const sqlstate[] = nullptr) :\n+ 425 integrity_constraint_violation{err, Q, sqlstate}\n+ 426 {}\n+ 427#endif\n+ 428};\n+ 429\n+430struct PQXX_LIBEXPORT not_null_violation : integrity_constraint_violation\n+ 431{\n+ 432#if pqxx_have_source_location\n+ 433 explicit not_null_violation(\n+ 434 std::string const &err, std::string const &Q = \"\",\n+ 435 char const sqlstate[] = nullptr,\n+ 436 std::source_location loc = std::source_location::current()) :\n+ 437 integrity_constraint_violation{err, Q, sqlstate, loc}\n+ 438 {}\n+ 439#else\n+440 explicit not_null_violation(\n+ 441 std::string const &err, std::string const &Q = \"\",\n+ 442 char const sqlstate[] = nullptr) :\n+ 443 integrity_constraint_violation{err, Q, sqlstate}\n+ 444 {}\n+ 445#endif\n+ 446};\n+ 447\n+448struct PQXX_LIBEXPORT foreign_key_violation : integrity_constraint_violation\n+ 449{\n+ 450#if pqxx_have_source_location\n+ 451 explicit foreign_key_violation(\n+ 452 std::string const &err, std::string const &Q = \"\",\n+ 453 char const sqlstate[] = nullptr,\n+ 454 std::source_location loc = std::source_location::current()) :\n+ 455 integrity_constraint_violation{err, Q, sqlstate, loc}\n+ 456 {}\n+ 457#else\n+458 explicit foreign_key_violation(\n+ 459 std::string const &err, std::string const &Q = \"\",\n+ 460 char const sqlstate[] = nullptr) :\n+ 461 integrity_constraint_violation{err, Q, sqlstate}\n+ 462 {}\n+ 463#endif\n+ 464};\n+ 465\n+466struct PQXX_LIBEXPORT unique_violation : integrity_constraint_violation\n+ 467{\n+ 468#if pqxx_have_source_location\n+ 469 explicit unique_violation(\n+ 470 std::string const &err, std::string const &Q = \"\",\n+ 471 char const sqlstate[] = nullptr,\n+ 472 std::source_location loc = std::source_location::current()) :\n+ 473 integrity_constraint_violation{err, Q, sqlstate, loc}\n+ 474 {}\n+ 475#else\n+476 explicit unique_violation(\n+ 477 std::string const &err, std::string const &Q = \"\",\n+ 478 char const sqlstate[] = nullptr) :\n+ 479 integrity_constraint_violation{err, Q, sqlstate}\n+ 480 {}\n+ 481#endif\n+ 482};\n+ 483\n+484struct PQXX_LIBEXPORT check_violation : integrity_constraint_violation\n+ 485{\n+ 486#if pqxx_have_source_location\n+ 487 explicit check_violation(\n+ 488 std::string const &err, std::string const &Q = \"\",\n+ 489 char const sqlstate[] = nullptr,\n+ 490 std::source_location loc = std::source_location::current()) :\n+ 491 integrity_constraint_violation{err, Q, sqlstate, loc}\n+ 492 {}\n+ 493#else\n+494 explicit check_violation(\n+ 495 std::string const &err, std::string const &Q = \"\",\n+ 496 char const sqlstate[] = nullptr) :\n+ 497 integrity_constraint_violation{err, Q, sqlstate}\n+ 498 {}\n+ 499#endif\n+ 500};\n+ 501\n+502struct PQXX_LIBEXPORT invalid_cursor_state : sql_error\n+ 503{\n+ 504#if pqxx_have_source_location\n+ 505 explicit invalid_cursor_state(\n+ 506 std::string const &err, std::string const &Q = \"\",\n+ 507 char const sqlstate[] = nullptr,\n+ 508 std::source_location loc = std::source_location::current()) :\n+ 509 sql_error{err, Q, sqlstate, loc}\n+ 510 {}\n+ 511#else\n+512 explicit invalid_cursor_state(\n+ 513 std::string const &err, std::string const &Q = \"\",\n+ 514 char const sqlstate[] = nullptr) :\n+ 515 sql_error{err, Q, sqlstate}\n+ 516 {}\n+ 517#endif\n+ 518};\n+ 519\n+520struct PQXX_LIBEXPORT invalid_sql_statement_name : sql_error\n+ 521{\n+ 522#if pqxx_have_source_location\n+ 523 explicit invalid_sql_statement_name(\n+ 524 std::string const &err, std::string const &Q = \"\",\n+ 525 char const sqlstate[] = nullptr,\n+ 526 std::source_location loc = std::source_location::current()) :\n+ 527 sql_error{err, Q, sqlstate, loc}\n+ 528 {}\n+ 529#else\n+530 explicit invalid_sql_statement_name(\n+ 531 std::string const &err, std::string const &Q = \"\",\n+ 532 char const sqlstate[] = nullptr) :\n+ 533 sql_error{err, Q, sqlstate}\n+ 534 {}\n+ 535#endif\n+ 536};\n+ 537\n+538struct PQXX_LIBEXPORT invalid_cursor_name : sql_error\n+ 539{\n+ 540#if pqxx_have_source_location\n+ 541 explicit invalid_cursor_name(\n+ 542 std::string const &err, std::string const &Q = \"\",\n+ 543 char const sqlstate[] = nullptr,\n+ 544 std::source_location loc = std::source_location::current()) :\n+ 545 sql_error{err, Q, sqlstate, loc}\n+ 546 {}\n+ 547#else\n+548 explicit invalid_cursor_name(\n+ 549 std::string const &err, std::string const &Q = \"\",\n+ 550 char const sqlstate[] = nullptr) :\n+ 551 sql_error{err, Q, sqlstate}\n+ 552 {}\n+ 553#endif\n+ 554};\n+ 555\n+556struct PQXX_LIBEXPORT syntax_error : sql_error\n+ 557{\n+559 int const error_position;\n+ 560\n+ 561#if pqxx_have_source_location\n+ 562 explicit syntax_error(\n+ 563 std::string const &err, std::string const &Q = \"\",\n+ 564 char const sqlstate[] = nullptr, int pos = -1,\n+ 565 std::source_location loc = std::source_location::current()) :\n+ 566 sql_error{err, Q, sqlstate, loc}, error_position{pos}\n+ 567 {}\n+ 568#else\n+569 explicit syntax_error(\n+ 570 std::string const &err, std::string const &Q = \"\",\n+ 571 char const sqlstate[] = nullptr, int pos = -1) :\n+ 572 sql_error{err, Q, sqlstate}, error_position{pos}\n+ 573 {}\n+ 574#endif\n+ 575};\n+ 576\n+577struct PQXX_LIBEXPORT undefined_column : syntax_error\n+ 578{\n+ 579#if pqxx_have_source_location\n+ 580 explicit undefined_column(\n+ 581 std::string const &err, std::string const &Q = \"\",\n+ 582 char const sqlstate[] = nullptr,\n+ 583 std::source_location loc = std::source_location::current()) :\n+ 584 // TODO: Can we get the column?\n+ 585 syntax_error{err, Q, sqlstate, -1, loc}\n+ 586 {}\n+ 587#else\n+588 explicit undefined_column(\n+ 589 std::string const &err, std::string const &Q = \"\",\n+ 590 char const sqlstate[] = nullptr) :\n+ 591 syntax_error{err, Q, sqlstate}\n+ 592 {}\n+ 593#endif\n+ 594};\n+ 595\n+596struct PQXX_LIBEXPORT undefined_function : syntax_error\n+ 597{\n+ 598#if pqxx_have_source_location\n+ 599 explicit undefined_function(\n+ 600 std::string const &err, std::string const &Q = \"\",\n+ 601 char const sqlstate[] = nullptr,\n+ 602 std::source_location loc = std::source_location::current()) :\n+ 603 // TODO: Can we get the column?\n+ 604 syntax_error{err, Q, sqlstate, -1, loc}\n+ 605 {}\n+ 606#else\n+607 explicit undefined_function(\n+ 608 std::string const &err, std::string const &Q = \"\",\n+ 609 char const sqlstate[] = nullptr) :\n+ 610 syntax_error{err, Q, sqlstate}\n+ 611 {}\n+ 612#endif\n+ 613};\n+ 614\n+615struct PQXX_LIBEXPORT undefined_table : syntax_error\n+ 616{\n+ 617#if pqxx_have_source_location\n+ 618 explicit undefined_table(\n+ 619 std::string const &err, std::string const &Q = \"\",\n+ 620 char const sqlstate[] = nullptr,\n+ 621 std::source_location loc = std::source_location::current()) :\n+ 622 // TODO: Can we get the column?\n+ 623 syntax_error{err, Q, sqlstate, -1, loc}\n+ 624 {}\n+ 625#else\n+626 explicit undefined_table(\n+ 627 std::string const &err, std::string const &Q = \"\",\n+ 628 char const sqlstate[] = nullptr) :\n+ 629 syntax_error{err, Q, sqlstate}\n+ 630 {}\n+ 631#endif\n+ 632};\n+ 633\n+634struct PQXX_LIBEXPORT insufficient_privilege : sql_error\n+ 635{\n+ 636#if pqxx_have_source_location\n+ 637 explicit insufficient_privilege(\n+ 638 std::string const &err, std::string const &Q = \"\",\n+ 639 char const sqlstate[] = nullptr,\n+ 640 std::source_location loc = std::source_location::current()) :\n+ 641 sql_error{err, Q, sqlstate, loc}\n+ 642 {}\n+ 643#else\n+644 explicit insufficient_privilege(\n+ 645 std::string const &err, std::string const &Q = \"\",\n+ 646 char const sqlstate[] = nullptr) :\n+ 647 sql_error{err, Q, sqlstate}\n+ 648 {}\n+ 649#endif\n+ 650};\n+ 651\n+653struct PQXX_LIBEXPORT insufficient_resources : sql_error\n+ 654{\n+ 655#if pqxx_have_source_location\n+ 656 explicit insufficient_resources(\n+ 657 std::string const &err, std::string const &Q = \"\",\n+ 658 char const sqlstate[] = nullptr,\n+ 659 std::source_location loc = std::source_location::current()) :\n+ 660 sql_error{err, Q, sqlstate, loc}\n+ 661 {}\n+ 662#else\n+663 explicit insufficient_resources(\n+ 664 std::string const &err, std::string const &Q = \"\",\n+ 665 char const sqlstate[] = nullptr) :\n+ 666 sql_error{err, Q, sqlstate}\n+ 667 {}\n+ 668#endif\n+ 669};\n+ 670\n+671struct PQXX_LIBEXPORT disk_full : insufficient_resources\n+ 672{\n+ 673#if pqxx_have_source_location\n+ 674 explicit disk_full(\n+ 675 std::string const &err, std::string const &Q = \"\",\n+ 676 char const sqlstate[] = nullptr,\n+ 677 std::source_location loc = std::source_location::current()) :\n+ 678 insufficient_resources{err, Q, sqlstate, loc}\n+ 679 {}\n+ 680#else\n+681 explicit disk_full(\n+ 682 std::string const &err, std::string const &Q = \"\",\n+ 683 char const sqlstate[] = nullptr) :\n+ 684 insufficient_resources{err, Q, sqlstate}\n+ 685 {}\n+ 686#endif\n+ 687};\n+ 688\n+689struct PQXX_LIBEXPORT out_of_memory : insufficient_resources\n+ 690{\n+ 691#if pqxx_have_source_location\n+ 692 explicit out_of_memory(\n+ 693 std::string const &err, std::string const &Q = \"\",\n+ 694 char const sqlstate[] = nullptr,\n+ 695 std::source_location loc = std::source_location::current()) :\n+ 696 insufficient_resources{err, Q, sqlstate, loc}\n+ 697 {}\n+ 698#else\n+699 explicit out_of_memory(\n+ 700 std::string const &err, std::string const &Q = \"\",\n+ 701 char const sqlstate[] = nullptr) :\n+ 702 insufficient_resources{err, Q, sqlstate}\n+ 703 {}\n+ 704#endif\n+ 705};\n+ 706\n+707struct PQXX_LIBEXPORT too_many_connections : broken_connection\n+ 708{\n+ 709#if pqxx_have_source_location\n+ 710 explicit too_many_connections(\n+ 711 std::string const &err,\n+ 712 std::source_location loc = std::source_location::current()) :\n+ 713 broken_connection{err, loc}\n+ 714 {}\n+ 715#else\n+716 explicit too_many_connections(std::string const &err) :\n+ 717 broken_connection{err}\n+ 718 {}\n+ 719#endif\n+ 720};\n+ 721\n+ 723\n+725struct PQXX_LIBEXPORT plpgsql_error : sql_error\n+ 726{\n+ 727#if pqxx_have_source_location\n+ 728 explicit plpgsql_error(\n+ 729 std::string const &err, std::string const &Q = \"\",\n+ 730 char const sqlstate[] = nullptr,\n+ 731 std::source_location loc = std::source_location::current()) :\n+ 732 sql_error{err, Q, sqlstate, loc}\n+ 733 {}\n+ 734#else\n+735 explicit plpgsql_error(\n+ 736 std::string const &err, std::string const &Q = \"\",\n+ 737 char const sqlstate[] = nullptr) :\n+ 738 sql_error{err, Q, sqlstate}\n+ 739 {}\n+ 740#endif\n+ 741};\n+ 742\n+744struct PQXX_LIBEXPORT plpgsql_raise : plpgsql_error\n+ 745{\n+ 746#if pqxx_have_source_location\n+ 747 explicit plpgsql_raise(\n+ 748 std::string const &err, std::string const &Q = \"\",\n+ 749 char const sqlstate[] = nullptr,\n+ 750 std::source_location loc = std::source_location::current()) :\n+ 751 plpgsql_error{err, Q, sqlstate, loc}\n+ 752 {}\n+ 753#else\n+754 explicit plpgsql_raise(\n+ 755 std::string const &err, std::string const &Q = \"\",\n+ 756 char const sqlstate[] = nullptr) :\n+ 757 plpgsql_error{err, Q, sqlstate}\n+ 758 {}\n+ 759#endif\n+ 760};\n+ 761\n+762struct PQXX_LIBEXPORT plpgsql_no_data_found : plpgsql_error\n+ 763{\n+ 764#if pqxx_have_source_location\n+ 765 explicit plpgsql_no_data_found(\n+ 766 std::string const &err, std::string const &Q = \"\",\n+ 767 char const sqlstate[] = nullptr,\n+ 768 std::source_location loc = std::source_location::current()) :\n+ 769 plpgsql_error{err, Q, sqlstate, loc}\n+ 770 {}\n+ 771#else\n+772 explicit plpgsql_no_data_found(\n+ 773 std::string const &err, std::string const &Q = \"\",\n+ 774 char const sqlstate[] = nullptr) :\n+ 775 plpgsql_error{err, Q, sqlstate}\n+ 776 {}\n+ 777#endif\n+ 778};\n+ 779\n+780struct PQXX_LIBEXPORT plpgsql_too_many_rows : plpgsql_error\n+ 781{\n+ 782#if pqxx_have_source_location\n+ 783 explicit plpgsql_too_many_rows(\n+ 784 std::string const &err, std::string const &Q = \"\",\n+ 785 char const sqlstate[] = nullptr,\n+ 786 std::source_location loc = std::source_location::current()) :\n+ 787 plpgsql_error{err, Q, sqlstate, loc}\n+ 788 {}\n+ 789#else\n+790 explicit plpgsql_too_many_rows(\n+ 791 std::string const &err, std::string const &Q = \"\",\n+ 792 char const sqlstate[] = nullptr) :\n+ 793 plpgsql_error{err, Q, sqlstate}\n+ 794 {}\n+ 795#endif\n+ 796};\n+ 797\n+ 801} // namespace pqxx\n+ 802#endif\n+pqxx\n+The home of all libpqxx classes, functions, templates, etc.\n+Definition array.hxx:33\n+pqxx::failure\n+Run-time failure encountered by libpqxx, similar to std::runtime_error.\n+Definition except.hxx:48\n+pqxx::broken_connection\n+Exception class for lost or failed backend connection.\n+Definition except.hxx:81\n+pqxx::protocol_violation\n+Exception class for micommunication with the server.\n+Definition except.hxx:103\n+pqxx::variable_set_to_null\n+The caller attempted to set a variable to null, which is not allowed.\n+Definition except.hxx:116\n+pqxx::sql_error\n+Exception class for failed queries.\n+Definition except.hxx:132\n+pqxx::sql_error::~sql_error\n+virtual ~sql_error() noexcept override\n+pqxx::in_doubt_error\n+\"Help, I don't know whether transaction was committed successfully!\"\n+Definition except.hxx:165\n+pqxx::transaction_rollback\n+The backend saw itself forced to roll back the ongoing transaction.\n+Definition except.hxx:178\n+pqxx::serialization_failure\n+Transaction failed to serialize. Please retry it.\n+Definition except.hxx:200\n+pqxx::statement_completion_unknown\n+We can't tell whether our last statement succeeded.\n+Definition except.hxx:214\n+pqxx::deadlock_detected\n+The ongoing transaction has deadlocked. Retrying it may help.\n+Definition except.hxx:228\n+pqxx::internal_error\n+Internal error in libpqxx library.\n+Definition except.hxx:242\n+pqxx::usage_error\n+Error in usage of libpqxx library, similar to std::logic_error.\n+Definition except.hxx:249\n+pqxx::argument_error\n+Invalid argument passed to libpqxx, similar to std::invalid_argument.\n+Definition except.hxx:266\n+pqxx::conversion_error\n+Value conversion failed, e.g. when converting \"Hello\" to int.\n+Definition except.hxx:283\n+pqxx::unexpected_null\n+Could not convert null value: target type does not support null.\n+Definition except.hxx:300\n+pqxx::conversion_overrun\n+Could not convert value to string: not enough buffer space.\n+Definition except.hxx:313\n+pqxx::range_error\n+Something is out of range, similar to std::out_of_range.\n+Definition except.hxx:326\n+pqxx::unexpected_rows\n+Query returned an unexpected number of rows.\n+Definition except.hxx:343\n+pqxx::unexpected_rows::unexpected_rows\n+unexpected_rows(std::string const &msg)\n+Definition except.hxx:351\n+pqxx::feature_not_supported\n+Database feature not supported in current setup.\n+Definition except.hxx:358\n+pqxx::feature_not_supported::feature_not_supported\n+feature_not_supported(std::string const &err, std::string const &Q=\"\", char\n+const sqlstate[]=nullptr)\n+Definition except.hxx:367\n+pqxx::data_exception\n+Error in data provided to SQL statement.\n+Definition except.hxx:377\n+pqxx::data_exception::data_exception\n+data_exception(std::string const &err, std::string const &Q=\"\", char const\n+sqlstate[]=nullptr)\n+Definition except.hxx:386\n+pqxx::integrity_constraint_violation\n+Definition except.hxx:395\n+pqxx::integrity_constraint_violation::integrity_constraint_violation\n+integrity_constraint_violation(std::string const &err, std::string const &Q=\"\",\n+char const sqlstate[]=nullptr)\n+Definition except.hxx:404\n+pqxx::restrict_violation\n+Definition except.hxx:413\n+pqxx::restrict_violation::restrict_violation\n+restrict_violation(std::string const &err, std::string const &Q=\"\", char const\n+sqlstate[]=nullptr)\n+Definition except.hxx:422\n+pqxx::not_null_violation\n+Definition except.hxx:431\n+pqxx::not_null_violation::not_null_violation\n+not_null_violation(std::string const &err, std::string const &Q=\"\", char const\n+sqlstate[]=nullptr)\n+Definition except.hxx:440\n+pqxx::foreign_key_violation\n+Definition except.hxx:449\n+pqxx::foreign_key_violation::foreign_key_violation\n+foreign_key_violation(std::string const &err, std::string const &Q=\"\", char\n+const sqlstate[]=nullptr)\n+Definition except.hxx:458\n+pqxx::unique_violation\n+Definition except.hxx:467\n+pqxx::unique_violation::unique_violation\n+unique_violation(std::string const &err, std::string const &Q=\"\", char const\n+sqlstate[]=nullptr)\n+Definition except.hxx:476\n+pqxx::check_violation\n+Definition except.hxx:485\n+pqxx::check_violation::check_violation\n+check_violation(std::string const &err, std::string const &Q=\"\", char const\n+sqlstate[]=nullptr)\n+Definition except.hxx:494\n+pqxx::invalid_cursor_state\n+Definition except.hxx:503\n+pqxx::invalid_cursor_state::invalid_cursor_state\n+invalid_cursor_state(std::string const &err, std::string const &Q=\"\", char\n+const sqlstate[]=nullptr)\n+Definition except.hxx:512\n+pqxx::invalid_sql_statement_name\n+Definition except.hxx:521\n+pqxx::invalid_sql_statement_name::invalid_sql_statement_name\n+invalid_sql_statement_name(std::string const &err, std::string const &Q=\"\",\n+char const sqlstate[]=nullptr)\n+Definition except.hxx:530\n+pqxx::invalid_cursor_name\n+Definition except.hxx:539\n+pqxx::invalid_cursor_name::invalid_cursor_name\n+invalid_cursor_name(std::string const &err, std::string const &Q=\"\", char const\n+sqlstate[]=nullptr)\n+Definition except.hxx:548\n+pqxx::syntax_error\n+Definition except.hxx:557\n+pqxx::syntax_error::syntax_error\n+syntax_error(std::string const &err, std::string const &Q=\"\", char const\n+sqlstate[]=nullptr, int pos=-1)\n+Definition except.hxx:569\n+pqxx::syntax_error::error_position\n+int const error_position\n+Approximate position in string where error occurred, or -1 if unknown.\n+Definition except.hxx:559\n+pqxx::undefined_column\n+Definition except.hxx:578\n+pqxx::undefined_column::undefined_column\n+undefined_column(std::string const &err, std::string const &Q=\"\", char const\n+sqlstate[]=nullptr)\n+Definition except.hxx:588\n+pqxx::undefined_function\n+Definition except.hxx:597\n+pqxx::undefined_function::undefined_function\n+undefined_function(std::string const &err, std::string const &Q=\"\", char const\n+sqlstate[]=nullptr)\n+Definition except.hxx:607\n+pqxx::undefined_table\n+Definition except.hxx:616\n+pqxx::undefined_table::undefined_table\n+undefined_table(std::string const &err, std::string const &Q=\"\", char const\n+sqlstate[]=nullptr)\n+Definition except.hxx:626\n+pqxx::insufficient_privilege\n+Definition except.hxx:635\n+pqxx::insufficient_privilege::insufficient_privilege\n+insufficient_privilege(std::string const &err, std::string const &Q=\"\", char\n+const sqlstate[]=nullptr)\n+Definition except.hxx:644\n+pqxx::insufficient_resources\n+Resource shortage on the server.\n+Definition except.hxx:654\n+pqxx::insufficient_resources::insufficient_resources\n+insufficient_resources(std::string const &err, std::string const &Q=\"\", char\n+const sqlstate[]=nullptr)\n+Definition except.hxx:663\n+pqxx::disk_full\n+Definition except.hxx:672\n+pqxx::disk_full::disk_full\n+disk_full(std::string const &err, std::string const &Q=\"\", char const sqlstate\n+[]=nullptr)\n+Definition except.hxx:681\n+pqxx::out_of_memory\n+Definition except.hxx:690\n+pqxx::out_of_memory::out_of_memory\n+out_of_memory(std::string const &err, std::string const &Q=\"\", char const\n+sqlstate[]=nullptr)\n+Definition except.hxx:699\n+pqxx::too_many_connections\n+Definition except.hxx:708\n+pqxx::too_many_connections::too_many_connections\n+too_many_connections(std::string const &err)\n+Definition except.hxx:716\n+pqxx::plpgsql_error\n+PL/pgSQL error.\n+Definition except.hxx:726\n+pqxx::plpgsql_error::plpgsql_error\n+plpgsql_error(std::string const &err, std::string const &Q=\"\", char const\n+sqlstate[]=nullptr)\n+Definition except.hxx:735\n+pqxx::plpgsql_raise\n+Exception raised in PL/pgSQL procedure.\n+Definition except.hxx:745\n+pqxx::plpgsql_raise::plpgsql_raise\n+plpgsql_raise(std::string const &err, std::string const &Q=\"\", char const\n+sqlstate[]=nullptr)\n+Definition except.hxx:754\n+pqxx::plpgsql_no_data_found\n+Definition except.hxx:763\n+pqxx::plpgsql_no_data_found::plpgsql_no_data_found\n+plpgsql_no_data_found(std::string const &err, std::string const &Q=\"\", char\n+const sqlstate[]=nullptr)\n+Definition except.hxx:772\n+pqxx::plpgsql_too_many_rows\n+Definition except.hxx:781\n+pqxx::plpgsql_too_many_rows::plpgsql_too_many_rows\n+plpgsql_too_many_rows(std::string const &err, std::string const &Q=\"\", char\n+const sqlstate[]=nullptr)\n+Definition except.hxx:790\n * include\n * pqxx\n- * config-public-compiler.h\n+ * except.hxx\n * Generated by [doxygen] 1.9.8\n"}]}, {"source1": "./usr/share/doc/libpqxx-doc/html/a00050_source.html", "source2": "./usr/share/doc/libpqxx-doc/html/a00050_source.html", "unified_diff": "@@ -1,15 +1,15 @@\n \n \n \n \n \n \n \n-libpqxx: pipeline.hxx Source File\n+libpqxx: config-public-compiler.h Source File\n \n \n \n \n \n \n \n@@ -60,199 +60,27 @@\n \n
\n
\n-
pipeline.hxx
\n+
config-public-compiler.h
\n
\n
\n-
1/* Definition of the pqxx::pipeline class.
\n-
2 *
\n-
3 * Throughput-optimized mechanism for executing queries.
\n-
4 *
\n-
5 * DO NOT INCLUDE THIS FILE DIRECTLY; include pqxx/pipeline instead.
\n-
6 *
\n-
7 * Copyright (c) 2000-2023, Jeroen T. Vermeulen.
\n-
8 *
\n-
9 * See COPYING for copyright license. If you did not receive a file called
\n-
10 * COPYING with this source code, please notify the distributor of this
\n-
11 * mistake, or contact the author.
\n-
12 */
\n-
13#ifndef PQXX_H_PIPELINE
\n-
14#define PQXX_H_PIPELINE
\n-
15
\n-
16#if !defined(PQXX_HEADER_PRE)
\n-
17# error "Include libpqxx headers as <pqxx/header>, not <pqxx/header.hxx>."
\n-
18#endif
\n-
19
\n-
20#include <limits>
\n-
21#include <map>
\n-
22#include <string>
\n-
23
\n-
24#include "pqxx/transaction_base.hxx"
\n-
25
\n-
26
\n-
27namespace pqxx
\n-
28{
\n-
29// TODO: libpq 14 introduced a similar "pipeline mode." Can we use that?
\n-
30
\n-
32
\n-
\n-
50class PQXX_LIBEXPORT pipeline : public transaction_focus
\n-
51{
\n-
52public:
\n-
54 using query_id = long;
\n-
55
\n-
56 pipeline(pipeline const &) = delete;
\n-
57 pipeline &operator=(pipeline const &) = delete;
\n-
58 pipeline(pipeline &&) = delete;
\n-\n-
60
\n-
61
\n-
\n-
63 explicit pipeline(transaction_base &t) : transaction_focus{t, s_classname}
\n-
64 {
\n-
65 init();
\n-
66 }
\n-
\n-
\n-
68 pipeline(transaction_base &t, std::string_view tname) :
\n-
69 transaction_focus{t, s_classname, tname}
\n-
70 {
\n-
71 init();
\n-
72 }
\n-
\n-
73
\n-
75 ~pipeline() noexcept;
\n-
76
\n-
78
\n-
84 query_id insert(std::string_view) &;
\n-
85
\n-
87
\n-
93 void complete();
\n-
94
\n-
96
\n-
105 void flush();
\n-
106
\n-
108
\n-
116 void cancel();
\n-
117
\n-
119 [[nodiscard]] bool is_finished(query_id) const;
\n-
120
\n-
122
\n-
\n-
128 result retrieve(query_id qid)
\n-
129 {
\n-
130 return retrieve(m_queries.find(qid)).second;
\n-
131 }
\n-
\n-
132
\n-
134
\n-
135 std::pair<query_id, result> retrieve();
\n-
136
\n-
137 [[nodiscard]] bool empty() const noexcept { return std::empty(m_queries); }
\n-
138
\n-
141
\n-
152 int retain(int retain_max = 2) &;
\n-
153
\n-
154
\n-
156 void resume() &;
\n-
157
\n-
158private:
\n-
159 struct PQXX_PRIVATE Query
\n-
160 {
\n-
161 explicit Query(std::string_view q) :
\n-
162 query{std::make_shared<std::string>(q)}
\n-
163 {}
\n-
164
\n-
165 std::shared_ptr<std::string> query;
\n-
166 result res;
\n-
167 };
\n-
168
\n-
169 using QueryMap = std::map<query_id, Query>;
\n-
170
\n-
171 void init();
\n-
172 void attach();
\n-
173 void detach();
\n-
174
\n-
176 static constexpr query_id qid_limit() noexcept
\n-
177 {
\n-
178 // Parenthesise this to work around an eternal Visual C++ problem:
\n-
179 // Without the extra parentheses, unless NOMINMAX is defined, the
\n-
180 // preprocessor will mistake this "max" for its annoying built-in macro
\n-
181 // of the same name.
\n-
182 return (std::numeric_limits<query_id>::max)();
\n-
183 }
\n-
184
\n-
186 PQXX_PRIVATE query_id generate_id();
\n-
187
\n-
188 bool have_pending() const noexcept
\n-
189 {
\n-
190 return m_issuedrange.second != m_issuedrange.first;
\n-
191 }
\n-
192
\n-
193 PQXX_PRIVATE void issue();
\n-
194
\n-
196 void set_error_at(query_id qid) noexcept
\n-
197 {
\n-
198 PQXX_UNLIKELY
\n-
199 if (qid < m_error)
\n-
200 m_error = qid;
\n-
201 }
\n-
202
\n-
204 [[noreturn]] PQXX_PRIVATE void internal_error(std::string const &err);
\n-
205
\n-
206 PQXX_PRIVATE bool obtain_result(bool expect_none = false);
\n-
207
\n-
208 PQXX_PRIVATE void obtain_dummy();
\n-
209 PQXX_PRIVATE void get_further_available_results();
\n-
210 PQXX_PRIVATE void check_end_results();
\n-
211
\n-
213 PQXX_PRIVATE void receive_if_available();
\n-
214
\n-
216 PQXX_PRIVATE void receive(pipeline::QueryMap::const_iterator stop);
\n-
217 std::pair<pipeline::query_id, result> retrieve(pipeline::QueryMap::iterator);
\n-
218
\n-
219 QueryMap m_queries;
\n-
220 std::pair<QueryMap::iterator, QueryMap::iterator> m_issuedrange;
\n-
221 int m_retain = 0;
\n-
222 int m_num_waiting = 0;
\n-
223 query_id m_q_id = 0;
\n-
224
\n-
226 bool m_dummy_pending = false;
\n-
227
\n-
229 query_id m_error = qid_limit();
\n-
230
\n-
232
\n-
235 internal::encoding_group m_encoding;
\n-
236
\n-
237 static constexpr std::string_view s_classname{"pipeline"};
\n-
238};
\n-
\n-
239} // namespace pqxx
\n-
240#endif
\n-
The home of all libpqxx classes, functions, templates, etc.
Definition array.hxx:33
\n-
Processes several queries in FIFO manner, optimized for high throughput.
Definition pipeline.hxx:51
\n-
pipeline(transaction_base &t)
Start a pipeline.
Definition pipeline.hxx:63
\n-
pipeline & operator=(pipeline &&)=delete
\n-
bool empty() const noexcept
Definition pipeline.hxx:137
\n-
pipeline & operator=(pipeline const &)=delete
\n-
pipeline(transaction_base &t, std::string_view tname)
Start a pipeline. Assign it a name, for more helpful error messages.
Definition pipeline.hxx:68
\n-
pipeline(pipeline &&)=delete
\n-
pipeline(pipeline const &)=delete
\n-
long query_id
Identifying numbers for queries.
Definition pipeline.hxx:54
\n-
Result set containing data returned by a query or command.
Definition result.hxx:73
\n-
Interface definition (and common code) for "transaction" classes.
Definition transaction_base.hxx:88
\n-
Base class for things that monopolise a transaction's attention.
Definition transaction_focus.hxx:29
\n+
1/* Automatically generated from config.h: public/compiler config. */
\n+
2
\n+
3#define PQXX_HAVE_GCC_PURE 1
\n+
4#define PQXX_HAVE_GCC_VISIBILITY 1
\n+
5#define PQXX_HAVE_PATH 1
\n+
6#define PQXX_HAVE_STRERROR_R 1
\n
\n
\n \n
\n \n
\n \n \n", "details": [{"source1": "html2text {}", "source2": "html2text {}", "unified_diff": "@@ -1,208 +1,18 @@\n \n \n \n \n \n libpqxx\u00a07.8.1\n \n-pipeline.hxx\n- 1/* Definition of the pqxx::pipeline class.\n- 2 *\n- 3 * Throughput-optimized mechanism for executing queries.\n- 4 *\n- 5 * DO NOT INCLUDE THIS FILE DIRECTLY; include pqxx/pipeline instead.\n- 6 *\n- 7 * Copyright (c) 2000-2023, Jeroen T. Vermeulen.\n- 8 *\n- 9 * See COPYING for copyright license. If you did not receive a file called\n- 10 * COPYING with this source code, please notify the distributor of this\n- 11 * mistake, or contact the author.\n- 12 */\n- 13#ifndef PQXX_H_PIPELINE\n- 14#define PQXX_H_PIPELINE\n- 15\n- 16#if !defined(PQXX_HEADER_PRE)\n- 17# error \"Include libpqxx headers as , not .\"\n- 18#endif\n- 19\n- 20#include \n- 21#include \n- 22#include \n- 23\n- 24#include \"pqxx/transaction_base.hxx\"\n- 25\n- 26\n- 27namespace pqxx\n- 28{\n- 29// TODO: libpq 14 introduced a similar \"pipeline mode.\" Can we use that?\n- 30\n- 32\n-50class PQXX_LIBEXPORT pipeline : public transaction_focus\n- 51{\n- 52public:\n-54 using query_id = long;\n- 55\n-56 pipeline(pipeline const &) = delete;\n-57 pipeline &operator=(pipeline const &) = delete;\n-58 pipeline(pipeline &&) = delete;\n-59 pipeline &operator=(pipeline &&) = delete;\n- 60\n- 61\n-63 explicit pipeline(transaction_base &t) : transaction_focus{t, s_classname}\n- 64 {\n- 65 init();\n- 66 }\n-68 pipeline(transaction_base &t, std::string_view tname) :\n- 69 transaction_focus{t, s_classname, tname}\n- 70 {\n- 71 init();\n- 72 }\n- 73\n- 75 ~pipeline() noexcept;\n- 76\n- 78\n- 84 query_id insert(std::string_view) &;\n- 85\n- 87\n- 93 void complete();\n- 94\n- 96\n- 105 void flush();\n- 106\n- 108\n- 116 void cancel();\n- 117\n- 119 [[nodiscard]] bool is_finished(query_id) const;\n- 120\n- 122\n-128 result retrieve(query_id qid)\n- 129 {\n- 130 return retrieve(m_queries.find(qid)).second;\n- 131 }\n- 132\n- 134\n- 135 std::pair retrieve();\n- 136\n-137 [[nodiscard]] bool empty() const noexcept { return std::empty(m_queries); }\n- 138\n- 141\n- 152 int retain(int retain_max = 2) &;\n- 153\n- 154\n- 156 void resume() &;\n- 157\n- 158private:\n- 159 struct PQXX_PRIVATE Query\n- 160 {\n- 161 explicit Query(std::string_view q) :\n- 162 query{std::make_shared(q)}\n- 163 {}\n- 164\n- 165 std::shared_ptr query;\n- 166 result res;\n- 167 };\n- 168\n- 169 using QueryMap = std::map;\n- 170\n- 171 void init();\n- 172 void attach();\n- 173 void detach();\n- 174\n- 176 static constexpr query_id qid_limit() noexcept\n- 177 {\n- 178 // Parenthesise this to work around an eternal Visual C++ problem:\n- 179 // Without the extra parentheses, unless NOMINMAX is defined, the\n- 180 // preprocessor will mistake this \"max\" for its annoying built-in macro\n- 181 // of the same name.\n- 182 return (std::numeric_limits::max)();\n- 183 }\n- 184\n- 186 PQXX_PRIVATE query_id generate_id();\n- 187\n- 188 bool have_pending() const noexcept\n- 189 {\n- 190 return m_issuedrange.second != m_issuedrange.first;\n- 191 }\n- 192\n- 193 PQXX_PRIVATE void issue();\n- 194\n- 196 void set_error_at(query_id qid) noexcept\n- 197 {\n- 198 PQXX_UNLIKELY\n- 199 if (qid < m_error)\n- 200 m_error = qid;\n- 201 }\n- 202\n- 204 [[noreturn]] PQXX_PRIVATE void internal_error(std::string const &err);\n- 205\n- 206 PQXX_PRIVATE bool obtain_result(bool expect_none = false);\n- 207\n- 208 PQXX_PRIVATE void obtain_dummy();\n- 209 PQXX_PRIVATE void get_further_available_results();\n- 210 PQXX_PRIVATE void check_end_results();\n- 211\n- 213 PQXX_PRIVATE void receive_if_available();\n- 214\n- 216 PQXX_PRIVATE void receive(pipeline::QueryMap::const_iterator stop);\n- 217 std::pair retrieve(pipeline::QueryMap::\n-iterator);\n- 218\n- 219 QueryMap m_queries;\n- 220 std::pair m_issuedrange;\n- 221 int m_retain = 0;\n- 222 int m_num_waiting = 0;\n- 223 query_id m_q_id = 0;\n- 224\n- 226 bool m_dummy_pending = false;\n- 227\n- 229 query_id m_error = qid_limit();\n- 230\n- 232\n- 235 internal::encoding_group m_encoding;\n- 236\n- 237 static constexpr std::string_view s_classname{\"pipeline\"};\n- 238};\n- 239} // namespace pqxx\n- 240#endif\n-pqxx\n-The home of all libpqxx classes, functions, templates, etc.\n-Definition array.hxx:33\n-pqxx::pipeline\n-Processes several queries in FIFO manner, optimized for high throughput.\n-Definition pipeline.hxx:51\n-pqxx::pipeline::pipeline\n-pipeline(transaction_base &t)\n-Start a pipeline.\n-Definition pipeline.hxx:63\n-pqxx::pipeline::operator=\n-pipeline & operator=(pipeline &&)=delete\n-pqxx::pipeline::empty\n-bool empty() const noexcept\n-Definition pipeline.hxx:137\n-pqxx::pipeline::operator=\n-pipeline & operator=(pipeline const &)=delete\n-pqxx::pipeline::pipeline\n-pipeline(transaction_base &t, std::string_view tname)\n-Start a pipeline. Assign it a name, for more helpful error messages.\n-Definition pipeline.hxx:68\n-pqxx::pipeline::pipeline\n-pipeline(pipeline &&)=delete\n-pqxx::pipeline::pipeline\n-pipeline(pipeline const &)=delete\n-pqxx::pipeline::query_id\n-long query_id\n-Identifying numbers for queries.\n-Definition pipeline.hxx:54\n-pqxx::result\n-Result set containing data returned by a query or command.\n-Definition result.hxx:73\n-pqxx::transaction_base\n-Interface definition (and common code) for \"transaction\" classes.\n-Definition transaction_base.hxx:88\n-pqxx::transaction_focus\n-Base class for things that monopolise a transaction's attention.\n-Definition transaction_focus.hxx:29\n+config-public-compiler.h\n+ 1/* Automatically generated from config.h: public/compiler config. */\n+ 2\n+ 3#define PQXX_HAVE_GCC_PURE 1\n+ 4#define PQXX_HAVE_GCC_VISIBILITY 1\n+ 5#define PQXX_HAVE_PATH 1\n+ 6#define PQXX_HAVE_STRERROR_R 1\n * include\n * pqxx\n- * pipeline.hxx\n+ * config-public-compiler.h\n * Generated by [doxygen] 1.9.8\n"}]}, {"source1": "./usr/share/doc/libpqxx-doc/html/a00053_source.html", "source2": "./usr/share/doc/libpqxx-doc/html/a00053_source.html", "unified_diff": "@@ -1,15 +1,15 @@\n \n \n \n \n \n \n \n-libpqxx: config-public-autotools.h Source File\n+libpqxx: subtransaction.hxx Source File\n \n \n \n \n \n \n \n@@ -60,23 +60,71 @@\n \n
\n
\n-
config-public-autotools.h
\n+
subtransaction.hxx
\n
\n
\n-
1/* Automatically generated from config.h: public/autotools config. */
\n-
2
\n+
1/* Definition of the pqxx::subtransaction class.
\n+
2 *
\n+
3 * pqxx::subtransaction is a nested transaction, i.e. one within a transaction.
\n+
4 *
\n+
5 * DO NOT INCLUDE THIS FILE DIRECTLY; include pqxx/subtransaction instead.
\n+
6 *
\n+
7 * Copyright (c) 2000-2023, Jeroen T. Vermeulen.
\n+
8 *
\n+
9 * See COPYING for copyright license. If you did not receive a file called
\n+
10 * COPYING with this source code, please notify the distributor of this
\n+
11 * mistake, or contact the author.
\n+
12 */
\n+
13#ifndef PQXX_H_SUBTRANSACTION
\n+
14#define PQXX_H_SUBTRANSACTION
\n+
15
\n+
16#if !defined(PQXX_HEADER_PRE)
\n+
17# error "Include libpqxx headers as <pqxx/header>, not <pqxx/header.hxx>."
\n+
18#endif
\n+
19
\n+
20#include "pqxx/dbtransaction.hxx"
\n+
21
\n+
22namespace pqxx
\n+
23{
\n+
28
\n+
\n+
76class PQXX_LIBEXPORT subtransaction : public transaction_focus,
\n+
77 public dbtransaction
\n+
78{
\n+
79public:
\n+
81 explicit subtransaction(dbtransaction &t, std::string_view tname = ""sv);
\n+
82
\n+
84 explicit subtransaction(subtransaction &t, std::string_view name = ""sv);
\n+
85
\n+
86 virtual ~subtransaction() noexcept override;
\n+
87
\n+
88private:
\n+
89 std::string quoted_name() const
\n+
90 {
\n+
91 return quote_name(transaction_focus::name());
\n+
92 }
\n+
93 virtual void do_commit() override;
\n+
94};
\n+
\n+
95} // namespace pqxx
\n+
96#endif
\n+
The home of all libpqxx classes, functions, templates, etc.
Definition array.hxx:33
\n+
Abstract transaction base class: bracket transactions on the database.
Definition dbtransaction.hxx:54
\n+
"Transaction" nested within another transaction
Definition subtransaction.hxx:78
\n+
Base class for things that monopolise a transaction's attention.
Definition transaction_focus.hxx:29
\n+
std::string_view name() const &noexcept
Name for this object, if the caller passed one; empty string otherwise.
Definition transaction_focus.hxx:56
\n
\n
\n \n
\n \n
\n \n \n", "details": [{"source1": "html2text {}", "source2": "html2text {}", "unified_diff": "@@ -1,14 +1,72 @@\n \n \n \n \n \n libpqxx\u00a07.8.1\n \n-config-public-autotools.h\n- 1/* Automatically generated from config.h: public/autotools config. */\n- 2\n+subtransaction.hxx\n+ 1/* Definition of the pqxx::subtransaction class.\n+ 2 *\n+ 3 * pqxx::subtransaction is a nested transaction, i.e. one within a\n+transaction.\n+ 4 *\n+ 5 * DO NOT INCLUDE THIS FILE DIRECTLY; include pqxx/subtransaction instead.\n+ 6 *\n+ 7 * Copyright (c) 2000-2023, Jeroen T. Vermeulen.\n+ 8 *\n+ 9 * See COPYING for copyright license. If you did not receive a file called\n+ 10 * COPYING with this source code, please notify the distributor of this\n+ 11 * mistake, or contact the author.\n+ 12 */\n+ 13#ifndef PQXX_H_SUBTRANSACTION\n+ 14#define PQXX_H_SUBTRANSACTION\n+ 15\n+ 16#if !defined(PQXX_HEADER_PRE)\n+ 17# error \"Include libpqxx headers as , not .\"\n+ 18#endif\n+ 19\n+ 20#include \"pqxx/dbtransaction.hxx\"\n+ 21\n+ 22namespace pqxx\n+ 23{\n+ 28\n+76class PQXX_LIBEXPORT subtransaction : public transaction_focus,\n+ 77 public dbtransaction\n+ 78{\n+ 79public:\n+ 81 explicit subtransaction(dbtransaction &t, std::string_view tname = \"\"sv);\n+ 82\n+ 84 explicit subtransaction(subtransaction &t, std::string_view name = \"\"sv);\n+ 85\n+ 86 virtual ~subtransaction() noexcept override;\n+ 87\n+ 88private:\n+ 89 std::string quoted_name() const\n+ 90 {\n+ 91 return quote_name(transaction_focus::name());\n+ 92 }\n+ 93 virtual void do_commit() override;\n+ 94};\n+ 95} // namespace pqxx\n+ 96#endif\n+pqxx\n+The home of all libpqxx classes, functions, templates, etc.\n+Definition array.hxx:33\n+pqxx::dbtransaction\n+Abstract transaction base class: bracket transactions on the database.\n+Definition dbtransaction.hxx:54\n+pqxx::subtransaction\n+\"Transaction\" nested within another transaction\n+Definition subtransaction.hxx:78\n+pqxx::transaction_focus\n+Base class for things that monopolise a transaction's attention.\n+Definition transaction_focus.hxx:29\n+pqxx::transaction_focus::name\n+std::string_view name() const &noexcept\n+Name for this object, if the caller passed one; empty string otherwise.\n+Definition transaction_focus.hxx:56\n * include\n * pqxx\n- * config-public-autotools.h\n+ * subtransaction.hxx\n * Generated by [doxygen] 1.9.8\n"}]}, {"source1": "./usr/share/doc/libpqxx-doc/html/a00056_source.html", "source2": "./usr/share/doc/libpqxx-doc/html/a00056_source.html", "unified_diff": "@@ -1,15 +1,15 @@\n \n \n \n \n \n \n \n-libpqxx: cursor.hxx Source File\n+libpqxx: prepared_statement.hxx Source File\n \n \n \n \n \n \n \n@@ -60,373 +60,24 @@\n \n
\n
\n-
cursor.hxx
\n+
prepared_statement.hxx
\n
\n
\n-
1/* Definition of the iterator/container-style cursor classes.
\n-
2 *
\n-
3 * C++-style wrappers for SQL cursors.
\n-
4 *
\n-
5 * DO NOT INCLUDE THIS FILE DIRECTLY; include pqxx/cursor instead.
\n-
6 *
\n-
7 * Copyright (c) 2000-2023, Jeroen T. Vermeulen.
\n-
8 *
\n-
9 * See COPYING for copyright license. If you did not receive a file called
\n-
10 * COPYING with this source code, please notify the distributor of this
\n-
11 * mistake, or contact the author.
\n-
12 */
\n-
13#ifndef PQXX_H_CURSOR
\n-
14#define PQXX_H_CURSOR
\n-
15
\n-
16#if !defined(PQXX_HEADER_PRE)
\n-
17# error "Include libpqxx headers as <pqxx/header>, not <pqxx/header.hxx>."
\n-
18#endif
\n-
19
\n-
20#include <limits>
\n-
21#include <stdexcept>
\n-
22
\n-
23#include "pqxx/result.hxx"
\n-
24#include "pqxx/transaction_base.hxx"
\n-
25
\n-
26
\n-
27namespace pqxx
\n-
28{
\n-
30
\n-
\n-
41class PQXX_LIBEXPORT cursor_base
\n-
42{
\n-
43public:
\n-\n-\n-
46
\n-
48
\n-
\n-\n-
52 {
\n-\n-
56 random_access
\n-
57 };
\n-
\n-
58
\n-
60
\n-
\n-\n-
64 {
\n-\n-
68 update
\n-
69 };
\n-
\n-
70
\n-
72
\n-
\n-\n-
88 {
\n-\n-
92 loose
\n-
93 };
\n-
\n-
94
\n-
95 cursor_base() = delete;
\n-
96 cursor_base(cursor_base const &) = delete;
\n-
97 cursor_base &operator=(cursor_base const &) = delete;
\n-
98
\n-
103
\n-
105
\n-
\n-
108 [[nodiscard]] static constexpr difference_type all() noexcept
\n-
109 {
\n-
110 return (std::numeric_limits<int>::max)() - 1;
\n-
111 }
\n-
\n-
112
\n-
114
\n-
116 [[nodiscard]] static constexpr difference_type next() noexcept { return 1; }
\n-
117
\n-
119
\n-
\n-
121 [[nodiscard]] static constexpr difference_type prior() noexcept
\n-
122 {
\n-
123 return -1;
\n-
124 }
\n-
\n-
125
\n-
127
\n-
\n-
129 [[nodiscard]] static constexpr difference_type backward_all() noexcept
\n-
130 {
\n-
131 return (std::numeric_limits<int>::min)() + 1;
\n-
132 }
\n-
\n-
133
\n-
135
\n-
137
\n-
\n-
142 [[nodiscard]] constexpr std::string const &name() const noexcept
\n-
143 {
\n-
144 return m_name;
\n-
145 }
\n-
\n-
146
\n-
147protected:
\n-
148 cursor_base(connection &, std::string_view Name, bool embellish_name = true);
\n-
149
\n-
150 std::string const m_name;
\n-
151};
\n-
\n-
152} // namespace pqxx
\n-
153
\n-
154
\n-
155#include <pqxx/internal/sql_cursor.hxx>
\n-
156
\n-
157
\n-
158namespace pqxx
\n-
159{
\n-
161
\n-
167template<cursor_base::update_policy up, cursor_base::ownership_policy op>
\n-
\n-\n-
169{
\n-
170public:
\n-\n-\n-
173
\n-
175
\n-
\n-\n-
184 transaction_base &tx, std::string_view query, std::string_view cname,
\n-
185 bool hold) :
\n-
186 m_cur{tx, query, cname, cursor_base::random_access, up, op, hold}
\n-
187 {}
\n-
\n-
188
\n-
190
\n-
\n-
196 stateless_cursor(transaction_base &tx, std::string_view adopted_cursor) :
\n-
197 m_cur{tx, adopted_cursor, op}
\n-
198 {
\n-
199 // Put cursor in known position
\n-
200 m_cur.move(cursor_base::backward_all());
\n-
201 }
\n-
\n-
202
\n-
204
\n-
209 void close() noexcept { m_cur.close(); }
\n-
210
\n-
212
\n-
\n-
215 [[nodiscard]] size_type size()
\n-
216 {
\n-
217 return internal::obtain_stateless_cursor_size(m_cur);
\n-
218 }
\n-
\n-
219
\n-
221
\n-
\n-\n-
233 {
\n-
234 return internal::stateless_cursor_retrieve(
\n-
235 m_cur, result::difference_type(size()), begin_pos, end_pos);
\n-
236 }
\n-
\n-
237
\n-
\n-
239 [[nodiscard]] constexpr std::string const &name() const noexcept
\n-
240 {
\n-
241 return m_cur.name();
\n-
242 }
\n-
\n-
243
\n-
244private:
\n-
245 internal::sql_cursor m_cur;
\n-
246};
\n-
\n-
247
\n-
248
\n-
249class icursor_iterator;
\n-
250} // namespace pqxx
\n-
251
\n-
252
\n-
253namespace pqxx::internal::gate
\n-
254{
\n-
255class icursor_iterator_icursorstream;
\n-
256class icursorstream_icursor_iterator;
\n-
257} // namespace pqxx::internal::gate
\n-
258
\n-
259
\n-
260namespace pqxx
\n-
261{
\n-
263
\n-
278class PQXX_LIBEXPORT icursorstream
\n-
279{
\n-
280public:
\n-
281 using size_type = cursor_base::size_type;
\n-
282 using difference_type = cursor_base::difference_type;
\n-
283
\n-
285
\n-
296 icursorstream(
\n-
297 transaction_base &context, std::string_view query,
\n-
298 std::string_view basename, difference_type sstride = 1);
\n-
299
\n-
301
\n-
325 icursorstream(
\n-
326 transaction_base &context, field const &cname, difference_type sstride = 1,
\n-\n-
328
\n-
330 constexpr operator bool() const &noexcept { return not m_done; }
\n-
331
\n-
333
\n-
341 icursorstream &get(result &res)
\n-
342 {
\n-
343 res = fetchblock();
\n-
344 return *this;
\n-
345 }
\n-
347
\n-
355 icursorstream &operator>>(result &res) { return get(res); }
\n-
356
\n-
358
\n-
364 icursorstream &ignore(std::streamsize n = 1) &;
\n-
365
\n-
367
\n-
370 void set_stride(difference_type stride) &;
\n-
371 [[nodiscard]] constexpr difference_type stride() const noexcept
\n-
372 {
\n-
373 return m_stride;
\n-
374 }
\n-
375
\n-
376private:
\n-
377 result fetchblock();
\n-
378
\n-
379 friend class internal::gate::icursorstream_icursor_iterator;
\n-
380 size_type forward(size_type n = 1);
\n-
381 void insert_iterator(icursor_iterator *) noexcept;
\n-
382 void remove_iterator(icursor_iterator *) const noexcept;
\n-
383
\n-
384 void service_iterators(difference_type);
\n-
385
\n-
386 internal::sql_cursor m_cur;
\n-
387
\n-
388 difference_type m_stride;
\n-
389 difference_type m_realpos, m_reqpos;
\n-
390
\n-
391 mutable icursor_iterator *m_iterators;
\n-
392
\n-
393 bool m_done;
\n-
394};
\n-
395
\n-
396
\n-
398
\n-
424class PQXX_LIBEXPORT icursor_iterator
\n-
425{
\n-
426public:
\n-
427 using iterator_category = std::input_iterator_tag;
\n-
428 using value_type = result;
\n-
429 using pointer = result const *;
\n-
430 using reference = result const &;
\n-
431 using istream_type = icursorstream;
\n-
432 using size_type = istream_type::size_type;
\n-
433 using difference_type = istream_type::difference_type;
\n-
434
\n-
435 icursor_iterator() noexcept;
\n-
436 explicit icursor_iterator(istream_type &) noexcept;
\n-
437 icursor_iterator(icursor_iterator const &) noexcept;
\n-
438 ~icursor_iterator() noexcept;
\n-
439
\n-
440 result const &operator*() const
\n-
441 {
\n-
442 refresh();
\n-
443 return m_here;
\n-
444 }
\n-
445 result const *operator->() const
\n-
446 {
\n-
447 refresh();
\n-
448 return &m_here;
\n-
449 }
\n-
450 icursor_iterator &operator++();
\n-
451 icursor_iterator operator++(int);
\n-
452 icursor_iterator &operator+=(difference_type);
\n-
453 icursor_iterator &operator=(icursor_iterator const &) noexcept;
\n-
454
\n-
455 [[nodiscard]] bool operator==(icursor_iterator const &rhs) const;
\n-
456 [[nodiscard]] bool operator!=(icursor_iterator const &rhs) const noexcept
\n-
457 {
\n-
458 return not operator==(rhs);
\n-
459 }
\n-
460 [[nodiscard]] bool operator<(icursor_iterator const &rhs) const;
\n-
461 [[nodiscard]] bool operator>(icursor_iterator const &rhs) const
\n-
462 {
\n-
463 return rhs < *this;
\n-
464 }
\n-
465 [[nodiscard]] bool operator<=(icursor_iterator const &rhs) const
\n-
466 {
\n-
467 return not(*this > rhs);
\n-
468 }
\n-
469 [[nodiscard]] bool operator>=(icursor_iterator const &rhs) const
\n-
470 {
\n-
471 return not(*this < rhs);
\n-
472 }
\n-
473
\n-
474private:
\n-
475 void refresh() const;
\n-
476
\n-
477 friend class internal::gate::icursor_iterator_icursorstream;
\n-
478 difference_type pos() const noexcept { return m_pos; }
\n-
479 void fill(result const &);
\n-
480
\n-
481 icursorstream *m_stream{nullptr};
\n-
482 result m_here;
\n-
483 difference_type m_pos;
\n-
484 icursor_iterator *m_prev{nullptr}, *m_next{nullptr};
\n-
485};
\n-
486} // namespace pqxx
\n-
487#endif
\n-
The home of all libpqxx classes, functions, templates, etc.
Definition array.hxx:33
\n-
int result_difference_type
Difference between result sizes.
Definition types.hxx:31
\n-
strip_t< decltype(*std::begin(std::declval< CONTAINER >()))> value_type
The type of a container's elements.
Definition types.hxx:107
\n-
int result_size_type
Number of rows in a result set.
Definition types.hxx:28
\n-
Definition connection.hxx:112
\n-
Connection to a database.
Definition connection.hxx:253
\n-
Common definitions for cursor types.
Definition cursor.hxx:42
\n-
cursor_base & operator=(cursor_base const &)=delete
\n-
constexpr std::string const & name() const noexcept
Name of underlying SQL cursor.
Definition cursor.hxx:142
\n-
result_size_type size_type
Definition cursor.hxx:44
\n-
static constexpr difference_type next() noexcept
Special value: read one row only.
Definition cursor.hxx:116
\n-
cursor_base(cursor_base const &)=delete
\n-
static constexpr difference_type all() noexcept
Special value: read until end.
Definition cursor.hxx:108
\n-
static constexpr difference_type prior() noexcept
Special value: read backwards, one row only.
Definition cursor.hxx:121
\n-
cursor_base()=delete
\n-
access_policy
Cursor access-pattern policy.
Definition cursor.hxx:52
\n-
@ forward_only
Cursor can move forward only.
Definition cursor.hxx:54
\n-
ownership_policy
Cursor destruction policy.
Definition cursor.hxx:88
\n-
@ owned
Destroy SQL cursor when cursor object is closed at end of transaction.
Definition cursor.hxx:90
\n-
update_policy
Cursor update policy.
Definition cursor.hxx:64
\n-
@ read_only
Cursor can be used to read data but not to write.
Definition cursor.hxx:66
\n-
result_difference_type difference_type
Definition cursor.hxx:45
\n-
std::string const m_name
Definition cursor.hxx:150
\n-
static constexpr difference_type backward_all() noexcept
Special value: read backwards from current position back to origin.
Definition cursor.hxx:129
\n-
"Stateless cursor" class: easy API for retrieving parts of result sets
Definition cursor.hxx:169
\n-
constexpr std::string const & name() const noexcept
Return this cursor's name.
Definition cursor.hxx:239
\n-
void close() noexcept
Close this cursor.
Definition cursor.hxx:209
\n-
result_size_type size_type
Definition cursor.hxx:171
\n-
result_difference_type difference_type
Definition cursor.hxx:172
\n-
result retrieve(difference_type begin_pos, difference_type end_pos)
Retrieve rows from begin_pos (inclusive) to end_pos (exclusive)
Definition cursor.hxx:232
\n-
stateless_cursor(transaction_base &tx, std::string_view query, std::string_view cname, bool hold)
Create cursor.
Definition cursor.hxx:183
\n-
size_type size()
Number of rows in cursor's result set.
Definition cursor.hxx:215
\n-
stateless_cursor(transaction_base &tx, std::string_view adopted_cursor)
Adopt an existing scrolling SQL cursor.
Definition cursor.hxx:196
\n-
Result set containing data returned by a query or command.
Definition result.hxx:73
\n-
result_difference_type difference_type
Definition result.hxx:76
\n-
Interface definition (and common code) for "transaction" classes.
Definition transaction_base.hxx:88
\n+
1
\n+
2
\n+
3#include "params.hxx"
\n
\n
\n \n
\n \n
\n \n \n", "details": [{"source1": "html2text {}", "source2": "html2text {}", "unified_diff": "@@ -1,428 +1,15 @@\n \n \n \n \n \n libpqxx\u00a07.8.1\n \n-cursor.hxx\n- 1/* Definition of the iterator/container-style cursor classes.\n- 2 *\n- 3 * C++-style wrappers for SQL cursors.\n- 4 *\n- 5 * DO NOT INCLUDE THIS FILE DIRECTLY; include pqxx/cursor instead.\n- 6 *\n- 7 * Copyright (c) 2000-2023, Jeroen T. Vermeulen.\n- 8 *\n- 9 * See COPYING for copyright license. If you did not receive a file called\n- 10 * COPYING with this source code, please notify the distributor of this\n- 11 * mistake, or contact the author.\n- 12 */\n- 13#ifndef PQXX_H_CURSOR\n- 14#define PQXX_H_CURSOR\n- 15\n- 16#if !defined(PQXX_HEADER_PRE)\n- 17# error \"Include libpqxx headers as , not .\"\n- 18#endif\n- 19\n- 20#include \n- 21#include \n- 22\n- 23#include \"pqxx/result.hxx\"\n- 24#include \"pqxx/transaction_base.hxx\"\n- 25\n- 26\n- 27namespace pqxx\n- 28{\n- 30\n-41class PQXX_LIBEXPORT cursor_base\n- 42{\n- 43public:\n-44 using size_type = result_size_type;\n-45 using difference_type = result_difference_type;\n- 46\n- 48\n-51 enum access_policy\n- 52 {\n-54 forward_only,\n- 56 random_access\n-57 };\n- 58\n- 60\n-63 enum update_policy\n- 64 {\n-66 read_only,\n- 68 update\n-69 };\n- 70\n- 72\n-87 enum ownership_policy\n- 88 {\n-90 owned,\n- 92 loose\n-93 };\n- 94\n-95 cursor_base() = delete;\n-96 cursor_base(cursor_base const &) = delete;\n-97 cursor_base &operator=(cursor_base const &) = delete;\n- 98\n- 103\n- 105\n-108 [[nodiscard]] static constexpr difference_type all() noexcept\n- 109 {\n- 110 return (std::numeric_limits::max)() - 1;\n- 111 }\n- 112\n- 114\n-116 [[nodiscard]] static constexpr difference_type next() noexcept { return 1;\n-}\n- 117\n- 119\n-121 [[nodiscard]] static constexpr difference_type prior() noexcept\n- 122 {\n- 123 return -1;\n- 124 }\n- 125\n- 127\n-129 [[nodiscard]] static constexpr difference_type backward_all() noexcept\n- 130 {\n- 131 return (std::numeric_limits::min)() + 1;\n- 132 }\n- 133\n- 135\n- 137\n-142 [[nodiscard]] constexpr std::string const &name() const noexcept\n- 143 {\n- 144 return m_name;\n- 145 }\n- 146\n- 147protected:\n- 148 cursor_base(connection &, std::string_view Name, bool embellish_name =\n-true);\n- 149\n-150 std::string const m_name;\n- 151};\n- 152} // namespace pqxx\n- 153\n- 154\n- 155#include \n- 156\n- 157\n- 158namespace pqxx\n- 159{\n- 161\n- 167template\n-168class stateless_cursor\n- 169{\n- 170public:\n-171 using size_type = result_size_type;\n-172 using difference_type = result_difference_type;\n- 173\n- 175\n-183 stateless_cursor(\n- 184 transaction_base &tx, std::string_view query, std::string_view cname,\n- 185 bool hold) :\n- 186 m_cur{tx, query, cname, cursor_base::random_access, up, op, hold}\n- 187 {}\n- 188\n- 190\n-196 stateless_cursor(transaction_base &tx, std::string_view adopted_cursor) :\n- 197 m_cur{tx, adopted_cursor, op}\n- 198 {\n- 199 // Put cursor in known position\n- 200 m_cur.move(cursor_base::backward_all());\n- 201 }\n- 202\n- 204\n-209 void close() noexcept { m_cur.close(); }\n- 210\n- 212\n-215 [[nodiscard]] size_type size()\n- 216 {\n- 217 return internal::obtain_stateless_cursor_size(m_cur);\n- 218 }\n- 219\n- 221\n-232 result retrieve(difference_type begin_pos, difference_type end_pos)\n- 233 {\n- 234 return internal::stateless_cursor_retrieve(\n- 235 m_cur, result::difference_type(size()), begin_pos, end_pos);\n- 236 }\n- 237\n-239 [[nodiscard]] constexpr std::string const &name() const noexcept\n- 240 {\n- 241 return m_cur.name();\n- 242 }\n- 243\n- 244private:\n- 245 internal::sql_cursor m_cur;\n- 246};\n- 247\n- 248\n- 249class icursor_iterator;\n- 250} // namespace pqxx\n- 251\n- 252\n- 253namespace pqxx::internal::gate\n- 254{\n- 255class icursor_iterator_icursorstream;\n- 256class icursorstream_icursor_iterator;\n- 257} // namespace pqxx::internal::gate\n- 258\n- 259\n- 260namespace pqxx\n- 261{\n- 263\n- 278class PQXX_LIBEXPORT icursorstream\n- 279{\n- 280public:\n- 281 using size_type = cursor_base::size_type;\n- 282 using difference_type = cursor_base::difference_type;\n- 283\n- 285\n- 296 icursorstream(\n- 297 transaction_base &context, std::string_view query,\n- 298 std::string_view basename, difference_type sstride = 1);\n- 299\n- 301\n- 325 icursorstream(\n- 326 transaction_base &context, field const &cname, difference_type sstride =\n-1,\n- 327 cursor_base::ownership_policy op = cursor_base::owned);\n- 328\n- 330 constexpr operator bool() const &noexcept { return not m_done; }\n- 331\n- 333\n- 341 icursorstream &get(result &res)\n- 342 {\n- 343 res = fetchblock();\n- 344 return *this;\n- 345 }\n- 347\n- 355 icursorstream &operator>>(result &res) { return get(res); }\n- 356\n- 358\n- 364 icursorstream &ignore(std::streamsize n = 1) &;\n- 365\n- 367\n- 370 void set_stride(difference_type stride) &;\n- 371 [[nodiscard]] constexpr difference_type stride() const noexcept\n- 372 {\n- 373 return m_stride;\n- 374 }\n- 375\n- 376private:\n- 377 result fetchblock();\n- 378\n- 379 friend class internal::gate::icursorstream_icursor_iterator;\n- 380 size_type forward(size_type n = 1);\n- 381 void insert_iterator(icursor_iterator *) noexcept;\n- 382 void remove_iterator(icursor_iterator *) const noexcept;\n- 383\n- 384 void service_iterators(difference_type);\n- 385\n- 386 internal::sql_cursor m_cur;\n- 387\n- 388 difference_type m_stride;\n- 389 difference_type m_realpos, m_reqpos;\n- 390\n- 391 mutable icursor_iterator *m_iterators;\n- 392\n- 393 bool m_done;\n- 394};\n- 395\n- 396\n- 398\n- 424class PQXX_LIBEXPORT icursor_iterator\n- 425{\n- 426public:\n- 427 using iterator_category = std::input_iterator_tag;\n- 428 using value_type = result;\n- 429 using pointer = result const *;\n- 430 using reference = result const &;\n- 431 using istream_type = icursorstream;\n- 432 using size_type = istream_type::size_type;\n- 433 using difference_type = istream_type::difference_type;\n- 434\n- 435 icursor_iterator() noexcept;\n- 436 explicit icursor_iterator(istream_type &) noexcept;\n- 437 icursor_iterator(icursor_iterator const &) noexcept;\n- 438 ~icursor_iterator() noexcept;\n- 439\n- 440 result const &operator*() const\n- 441 {\n- 442 refresh();\n- 443 return m_here;\n- 444 }\n- 445 result const *operator->() const\n- 446 {\n- 447 refresh();\n- 448 return &m_here;\n- 449 }\n- 450 icursor_iterator &operator++();\n- 451 icursor_iterator operator++(int);\n- 452 icursor_iterator &operator+=(difference_type);\n- 453 icursor_iterator &operator=(icursor_iterator const &) noexcept;\n- 454\n- 455 [[nodiscard]] bool operator==(icursor_iterator const &rhs) const;\n- 456 [[nodiscard]] bool operator!=(icursor_iterator const &rhs) const noexcept\n- 457 {\n- 458 return not operator==(rhs);\n- 459 }\n- 460 [[nodiscard]] bool operator<(icursor_iterator const &rhs) const;\n- 461 [[nodiscard]] bool operator>(icursor_iterator const &rhs) const\n- 462 {\n- 463 return rhs < *this;\n- 464 }\n- 465 [[nodiscard]] bool operator<=(icursor_iterator const &rhs) const\n- 466 {\n- 467 return not(*this > rhs);\n- 468 }\n- 469 [[nodiscard]] bool operator>=(icursor_iterator const &rhs) const\n- 470 {\n- 471 return not(*this < rhs);\n- 472 }\n- 473\n- 474private:\n- 475 void refresh() const;\n- 476\n- 477 friend class internal::gate::icursor_iterator_icursorstream;\n- 478 difference_type pos() const noexcept { return m_pos; }\n- 479 void fill(result const &);\n- 480\n- 481 icursorstream *m_stream{nullptr};\n- 482 result m_here;\n- 483 difference_type m_pos;\n- 484 icursor_iterator *m_prev{nullptr}, *m_next{nullptr};\n- 485};\n- 486} // namespace pqxx\n- 487#endif\n-pqxx\n-The home of all libpqxx classes, functions, templates, etc.\n-Definition array.hxx:33\n-pqxx::result_difference_type\n-int result_difference_type\n-Difference between result sizes.\n-Definition types.hxx:31\n-pqxx::value_type\n-strip_t< decltype(*std::begin(std::declval< CONTAINER >()))> value_type\n-The type of a container's elements.\n-Definition types.hxx:107\n-pqxx::result_size_type\n-int result_size_type\n-Number of rows in a result set.\n-Definition types.hxx:28\n-pqxx::internal::gate\n-Definition connection.hxx:112\n-pqxx::connection\n-Connection to a database.\n-Definition connection.hxx:253\n-pqxx::cursor_base\n-Common definitions for cursor types.\n-Definition cursor.hxx:42\n-pqxx::cursor_base::operator=\n-cursor_base & operator=(cursor_base const &)=delete\n-pqxx::cursor_base::name\n-constexpr std::string const & name() const noexcept\n-Name of underlying SQL cursor.\n-Definition cursor.hxx:142\n-pqxx::cursor_base::size_type\n-result_size_type size_type\n-Definition cursor.hxx:44\n-pqxx::cursor_base::next\n-static constexpr difference_type next() noexcept\n-Special value: read one row only.\n-Definition cursor.hxx:116\n-pqxx::cursor_base::cursor_base\n-cursor_base(cursor_base const &)=delete\n-pqxx::cursor_base::all\n-static constexpr difference_type all() noexcept\n-Special value: read until end.\n-Definition cursor.hxx:108\n-pqxx::cursor_base::prior\n-static constexpr difference_type prior() noexcept\n-Special value: read backwards, one row only.\n-Definition cursor.hxx:121\n-pqxx::cursor_base::cursor_base\n-cursor_base()=delete\n-pqxx::cursor_base::access_policy\n-access_policy\n-Cursor access-pattern policy.\n-Definition cursor.hxx:52\n-pqxx::cursor_base::forward_only\n-@ forward_only\n-Cursor can move forward only.\n-Definition cursor.hxx:54\n-pqxx::cursor_base::ownership_policy\n-ownership_policy\n-Cursor destruction policy.\n-Definition cursor.hxx:88\n-pqxx::cursor_base::owned\n-@ owned\n-Destroy SQL cursor when cursor object is closed at end of transaction.\n-Definition cursor.hxx:90\n-pqxx::cursor_base::update_policy\n-update_policy\n-Cursor update policy.\n-Definition cursor.hxx:64\n-pqxx::cursor_base::read_only\n-@ read_only\n-Cursor can be used to read data but not to write.\n-Definition cursor.hxx:66\n-pqxx::cursor_base::difference_type\n-result_difference_type difference_type\n-Definition cursor.hxx:45\n-pqxx::cursor_base::m_name\n-std::string const m_name\n-Definition cursor.hxx:150\n-pqxx::cursor_base::backward_all\n-static constexpr difference_type backward_all() noexcept\n-Special value: read backwards from current position back to origin.\n-Definition cursor.hxx:129\n-pqxx::stateless_cursor\n-\"Stateless cursor\" class: easy API for retrieving parts of result sets\n-Definition cursor.hxx:169\n-pqxx::stateless_cursor::name\n-constexpr std::string const & name() const noexcept\n-Return this cursor's name.\n-Definition cursor.hxx:239\n-pqxx::stateless_cursor::close\n-void close() noexcept\n-Close this cursor.\n-Definition cursor.hxx:209\n-pqxx::stateless_cursor::size_type\n-result_size_type size_type\n-Definition cursor.hxx:171\n-pqxx::stateless_cursor::difference_type\n-result_difference_type difference_type\n-Definition cursor.hxx:172\n-pqxx::stateless_cursor::retrieve\n-result retrieve(difference_type begin_pos, difference_type end_pos)\n-Retrieve rows from begin_pos (inclusive) to end_pos (exclusive)\n-Definition cursor.hxx:232\n-pqxx::stateless_cursor::stateless_cursor\n-stateless_cursor(transaction_base &tx, std::string_view query, std::string_view\n-cname, bool hold)\n-Create cursor.\n-Definition cursor.hxx:183\n-pqxx::stateless_cursor::size\n-size_type size()\n-Number of rows in cursor's result set.\n-Definition cursor.hxx:215\n-pqxx::stateless_cursor::stateless_cursor\n-stateless_cursor(transaction_base &tx, std::string_view adopted_cursor)\n-Adopt an existing scrolling SQL cursor.\n-Definition cursor.hxx:196\n-pqxx::result\n-Result set containing data returned by a query or command.\n-Definition result.hxx:73\n-pqxx::result::difference_type\n-result_difference_type difference_type\n-Definition result.hxx:76\n-pqxx::transaction_base\n-Interface definition (and common code) for \"transaction\" classes.\n-Definition transaction_base.hxx:88\n+prepared_statement.hxx\n+ 1\n+ 2\n+ 3#include \"params.hxx\"\n * include\n * pqxx\n- * cursor.hxx\n+ * prepared_statement.hxx\n * Generated by [doxygen] 1.9.8\n"}]}, {"source1": "./usr/share/doc/libpqxx-doc/html/a00059_source.html", "source2": "./usr/share/doc/libpqxx-doc/html/a00059_source.html", "unified_diff": "@@ -1,15 +1,15 @@\n \n \n \n \n \n \n \n-libpqxx: array.hxx Source File\n+libpqxx: row.hxx Source File\n \n \n \n \n \n \n \n@@ -60,519 +60,620 @@\n \n
\n
\n-
array.hxx
\n+
row.hxx
\n
\n
\n-
1/* Handling of SQL arrays.
\n+
1/* Definitions for the pqxx::result class and support classes.
\n
2 *
\n-
3 * DO NOT INCLUDE THIS FILE DIRECTLY; include pqxx/field instead.
\n+
3 * pqxx::result represents the set of result rows from a database query.
\n
4 *
\n-
5 * Copyright (c) 2000-2023, Jeroen T. Vermeulen.
\n+
5 * DO NOT INCLUDE THIS FILE DIRECTLY; include pqxx/result instead.
\n
6 *
\n-
7 * See COPYING for copyright license. If you did not receive a file called
\n-
8 * COPYING with this source code, please notify the distributor of this
\n-
9 * mistake, or contact the author.
\n-
10 */
\n-
11#ifndef PQXX_H_ARRAY
\n-
12#define PQXX_H_ARRAY
\n-
13
\n-
14#if !defined(PQXX_HEADER_PRE)
\n-
15# error "Include libpqxx headers as <pqxx/header>, not <pqxx/header.hxx>."
\n-
16#endif
\n-
17
\n-
18#include <algorithm>
\n-
19#include <cassert>
\n-
20#include <stdexcept>
\n-
21#include <string>
\n-
22#include <type_traits>
\n-
23#include <utility>
\n-
24#include <vector>
\n+
7 * Copyright (c) 2000-2023, Jeroen T. Vermeulen.
\n+
8 *
\n+
9 * See COPYING for copyright license. If you did not receive a file called
\n+
10 * COPYING with this source code, please notify the distributor of this
\n+
11 * mistake, or contact the author.
\n+
12 */
\n+
13#ifndef PQXX_H_ROW
\n+
14#define PQXX_H_ROW
\n+
15
\n+
16#if !defined(PQXX_HEADER_PRE)
\n+
17# error "Include libpqxx headers as <pqxx/header>, not <pqxx/header.hxx>."
\n+
18#endif
\n+
19
\n+
20#include "pqxx/except.hxx"
\n+
21#include "pqxx/field.hxx"
\n+
22#include "pqxx/result.hxx"
\n+
23
\n+
24#include "pqxx/internal/concat.hxx"
\n
25
\n-
26#include "pqxx/connection.hxx"
\n-
27#include "pqxx/internal/array-composite.hxx"
\n-
28#include "pqxx/internal/encoding_group.hxx"
\n-
29#include "pqxx/internal/encodings.hxx"
\n+
26namespace pqxx::internal
\n+
27{
\n+
28template<typename... T> class result_iter;
\n+
29} // namespace pqxx::internal
\n
30
\n
31
\n-
\n-
32namespace pqxx
\n+
32namespace pqxx
\n
33{
\n-
34// TODO: Specialise for string_view/zview, allocate all strings in one buffer.
\n
35
\n-
37
\n-
52template<
\n-
53 typename ELEMENT, std::size_t DIMENSIONS = 1u,
\n-
54 char SEPARATOR = array_separator<ELEMENT>>
\n-
\n-
55class array final
\n-
56{
\n-
57public:
\n-
59
\n-
\n-
68 array(std::string_view data, connection const &conn) :
\n-
69 array{data, pqxx::internal::enc_group(conn.encoding_id())}
\n-
70 {}
\n-
\n-
71
\n-
73
\n-
75 constexpr std::size_t dimensions() noexcept { return DIMENSIONS; }
\n-
76
\n-
78
\n-
\n-
82 std::array<std::size_t, DIMENSIONS> const &sizes() noexcept
\n-
83 {
\n-
84 return m_extents;
\n-
85 }
\n-
\n+
\n+
46class PQXX_LIBEXPORT row
\n+
47{
\n+
48public:
\n+\n+\n+\n+\n+\n+\n+\n+\n+
57
\n+
58 row() noexcept = default;
\n+
59 row(row &&) noexcept = default;
\n+
60 row(row const &) noexcept = default;
\n+
61 row &operator=(row const &) noexcept = default;
\n+
62 row &operator=(row &&) noexcept = default;
\n+
63
\n+
68 [[nodiscard]] PQXX_PURE bool operator==(row const &) const noexcept;
\n+
\n+
69 [[nodiscard]] bool operator!=(row const &rhs) const noexcept
\n+
70 {
\n+
71 return not operator==(rhs);
\n+
72 }
\n+
\n+
74
\n+
75 [[nodiscard]] const_iterator begin() const noexcept;
\n+
76 [[nodiscard]] const_iterator cbegin() const noexcept;
\n+
77 [[nodiscard]] const_iterator end() const noexcept;
\n+
78 [[nodiscard]] const_iterator cend() const noexcept;
\n+
79
\n+
84 [[nodiscard]] reference front() const noexcept;
\n+
85 [[nodiscard]] reference back() const noexcept;
\n
86
\n-
\n-
87 template<typename... INDEX> ELEMENT const &at(INDEX... index) const
\n-
88 {
\n-
89 static_assert(sizeof...(index) == DIMENSIONS);
\n-
90 check_bounds(index...);
\n-
91 return m_elts.at(locate(index...));
\n-
92 }
\n-
\n-
93
\n-
95
\n-
\n-
103 template<typename... INDEX> ELEMENT const &operator[](INDEX... index) const
\n-
104 {
\n-
105 static_assert(sizeof...(index) == DIMENSIONS);
\n-
106 return m_elts[locate(index...)];
\n+
87 [[nodiscard]] const_reverse_row_iterator rbegin() const noexcept;
\n+
88 [[nodiscard]] const_reverse_row_iterator crbegin() const noexcept;
\n+
89 [[nodiscard]] const_reverse_row_iterator rend() const noexcept;
\n+
90 [[nodiscard]] const_reverse_row_iterator crend() const noexcept;
\n+
91
\n+
92 [[nodiscard]] reference operator[](size_type) const noexcept;
\n+
96 [[nodiscard]] reference operator[](zview col_name) const;
\n+
97
\n+
98 reference at(size_type) const;
\n+
102 reference at(zview col_name) const;
\n+
103
\n+
\n+
104 [[nodiscard]] constexpr size_type size() const noexcept
\n+
105 {
\n+
106 return m_end - m_begin;
\n
107 }
\n
\n
108
\n+
109 [[deprecated("Swap iterators, not rows.")]] void swap(row &) noexcept;
\n
110
\n-
115 constexpr auto cbegin() const noexcept { return m_elts.cbegin(); }
\n-
117 constexpr auto cend() const noexcept { return m_elts.cend(); }
\n-
119 constexpr auto crbegin() const noexcept { return m_elts.crbegin(); }
\n-
121 constexpr auto crend() const noexcept { return m_elts.crend(); }
\n-
122
\n-
124
\n-
127 constexpr std::size_t size() const noexcept { return m_elts.size(); }
\n-
128
\n-
130
\n-
\n-
145 constexpr auto ssize() const noexcept
\n-
146 {
\n-
147 return static_cast<std::ptrdiff_t>(size());
\n-
148 }
\n-
\n-
149
\n+
\n+
112 [[nodiscard]] constexpr result::size_type rownumber() const noexcept
\n+
113 {
\n+
114 return m_index;
\n+
115 }
\n+
\n+
116
\n+
122 [[nodiscard]] size_type column_number(zview col_name) const;
\n+
123
\n+
125 [[nodiscard]] oid column_type(size_type) const;
\n+
126
\n+
\n+
128 [[nodiscard]] oid column_type(zview col_name) const
\n+
129 {
\n+
130 return column_type(column_number(col_name));
\n+
131 }
\n+
\n+
132
\n+
134 [[nodiscard]] oid column_table(size_type col_num) const;
\n+
135
\n+
\n+
137 [[nodiscard]] oid column_table(zview col_name) const
\n+
138 {
\n+
139 return column_table(column_number(col_name));
\n+
140 }
\n+
\n+
141
\n+
143
\n+
150 [[nodiscard]] size_type table_column(size_type) const;
\n
151
\n-
153 constexpr auto front() const noexcept { return m_elts.front(); }
\n-
154
\n-
156
\n-
158 constexpr auto back() const noexcept { return m_elts.back(); }
\n-
159
\n-
160private:
\n-
162
\n-
170 void check_dims(std::string_view data)
\n-
171 {
\n-
172 auto sz{std::size(data)};
\n-
173 if (sz < DIMENSIONS * 2)
\n-
174 throw conversion_error{pqxx::internal::concat(
\n-
175 "Trying to parse a ", DIMENSIONS, "-dimensional array out of '", data,
\n-
176 "'.")};
\n+
\n+
153 [[nodiscard]] size_type table_column(zview col_name) const
\n+
154 {
\n+
155 return table_column(column_number(col_name));
\n+
156 }
\n+
\n+
158
\n+
\n+
159 [[nodiscard]] constexpr result::size_type num() const noexcept
\n+
160 {
\n+
161 return rownumber();
\n+
162 }
\n+
\n+
163
\n+
175 [[deprecated("Row slicing is going away. File a bug if you need it.")]] row
\n+
176 slice(size_type sbegin, size_type send) const;
\n
177
\n-
178 // Making some assumptions here:
\n-
179 // * The array holds no extraneous whitespace.
\n-
180 // * None of the sub-arrays can be null.
\n-
181 // * Only ASCII characters start off with a byte in the 0-127 range.
\n-
182 //
\n-
183 // Given those, the input must start with a sequence of DIMENSIONS bytes
\n-
184 // with the ASCII value for '{'; and likewise it must end with a sequence
\n-
185 // of DIMENSIONS bytes with the ASCII value for '}'.
\n-
186
\n-
187 if (data[0] != '{')
\n-
188 throw conversion_error{"Malformed array: does not start with '{'."};
\n-
189 for (std::size_t i{0}; i < DIMENSIONS; ++i)
\n-
190 if (data[i] != '{')
\n-
191 throw conversion_error{pqxx::internal::concat(
\n-
192 "Expecting ", DIMENSIONS, "-dimensional array, but found ", i, ".")};
\n-
193 if (data[DIMENSIONS] == '{')
\n-
194 throw conversion_error{pqxx::internal::concat(
\n-
195 "Tried to parse ", DIMENSIONS,
\n-
196 "-dimensional array from array data that has more dimensions.")};
\n-
197 for (std::size_t i{0}; i < DIMENSIONS; ++i)
\n-
198 if (data[sz - 1 - i] != '}')
\n-
199 throw conversion_error{
\n-
200 "Malformed array: does not end in the right number of '}'."};
\n-
201 }
\n-
202
\n-
203 explicit array(std::string_view data, pqxx::internal::encoding_group enc)
\n-
204 {
\n-
205 using group = pqxx::internal::encoding_group;
\n-
206 switch (enc)
\n-
207 {
\n-
208 case group::MONOBYTE: parse<group::MONOBYTE>(data); break;
\n-
209 case group::BIG5: parse<group::BIG5>(data); break;
\n-
210 case group::EUC_CN: parse<group::EUC_CN>(data); break;
\n-
211 case group::EUC_JP: parse<group::EUC_JP>(data); break;
\n-
212 case group::EUC_KR: parse<group::EUC_KR>(data); break;
\n-
213 case group::EUC_TW: parse<group::EUC_TW>(data); break;
\n-
214 case group::GB18030: parse<group::GB18030>(data); break;
\n-
215 case group::GBK: parse<group::GBK>(data); break;
\n-
216 case group::JOHAB: parse<group::JOHAB>(data); break;
\n-
217 case group::MULE_INTERNAL: parse<group::MULE_INTERNAL>(data); break;
\n-
218 case group::SJIS: parse<group::SJIS>(data); break;
\n-
219 case group::UHC: parse<group::UHC>(data); break;
\n-
220 case group::UTF8: parse<group::UTF8>(data); break;
\n-
221 }
\n-
222 }
\n-
223
\n-
225
\n-
228 std::size_t parse_field_end(std::string_view data, std::size_t here) const
\n-
229 {
\n-
230 auto const sz{std::size(data)};
\n-
231 if (here < sz)
\n-
232 switch (data[here])
\n-
233 {
\n-
234 case SEPARATOR:
\n-
235 ++here;
\n-
236 if (here >= sz)
\n-
237 throw conversion_error{"Array looks truncated."};
\n-
238 switch (data[here])
\n-
239 {
\n-
240 case SEPARATOR:
\n-
241 throw conversion_error{"Array contains double separator."};
\n-
242 case '}': throw conversion_error{"Array contains trailing separator."};
\n-
243 default: break;
\n-
244 }
\n-
245 break;
\n-
246 case '}': break;
\n-
247 default:
\n-
248 throw conversion_error{pqxx::internal::concat(
\n-
249 "Unexpected character in array: ",
\n-
250 static_cast<unsigned>(static_cast<unsigned char>(data[here])),
\n-
251 " where separator or closing brace expected.")};
\n-
252 }
\n-
253 return here;
\n-
254 }
\n+
179 [[nodiscard, deprecated("Row slicing is going away.")]] PQXX_PURE bool
\n+
180 empty() const noexcept;
\n+
181
\n+
183
\n+
\n+
188 template<typename Tuple> void to(Tuple &t) const
\n+
189 {
\n+
190 check_size(std::tuple_size_v<Tuple>);
\n+
191 convert(t);
\n+
192 }
\n+
\n+
193
\n+
195
\n+
\n+
200 template<typename... TYPE> std::tuple<TYPE...> as() const
\n+
201 {
\n+
202 check_size(sizeof...(TYPE));
\n+
203 using seq = std::make_index_sequence<sizeof...(TYPE)>;
\n+
204 return get_tuple<std::tuple<TYPE...>>(seq{});
\n+
205 }
\n+
\n+
206
\n+
207protected:
\n+
208 friend class const_row_iterator;
\n+
209 friend class result;
\n+
210 row(result const &r, result_size_type index, size_type cols) noexcept;
\n+
211
\n+
\n+
213 void check_size(size_type expected) const
\n+
214 {
\n+
215 if (size() != expected)
\n+
216 throw usage_error{internal::concat(
\n+
217 "Tried to extract ", expected, " field(s) from a row of ", size(),
\n+
218 ".")};
\n+
219 }
\n+
\n+
220
\n+
222
\n+
\n+
225 template<typename TUPLE> TUPLE as_tuple() const
\n+
226 {
\n+
227 using seq = std::make_index_sequence<std::tuple_size_v<TUPLE>>;
\n+
228 return get_tuple<TUPLE>(seq{});
\n+
229 }
\n+
\n+
230
\n+
231 template<typename... T> friend class pqxx::internal::result_iter;
\n+
\n+
233 template<typename Tuple> void convert(Tuple &t) const
\n+
234 {
\n+
235 extract_fields(t, std::make_index_sequence<std::tuple_size_v<Tuple>>{});
\n+
236 }
\n+
\n+
237
\n+
238 friend class field;
\n+
239
\n+\n+
242
\n+
244
\n+
248 result::size_type m_index = 0;
\n+
249
\n+
250 // TODO: Remove m_begin and (if possible) m_end when we remove slice().
\n+
252 size_type m_begin = 0;
\n+
254 size_type m_end = 0;
\n
255
\n-
257
\n-
262 constexpr std::size_t estimate_elements(std::string_view data) const noexcept
\n-
263 {
\n-
264 // Dirty trick: just count the number of bytes that look as if they may be
\n-
265 // separators. At the very worst we may overestimate by a factor of two or
\n-
266 // so, in exceedingly rare cases, on some encodings.
\n-
267 auto const separators{
\n-
268 std::count(std::begin(data), std::end(data), SEPARATOR)};
\n-
269 // The number of dimensions makes no difference here. It's still one
\n-
270 // separator between consecutive elements, just possibly with some extra
\n-
271 // braces as well.
\n-
272 return static_cast<std::size_t>(separators + 1);
\n-
273 }
\n-
274
\n-
275 template<pqxx::internal::encoding_group ENC>
\n-
276 void parse(std::string_view data)
\n-
277 {
\n-
278 static_assert(DIMENSIONS > 0u, "Can't create a zero-dimensional array.");
\n-
279 auto const sz{std::size(data)};
\n-
280 check_dims(data);
\n-
281
\n-
282 m_elts.reserve(estimate_elements(data));
\n-
283
\n-
284 // We discover the array's extents along each of the dimensions, starting
\n-
285 // with the final dimension and working our way towards the first. At any
\n-
286 // given point during parsing, we know the extents starting at this
\n-
287 // dimension.
\n-
288 std::size_t know_extents_from{DIMENSIONS};
\n-
289
\n-
290 // Currently parsing this dimension. We start off at -1, relying on C++'s
\n-
291 // well-defined rollover for unsigned numbers.
\n-
292 // The actual outermost dimension of the array is 0, and the innermost is
\n-
293 // at the end. But, the array as a whole is enclosed in braces just like
\n-
294 // each row. So we act like there's an anomalous "outer" dimension holding
\n-
295 // the entire array.
\n-
296 constexpr std::size_t outer{std::size_t{0u} - std::size_t{1u}};
\n-
297
\n-
298 // We start parsing at the fictional outer dimension. The input begins
\n-
299 // with opening braces, one for each dimension, so we'll start off by
\n-
300 // bumping all the way to the innermost dimension.
\n-
301 std::size_t dim{outer};
\n-
302
\n-
303 // Extent counters, one per "real" dimension.
\n-
304 // Note initialiser syntax; this should zero-initialise all elements.
\n-
305 std::array<std::size_t, DIMENSIONS> extents{};
\n-
306#if !defined(NDEBUG)
\n-
307 for (auto const e : extents) assert(e == 0u);
\n-
308#endif
\n+
256private:
\n+
257 template<typename Tuple, std::size_t... indexes>
\n+
258 void extract_fields(Tuple &t, std::index_sequence<indexes...>) const
\n+
259 {
\n+
260 (extract_value<Tuple, indexes>(t), ...);
\n+
261 }
\n+
262
\n+
263 template<typename Tuple, std::size_t index>
\n+
264 void extract_value(Tuple &t) const;
\n+
265
\n+
267 template<typename TUPLE, std::size_t... indexes>
\n+
268 auto get_tuple(std::index_sequence<indexes...>) const
\n+
269 {
\n+
270 return std::make_tuple(get_field<TUPLE, indexes>()...);
\n+
271 }
\n+
272
\n+
274 template<typename TUPLE, std::size_t index> auto get_field() const
\n+
275 {
\n+
276 return (*this)[index].as<std::tuple_element_t<index, TUPLE>>();
\n+
277 }
\n+
278};
\n+
\n+
279
\n+
280
\n+
\n+
282class PQXX_LIBEXPORT const_row_iterator : public field
\n+
283{
\n+
284public:
\n+
285 using iterator_category = std::random_access_iterator_tag;
\n+
286 using value_type = field const;
\n+
287 using pointer = field const *;
\n+\n+\n+\n+
291
\n+
292#include "pqxx/internal/ignore-deprecated-pre.hxx"
\n+
293 const_row_iterator() noexcept = default;
\n+
294#include "pqxx/internal/ignore-deprecated-post.hxx"
\n+
\n+
295 const_row_iterator(row const &t, row_size_type c) noexcept :
\n+
296 field{t.m_result, t.m_index, c}
\n+
297 {}
\n+
\n+
298 const_row_iterator(field const &F) noexcept : field{F} {}
\n+
299 const_row_iterator(const_row_iterator const &) noexcept = default;
\n+\n+
301
\n+
306 [[nodiscard]] constexpr pointer operator->() const noexcept { return this; }
\n+
307 [[nodiscard]] reference operator*() const noexcept { return {*this}; }
\n
309
\n-
310 // Current parsing position.
\n-
311 std::size_t here{0};
\n-
312 while (here < sz)
\n-
313 {
\n-
314 if (data[here] == '{')
\n-
315 {
\n-
316 if (dim == outer)
\n-
317 {
\n-
318 // This must be the initial opening brace.
\n-
319 if (know_extents_from != DIMENSIONS)
\n-
320 throw conversion_error{
\n-
321 "Array text representation closed and reopened its outside "
\n-
322 "brace pair."};
\n-
323 assert(here == 0);
\n-
324 }
\n-
325 else
\n-
326 {
\n-
327 if (dim >= (DIMENSIONS - 1))
\n-
328 throw conversion_error{
\n-
329 "Array seems to have inconsistent number of dimensions."};
\n-
330 ++extents[dim];
\n-
331 }
\n-
332 // (Rolls over to zero if we're coming from the outer dimension.)
\n-
333 ++dim;
\n-
334 extents[dim] = 0u;
\n-
335 ++here;
\n-
336 }
\n-
337 else if (data[here] == '}')
\n-
338 {
\n-
339 if (dim == outer)
\n-
340 throw conversion_error{"Array has spurious '}'."};
\n-
341 if (dim < know_extents_from)
\n-
342 {
\n-
343 // We just finished parsing our first row in this dimension.
\n-
344 // Now we know the array dimension's extent.
\n-
345 m_extents[dim] = extents[dim];
\n-
346 know_extents_from = dim;
\n-
347 }
\n-
348 else
\n-
349 {
\n-
350 if (extents[dim] != m_extents[dim])
\n-
351 throw conversion_error{"Rows in array have inconsistent sizes."};
\n-
352 }
\n-
353 // Bump back down to the next-lower dimension. Which may be the outer
\n-
354 // dimension, through underflow.
\n-
355 --dim;
\n-
356 ++here;
\n-
357 here = parse_field_end(data, here);
\n-
358 }
\n-
359 else
\n-
360 {
\n-
361 // Found an array element. The actual elements always live in the
\n-
362 // "inner" dimension.
\n-
363 if (dim != DIMENSIONS - 1)
\n-
364 throw conversion_error{
\n-
365 "Malformed array: found element where sub-array was expected."};
\n-
366 assert(dim != outer);
\n-
367 ++extents[dim];
\n-
368 std::size_t end;
\n-
369 switch (data[here])
\n-
370 {
\n-
371 case '\\0': throw conversion_error{"Unexpected zero byte in array."};
\n-
372 case ',': throw conversion_error{"Array contains empty field."};
\n-
373 case '"': {
\n-
374 // Double-quoted string. We parse it into a buffer before parsing
\n-
375 // the resulting string as an element. This seems wasteful: the
\n-
376 // string might not contain any special characters. So it's
\n-
377 // tempting to check, and try to use a string_view and avoid a
\n-
378 // useless copy step. But. Even besides the branch prediction
\n-
379 // risk, the very fact that the back-end chose to quote the string
\n-
380 // indicates that there is some kind of special character in there.
\n-
381 // So in practice, this optimisation would only apply if the only
\n-
382 // special characters in the string were commas.
\n-
383 end = pqxx::internal::scan_double_quoted_string<ENC>(
\n-
384 std::data(data), std::size(data), here);
\n-
385 // TODO: scan_double_quoted_string() with reusable buffer.
\n-
386 std::string const buf{
\n-
387 pqxx::internal::parse_double_quoted_string<ENC>(
\n-
388 std::data(data), end, here)};
\n-
389 m_elts.emplace_back(from_string<ELEMENT>(buf));
\n-
390 }
\n-
391 break;
\n-
392 default: {
\n-
393 // Unquoted string. An unquoted string is always literal, no
\n-
394 // escaping or encoding, so we don't need to parse it into a
\n-
395 // buffer. We can just read it as a string_view.
\n-
396 end = pqxx::internal::scan_unquoted_string<ENC, SEPARATOR, '}'>(
\n-
397 std::data(data), std::size(data), here);
\n-
398 std::string_view const field{
\n-
399 std::string_view{std::data(data) + here, end - here}};
\n-
400 if (field == "NULL")
\n-
401 {
\n-
402 if constexpr (nullness<ELEMENT>::has_null)
\n-
403 m_elts.emplace_back(nullness<ELEMENT>::null());
\n-
404 else
\n-
405 throw unexpected_null{pqxx::internal::concat(
\n-
406 "Array contains a null ", type_name<ELEMENT>,
\n-
407 ". Consider making it an array of std::optional<",
\n-
408 type_name<ELEMENT>, "> instead.")};
\n-
409 }
\n-
410 else
\n-
411 m_elts.emplace_back(from_string<ELEMENT>(field));
\n-
412 }
\n-
413 }
\n-
414 here = end;
\n-
415 here = parse_field_end(data, here);
\n-
416 }
\n-
417 }
\n+
314 const_row_iterator &operator=(const_row_iterator const &) noexcept = default;
\n+\n+
316
\n+
317 const_row_iterator operator++(int) noexcept;
\n+
\n+
318 const_row_iterator &operator++() noexcept
\n+
319 {
\n+
320 ++m_col;
\n+
321 return *this;
\n+
322 }
\n+
\n+
323 const_row_iterator operator--(int) noexcept;
\n+
\n+\n+
325 {
\n+
326 --m_col;
\n+
327 return *this;
\n+
328 }
\n+
\n+
329
\n+
\n+\n+
331 {
\n+
332 m_col = size_type(difference_type(m_col) + i);
\n+
333 return *this;
\n+
334 }
\n+
\n+
\n+\n+
336 {
\n+
337 m_col = size_type(difference_type(m_col) - i);
\n+
338 return *this;
\n+
339 }
\n+
\n+
341
\n+
346 [[nodiscard]] constexpr bool
\n+
\n+
347 operator==(const_row_iterator const &i) const noexcept
\n+
348 {
\n+
349 return col() == i.col();
\n+
350 }
\n+
\n+
351 [[nodiscard]] constexpr bool
\n+
\n+
352 operator!=(const_row_iterator const &i) const noexcept
\n+
353 {
\n+
354 return col() != i.col();
\n+
355 }
\n+
\n+
\n+
356 [[nodiscard]] constexpr bool
\n+
357 operator<(const_row_iterator const &i) const noexcept
\n+
358 {
\n+
359 return col() < i.col();
\n+
360 }
\n+
\n+
\n+
361 [[nodiscard]] constexpr bool
\n+
362 operator<=(const_row_iterator const &i) const noexcept
\n+
363 {
\n+
364 return col() <= i.col();
\n+
365 }
\n+
\n+
366 [[nodiscard]] constexpr bool
\n+
\n+
367 operator>(const_row_iterator const &i) const noexcept
\n+
368 {
\n+
369 return col() > i.col();
\n+
370 }
\n+
\n+
371 [[nodiscard]] constexpr bool
\n+
\n+
372 operator>=(const_row_iterator const &i) const noexcept
\n+
373 {
\n+
374 return col() >= i.col();
\n+
375 }
\n+
\n+
377
\n+
382 [[nodiscard]] inline const_row_iterator
\n+
383 operator+(difference_type) const noexcept;
\n+
384
\n+
385 friend const_row_iterator
\n+
386 operator+(difference_type, const_row_iterator const &) noexcept;
\n+
387
\n+
388 [[nodiscard]] inline const_row_iterator
\n+
\n+
389 operator-(difference_type) const noexcept;
\n+
390 [[nodiscard]] inline difference_type
\n+
\n+
391 operator-(const_row_iterator const &) const noexcept;
\n+
393};
\n+
394
\n+
395
\n+
\n+
397class PQXX_LIBEXPORT const_reverse_row_iterator : private const_row_iterator
\n+
398{
\n+
399public:
\n+\n+\n+\n+\n+\n+\n+\n+
407
\n+
408 const_reverse_row_iterator() noexcept = default;
\n+\n+
410 default;
\n+\n+
412
\n+
\n+
413 explicit const_reverse_row_iterator(super const &rhs) noexcept :
\n+\n+
415 {
\n+
416 super::operator--();
\n+
417 }
\n+
\n
418
\n-
419 if (dim != outer)
\n-
420 throw conversion_error{"Malformed array; may be truncated."};
\n-
421 assert(know_extents_from == 0);
\n-
422
\n-
423 init_factors();
\n-
424 }
\n-
425
\n-
427 void init_factors() noexcept
\n-
428 {
\n-
429 std::size_t factor{1};
\n-
430 for (std::size_t dim{DIMENSIONS - 1}; dim > 0; --dim)
\n-
431 {
\n-
432 factor *= m_extents[dim];
\n-
433 m_factors[dim - 1] = factor;
\n-
434 }
\n-
435 }
\n-
436
\n-
438 template<typename... INDEX> std::size_t locate(INDEX... index) const noexcept
\n-
439 {
\n-
440 static_assert(
\n-
441 sizeof...(index) == DIMENSIONS,
\n-
442 "Indexing array with wrong number of dimensions.");
\n-
443 return add_index(index...);
\n-
444 }
\n-
445
\n-
446 template<typename OUTER, typename... INDEX>
\n-
447 constexpr std::size_t add_index(OUTER outer, INDEX... indexes) const noexcept
\n-
448 {
\n-
449 std::size_t const first{check_cast<std::size_t>(outer, "array index"sv)};
\n-
450 if constexpr (sizeof...(indexes) == 0)
\n-
451 {
\n-
452 return first;
\n-
453 }
\n-
454 else
\n-
455 {
\n-
456 static_assert(sizeof...(indexes) < DIMENSIONS);
\n-
457 // (Offset by 1 here because the outer dimension is not in there.)
\n-
458 constexpr auto dimension{DIMENSIONS - (sizeof...(indexes) + 1)};
\n-
459 static_assert(dimension < DIMENSIONS);
\n-
460 return first * m_factors[dimension] + add_index(indexes...);
\n-
461 }
\n-
462 }
\n-
463
\n-
465
\n-
467 template<typename OUTER, typename... INDEX>
\n-
468 constexpr void check_bounds(OUTER outer, INDEX... indexes) const
\n-
469 {
\n-
470 std::size_t const first{check_cast<std::size_t>(outer, "array index"sv)};
\n-
471 static_assert(sizeof...(indexes) < DIMENSIONS);
\n-
472 // (Offset by 1 here because the outer dimension is not in there.)
\n-
473 constexpr auto dimension{DIMENSIONS - (sizeof...(indexes) + 1)};
\n-
474 static_assert(dimension < DIMENSIONS);
\n-
475 if (first >= m_extents[dimension])
\n-
476 throw range_error{pqxx::internal::concat(
\n-
477 "Array index for dimension ", dimension, " is out of bounds: ", first,
\n-
478 " >= ", m_extents[dimension])};
\n-
479
\n-
480 // Now check the rest of the indexes, if any.
\n-
481 if constexpr (sizeof...(indexes) > 0)
\n-
482 check_bounds(indexes...);
\n-
483 }
\n-
484
\n-
486 std::vector<ELEMENT> m_elts;
\n-
487
\n-
489 std::array<std::size_t, DIMENSIONS> m_extents;
\n-
490
\n-
492
\n-
499 std::array<std::size_t, DIMENSIONS - 1> m_factors;
\n-
500};
\n-
\n-
501
\n-
502
\n-
504
\n-
\n-
526class PQXX_LIBEXPORT array_parser
\n-
527{
\n-
528public:
\n-
\n-
530 enum class juncture
\n-
531 {
\n-
533 row_start,
\n-
535 row_end,
\n-
537 null_value,
\n-
539 string_value,
\n-
541 done,
\n-
542 };
\n-
\n-
543
\n-
545
\n-
549 explicit array_parser(
\n-
550 std::string_view input,
\n-
551 internal::encoding_group = internal::encoding_group::MONOBYTE);
\n+
419 [[nodiscard]] PQXX_PURE iterator_type base() const noexcept;
\n+
420
\n+
425 using iterator_type::operator->;
\n+
426 using iterator_type::operator*;
\n+
428
\n+
433 const_reverse_row_iterator &
\n+
\n+
434 operator=(const_reverse_row_iterator const &r) noexcept
\n+
435 {
\n+
436 iterator_type::operator=(r);
\n+
437 return *this;
\n+
438 }
\n+
\n+
\n+\n+
440 {
\n+
441 iterator_type::operator--();
\n+
442 return *this;
\n+
443 }
\n+
\n+
444 const_reverse_row_iterator operator++(int) noexcept;
\n+
\n+\n+
446 {
\n+
447 iterator_type::operator++();
\n+
448 return *this;
\n+
449 }
\n+
\n+
450 const_reverse_row_iterator operator--(int);
\n+
\n+\n+
452 {
\n+
453 iterator_type::operator-=(i);
\n+
454 return *this;
\n+
455 }
\n+
\n+
\n+\n+
457 {
\n+
458 iterator_type::operator+=(i);
\n+
459 return *this;
\n+
460 }
\n+
\n+
462
\n+
467 [[nodiscard]] const_reverse_row_iterator
\n+
\n+
468 operator+(difference_type i) const noexcept
\n+
469 {
\n+
470 return const_reverse_row_iterator{base() - i};
\n+
471 }
\n+
\n+
472 [[nodiscard]] const_reverse_row_iterator
\n+
\n+\n+
474 {
\n+
475 return const_reverse_row_iterator{base() + i};
\n+
476 }
\n+
\n+
477 [[nodiscard]] difference_type
\n+
\n+
478 operator-(const_reverse_row_iterator const &rhs) const noexcept
\n+
479 {
\n+
480 return rhs.const_row_iterator::operator-(*this);
\n+
481 }
\n+
\n+
483
\n+
488 [[nodiscard]] bool
\n+
\n+
489 operator==(const_reverse_row_iterator const &rhs) const noexcept
\n+
490 {
\n+
491 return iterator_type::operator==(rhs);
\n+
492 }
\n+
\n+
493 [[nodiscard]] bool
\n+
\n+
494 operator!=(const_reverse_row_iterator const &rhs) const noexcept
\n+
495 {
\n+
496 return !operator==(rhs);
\n+
497 }
\n+
\n+
498
\n+
\n+
499 [[nodiscard]] constexpr bool
\n+
500 operator<(const_reverse_row_iterator const &rhs) const noexcept
\n+
501 {
\n+
502 return iterator_type::operator>(rhs);
\n+
503 }
\n+
\n+
\n+
504 [[nodiscard]] constexpr bool
\n+
505 operator<=(const_reverse_row_iterator const &rhs) const noexcept
\n+
506 {
\n+
507 return iterator_type::operator>=(rhs);
\n+
508 }
\n+
\n+
509 [[nodiscard]] constexpr bool
\n+
\n+
510 operator>(const_reverse_row_iterator const &rhs) const noexcept
\n+
511 {
\n+
512 return iterator_type::operator<(rhs);
\n+
513 }
\n+
\n+
514 [[nodiscard]] constexpr bool
\n+
\n+
515 operator>=(const_reverse_row_iterator const &rhs) const noexcept
\n+
516 {
\n+
517 return iterator_type::operator<=(rhs);
\n+
518 }
\n+
\n+
520};
\n+
\n+
521
\n+
522
\n+
523const_row_iterator
\n+
\n+\n+
525{
\n+
526 // TODO:: More direct route to home().columns()?
\n+
527 return {
\n+
528 row{home(), idx(), home().columns()},
\n+
529 size_type(difference_type(col()) + o)};
\n+
530}
\n+
\n+
531
\n+
\n+\n+\n+
534{
\n+
535 return i + o;
\n+
536}
\n+
\n+
537
\n+\n+
\n+\n+
540{
\n+
541 // TODO:: More direct route to home().columns()?
\n+
542 return {
\n+
543 row{home(), idx(), home().columns()},
\n+
544 size_type(difference_type(col()) - o)};
\n+
545}
\n+
\n+
546
\n+\n+
\n+\n+
549{
\n+
550 return difference_type(num() - i.num());
\n+
551}
\n+
\n+
\n
552
\n-
554
\n-
560 std::pair<juncture, std::string> get_next() { return (this->*m_impl)(); }
\n-
561
\n-
562private:
\n-
563 std::string_view m_input;
\n-
564
\n-
566 std::size_t m_pos = 0u;
\n-
567
\n-
569
\n-
574 using implementation = std::pair<juncture, std::string> (array_parser::*)();
\n-
575
\n-
577 static implementation
\n-
578 specialize_for_encoding(pqxx::internal::encoding_group enc);
\n-
579
\n-
581 implementation m_impl;
\n-
582
\n-
584 template<pqxx::internal::encoding_group>
\n-
585 std::pair<juncture, std::string> parse_array_step();
\n-
586
\n-
587 template<pqxx::internal::encoding_group>
\n-
588 std::string::size_type scan_double_quoted_string() const;
\n-
589 template<pqxx::internal::encoding_group>
\n-
590 std::string parse_double_quoted_string(std::string::size_type end) const;
\n-
591 template<pqxx::internal::encoding_group>
\n-
592 std::string::size_type scan_unquoted_string() const;
\n-
593 template<pqxx::internal::encoding_group>
\n-
594 std::string parse_unquoted_string(std::string::size_type end) const;
\n-
595
\n-
596 template<pqxx::internal::encoding_group>
\n-
597 std::string::size_type scan_glyph(std::string::size_type pos) const;
\n-
598 template<pqxx::internal::encoding_group>
\n-
599 std::string::size_type
\n-
600 scan_glyph(std::string::size_type pos, std::string::size_type end) const;
\n-
601};
\n+
553
\n+
554template<typename Tuple, std::size_t index>
\n+
555inline void row::extract_value(Tuple &t) const
\n+
556{
\n+
557 using field_type = strip_t<decltype(std::get<index>(t))>;
\n+
558 field const f{m_result, m_index, index};
\n+
559 std::get<index>(t) = from_string<field_type>(f);
\n+
560}
\n+
561} // namespace pqxx
\n+
562#endif
\n
\n-
602} // namespace pqxx
\n
\n-
603#endif
\n
The home of all libpqxx classes, functions, templates, etc.
Definition array.hxx:33
\n-
An SQL array received from the database.
Definition array.hxx:56
\n-
constexpr auto back() const noexcept
Refer to the last element, if any.
Definition array.hxx:158
\n-
constexpr auto cend() const noexcept
Return end point of iteration.
Definition array.hxx:117
\n-
constexpr auto crbegin() const noexcept
Begin reverse iteration.
Definition array.hxx:119
\n-
ELEMENT const & operator[](INDEX... index) const
Access element (without bounds check).
Definition array.hxx:103
\n-
constexpr std::size_t size() const noexcept
Number of elements in the array.
Definition array.hxx:127
\n-
constexpr auto ssize() const noexcept
Number of elements in the array (as a signed number).
Definition array.hxx:145
\n-
constexpr std::size_t dimensions() noexcept
How many dimensions does this array have?
Definition array.hxx:75
\n-
constexpr auto cbegin() const noexcept
Begin iteration of individual elements.
Definition array.hxx:115
\n-
ELEMENT const & at(INDEX... index) const
Definition array.hxx:87
\n-
array(std::string_view data, connection const &conn)
Parse an SQL array, read as text from a pqxx::result or stream.
Definition array.hxx:68
\n-
constexpr auto crend() const noexcept
Return end point of reverse iteration.
Definition array.hxx:121
\n-
std::array< std::size_t, DIMENSIONS > const & sizes() noexcept
Return the sizes of this array in each of its dimensions.
Definition array.hxx:82
\n-
constexpr auto front() const noexcept
Refer to the first element, if any.
Definition array.hxx:153
\n-
Low-level array parser.
Definition array.hxx:527
\n-
juncture
What's the latest thing found in the array?
Definition array.hxx:531
\n-
std::pair< juncture, std::string > get_next()
Parse the next step in the array.
Definition array.hxx:560
\n-
Connection to a database.
Definition connection.hxx:253
\n-
static TYPE null()
Return a null value.
\n-
static bool has_null
Does this type have a null value?
Definition strconv.hxx:95
\n+
int row_size_type
Number of fields in a row of database data.
Definition types.hxx:34
\n+
std::remove_cv_t< std::remove_reference_t< TYPE > > strip_t
Remove any constness, volatile, and reference-ness from a type.
Definition types.hxx:91
\n+
int row_difference_type
Difference between row sizes.
Definition types.hxx:37
\n+
const_row_iterator operator+(const_row_iterator::difference_type o, const_row_iterator const &i) noexcept
Definition row.hxx:532
\n+
int result_size_type
Number of rows in a result set.
Definition types.hxx:28
\n+
Internal items for libpqxx' own use. Do not use these yourself.
Definition composite.hxx:84
\n+
Error in usage of libpqxx library, similar to std::logic_error.
Definition except.hxx:249
\n+
Reference to a field in a result set.
Definition field.hxx:35
\n+
Result set containing data returned by a query or command.
Definition result.hxx:73
\n+
result_size_type size_type
Definition result.hxx:75
\n+
Definition row.hxx:28
\n+
Reference to one row in a result.
Definition row.hxx:47
\n+
std::tuple< TYPE... > as() const
Extract entire row's values into a tuple.
Definition row.hxx:200
\n+
row_size_type size_type
Definition row.hxx:49
\n+
oid column_type(zview col_name) const
Return a column's type.
Definition row.hxx:128
\n+
row_difference_type difference_type
Definition row.hxx:50
\n+
result m_result
Result set of which this is one row.
Definition row.hxx:241
\n+
result::size_type m_index
Row number.
Definition row.hxx:248
\n+
constexpr result::size_type num() const noexcept
Definition row.hxx:159
\n+
row() noexcept=default
\n+
constexpr result::size_type rownumber() const noexcept
Row number, assuming this is a real row and not end()/rend().
Definition row.hxx:112
\n+
TUPLE as_tuple() const
Convert to a given tuple of values, don't check sizes.
Definition row.hxx:225
\n+
void check_size(size_type expected) const
Throw usage_error if row size is not expected.
Definition row.hxx:213
\n+
size_type table_column(zview col_name) const
What column number in its table did this result column come from?
Definition row.hxx:153
\n+
void convert(Tuple &t) const
Convert entire row to tuple fields, without checking row size.
Definition row.hxx:233
\n+
oid column_table(zview col_name) const
What table did this column come from?
Definition row.hxx:137
\n+
Iterator for fields in a row. Use as row::const_iterator.
Definition row.hxx:283
\n+
const_row_iterator operator-(difference_type) const noexcept
Definition row.hxx:539
\n+
const_row_iterator & operator=(const_row_iterator &&) noexcept=default
\n+
reference operator*() const noexcept
Definition row.hxx:307
\n+
const_row_iterator(field const &F) noexcept
Definition row.hxx:298
\n+
friend const_row_iterator operator+(difference_type, const_row_iterator const &) noexcept
Definition row.hxx:532
\n+
constexpr bool operator>=(const_row_iterator const &i) const noexcept
Definition row.hxx:372
\n+
const_row_iterator(const_row_iterator const &) noexcept=default
\n+
const_row_iterator & operator=(const_row_iterator const &) noexcept=default
\n+
std::random_access_iterator_tag iterator_category
Definition row.hxx:285
\n+
constexpr bool operator==(const_row_iterator const &i) const noexcept
Definition row.hxx:347
\n+
field const * pointer
Definition row.hxx:287
\n+
field const value_type
Definition row.hxx:286
\n+
constexpr bool operator!=(const_row_iterator const &i) const noexcept
Definition row.hxx:352
\n+
const_row_iterator(const_row_iterator &&) noexcept=default
\n+
row_size_type size_type
Definition row.hxx:288
\n+
const_row_iterator & operator--() noexcept
Definition row.hxx:324
\n+
const_row_iterator() noexcept=default
\n+
row_difference_type difference_type
Definition row.hxx:289
\n+
const_row_iterator & operator-=(difference_type i) noexcept
Definition row.hxx:335
\n+
const_row_iterator & operator+=(difference_type i) noexcept
Definition row.hxx:330
\n+
const_row_iterator(row const &t, row_size_type c) noexcept
Definition row.hxx:295
\n+
constexpr bool operator>(const_row_iterator const &i) const noexcept
Definition row.hxx:367
\n+
Reverse iterator for a row. Use as row::const_reverse_iterator.
Definition row.hxx:398
\n+
const_reverse_row_iterator operator++() noexcept
Definition row.hxx:439
\n+
bool operator!=(const_reverse_row_iterator const &rhs) const noexcept
Definition row.hxx:494
\n+
constexpr bool operator>=(const_reverse_row_iterator const &rhs) const noexcept
Definition row.hxx:515
\n+
constexpr bool operator>(const_reverse_row_iterator const &rhs) const noexcept
Definition row.hxx:510
\n+
difference_type operator-(const_reverse_row_iterator const &rhs) const noexcept
Definition row.hxx:478
\n+
const_reverse_row_iterator & operator+=(difference_type i) noexcept
Definition row.hxx:451
\n+
const_reverse_row_iterator operator+(difference_type i) const noexcept
Definition row.hxx:468
\n+
const_reverse_row_iterator & operator-=(difference_type i) noexcept
Definition row.hxx:456
\n+
const_reverse_row_iterator & operator--() noexcept
Definition row.hxx:445
\n+
row_difference_type difference_type
Definition row.hxx:289
\n+
bool operator==(const_reverse_row_iterator const &rhs) const noexcept
Definition row.hxx:489
\n+
const_reverse_row_iterator() noexcept=default
\n+
const_reverse_row_iterator operator-(difference_type i) noexcept
Definition row.hxx:473
\n+
iterator_type::value_type value_type
Definition row.hxx:405
\n+
Marker-type wrapper: zero-terminated std::string_view.
Definition zview.hxx:38
\n
\n
\n \n
\n \n
\n \n \n", "details": [{"source1": "html2text {}", "source2": "html2text {}", "unified_diff": "@@ -1,554 +1,662 @@\n \n \n \n \n \n libpqxx\u00a07.8.1\n \n-array.hxx\n- 1/* Handling of SQL arrays.\n+row.hxx\n+ 1/* Definitions for the pqxx::result class and support classes.\n 2 *\n- 3 * DO NOT INCLUDE THIS FILE DIRECTLY; include pqxx/field instead.\n+ 3 * pqxx::result represents the set of result rows from a database query.\n 4 *\n- 5 * Copyright (c) 2000-2023, Jeroen T. Vermeulen.\n+ 5 * DO NOT INCLUDE THIS FILE DIRECTLY; include pqxx/result instead.\n 6 *\n- 7 * See COPYING for copyright license. If you did not receive a file called\n- 8 * COPYING with this source code, please notify the distributor of this\n- 9 * mistake, or contact the author.\n- 10 */\n- 11#ifndef PQXX_H_ARRAY\n- 12#define PQXX_H_ARRAY\n- 13\n- 14#if !defined(PQXX_HEADER_PRE)\n- 15# error \"Include libpqxx headers as , not .\"\n- 16#endif\n- 17\n- 18#include \n- 19#include \n- 20#include \n- 21#include \n- 22#include \n- 23#include \n- 24#include \n+ 7 * Copyright (c) 2000-2023, Jeroen T. Vermeulen.\n+ 8 *\n+ 9 * See COPYING for copyright license. If you did not receive a file called\n+ 10 * COPYING with this source code, please notify the distributor of this\n+ 11 * mistake, or contact the author.\n+ 12 */\n+ 13#ifndef PQXX_H_ROW\n+ 14#define PQXX_H_ROW\n+ 15\n+ 16#if !defined(PQXX_HEADER_PRE)\n+ 17# error \"Include libpqxx headers as , not .\"\n+ 18#endif\n+ 19\n+ 20#include \"pqxx/except.hxx\"\n+ 21#include \"pqxx/field.hxx\"\n+ 22#include \"pqxx/result.hxx\"\n+ 23\n+ 24#include \"pqxx/internal/concat.hxx\"\n 25\n- 26#include \"pqxx/connection.hxx\"\n- 27#include \"pqxx/internal/array-composite.hxx\"\n- 28#include \"pqxx/internal/encoding_group.hxx\"\n- 29#include \"pqxx/internal/encodings.hxx\"\n+ 26namespace pqxx::internal\n+ 27{\n+28template class result_iter;\n+ 29} // namespace pqxx::internal\n 30\n 31\n-32namespace pqxx\n+ 32namespace pqxx\n 33{\n- 34// TODO: Specialise for string_view/zview, allocate all strings in one\n-buffer.\n 35\n- 37\n- 52template<\n- 53 typename ELEMENT, std::size_t DIMENSIONS = 1u,\n- 54 char SEPARATOR = array_separator>\n-55class array final\n- 56{\n- 57public:\n- 59\n-68 array(std::string_view data, connection const &conn) :\n- 69 array{data, pqxx::internal::enc_group(conn.encoding_id())}\n- 70 {}\n- 71\n- 73\n-75 constexpr std::size_t dimensions() noexcept { return DIMENSIONS; }\n- 76\n- 78\n-82 std::array const &sizes() noexcept\n- 83 {\n- 84 return m_extents;\n- 85 }\n+46class PQXX_LIBEXPORT row\n+ 47{\n+ 48public:\n+49 using size_type = row_size_type;\n+50 using difference_type = row_difference_type;\n+51 using const_iterator = const_row_iterator;\n+52 using iterator = const_iterator;\n+53 using reference = field;\n+54 using pointer = const_row_iterator;\n+55 using const_reverse_iterator = const_reverse_row_iterator;\n+56 using reverse_iterator = const_reverse_iterator;\n+ 57\n+58 row() noexcept = default;\n+59 row(row &&) noexcept = default;\n+60 row(row const &) noexcept = default;\n+61 row &operator=(row const &) noexcept = default;\n+62 row &operator=(row &&) noexcept = default;\n+ 63\n+ 68 [[nodiscard]] PQXX_PURE bool operator==(row const &) const noexcept;\n+69 [[nodiscard]] bool operator!=(row const &rhs) const noexcept\n+ 70 {\n+ 71 return not operator==(rhs);\n+ 72 }\n+ 74\n+ 75 [[nodiscard]] const_iterator begin() const noexcept;\n+ 76 [[nodiscard]] const_iterator cbegin() const noexcept;\n+ 77 [[nodiscard]] const_iterator end() const noexcept;\n+ 78 [[nodiscard]] const_iterator cend() const noexcept;\n+ 79\n+ 84 [[nodiscard]] reference front() const noexcept;\n+ 85 [[nodiscard]] reference back() const noexcept;\n 86\n-87 template ELEMENT const &at(INDEX... index) const\n- 88 {\n- 89 static_assert(sizeof...(index) == DIMENSIONS);\n- 90 check_bounds(index...);\n- 91 return m_elts.at(locate(index...));\n- 92 }\n- 93\n- 95\n-103 template ELEMENT const &operator[](INDEX... index) const\n- 104 {\n- 105 static_assert(sizeof...(index) == DIMENSIONS);\n- 106 return m_elts[locate(index...)];\n+ 87 [[nodiscard]] const_reverse_row_iterator rbegin() const noexcept;\n+ 88 [[nodiscard]] const_reverse_row_iterator crbegin() const noexcept;\n+ 89 [[nodiscard]] const_reverse_row_iterator rend() const noexcept;\n+ 90 [[nodiscard]] const_reverse_row_iterator crend() const noexcept;\n+ 91\n+ 92 [[nodiscard]] reference operator[](size_type) const noexcept;\n+ 96 [[nodiscard]] reference operator[](zview col_name) const;\n+ 97\n+ 98 reference at(size_type) const;\n+ 102 reference at(zview col_name) const;\n+ 103\n+104 [[nodiscard]] constexpr size_type size() const noexcept\n+ 105 {\n+ 106 return m_end - m_begin;\n 107 }\n 108\n+ 109 [[deprecated(\"Swap iterators, not rows.\")]] void swap(row &) noexcept;\n 110\n-115 constexpr auto cbegin() const noexcept { return m_elts.cbegin(); }\n-117 constexpr auto cend() const noexcept { return m_elts.cend(); }\n-119 constexpr auto crbegin() const noexcept { return m_elts.crbegin(); }\n-121 constexpr auto crend() const noexcept { return m_elts.crend(); }\n- 122\n- 124\n-127 constexpr std::size_t size() const noexcept { return m_elts.size(); }\n- 128\n- 130\n-145 constexpr auto ssize() const noexcept\n- 146 {\n- 147 return static_cast(size());\n- 148 }\n- 149\n+112 [[nodiscard]] constexpr result::size_type rownumber() const noexcept\n+ 113 {\n+ 114 return m_index;\n+ 115 }\n+ 116\n+ 122 [[nodiscard]] size_type column_number(zview col_name) const;\n+ 123\n+ 125 [[nodiscard]] oid column_type(size_type) const;\n+ 126\n+128 [[nodiscard]] oid column_type(zview col_name) const\n+ 129 {\n+ 130 return column_type(column_number(col_name));\n+ 131 }\n+ 132\n+ 134 [[nodiscard]] oid column_table(size_type col_num) const;\n+ 135\n+137 [[nodiscard]] oid column_table(zview col_name) const\n+ 138 {\n+ 139 return column_table(column_number(col_name));\n+ 140 }\n+ 141\n+ 143\n+ 150 [[nodiscard]] size_type table_column(size_type) const;\n 151\n-153 constexpr auto front() const noexcept { return m_elts.front(); }\n- 154\n- 156\n-158 constexpr auto back() const noexcept { return m_elts.back(); }\n- 159\n- 160private:\n- 162\n- 170 void check_dims(std::string_view data)\n- 171 {\n- 172 auto sz{std::size(data)};\n- 173 if (sz < DIMENSIONS * 2)\n- 174 throw conversion_error{pqxx::internal::concat(\n- 175 \"Trying to parse a \", DIMENSIONS, \"-dimensional array out of '\", data,\n- 176 \"'.\")};\n+153 [[nodiscard]] size_type table_column(zview col_name) const\n+ 154 {\n+ 155 return table_column(column_number(col_name));\n+ 156 }\n+ 158\n+159 [[nodiscard]] constexpr result::size_type num() const noexcept\n+ 160 {\n+ 161 return rownumber();\n+ 162 }\n+ 163\n+ 175 [[deprecated(\"Row slicing is going away. File a bug if you need it.\")]]\n+row\n+ 176 slice(size_type sbegin, size_type send) const;\n 177\n- 178 // Making some assumptions here:\n- 179 // * The array holds no extraneous whitespace.\n- 180 // * None of the sub-arrays can be null.\n- 181 // * Only ASCII characters start off with a byte in the 0-127 range.\n- 182 //\n- 183 // Given those, the input must start with a sequence of DIMENSIONS bytes\n- 184 // with the ASCII value for '{'; and likewise it must end with a sequence\n- 185 // of DIMENSIONS bytes with the ASCII value for '}'.\n- 186\n- 187 if (data[0] != '{')\n- 188 throw conversion_error{\"Malformed array: does not start with '{'.\"};\n- 189 for (std::size_t i{0}; i < DIMENSIONS; ++i)\n- 190 if (data[i] != '{')\n- 191 throw conversion_error{pqxx::internal::concat(\n- 192 \"Expecting \", DIMENSIONS, \"-dimensional array, but found \", i, \".\")};\n- 193 if (data[DIMENSIONS] == '{')\n- 194 throw conversion_error{pqxx::internal::concat(\n- 195 \"Tried to parse \", DIMENSIONS,\n- 196 \"-dimensional array from array data that has more dimensions.\")};\n- 197 for (std::size_t i{0}; i < DIMENSIONS; ++i)\n- 198 if (data[sz - 1 - i] != '}')\n- 199 throw conversion_error{\n- 200 \"Malformed array: does not end in the right number of '}'.\"};\n- 201 }\n- 202\n- 203 explicit array(std::string_view data, pqxx::internal::encoding_group enc)\n- 204 {\n- 205 using group = pqxx::internal::encoding_group;\n- 206 switch (enc)\n- 207 {\n- 208 case group::MONOBYTE: parse(data); break;\n- 209 case group::BIG5: parse(data); break;\n- 210 case group::EUC_CN: parse(data); break;\n- 211 case group::EUC_JP: parse(data); break;\n- 212 case group::EUC_KR: parse(data); break;\n- 213 case group::EUC_TW: parse(data); break;\n- 214 case group::GB18030: parse(data); break;\n- 215 case group::GBK: parse(data); break;\n- 216 case group::JOHAB: parse(data); break;\n- 217 case group::MULE_INTERNAL: parse(data); break;\n- 218 case group::SJIS: parse(data); break;\n- 219 case group::UHC: parse(data); break;\n- 220 case group::UTF8: parse(data); break;\n- 221 }\n- 222 }\n- 223\n- 225\n- 228 std::size_t parse_field_end(std::string_view data, std::size_t here) const\n- 229 {\n- 230 auto const sz{std::size(data)};\n- 231 if (here < sz)\n- 232 switch (data[here])\n- 233 {\n- 234 case SEPARATOR:\n- 235 ++here;\n- 236 if (here >= sz)\n- 237 throw conversion_error{\"Array looks truncated.\"};\n- 238 switch (data[here])\n- 239 {\n- 240 case SEPARATOR:\n- 241 throw conversion_error{\"Array contains double separator.\"};\n- 242 case '}': throw conversion_error{\"Array contains trailing separator.\"};\n- 243 default: break;\n- 244 }\n- 245 break;\n- 246 case '}': break;\n- 247 default:\n- 248 throw conversion_error{pqxx::internal::concat(\n- 249 \"Unexpected character in array: \",\n- 250 static_cast(static_cast(data[here])),\n- 251 \" where separator or closing brace expected.\")};\n- 252 }\n- 253 return here;\n- 254 }\n+ 179 [[nodiscard, deprecated(\"Row slicing is going away.\")]] PQXX_PURE bool\n+ 180 empty() const noexcept;\n+ 181\n+ 183\n+188 template void to(Tuple &t) const\n+ 189 {\n+ 190 check_size(std::tuple_size_v);\n+ 191 convert(t);\n+ 192 }\n+ 193\n+ 195\n+200 template std::tuple as() const\n+ 201 {\n+ 202 check_size(sizeof...(TYPE));\n+ 203 using seq = std::make_index_sequence;\n+ 204 return get_tuple>(seq{});\n+ 205 }\n+ 206\n+ 207protected:\n+208 friend class const_row_iterator;\n+209 friend class result;\n+ 210 row(result const &r, result_size_type index, size_type cols) noexcept;\n+ 211\n+213 void check_size(size_type expected) const\n+ 214 {\n+ 215 if (size() != expected)\n+ 216 throw usage_error{internal::concat(\n+ 217 \"Tried to extract \", expected, \" field(s) from a row of \", size(),\n+ 218 \".\")};\n+ 219 }\n+ 220\n+ 222\n+225 template TUPLE as_tuple() const\n+ 226 {\n+ 227 using seq = std::make_index_sequence>;\n+ 228 return get_tuple(seq{});\n+ 229 }\n+ 230\n+231 template friend class pqxx::internal::result_iter;\n+233 template void convert(Tuple &t) const\n+ 234 {\n+ 235 extract_fields(t, std::make_index_sequence>{});\n+ 236 }\n+ 237\n+238 friend class field;\n+ 239\n+241 result m_result;\n+ 242\n+ 244\n+248 result::size_type m_index = 0;\n+ 249\n+ 250 // TODO: Remove m_begin and (if possible) m_end when we remove slice().\n+252 size_type m_begin = 0;\n+254 size_type m_end = 0;\n 255\n- 257\n- 262 constexpr std::size_t estimate_elements(std::string_view data) const\n-noexcept\n- 263 {\n- 264 // Dirty trick: just count the number of bytes that look as if they may be\n- 265 // separators. At the very worst we may overestimate by a factor of two or\n- 266 // so, in exceedingly rare cases, on some encodings.\n- 267 auto const separators{\n- 268 std::count(std::begin(data), std::end(data), SEPARATOR)};\n- 269 // The number of dimensions makes no difference here. It's still one\n- 270 // separator between consecutive elements, just possibly with some extra\n- 271 // braces as well.\n- 272 return static_cast(separators + 1);\n- 273 }\n- 274\n- 275 template\n- 276 void parse(std::string_view data)\n- 277 {\n- 278 static_assert(DIMENSIONS > 0u, \"Can't create a zero-dimensional array.\");\n- 279 auto const sz{std::size(data)};\n- 280 check_dims(data);\n- 281\n- 282 m_elts.reserve(estimate_elements(data));\n- 283\n- 284 // We discover the array's extents along each of the dimensions, starting\n- 285 // with the final dimension and working our way towards the first. At any\n- 286 // given point during parsing, we know the extents starting at this\n- 287 // dimension.\n- 288 std::size_t know_extents_from{DIMENSIONS};\n- 289\n- 290 // Currently parsing this dimension. We start off at -1, relying on C++'s\n- 291 // well-defined rollover for unsigned numbers.\n- 292 // The actual outermost dimension of the array is 0, and the innermost is\n- 293 // at the end. But, the array as a whole is enclosed in braces just like\n- 294 // each row. So we act like there's an anomalous \"outer\" dimension holding\n- 295 // the entire array.\n- 296 constexpr std::size_t outer{std::size_t{0u} - std::size_t{1u}};\n- 297\n- 298 // We start parsing at the fictional outer dimension. The input begins\n- 299 // with opening braces, one for each dimension, so we'll start off by\n- 300 // bumping all the way to the innermost dimension.\n- 301 std::size_t dim{outer};\n- 302\n- 303 // Extent counters, one per \"real\" dimension.\n- 304 // Note initialiser syntax; this should zero-initialise all elements.\n- 305 std::array extents{};\n- 306#if !defined(NDEBUG)\n- 307 for (auto const e : extents) assert(e == 0u);\n- 308#endif\n+ 256private:\n+ 257 template\n+ 258 void extract_fields(Tuple &t, std::index_sequence) const\n+ 259 {\n+ 260 (extract_value(t), ...);\n+ 261 }\n+ 262\n+ 263 template\n+ 264 void extract_value(Tuple &t) const;\n+ 265\n+ 267 template\n+ 268 auto get_tuple(std::index_sequence) const\n+ 269 {\n+ 270 return std::make_tuple(get_field()...);\n+ 271 }\n+ 272\n+ 274 template auto get_field() const\n+ 275 {\n+ 276 return (*this)[index].as>();\n+ 277 }\n+ 278};\n+ 279\n+ 280\n+282class PQXX_LIBEXPORT const_row_iterator : public field\n+ 283{\n+ 284public:\n+285 using iterator_category = std::random_access_iterator_tag;\n+286 using value_type = field const;\n+287 using pointer = field const *;\n+288 using size_type = row_size_type;\n+289 using difference_type = row_difference_type;\n+290 using reference = field;\n+ 291\n+ 292#include \"pqxx/internal/ignore-deprecated-pre.hxx\"\n+293 const_row_iterator() noexcept = default;\n+ 294#include \"pqxx/internal/ignore-deprecated-post.hxx\"\n+295 const_row_iterator(row const &t, row_size_type c) noexcept :\n+ 296 field{t.m_result, t.m_index, c}\n+ 297 {}\n+298 const_row_iterator(field const &F) noexcept : field{F} {}\n+299 const_row_iterator(const_row_iterator const &) noexcept = default;\n+300 const_row_iterator(const_row_iterator &&) noexcept = default;\n+ 301\n+306 [[nodiscard]] constexpr pointer operator->() const noexcept { return this;\n+}\n+307 [[nodiscard]] reference operator*() const noexcept { return {*this}; }\n 309\n- 310 // Current parsing position.\n- 311 std::size_t here{0};\n- 312 while (here < sz)\n- 313 {\n- 314 if (data[here] == '{')\n- 315 {\n- 316 if (dim == outer)\n- 317 {\n- 318 // This must be the initial opening brace.\n- 319 if (know_extents_from != DIMENSIONS)\n- 320 throw conversion_error{\n- 321 \"Array text representation closed and reopened its outside \"\n- 322 \"brace pair.\"};\n- 323 assert(here == 0);\n- 324 }\n- 325 else\n- 326 {\n- 327 if (dim >= (DIMENSIONS - 1))\n- 328 throw conversion_error{\n- 329 \"Array seems to have inconsistent number of dimensions.\"};\n- 330 ++extents[dim];\n- 331 }\n- 332 // (Rolls over to zero if we're coming from the outer dimension.)\n- 333 ++dim;\n- 334 extents[dim] = 0u;\n- 335 ++here;\n- 336 }\n- 337 else if (data[here] == '}')\n- 338 {\n- 339 if (dim == outer)\n- 340 throw conversion_error{\"Array has spurious '}'.\"};\n- 341 if (dim < know_extents_from)\n- 342 {\n- 343 // We just finished parsing our first row in this dimension.\n- 344 // Now we know the array dimension's extent.\n- 345 m_extents[dim] = extents[dim];\n- 346 know_extents_from = dim;\n- 347 }\n- 348 else\n- 349 {\n- 350 if (extents[dim] != m_extents[dim])\n- 351 throw conversion_error{\"Rows in array have inconsistent sizes.\"};\n- 352 }\n- 353 // Bump back down to the next-lower dimension. Which may be the outer\n- 354 // dimension, through underflow.\n- 355 --dim;\n- 356 ++here;\n- 357 here = parse_field_end(data, here);\n- 358 }\n- 359 else\n- 360 {\n- 361 // Found an array element. The actual elements always live in the\n- 362 // \"inner\" dimension.\n- 363 if (dim != DIMENSIONS - 1)\n- 364 throw conversion_error{\n- 365 \"Malformed array: found element where sub-array was expected.\"};\n- 366 assert(dim != outer);\n- 367 ++extents[dim];\n- 368 std::size_t end;\n- 369 switch (data[here])\n- 370 {\n- 371 case '\\0': throw conversion_error{\"Unexpected zero byte in array.\"};\n- 372 case ',': throw conversion_error{\"Array contains empty field.\"};\n- 373 case '\"': {\n- 374 // Double-quoted string. We parse it into a buffer before parsing\n- 375 // the resulting string as an element. This seems wasteful: the\n- 376 // string might not contain any special characters. So it's\n- 377 // tempting to check, and try to use a string_view and avoid a\n- 378 // useless copy step. But. Even besides the branch prediction\n- 379 // risk, the very fact that the back-end chose to quote the string\n- 380 // indicates that there is some kind of special character in there.\n- 381 // So in practice, this optimisation would only apply if the only\n- 382 // special characters in the string were commas.\n- 383 end = pqxx::internal::scan_double_quoted_string(\n- 384 std::data(data), std::size(data), here);\n- 385 // TODO: scan_double_quoted_string() with reusable buffer.\n- 386 std::string const buf{\n- 387 pqxx::internal::parse_double_quoted_string(\n- 388 std::data(data), end, here)};\n- 389 m_elts.emplace_back(from_string(buf));\n- 390 }\n- 391 break;\n- 392 default: {\n- 393 // Unquoted string. An unquoted string is always literal, no\n- 394 // escaping or encoding, so we don't need to parse it into a\n- 395 // buffer. We can just read it as a string_view.\n- 396 end = pqxx::internal::scan_unquoted_string(\n- 397 std::data(data), std::size(data), here);\n- 398 std::string_view const field{\n- 399 std::string_view{std::data(data) + here, end - here}};\n- 400 if (field == \"NULL\")\n- 401 {\n- 402 if constexpr (nullness::has_null)\n- 403 m_elts.emplace_back(nullness::null());\n- 404 else\n- 405 throw unexpected_null{pqxx::internal::concat(\n- 406 \"Array contains a null \", type_name,\n- 407 \". Consider making it an array of std::optional<\",\n- 408 type_name, \"> instead.\")};\n- 409 }\n- 410 else\n- 411 m_elts.emplace_back(from_string(field));\n- 412 }\n- 413 }\n- 414 here = end;\n- 415 here = parse_field_end(data, here);\n- 416 }\n+314 const_row_iterator &operator=(const_row_iterator const &) noexcept =\n+default;\n+315 const_row_iterator &operator=(const_row_iterator &&) noexcept = default;\n+ 316\n+ 317 const_row_iterator operator++(int) noexcept;\n+318 const_row_iterator &operator++() noexcept\n+ 319 {\n+ 320 ++m_col;\n+ 321 return *this;\n+ 322 }\n+ 323 const_row_iterator operator--(int) noexcept;\n+324 const_row_iterator &operator--() noexcept\n+ 325 {\n+ 326 --m_col;\n+ 327 return *this;\n+ 328 }\n+ 329\n+330 const_row_iterator &operator+=(difference_type i) noexcept\n+ 331 {\n+ 332 m_col = size_type(difference_type(m_col) + i);\n+ 333 return *this;\n+ 334 }\n+335 const_row_iterator &operator-=(difference_type i) noexcept\n+ 336 {\n+ 337 m_col = size_type(difference_type(m_col) - i);\n+ 338 return *this;\n+ 339 }\n+ 341\n+ 346 [[nodiscard]] constexpr bool\n+347 operator==(const_row_iterator const &i) const noexcept\n+ 348 {\n+ 349 return col() == i.col();\n+ 350 }\n+ 351 [[nodiscard]] constexpr bool\n+352 operator!=(const_row_iterator const &i) const noexcept\n+ 353 {\n+ 354 return col() != i.col();\n+ 355 }\n+356 [[nodiscard]] constexpr bool\n+ 357 operator<(const_row_iterator const &i) const noexcept\n+ 358 {\n+ 359 return col() < i.col();\n+ 360 }\n+361 [[nodiscard]] constexpr bool\n+ 362 operator<=(const_row_iterator const &i) const noexcept\n+ 363 {\n+ 364 return col() <= i.col();\n+ 365 }\n+ 366 [[nodiscard]] constexpr bool\n+367 operator>(const_row_iterator const &i) const noexcept\n+ 368 {\n+ 369 return col() > i.col();\n+ 370 }\n+ 371 [[nodiscard]] constexpr bool\n+372 operator>=(const_row_iterator const &i) const noexcept\n+ 373 {\n+ 374 return col() >= i.col();\n+ 375 }\n+ 377\n+ 382 [[nodiscard]] inline const_row_iterator\n+ 383 operator+(difference_type) const noexcept;\n+ 384\n+ 385 friend const_row_iterator\n+ 386 operator+(difference_type, const_row_iterator const &) noexcept;\n+ 387\n+ 388 [[nodiscard]] inline const_row_iterator\n+389 operator-(difference_type) const noexcept;\n+ 390 [[nodiscard]] inline difference_type\n+391 operator-(const_row_iterator const &) const noexcept;\n+ 393};\n+ 394\n+ 395\n+397class PQXX_LIBEXPORT const_reverse_row_iterator : private const_row_iterator\n+ 398{\n+ 399public:\n+400 using super = const_row_iterator;\n+401 using iterator_type = const_row_iterator;\n+ 402 using iterator_type::difference_type;\n+ 403 using iterator_type::iterator_category;\n+ 404 using iterator_type::pointer;\n+405 using value_type = iterator_type::value_type;\n+406 using reference = iterator_type::reference;\n+ 407\n+408 const_reverse_row_iterator() noexcept = default;\n+409 const_reverse_row_iterator(const_reverse_row_iterator const &) noexcept =\n+ 410 default;\n+411 const_reverse_row_iterator(const_reverse_row_iterator &&) noexcept =\n+default;\n+ 412\n+413 explicit const_reverse_row_iterator(super const &rhs) noexcept :\n+ 414 const_row_iterator{rhs}\n+ 415 {\n+ 416 super::operator--();\n 417 }\n 418\n- 419 if (dim != outer)\n- 420 throw conversion_error{\"Malformed array; may be truncated.\"};\n- 421 assert(know_extents_from == 0);\n- 422\n- 423 init_factors();\n- 424 }\n- 425\n- 427 void init_factors() noexcept\n- 428 {\n- 429 std::size_t factor{1};\n- 430 for (std::size_t dim{DIMENSIONS - 1}; dim > 0; --dim)\n- 431 {\n- 432 factor *= m_extents[dim];\n- 433 m_factors[dim - 1] = factor;\n- 434 }\n- 435 }\n- 436\n- 438 template std::size_t locate(INDEX... index) const\n-noexcept\n- 439 {\n- 440 static_assert(\n- 441 sizeof...(index) == DIMENSIONS,\n- 442 \"Indexing array with wrong number of dimensions.\");\n- 443 return add_index(index...);\n- 444 }\n- 445\n- 446 template\n- 447 constexpr std::size_t add_index(OUTER outer, INDEX... indexes) const\n-noexcept\n- 448 {\n- 449 std::size_t const first{check_cast(outer, \"array index\"sv)};\n- 450 if constexpr (sizeof...(indexes) == 0)\n- 451 {\n- 452 return first;\n- 453 }\n- 454 else\n- 455 {\n- 456 static_assert(sizeof...(indexes) < DIMENSIONS);\n- 457 // (Offset by 1 here because the outer dimension is not in there.)\n- 458 constexpr auto dimension{DIMENSIONS - (sizeof...(indexes) + 1)};\n- 459 static_assert(dimension < DIMENSIONS);\n- 460 return first * m_factors[dimension] + add_index(indexes...);\n- 461 }\n- 462 }\n- 463\n- 465\n- 467 template\n- 468 constexpr void check_bounds(OUTER outer, INDEX... indexes) const\n+ 419 [[nodiscard]] PQXX_PURE iterator_type base() const noexcept;\n+ 420\n+ 425 using iterator_type::operator->;\n+ 426 using iterator_type::operator*;\n+ 428\n+ 433 const_reverse_row_iterator &\n+434 operator=(const_reverse_row_iterator const &r) noexcept\n+ 435 {\n+ 436 iterator_type::operator=(r);\n+ 437 return *this;\n+ 438 }\n+439 const_reverse_row_iterator operator++() noexcept\n+ 440 {\n+ 441 iterator_type::operator--();\n+ 442 return *this;\n+ 443 }\n+ 444 const_reverse_row_iterator operator++(int) noexcept;\n+445 const_reverse_row_iterator &operator--() noexcept\n+ 446 {\n+ 447 iterator_type::operator++();\n+ 448 return *this;\n+ 449 }\n+ 450 const_reverse_row_iterator operator--(int);\n+451 const_reverse_row_iterator &operator+=(difference_type i) noexcept\n+ 452 {\n+ 453 iterator_type::operator-=(i);\n+ 454 return *this;\n+ 455 }\n+456 const_reverse_row_iterator &operator-=(difference_type i) noexcept\n+ 457 {\n+ 458 iterator_type::operator+=(i);\n+ 459 return *this;\n+ 460 }\n+ 462\n+ 467 [[nodiscard]] const_reverse_row_iterator\n+468 operator+(difference_type i) const noexcept\n 469 {\n- 470 std::size_t const first{check_cast(outer, \"array index\"sv)};\n- 471 static_assert(sizeof...(indexes) < DIMENSIONS);\n- 472 // (Offset by 1 here because the outer dimension is not in there.)\n- 473 constexpr auto dimension{DIMENSIONS - (sizeof...(indexes) + 1)};\n- 474 static_assert(dimension < DIMENSIONS);\n- 475 if (first >= m_extents[dimension])\n- 476 throw range_error{pqxx::internal::concat(\n- 477 \"Array index for dimension \", dimension, \" is out of bounds: \", first,\n- 478 \" >= \", m_extents[dimension])};\n- 479\n- 480 // Now check the rest of the indexes, if any.\n- 481 if constexpr (sizeof...(indexes) > 0)\n- 482 check_bounds(indexes...);\n- 483 }\n- 484\n- 486 std::vector m_elts;\n- 487\n- 489 std::array m_extents;\n- 490\n- 492\n- 499 std::array m_factors;\n- 500};\n- 501\n- 502\n- 504\n-526class PQXX_LIBEXPORT array_parser\n- 527{\n- 528public:\n-530 enum class juncture\n- 531 {\n- 533 row_start,\n- 535 row_end,\n- 537 null_value,\n- 539 string_value,\n- 541 done,\n- 542 };\n- 543\n- 545\n- 549 explicit array_parser(\n- 550 std::string_view input,\n- 551 internal::encoding_group = internal::encoding_group::MONOBYTE);\n+ 470 return const_reverse_row_iterator{base() - i};\n+ 471 }\n+ 472 [[nodiscard]] const_reverse_row_iterator\n+473 operator-(difference_type i) noexcept\n+ 474 {\n+ 475 return const_reverse_row_iterator{base() + i};\n+ 476 }\n+ 477 [[nodiscard]] difference_type\n+478 operator-(const_reverse_row_iterator const &rhs) const noexcept\n+ 479 {\n+ 480 return rhs.const_row_iterator::operator-(*this);\n+ 481 }\n+ 483\n+ 488 [[nodiscard]] bool\n+489 operator==(const_reverse_row_iterator const &rhs) const noexcept\n+ 490 {\n+ 491 return iterator_type::operator==(rhs);\n+ 492 }\n+ 493 [[nodiscard]] bool\n+494 operator!=(const_reverse_row_iterator const &rhs) const noexcept\n+ 495 {\n+ 496 return !operator==(rhs);\n+ 497 }\n+ 498\n+499 [[nodiscard]] constexpr bool\n+ 500 operator<(const_reverse_row_iterator const &rhs) const noexcept\n+ 501 {\n+ 502 return iterator_type::operator>(rhs);\n+ 503 }\n+504 [[nodiscard]] constexpr bool\n+ 505 operator<=(const_reverse_row_iterator const &rhs) const noexcept\n+ 506 {\n+ 507 return iterator_type::operator>=(rhs);\n+ 508 }\n+ 509 [[nodiscard]] constexpr bool\n+510 operator>(const_reverse_row_iterator const &rhs) const noexcept\n+ 511 {\n+ 512 return iterator_type::operator<(rhs);\n+ 513 }\n+ 514 [[nodiscard]] constexpr bool\n+515 operator>=(const_reverse_row_iterator const &rhs) const noexcept\n+ 516 {\n+ 517 return iterator_type::operator<=(rhs);\n+ 518 }\n+ 520};\n+ 521\n+ 522\n+ 523const_row_iterator\n+524const_row_iterator::operator+(difference_type o) const noexcept\n+ 525{\n+ 526 // TODO:: More direct route to home().columns()?\n+ 527 return {\n+ 528 row{home(), idx(), home().columns()},\n+ 529 size_type(difference_type(col()) + o)};\n+ 530}\n+ 531\n+532inline const_row_iterator operator+(\n+ 533 const_row_iterator::difference_type o, const_row_iterator const &i)\n+noexcept\n+ 534{\n+ 535 return i + o;\n+ 536}\n+ 537\n+ 538inline const_row_iterator\n+539const_row_iterator::operator-(difference_type o) const noexcept\n+ 540{\n+ 541 // TODO:: More direct route to home().columns()?\n+ 542 return {\n+ 543 row{home(), idx(), home().columns()},\n+ 544 size_type(difference_type(col()) - o)};\n+ 545}\n+ 546\n+ 547inline const_row_iterator::difference_type\n+548const_row_iterator::operator-(const_row_iterator const &i) const noexcept\n+ 549{\n+ 550 return difference_type(num() - i.num());\n+ 551}\n 552\n- 554\n-560 std::pair get_next() { return (this->*m_impl)(); }\n- 561\n- 562private:\n- 563 std::string_view m_input;\n- 564\n- 566 std::size_t m_pos = 0u;\n- 567\n- 569\n- 574 using implementation = std::pair (array_parser::*)\n-();\n- 575\n- 577 static implementation\n- 578 specialize_for_encoding(pqxx::internal::encoding_group enc);\n- 579\n- 581 implementation m_impl;\n- 582\n- 584 template\n- 585 std::pair parse_array_step();\n- 586\n- 587 template\n- 588 std::string::size_type scan_double_quoted_string() const;\n- 589 template\n- 590 std::string parse_double_quoted_string(std::string::size_type end) const;\n- 591 template\n- 592 std::string::size_type scan_unquoted_string() const;\n- 593 template\n- 594 std::string parse_unquoted_string(std::string::size_type end) const;\n- 595\n- 596 template\n- 597 std::string::size_type scan_glyph(std::string::size_type pos) const;\n- 598 template\n- 599 std::string::size_type\n- 600 scan_glyph(std::string::size_type pos, std::string::size_type end) const;\n- 601};\n- 602} // namespace pqxx\n- 603#endif\n+ 553\n+ 554template\n+ 555inline void row::extract_value(Tuple &t) const\n+ 556{\n+ 557 using field_type = strip_t(t))>;\n+ 558 field const f{m_result, m_index, index};\n+ 559 std::get(t) = from_string(f);\n+ 560}\n+ 561} // namespace pqxx\n+ 562#endif\n pqxx\n The home of all libpqxx classes, functions, templates, etc.\n Definition array.hxx:33\n-pqxx::array\n-An SQL array received from the database.\n-Definition array.hxx:56\n-pqxx::array::back\n-constexpr auto back() const noexcept\n-Refer to the last element, if any.\n-Definition array.hxx:158\n-pqxx::array::cend\n-constexpr auto cend() const noexcept\n-Return end point of iteration.\n-Definition array.hxx:117\n-pqxx::array::crbegin\n-constexpr auto crbegin() const noexcept\n-Begin reverse iteration.\n-Definition array.hxx:119\n-pqxx::array::operator[]\n-ELEMENT const & operator[](INDEX... index) const\n-Access element (without bounds check).\n-Definition array.hxx:103\n-pqxx::array::size\n-constexpr std::size_t size() const noexcept\n-Number of elements in the array.\n-Definition array.hxx:127\n-pqxx::array::ssize\n-constexpr auto ssize() const noexcept\n-Number of elements in the array (as a signed number).\n-Definition array.hxx:145\n-pqxx::array::dimensions\n-constexpr std::size_t dimensions() noexcept\n-How many dimensions does this array have?\n-Definition array.hxx:75\n-pqxx::array::cbegin\n-constexpr auto cbegin() const noexcept\n-Begin iteration of individual elements.\n-Definition array.hxx:115\n-pqxx::array::at\n-ELEMENT const & at(INDEX... index) const\n-Definition array.hxx:87\n-pqxx::array::array\n-array(std::string_view data, connection const &conn)\n-Parse an SQL array, read as text from a pqxx::result or stream.\n-Definition array.hxx:68\n-pqxx::array::crend\n-constexpr auto crend() const noexcept\n-Return end point of reverse iteration.\n-Definition array.hxx:121\n-pqxx::array::sizes\n-std::array< std::size_t, DIMENSIONS > const & sizes() noexcept\n-Return the sizes of this array in each of its dimensions.\n-Definition array.hxx:82\n-pqxx::array::front\n-constexpr auto front() const noexcept\n-Refer to the first element, if any.\n-Definition array.hxx:153\n-pqxx::array_parser\n-Low-level array parser.\n-Definition array.hxx:527\n-pqxx::array_parser::juncture\n-juncture\n-What's the latest thing found in the array?\n-Definition array.hxx:531\n-pqxx::array_parser::get_next\n-std::pair< juncture, std::string > get_next()\n-Parse the next step in the array.\n-Definition array.hxx:560\n-pqxx::connection\n-Connection to a database.\n-Definition connection.hxx:253\n-pqxx::nullness::null\n-static TYPE null()\n-Return a null value.\n-pqxx::nullness::has_null\n-static bool has_null\n-Does this type have a null value?\n-Definition strconv.hxx:95\n+pqxx::row_size_type\n+int row_size_type\n+Number of fields in a row of database data.\n+Definition types.hxx:34\n+pqxx::strip_t\n+std::remove_cv_t< std::remove_reference_t< TYPE > > strip_t\n+Remove any constness, volatile, and reference-ness from a type.\n+Definition types.hxx:91\n+pqxx::row_difference_type\n+int row_difference_type\n+Difference between row sizes.\n+Definition types.hxx:37\n+pqxx::operator+\n+const_row_iterator operator+(const_row_iterator::difference_type o,\n+const_row_iterator const &i) noexcept\n+Definition row.hxx:532\n+pqxx::result_size_type\n+int result_size_type\n+Number of rows in a result set.\n+Definition types.hxx:28\n+pqxx::internal\n+Internal items for libpqxx' own use. Do not use these yourself.\n+Definition composite.hxx:84\n+pqxx::usage_error\n+Error in usage of libpqxx library, similar to std::logic_error.\n+Definition except.hxx:249\n+pqxx::field\n+Reference to a field in a result set.\n+Definition field.hxx:35\n+pqxx::result\n+Result set containing data returned by a query or command.\n+Definition result.hxx:73\n+pqxx::result::size_type\n+result_size_type size_type\n+Definition result.hxx:75\n+pqxx::internal::result_iter\n+Definition row.hxx:28\n+pqxx::row\n+Reference to one row in a result.\n+Definition row.hxx:47\n+pqxx::row::as\n+std::tuple< TYPE... > as() const\n+Extract entire row's values into a tuple.\n+Definition row.hxx:200\n+pqxx::row::size_type\n+row_size_type size_type\n+Definition row.hxx:49\n+pqxx::row::column_type\n+oid column_type(zview col_name) const\n+Return a column's type.\n+Definition row.hxx:128\n+pqxx::row::difference_type\n+row_difference_type difference_type\n+Definition row.hxx:50\n+pqxx::row::m_result\n+result m_result\n+Result set of which this is one row.\n+Definition row.hxx:241\n+pqxx::row::m_index\n+result::size_type m_index\n+Row number.\n+Definition row.hxx:248\n+pqxx::row::num\n+constexpr result::size_type num() const noexcept\n+Definition row.hxx:159\n+pqxx::row::row\n+row() noexcept=default\n+pqxx::row::rownumber\n+constexpr result::size_type rownumber() const noexcept\n+Row number, assuming this is a real row and not end()/rend().\n+Definition row.hxx:112\n+pqxx::row::as_tuple\n+TUPLE as_tuple() const\n+Convert to a given tuple of values, don't check sizes.\n+Definition row.hxx:225\n+pqxx::row::check_size\n+void check_size(size_type expected) const\n+Throw usage_error if row size is not expected.\n+Definition row.hxx:213\n+pqxx::row::table_column\n+size_type table_column(zview col_name) const\n+What column number in its table did this result column come from?\n+Definition row.hxx:153\n+pqxx::row::convert\n+void convert(Tuple &t) const\n+Convert entire row to tuple fields, without checking row size.\n+Definition row.hxx:233\n+pqxx::row::column_table\n+oid column_table(zview col_name) const\n+What table did this column come from?\n+Definition row.hxx:137\n+pqxx::const_row_iterator\n+Iterator for fields in a row. Use as row::const_iterator.\n+Definition row.hxx:283\n+pqxx::const_row_iterator::operator-\n+const_row_iterator operator-(difference_type) const noexcept\n+Definition row.hxx:539\n+pqxx::const_row_iterator::operator=\n+const_row_iterator & operator=(const_row_iterator &&) noexcept=default\n+pqxx::const_row_iterator::operator*\n+reference operator*() const noexcept\n+Definition row.hxx:307\n+pqxx::const_row_iterator::const_row_iterator\n+const_row_iterator(field const &F) noexcept\n+Definition row.hxx:298\n+pqxx::const_row_iterator::operator+\n+friend const_row_iterator operator+(difference_type, const_row_iterator const\n+&) noexcept\n+Definition row.hxx:532\n+pqxx::const_row_iterator::operator>=\n+constexpr bool operator>=(const_row_iterator const &i) const noexcept\n+Definition row.hxx:372\n+pqxx::const_row_iterator::const_row_iterator\n+const_row_iterator(const_row_iterator const &) noexcept=default\n+pqxx::const_row_iterator::operator=\n+const_row_iterator & operator=(const_row_iterator const &) noexcept=default\n+pqxx::const_row_iterator::iterator_category\n+std::random_access_iterator_tag iterator_category\n+Definition row.hxx:285\n+pqxx::const_row_iterator::operator==\n+constexpr bool operator==(const_row_iterator const &i) const noexcept\n+Definition row.hxx:347\n+pqxx::const_row_iterator::pointer\n+field const * pointer\n+Definition row.hxx:287\n+pqxx::const_row_iterator::value_type\n+field const value_type\n+Definition row.hxx:286\n+pqxx::const_row_iterator::operator!=\n+constexpr bool operator!=(const_row_iterator const &i) const noexcept\n+Definition row.hxx:352\n+pqxx::const_row_iterator::const_row_iterator\n+const_row_iterator(const_row_iterator &&) noexcept=default\n+pqxx::const_row_iterator::size_type\n+row_size_type size_type\n+Definition row.hxx:288\n+pqxx::const_row_iterator::operator--\n+const_row_iterator & operator--() noexcept\n+Definition row.hxx:324\n+pqxx::const_row_iterator::const_row_iterator\n+const_row_iterator() noexcept=default\n+pqxx::const_row_iterator::difference_type\n+row_difference_type difference_type\n+Definition row.hxx:289\n+pqxx::const_row_iterator::operator-=\n+const_row_iterator & operator-=(difference_type i) noexcept\n+Definition row.hxx:335\n+pqxx::const_row_iterator::operator+=\n+const_row_iterator & operator+=(difference_type i) noexcept\n+Definition row.hxx:330\n+pqxx::const_row_iterator::const_row_iterator\n+const_row_iterator(row const &t, row_size_type c) noexcept\n+Definition row.hxx:295\n+pqxx::const_row_iterator::operator>\n+constexpr bool operator>(const_row_iterator const &i) const noexcept\n+Definition row.hxx:367\n+pqxx::const_reverse_row_iterator\n+Reverse iterator for a row. Use as row::const_reverse_iterator.\n+Definition row.hxx:398\n+pqxx::const_reverse_row_iterator::operator++\n+const_reverse_row_iterator operator++() noexcept\n+Definition row.hxx:439\n+pqxx::const_reverse_row_iterator::operator!=\n+bool operator!=(const_reverse_row_iterator const &rhs) const noexcept\n+Definition row.hxx:494\n+pqxx::const_reverse_row_iterator::operator>=\n+constexpr bool operator>=(const_reverse_row_iterator const &rhs) const noexcept\n+Definition row.hxx:515\n+pqxx::const_reverse_row_iterator::operator>\n+constexpr bool operator>(const_reverse_row_iterator const &rhs) const noexcept\n+Definition row.hxx:510\n+pqxx::const_reverse_row_iterator::operator-\n+difference_type operator-(const_reverse_row_iterator const &rhs) const noexcept\n+Definition row.hxx:478\n+pqxx::const_reverse_row_iterator::operator+=\n+const_reverse_row_iterator & operator+=(difference_type i) noexcept\n+Definition row.hxx:451\n+pqxx::const_reverse_row_iterator::operator+\n+const_reverse_row_iterator operator+(difference_type i) const noexcept\n+Definition row.hxx:468\n+pqxx::const_reverse_row_iterator::operator-=\n+const_reverse_row_iterator & operator-=(difference_type i) noexcept\n+Definition row.hxx:456\n+pqxx::const_reverse_row_iterator::operator--\n+const_reverse_row_iterator & operator--() noexcept\n+Definition row.hxx:445\n+pqxx::const_reverse_row_iterator::difference_type\n+row_difference_type difference_type\n+Definition row.hxx:289\n+pqxx::const_reverse_row_iterator::operator==\n+bool operator==(const_reverse_row_iterator const &rhs) const noexcept\n+Definition row.hxx:489\n+pqxx::const_reverse_row_iterator::const_reverse_row_iterator\n+const_reverse_row_iterator() noexcept=default\n+pqxx::const_reverse_row_iterator::operator-\n+const_reverse_row_iterator operator-(difference_type i) noexcept\n+Definition row.hxx:473\n+pqxx::const_reverse_row_iterator::value_type\n+iterator_type::value_type value_type\n+Definition row.hxx:405\n+pqxx::zview\n+Marker-type wrapper: zero-terminated std::string_view.\n+Definition zview.hxx:38\n * include\n * pqxx\n- * array.hxx\n+ * row.hxx\n * Generated by [doxygen] 1.9.8\n"}]}, {"source1": "./usr/share/doc/libpqxx-doc/html/a00062_source.html", "source2": "./usr/share/doc/libpqxx-doc/html/a00062_source.html", "unified_diff": "@@ -1,15 +1,15 @@\n \n \n \n \n \n \n \n-libpqxx: params.hxx Source File\n+libpqxx: blob.hxx Source File\n \n \n \n \n \n \n \n@@ -60,312 +60,233 @@\n \n
\n
\n-
params.hxx
\n+
blob.hxx
\n
\n
\n-
1/* Helpers for prepared statements and parameterised statements.
\n+
1/* Binary Large Objects interface.
\n
2 *
\n-
3 * See the connection class for more about such statements.
\n+
3 * Read or write large objects, stored in their own storage on the server.
\n
4 *
\n-
5 * Copyright (c) 2000-2023, Jeroen T. Vermeulen.
\n+
5 * DO NOT INCLUDE THIS FILE DIRECTLY; include pqxx/largeobject instead.
\n
6 *
\n-
7 * See COPYING for copyright license. If you did not receive a file called
\n-
8 * COPYING with this source code, please notify the distributor of this
\n-
9 * mistake, or contact the author.
\n-
10 */
\n-
11#ifndef PQXX_H_PARAMS
\n-
12#define PQXX_H_PARAMS
\n-
13
\n-
14#if !defined(PQXX_HEADER_PRE)
\n-
15# error "Include libpqxx headers as <pqxx/header>, not <pqxx/header.hxx>."
\n-
16#endif
\n-
17
\n-
18#include <array>
\n+
7 * Copyright (c) 2000-2023, Jeroen T. Vermeulen.
\n+
8 *
\n+
9 * See COPYING for copyright license. If you did not receive a file called
\n+
10 * COPYING with this source code, please notify the distributor of this
\n+
11 * mistake, or contact the author.
\n+
12 */
\n+
13#ifndef PQXX_H_BLOB
\n+
14#define PQXX_H_BLOB
\n+
15
\n+
16#if !defined(PQXX_HEADER_PRE)
\n+
17# error "Include libpqxx headers as <pqxx/header>, not <pqxx/header.hxx>."
\n+
18#endif
\n
19
\n-
20#include "pqxx/internal/concat.hxx"
\n-
21#include "pqxx/internal/statement_parameters.hxx"
\n-
22#include "pqxx/types.hxx"
\n-
23
\n-
24
\n-
\n-\n-
27{
\n+
20#include <cstdint>
\n+
21
\n+
22#if defined(PQXX_HAVE_PATH)
\n+
23# include <filesystem>
\n+
24#endif
\n+
25
\n+
26#if defined(PQXX_HAVE_RANGES) && __has_include(<ranges>)
\n+
27# include <ranges>
\n+
28#endif
\n
29
\n-
46template<typename IT>
\n-
47[[deprecated("Use the params class instead.")]] constexpr inline auto
\n-
\n-
48make_dynamic_params(IT begin, IT end)
\n-
49{
\n-
50 return pqxx::internal::dynamic_params(begin, end);
\n-
51}
\n+
30#if defined(PQXX_HAVE_SPAN) && __has_include(<span>)
\n+
31# include <span>
\n+
32#endif
\n+
33
\n+
34#include "pqxx/dbtransaction.hxx"
\n+
35
\n+
36
\n+
37namespace pqxx
\n+
38{
\n+
\n+
52class PQXX_LIBEXPORT blob
\n+
53{
\n+
54public:
\n+
56
\n+
60 [[nodiscard]] static oid create(dbtransaction &, oid = 0);
\n+
61
\n+
63 static void remove(dbtransaction &, oid);
\n+
64
\n+
66 [[nodiscard]] static blob open_r(dbtransaction &, oid);
\n+
67 // Open blob for writing. Any attempt to read from it will fail.
\n+
68 [[nodiscard]] static blob open_w(dbtransaction &, oid);
\n+
69 // Open blob for reading and/or writing.
\n+
70 [[nodiscard]] static blob open_rw(dbtransaction &, oid);
\n+
71
\n+
73
\n+
76 blob() = default;
\n+
77
\n+
79 blob(blob &&);
\n+
81 blob &operator=(blob &&);
\n+
82
\n+
83 blob(blob const &) = delete;
\n+
84 blob &operator=(blob const &) = delete;
\n+
85 ~blob();
\n+
86
\n+
88
\n+
94 static constexpr std::size_t chunk_limit = 0x7fffffff;
\n+
95
\n+
97
\n+
105 std::size_t read(std::basic_string<std::byte> &buf, std::size_t size);
\n+
106
\n+
107#if defined(PQXX_HAVE_SPAN)
\n+
109
\n+
114 template<std::size_t extent = std::dynamic_extent>
\n+
115 std::span<std::byte> read(std::span<std::byte, extent> buf)
\n+
116 {
\n+
117 return buf.subspan(0, raw_read(std::data(buf), std::size(buf)));
\n+
118 }
\n+
119#endif // PQXX_HAVE_SPAN
\n+
120
\n+
121#if defined(PQXX_HAVE_CONCEPTS) && defined(PQXX_HAVE_SPAN)
\n+
123
\n+
128 template<binary DATA> std::span<std::byte> read(DATA &buf)
\n+
129 {
\n+
130 return {std::data(buf), raw_read(std::data(buf), std::size(buf))};
\n+
131 }
\n+
132#else // PQXX_HAVE_CONCEPTS && PQXX_HAVE_SPAN
\n+
134
\n+
146 template<typename ALLOC>
\n+
\n+
147 std::basic_string_view<std::byte> read(std::vector<std::byte, ALLOC> &buf)
\n+
148 {
\n+
149 return {std::data(buf), raw_read(std::data(buf), std::size(buf))};
\n+
150 }
\n+
\n+
151#endif // PQXX_HAVE_CONCEPTS && PQXX_HAVE_SPAN
\n+
152
\n+
153#if defined(PQXX_HAVE_CONCEPTS)
\n+
155
\n+
173 template<binary DATA> void write(DATA const &data)
\n+
174 {
\n+
175 raw_write(std::data(data), std::size(data));
\n+
176 }
\n+
177#else
\n+
179
\n+
\n+
197 template<typename DATA> void write(DATA const &data)
\n+
198 {
\n+
199 raw_write(std::data(data), std::size(data));
\n+
200 }
\n
\n-
52
\n-
53
\n-
55
\n-
71template<typename C>
\n-
72[[deprecated("Use the params class instead.")]] constexpr inline auto
\n-
\n-
73make_dynamic_params(C const &container)
\n-
74{
\n-
75 using IT = typename C::const_iterator;
\n-
76#include "pqxx/internal/ignore-deprecated-pre.hxx"
\n-
77 return pqxx::internal::dynamic_params<IT>{container};
\n-
78#include "pqxx/internal/ignore-deprecated-post.hxx"
\n-
79}
\n-
\n-
80
\n-
81
\n-
83
\n-
100template<typename C, typename ACCESSOR>
\n-
101[[deprecated("Use the params class instead.")]] constexpr inline auto
\n-
\n-
102make_dynamic_params(C &container, ACCESSOR accessor)
\n-
103{
\n-
104 using IT = decltype(std::begin(container));
\n-
105#include "pqxx/internal/ignore-deprecated-pre.hxx"
\n-
106 return pqxx::internal::dynamic_params<IT, ACCESSOR>{container, accessor};
\n-
107#include "pqxx/internal/ignore-deprecated-post.hxx"
\n-
108}
\n-
\n-
109} // namespace pqxx::prepare
\n-
\n-
110
\n-
111
\n-
112namespace pqxx
\n-
113{
\n-
115
\n-
\n-
125template<typename COUNTER = unsigned int> class placeholders
\n-
126{
\n-
127public:
\n-
\n-
129 static inline constexpr unsigned int max_params{
\n-
130 (std::numeric_limits<COUNTER>::max)()};
\n-
\n-
131
\n-
\n-\n-
133 {
\n-
134 static constexpr auto initial{"$1\\0"sv};
\n-
135 initial.copy(std::data(m_buf), std::size(initial));
\n-
136 }
\n-
\n-
137
\n-
139
\n-
\n-
142 constexpr zview view() const &noexcept
\n-
143 {
\n-
144 return zview{std::data(m_buf), m_len};
\n-
145 }
\n-
\n-
146
\n-
148
\n-
153 std::string get() const { return std::string(std::data(m_buf), m_len); }
\n-
154
\n-
\n-
156 void next() &
\n-
157 {
\n-
158 if (m_current >= max_params)
\n-
159 throw range_error{pqxx::internal::concat(
\n-
160 "Too many parameters in one statement: limit is ", max_params, ".")};
\n-
161 ++m_current;
\n-
162 if (m_current % 10 == 0)
\n-
163 {
\n-
164 // Carry the 1. Don't get too clever for this relatively rare
\n-
165 // case, just rewrite the entire number. Leave the $ in place
\n-
166 // though.
\n-
167 char *const data{std::data(m_buf)};
\n-
168 char *const end{string_traits<COUNTER>::into_buf(
\n-
169 data + 1, data + std::size(m_buf), m_current)};
\n-
170 // (Subtract because we don't include the trailing zero.)
\n-
171 m_len = check_cast<COUNTER>(end - data, "placeholders counter") - 1;
\n-
172 }
\n-
173 else
\n-
174 {
\n-
175 PQXX_LIKELY
\n-
176 // Shortcut for the common case: just increment that last digit.
\n-
177 ++m_buf[m_len - 1];
\n-
178 }
\n-
179 }
\n-
\n-
180
\n-
182 COUNTER count() const noexcept { return m_current; }
\n-
183
\n-
184private:
\n-
186 COUNTER m_current = 1;
\n-
187
\n-
189 COUNTER m_len = 2;
\n-
190
\n-
192
\n-
199 std::array<char, std::numeric_limits<COUNTER>::digits10 + 3> m_buf;
\n-
200};
\n-
\n-
201
\n+
201#endif
\n
202
\n
204
\n-
\n-
219class PQXX_LIBEXPORT params
\n-
220{
\n-
221public:
\n-
222 params() = default;
\n-
223
\n-
\n-
225 template<typename... Args> constexpr params(Args &&...args)
\n-
226 {
\n-
227 reserve(sizeof...(args));
\n-
228 append_pack(std::forward<Args>(args)...);
\n-
229 }
\n-
\n+
210 void resize(std::int64_t size);
\n+
211
\n+
213 [[nodiscard]] std::int64_t tell() const;
\n+
214
\n+
216
\n+
217 std::int64_t seek_abs(std::int64_t offset = 0);
\n+
219
\n+
223 std::int64_t seek_rel(std::int64_t offset = 0);
\n+
225
\n+
229 std::int64_t seek_end(std::int64_t offset = 0);
\n
230
\n
232
\n-
238 void reserve(std::size_t n) &;
\n+
235 static oid from_buf(
\n+
236 dbtransaction &tx, std::basic_string_view<std::byte> data, oid id = 0);
\n+
237
\n
239
\n-
240 // C++20: constexpr.
\n-
242 [[nodiscard]] auto size() const noexcept { return m_params.size(); }
\n+
241 static void append_from_buf(
\n+
242 dbtransaction &tx, std::basic_string_view<std::byte> data, oid id);
\n
243
\n-
244 // C++20: Use the vector's ssize() directly and go noexcept+constexpr.
\n+
245 [[nodiscard]] static oid from_file(dbtransaction &, char const path[]);
\n
246
\n-
251 [[nodiscard]] auto ssize() const { return pqxx::internal::ssize(m_params); }
\n-
252
\n-
254 void append() &;
\n-
255
\n-
257
\n-
260 void append(zview) &;
\n-
261
\n-
263
\n-
266 void append(std::string const &) &;
\n+
247#if defined(PQXX_HAVE_PATH) && !defined(_WIN32)
\n+
249
\n+
252 [[nodiscard]] static oid
\n+
253 from_file(dbtransaction &tx, std::filesystem::path const &path)
\n+
254 {
\n+
255 return from_file(tx, path.c_str());
\n+
256 }
\n+
257#endif
\n+
258
\n+
260
\n+
263 static oid from_file(dbtransaction &, char const path[], oid);
\n+
264
\n+
265#if defined(PQXX_HAVE_PATH) && !defined(_WIN32)
\n
267
\n-
269 void append(std::string &&) &;
\n-
270
\n-
272
\n-
275 void append(std::basic_string_view<std::byte>) &;
\n-
276
\n-
278
\n-
282 void append(std::basic_string<std::byte> const &) &;
\n-
283
\n-
284#if defined(PQXX_HAVE_CONCEPTS)
\n-
286
\n-
289 template<binary DATA> void append(DATA const &data) &
\n-
290 {
\n-
291 append(
\n-
292 std::basic_string_view<std::byte>{std::data(data), std::size(data)});
\n-
293 }
\n-
294#endif // PQXX_HAVE_CONCEPTS
\n-
295
\n-
297 void append(std::basic_string<std::byte> &&) &;
\n+
273 static oid
\n+
274 from_file(dbtransaction &tx, std::filesystem::path const &path, oid id)
\n+
275 {
\n+
276 return from_file(tx, path.c_str(), id);
\n+
277 }
\n+
278#endif
\n+
279
\n+
281
\n+
284 static void to_buf(
\n+
285 dbtransaction &, oid, std::basic_string<std::byte> &,
\n+
286 std::size_t max_size);
\n+
287
\n+
289
\n+
295 static std::size_t append_to_buf(
\n+
296 dbtransaction &tx, oid id, std::int64_t offset,
\n+
297 std::basic_string<std::byte> &buf, std::size_t append_max);
\n
298
\n-
300
\n-
303 void append(binarystring const &value) &;
\n+
300 static void to_file(dbtransaction &, oid, char const path[]);
\n+
301
\n+
302#if defined(PQXX_HAVE_PATH) && !defined(_WIN32)
\n
304
\n-
306 template<typename IT, typename ACCESSOR>
\n-
\n-
307 void append(pqxx::internal::dynamic_params<IT, ACCESSOR> const &value) &
\n-
308 {
\n-
309 for (auto &param : value) append(value.access(param));
\n-
310 }
\n-
\n-
311
\n-
312 void append(params const &value) &;
\n+
307 static void
\n+
308 to_file(dbtransaction &tx, oid id, std::filesystem::path const &path)
\n+
309 {
\n+
310 to_file(tx, id, path.c_str());
\n+
311 }
\n+
312#endif
\n
313
\n-
314 void append(params &&value) &;
\n
315
\n-
\n-
318 template<typename TYPE> void append(TYPE const &value) &
\n-
319 {
\n-
320 // TODO: Pool storage for multiple string conversions in one buffer?
\n-
321 if constexpr (nullness<strip_t<TYPE>>::always_null)
\n-
322 {
\n-
323 ignore_unused(value);
\n-
324 m_params.emplace_back();
\n-
325 }
\n-
326 else if (is_null(value))
\n-
327 {
\n-
328 m_params.emplace_back();
\n-
329 }
\n-
330 else
\n-
331 {
\n-
332 m_params.emplace_back(entry{to_string(value)});
\n-
333 }
\n-
334 }
\n-
\n-
335
\n-
\n-
337 template<PQXX_RANGE_ARG RANGE> void append_multi(RANGE const &range) &
\n-
338 {
\n-
339#if defined(PQXX_HAVE_CONCEPTS)
\n-
340 if constexpr (std::ranges::sized_range<RANGE>)
\n-
341 reserve(std::size(*this) + std::size(range));
\n-
342#endif
\n-
343 for (auto &value : range) append(value);
\n-
344 }
\n-
\n-
345
\n-
347
\n-
356 pqxx::internal::c_params make_c_params() const;
\n-
357
\n-
358private:
\n-
360 template<typename Arg, typename... More>
\n-
361 void append_pack(Arg &&arg, More &&...args)
\n-
362 {
\n-
363 this->append(std::forward<Arg>(arg));
\n-
364 // Recurse for remaining args.
\n-
365 append_pack(std::forward<More>(args)...);
\n-
366 }
\n-
367
\n-
369 constexpr void append_pack() noexcept {}
\n-
370
\n-
371 // The way we store a parameter depends on whether it's binary or text
\n-
372 // (most types are text), and whether we're responsible for storing the
\n-
373 // contents.
\n-
374 using entry = std::variant<
\n-
375 std::nullptr_t, zview, std::string, std::basic_string_view<std::byte>,
\n-
376 std::basic_string<std::byte>>;
\n-
377 std::vector<entry> m_params;
\n-
378
\n-
379 static constexpr std::string_view s_overflow{
\n-
380 "Statement parameter length overflow."sv};
\n-
381};
\n+
326 void close();
\n+
327
\n+
328private:
\n+
329 PQXX_PRIVATE blob(connection &conn, int fd) noexcept :
\n+
330 m_conn{&conn}, m_fd{fd}
\n+
331 {}
\n+
332 static PQXX_PRIVATE blob open_internal(dbtransaction &, oid, int);
\n+
333 static PQXX_PRIVATE pqxx::internal::pq::PGconn *
\n+
334 raw_conn(pqxx::connection *) noexcept;
\n+
335 static PQXX_PRIVATE pqxx::internal::pq::PGconn *
\n+
336 raw_conn(pqxx::dbtransaction const &) noexcept;
\n+
337 static PQXX_PRIVATE std::string errmsg(connection const *);
\n+
338 static PQXX_PRIVATE std::string errmsg(dbtransaction const &tx)
\n+
339 {
\n+
340 return errmsg(&tx.conn());
\n+
341 }
\n+
342 PQXX_PRIVATE std::string errmsg() const { return errmsg(m_conn); }
\n+
343 PQXX_PRIVATE std::int64_t seek(std::int64_t offset, int whence);
\n+
344 std::size_t raw_read(std::byte buf[], std::size_t size);
\n+
345 void raw_write(std::byte const buf[], std::size_t size);
\n+
346
\n+
347 connection *m_conn = nullptr;
\n+
348 int m_fd = -1;
\n+
349};
\n
\n-
382} // namespace pqxx
\n-
383#endif
\n+
350} // namespace pqxx
\n+
351#endif
\n
The home of all libpqxx classes, functions, templates, etc.
Definition array.hxx:33
\n-
constexpr void ignore_unused(T &&...) noexcept
Suppress compiler warning about an unused item.
Definition util.hxx:142
\n-
std::string to_string(field const &value)
Convert a field to a string.
Definition result.cxx:549
\n-
auto ssize(T const &c)
Transitional: std::ssize(), or custom implementation if not available.
Definition util.hxx:453
\n-
Definition params.hxx:27
\n-
constexpr auto make_dynamic_params(IT begin, IT end)
Pass a number of statement parameters only known at runtime.
Definition params.hxx:48
\n-
Something is out of range, similar to std::out_of_range.
Definition except.hxx:326
\n-
Generate parameter placeholders for use in an SQL statement.
Definition params.hxx:126
\n-
static constexpr unsigned int max_params
Maximum number of parameters we support.
Definition params.hxx:129
\n-
COUNTER count() const noexcept
Return the current placeholder number. The initial placeholder is 1.
Definition params.hxx:182
\n-
std::string get() const
Read the current placeholder text, as a std::string.
Definition params.hxx:153
\n-
placeholders()
Definition params.hxx:132
\n-
constexpr zview view() const &noexcept
Read an ephemeral version of the current placeholder text.
Definition params.hxx:142
\n-
void next() &
Move on to the next parameter.
Definition params.hxx:156
\n-
Build a parameter list for a parameterised or prepared statement.
Definition params.hxx:220
\n-
auto size() const noexcept
Get the number of parameters currently in this params.
Definition params.hxx:242
\n-
void append_multi(RANGE const &range) &
Append all elements of range as parameters.
Definition params.hxx:337
\n-
void append(TYPE const &value) &
Definition params.hxx:318
\n-
params()=default
\n-
auto ssize() const
Get the number of parameters (signed).
Definition params.hxx:251
\n-
void append(pqxx::internal::dynamic_params< IT, ACCESSOR > const &value) &
Append all parameters from value.
Definition params.hxx:307
\n-
constexpr params(Args &&...args)
Pre-populate a params with args. Feel free to add more later.
Definition params.hxx:225
\n-
A C++ equivalent to PostgreSQL's range types.
Definition range.hxx:234
\n-
Traits describing a type's "null value," if any.
Definition strconv.hxx:93
\n-
static char * into_buf(char *begin, char *end, TYPE const &value)
Write value's string representation into buffer at begin.
\n-
Marker-type wrapper: zero-terminated std::string_view.
Definition zview.hxx:38
\n+
Definition blob.hxx:53
\n+
void write(DATA const &data)
Write data large object, at the current position.
Definition blob.hxx:197
\n+
blob(blob const &)=delete
\n+
blob()=default
You can default-construct a blob, but it won't do anything useful.
\n+
std::basic_string_view< std::byte > read(std::vector< std::byte, ALLOC > &buf)
Read up to std::size(buf) bytes from the object.
Definition blob.hxx:147
\n+
blob & operator=(blob const &)=delete
\n+
Connection to a database.
Definition connection.hxx:253
\n+
Abstract transaction base class: bracket transactions on the database.
Definition dbtransaction.hxx:54
\n
\n
\n \n
\n \n
\n \n \n", "details": [{"source1": "html2text {}", "source2": "html2text {}", "unified_diff": "@@ -1,340 +1,235 @@\n \n \n \n \n \n libpqxx\u00a07.8.1\n \n-params.hxx\n- 1/* Helpers for prepared statements and parameterised statements.\n+blob.hxx\n+ 1/* Binary Large Objects interface.\n 2 *\n- 3 * See the connection class for more about such statements.\n+ 3 * Read or write large objects, stored in their own storage on the server.\n 4 *\n- 5 * Copyright (c) 2000-2023, Jeroen T. Vermeulen.\n+ 5 * DO NOT INCLUDE THIS FILE DIRECTLY; include pqxx/largeobject instead.\n 6 *\n- 7 * See COPYING for copyright license. If you did not receive a file called\n- 8 * COPYING with this source code, please notify the distributor of this\n- 9 * mistake, or contact the author.\n- 10 */\n- 11#ifndef PQXX_H_PARAMS\n- 12#define PQXX_H_PARAMS\n- 13\n- 14#if !defined(PQXX_HEADER_PRE)\n- 15# error \"Include libpqxx headers as , not .\"\n- 16#endif\n- 17\n- 18#include \n+ 7 * Copyright (c) 2000-2023, Jeroen T. Vermeulen.\n+ 8 *\n+ 9 * See COPYING for copyright license. If you did not receive a file called\n+ 10 * COPYING with this source code, please notify the distributor of this\n+ 11 * mistake, or contact the author.\n+ 12 */\n+ 13#ifndef PQXX_H_BLOB\n+ 14#define PQXX_H_BLOB\n+ 15\n+ 16#if !defined(PQXX_HEADER_PRE)\n+ 17# error \"Include libpqxx headers as , not .\"\n+ 18#endif\n 19\n- 20#include \"pqxx/internal/concat.hxx\"\n- 21#include \"pqxx/internal/statement_parameters.hxx\"\n- 22#include \"pqxx/types.hxx\"\n- 23\n- 24\n-26namespace pqxx::prepare\n- 27{\n+ 20#include \n+ 21\n+ 22#if defined(PQXX_HAVE_PATH)\n+ 23# include \n+ 24#endif\n+ 25\n+ 26#if defined(PQXX_HAVE_RANGES) && __has_include()\n+ 27# include \n+ 28#endif\n 29\n- 46template\n- 47[[deprecated(\"Use the params class instead.\")]] constexpr inline auto\n-48make_dynamic_params(IT begin, IT end)\n- 49{\n- 50 return pqxx::internal::dynamic_params(begin, end);\n- 51}\n- 52\n- 53\n- 55\n- 71template\n- 72[[deprecated(\"Use the params class instead.\")]] constexpr inline auto\n-73make_dynamic_params(C const &container)\n- 74{\n- 75 using IT = typename C::const_iterator;\n- 76#include \"pqxx/internal/ignore-deprecated-pre.hxx\"\n- 77 return pqxx::internal::dynamic_params{container};\n- 78#include \"pqxx/internal/ignore-deprecated-post.hxx\"\n- 79}\n- 80\n- 81\n- 83\n- 100template\n- 101[[deprecated(\"Use the params class instead.\")]] constexpr inline auto\n-102make_dynamic_params(C &container, ACCESSOR accessor)\n- 103{\n- 104 using IT = decltype(std::begin(container));\n- 105#include \"pqxx/internal/ignore-deprecated-pre.hxx\"\n- 106 return pqxx::internal::dynamic_params{container, accessor};\n- 107#include \"pqxx/internal/ignore-deprecated-post.hxx\"\n- 108}\n- 109} // namespace pqxx::prepare\n- 110\n- 111\n- 112namespace pqxx\n- 113{\n- 115\n-125template class placeholders\n- 126{\n- 127public:\n-129 static inline constexpr unsigned int max_params{\n- 130 (std::numeric_limits::max)()};\n- 131\n-132 placeholders()\n- 133 {\n- 134 static constexpr auto initial{\"$1\\0\"sv};\n- 135 initial.copy(std::data(m_buf), std::size(initial));\n- 136 }\n- 137\n- 139\n-142 constexpr zview view() const &noexcept\n- 143 {\n- 144 return zview{std::data(m_buf), m_len};\n- 145 }\n- 146\n- 148\n-153 std::string get() const { return std::string(std::data(m_buf), m_len); }\n- 154\n-156 void next() &\n- 157 {\n- 158 if (m_current >= max_params)\n- 159 throw range_error{pqxx::internal::concat(\n- 160 \"Too many parameters in one statement: limit is \", max_params, \".\")};\n- 161 ++m_current;\n- 162 if (m_current % 10 == 0)\n- 163 {\n- 164 // Carry the 1. Don't get too clever for this relatively rare\n- 165 // case, just rewrite the entire number. Leave the $ in place\n- 166 // though.\n- 167 char *const data{std::data(m_buf)};\n- 168 char *const end{string_traits::into_buf(\n- 169 data + 1, data + std::size(m_buf), m_current)};\n- 170 // (Subtract because we don't include the trailing zero.)\n- 171 m_len = check_cast(end - data, \"placeholders counter\") - 1;\n- 172 }\n- 173 else\n+ 30#if defined(PQXX_HAVE_SPAN) && __has_include()\n+ 31# include \n+ 32#endif\n+ 33\n+ 34#include \"pqxx/dbtransaction.hxx\"\n+ 35\n+ 36\n+ 37namespace pqxx\n+ 38{\n+52class PQXX_LIBEXPORT blob\n+ 53{\n+ 54public:\n+ 56\n+ 60 [[nodiscard]] static oid create(dbtransaction &, oid = 0);\n+ 61\n+ 63 static void remove(dbtransaction &, oid);\n+ 64\n+ 66 [[nodiscard]] static blob open_r(dbtransaction &, oid);\n+ 67 // Open blob for writing. Any attempt to read from it will fail.\n+ 68 [[nodiscard]] static blob open_w(dbtransaction &, oid);\n+ 69 // Open blob for reading and/or writing.\n+ 70 [[nodiscard]] static blob open_rw(dbtransaction &, oid);\n+ 71\n+ 73\n+76 blob() = default;\n+ 77\n+ 79 blob(blob &&);\n+ 81 blob &operator=(blob &&);\n+ 82\n+83 blob(blob const &) = delete;\n+84 blob &operator=(blob const &) = delete;\n+ 85 ~blob();\n+ 86\n+ 88\n+94 static constexpr std::size_t chunk_limit = 0x7fffffff;\n+ 95\n+ 97\n+ 105 std::size_t read(std::basic_string &buf, std::size_t size);\n+ 106\n+ 107#if defined(PQXX_HAVE_SPAN)\n+ 109\n+ 114 template\n+ 115 std::span read(std::span buf)\n+ 116 {\n+ 117 return buf.subspan(0, raw_read(std::data(buf), std::size(buf)));\n+ 118 }\n+ 119#endif // PQXX_HAVE_SPAN\n+ 120\n+ 121#if defined(PQXX_HAVE_CONCEPTS) && defined(PQXX_HAVE_SPAN)\n+ 123\n+ 128 template std::span read(DATA &buf)\n+ 129 {\n+ 130 return {std::data(buf), raw_read(std::data(buf), std::size(buf))};\n+ 131 }\n+ 132#else // PQXX_HAVE_CONCEPTS && PQXX_HAVE_SPAN\n+ 134\n+ 146 template\n+147 std::basic_string_view read(std::vector &buf)\n+ 148 {\n+ 149 return {std::data(buf), raw_read(std::data(buf), std::size(buf))};\n+ 150 }\n+ 151#endif // PQXX_HAVE_CONCEPTS && PQXX_HAVE_SPAN\n+ 152\n+ 153#if defined(PQXX_HAVE_CONCEPTS)\n+ 155\n+ 173 template void write(DATA const &data)\n 174 {\n- 175 PQXX_LIKELY\n- 176 // Shortcut for the common case: just increment that last digit.\n- 177 ++m_buf[m_len - 1];\n- 178 }\n- 179 }\n- 180\n-182 COUNTER count() const noexcept { return m_current; }\n- 183\n- 184private:\n- 186 COUNTER m_current = 1;\n- 187\n- 189 COUNTER m_len = 2;\n- 190\n- 192\n- 199 std::array::digits10 + 3> m_buf;\n- 200};\n- 201\n+ 175 raw_write(std::data(data), std::size(data));\n+ 176 }\n+ 177#else\n+ 179\n+197 template void write(DATA const &data)\n+ 198 {\n+ 199 raw_write(std::data(data), std::size(data));\n+ 200 }\n+ 201#endif\n 202\n 204\n-219class PQXX_LIBEXPORT params\n- 220{\n- 221public:\n-222 params() = default;\n- 223\n-225 template constexpr params(Args &&...args)\n- 226 {\n- 227 reserve(sizeof...(args));\n- 228 append_pack(std::forward(args)...);\n- 229 }\n+ 210 void resize(std::int64_t size);\n+ 211\n+ 213 [[nodiscard]] std::int64_t tell() const;\n+ 214\n+ 216\n+ 217 std::int64_t seek_abs(std::int64_t offset = 0);\n+ 219\n+ 223 std::int64_t seek_rel(std::int64_t offset = 0);\n+ 225\n+ 229 std::int64_t seek_end(std::int64_t offset = 0);\n 230\n 232\n- 238 void reserve(std::size_t n) &;\n+ 235 static oid from_buf(\n+ 236 dbtransaction &tx, std::basic_string_view data, oid id = 0);\n+ 237\n 239\n- 240 // C++20: constexpr.\n-242 [[nodiscard]] auto size() const noexcept { return m_params.size(); }\n+ 241 static void append_from_buf(\n+ 242 dbtransaction &tx, std::basic_string_view data, oid id);\n 243\n- 244 // C++20: Use the vector's ssize() directly and go noexcept+constexpr.\n+ 245 [[nodiscard]] static oid from_file(dbtransaction &, char const path[]);\n 246\n-251 [[nodiscard]] auto ssize() const { return pqxx::internal::ssize(m_params);\n-}\n- 252\n- 254 void append() &;\n- 255\n- 257\n- 260 void append(zview) &;\n- 261\n- 263\n- 266 void append(std::string const &) &;\n+ 247#if defined(PQXX_HAVE_PATH) && !defined(_WIN32)\n+ 249\n+ 252 [[nodiscard]] static oid\n+ 253 from_file(dbtransaction &tx, std::filesystem::path const &path)\n+ 254 {\n+ 255 return from_file(tx, path.c_str());\n+ 256 }\n+ 257#endif\n+ 258\n+ 260\n+ 263 static oid from_file(dbtransaction &, char const path[], oid);\n+ 264\n+ 265#if defined(PQXX_HAVE_PATH) && !defined(_WIN32)\n 267\n- 269 void append(std::string &&) &;\n- 270\n- 272\n- 275 void append(std::basic_string_view) &;\n- 276\n- 278\n- 282 void append(std::basic_string const &) &;\n- 283\n- 284#if defined(PQXX_HAVE_CONCEPTS)\n- 286\n- 289 template void append(DATA const &data) &\n- 290 {\n- 291 append(\n- 292 std::basic_string_view{std::data(data), std::size(data)});\n- 293 }\n- 294#endif // PQXX_HAVE_CONCEPTS\n- 295\n- 297 void append(std::basic_string &&) &;\n+ 273 static oid\n+ 274 from_file(dbtransaction &tx, std::filesystem::path const &path, oid id)\n+ 275 {\n+ 276 return from_file(tx, path.c_str(), id);\n+ 277 }\n+ 278#endif\n+ 279\n+ 281\n+ 284 static void to_buf(\n+ 285 dbtransaction &, oid, std::basic_string &,\n+ 286 std::size_t max_size);\n+ 287\n+ 289\n+ 295 static std::size_t append_to_buf(\n+ 296 dbtransaction &tx, oid id, std::int64_t offset,\n+ 297 std::basic_string &buf, std::size_t append_max);\n 298\n- 300\n- 303 void append(binarystring const &value) &;\n+ 300 static void to_file(dbtransaction &, oid, char const path[]);\n+ 301\n+ 302#if defined(PQXX_HAVE_PATH) && !defined(_WIN32)\n 304\n- 306 template\n-307 void append(pqxx::internal::dynamic_params const &value) &\n- 308 {\n- 309 for (auto ¶m : value) append(value.access(param));\n- 310 }\n- 311\n- 312 void append(params const &value) &;\n+ 307 static void\n+ 308 to_file(dbtransaction &tx, oid id, std::filesystem::path const &path)\n+ 309 {\n+ 310 to_file(tx, id, path.c_str());\n+ 311 }\n+ 312#endif\n 313\n- 314 void append(params &&value) &;\n 315\n-318 template void append(TYPE const &value) &\n- 319 {\n- 320 // TODO: Pool storage for multiple string conversions in one buffer?\n- 321 if constexpr (nullness>::always_null)\n- 322 {\n- 323 ignore_unused(value);\n- 324 m_params.emplace_back();\n- 325 }\n- 326 else if (is_null(value))\n- 327 {\n- 328 m_params.emplace_back();\n- 329 }\n- 330 else\n- 331 {\n- 332 m_params.emplace_back(entry{to_string(value)});\n- 333 }\n- 334 }\n- 335\n-337 template void append_multi(RANGE const &range) &\n- 338 {\n- 339#if defined(PQXX_HAVE_CONCEPTS)\n- 340 if constexpr (std::ranges::sized_range)\n- 341 reserve(std::size(*this) + std::size(range));\n- 342#endif\n- 343 for (auto &value : range) append(value);\n- 344 }\n- 345\n- 347\n- 356 pqxx::internal::c_params make_c_params() const;\n- 357\n- 358private:\n- 360 template\n- 361 void append_pack(Arg &&arg, More &&...args)\n- 362 {\n- 363 this->append(std::forward(arg));\n- 364 // Recurse for remaining args.\n- 365 append_pack(std::forward(args)...);\n- 366 }\n- 367\n- 369 constexpr void append_pack() noexcept {}\n- 370\n- 371 // The way we store a parameter depends on whether it's binary or text\n- 372 // (most types are text), and whether we're responsible for storing the\n- 373 // contents.\n- 374 using entry = std::variant<\n- 375 std::nullptr_t, zview, std::string, std::basic_string_view,\n- 376 std::basic_string>;\n- 377 std::vector m_params;\n- 378\n- 379 static constexpr std::string_view s_overflow{\n- 380 \"Statement parameter length overflow.\"sv};\n- 381};\n- 382} // namespace pqxx\n- 383#endif\n+ 326 void close();\n+ 327\n+ 328private:\n+ 329 PQXX_PRIVATE blob(connection &conn, int fd) noexcept :\n+ 330 m_conn{&conn}, m_fd{fd}\n+ 331 {}\n+ 332 static PQXX_PRIVATE blob open_internal(dbtransaction &, oid, int);\n+ 333 static PQXX_PRIVATE pqxx::internal::pq::PGconn *\n+ 334 raw_conn(pqxx::connection *) noexcept;\n+ 335 static PQXX_PRIVATE pqxx::internal::pq::PGconn *\n+ 336 raw_conn(pqxx::dbtransaction const &) noexcept;\n+ 337 static PQXX_PRIVATE std::string errmsg(connection const *);\n+ 338 static PQXX_PRIVATE std::string errmsg(dbtransaction const &tx)\n+ 339 {\n+ 340 return errmsg(&tx.conn());\n+ 341 }\n+ 342 PQXX_PRIVATE std::string errmsg() const { return errmsg(m_conn); }\n+ 343 PQXX_PRIVATE std::int64_t seek(std::int64_t offset, int whence);\n+ 344 std::size_t raw_read(std::byte buf[], std::size_t size);\n+ 345 void raw_write(std::byte const buf[], std::size_t size);\n+ 346\n+ 347 connection *m_conn = nullptr;\n+ 348 int m_fd = -1;\n+ 349};\n+ 350} // namespace pqxx\n+ 351#endif\n pqxx\n The home of all libpqxx classes, functions, templates, etc.\n Definition array.hxx:33\n-pqxx::ignore_unused\n-constexpr void ignore_unused(T &&...) noexcept\n-Suppress compiler warning about an unused item.\n-Definition util.hxx:142\n-pqxx::to_string\n-std::string to_string(field const &value)\n-Convert a field to a string.\n-Definition result.cxx:549\n-pqxx::internal::ssize\n-auto ssize(T const &c)\n-Transitional: std::ssize(), or custom implementation if not available.\n-Definition util.hxx:453\n-pqxx::prepare\n-Definition params.hxx:27\n-pqxx::prepare::make_dynamic_params\n-constexpr auto make_dynamic_params(IT begin, IT end)\n-Pass a number of statement parameters only known at runtime.\n-Definition params.hxx:48\n-pqxx::range_error\n-Something is out of range, similar to std::out_of_range.\n-Definition except.hxx:326\n-pqxx::placeholders\n-Generate parameter placeholders for use in an SQL statement.\n-Definition params.hxx:126\n-pqxx::placeholders::max_params\n-static constexpr unsigned int max_params\n-Maximum number of parameters we support.\n-Definition params.hxx:129\n-pqxx::placeholders::count\n-COUNTER count() const noexcept\n-Return the current placeholder number. The initial placeholder is 1.\n-Definition params.hxx:182\n-pqxx::placeholders::get\n-std::string get() const\n-Read the current placeholder text, as a std::string.\n-Definition params.hxx:153\n-pqxx::placeholders::placeholders\n-placeholders()\n-Definition params.hxx:132\n-pqxx::placeholders::view\n-constexpr zview view() const &noexcept\n-Read an ephemeral version of the current placeholder text.\n-Definition params.hxx:142\n-pqxx::placeholders::next\n-void next() &\n-Move on to the next parameter.\n-Definition params.hxx:156\n-pqxx::params\n-Build a parameter list for a parameterised or prepared statement.\n-Definition params.hxx:220\n-pqxx::params::size\n-auto size() const noexcept\n-Get the number of parameters currently in this params.\n-Definition params.hxx:242\n-pqxx::params::append_multi\n-void append_multi(RANGE const &range) &\n-Append all elements of range as parameters.\n-Definition params.hxx:337\n-pqxx::params::append\n-void append(TYPE const &value) &\n-Definition params.hxx:318\n-pqxx::params::params\n-params()=default\n-pqxx::params::ssize\n-auto ssize() const\n-Get the number of parameters (signed).\n-Definition params.hxx:251\n-pqxx::params::append\n-void append(pqxx::internal::dynamic_params< IT, ACCESSOR > const &value) &\n-Append all parameters from value.\n-Definition params.hxx:307\n-pqxx::params::params\n-constexpr params(Args &&...args)\n-Pre-populate a params with args. Feel free to add more later.\n-Definition params.hxx:225\n-pqxx::range\n-A C++ equivalent to PostgreSQL's range types.\n-Definition range.hxx:234\n-pqxx::nullness\n-Traits describing a type's \"null value,\" if any.\n-Definition strconv.hxx:93\n-pqxx::string_traits::into_buf\n-static char * into_buf(char *begin, char *end, TYPE const &value)\n-Write value's string representation into buffer at begin.\n-pqxx::zview\n-Marker-type wrapper: zero-terminated std::string_view.\n-Definition zview.hxx:38\n+pqxx::blob\n+Definition blob.hxx:53\n+pqxx::blob::write\n+void write(DATA const &data)\n+Write data large object, at the current position.\n+Definition blob.hxx:197\n+pqxx::blob::blob\n+blob(blob const &)=delete\n+pqxx::blob::blob\n+blob()=default\n+You can default-construct a blob, but it won't do anything useful.\n+pqxx::blob::read\n+std::basic_string_view< std::byte > read(std::vector< std::byte, ALLOC > &buf)\n+Read up to std::size(buf) bytes from the object.\n+Definition blob.hxx:147\n+pqxx::blob::operator=\n+blob & operator=(blob const &)=delete\n+pqxx::connection\n+Connection to a database.\n+Definition connection.hxx:253\n+pqxx::dbtransaction\n+Abstract transaction base class: bracket transactions on the database.\n+Definition dbtransaction.hxx:54\n * include\n * pqxx\n- * params.hxx\n+ * blob.hxx\n * Generated by [doxygen] 1.9.8\n"}]}, {"source1": "./usr/share/doc/libpqxx-doc/html/a00065_source.html", "source2": "./usr/share/doc/libpqxx-doc/html/a00065_source.html", "unified_diff": "@@ -1,15 +1,15 @@\n \n \n \n \n \n \n \n-libpqxx: binarystring.hxx Source File\n+libpqxx: connection.hxx Source File\n \n \n \n \n \n \n \n@@ -60,284 +60,822 @@\n \n
\n
\n-
binarystring.hxx
\n+
connection.hxx
\n
\n
\n-
1/* Deprecated representation for raw, binary data.
\n+
1/* Definition of the connection class.
\n
2 *
\n-
3 * DO NOT INCLUDE THIS FILE DIRECTLY; include pqxx/binarystring instead.
\n+
3 * pqxx::connection encapsulates a connection to a database.
\n
4 *
\n-
5 * Copyright (c) 2000-2023, Jeroen T. Vermeulen.
\n+
5 * DO NOT INCLUDE THIS FILE DIRECTLY; include pqxx/connection instead.
\n
6 *
\n-
7 * See COPYING for copyright license. If you did not receive a file called
\n-
8 * COPYING with this source code, please notify the distributor of this
\n-
9 * mistake, or contact the author.
\n-
10 */
\n-
11#ifndef PQXX_H_BINARYSTRING
\n-
12#define PQXX_H_BINARYSTRING
\n-
13
\n-
14#if !defined(PQXX_HEADER_PRE)
\n-
15# error "Include libpqxx headers as <pqxx/header>, not <pqxx/header.hxx>."
\n-
16#endif
\n-
17
\n-
18#include <memory>
\n-
19#include <string>
\n-
20#include <string_view>
\n-
21
\n-
22#include "pqxx/result.hxx"
\n-
23#include "pqxx/strconv.hxx"
\n-
24
\n-
25namespace pqxx
\n-
26{
\n-
27class binarystring;
\n-
28template<> struct string_traits<binarystring>;
\n-
29
\n-
30
\n-
32
\n-
\n-
58class PQXX_LIBEXPORT binarystring
\n-
59{
\n-
60public:
\n-
61 using char_type = unsigned char;
\n-
62 using value_type = std::char_traits<char_type>::char_type;
\n-
63 using size_type = std::size_t;
\n-
64 using difference_type = long;
\n-
65 using const_reference = value_type const &;
\n-
66 using const_pointer = value_type const *;
\n-\n-
68 using const_reverse_iterator = std::reverse_iterator<const_iterator>;
\n-
69
\n-
70 [[deprecated("Use std::byte for binary data.")]] binarystring(
\n-
71 binarystring const &) = default;
\n-
72
\n-
74
\n-
78 [[deprecated("Use std::byte for binary data.")]] explicit binarystring(
\n-
79 field const &);
\n-
80
\n-
82
\n-
85 [[deprecated("Use std::byte for binary data.")]] explicit binarystring(
\n-
86 std::string_view);
\n-
87
\n-
89 [[deprecated("Use std::byte for binary data.")]] binarystring(
\n-
90 void const *, std::size_t);
\n-
91
\n-
\n-
93 [[deprecated("Use std::byte for binary data.")]] binarystring(
\n-
94 std::shared_ptr<value_type> ptr, size_type size) :
\n-
95 m_buf{std::move(ptr)}, m_size{size}
\n-
96 {}
\n-
\n+
7 * Copyright (c) 2000-2023, Jeroen T. Vermeulen.
\n+
8 *
\n+
9 * See COPYING for copyright license. If you did not receive a file called
\n+
10 * COPYING with this source code, please notify the distributor of this
\n+
11 * mistake, or contact the author.
\n+
12 */
\n+
13#ifndef PQXX_H_CONNECTION
\n+
14#define PQXX_H_CONNECTION
\n+
15
\n+
16#if !defined(PQXX_HEADER_PRE)
\n+
17# error "Include libpqxx headers as <pqxx/header>, not <pqxx/header.hxx>."
\n+
18#endif
\n+
19
\n+
20#include <cstddef>
\n+
21#include <ctime>
\n+
22#include <initializer_list>
\n+
23#include <list>
\n+
24#include <map>
\n+
25#include <memory>
\n+
26#include <string_view>
\n+
27#include <tuple>
\n+
28
\n+
29// Double-check in order to suppress an overzealous Visual C++ warning (#418).
\n+
30#if defined(PQXX_HAVE_CONCEPTS) && __has_include(<ranges>)
\n+
31# include <ranges>
\n+
32#endif
\n+
33
\n+
34#include "pqxx/errorhandler.hxx"
\n+
35#include "pqxx/except.hxx"
\n+
36#include "pqxx/internal/concat.hxx"
\n+
37#include "pqxx/params.hxx"
\n+
38#include "pqxx/separated_list.hxx"
\n+
39#include "pqxx/strconv.hxx"
\n+
40#include "pqxx/types.hxx"
\n+
41#include "pqxx/util.hxx"
\n+
42#include "pqxx/zview.hxx"
\n+
43
\n+
44
\n+
75namespace pqxx::internal
\n+
76{
\n+
77class sql_cursor;
\n+
78
\n+
79#if defined(PQXX_HAVE_CONCEPTS)
\n+
81template<typename T>
\n+
82concept ZKey_ZValues =
\n+
83 std::ranges::input_range<T> and
\n+
84 requires(T t) {
\n+
85 {
\n+
86 std::cbegin(t)
\n+
87 };
\n+
88 {
\n+
89 std::get<0>(*std::cbegin(t))
\n+
90 } -> ZString;
\n+
91 {
\n+
92 std::get<1>(*std::cbegin(t))
\n+
93 } -> ZString;
\n+
94 } and
\n+
95 std::tuple_size_v<typename std::ranges::iterator_t<T>::value_type> == 2;
\n+
96#endif // PQXX_HAVE_CONCEPTS
\n
97
\n-
99 [[nodiscard]] size_type size() const noexcept { return m_size; }
\n-
101 [[nodiscard]] size_type length() const noexcept { return size(); }
\n-
102 [[nodiscard]] bool empty() const noexcept { return size() == 0; }
\n-
103
\n-
104 [[nodiscard]] const_iterator begin() const noexcept { return data(); }
\n-
105 [[nodiscard]] const_iterator cbegin() const noexcept { return begin(); }
\n-
106 [[nodiscard]] const_iterator end() const noexcept { return data() + m_size; }
\n-
107 [[nodiscard]] const_iterator cend() const noexcept { return end(); }
\n-
108
\n-
109 [[nodiscard]] const_reference front() const noexcept { return *begin(); }
\n-
\n-
110 [[nodiscard]] const_reference back() const noexcept
\n-
111 {
\n-
112 return *(data() + m_size - 1);
\n-
113 }
\n-
\n-
114
\n-
\n-
115 [[nodiscard]] const_reverse_iterator rbegin() const
\n-
116 {
\n-
117 return const_reverse_iterator{end()};
\n-
118 }
\n-
\n-
119 [[nodiscard]] const_reverse_iterator crbegin() const { return rbegin(); }
\n-
\n-
120 [[nodiscard]] const_reverse_iterator rend() const
\n-
121 {
\n-
122 return const_reverse_iterator{begin()};
\n-
123 }
\n+
98
\n+
100
\n+
107void PQXX_COLD PQXX_LIBEXPORT skip_init_ssl(int flags) noexcept;
\n+
108} // namespace pqxx::internal
\n+
109
\n+
110
\n+
\n+\n+
112{
\n+
113class connection_dbtransaction;
\n+
114class connection_errorhandler;
\n+
115class connection_largeobject;
\n+
116class connection_notification_receiver;
\n+
117class connection_pipeline;
\n+
118class connection_sql_cursor;
\n+
119struct connection_stream_from;
\n+
120class connection_stream_to;
\n+
121class connection_transaction;
\n+
122class const_connection_largeobject;
\n+
123} // namespace pqxx::internal::gate
\n
\n-
124 [[nodiscard]] const_reverse_iterator crend() const { return rend(); }
\n+
124
\n
125
\n-
127 [[nodiscard]] value_type const *data() const noexcept { return m_buf.get(); }
\n-
128
\n-
\n-
129 [[nodiscard]] const_reference operator[](size_type i) const noexcept
\n-
130 {
\n-
131 return data()[i];
\n-
132 }
\n-
\n-
133
\n-
134 [[nodiscard]] PQXX_PURE bool operator==(binarystring const &) const noexcept;
\n-
\n-
135 [[nodiscard]] bool operator!=(binarystring const &rhs) const noexcept
\n-
136 {
\n-
137 return not operator==(rhs);
\n-
138 }
\n-
\n-
139
\n-\n-
141
\n-
143 const_reference at(size_type) const;
\n-
144
\n-
146 void swap(binarystring &);
\n+
126namespace pqxx
\n+
127{
\n+
129
\n+
\n+
136enum skip_init : int
\n+
137{
\n+\n+
140
\n+\n+
143
\n+\n+
146};
\n+
\n
147
\n-
149
\n-
\n-
152 [[nodiscard]] char const *get() const noexcept
\n-
153 {
\n-
154 return reinterpret_cast<char const *>(m_buf.get());
\n-
155 }
\n-
\n-
156
\n-
\n-
158 [[nodiscard]] std::string_view view() const noexcept
\n-
159 {
\n-
160 return std::string_view(get(), size());
\n-
161 }
\n-
\n-
162
\n-
164
\n-
169 [[nodiscard]] std::string str() const;
\n-
170
\n-
\n-
172 [[nodiscard]] std::byte const *bytes() const
\n-
173 {
\n-
174 return reinterpret_cast<std::byte const *>(get());
\n-
175 }
\n-
\n-
176
\n-
\n-
178 [[nodiscard]] std::basic_string_view<std::byte> bytes_view() const
\n-
179 {
\n-
180 return std::basic_string_view<std::byte>{bytes(), size()};
\n-
181 }
\n-
\n-
182
\n-
183private:
\n-
184 std::shared_ptr<value_type> m_buf;
\n-
185 size_type m_size{0};
\n-
186};
\n-
\n-
187
\n-
188
\n-
\n-
189template<> struct nullness<binarystring> : no_null<binarystring>
\n-
190{};
\n-
\n-
191
\n-
192
\n-
194
\n-
\n-
201template<> struct string_traits<binarystring>
\n-
202{
\n-
\n-
203 static std::size_t size_buffer(binarystring const &value) noexcept
\n-
204 {
\n-
205 return internal::size_esc_bin(std::size(value));
\n-
206 }
\n+
148
\n+
150
\n+
\n+
173template<skip_init... SKIP> inline void skip_init_ssl() noexcept
\n+
174{
\n+
175 // (Normalise skip flags to one per.)
\n+
176 pqxx::internal::skip_init_ssl(((1 << SKIP) | ...));
\n+
177}
\n+
\n+
178
\n+
179
\n+
181
\n+
188using table_path = std::initializer_list<std::string_view>;
\n+
189
\n+
190
\n+
192[[nodiscard,
\n+
193 deprecated("Use connection::encrypt_password instead.")]] std::string
\n+
194 PQXX_LIBEXPORT
\n+
195 encrypt_password(char const user[], char const password[]);
\n+
196
\n+
198[[nodiscard,
\n+
199 deprecated("Use connection::encrypt_password instead.")]] inline std::string
\n+
\n+\n+
201{
\n+
202#include "pqxx/internal/ignore-deprecated-pre.hxx"
\n+
203 return encrypt_password(user.c_str(), password.c_str());
\n+
204#include "pqxx/internal/ignore-deprecated-post.hxx"
\n+
205}
\n
\n+
206
\n
207
\n-
\n-
208 static zview to_buf(char *begin, char *end, binarystring const &value)
\n-
209 {
\n-
210 return generic_to_buf(begin, end, value);
\n-
211 }
\n-
\n-
212
\n-
\n-
213 static char *into_buf(char *begin, char *end, binarystring const &value)
\n-
214 {
\n-
215 auto const budget{size_buffer(value)};
\n-
216 if (internal::cmp_less(end - begin, budget))
\n-
217 throw conversion_overrun{
\n-
218 "Not enough buffer space to escape binary data."};
\n-
219 std::string_view text{value.view()};
\n-\n-
221 return begin + budget;
\n-
222 }
\n-
\n-
223
\n-
\n-
224 static binarystring from_string(std::string_view text)
\n-
225 {
\n-
226 auto const size{pqxx::internal::size_unesc_bin(std::size(text))};
\n-
227 std::shared_ptr<unsigned char> buf{
\n-
228 new unsigned char[size], [](unsigned char const *x) { delete[] x; }};
\n-
229 pqxx::internal::unesc_bin(text, reinterpret_cast<std::byte *>(buf.get()));
\n-
230#include "pqxx/internal/ignore-deprecated-pre.hxx"
\n-
231 return binarystring{std::move(buf), size};
\n-
232#include "pqxx/internal/ignore-deprecated-post.hxx"
\n-
233 }
\n-
\n-
234};
\n-
\n-
235} // namespace pqxx
\n-
236#endif
\n+
\n+
209enum class error_verbosity : int
\n+
210{
\n+
211 // These values must match those in libpq's PGVerbosity enum.
\n+
212 terse = 0,
\n+
213 normal = 1,
\n+
214 verbose = 2
\n+
215};
\n+
\n+
216
\n+
217
\n+
219
\n+
\n+
252class PQXX_LIBEXPORT connection
\n+
253{
\n+
254public:
\n+\n+
256
\n+
\n+
258 explicit connection(char const options[])
\n+
259 {
\n+\n+
261 init(options);
\n+
262 }
\n+
\n+
263
\n+
\n+
265 explicit connection(zview options) : connection{options.c_str()}
\n+
266 {
\n+
267 // (Delegates to other constructor which calls check_version for us.)
\n+
268 }
\n+
\n+
269
\n+
271
\n+
276 connection(connection &&rhs);
\n+
277
\n+
278#if defined(PQXX_HAVE_CONCEPTS)
\n+
280
\n+
295 template<internal::ZKey_ZValues MAPPING>
\n+
296 inline connection(MAPPING const &params);
\n+
297#endif // PQXX_HAVE_CONCEPTS
\n+
298
\n+
\n+\n+
300 {
\n+
301 try
\n+
302 {
\n+
303 close();
\n+
304 }
\n+
305 catch (std::exception const &)
\n+
306 {}
\n+
307 }
\n+
\n+
308
\n+
310
\n+
313 connection &operator=(connection &&rhs);
\n+
314
\n+
315 connection(connection const &) = delete;
\n+
316 connection &operator=(connection const &) = delete;
\n+
317
\n+
319
\n+
324 [[nodiscard]] bool PQXX_PURE is_open() const noexcept;
\n+
325
\n+
327 void process_notice(char const[]) noexcept;
\n+
329
\n+
332 void process_notice(zview) noexcept;
\n+
333
\n+
335 void trace(std::FILE *) noexcept;
\n+
336
\n+
348
\n+
349 [[nodiscard]] char const *dbname() const;
\n+
350
\n+
352
\n+
353 [[nodiscard]] char const *username() const;
\n+
354
\n+
356
\n+
359 [[nodiscard]] char const *hostname() const;
\n+
360
\n+
362 [[nodiscard]] char const *port() const;
\n+
363
\n+
365 [[nodiscard]] int PQXX_PURE backendpid() const &noexcept;
\n+
366
\n+
368
\n+
378 [[nodiscard]] int PQXX_PURE sock() const &noexcept;
\n+
379
\n+
381
\n+
384 [[nodiscard]] int PQXX_PURE protocol_version() const noexcept;
\n+
385
\n+
387
\n+
399 [[nodiscard]] int PQXX_PURE server_version() const noexcept;
\n+
401
\n+
403
\n+
424 [[nodiscard]] std::string get_client_encoding() const;
\n+
425
\n+
427
\n+
\n+
430 void set_client_encoding(zview encoding) &
\n+
431 {
\n+
432 set_client_encoding(encoding.c_str());
\n+
433 }
\n+
\n+
434
\n+
436
\n+
439 void set_client_encoding(char const encoding[]) &;
\n+
440
\n+
442 [[nodiscard]] int encoding_id() const;
\n+
443
\n+
445
\n+
447
\n+
460 [[deprecated("To set session variables, use set_session_var.")]] void
\n+
461 set_variable(std::string_view var, std::string_view value) &;
\n+
462
\n+
464
\n+
485 template<typename TYPE>
\n+
\n+
486 void set_session_var(std::string_view var, TYPE const &value) &
\n+
487 {
\n+
488 if constexpr (nullness<TYPE>::has_null)
\n+
489 {
\n+
490 if (nullness<TYPE>::is_null(value))
\n+\n+
492 internal::concat("Attempted to set variable ", var, " to null.")};
\n+
493 }
\n+
494 exec(internal::concat("SET ", quote_name(var), "=", quote(value)));
\n+
495 }
\n+
\n+
496
\n+
498
\n+
501 [[deprecated("Use get_var instead.")]] std::string
\n+
502 get_variable(std::string_view);
\n+
503
\n+
505
\n+
511 std::string get_var(std::string_view var);
\n+
512
\n+
514
\n+
\n+
520 template<typename TYPE> TYPE get_var_as(std::string_view var)
\n+
521 {
\n+
522 return from_string<TYPE>(get_var(var));
\n+
523 }
\n+
\n+
524
\n+
530
\n+
547 int get_notifs();
\n+
548
\n+
550
\n+
562 int await_notification();
\n+
563
\n+
565
\n+
577 int await_notification(std::time_t seconds, long microseconds);
\n+
579
\n+
611 [[nodiscard]] std::string
\n+
\n+
612 encrypt_password(zview user, zview password, zview algorithm)
\n+
613 {
\n+
614 return encrypt_password(user.c_str(), password.c_str(), algorithm.c_str());
\n+
615 }
\n+
\n+
617 [[nodiscard]] std::string encrypt_password(
\n+
618 char const user[], char const password[], char const *algorithm = nullptr);
\n+
620
\n+
663
\n+
665
\n+
\n+
669 void prepare(zview name, zview definition) &
\n+
670 {
\n+
671 prepare(name.c_str(), definition.c_str());
\n+
672 }
\n+
\n+
673
\n+
678 void prepare(char const name[], char const definition[]) &;
\n+
679
\n+
681
\n+
688 void prepare(char const definition[]) &;
\n+
689 void prepare(zview definition) & { return prepare(definition.c_str()); }
\n+
690
\n+
692 void unprepare(std::string_view name);
\n+
693
\n+
695
\n+
696 // C++20: constexpr. Breaks ABI.
\n+
698
\n+
701 [[nodiscard]] std::string adorn_name(std::string_view);
\n+
702
\n+
707
\n+
709
\n+
713 [[deprecated("Use std::string_view or pqxx:zview.")]] std::string
\n+
\n+
714 esc(char const text[], std::size_t maxlen) const
\n+
715 {
\n+
716 return esc(std::string_view{text, maxlen});
\n+
717 }
\n+
\n+
718
\n+
\n+
720 [[nodiscard]] std::string esc(char const text[]) const
\n+
721 {
\n+
722 return esc(std::string_view{text});
\n+
723 }
\n+
\n+
724
\n+
725#if defined(PQXX_HAVE_SPAN)
\n+
727
\n+
738 [[nodiscard]] std::string_view
\n+
739 esc(std::string_view text, std::span<char> buffer)
\n+
740 {
\n+
741 auto const size{std::size(text)}, space{std::size(buffer)};
\n+
742 auto const needed{2 * size + 1};
\n+
743 if (space < needed)
\n+
744 throw range_error{internal::concat(
\n+
745 "Not enough room to escape string of ", size, " byte(s): need ",
\n+
746 needed, " bytes of buffer space, but buffer size is ", space, ".")};
\n+
747 auto const data{buffer.data()};
\n+
748 return {data, esc_to_buf(text, data)};
\n+
749 }
\n+
750#endif
\n+
751
\n+
753
\n+
756 [[nodiscard]] std::string esc(std::string_view text) const;
\n+
757
\n+
758#if defined(PQXX_HAVE_CONCEPTS)
\n+
760
\n+
761 template<binary DATA> [[nodiscard]] std::string esc(DATA const &data) const
\n+
762 {
\n+
763 return esc_raw(data);
\n+
764 }
\n+
765#endif
\n+
766
\n+
767#if defined(PQXX_HAVE_CONCEPTS) && defined(PQXX_HAVE_SPAN)
\n+
769
\n+
780 template<binary DATA>
\n+
781 [[nodiscard]] zview esc(DATA const &data, std::span<char> buffer) const
\n+
782 {
\n+
783 auto const size{std::size(data)}, space{std::size(buffer)};
\n+
784 auto const needed{internal::size_esc_bin(std::size(data))};
\n+
785 if (space < needed)
\n+
786 throw range_error{internal::concat(
\n+
787 "Not enough room to escape binary string of ", size, " byte(s): need ",
\n+
788 needed, " bytes of buffer space, but buffer size is ", space, ".")};
\n+
789
\n+
790 std::basic_string_view<std::byte> view{std::data(data), std::size(data)};
\n+
791 auto const out{std::data(buffer)};
\n+
792 // Actually, in the modern format, we know beforehand exactly how many
\n+
793 // bytes we're going to fill. Just leave out the trailing zero.
\n+
794 internal::esc_bin(view, out);
\n+
795 return zview{out, needed - 1};
\n+
796 }
\n+
797#endif
\n+
798
\n+
800 [[deprecated("Use std::byte for binary data.")]] std::string
\n+
801 esc_raw(unsigned char const bin[], std::size_t len) const;
\n+
802
\n+
804
\n+
805 [[nodiscard]] std::string esc_raw(std::basic_string_view<std::byte>) const;
\n+
806
\n+
807#if defined(PQXX_HAVE_SPAN)
\n+
809
\n+
810 [[nodiscard]] std::string
\n+
811 esc_raw(std::basic_string_view<std::byte>, std::span<char> buffer) const;
\n+
812#endif
\n+
813
\n+
814#if defined(PQXX_HAVE_CONCEPTS)
\n+
816
\n+
817 template<binary DATA>
\n+
818 [[nodiscard]] std::string esc_raw(DATA const &data) const
\n+
819 {
\n+
820 return esc_raw(
\n+
821 std::basic_string_view<std::byte>{std::data(data), std::size(data)});
\n+
822 }
\n+
823#endif
\n+
824
\n+
825#if defined(PQXX_HAVE_CONCEPTS) && defined(PQXX_HAVE_SPAN)
\n+
827 template<binary DATA>
\n+
828 [[nodiscard]] zview esc_raw(DATA const &data, std::span<char> buffer) const
\n+
829 {
\n+
830 return this->esc(binary_cast(data), buffer);
\n+
831 }
\n+
832#endif
\n+
833
\n+
835
\n+
838 [[nodiscard, deprecated("Use unesc_bin() instead.")]] std::string
\n+
\n+\n+
840 {
\n+
841#include "pqxx/internal/ignore-deprecated-pre.hxx"
\n+
842 return unesc_raw(text.c_str());
\n+
843#include "pqxx/internal/ignore-deprecated-post.hxx"
\n+
844 }
\n+
\n+
845
\n+
847
\n+
850 [[nodiscard, deprecated("Use unesc_bin() instead.")]] std::string
\n+
851 unesc_raw(char const text[]) const;
\n+
852
\n+
853 // TODO: Make "into buffer" variant to eliminate a string allocation.
\n+
855
\n+
862 [[nodiscard]] std::basic_string<std::byte>
\n+
\n+
863 unesc_bin(std::string_view text) const
\n+
864 {
\n+
865 std::basic_string<std::byte> buf;
\n+
866 buf.resize(pqxx::internal::size_unesc_bin(std::size(text)));
\n+
867 pqxx::internal::unesc_bin(text, buf.data());
\n+
868 return buf;
\n+
869 }
\n+
\n+
870
\n+
872 [[deprecated("Use quote(std::basic_string_view<std::byte>).")]] std::string
\n+
873 quote_raw(unsigned char const bin[], std::size_t len) const;
\n+
874
\n+
876 std::string quote_raw(std::basic_string_view<std::byte>) const;
\n+
877
\n+
878#if defined(PQXX_HAVE_CONCEPTS)
\n+
880
\n+
881 template<binary DATA>
\n+
882 [[nodiscard]] std::string quote_raw(DATA const &data) const
\n+
883 {
\n+
884 return quote_raw(
\n+
885 std::basic_string_view<std::byte>{std::data(data), std::size(data)});
\n+
886 }
\n+
887#endif
\n+
888
\n+
889 // TODO: Make "into buffer" variant to eliminate a string allocation.
\n+
891 [[nodiscard]] std::string quote_name(std::string_view identifier) const;
\n+
892
\n+
893 // TODO: Make "into buffer" variant to eliminate a string allocation.
\n+
895
\n+
898 [[nodiscard]] std::string quote_table(std::string_view name) const;
\n+
899
\n+
900 // TODO: Make "into buffer" variant to eliminate a string allocation.
\n+
902
\n+
910 [[nodiscard]] std::string quote_table(table_path) const;
\n+
911
\n+
912 // TODO: Make "into buffer" variant to eliminate a string allocation.
\n+
914
\n+
921 template<PQXX_CHAR_STRINGS_ARG STRINGS>
\n+
922 inline std::string quote_columns(STRINGS const &columns) const;
\n+
923
\n+
924 // TODO: Make "into buffer" variant to eliminate a string allocation.
\n+
926
\n+
929 template<typename T>
\n+
930 [[nodiscard]] inline std::string quote(T const &t) const;
\n+
931
\n+
932 [[deprecated("Use std::byte for binary data.")]] std::string
\n+
933 quote(binarystring const &) const;
\n+
934
\n+
935 // TODO: Make "into buffer" variant to eliminate a string allocation.
\n+
937 [[nodiscard]] std::string
\n+
938 quote(std::basic_string_view<std::byte> bytes) const;
\n+
939
\n+
940 // TODO: Make "into buffer" variant to eliminate a string allocation.
\n+
942
\n+
967 [[nodiscard]] std::string
\n+
968 esc_like(std::string_view text, char escape_char = '\\\\') const;
\n+
970
\n+
972
\n+
976 void cancel_query();
\n+
977
\n+
978#if defined(_WIN32) || __has_include(<fcntl.h>)
\n+
980
\n+
984 void set_blocking(bool block) &;
\n+
985#endif // defined(_WIN32) || __has_include(<fcntl.h>)
\n+
986
\n+
988
\n+
997 void set_verbosity(error_verbosity verbosity) &noexcept;
\n+
998
\n+
1000
\n+
1012 [[nodiscard]] std::vector<errorhandler *> get_errorhandlers() const;
\n+
1013
\n+
1015
\n+
1021 [[nodiscard]] std::string connection_string() const;
\n+
1022
\n+
1024
\n+
1032 void close();
\n+
1033
\n+
1035
\n+
\n+
1041 static connection seize_raw_connection(internal::pq::PGconn *raw_conn)
\n+
1042 {
\n+
1043 return connection{raw_conn};
\n+
1044 }
\n+
\n+
1045
\n+
1047
\n+
\n+
1052 internal::pq::PGconn *release_raw_connection() &&
\n+
1053 {
\n+
1054 return std::exchange(m_conn, nullptr);
\n+
1055 }
\n+
\n+
1056
\n+
1057private:
\n+
1058 friend class connecting;
\n+
1059 enum connect_mode
\n+
1060 {
\n+
1061 connect_nonblocking
\n+
1062 };
\n+
1063 connection(connect_mode, zview connection_string);
\n+
1064
\n+
1066 explicit connection(internal::pq::PGconn *raw_conn) : m_conn{raw_conn} {}
\n+
1067
\n+
1069
\n+
1074 std::pair<bool, bool> poll_connect();
\n+
1075
\n+
1076 // Initialise based on connection string.
\n+
1077 void init(char const options[]);
\n+
1078 // Initialise based on parameter names and values.
\n+
1079 void init(char const *params[], char const *values[]);
\n+
1080 void complete_init();
\n+
1081
\n+
1082 result make_result(
\n+
1083 internal::pq::PGresult *pgr, std::shared_ptr<std::string> const &query,
\n+
1084 std::string_view desc = ""sv);
\n+
1085
\n+
1086 void PQXX_PRIVATE set_up_state();
\n+
1087
\n+
1088 int PQXX_PRIVATE PQXX_PURE status() const noexcept;
\n+
1089
\n+
1091
\n+
1095 std::size_t esc_to_buf(std::string_view text, char *buf) const;
\n+
1096
\n+
1097 friend class internal::gate::const_connection_largeobject;
\n+
1098 char const *PQXX_PURE err_msg() const noexcept;
\n+
1099
\n+
1100 void PQXX_PRIVATE process_notice_raw(char const msg[]) noexcept;
\n+
1101
\n+
1102 result exec_prepared(std::string_view statement, internal::c_params const &);
\n+
1103
\n+
1105 void check_movable() const;
\n+
1107 void check_overwritable() const;
\n+
1108
\n+
1109 friend class internal::gate::connection_errorhandler;
\n+
1110 void PQXX_PRIVATE register_errorhandler(errorhandler *);
\n+
1111 void PQXX_PRIVATE unregister_errorhandler(errorhandler *) noexcept;
\n+
1112
\n+
1113 friend class internal::gate::connection_transaction;
\n+
1114 result exec(std::string_view, std::string_view = ""sv);
\n+
1115 result
\n+
1116 PQXX_PRIVATE exec(std::shared_ptr<std::string>, std::string_view = ""sv);
\n+
1117 void PQXX_PRIVATE register_transaction(transaction_base *);
\n+
1118 void PQXX_PRIVATE unregister_transaction(transaction_base *) noexcept;
\n+
1119
\n+
1120 friend struct internal::gate::connection_stream_from;
\n+
1121 std::pair<std::unique_ptr<char, void (*)(void const *)>, std::size_t>
\n+
1122 read_copy_line();
\n+
1123
\n+
1124 friend class internal::gate::connection_stream_to;
\n+
1125 void PQXX_PRIVATE write_copy_line(std::string_view);
\n+
1126 void PQXX_PRIVATE end_copy_write();
\n+
1127
\n+
1128 friend class internal::gate::connection_largeobject;
\n+
1129 internal::pq::PGconn *raw_connection() const { return m_conn; }
\n+
1130
\n+
1131 friend class internal::gate::connection_notification_receiver;
\n+
1132 void add_receiver(notification_receiver *);
\n+
1133 void remove_receiver(notification_receiver *) noexcept;
\n+
1134
\n+
1135 friend class internal::gate::connection_pipeline;
\n+
1136 void PQXX_PRIVATE start_exec(char const query[]);
\n+
1137 bool PQXX_PRIVATE consume_input() noexcept;
\n+
1138 bool PQXX_PRIVATE is_busy() const noexcept;
\n+
1139 internal::pq::PGresult *get_result();
\n+
1140
\n+
1141 friend class internal::gate::connection_dbtransaction;
\n+
1142 friend class internal::gate::connection_sql_cursor;
\n+
1143
\n+
1144 result exec_params(std::string_view query, internal::c_params const &args);
\n+
1145
\n+
1147 internal::pq::PGconn *m_conn = nullptr;
\n+
1148
\n+
1150
\n+
1157 transaction_base const *m_trans = nullptr;
\n+
1158
\n+
1159 std::list<errorhandler *> m_errorhandlers;
\n+
1160
\n+
1161 using receiver_list =
\n+
1162 std::multimap<std::string, pqxx::notification_receiver *>;
\n+
1164 receiver_list m_receivers;
\n+
1165
\n+
1167 int m_unique_id = 0;
\n+
1168};
\n+
\n+
1169
\n+
1170
\n+\n+
1173
\n+
1174
\n+
1176
\n+
\n+
1219class PQXX_LIBEXPORT connecting
\n+
1220{
\n+
1221public:
\n+
1223 connecting(zview connection_string = ""_zv);
\n+
1224
\n+
1225 connecting(connecting const &) = delete;
\n+
1226 connecting(connecting &&) = default;
\n+
1227 connecting &operator=(connecting const &) = delete;
\n+\n+
1229
\n+
1231 [[nodiscard]] int sock() const &noexcept { return m_conn.sock(); }
\n+
1232
\n+
\n+
1234 [[nodiscard]] constexpr bool wait_to_read() const &noexcept
\n+
1235 {
\n+
1236 return m_reading;
\n+
1237 }
\n+
\n+
1238
\n+
\n+
1240 [[nodiscard]] constexpr bool wait_to_write() const &noexcept
\n+
1241 {
\n+
1242 return m_writing;
\n+
1243 }
\n+
\n+
1244
\n+
1246 void process() &;
\n+
1247
\n+
\n+
1249 [[nodiscard]] constexpr bool done() const &noexcept
\n+
1250 {
\n+
1251 return not m_reading and not m_writing;
\n+
1252 }
\n+
\n+
1253
\n+
1255
\n+
1263 [[nodiscard]] connection produce() &&;
\n+
1264
\n+
1265private:
\n+
1266 connection m_conn;
\n+
1267 bool m_reading{false};
\n+
1268 bool m_writing{true};
\n+
1269};
\n+
\n+
1270
\n+
1271
\n+
\n+
1272template<typename T> inline std::string connection::quote(T const &t) const
\n+
1273{
\n+
1274 if constexpr (nullness<T>::always_null)
\n+
1275 {
\n+
1276 return "NULL";
\n+
1277 }
\n+
1278 else
\n+
1279 {
\n+
1280 if (is_null(t))
\n+
1281 return "NULL";
\n+
1282 auto const text{to_string(t)};
\n+
1283
\n+
1284 // Okay, there's an easy way to do this and there's a hard way. The easy
\n+
1285 // way was "quote, esc(to_string(t)), quote". I'm going with the hard way
\n+
1286 // because it's going to save some string manipulation that will probably
\n+
1287 // incur some unnecessary memory allocations and deallocations.
\n+
1288 std::string buf{'\\''};
\n+
1289 buf.resize(2 + 2 * std::size(text) + 1);
\n+
1290 auto const content_bytes{esc_to_buf(text, buf.data() + 1)};
\n+
1291 auto const closing_quote{1 + content_bytes};
\n+
1292 buf[closing_quote] = '\\'';
\n+
1293 auto const end{closing_quote + 1};
\n+
1294 buf.resize(end);
\n+
1295 return buf;
\n+
1296 }
\n+
1297}
\n+
\n+
1298
\n+
1299
\n+
1300template<PQXX_CHAR_STRINGS_ARG STRINGS>
\n+
\n+
1301inline std::string connection::quote_columns(STRINGS const &columns) const
\n+
1302{
\n+
1303 return separated_list(
\n+
1304 ","sv, std::cbegin(columns), std::cend(columns),
\n+
1305 [this](auto col) { return this->quote_name(*col); });
\n+
1306}
\n+
\n+
1307
\n+
1308
\n+
1309#if defined(PQXX_HAVE_CONCEPTS)
\n+
1310template<internal::ZKey_ZValues MAPPING>
\n+
1311inline connection::connection(MAPPING const &params)
\n+
1312{
\n+
1313 check_version();
\n+
1314
\n+
1315 std::vector<char const *> keys, values;
\n+
1316 if constexpr (std::ranges::sized_range<MAPPING>)
\n+
1317 {
\n+
1318 auto const size{std::ranges::size(params) + 1};
\n+
1319 keys.reserve(size);
\n+
1320 values.reserve(size);
\n+
1321 }
\n+
1322 for (auto const &[key, value] : params)
\n+
1323 {
\n+
1324 keys.push_back(internal::as_c_string(key));
\n+
1325 values.push_back(internal::as_c_string(value));
\n+
1326 }
\n+
1327 keys.push_back(nullptr);
\n+
1328 values.push_back(nullptr);
\n+
1329 init(std::data(keys), std::data(values));
\n+
1330}
\n+
1331#endif // PQXX_HAVE_CONCEPTS
\n+
1332} // namespace pqxx
\n+
1333#endif
\n
The home of all libpqxx classes, functions, templates, etc.
Definition array.hxx:33
\n+
std::string separated_list(std::string_view sep, ITER begin, ITER end, ACCESS access)
Represent sequence of values as a string, joined by a given separator.
Definition separated_list.hxx:44
\n+
std::string encrypt_password(char const user[], char const password[])
Encrypt a password.
Definition connection.cxx:94
\n
std::basic_string_view< std::byte > binary_cast(TYPE const &data)
Cast binary data to a type that libpqxx will recognise as binary.
Definition util.hxx:303
\n+
void skip_init_ssl() noexcept
Control initialisation of OpenSSL and libcrypto libraries.
Definition connection.hxx:173
\n+
std::initializer_list< std::string_view > table_path
Representation of a PostgreSQL table path.
Definition connection.hxx:188
\n+
void check_version() noexcept
Definition util.hxx:234
\n+
std::string to_string(field const &value)
Convert a field to a string.
Definition result.cxx:549
\n+
skip_init
Flags for skipping initialisation of SSL-related libraries.
Definition connection.hxx:137
\n+
@ crypto
Skip initialisation of libcrypto.
Definition connection.hxx:145
\n+
@ openssl
Skip initialisation of OpenSSL library.
Definition connection.hxx:142
\n+
@ nothing
A do-nothing flag that does not affect anything.
Definition connection.hxx:139
\n+
error_verbosity
Error verbosity levels.
Definition connection.hxx:210
\n+\n+\n+\n \n+
Internal items for libpqxx' own use. Do not use these yourself.
Definition composite.hxx:84
\n+
void PQXX_COLD skip_init_ssl(int flags) noexcept
Control OpenSSL/crypto library initialisation.
Definition connection.cxx:83
\n
void unesc_bin(std::string_view escaped_data, std::byte buffer[])
Reconstitute binary data from its escaped version.
Definition util.cxx:158
\n
void esc_bin(std::basic_string_view< std::byte > binary_data, char buffer[]) noexcept
Hex-escape binary data into a buffer.
Definition util.cxx:126
\n
constexpr std::size_t size_esc_bin(std::size_t binary_bytes) noexcept
Compute buffer size needed to escape binary data for use as a BYTEA.
Definition util.hxx:411
\n-
constexpr bool cmp_less(LEFT lhs, RIGHT rhs) noexcept
Same as std::cmp_less, or a workaround where that's not available.
Definition util.hxx:63
\n+
constexpr char const * as_c_string(char const str[]) noexcept
Get a raw C string pointer.
Definition zview.hxx:145
\n
constexpr std::size_t size_unesc_bin(std::size_t escaped_bytes) noexcept
Compute binary size from the size of its escaped version.
Definition util.hxx:420
\n-
Binary data corresponding to PostgreSQL's "BYTEA" binary-string type.
Definition binarystring.hxx:59
\n-
const_reverse_iterator crend() const
Definition binarystring.hxx:124
\n-
char const * get() const noexcept
Raw character buffer (no terminating zero is added).
Definition binarystring.hxx:152
\n-
const_reverse_iterator rbegin() const
Definition binarystring.hxx:115
\n-
bool operator!=(binarystring const &rhs) const noexcept
Definition binarystring.hxx:135
\n-
const_pointer const_iterator
Definition binarystring.hxx:67
\n-
const_iterator end() const noexcept
Definition binarystring.hxx:106
\n-
std::basic_string_view< std::byte > bytes_view() const
Read data as a std::basic_string_view<std::byte>.
Definition binarystring.hxx:178
\n-
const_iterator begin() const noexcept
Definition binarystring.hxx:104
\n-
std::char_traits< char_type >::char_type value_type
Definition binarystring.hxx:62
\n-
value_type const & const_reference
Definition binarystring.hxx:65
\n-
long difference_type
Definition binarystring.hxx:64
\n-
binarystring(std::shared_ptr< value_type > ptr, size_type size)
Efficiently wrap a buffer of binary data in a binarystring.
Definition binarystring.hxx:93
\n-
const_reverse_iterator crbegin() const
Definition binarystring.hxx:119
\n-
std::size_t size_type
Definition binarystring.hxx:63
\n-
const_reference front() const noexcept
Definition binarystring.hxx:109
\n-
const_reference back() const noexcept
Definition binarystring.hxx:110
\n-
std::string_view view() const noexcept
Read contents as a std::string_view.
Definition binarystring.hxx:158
\n-
bool empty() const noexcept
Definition binarystring.hxx:102
\n-
std::byte const * bytes() const
Access data as a pointer to std::byte.
Definition binarystring.hxx:172
\n-
const_reference operator[](size_type i) const noexcept
Definition binarystring.hxx:129
\n-
const_iterator cend() const noexcept
Definition binarystring.hxx:107
\n-
value_type const * data() const noexcept
Unescaped field contents.
Definition binarystring.hxx:127
\n-
const_reverse_iterator rend() const
Definition binarystring.hxx:120
\n-
size_type length() const noexcept
Size of converted string in bytes.
Definition binarystring.hxx:101
\n-
binarystring & operator=(binarystring const &)
\n-
unsigned char char_type
Definition binarystring.hxx:61
\n-
std::reverse_iterator< const_iterator > const_reverse_iterator
Definition binarystring.hxx:68
\n-
const_iterator cbegin() const noexcept
Definition binarystring.hxx:105
\n-
binarystring(binarystring const &)=default
\n-
value_type const * const_pointer
Definition binarystring.hxx:66
\n-
size_type size() const noexcept
Size of converted string in bytes.
Definition binarystring.hxx:99
\n-
static char * into_buf(char *begin, char *end, binarystring const &value)
Definition binarystring.hxx:213
\n-
static std::size_t size_buffer(binarystring const &value) noexcept
Definition binarystring.hxx:203
\n-
static zview to_buf(char *begin, char *end, binarystring const &value)
Definition binarystring.hxx:208
\n-
static binarystring from_string(std::string_view text)
Definition binarystring.hxx:224
\n-
Could not convert value to string: not enough buffer space.
Definition except.hxx:313
\n-
Reference to a field in a result set.
Definition field.hxx:35
\n+
Definition connection.hxx:112
\n+
Connection to a database.
Definition connection.hxx:253
\n+
std::string encrypt_password(zview user, zview password, zview algorithm)
Encrypt a password for a given user.
Definition connection.hxx:612
\n+
void prepare(zview definition) &
Definition connection.hxx:689
\n+
connection(char const options[])
Connect to a database, using options string.
Definition connection.hxx:258
\n+
connection & operator=(connection const &)=delete
\n+
TYPE get_var_as(std::string_view var)
Read currently applicable value of a variable.
Definition connection.hxx:520
\n+
connection()
Definition connection.hxx:255
\n+
~connection()
Definition connection.hxx:299
\n+
std::string quote_columns(STRINGS const &columns) const
Quote and comma-separate a series of column names.
Definition connection.hxx:1301
\n+
connection(zview options)
Connect to a database, using options string.
Definition connection.hxx:265
\n+
internal::pq::PGconn * release_raw_connection() &&
Release the raw connection without closing it.
Definition connection.hxx:1052
\n+
static connection seize_raw_connection(internal::pq::PGconn *raw_conn)
Seize control of a raw libpq connection.
Definition connection.hxx:1041
\n+
std::basic_string< std::byte > unesc_bin(std::string_view text) const
Unescape binary data, e.g. from a table field or notification payload.
Definition connection.hxx:863
\n+
std::string esc(char const text[]) const
Escape string for use as SQL string literal on this connection.
Definition connection.hxx:720
\n+
std::string unesc_raw(zview text) const
Unescape binary data, e.g. from a table field or notification payload.
Definition connection.hxx:839
\n+
std::string esc(char const text[], std::size_t maxlen) const
Escape string for use as SQL string literal on this connection.
Definition connection.hxx:714
\n+
void prepare(zview name, zview definition) &
Define a prepared statement.
Definition connection.hxx:669
\n+
void set_session_var(std::string_view var, TYPE const &value) &
Set one of the session variables to a new value.
Definition connection.hxx:486
\n+
std::string quote(T const &t) const
Represent object as SQL string, including quoting & escaping.
Definition connection.hxx:1272
\n+
connection(connection const &)=delete
\n+
An ongoing, non-blocking stepping stone to a connection.
Definition connection.hxx:1220
\n+
connecting(connecting &&)=default
\n+
int sock() const &noexcept
Get the socket. The socket may change during the connection process.
Definition connection.hxx:1231
\n+
constexpr bool done() const &noexcept
Is our connection finished?
Definition connection.hxx:1249
\n+
connecting & operator=(connecting const &)=delete
\n+
connecting(connecting const &)=delete
\n+
constexpr bool wait_to_write() const &noexcept
Should we currently wait to be able to write to the socket?
Definition connection.hxx:1240
\n+
void process() &
Progress towards completion (but don't block).
\n+
connecting & operator=(connecting &&)=default
\n+
constexpr bool wait_to_read() const &noexcept
Should we currently wait to be able to read from the socket?
Definition connection.hxx:1234
\n+
connecting(zview connection_string=""_zv)
Start connecting.
\n+
connection produce() &&
Produce the completed connection object.
\n+
Base class for error-handler callbacks.
Definition errorhandler.hxx:54
\n+
The caller attempted to set a variable to null, which is not allowed.
Definition except.hxx:116
\n+
Definition notification.hxx:57
\n+
Build a parameter list for a parameterised or prepared statement.
Definition params.hxx:220
\n+
Result set containing data returned by a query or command.
Definition result.hxx:73
\n
Traits describing a type's "null value," if any.
Definition strconv.hxx:93
\n-
Nullness traits describing a type which does not have a null value.
Definition strconv.hxx:115
\n-
Traits class for use in string conversions.
Definition strconv.hxx:155
\n-
static std::size_t size_buffer(TYPE const &value) noexcept
Estimate how much buffer space is needed to represent value.
\n+
Interface definition (and common code) for "transaction" classes.
Definition transaction_base.hxx:88
\n
Marker-type wrapper: zero-terminated std::string_view.
Definition zview.hxx:38
\n+
constexpr char const * c_str() const &noexcept
Either a null pointer, or a zero-terminated text buffer.
Definition zview.hxx:96
\n
\n
\n \n
\n \n
\n \n \n", "details": [{"source1": "html2text {}", "source2": "html2text {}", "unified_diff": "@@ -1,358 +1,929 @@\n \n \n \n \n \n libpqxx\u00a07.8.1\n \n-binarystring.hxx\n- 1/* Deprecated representation for raw, binary data.\n+connection.hxx\n+ 1/* Definition of the connection class.\n 2 *\n- 3 * DO NOT INCLUDE THIS FILE DIRECTLY; include pqxx/binarystring instead.\n+ 3 * pqxx::connection encapsulates a connection to a database.\n 4 *\n- 5 * Copyright (c) 2000-2023, Jeroen T. Vermeulen.\n+ 5 * DO NOT INCLUDE THIS FILE DIRECTLY; include pqxx/connection instead.\n 6 *\n- 7 * See COPYING for copyright license. If you did not receive a file called\n- 8 * COPYING with this source code, please notify the distributor of this\n- 9 * mistake, or contact the author.\n- 10 */\n- 11#ifndef PQXX_H_BINARYSTRING\n- 12#define PQXX_H_BINARYSTRING\n- 13\n- 14#if !defined(PQXX_HEADER_PRE)\n- 15# error \"Include libpqxx headers as , not .\"\n- 16#endif\n- 17\n- 18#include \n- 19#include \n- 20#include \n- 21\n- 22#include \"pqxx/result.hxx\"\n- 23#include \"pqxx/strconv.hxx\"\n- 24\n- 25namespace pqxx\n- 26{\n- 27class binarystring;\n- 28template<> struct string_traits;\n- 29\n- 30\n- 32\n-58class PQXX_LIBEXPORT binarystring\n- 59{\n- 60public:\n-61 using char_type = unsigned char;\n-62 using value_type = std::char_traits::char_type;\n-63 using size_type = std::size_t;\n-64 using difference_type = long;\n-65 using const_reference = value_type const &;\n-66 using const_pointer = value_type const *;\n-67 using const_iterator = const_pointer;\n-68 using const_reverse_iterator = std::reverse_iterator;\n- 69\n-70 [[deprecated(\"Use std::byte for binary data.\")]] binarystring(\n- 71 binarystring const &) = default;\n- 72\n- 74\n- 78 [[deprecated(\"Use std::byte for binary data.\")]] explicit binarystring(\n- 79 field const &);\n- 80\n- 82\n- 85 [[deprecated(\"Use std::byte for binary data.\")]] explicit binarystring(\n- 86 std::string_view);\n- 87\n- 89 [[deprecated(\"Use std::byte for binary data.\")]] binarystring(\n- 90 void const *, std::size_t);\n- 91\n-93 [[deprecated(\"Use std::byte for binary data.\")]] binarystring(\n- 94 std::shared_ptr ptr, size_type size) :\n- 95 m_buf{std::move(ptr)}, m_size{size}\n- 96 {}\n+ 7 * Copyright (c) 2000-2023, Jeroen T. Vermeulen.\n+ 8 *\n+ 9 * See COPYING for copyright license. If you did not receive a file called\n+ 10 * COPYING with this source code, please notify the distributor of this\n+ 11 * mistake, or contact the author.\n+ 12 */\n+ 13#ifndef PQXX_H_CONNECTION\n+ 14#define PQXX_H_CONNECTION\n+ 15\n+ 16#if !defined(PQXX_HEADER_PRE)\n+ 17# error \"Include libpqxx headers as , not .\"\n+ 18#endif\n+ 19\n+ 20#include \n+ 21#include \n+ 22#include \n+ 23#include \n+ 24#include \n+ 25#include \n+ 26#include \n+ 27#include \n+ 28\n+ 29// Double-check in order to suppress an overzealous Visual C++ warning\n+(#418).\n+ 30#if defined(PQXX_HAVE_CONCEPTS) && __has_include()\n+ 31# include \n+ 32#endif\n+ 33\n+ 34#include \"pqxx/errorhandler.hxx\"\n+ 35#include \"pqxx/except.hxx\"\n+ 36#include \"pqxx/internal/concat.hxx\"\n+ 37#include \"pqxx/params.hxx\"\n+ 38#include \"pqxx/separated_list.hxx\"\n+ 39#include \"pqxx/strconv.hxx\"\n+ 40#include \"pqxx/types.hxx\"\n+ 41#include \"pqxx/util.hxx\"\n+ 42#include \"pqxx/zview.hxx\"\n+ 43\n+ 44\n+ 75namespace pqxx::internal\n+ 76{\n+ 77class sql_cursor;\n+ 78\n+ 79#if defined(PQXX_HAVE_CONCEPTS)\n+ 81template\n+ 82concept ZKey_ZValues =\n+ 83 std::ranges::input_range and\n+ 84 requires(T t) {\n+ 85 {\n+ 86 std::cbegin(t)\n+ 87 };\n+ 88 {\n+ 89 std::get<0>(*std::cbegin(t))\n+ 90 } -> ZString;\n+ 91 {\n+ 92 std::get<1>(*std::cbegin(t))\n+ 93 } -> ZString;\n+ 94 } and\n+ 95 std::tuple_size_v::value_type> == 2;\n+ 96#endif // PQXX_HAVE_CONCEPTS\n 97\n-99 [[nodiscard]] size_type size() const noexcept { return m_size; }\n-101 [[nodiscard]] size_type length() const noexcept { return size(); }\n-102 [[nodiscard]] bool empty() const noexcept { return size() == 0; }\n- 103\n-104 [[nodiscard]] const_iterator begin() const noexcept { return data(); }\n-105 [[nodiscard]] const_iterator cbegin() const noexcept { return begin(); }\n-106 [[nodiscard]] const_iterator end() const noexcept { return data() + m_size;\n-}\n-107 [[nodiscard]] const_iterator cend() const noexcept { return end(); }\n- 108\n-109 [[nodiscard]] const_reference front() const noexcept { return *begin(); }\n-110 [[nodiscard]] const_reference back() const noexcept\n- 111 {\n- 112 return *(data() + m_size - 1);\n- 113 }\n- 114\n-115 [[nodiscard]] const_reverse_iterator rbegin() const\n- 116 {\n- 117 return const_reverse_iterator{end()};\n- 118 }\n-119 [[nodiscard]] const_reverse_iterator crbegin() const { return rbegin(); }\n-120 [[nodiscard]] const_reverse_iterator rend() const\n- 121 {\n- 122 return const_reverse_iterator{begin()};\n- 123 }\n-124 [[nodiscard]] const_reverse_iterator crend() const { return rend(); }\n+ 98\n+ 100\n+ 107void PQXX_COLD PQXX_LIBEXPORT skip_init_ssl(int flags) noexcept;\n+ 108} // namespace pqxx::internal\n+ 109\n+ 110\n+111namespace pqxx::internal::gate\n+ 112{\n+ 113class connection_dbtransaction;\n+ 114class connection_errorhandler;\n+ 115class connection_largeobject;\n+ 116class connection_notification_receiver;\n+ 117class connection_pipeline;\n+ 118class connection_sql_cursor;\n+ 119struct connection_stream_from;\n+ 120class connection_stream_to;\n+ 121class connection_transaction;\n+ 122class const_connection_largeobject;\n+ 123} // namespace pqxx::internal::gate\n+ 124\n 125\n-127 [[nodiscard]] value_type const *data() const noexcept { return m_buf.get();\n-}\n- 128\n-129 [[nodiscard]] const_reference operator[](size_type i) const noexcept\n- 130 {\n- 131 return data()[i];\n- 132 }\n- 133\n- 134 [[nodiscard]] PQXX_PURE bool operator==(binarystring const &) const\n-noexcept;\n-135 [[nodiscard]] bool operator!=(binarystring const &rhs) const noexcept\n- 136 {\n- 137 return not operator==(rhs);\n- 138 }\n- 139\n-140 binarystring &operator=(binarystring const &);\n- 141\n- 143 const_reference at(size_type) const;\n- 144\n- 146 void swap(binarystring &);\n+ 126namespace pqxx\n+ 127{\n+ 129\n+136enum skip_init : int\n+ 137{\n+139 nothing,\n+ 140\n+142 openssl,\n+ 143\n+145 crypto,\n+ 146};\n 147\n- 149\n-152 [[nodiscard]] char const *get() const noexcept\n- 153 {\n- 154 return reinterpret_cast(m_buf.get());\n- 155 }\n- 156\n-158 [[nodiscard]] std::string_view view() const noexcept\n- 159 {\n- 160 return std::string_view(get(), size());\n- 161 }\n- 162\n- 164\n- 169 [[nodiscard]] std::string str() const;\n- 170\n-172 [[nodiscard]] std::byte const *bytes() const\n- 173 {\n- 174 return reinterpret_cast(get());\n- 175 }\n- 176\n-178 [[nodiscard]] std::basic_string_view bytes_view() const\n- 179 {\n- 180 return std::basic_string_view{bytes(), size()};\n- 181 }\n- 182\n- 183private:\n- 184 std::shared_ptr m_buf;\n- 185 size_type m_size{0};\n- 186};\n- 187\n- 188\n-189template<> struct nullness : no_null\n- 190{};\n- 191\n- 192\n- 194\n-201template<> struct string_traits\n- 202{\n-203 static std::size_t size_buffer(binarystring const &value) noexcept\n- 204 {\n- 205 return internal::size_esc_bin(std::size(value));\n- 206 }\n+ 148\n+ 150\n+173template inline void skip_init_ssl() noexcept\n+ 174{\n+ 175 // (Normalise skip flags to one per.)\n+ 176 pqxx::internal::skip_init_ssl(((1 << SKIP) | ...));\n+ 177}\n+ 178\n+ 179\n+ 181\n+188using table_path = std::initializer_list;\n+ 189\n+ 190\n+ 192[[nodiscard,\n+ 193 deprecated(\"Use connection::encrypt_password instead.\")]] std::string\n+ 194 PQXX_LIBEXPORT\n+ 195 encrypt_password(char const user[], char const password[]);\n+ 196\n+ 198[[nodiscard,\n+ 199 deprecated(\"Use connection::encrypt_password instead.\")]] inline std::\n+string\n+200encrypt_password(zview user, zview password)\n+ 201{\n+ 202#include \"pqxx/internal/ignore-deprecated-pre.hxx\"\n+ 203 return encrypt_password(user.c_str(), password.c_str());\n+ 204#include \"pqxx/internal/ignore-deprecated-post.hxx\"\n+ 205}\n+ 206\n 207\n-208 static zview to_buf(char *begin, char *end, binarystring const &value)\n- 209 {\n- 210 return generic_to_buf(begin, end, value);\n- 211 }\n- 212\n-213 static char *into_buf(char *begin, char *end, binarystring const &value)\n- 214 {\n- 215 auto const budget{size_buffer(value)};\n- 216 if (internal::cmp_less(end - begin, budget))\n- 217 throw conversion_overrun{\n- 218 \"Not enough buffer space to escape binary data.\"};\n- 219 std::string_view text{value.view()};\n- 220 internal::esc_bin(binary_cast(text), begin);\n- 221 return begin + budget;\n- 222 }\n- 223\n-224 static binarystring from_string(std::string_view text)\n- 225 {\n- 226 auto const size{pqxx::internal::size_unesc_bin(std::size(text))};\n- 227 std::shared_ptr buf{\n- 228 new unsigned char[size], [](unsigned char const *x) { delete[] x; }};\n- 229 pqxx::internal::unesc_bin(text, reinterpret_cast(buf.get()));\n- 230#include \"pqxx/internal/ignore-deprecated-pre.hxx\"\n- 231 return binarystring{std::move(buf), size};\n- 232#include \"pqxx/internal/ignore-deprecated-post.hxx\"\n- 233 }\n- 234};\n- 235} // namespace pqxx\n- 236#endif\n+209enum class error_verbosity : int\n+ 210{\n+ 211 // These values must match those in libpq's PGVerbosity enum.\n+ 212 terse = 0,\n+ 213 normal = 1,\n+ 214 verbose = 2\n+ 215};\n+ 216\n+ 217\n+ 219\n+252class PQXX_LIBEXPORT connection\n+ 253{\n+ 254public:\n+255 connection() : connection{\"\"} {}\n+ 256\n+258 explicit connection(char const options[])\n+ 259 {\n+ 260 check_version();\n+ 261 init(options);\n+ 262 }\n+ 263\n+265 explicit connection(zview options) : connection{options.c_str()}\n+ 266 {\n+ 267 // (Delegates to other constructor which calls check_version for us.)\n+ 268 }\n+ 269\n+ 271\n+ 276 connection(connection &&rhs);\n+ 277\n+ 278#if defined(PQXX_HAVE_CONCEPTS)\n+ 280\n+ 295 template\n+ 296 inline connection(MAPPING const ¶ms);\n+ 297#endif // PQXX_HAVE_CONCEPTS\n+ 298\n+299 ~connection()\n+ 300 {\n+ 301 try\n+ 302 {\n+ 303 close();\n+ 304 }\n+ 305 catch (std::exception const &)\n+ 306 {}\n+ 307 }\n+ 308\n+ 310\n+ 313 connection &operator=(connection &&rhs);\n+ 314\n+315 connection(connection const &) = delete;\n+316 connection &operator=(connection const &) = delete;\n+ 317\n+ 319\n+ 324 [[nodiscard]] bool PQXX_PURE is_open() const noexcept;\n+ 325\n+ 327 void process_notice(char const[]) noexcept;\n+ 329\n+ 332 void process_notice(zview) noexcept;\n+ 333\n+ 335 void trace(std::FILE *) noexcept;\n+ 336\n+ 348\n+ 349 [[nodiscard]] char const *dbname() const;\n+ 350\n+ 352\n+ 353 [[nodiscard]] char const *username() const;\n+ 354\n+ 356\n+ 359 [[nodiscard]] char const *hostname() const;\n+ 360\n+ 362 [[nodiscard]] char const *port() const;\n+ 363\n+ 365 [[nodiscard]] int PQXX_PURE backendpid() const &noexcept;\n+ 366\n+ 368\n+ 378 [[nodiscard]] int PQXX_PURE sock() const &noexcept;\n+ 379\n+ 381\n+ 384 [[nodiscard]] int PQXX_PURE protocol_version() const noexcept;\n+ 385\n+ 387\n+ 399 [[nodiscard]] int PQXX_PURE server_version() const noexcept;\n+ 401\n+ 403\n+ 424 [[nodiscard]] std::string get_client_encoding() const;\n+ 425\n+ 427\n+430 void set_client_encoding(zview encoding) &\n+ 431 {\n+ 432 set_client_encoding(encoding.c_str());\n+ 433 }\n+ 434\n+ 436\n+ 439 void set_client_encoding(char const encoding[]) &;\n+ 440\n+ 442 [[nodiscard]] int encoding_id() const;\n+ 443\n+ 445\n+ 447\n+ 460 [[deprecated(\"To set session variables, use set_session_var.\")]] void\n+ 461 set_variable(std::string_view var, std::string_view value) &;\n+ 462\n+ 464\n+ 485 template\n+486 void set_session_var(std::string_view var, TYPE const &value) &\n+ 487 {\n+ 488 if constexpr (nullness::has_null)\n+ 489 {\n+ 490 if (nullness::is_null(value))\n+ 491 throw variable_set_to_null{\n+ 492 internal::concat(\"Attempted to set variable \", var, \" to null.\")};\n+ 493 }\n+ 494 exec(internal::concat(\"SET \", quote_name(var), \"=\", quote(value)));\n+ 495 }\n+ 496\n+ 498\n+ 501 [[deprecated(\"Use get_var instead.\")]] std::string\n+ 502 get_variable(std::string_view);\n+ 503\n+ 505\n+ 511 std::string get_var(std::string_view var);\n+ 512\n+ 514\n+520 template TYPE get_var_as(std::string_view var)\n+ 521 {\n+ 522 return from_string(get_var(var));\n+ 523 }\n+ 524\n+ 530\n+ 547 int get_notifs();\n+ 548\n+ 550\n+ 562 int await_notification();\n+ 563\n+ 565\n+ 577 int await_notification(std::time_t seconds, long microseconds);\n+ 579\n+ 611 [[nodiscard]] std::string\n+612 encrypt_password(zview user, zview password, zview algorithm)\n+ 613 {\n+ 614 return encrypt_password(user.c_str(), password.c_str(), algorithm.c_str\n+());\n+ 615 }\n+ 617 [[nodiscard]] std::string encrypt_password(\n+ 618 char const user[], char const password[], char const *algorithm =\n+nullptr);\n+ 620\n+ 663\n+ 665\n+669 void prepare(zview name, zview definition) &\n+ 670 {\n+ 671 prepare(name.c_str(), definition.c_str());\n+ 672 }\n+ 673\n+ 678 void prepare(char const name[], char const definition[]) &;\n+ 679\n+ 681\n+ 688 void prepare(char const definition[]) &;\n+689 void prepare(zview definition) & { return prepare(definition.c_str()); }\n+ 690\n+ 692 void unprepare(std::string_view name);\n+ 693\n+ 695\n+ 696 // C++20: constexpr. Breaks ABI.\n+ 698\n+ 701 [[nodiscard]] std::string adorn_name(std::string_view);\n+ 702\n+ 707\n+ 709\n+ 713 [[deprecated(\"Use std::string_view or pqxx:zview.\")]] std::string\n+714 esc(char const text[], std::size_t maxlen) const\n+ 715 {\n+ 716 return esc(std::string_view{text, maxlen});\n+ 717 }\n+ 718\n+720 [[nodiscard]] std::string esc(char const text[]) const\n+ 721 {\n+ 722 return esc(std::string_view{text});\n+ 723 }\n+ 724\n+ 725#if defined(PQXX_HAVE_SPAN)\n+ 727\n+ 738 [[nodiscard]] std::string_view\n+ 739 esc(std::string_view text, std::span buffer)\n+ 740 {\n+ 741 auto const size{std::size(text)}, space{std::size(buffer)};\n+ 742 auto const needed{2 * size + 1};\n+ 743 if (space < needed)\n+ 744 throw range_error{internal::concat(\n+ 745 \"Not enough room to escape string of \", size, \" byte(s): need \",\n+ 746 needed, \" bytes of buffer space, but buffer size is \", space, \".\")};\n+ 747 auto const data{buffer.data()};\n+ 748 return {data, esc_to_buf(text, data)};\n+ 749 }\n+ 750#endif\n+ 751\n+ 753\n+ 756 [[nodiscard]] std::string esc(std::string_view text) const;\n+ 757\n+ 758#if defined(PQXX_HAVE_CONCEPTS)\n+ 760\n+ 761 template [[nodiscard]] std::string esc(DATA const &data)\n+const\n+ 762 {\n+ 763 return esc_raw(data);\n+ 764 }\n+ 765#endif\n+ 766\n+ 767#if defined(PQXX_HAVE_CONCEPTS) && defined(PQXX_HAVE_SPAN)\n+ 769\n+ 780 template\n+ 781 [[nodiscard]] zview esc(DATA const &data, std::span buffer) const\n+ 782 {\n+ 783 auto const size{std::size(data)}, space{std::size(buffer)};\n+ 784 auto const needed{internal::size_esc_bin(std::size(data))};\n+ 785 if (space < needed)\n+ 786 throw range_error{internal::concat(\n+ 787 \"Not enough room to escape binary string of \", size, \" byte(s): need \",\n+ 788 needed, \" bytes of buffer space, but buffer size is \", space, \".\")};\n+ 789\n+ 790 std::basic_string_view view{std::data(data), std::size(data)};\n+ 791 auto const out{std::data(buffer)};\n+ 792 // Actually, in the modern format, we know beforehand exactly how many\n+ 793 // bytes we're going to fill. Just leave out the trailing zero.\n+ 794 internal::esc_bin(view, out);\n+ 795 return zview{out, needed - 1};\n+ 796 }\n+ 797#endif\n+ 798\n+ 800 [[deprecated(\"Use std::byte for binary data.\")]] std::string\n+ 801 esc_raw(unsigned char const bin[], std::size_t len) const;\n+ 802\n+ 804\n+ 805 [[nodiscard]] std::string esc_raw(std::basic_string_view)\n+const;\n+ 806\n+ 807#if defined(PQXX_HAVE_SPAN)\n+ 809\n+ 810 [[nodiscard]] std::string\n+ 811 esc_raw(std::basic_string_view, std::span buffer) const;\n+ 812#endif\n+ 813\n+ 814#if defined(PQXX_HAVE_CONCEPTS)\n+ 816\n+ 817 template\n+ 818 [[nodiscard]] std::string esc_raw(DATA const &data) const\n+ 819 {\n+ 820 return esc_raw(\n+ 821 std::basic_string_view{std::data(data), std::size(data)});\n+ 822 }\n+ 823#endif\n+ 824\n+ 825#if defined(PQXX_HAVE_CONCEPTS) && defined(PQXX_HAVE_SPAN)\n+ 827 template\n+ 828 [[nodiscard]] zview esc_raw(DATA const &data, std::span buffer)\n+const\n+ 829 {\n+ 830 return this->esc(binary_cast(data), buffer);\n+ 831 }\n+ 832#endif\n+ 833\n+ 835\n+ 838 [[nodiscard, deprecated(\"Use unesc_bin() instead.\")]] std::string\n+839 unesc_raw(zview text) const\n+ 840 {\n+ 841#include \"pqxx/internal/ignore-deprecated-pre.hxx\"\n+ 842 return unesc_raw(text.c_str());\n+ 843#include \"pqxx/internal/ignore-deprecated-post.hxx\"\n+ 844 }\n+ 845\n+ 847\n+ 850 [[nodiscard, deprecated(\"Use unesc_bin() instead.\")]] std::string\n+ 851 unesc_raw(char const text[]) const;\n+ 852\n+ 853 // TODO: Make \"into buffer\" variant to eliminate a string allocation.\n+ 855\n+ 862 [[nodiscard]] std::basic_string\n+863 unesc_bin(std::string_view text) const\n+ 864 {\n+ 865 std::basic_string buf;\n+ 866 buf.resize(pqxx::internal::size_unesc_bin(std::size(text)));\n+ 867 pqxx::internal::unesc_bin(text, buf.data());\n+ 868 return buf;\n+ 869 }\n+ 870\n+ 872 [[deprecated(\"Use quote(std::basic_string_view).\")]] std::\n+string\n+ 873 quote_raw(unsigned char const bin[], std::size_t len) const;\n+ 874\n+ 876 std::string quote_raw(std::basic_string_view) const;\n+ 877\n+ 878#if defined(PQXX_HAVE_CONCEPTS)\n+ 880\n+ 881 template\n+ 882 [[nodiscard]] std::string quote_raw(DATA const &data) const\n+ 883 {\n+ 884 return quote_raw(\n+ 885 std::basic_string_view{std::data(data), std::size(data)});\n+ 886 }\n+ 887#endif\n+ 888\n+ 889 // TODO: Make \"into buffer\" variant to eliminate a string allocation.\n+ 891 [[nodiscard]] std::string quote_name(std::string_view identifier) const;\n+ 892\n+ 893 // TODO: Make \"into buffer\" variant to eliminate a string allocation.\n+ 895\n+ 898 [[nodiscard]] std::string quote_table(std::string_view name) const;\n+ 899\n+ 900 // TODO: Make \"into buffer\" variant to eliminate a string allocation.\n+ 902\n+ 910 [[nodiscard]] std::string quote_table(table_path) const;\n+ 911\n+ 912 // TODO: Make \"into buffer\" variant to eliminate a string allocation.\n+ 914\n+ 921 template\n+ 922 inline std::string quote_columns(STRINGS const &columns) const;\n+ 923\n+ 924 // TODO: Make \"into buffer\" variant to eliminate a string allocation.\n+ 926\n+ 929 template\n+ 930 [[nodiscard]] inline std::string quote(T const &t) const;\n+ 931\n+ 932 [[deprecated(\"Use std::byte for binary data.\")]] std::string\n+ 933 quote(binarystring const &) const;\n+ 934\n+ 935 // TODO: Make \"into buffer\" variant to eliminate a string allocation.\n+ 937 [[nodiscard]] std::string\n+ 938 quote(std::basic_string_view bytes) const;\n+ 939\n+ 940 // TODO: Make \"into buffer\" variant to eliminate a string allocation.\n+ 942\n+ 967 [[nodiscard]] std::string\n+ 968 esc_like(std::string_view text, char escape_char = '\\\\') const;\n+ 970\n+ 972\n+ 976 void cancel_query();\n+ 977\n+ 978#if defined(_WIN32) || __has_include()\n+ 980\n+ 984 void set_blocking(bool block) &;\n+ 985#endif // defined(_WIN32) || __has_include()\n+ 986\n+ 988\n+ 997 void set_verbosity(error_verbosity verbosity) &noexcept;\n+ 998\n+ 1000\n+ 1012 [[nodiscard]] std::vector get_errorhandlers() const;\n+ 1013\n+ 1015\n+ 1021 [[nodiscard]] std::string connection_string() const;\n+ 1022\n+ 1024\n+ 1032 void close();\n+ 1033\n+ 1035\n+1041 static connection seize_raw_connection(internal::pq::PGconn *raw_conn)\n+ 1042 {\n+ 1043 return connection{raw_conn};\n+ 1044 }\n+ 1045\n+ 1047\n+1052 internal::pq::PGconn *release_raw_connection() &&\n+ 1053 {\n+ 1054 return std::exchange(m_conn, nullptr);\n+ 1055 }\n+ 1056\n+ 1057private:\n+1058 friend class connecting;\n+ 1059 enum connect_mode\n+ 1060 {\n+ 1061 connect_nonblocking\n+ 1062 };\n+ 1063 connection(connect_mode, zview connection_string);\n+ 1064\n+ 1066 explicit connection(internal::pq::PGconn *raw_conn) : m_conn{raw_conn} {}\n+ 1067\n+ 1069\n+ 1074 std::pair poll_connect();\n+ 1075\n+ 1076 // Initialise based on connection string.\n+ 1077 void init(char const options[]);\n+ 1078 // Initialise based on parameter names and values.\n+ 1079 void init(char const *params[], char const *values[]);\n+ 1080 void complete_init();\n+ 1081\n+ 1082 result make_result(\n+ 1083 internal::pq::PGresult *pgr, std::shared_ptr const &query,\n+ 1084 std::string_view desc = \"\"sv);\n+ 1085\n+ 1086 void PQXX_PRIVATE set_up_state();\n+ 1087\n+ 1088 int PQXX_PRIVATE PQXX_PURE status() const noexcept;\n+ 1089\n+ 1091\n+ 1095 std::size_t esc_to_buf(std::string_view text, char *buf) const;\n+ 1096\n+1097 friend class internal::gate::const_connection_largeobject;\n+ 1098 char const *PQXX_PURE err_msg() const noexcept;\n+ 1099\n+ 1100 void PQXX_PRIVATE process_notice_raw(char const msg[]) noexcept;\n+ 1101\n+ 1102 result exec_prepared(std::string_view statement, internal::c_params const\n+&);\n+ 1103\n+ 1105 void check_movable() const;\n+ 1107 void check_overwritable() const;\n+ 1108\n+1109 friend class internal::gate::connection_errorhandler;\n+ 1110 void PQXX_PRIVATE register_errorhandler(errorhandler *);\n+ 1111 void PQXX_PRIVATE unregister_errorhandler(errorhandler *) noexcept;\n+ 1112\n+1113 friend class internal::gate::connection_transaction;\n+ 1114 result exec(std::string_view, std::string_view = \"\"sv);\n+ 1115 result\n+ 1116 PQXX_PRIVATE exec(std::shared_ptr, std::string_view = \"\"sv);\n+ 1117 void PQXX_PRIVATE register_transaction(transaction_base *);\n+ 1118 void PQXX_PRIVATE unregister_transaction(transaction_base *) noexcept;\n+ 1119\n+1120 friend struct internal::gate::connection_stream_from;\n+ 1121 std::pair, std::size_t>\n+ 1122 read_copy_line();\n+ 1123\n+1124 friend class internal::gate::connection_stream_to;\n+ 1125 void PQXX_PRIVATE write_copy_line(std::string_view);\n+ 1126 void PQXX_PRIVATE end_copy_write();\n+ 1127\n+1128 friend class internal::gate::connection_largeobject;\n+ 1129 internal::pq::PGconn *raw_connection() const { return m_conn; }\n+ 1130\n+1131 friend class internal::gate::connection_notification_receiver;\n+ 1132 void add_receiver(notification_receiver *);\n+ 1133 void remove_receiver(notification_receiver *) noexcept;\n+ 1134\n+1135 friend class internal::gate::connection_pipeline;\n+ 1136 void PQXX_PRIVATE start_exec(char const query[]);\n+ 1137 bool PQXX_PRIVATE consume_input() noexcept;\n+ 1138 bool PQXX_PRIVATE is_busy() const noexcept;\n+ 1139 internal::pq::PGresult *get_result();\n+ 1140\n+1141 friend class internal::gate::connection_dbtransaction;\n+1142 friend class internal::gate::connection_sql_cursor;\n+ 1143\n+ 1144 result exec_params(std::string_view query, internal::c_params const\n+&args);\n+ 1145\n+ 1147 internal::pq::PGconn *m_conn = nullptr;\n+ 1148\n+ 1150\n+ 1157 transaction_base const *m_trans = nullptr;\n+ 1158\n+ 1159 std::list m_errorhandlers;\n+ 1160\n+ 1161 using receiver_list =\n+ 1162 std::multimap;\n+ 1164 receiver_list m_receivers;\n+ 1165\n+ 1167 int m_unique_id = 0;\n+ 1168};\n+ 1169\n+ 1170\n+1172using connection_base = connection;\n+ 1173\n+ 1174\n+ 1176\n+1219class PQXX_LIBEXPORT connecting\n+ 1220{\n+ 1221public:\n+1223 connecting(zview connection_string = \"\"_zv);\n+ 1224\n+1225 connecting(connecting const &) = delete;\n+1226 connecting(connecting &&) = default;\n+1227 connecting &operator=(connecting const &) = delete;\n+1228 connecting &operator=(connecting &&) = default;\n+ 1229\n+1231 [[nodiscard]] int sock() const &noexcept { return m_conn.sock(); }\n+ 1232\n+1234 [[nodiscard]] constexpr bool wait_to_read() const &noexcept\n+ 1235 {\n+ 1236 return m_reading;\n+ 1237 }\n+ 1238\n+1240 [[nodiscard]] constexpr bool wait_to_write() const &noexcept\n+ 1241 {\n+ 1242 return m_writing;\n+ 1243 }\n+ 1244\n+1246 void process() &;\n+ 1247\n+1249 [[nodiscard]] constexpr bool done() const &noexcept\n+ 1250 {\n+ 1251 return not m_reading and not m_writing;\n+ 1252 }\n+ 1253\n+ 1255\n+1263 [[nodiscard]] connection produce() &&;\n+ 1264\n+ 1265private:\n+ 1266 connection m_conn;\n+ 1267 bool m_reading{false};\n+ 1268 bool m_writing{true};\n+ 1269};\n+ 1270\n+ 1271\n+1272template inline std::string connection::quote(T const &t) const\n+ 1273{\n+ 1274 if constexpr (nullness::always_null)\n+ 1275 {\n+ 1276 return \"NULL\";\n+ 1277 }\n+ 1278 else\n+ 1279 {\n+ 1280 if (is_null(t))\n+ 1281 return \"NULL\";\n+ 1282 auto const text{to_string(t)};\n+ 1283\n+ 1284 // Okay, there's an easy way to do this and there's a hard way. The easy\n+ 1285 // way was \"quote, esc(to_string(t)), quote\". I'm going with the hard way\n+ 1286 // because it's going to save some string manipulation that will probably\n+ 1287 // incur some unnecessary memory allocations and deallocations.\n+ 1288 std::string buf{'\\''};\n+ 1289 buf.resize(2 + 2 * std::size(text) + 1);\n+ 1290 auto const content_bytes{esc_to_buf(text, buf.data() + 1)};\n+ 1291 auto const closing_quote{1 + content_bytes};\n+ 1292 buf[closing_quote] = '\\'';\n+ 1293 auto const end{closing_quote + 1};\n+ 1294 buf.resize(end);\n+ 1295 return buf;\n+ 1296 }\n+ 1297}\n+ 1298\n+ 1299\n+ 1300template\n+1301inline std::string connection::quote_columns(STRINGS const &columns) const\n+ 1302{\n+ 1303 return separated_list(\n+ 1304 \",\"sv, std::cbegin(columns), std::cend(columns),\n+ 1305 [this](auto col) { return this->quote_name(*col); });\n+ 1306}\n+ 1307\n+ 1308\n+ 1309#if defined(PQXX_HAVE_CONCEPTS)\n+ 1310template\n+ 1311inline connection::connection(MAPPING const ¶ms)\n+ 1312{\n+ 1313 check_version();\n+ 1314\n+ 1315 std::vector keys, values;\n+ 1316 if constexpr (std::ranges::sized_range)\n+ 1317 {\n+ 1318 auto const size{std::ranges::size(params) + 1};\n+ 1319 keys.reserve(size);\n+ 1320 values.reserve(size);\n+ 1321 }\n+ 1322 for (auto const &[key, value] : params)\n+ 1323 {\n+ 1324 keys.push_back(internal::as_c_string(key));\n+ 1325 values.push_back(internal::as_c_string(value));\n+ 1326 }\n+ 1327 keys.push_back(nullptr);\n+ 1328 values.push_back(nullptr);\n+ 1329 init(std::data(keys), std::data(values));\n+ 1330}\n+ 1331#endif // PQXX_HAVE_CONCEPTS\n+ 1332} // namespace pqxx\n+ 1333#endif\n pqxx\n The home of all libpqxx classes, functions, templates, etc.\n Definition array.hxx:33\n+pqxx::separated_list\n+std::string separated_list(std::string_view sep, ITER begin, ITER end, ACCESS\n+access)\n+Represent sequence of values as a string, joined by a given separator.\n+Definition separated_list.hxx:44\n+pqxx::encrypt_password\n+std::string encrypt_password(char const user[], char const password[])\n+Encrypt a password.\n+Definition connection.cxx:94\n pqxx::binary_cast\n std::basic_string_view< std::byte > binary_cast(TYPE const &data)\n Cast binary data to a type that libpqxx will recognise as binary.\n Definition util.hxx:303\n+pqxx::skip_init_ssl\n+void skip_init_ssl() noexcept\n+Control initialisation of OpenSSL and libcrypto libraries.\n+Definition connection.hxx:173\n+pqxx::table_path\n+std::initializer_list< std::string_view > table_path\n+Representation of a PostgreSQL table path.\n+Definition connection.hxx:188\n+pqxx::check_version\n+void check_version() noexcept\n+Definition util.hxx:234\n+pqxx::to_string\n+std::string to_string(field const &value)\n+Convert a field to a string.\n+Definition result.cxx:549\n+pqxx::skip_init\n+skip_init\n+Flags for skipping initialisation of SSL-related libraries.\n+Definition connection.hxx:137\n+pqxx::crypto\n+@ crypto\n+Skip initialisation of libcrypto.\n+Definition connection.hxx:145\n+pqxx::openssl\n+@ openssl\n+Skip initialisation of OpenSSL library.\n+Definition connection.hxx:142\n+pqxx::nothing\n+@ nothing\n+A do-nothing flag that does not affect anything.\n+Definition connection.hxx:139\n+pqxx::error_verbosity\n+error_verbosity\n+Error verbosity levels.\n+Definition connection.hxx:210\n+pqxx::error_verbosity::terse\n+@ terse\n+pqxx::error_verbosity::verbose\n+@ verbose\n+pqxx::error_verbosity::normal\n+@ normal\n pqxx::format::text\n @ text\n+pqxx::internal\n+Internal items for libpqxx' own use. Do not use these yourself.\n+Definition composite.hxx:84\n+pqxx::internal::skip_init_ssl\n+void PQXX_COLD skip_init_ssl(int flags) noexcept\n+Control OpenSSL/crypto library initialisation.\n+Definition connection.cxx:83\n pqxx::internal::unesc_bin\n void unesc_bin(std::string_view escaped_data, std::byte buffer[])\n Reconstitute binary data from its escaped version.\n Definition util.cxx:158\n pqxx::internal::esc_bin\n void esc_bin(std::basic_string_view< std::byte > binary_data, char buffer[])\n noexcept\n Hex-escape binary data into a buffer.\n Definition util.cxx:126\n pqxx::internal::size_esc_bin\n constexpr std::size_t size_esc_bin(std::size_t binary_bytes) noexcept\n Compute buffer size needed to escape binary data for use as a BYTEA.\n Definition util.hxx:411\n-pqxx::internal::cmp_less\n-constexpr bool cmp_less(LEFT lhs, RIGHT rhs) noexcept\n-Same as std::cmp_less, or a workaround where that's not available.\n-Definition util.hxx:63\n+pqxx::internal::as_c_string\n+constexpr char const * as_c_string(char const str[]) noexcept\n+Get a raw C string pointer.\n+Definition zview.hxx:145\n pqxx::internal::size_unesc_bin\n constexpr std::size_t size_unesc_bin(std::size_t escaped_bytes) noexcept\n Compute binary size from the size of its escaped version.\n Definition util.hxx:420\n-pqxx::binarystring\n-Binary data corresponding to PostgreSQL's \"BYTEA\" binary-string type.\n-Definition binarystring.hxx:59\n-pqxx::binarystring::crend\n-const_reverse_iterator crend() const\n-Definition binarystring.hxx:124\n-pqxx::binarystring::get\n-char const * get() const noexcept\n-Raw character buffer (no terminating zero is added).\n-Definition binarystring.hxx:152\n-pqxx::binarystring::rbegin\n-const_reverse_iterator rbegin() const\n-Definition binarystring.hxx:115\n-pqxx::binarystring::operator!=\n-bool operator!=(binarystring const &rhs) const noexcept\n-Definition binarystring.hxx:135\n-pqxx::binarystring::const_iterator\n-const_pointer const_iterator\n-Definition binarystring.hxx:67\n-pqxx::binarystring::end\n-const_iterator end() const noexcept\n-Definition binarystring.hxx:106\n-pqxx::binarystring::bytes_view\n-std::basic_string_view< std::byte > bytes_view() const\n-Read data as a std::basic_string_view.\n-Definition binarystring.hxx:178\n-pqxx::binarystring::begin\n-const_iterator begin() const noexcept\n-Definition binarystring.hxx:104\n-pqxx::binarystring::value_type\n-std::char_traits< char_type >::char_type value_type\n-Definition binarystring.hxx:62\n-pqxx::binarystring::const_reference\n-value_type const & const_reference\n-Definition binarystring.hxx:65\n-pqxx::binarystring::difference_type\n-long difference_type\n-Definition binarystring.hxx:64\n-pqxx::binarystring::binarystring\n-binarystring(std::shared_ptr< value_type > ptr, size_type size)\n-Efficiently wrap a buffer of binary data in a binarystring.\n-Definition binarystring.hxx:93\n-pqxx::binarystring::crbegin\n-const_reverse_iterator crbegin() const\n-Definition binarystring.hxx:119\n-pqxx::binarystring::size_type\n-std::size_t size_type\n-Definition binarystring.hxx:63\n-pqxx::binarystring::front\n-const_reference front() const noexcept\n-Definition binarystring.hxx:109\n-pqxx::binarystring::back\n-const_reference back() const noexcept\n-Definition binarystring.hxx:110\n-pqxx::binarystring::view\n-std::string_view view() const noexcept\n-Read contents as a std::string_view.\n-Definition binarystring.hxx:158\n-pqxx::binarystring::empty\n-bool empty() const noexcept\n-Definition binarystring.hxx:102\n-pqxx::binarystring::bytes\n-std::byte const * bytes() const\n-Access data as a pointer to std::byte.\n-Definition binarystring.hxx:172\n-pqxx::binarystring::operator[]\n-const_reference operator[](size_type i) const noexcept\n-Definition binarystring.hxx:129\n-pqxx::binarystring::cend\n-const_iterator cend() const noexcept\n-Definition binarystring.hxx:107\n-pqxx::binarystring::data\n-value_type const * data() const noexcept\n-Unescaped field contents.\n-Definition binarystring.hxx:127\n-pqxx::binarystring::rend\n-const_reverse_iterator rend() const\n-Definition binarystring.hxx:120\n-pqxx::binarystring::length\n-size_type length() const noexcept\n-Size of converted string in bytes.\n-Definition binarystring.hxx:101\n-pqxx::binarystring::operator=\n-binarystring & operator=(binarystring const &)\n-pqxx::binarystring::char_type\n-unsigned char char_type\n-Definition binarystring.hxx:61\n-pqxx::binarystring::const_reverse_iterator\n-std::reverse_iterator< const_iterator > const_reverse_iterator\n-Definition binarystring.hxx:68\n-pqxx::binarystring::cbegin\n-const_iterator cbegin() const noexcept\n-Definition binarystring.hxx:105\n-pqxx::binarystring::binarystring\n-binarystring(binarystring const &)=default\n-pqxx::binarystring::const_pointer\n-value_type const * const_pointer\n-Definition binarystring.hxx:66\n-pqxx::binarystring::size\n-size_type size() const noexcept\n-Size of converted string in bytes.\n-Definition binarystring.hxx:99\n-pqxx::string_traits<_binarystring_>::into_buf\n-static char * into_buf(char *begin, char *end, binarystring const &value)\n-Definition binarystring.hxx:213\n-pqxx::string_traits<_binarystring_>::size_buffer\n-static std::size_t size_buffer(binarystring const &value) noexcept\n-Definition binarystring.hxx:203\n-pqxx::string_traits<_binarystring_>::to_buf\n-static zview to_buf(char *begin, char *end, binarystring const &value)\n-Definition binarystring.hxx:208\n-pqxx::string_traits<_binarystring_>::from_string\n-static binarystring from_string(std::string_view text)\n-Definition binarystring.hxx:224\n-pqxx::conversion_overrun\n-Could not convert value to string: not enough buffer space.\n-Definition except.hxx:313\n-pqxx::field\n-Reference to a field in a result set.\n-Definition field.hxx:35\n+pqxx::internal::gate\n+Definition connection.hxx:112\n+pqxx::connection\n+Connection to a database.\n+Definition connection.hxx:253\n+pqxx::connection::encrypt_password\n+std::string encrypt_password(zview user, zview password, zview algorithm)\n+Encrypt a password for a given user.\n+Definition connection.hxx:612\n+pqxx::connection::prepare\n+void prepare(zview definition) &\n+Definition connection.hxx:689\n+pqxx::connection::connection\n+connection(char const options[])\n+Connect to a database, using options string.\n+Definition connection.hxx:258\n+pqxx::connection::operator=\n+connection & operator=(connection const &)=delete\n+pqxx::connection::get_var_as\n+TYPE get_var_as(std::string_view var)\n+Read currently applicable value of a variable.\n+Definition connection.hxx:520\n+pqxx::connection::connection\n+connection()\n+Definition connection.hxx:255\n+pqxx::connection::~connection\n+~connection()\n+Definition connection.hxx:299\n+pqxx::connection::quote_columns\n+std::string quote_columns(STRINGS const &columns) const\n+Quote and comma-separate a series of column names.\n+Definition connection.hxx:1301\n+pqxx::connection::connection\n+connection(zview options)\n+Connect to a database, using options string.\n+Definition connection.hxx:265\n+pqxx::connection::release_raw_connection\n+internal::pq::PGconn * release_raw_connection() &&\n+Release the raw connection without closing it.\n+Definition connection.hxx:1052\n+pqxx::connection::seize_raw_connection\n+static connection seize_raw_connection(internal::pq::PGconn *raw_conn)\n+Seize control of a raw libpq connection.\n+Definition connection.hxx:1041\n+pqxx::connection::unesc_bin\n+std::basic_string< std::byte > unesc_bin(std::string_view text) const\n+Unescape binary data, e.g. from a table field or notification payload.\n+Definition connection.hxx:863\n+pqxx::connection::esc\n+std::string esc(char const text[]) const\n+Escape string for use as SQL string literal on this connection.\n+Definition connection.hxx:720\n+pqxx::connection::unesc_raw\n+std::string unesc_raw(zview text) const\n+Unescape binary data, e.g. from a table field or notification payload.\n+Definition connection.hxx:839\n+pqxx::connection::esc\n+std::string esc(char const text[], std::size_t maxlen) const\n+Escape string for use as SQL string literal on this connection.\n+Definition connection.hxx:714\n+pqxx::connection::prepare\n+void prepare(zview name, zview definition) &\n+Define a prepared statement.\n+Definition connection.hxx:669\n+pqxx::connection::set_session_var\n+void set_session_var(std::string_view var, TYPE const &value) &\n+Set one of the session variables to a new value.\n+Definition connection.hxx:486\n+pqxx::connection::quote\n+std::string quote(T const &t) const\n+Represent object as SQL string, including quoting & escaping.\n+Definition connection.hxx:1272\n+pqxx::connection::connection\n+connection(connection const &)=delete\n+pqxx::connecting\n+An ongoing, non-blocking stepping stone to a connection.\n+Definition connection.hxx:1220\n+pqxx::connecting::connecting\n+connecting(connecting &&)=default\n+pqxx::connecting::sock\n+int sock() const &noexcept\n+Get the socket. The socket may change during the connection process.\n+Definition connection.hxx:1231\n+pqxx::connecting::done\n+constexpr bool done() const &noexcept\n+Is our connection finished?\n+Definition connection.hxx:1249\n+pqxx::connecting::operator=\n+connecting & operator=(connecting const &)=delete\n+pqxx::connecting::connecting\n+connecting(connecting const &)=delete\n+pqxx::connecting::wait_to_write\n+constexpr bool wait_to_write() const &noexcept\n+Should we currently wait to be able to write to the socket?\n+Definition connection.hxx:1240\n+pqxx::connecting::process\n+void process() &\n+Progress towards completion (but don't block).\n+pqxx::connecting::operator=\n+connecting & operator=(connecting &&)=default\n+pqxx::connecting::wait_to_read\n+constexpr bool wait_to_read() const &noexcept\n+Should we currently wait to be able to read from the socket?\n+Definition connection.hxx:1234\n+pqxx::connecting::connecting\n+connecting(zview connection_string=\"\"_zv)\n+Start connecting.\n+pqxx::connecting::produce\n+connection produce() &&\n+Produce the completed connection object.\n+pqxx::errorhandler\n+Base class for error-handler callbacks.\n+Definition errorhandler.hxx:54\n+pqxx::variable_set_to_null\n+The caller attempted to set a variable to null, which is not allowed.\n+Definition except.hxx:116\n+pqxx::notification_receiver\n+Definition notification.hxx:57\n+pqxx::params\n+Build a parameter list for a parameterised or prepared statement.\n+Definition params.hxx:220\n+pqxx::result\n+Result set containing data returned by a query or command.\n+Definition result.hxx:73\n pqxx::nullness\n Traits describing a type's \"null value,\" if any.\n Definition strconv.hxx:93\n-pqxx::no_null\n-Nullness traits describing a type which does not have a null value.\n-Definition strconv.hxx:115\n-pqxx::string_traits\n-Traits class for use in string conversions.\n-Definition strconv.hxx:155\n-pqxx::string_traits::size_buffer\n-static std::size_t size_buffer(TYPE const &value) noexcept\n-Estimate how much buffer space is needed to represent value.\n+pqxx::transaction_base\n+Interface definition (and common code) for \"transaction\" classes.\n+Definition transaction_base.hxx:88\n pqxx::zview\n Marker-type wrapper: zero-terminated std::string_view.\n Definition zview.hxx:38\n+pqxx::zview::c_str\n+constexpr char const * c_str() const &noexcept\n+Either a null pointer, or a zero-terminated text buffer.\n+Definition zview.hxx:96\n * include\n * pqxx\n- * binarystring.hxx\n+ * connection.hxx\n * Generated by [doxygen] 1.9.8\n"}]}, {"source1": "./usr/share/doc/libpqxx-doc/html/a00068_source.html", "source2": "./usr/share/doc/libpqxx-doc/html/a00068_source.html", "unified_diff": "@@ -1,15 +1,15 @@\n \n \n \n \n \n \n \n-libpqxx: transaction_base.hxx Source File\n+libpqxx: robusttransaction.hxx Source File\n \n \n \n \n \n \n \n@@ -60,671 +60,112 @@\n \n
\n
\n-
transaction_base.hxx
\n+
robusttransaction.hxx
\n
\n
\n-
1/* Common code and definitions for the transaction classes.
\n+
1/* Definition of the pqxx::robusttransaction class.
\n
2 *
\n-
3 * pqxx::transaction_base defines the interface for any abstract class that
\n-
4 * represents a database transaction.
\n-
5 *
\n-
6 * DO NOT INCLUDE THIS FILE DIRECTLY; include pqxx/transaction_base instead.
\n-
7 *
\n-
8 * Copyright (c) 2000-2023, Jeroen T. Vermeulen.
\n-
9 *
\n-
10 * See COPYING for copyright license. If you did not receive a file called
\n-
11 * COPYING with this source code, please notify the distributor of this
\n-
12 * mistake, or contact the author.
\n-
13 */
\n-
14#ifndef PQXX_H_TRANSACTION_BASE
\n-
15#define PQXX_H_TRANSACTION_BASE
\n-
16
\n-
17#if !defined(PQXX_HEADER_PRE)
\n-
18# error "Include libpqxx headers as <pqxx/header>, not <pqxx/header.hxx>."
\n-
19#endif
\n-
20
\n-
21#include <string_view>
\n-
22
\n-
23/* End-user programs need not include this file, unless they define their own
\n-
24 * transaction classes. This is not something the typical program should want
\n-
25 * to do.
\n-
26 *
\n-
27 * However, reading this file is worthwhile because it defines the public
\n-
28 * interface for the available transaction classes such as transaction and
\n-
29 * nontransaction.
\n-
30 */
\n-
31
\n-
32#include "pqxx/connection.hxx"
\n-
33#include "pqxx/internal/concat.hxx"
\n-
34#include "pqxx/internal/encoding_group.hxx"
\n-
35#include "pqxx/internal/stream_query.hxx"
\n-
36#include "pqxx/isolation.hxx"
\n-
37#include "pqxx/result.hxx"
\n-
38#include "pqxx/row.hxx"
\n-
39#include "pqxx/util.hxx"
\n-
40
\n-\n-
42{
\n-
43class transaction_subtransaction;
\n-
44class transaction_sql_cursor;
\n-
45class transaction_stream_to;
\n-
46class transaction_transaction_focus;
\n-
47} // namespace pqxx::internal::gate
\n-
48
\n+
3 * pqxx::robusttransaction is a slower but safer transaction class.
\n+
4 *
\n+
5 * DO NOT INCLUDE THIS FILE DIRECTLY; include pqxx/robusttransaction instead.
\n+
6 *
\n+
7 * Copyright (c) 2000-2023, Jeroen T. Vermeulen.
\n+
8 *
\n+
9 * See COPYING for copyright license. If you did not receive a file called
\n+
10 * COPYING with this source code, please notify the distributor of this
\n+
11 * mistake, or contact the author.
\n+
12 */
\n+
13#ifndef PQXX_H_ROBUSTTRANSACTION
\n+
14#define PQXX_H_ROBUSTTRANSACTION
\n+
15
\n+
16#if !defined(PQXX_HEADER_PRE)
\n+
17# error "Include libpqxx headers as <pqxx/header>, not <pqxx/header.hxx>."
\n+
18#endif
\n+
19
\n+
20#include "pqxx/dbtransaction.hxx"
\n+
21
\n+
22namespace pqxx::internal
\n+
23{
\n+
\n+
25class PQXX_LIBEXPORT PQXX_NOVTABLE basic_robusttransaction
\n+
26 : public dbtransaction
\n+
27{
\n+
28public:
\n+
29 virtual ~basic_robusttransaction() override = 0;
\n+
30
\n+
31protected:
\n+\n+
33 connection &c, zview begin_command, std::string_view tname);
\n+
34 basic_robusttransaction(connection &c, zview begin_command);
\n+
35
\n+
36private:
\n+
37 using IDType = unsigned long;
\n+
38
\n+
39 std::string m_conn_string;
\n+
40 std::string m_xid;
\n+
41 int m_backendpid = -1;
\n+
42
\n+
43 void init(zview begin_command);
\n+
44
\n+
45 // @warning This function will become `final`.
\n+
46 virtual void do_commit() override;
\n+
47};
\n+
\n+
48} // namespace pqxx::internal
\n
49
\n-
50namespace pqxx
\n-
51{
\n-
52using namespace std::literals;
\n-
53
\n-
54
\n-
55class transaction_focus;
\n-
56
\n-
57
\n-
82
\n-
\n-
87class PQXX_LIBEXPORT PQXX_NOVTABLE transaction_base
\n-
88{
\n-
89public:
\n-
90 transaction_base() = delete;
\n-\n-\n-\n-\n-
95
\n-
96 virtual ~transaction_base() = 0;
\n-
97
\n-
99
\n-
112 void commit();
\n-
113
\n+
50
\n+
51namespace pqxx
\n+
52{
\n+
60
\n+
81template<isolation_level ISOLATION = read_committed>
\n+
82class robusttransaction final : public internal::basic_robusttransaction
\n+
83{
\n+
84public:
\n+
89 robusttransaction(connection &c, std::string_view tname) :
\n+\n+
91 c, pqxx::internal::begin_cmd<ISOLATION, write_policy::read_write>,
\n+
92 tname}
\n+
93 {}
\n+
94
\n+
99 robusttransaction(connection &c, std::string &&tname) :
\n+
100 internal::basic_robusttransaction{
\n+
101 c, pqxx::internal::begin_cmd<ISOLATION, write_policy::read_write>,
\n+
102 std::move(tname)}
\n+
103 {}
\n+
104
\n+
108 explicit robusttransaction(connection &c) :
\n+
109 internal::basic_robusttransaction{
\n+
110 c, pqxx::internal::begin_cmd<ISOLATION, write_policy::read_write>}
\n+
111 {}
\n+
112
\n+
113 virtual ~robusttransaction() noexcept override { close(); }
\n+
114};
\n
115
\n-
118 void abort();
\n-
119
\n-
\n-
131 template<typename... ARGS> [[nodiscard]] auto esc(ARGS &&...args) const
\n-
132 {
\n-
133 return conn().esc(std::forward<ARGS>(args)...);
\n-
134 }
\n-
\n-
135
\n-
137
\n-
\n-
148 template<typename... ARGS> [[nodiscard]] auto esc_raw(ARGS &&...args) const
\n-
149 {
\n-
150 return conn().esc_raw(std::forward<ARGS>(args)...);
\n-
151 }
\n-
\n-
152
\n-
154
\n-
157 [[nodiscard, deprecated("Use unesc_bin() instead.")]] std::string
\n-
\n-\n-
159 {
\n-
160#include "pqxx/internal/ignore-deprecated-pre.hxx"
\n-
161 return conn().unesc_raw(text);
\n-
162#include "pqxx/internal/ignore-deprecated-post.hxx"
\n-
163 }
\n-
\n-
164
\n-
166
\n-
\n-
169 [[nodiscard]] std::basic_string<std::byte> unesc_bin(zview text)
\n-
170 {
\n-
171 return conn().unesc_bin(text);
\n-
172 }
\n-
\n-
173
\n-
175
\n-
178 [[nodiscard, deprecated("Use unesc_bin() instead.")]] std::string
\n-
\n-
179 unesc_raw(char const *text) const
\n-
180 {
\n-
181#include "pqxx/internal/ignore-deprecated-pre.hxx"
\n-
182 return conn().unesc_raw(text);
\n-
183#include "pqxx/internal/ignore-deprecated-post.hxx"
\n-
184 }
\n-
\n-
185
\n-
187
\n-
\n-
190 [[nodiscard]] std::basic_string<std::byte> unesc_bin(char const text[])
\n-
191 {
\n-
192 return conn().unesc_bin(text);
\n-
193 }
\n-
\n-
194
\n-
196
\n-
\n-
197 template<typename T> [[nodiscard]] std::string quote(T const &t) const
\n-
198 {
\n-
199 return conn().quote(t);
\n-
200 }
\n-
\n-
201
\n-
202 [[deprecated(
\n-
203 "Use std::basic_string<std::byte> instead of binarystring.")]] std::string
\n-
\n-
204 quote(binarystring const &t) const
\n-
205 {
\n-
206 return conn().quote(t.bytes_view());
\n-
207 }
\n-
\n-
208
\n-
210 [[deprecated("Use quote(std::basic_string_view<std::byte>).")]] std::string
\n-
\n-
211 quote_raw(unsigned char const bin[], std::size_t len) const
\n-
212 {
\n-
213 return quote(binary_cast(bin, len));
\n-
214 }
\n-
\n-
215
\n-
217 [[deprecated("Use quote(std::basic_string_view<std::byte>).")]] std::string
\n-
218 quote_raw(zview bin) const;
\n-
219
\n-
220#if defined(PQXX_HAVE_CONCEPTS)
\n-
222
\n-
223 template<binary DATA>
\n-
224 [[nodiscard]] std::string quote_raw(DATA const &data) const
\n-
225 {
\n-
226 return conn().quote_raw(data);
\n-
227 }
\n-
228#endif
\n-
229
\n-
\n-
231 [[nodiscard]] std::string quote_name(std::string_view identifier) const
\n-
232 {
\n-
233 return conn().quote_name(identifier);
\n-
234 }
\n-
\n-
235
\n-
237 [[nodiscard]] std::string
\n-
\n-
238 esc_like(std::string_view bin, char escape_char = '\\\\') const
\n-
239 {
\n-
240 return conn().esc_like(bin, escape_char);
\n-
241 }
\n-
\n-
243
\n-
285
\n-
287
\n-
292 [[deprecated("The desc parameter is going away.")]] result
\n-
293 exec(std::string_view query, std::string_view desc);
\n-
294
\n-
296
\n-
\n-
300 result exec(std::string_view query)
\n-
301 {
\n-
302#include "pqxx/internal/ignore-deprecated-pre.hxx"
\n-
303 return exec(query, std::string_view{});
\n-
304#include "pqxx/internal/ignore-deprecated-post.hxx"
\n-
305 }
\n-
\n-
306
\n-
308
\n-
313 [[deprecated(
\n-
314 "Pass your query as a std::string_view, not stringstream.")]] result
\n-
\n-
315 exec(std::stringstream const &query, std::string_view desc)
\n-
316 {
\n-
317#include "pqxx/internal/ignore-deprecated-pre.hxx"
\n-
318 return exec(query.str(), desc);
\n-
319#include "pqxx/internal/ignore-deprecated-post.hxx"
\n-
320 }
\n-
\n-
321
\n-
323
\n-
328 [[deprecated("The desc parameter is going away.")]] result
\n-
\n-
329 exec0(zview query, std::string_view desc)
\n-
330 {
\n-
331#include "pqxx/internal/ignore-deprecated-pre.hxx"
\n-
332 return exec_n(0, query, desc);
\n-
333#include "pqxx/internal/ignore-deprecated-post.hxx"
\n-
334 }
\n-
\n-
335
\n-
337
\n-
342 result exec0(zview query) { return exec_n(0, query); }
\n-
343
\n-
345
\n-
351 [[deprecated("The desc parameter is going away.")]] row
\n-
\n-
352 exec1(zview query, std::string_view desc)
\n-
353 {
\n-
354#include "pqxx/internal/ignore-deprecated-pre.hxx"
\n-
355 return exec_n(1, query, desc).front();
\n-
356#include "pqxx/internal/ignore-deprecated-post.hxx"
\n-
357 }
\n-
\n-
358
\n-
360
\n-
366 row exec1(zview query) { return exec_n(1, query).front(); }
\n-
367
\n-
369
\n-
374 [[deprecated("The desc parameter is going away.")]] result
\n-
375 exec_n(result::size_type rows, zview query, std::string_view desc);
\n-
376
\n-
378
\n-
\n-\n-
384 {
\n-
385#include "pqxx/internal/ignore-deprecated-pre.hxx"
\n-
386 return exec_n(rows, query, std::string_view{});
\n-
387#include "pqxx/internal/ignore-deprecated-post.hxx"
\n-
388 }
\n-
\n-
389
\n-
391
\n-
394 template<typename TYPE>
\n-
395 [[deprecated("The desc parameter is going away.")]] TYPE
\n-
\n-
396 query_value(zview query, std::string_view desc)
\n-
397 {
\n-
398#include "pqxx/internal/ignore-deprecated-pre.hxx"
\n-
399 row const r{exec1(query, desc)};
\n-
400#include "pqxx/internal/ignore-deprecated-post.hxx"
\n-
401 if (std::size(r) != 1)
\n-
402 throw usage_error{internal::concat(
\n-
403 "Queried single value from result with ", std::size(r), " columns.")};
\n-
404 return r[0].as<TYPE>();
\n-
405 }
\n-
\n-
406
\n-
408
\n-
\n-
414 template<typename TYPE> TYPE query_value(zview query)
\n-
415 {
\n-
416 row const r{exec1(query)};
\n-
417 if (std::size(r) != 1)
\n-
418 throw usage_error{internal::concat(
\n-
419 "Queried single value from result with ", std::size(r), " columns.")};
\n-
420 return r[0].as<TYPE>();
\n-
421 }
\n-
\n-
422
\n-
424
\n-
431 template<typename... TYPE>
\n-
\n-
432 [[nodiscard]] std::tuple<TYPE...> query1(zview query)
\n-
433 {
\n-
434 return exec1(query).as<TYPE...>();
\n-
435 }
\n-
\n-
436
\n-
438
\n-
445 template<typename... TYPE>
\n-
\n-
446 [[nodiscard]] std::optional<std::tuple<TYPE...>> query01(zview query)
\n-
447 {
\n-
448 result res{exec(query)};
\n-
449 auto const rows{std::size(res)};
\n-
450 switch (rows)
\n-
451 {
\n-
452 case 0: return {};
\n-
453 case 1: return {res[0].as<TYPE...>()};
\n-
454 default:
\n-
455 throw unexpected_rows{internal::concat(
\n-
456 "Expected at most one row of data, got "sv, rows, "."sv)};
\n-
457 }
\n-
458 }
\n-
\n-
459
\n-
461
\n-
505 template<typename... TYPE>
\n-
\n-
506 [[nodiscard]] auto stream(std::string_view query) &
\n-
507 {
\n-
508 return pqxx::internal::stream_query<TYPE...>{*this, query};
\n-
509 }
\n-
\n-
510
\n-
511 // C++20: Concept like std::invocable, but without specifying param types.
\n-
513
\n-
537 template<typename CALLABLE>
\n-
\n-
538 auto for_stream(std::string_view query, CALLABLE &&func)
\n-
539 {
\n-
540 using param_types =
\n-\n-
542 param_types const *const sample{nullptr};
\n-
543 auto data_stream{stream_like(query, sample)};
\n-
544 for (auto const &fields : data_stream) std::apply(func, fields);
\n-
545 }
\n-
\n-
546
\n-
547 template<typename CALLABLE>
\n-
548 [[deprecated(
\n-
549 "pqxx::transaction_base::for_each is now called for_stream.")]] auto
\n-
\n-
550 for_each(std::string_view query, CALLABLE &&func)
\n-
551 {
\n-
552 return for_stream(query, std::forward<CALLABLE>(func));
\n-
553 }
\n-
\n-
554
\n-
556
\n-
\n-
587 template<typename... TYPE> auto query(zview query)
\n-
588 {
\n-
589 return exec(query).iter<TYPE...>();
\n-
590 }
\n-
\n-
591
\n-
593
\n-
\n-
601 template<typename... TYPE> auto query_n(result::size_type rows, zview query)
\n-
602 {
\n-
603 return exec_n(rows, query).iter<TYPE...>();
\n-
604 }
\n-
\n-
605
\n-
606 // C++20: Concept like std::invocable, but without specifying param types.
\n-
608
\n-
\n-
616 template<typename CALLABLE> void for_query(zview query, CALLABLE &&func)
\n-
617 {
\n-
618 exec(query).for_each(std::forward<CALLABLE>(func));
\n-
619 }
\n-
\n-
620
\n-
\n-
651 template<typename... Args> result exec_params(zview query, Args &&...args)
\n-
652 {
\n-
653 params pp(args...);
\n-
654 return internal_exec_params(query, pp.make_c_params());
\n-
655 }
\n-
\n-
656
\n-
657 // Execute parameterised statement, expect a single-row result.
\n-
\n-
660 template<typename... Args> row exec_params1(zview query, Args &&...args)
\n-
661 {
\n-
662 return exec_params_n(1, query, std::forward<Args>(args)...).front();
\n-
663 }
\n-
\n-
664
\n-
665 // Execute parameterised statement, expect a result with zero rows.
\n-
\n-
668 template<typename... Args> result exec_params0(zview query, Args &&...args)
\n-
669 {
\n-
670 return exec_params_n(0, query, std::forward<Args>(args)...);
\n-
671 }
\n-
\n-
672
\n-
673 // Execute parameterised statement, expect exactly a given number of rows.
\n-
676 template<typename... Args>
\n-
\n-
677 result exec_params_n(std::size_t rows, zview query, Args &&...args)
\n-
678 {
\n-
679 auto const r{exec_params(query, std::forward<Args>(args)...)};
\n-
680 check_rowcount_params(rows, std::size(r));
\n-
681 return r;
\n-
682 }
\n-
\n-
684
\n-
727
\n-
729 template<typename... Args>
\n-
\n-
730 result exec_prepared(zview statement, Args &&...args)
\n-
731 {
\n-
732 params pp(args...);
\n-
733 return internal_exec_prepared(statement, pp.make_c_params());
\n-
734 }
\n-
\n-
735
\n-
737
\n-
739 template<typename... Args>
\n-
\n-
740 row exec_prepared1(zview statement, Args &&...args)
\n-
741 {
\n-
742 return exec_prepared_n(1, statement, std::forward<Args>(args)...).front();
\n-
743 }
\n-
\n-
744
\n-
746
\n-
748 template<typename... Args>
\n-
\n-
749 result exec_prepared0(zview statement, Args &&...args)
\n-
750 {
\n-
751 return exec_prepared_n(0, statement, std::forward<Args>(args)...);
\n-
752 }
\n-
\n-
753
\n-
755
\n-
758 template<typename... Args>
\n-
759 result
\n-
\n-
760 exec_prepared_n(result::size_type rows, zview statement, Args &&...args)
\n-
761 {
\n-
762 auto const r{exec_prepared(statement, std::forward<Args>(args)...)};
\n-
763 check_rowcount_prepared(statement, rows, std::size(r));
\n-
764 return r;
\n-
765 }
\n-
\n-
766
\n-
768
\n-
774 void process_notice(char const msg[]) const { m_conn.process_notice(msg); }
\n-
776 void process_notice(zview msg) const { m_conn.process_notice(msg); }
\n-
778
\n-
780 [[nodiscard]] constexpr connection &conn() const noexcept { return m_conn; }
\n-
781
\n-
783
\n-
798 [[deprecated(
\n-
799 "Set transaction-local variables using SQL SET statements.")]] void
\n-
800 set_variable(std::string_view var, std::string_view value);
\n-
801
\n-
803
\n-
806 [[deprecated("Read variables using SQL SHOW statements.")]] std::string
\n-
807 get_variable(std::string_view);
\n-
808
\n-
809 // C++20: constexpr.
\n-
811 [[nodiscard]] std::string_view name() const &noexcept { return m_name; }
\n-
812
\n-
813protected:
\n-
815
\n-
\n-\n-
819 connection &c, std::string_view tname,
\n-
820 std::shared_ptr<std::string> rollback_cmd) :
\n-
821 m_conn{c}, m_name{tname}, m_rollback_cmd{rollback_cmd}
\n-
822 {}
\n-
\n-
823
\n-
825
\n-
830 transaction_base(connection &c, std::string_view tname);
\n-
831
\n-
833 explicit transaction_base(connection &c);
\n-
834
\n-
836 void register_transaction();
\n-
837
\n-
839 void close() noexcept;
\n-
840
\n-
842 virtual void do_commit() = 0;
\n-
843
\n-
845
\n-
848 virtual void do_abort();
\n-
849
\n-
\n-
851 void set_rollback_cmd(std::shared_ptr<std::string> cmd)
\n-
852 {
\n-
853 m_rollback_cmd = cmd;
\n-
854 }
\n-
\n-
855
\n-
857 result direct_exec(std::string_view, std::string_view desc = ""sv);
\n-
858 result
\n-
859 direct_exec(std::shared_ptr<std::string>, std::string_view desc = ""sv);
\n-
860
\n-
861private:
\n-
862 enum class status
\n-
863 {
\n-
864 active,
\n-
865 aborted,
\n-
866 committed,
\n-
867 in_doubt
\n-
868 };
\n-
869
\n-
870 PQXX_PRIVATE void check_pending_error();
\n-
871
\n-
872 result
\n-
873 internal_exec_prepared(zview statement, internal::c_params const &args);
\n-
874
\n-
875 result internal_exec_params(zview query, internal::c_params const &args);
\n-
876
\n-
878 void check_rowcount_prepared(
\n-
879 zview statement, result::size_type expected_rows,
\n-
880 result::size_type actual_rows);
\n-
881
\n-
883 void
\n-
884 check_rowcount_params(std::size_t expected_rows, std::size_t actual_rows);
\n-
885
\n-
887 [[nodiscard]] std::string description() const;
\n-
888
\n-
889 friend class pqxx::internal::gate::transaction_transaction_focus;
\n-
890 PQXX_PRIVATE void register_focus(transaction_focus *);
\n-
891 PQXX_PRIVATE void unregister_focus(transaction_focus *) noexcept;
\n-
892 PQXX_PRIVATE void register_pending_error(zview) noexcept;
\n-
893 PQXX_PRIVATE void register_pending_error(std::string &&) noexcept;
\n-
894
\n-
896 template<typename... ARGS>
\n-
897 auto stream_like(std::string_view query, std::tuple<ARGS...> const *)
\n-
898 {
\n-
899 return stream<ARGS...>(query);
\n-
900 }
\n-
901
\n-
902 connection &m_conn;
\n-
903
\n-
905
\n-
908 transaction_focus const *m_focus = nullptr;
\n-
909
\n-
910 status m_status = status::active;
\n-
911 bool m_registered = false;
\n-
912 std::string m_name;
\n-
913 std::string m_pending_error;
\n-
914
\n-
916 std::shared_ptr<std::string> m_rollback_cmd;
\n-
917
\n-
918 static constexpr std::string_view s_type_name{"transaction"sv};
\n-
919};
\n-
\n-
920
\n-
921
\n-
922// C++20: Can borrowed_range help?
\n-
924template<>
\n-
925std::string_view transaction_base::query_value<std::string_view>(
\n-
926 zview query, std::string_view desc) = delete;
\n-
928template<>
\n-
929zview transaction_base::query_value<zview>(
\n-
930 zview query, std::string_view desc) = delete;
\n-
931
\n-
932} // namespace pqxx
\n-
933
\n-
934
\n-
935namespace pqxx::internal
\n-
936{
\n-
938template<pqxx::isolation_level isolation, pqxx::write_policy rw>
\n-
939extern const zview begin_cmd;
\n-
940
\n-
941// These are not static members, so "constexpr" does not imply "inline".
\n-
942template<>
\n-
943inline constexpr zview begin_cmd<read_committed, write_policy::read_write>{
\n-
944 "BEGIN"_zv};
\n-
945template<>
\n-
946inline constexpr zview begin_cmd<read_committed, write_policy::read_only>{
\n-
947 "BEGIN READ ONLY"_zv};
\n-
948template<>
\n-
949inline constexpr zview begin_cmd<repeatable_read, write_policy::read_write>{
\n-
950 "BEGIN ISOLATION LEVEL REPEATABLE READ"_zv};
\n-
951template<>
\n-
952inline constexpr zview begin_cmd<repeatable_read, write_policy::read_only>{
\n-
953 "BEGIN ISOLATION LEVEL REPEATABLE READ READ ONLY"_zv};
\n-
954template<>
\n-
955inline constexpr zview begin_cmd<serializable, write_policy::read_write>{
\n-
956 "BEGIN ISOLATION LEVEL SERIALIZABLE"_zv};
\n-
957template<>
\n-
958inline constexpr zview begin_cmd<serializable, write_policy::read_only>{
\n-
959 "BEGIN ISOLATION LEVEL SERIALIZABLE READ ONLY"_zv};
\n-
960} // namespace pqxx::internal
\n-
961
\n-
962#include "pqxx/internal/stream_query_impl.hxx"
\n-
963#endif
\n-
auto esc(ARGS &&...args) const
Escape string for use as SQL string literal in this transaction.
Definition transaction_base.hxx:131
\n+
119} // namespace pqxx
\n+
120#endif
\n
The home of all libpqxx classes, functions, templates, etc.
Definition array.hxx:33
\n-
std::basic_string_view< std::byte > binary_cast(TYPE const &data)
Cast binary data to a type that libpqxx will recognise as binary.
Definition util.hxx:303
\n-\n+
write_policy
Should a transaction be read-only, or read-write?
Definition isolation.hxx:27
\n+\n
Internal items for libpqxx' own use. Do not use these yourself.
Definition composite.hxx:84
\n-
decltype(strip_types(std::declval< TYPES... >())) strip_types_t
Take a tuple type and apply strip_t to its component types.
Definition util.hxx:527
\n-
Definition connection.hxx:112
\n-
Binary data corresponding to PostgreSQL's "BYTEA" binary-string type.
Definition binarystring.hxx:59
\n-
std::basic_string_view< std::byte > bytes_view() const
Read data as a std::basic_string_view<std::byte>.
Definition binarystring.hxx:178
\n
Connection to a database.
Definition connection.hxx:253
\n-
Error in usage of libpqxx library, similar to std::logic_error.
Definition except.hxx:249
\n-
Query returned an unexpected number of rows.
Definition except.hxx:343
\n-
Build a parameter list for a parameterised or prepared statement.
Definition params.hxx:220
\n-
pqxx::internal::c_params make_c_params() const
For internal use: Generate a params object for use in calls.
Definition params.cxx:96
\n-
Result set containing data returned by a query or command.
Definition result.hxx:73
\n-
result_size_type size_type
Definition result.hxx:75
\n-
Reference to one row in a result.
Definition row.hxx:47
\n-
reference front() const noexcept
Definition row.cxx:60
\n-
Interface definition (and common code) for "transaction" classes.
Definition transaction_base.hxx:88
\n-
result exec_prepared(zview statement, Args &&...args)
Execute a prepared statement, with optional arguments.
Definition transaction_base.hxx:730
\n-
std::basic_string< std::byte > unesc_bin(zview text)
Unescape binary data, e.g. from a table field or notification payload.
Definition transaction_base.hxx:169
\n-
result exec0(zview query, std::string_view desc)
Execute command, which should return zero rows of data.
Definition transaction_base.hxx:329
\n-
constexpr connection & conn() const noexcept
The connection in which this transaction lives.
Definition transaction_base.hxx:780
\n-
auto for_each(std::string_view query, CALLABLE &&func)
Definition transaction_base.hxx:550
\n-
auto query(zview query)
Execute query, read full results, then iterate rows of data.
Definition transaction_base.hxx:587
\n-
void process_notice(zview msg) const
Have connection process a warning message.
Definition transaction_base.hxx:776
\n-
result exec0(zview query)
Execute command, which should return zero rows of data.
Definition transaction_base.hxx:342
\n-
auto query_n(result::size_type rows, zview query)
Perform query, expect given number of rows, iterate results.
Definition transaction_base.hxx:601
\n-
std::string unesc_raw(char const *text) const
Unescape binary data, e.g. from a table field or notification payload.
Definition transaction_base.hxx:179
\n-
TYPE query_value(zview query, std::string_view desc)
Perform query, expecting exactly 1 row with 1 field, and convert it.
Definition transaction_base.hxx:396
\n-
result exec_prepared_n(result::size_type rows, zview statement, Args &&...args)
Execute a prepared statement, expect a result with given number of rows.
Definition transaction_base.hxx:760
\n-
transaction_base(transaction_base const &)=delete
\n-
transaction_base(connection &c, std::string_view tname, std::shared_ptr< std::string > rollback_cmd)
Create a transaction (to be called by implementation classes only).
Definition transaction_base.hxx:818
\n-
std::string quote(T const &t) const
Represent object as SQL string, including quoting & escaping.
Definition transaction_base.hxx:197
\n-
row exec_params1(zview query, Args &&...args)
Definition transaction_base.hxx:660
\n-
TYPE query_value(zview query)
Perform query, expecting exactly 1 row with 1 field, and convert it.
Definition transaction_base.hxx:414
\n-
transaction_base & operator=(transaction_base const &)=delete
\n-
auto esc_raw(ARGS &&...args) const
Escape binary data for use as SQL string literal in this transaction.
Definition transaction_base.hxx:148
\n-
result exec(std::stringstream const &query, std::string_view desc)
Execute a command.
Definition transaction_base.hxx:315
\n-
std::string quote(binarystring const &t) const
Definition transaction_base.hxx:204
\n-
row exec1(zview query)
Execute command returning a single row of data.
Definition transaction_base.hxx:366
\n-
row exec1(zview query, std::string_view desc)
Execute command returning a single row of data.
Definition transaction_base.hxx:352
\n-
transaction_base(transaction_base &&)=delete
\n-
result exec_params(zview query, Args &&...args)
Execute an SQL statement with parameters.
Definition transaction_base.hxx:651
\n-
std::optional< std::tuple< TYPE... > > query01(zview query)
Query at most one row of data, and if there is one, convert it.
Definition transaction_base.hxx:446
\n-\n-
result exec_params0(zview query, Args &&...args)
Definition transaction_base.hxx:668
\n-
auto for_stream(std::string_view query, CALLABLE &&func)
Perform a streaming query, and for each result row, call func.
Definition transaction_base.hxx:538
\n-
std::string unesc_raw(zview text) const
Unescape binary data, e.g. from a table field or notification payload.
Definition transaction_base.hxx:158
\n-
result exec_prepared0(zview statement, Args &&...args)
Execute a prepared statement, and expect a result with zero rows.
Definition transaction_base.hxx:749
\n-
std::string esc_like(std::string_view bin, char escape_char='\\\\') const
Escape string for literal LIKE match.
Definition transaction_base.hxx:238
\n-
std::basic_string< std::byte > unesc_bin(char const text[])
Unescape binary data, e.g. from a table field or notification payload.
Definition transaction_base.hxx:190
\n-
transaction_base & operator=(transaction_base &&)=delete
\n-
result exec_n(result::size_type rows, zview query)
Execute command, expect given number of rows.
Definition transaction_base.hxx:383
\n-
std::tuple< TYPE... > query1(zview query)
Perform query returning exactly one row, and convert its fields.
Definition transaction_base.hxx:432
\n-
result exec(std::string_view query)
Execute a command.
Definition transaction_base.hxx:300
\n-
row exec_prepared1(zview statement, Args &&...args)
Execute a prepared statement, and expect a single-row result.
Definition transaction_base.hxx:740
\n-
std::string quote_name(std::string_view identifier) const
Escape an SQL identifier for use in a query.
Definition transaction_base.hxx:231
\n-
std::string quote_raw(unsigned char const bin[], std::size_t len) const
Binary-escape and quote a binary string for use as an SQL constant.
Definition transaction_base.hxx:211
\n-
std::string_view name() const &noexcept
Transaction name, if you passed one to the constructor; or empty string.
Definition transaction_base.hxx:811
\n-
result exec_params_n(std::size_t rows, zview query, Args &&...args)
Definition transaction_base.hxx:677
\n-
auto stream(std::string_view query) &
Execute a query, and loop over the results row by row.
Definition transaction_base.hxx:506
\n-
void for_query(zview query, CALLABLE &&func)
Execute a query, load the full result, and perform func for each row.
Definition transaction_base.hxx:616
\n-
void process_notice(char const msg[]) const
Have connection process a warning message.
Definition transaction_base.hxx:774
\n-
Base class for things that monopolise a transaction's attention.
Definition transaction_focus.hxx:29
\n+
Abstract transaction base class: bracket transactions on the database.
Definition dbtransaction.hxx:54
\n+
Helper base class for the robusttransaction class template.
Definition robusttransaction.hxx:27
\n+
virtual ~basic_robusttransaction() override=0
\n+
basic_robusttransaction(connection &c, zview begin_command, std::string_view tname)
Definition robusttransaction.cxx:104
\n+
void close() noexcept
End transaction. To be called by implementing class' destructor.
Definition transaction_base.cxx:343
\n
Marker-type wrapper: zero-terminated std::string_view.
Definition zview.hxx:38
\n
\n
\n \n
\n \n
\n \n \n", "details": [{"source1": "html2text {}", "source2": "html2text {}", "unified_diff": "@@ -1,761 +1,124 @@\n \n \n \n \n \n libpqxx\u00a07.8.1\n \n-transaction_base.hxx\n- 1/* Common code and definitions for the transaction classes.\n+robusttransaction.hxx\n+ 1/* Definition of the pqxx::robusttransaction class.\n 2 *\n- 3 * pqxx::transaction_base defines the interface for any abstract class that\n- 4 * represents a database transaction.\n- 5 *\n- 6 * DO NOT INCLUDE THIS FILE DIRECTLY; include pqxx/transaction_base instead.\n- 7 *\n- 8 * Copyright (c) 2000-2023, Jeroen T. Vermeulen.\n- 9 *\n- 10 * See COPYING for copyright license. If you did not receive a file called\n- 11 * COPYING with this source code, please notify the distributor of this\n- 12 * mistake, or contact the author.\n- 13 */\n- 14#ifndef PQXX_H_TRANSACTION_BASE\n- 15#define PQXX_H_TRANSACTION_BASE\n- 16\n- 17#if !defined(PQXX_HEADER_PRE)\n- 18# error \"Include libpqxx headers as , not .\"\n- 19#endif\n- 20\n- 21#include \n- 22\n- 23/* End-user programs need not include this file, unless they define their\n-own\n- 24 * transaction classes. This is not something the typical program should\n-want\n- 25 * to do.\n- 26 *\n- 27 * However, reading this file is worthwhile because it defines the public\n- 28 * interface for the available transaction classes such as transaction and\n- 29 * nontransaction.\n- 30 */\n- 31\n- 32#include \"pqxx/connection.hxx\"\n- 33#include \"pqxx/internal/concat.hxx\"\n- 34#include \"pqxx/internal/encoding_group.hxx\"\n- 35#include \"pqxx/internal/stream_query.hxx\"\n- 36#include \"pqxx/isolation.hxx\"\n- 37#include \"pqxx/result.hxx\"\n- 38#include \"pqxx/row.hxx\"\n- 39#include \"pqxx/util.hxx\"\n- 40\n- 41namespace pqxx::internal::gate\n- 42{\n- 43class transaction_subtransaction;\n- 44class transaction_sql_cursor;\n- 45class transaction_stream_to;\n- 46class transaction_transaction_focus;\n- 47} // namespace pqxx::internal::gate\n- 48\n+ 3 * pqxx::robusttransaction is a slower but safer transaction class.\n+ 4 *\n+ 5 * DO NOT INCLUDE THIS FILE DIRECTLY; include pqxx/robusttransaction instead.\n+ 6 *\n+ 7 * Copyright (c) 2000-2023, Jeroen T. Vermeulen.\n+ 8 *\n+ 9 * See COPYING for copyright license. If you did not receive a file called\n+ 10 * COPYING with this source code, please notify the distributor of this\n+ 11 * mistake, or contact the author.\n+ 12 */\n+ 13#ifndef PQXX_H_ROBUSTTRANSACTION\n+ 14#define PQXX_H_ROBUSTTRANSACTION\n+ 15\n+ 16#if !defined(PQXX_HEADER_PRE)\n+ 17# error \"Include libpqxx headers as , not .\"\n+ 18#endif\n+ 19\n+ 20#include \"pqxx/dbtransaction.hxx\"\n+ 21\n+ 22namespace pqxx::internal\n+ 23{\n+25class PQXX_LIBEXPORT PQXX_NOVTABLE basic_robusttransaction\n+ 26 : public dbtransaction\n+ 27{\n+ 28public:\n+29 virtual ~basic_robusttransaction() override = 0;\n+ 30\n+ 31protected:\n+ 32 basic_robusttransaction(\n+ 33 connection &c, zview begin_command, std::string_view tname);\n+ 34 basic_robusttransaction(connection &c, zview begin_command);\n+ 35\n+ 36private:\n+ 37 using IDType = unsigned long;\n+ 38\n+ 39 std::string m_conn_string;\n+ 40 std::string m_xid;\n+ 41 int m_backendpid = -1;\n+ 42\n+ 43 void init(zview begin_command);\n+ 44\n+ 45 // @warning This function will become `final`.\n+ 46 virtual void do_commit() override;\n+ 47};\n+ 48} // namespace pqxx::internal\n 49\n- 50namespace pqxx\n- 51{\n- 52using namespace std::literals;\n- 53\n- 54\n- 55class transaction_focus;\n- 56\n- 57\n- 82\n-87class PQXX_LIBEXPORT PQXX_NOVTABLE transaction_base\n- 88{\n- 89public:\n-90 transaction_base() = delete;\n-91 transaction_base(transaction_base const &) = delete;\n-92 transaction_base(transaction_base &&) = delete;\n-93 transaction_base &operator=(transaction_base const &) = delete;\n-94 transaction_base &operator=(transaction_base &&) = delete;\n- 95\n- 96 virtual ~transaction_base() = 0;\n- 97\n- 99\n- 112 void commit();\n- 113\n+ 50\n+ 51namespace pqxx\n+ 52{\n+ 60\n+ 81template\n+ 82class robusttransaction final : public internal::basic_robusttransaction\n+ 83{\n+ 84public:\n+ 89 robusttransaction(connection &c, std::string_view tname) :\n+ 90 internal::basic_robusttransaction{\n+ 91 c, pqxx::internal::begin_cmd,\n+ 92 tname}\n+ 93 {}\n+ 94\n+ 99 robusttransaction(connection &c, std::string &&tname) :\n+ 100 internal::basic_robusttransaction{\n+ 101 c, pqxx::internal::begin_cmd,\n+ 102 std::move(tname)}\n+ 103 {}\n+ 104\n+ 108 explicit robusttransaction(connection &c) :\n+ 109 internal::basic_robusttransaction{\n+ 110 c, pqxx::internal::begin_cmd}\n+ 111 {}\n+ 112\n+ 113 virtual ~robusttransaction() noexcept override { close(); }\n+ 114};\n 115\n- 118 void abort();\n- 119\n-131 template [[nodiscard]] auto esc(ARGS &&...args) const\n- 132 {\n- 133 return conn().esc(std::forward(args)...);\n- 134 }\n- 135\n- 137\n-148 template [[nodiscard]] auto esc_raw(ARGS &&...args) const\n- 149 {\n- 150 return conn().esc_raw(std::forward(args)...);\n- 151 }\n- 152\n- 154\n- 157 [[nodiscard, deprecated(\"Use unesc_bin() instead.\")]] std::string\n-158 unesc_raw(zview text) const\n- 159 {\n- 160#include \"pqxx/internal/ignore-deprecated-pre.hxx\"\n- 161 return conn().unesc_raw(text);\n- 162#include \"pqxx/internal/ignore-deprecated-post.hxx\"\n- 163 }\n- 164\n- 166\n-169 [[nodiscard]] std::basic_string unesc_bin(zview text)\n- 170 {\n- 171 return conn().unesc_bin(text);\n- 172 }\n- 173\n- 175\n- 178 [[nodiscard, deprecated(\"Use unesc_bin() instead.\")]] std::string\n-179 unesc_raw(char const *text) const\n- 180 {\n- 181#include \"pqxx/internal/ignore-deprecated-pre.hxx\"\n- 182 return conn().unesc_raw(text);\n- 183#include \"pqxx/internal/ignore-deprecated-post.hxx\"\n- 184 }\n- 185\n- 187\n-190 [[nodiscard]] std::basic_string unesc_bin(char const text[])\n- 191 {\n- 192 return conn().unesc_bin(text);\n- 193 }\n- 194\n- 196\n-197 template [[nodiscard]] std::string quote(T const &t) const\n- 198 {\n- 199 return conn().quote(t);\n- 200 }\n- 201\n- 202 [[deprecated(\n- 203 \"Use std::basic_string instead of binarystring.\")]] std::string\n-204 quote(binarystring const &t) const\n- 205 {\n- 206 return conn().quote(t.bytes_view());\n- 207 }\n- 208\n- 210 [[deprecated(\"Use quote(std::basic_string_view).\")]] std::\n-string\n-211 quote_raw(unsigned char const bin[], std::size_t len) const\n- 212 {\n- 213 return quote(binary_cast(bin, len));\n- 214 }\n- 215\n- 217 [[deprecated(\"Use quote(std::basic_string_view).\")]] std::\n-string\n- 218 quote_raw(zview bin) const;\n- 219\n- 220#if defined(PQXX_HAVE_CONCEPTS)\n- 222\n- 223 template\n- 224 [[nodiscard]] std::string quote_raw(DATA const &data) const\n- 225 {\n- 226 return conn().quote_raw(data);\n- 227 }\n- 228#endif\n- 229\n-231 [[nodiscard]] std::string quote_name(std::string_view identifier) const\n- 232 {\n- 233 return conn().quote_name(identifier);\n- 234 }\n- 235\n- 237 [[nodiscard]] std::string\n-238 esc_like(std::string_view bin, char escape_char = '\\\\') const\n- 239 {\n- 240 return conn().esc_like(bin, escape_char);\n- 241 }\n- 243\n- 285\n- 287\n- 292 [[deprecated(\"The desc parameter is going away.\")]] result\n- 293 exec(std::string_view query, std::string_view desc);\n- 294\n- 296\n-300 result exec(std::string_view query)\n- 301 {\n- 302#include \"pqxx/internal/ignore-deprecated-pre.hxx\"\n- 303 return exec(query, std::string_view{});\n- 304#include \"pqxx/internal/ignore-deprecated-post.hxx\"\n- 305 }\n- 306\n- 308\n- 313 [[deprecated(\n- 314 \"Pass your query as a std::string_view, not stringstream.\")]] result\n-315 exec(std::stringstream const &query, std::string_view desc)\n- 316 {\n- 317#include \"pqxx/internal/ignore-deprecated-pre.hxx\"\n- 318 return exec(query.str(), desc);\n- 319#include \"pqxx/internal/ignore-deprecated-post.hxx\"\n- 320 }\n- 321\n- 323\n- 328 [[deprecated(\"The desc parameter is going away.\")]] result\n-329 exec0(zview query, std::string_view desc)\n- 330 {\n- 331#include \"pqxx/internal/ignore-deprecated-pre.hxx\"\n- 332 return exec_n(0, query, desc);\n- 333#include \"pqxx/internal/ignore-deprecated-post.hxx\"\n- 334 }\n- 335\n- 337\n-342 result exec0(zview query) { return exec_n(0, query); }\n- 343\n- 345\n- 351 [[deprecated(\"The desc parameter is going away.\")]] row\n-352 exec1(zview query, std::string_view desc)\n- 353 {\n- 354#include \"pqxx/internal/ignore-deprecated-pre.hxx\"\n- 355 return exec_n(1, query, desc).front();\n- 356#include \"pqxx/internal/ignore-deprecated-post.hxx\"\n- 357 }\n- 358\n- 360\n-366 row exec1(zview query) { return exec_n(1, query).front(); }\n- 367\n- 369\n- 374 [[deprecated(\"The desc parameter is going away.\")]] result\n- 375 exec_n(result::size_type rows, zview query, std::string_view desc);\n- 376\n- 378\n-383 result exec_n(result::size_type rows, zview query)\n- 384 {\n- 385#include \"pqxx/internal/ignore-deprecated-pre.hxx\"\n- 386 return exec_n(rows, query, std::string_view{});\n- 387#include \"pqxx/internal/ignore-deprecated-post.hxx\"\n- 388 }\n- 389\n- 391\n- 394 template\n- 395 [[deprecated(\"The desc parameter is going away.\")]] TYPE\n-396 query_value(zview query, std::string_view desc)\n- 397 {\n- 398#include \"pqxx/internal/ignore-deprecated-pre.hxx\"\n- 399 row const r{exec1(query, desc)};\n- 400#include \"pqxx/internal/ignore-deprecated-post.hxx\"\n- 401 if (std::size(r) != 1)\n- 402 throw usage_error{internal::concat(\n- 403 \"Queried single value from result with \", std::size(r), \" columns.\")};\n- 404 return r[0].as();\n- 405 }\n- 406\n- 408\n-414 template TYPE query_value(zview query)\n- 415 {\n- 416 row const r{exec1(query)};\n- 417 if (std::size(r) != 1)\n- 418 throw usage_error{internal::concat(\n- 419 \"Queried single value from result with \", std::size(r), \" columns.\")};\n- 420 return r[0].as();\n- 421 }\n- 422\n- 424\n- 431 template\n-432 [[nodiscard]] std::tuple query1(zview query)\n- 433 {\n- 434 return exec1(query).as();\n- 435 }\n- 436\n- 438\n- 445 template\n-446 [[nodiscard]] std::optional> query01(zview query)\n- 447 {\n- 448 result res{exec(query)};\n- 449 auto const rows{std::size(res)};\n- 450 switch (rows)\n- 451 {\n- 452 case 0: return {};\n- 453 case 1: return {res[0].as()};\n- 454 default:\n- 455 throw unexpected_rows{internal::concat(\n- 456 \"Expected at most one row of data, got \"sv, rows, \".\"sv)};\n- 457 }\n- 458 }\n- 459\n- 461\n- 505 template\n-506 [[nodiscard]] auto stream(std::string_view query) &\n- 507 {\n- 508 return pqxx::internal::stream_query{*this, query};\n- 509 }\n- 510\n- 511 // C++20: Concept like std::invocable, but without specifying param types.\n- 513\n- 537 template\n-538 auto for_stream(std::string_view query, CALLABLE &&func)\n- 539 {\n- 540 using param_types =\n- 541 pqxx::internal::strip_types_t>;\n- 542 param_types const *const sample{nullptr};\n- 543 auto data_stream{stream_like(query, sample)};\n- 544 for (auto const &fields : data_stream) std::apply(func, fields);\n- 545 }\n- 546\n- 547 template\n- 548 [[deprecated(\n- 549 \"pqxx::transaction_base::for_each is now called for_stream.\")]] auto\n-550 for_each(std::string_view query, CALLABLE &&func)\n- 551 {\n- 552 return for_stream(query, std::forward(func));\n- 553 }\n- 554\n- 556\n-587 template auto query(zview query)\n- 588 {\n- 589 return exec(query).iter();\n- 590 }\n- 591\n- 593\n-601 template auto query_n(result::size_type rows, zview\n-query)\n- 602 {\n- 603 return exec_n(rows, query).iter();\n- 604 }\n- 605\n- 606 // C++20: Concept like std::invocable, but without specifying param types.\n- 608\n-616 template void for_query(zview query, CALLABLE &&func)\n- 617 {\n- 618 exec(query).for_each(std::forward(func));\n- 619 }\n- 620\n-651 template result exec_params(zview query, Args &&...args)\n- 652 {\n- 653 params pp(args...);\n- 654 return internal_exec_params(query, pp.make_c_params());\n- 655 }\n- 656\n- 657 // Execute parameterised statement, expect a single-row result.\n-660 template row exec_params1(zview query, Args &&...args)\n- 661 {\n- 662 return exec_params_n(1, query, std::forward(args)...).front();\n- 663 }\n- 664\n- 665 // Execute parameterised statement, expect a result with zero rows.\n-668 template result exec_params0(zview query, Args &&...args)\n- 669 {\n- 670 return exec_params_n(0, query, std::forward(args)...);\n- 671 }\n- 672\n- 673 // Execute parameterised statement, expect exactly a given number of rows.\n- 676 template\n-677 result exec_params_n(std::size_t rows, zview query, Args &&...args)\n- 678 {\n- 679 auto const r{exec_params(query, std::forward(args)...)};\n- 680 check_rowcount_params(rows, std::size(r));\n- 681 return r;\n- 682 }\n- 684\n- 727\n- 729 template\n-730 result exec_prepared(zview statement, Args &&...args)\n- 731 {\n- 732 params pp(args...);\n- 733 return internal_exec_prepared(statement, pp.make_c_params());\n- 734 }\n- 735\n- 737\n- 739 template\n-740 row exec_prepared1(zview statement, Args &&...args)\n- 741 {\n- 742 return exec_prepared_n(1, statement, std::forward(args)...).front();\n- 743 }\n- 744\n- 746\n- 748 template\n-749 result exec_prepared0(zview statement, Args &&...args)\n- 750 {\n- 751 return exec_prepared_n(0, statement, std::forward(args)...);\n- 752 }\n- 753\n- 755\n- 758 template\n- 759 result\n-760 exec_prepared_n(result::size_type rows, zview statement, Args &&...args)\n- 761 {\n- 762 auto const r{exec_prepared(statement, std::forward(args)...)};\n- 763 check_rowcount_prepared(statement, rows, std::size(r));\n- 764 return r;\n- 765 }\n- 766\n- 768\n-774 void process_notice(char const msg[]) const { m_conn.process_notice(msg); }\n-776 void process_notice(zview msg) const { m_conn.process_notice(msg); }\n- 778\n-780 [[nodiscard]] constexpr connection &conn() const noexcept { return m_conn;\n-}\n- 781\n- 783\n- 798 [[deprecated(\n- 799 \"Set transaction-local variables using SQL SET statements.\")]] void\n- 800 set_variable(std::string_view var, std::string_view value);\n- 801\n- 803\n- 806 [[deprecated(\"Read variables using SQL SHOW statements.\")]] std::string\n- 807 get_variable(std::string_view);\n- 808\n- 809 // C++20: constexpr.\n-811 [[nodiscard]] std::string_view name() const &noexcept { return m_name; }\n- 812\n- 813protected:\n- 815\n-818 transaction_base(\n- 819 connection &c, std::string_view tname,\n- 820 std::shared_ptr rollback_cmd) :\n- 821 m_conn{c}, m_name{tname}, m_rollback_cmd{rollback_cmd}\n- 822 {}\n- 823\n- 825\n- 830 transaction_base(connection &c, std::string_view tname);\n- 831\n- 833 explicit transaction_base(connection &c);\n- 834\n- 836 void register_transaction();\n- 837\n- 839 void close() noexcept;\n- 840\n-842 virtual void do_commit() = 0;\n- 843\n- 845\n- 848 virtual void do_abort();\n- 849\n-851 void set_rollback_cmd(std::shared_ptr cmd)\n- 852 {\n- 853 m_rollback_cmd = cmd;\n- 854 }\n- 855\n- 857 result direct_exec(std::string_view, std::string_view desc = \"\"sv);\n- 858 result\n- 859 direct_exec(std::shared_ptr, std::string_view desc = \"\"sv);\n- 860\n- 861private:\n- 862 enum class status\n- 863 {\n- 864 active,\n- 865 aborted,\n- 866 committed,\n- 867 in_doubt\n- 868 };\n- 869\n- 870 PQXX_PRIVATE void check_pending_error();\n- 871\n- 872 result\n- 873 internal_exec_prepared(zview statement, internal::c_params const &args);\n- 874\n- 875 result internal_exec_params(zview query, internal::c_params const &args);\n- 876\n- 878 void check_rowcount_prepared(\n- 879 zview statement, result::size_type expected_rows,\n- 880 result::size_type actual_rows);\n- 881\n- 883 void\n- 884 check_rowcount_params(std::size_t expected_rows, std::size_t actual_rows);\n- 885\n- 887 [[nodiscard]] std::string description() const;\n- 888\n-889 friend class pqxx::internal::gate::transaction_transaction_focus;\n- 890 PQXX_PRIVATE void register_focus(transaction_focus *);\n- 891 PQXX_PRIVATE void unregister_focus(transaction_focus *) noexcept;\n- 892 PQXX_PRIVATE void register_pending_error(zview) noexcept;\n- 893 PQXX_PRIVATE void register_pending_error(std::string &&) noexcept;\n- 894\n- 896 template\n- 897 auto stream_like(std::string_view query, std::tuple const *)\n- 898 {\n- 899 return stream(query);\n- 900 }\n- 901\n- 902 connection &m_conn;\n- 903\n- 905\n- 908 transaction_focus const *m_focus = nullptr;\n- 909\n- 910 status m_status = status::active;\n- 911 bool m_registered = false;\n- 912 std::string m_name;\n- 913 std::string m_pending_error;\n- 914\n- 916 std::shared_ptr m_rollback_cmd;\n- 917\n- 918 static constexpr std::string_view s_type_name{\"transaction\"sv};\n- 919};\n- 920\n- 921\n- 922// C++20: Can borrowed_range help?\n- 924template<>\n-925std::string_view transaction_base::query_value(\n- 926 zview query, std::string_view desc) = delete;\n- 928template<>\n-929zview transaction_base::query_value(\n- 930 zview query, std::string_view desc) = delete;\n- 931\n- 932} // namespace pqxx\n- 933\n- 934\n- 935namespace pqxx::internal\n- 936{\n- 938template\n- 939extern const zview begin_cmd;\n- 940\n- 941// These are not static members, so \"constexpr\" does not imply \"inline\".\n- 942template<>\n- 943inline constexpr zview begin_cmd{\n- 944 \"BEGIN\"_zv};\n- 945template<>\n- 946inline constexpr zview begin_cmd{\n- 947 \"BEGIN READ ONLY\"_zv};\n- 948template<>\n- 949inline constexpr zview begin_cmd\n-{\n- 950 \"BEGIN ISOLATION LEVEL REPEATABLE READ\"_zv};\n- 951template<>\n- 952inline constexpr zview begin_cmd{\n- 953 \"BEGIN ISOLATION LEVEL REPEATABLE READ READ ONLY\"_zv};\n- 954template<>\n- 955inline constexpr zview begin_cmd{\n- 956 \"BEGIN ISOLATION LEVEL SERIALIZABLE\"_zv};\n- 957template<>\n- 958inline constexpr zview begin_cmd{\n- 959 \"BEGIN ISOLATION LEVEL SERIALIZABLE READ ONLY\"_zv};\n- 960} // namespace pqxx::internal\n- 961\n- 962#include \"pqxx/internal/stream_query_impl.hxx\"\n- 963#endif\n-pqxx::transaction_base::esc\n-auto esc(ARGS &&...args) const\n-Escape string for use as SQL string literal in this transaction.\n-Definition transaction_base.hxx:131\n+ 119} // namespace pqxx\n+ 120#endif\n pqxx\n The home of all libpqxx classes, functions, templates, etc.\n Definition array.hxx:33\n-pqxx::binary_cast\n-std::basic_string_view< std::byte > binary_cast(TYPE const &data)\n-Cast binary data to a type that libpqxx will recognise as binary.\n-Definition util.hxx:303\n-pqxx::format::text\n-@ text\n+pqxx::write_policy\n+write_policy\n+Should a transaction be read-only, or read-write?\n+Definition isolation.hxx:27\n+pqxx::write_policy::read_write\n+@ read_write\n pqxx::internal\n Internal items for libpqxx' own use. Do not use these yourself.\n Definition composite.hxx:84\n-pqxx::internal::strip_types_t\n-decltype(strip_types(std::declval< TYPES... >())) strip_types_t\n-Take a tuple type and apply strip_t to its component types.\n-Definition util.hxx:527\n-pqxx::internal::gate\n-Definition connection.hxx:112\n-pqxx::binarystring\n-Binary data corresponding to PostgreSQL's \"BYTEA\" binary-string type.\n-Definition binarystring.hxx:59\n-pqxx::binarystring::bytes_view\n-std::basic_string_view< std::byte > bytes_view() const\n-Read data as a std::basic_string_view.\n-Definition binarystring.hxx:178\n pqxx::connection\n Connection to a database.\n Definition connection.hxx:253\n-pqxx::usage_error\n-Error in usage of libpqxx library, similar to std::logic_error.\n-Definition except.hxx:249\n-pqxx::unexpected_rows\n-Query returned an unexpected number of rows.\n-Definition except.hxx:343\n-pqxx::params\n-Build a parameter list for a parameterised or prepared statement.\n-Definition params.hxx:220\n-pqxx::params::make_c_params\n-pqxx::internal::c_params make_c_params() const\n-For internal use: Generate a params object for use in calls.\n-Definition params.cxx:96\n-pqxx::result\n-Result set containing data returned by a query or command.\n-Definition result.hxx:73\n-pqxx::result::size_type\n-result_size_type size_type\n-Definition result.hxx:75\n-pqxx::row\n-Reference to one row in a result.\n-Definition row.hxx:47\n-pqxx::row::front\n-reference front() const noexcept\n-Definition row.cxx:60\n-pqxx::transaction_base\n-Interface definition (and common code) for \"transaction\" classes.\n-Definition transaction_base.hxx:88\n-pqxx::transaction_base::exec_prepared\n-result exec_prepared(zview statement, Args &&...args)\n-Execute a prepared statement, with optional arguments.\n-Definition transaction_base.hxx:730\n-pqxx::transaction_base::unesc_bin\n-std::basic_string< std::byte > unesc_bin(zview text)\n-Unescape binary data, e.g. from a table field or notification payload.\n-Definition transaction_base.hxx:169\n-pqxx::transaction_base::exec0\n-result exec0(zview query, std::string_view desc)\n-Execute command, which should return zero rows of data.\n-Definition transaction_base.hxx:329\n-pqxx::transaction_base::conn\n-constexpr connection & conn() const noexcept\n-The connection in which this transaction lives.\n-Definition transaction_base.hxx:780\n-pqxx::transaction_base::for_each\n-auto for_each(std::string_view query, CALLABLE &&func)\n-Definition transaction_base.hxx:550\n-pqxx::transaction_base::query\n-auto query(zview query)\n-Execute query, read full results, then iterate rows of data.\n-Definition transaction_base.hxx:587\n-pqxx::transaction_base::process_notice\n-void process_notice(zview msg) const\n-Have connection process a warning message.\n-Definition transaction_base.hxx:776\n-pqxx::transaction_base::exec0\n-result exec0(zview query)\n-Execute command, which should return zero rows of data.\n-Definition transaction_base.hxx:342\n-pqxx::transaction_base::query_n\n-auto query_n(result::size_type rows, zview query)\n-Perform query, expect given number of rows, iterate results.\n-Definition transaction_base.hxx:601\n-pqxx::transaction_base::unesc_raw\n-std::string unesc_raw(char const *text) const\n-Unescape binary data, e.g. from a table field or notification payload.\n-Definition transaction_base.hxx:179\n-pqxx::transaction_base::query_value\n-TYPE query_value(zview query, std::string_view desc)\n-Perform query, expecting exactly 1 row with 1 field, and convert it.\n-Definition transaction_base.hxx:396\n-pqxx::transaction_base::exec_prepared_n\n-result exec_prepared_n(result::size_type rows, zview statement, Args &&...args)\n-Execute a prepared statement, expect a result with given number of rows.\n-Definition transaction_base.hxx:760\n-pqxx::transaction_base::transaction_base\n-transaction_base(transaction_base const &)=delete\n-pqxx::transaction_base::transaction_base\n-transaction_base(connection &c, std::string_view tname, std::shared_ptr< std::\n-string > rollback_cmd)\n-Create a transaction (to be called by implementation classes only).\n-Definition transaction_base.hxx:818\n-pqxx::transaction_base::quote\n-std::string quote(T const &t) const\n-Represent object as SQL string, including quoting & escaping.\n-Definition transaction_base.hxx:197\n-pqxx::transaction_base::exec_params1\n-row exec_params1(zview query, Args &&...args)\n-Definition transaction_base.hxx:660\n-pqxx::transaction_base::query_value\n-TYPE query_value(zview query)\n-Perform query, expecting exactly 1 row with 1 field, and convert it.\n-Definition transaction_base.hxx:414\n-pqxx::transaction_base::operator=\n-transaction_base & operator=(transaction_base const &)=delete\n-pqxx::transaction_base::esc_raw\n-auto esc_raw(ARGS &&...args) const\n-Escape binary data for use as SQL string literal in this transaction.\n-Definition transaction_base.hxx:148\n-pqxx::transaction_base::exec\n-result exec(std::stringstream const &query, std::string_view desc)\n-Execute a command.\n-Definition transaction_base.hxx:315\n-pqxx::transaction_base::quote\n-std::string quote(binarystring const &t) const\n-Definition transaction_base.hxx:204\n-pqxx::transaction_base::exec1\n-row exec1(zview query)\n-Execute command returning a single row of data.\n-Definition transaction_base.hxx:366\n-pqxx::transaction_base::exec1\n-row exec1(zview query, std::string_view desc)\n-Execute command returning a single row of data.\n-Definition transaction_base.hxx:352\n-pqxx::transaction_base::transaction_base\n-transaction_base(transaction_base &&)=delete\n-pqxx::transaction_base::exec_params\n-result exec_params(zview query, Args &&...args)\n-Execute an SQL statement with parameters.\n-Definition transaction_base.hxx:651\n-pqxx::transaction_base::query01\n-std::optional< std::tuple< TYPE... > > query01(zview query)\n-Query at most one row of data, and if there is one, convert it.\n-Definition transaction_base.hxx:446\n-pqxx::transaction_base::transaction_base\n-transaction_base()=delete\n-pqxx::transaction_base::exec_params0\n-result exec_params0(zview query, Args &&...args)\n-Definition transaction_base.hxx:668\n-pqxx::transaction_base::for_stream\n-auto for_stream(std::string_view query, CALLABLE &&func)\n-Perform a streaming query, and for each result row, call func.\n-Definition transaction_base.hxx:538\n-pqxx::transaction_base::unesc_raw\n-std::string unesc_raw(zview text) const\n-Unescape binary data, e.g. from a table field or notification payload.\n-Definition transaction_base.hxx:158\n-pqxx::transaction_base::exec_prepared0\n-result exec_prepared0(zview statement, Args &&...args)\n-Execute a prepared statement, and expect a result with zero rows.\n-Definition transaction_base.hxx:749\n-pqxx::transaction_base::esc_like\n-std::string esc_like(std::string_view bin, char escape_char='\\\\') const\n-Escape string for literal LIKE match.\n-Definition transaction_base.hxx:238\n-pqxx::transaction_base::unesc_bin\n-std::basic_string< std::byte > unesc_bin(char const text[])\n-Unescape binary data, e.g. from a table field or notification payload.\n-Definition transaction_base.hxx:190\n-pqxx::transaction_base::operator=\n-transaction_base & operator=(transaction_base &&)=delete\n-pqxx::transaction_base::exec_n\n-result exec_n(result::size_type rows, zview query)\n-Execute command, expect given number of rows.\n-Definition transaction_base.hxx:383\n-pqxx::transaction_base::query1\n-std::tuple< TYPE... > query1(zview query)\n-Perform query returning exactly one row, and convert its fields.\n-Definition transaction_base.hxx:432\n-pqxx::transaction_base::exec\n-result exec(std::string_view query)\n-Execute a command.\n-Definition transaction_base.hxx:300\n-pqxx::transaction_base::exec_prepared1\n-row exec_prepared1(zview statement, Args &&...args)\n-Execute a prepared statement, and expect a single-row result.\n-Definition transaction_base.hxx:740\n-pqxx::transaction_base::quote_name\n-std::string quote_name(std::string_view identifier) const\n-Escape an SQL identifier for use in a query.\n-Definition transaction_base.hxx:231\n-pqxx::transaction_base::quote_raw\n-std::string quote_raw(unsigned char const bin[], std::size_t len) const\n-Binary-escape and quote a binary string for use as an SQL constant.\n-Definition transaction_base.hxx:211\n-pqxx::transaction_base::name\n-std::string_view name() const &noexcept\n-Transaction name, if you passed one to the constructor; or empty string.\n-Definition transaction_base.hxx:811\n-pqxx::transaction_base::exec_params_n\n-result exec_params_n(std::size_t rows, zview query, Args &&...args)\n-Definition transaction_base.hxx:677\n-pqxx::transaction_base::stream\n-auto stream(std::string_view query) &\n-Execute a query, and loop over the results row by row.\n-Definition transaction_base.hxx:506\n-pqxx::transaction_base::for_query\n-void for_query(zview query, CALLABLE &&func)\n-Execute a query, load the full result, and perform func for each row.\n-Definition transaction_base.hxx:616\n-pqxx::transaction_base::process_notice\n-void process_notice(char const msg[]) const\n-Have connection process a warning message.\n-Definition transaction_base.hxx:774\n-pqxx::transaction_focus\n-Base class for things that monopolise a transaction's attention.\n-Definition transaction_focus.hxx:29\n+pqxx::dbtransaction\n+Abstract transaction base class: bracket transactions on the database.\n+Definition dbtransaction.hxx:54\n+pqxx::internal::basic_robusttransaction\n+Helper base class for the robusttransaction class template.\n+Definition robusttransaction.hxx:27\n+pqxx::internal::basic_robusttransaction::~basic_robusttransaction\n+virtual ~basic_robusttransaction() override=0\n+pqxx::internal::basic_robusttransaction::basic_robusttransaction\n+basic_robusttransaction(connection &c, zview begin_command, std::string_view\n+tname)\n+Definition robusttransaction.cxx:104\n+pqxx::transaction_base::close\n+void close() noexcept\n+End transaction. To be called by implementing class' destructor.\n+Definition transaction_base.cxx:343\n pqxx::zview\n Marker-type wrapper: zero-terminated std::string_view.\n Definition zview.hxx:38\n * include\n * pqxx\n- * transaction_base.hxx\n+ * robusttransaction.hxx\n * Generated by [doxygen] 1.9.8\n"}]}, {"source1": "./usr/share/doc/libpqxx-doc/html/a00071_source.html", "source2": "./usr/share/doc/libpqxx-doc/html/a00071_source.html", "unified_diff": "@@ -1,15 +1,15 @@\n \n \n \n \n \n \n \n-libpqxx: largeobject.hxx Source File\n+libpqxx: config-internal-autotools.h Source File\n \n \n \n \n \n \n \n@@ -60,664 +60,30 @@\n \n
\n
\n-
largeobject.hxx
\n+
config-internal-autotools.h
\n
\n
\n-
1/* Large Objects interface. Deprecated; use blob instead.
\n-
2 *
\n-
3 * DO NOT INCLUDE THIS FILE DIRECTLY; include pqxx/largeobject instead.
\n-
4 *
\n-
5 * Copyright (c) 2000-2023, Jeroen T. Vermeulen.
\n-
6 *
\n-
7 * See COPYING for copyright license. If you did not receive a file called
\n-
8 * COPYING with this source code, please notify the distributor of this
\n-
9 * mistake, or contact the author.
\n-
10 */
\n-
11#ifndef PQXX_H_LARGEOBJECT
\n-
12#define PQXX_H_LARGEOBJECT
\n-
13
\n-
14#if !defined(PQXX_HEADER_PRE)
\n-
15# error "Include libpqxx headers as <pqxx/header>, not <pqxx/header.hxx>."
\n-
16#endif
\n-
17
\n-
18#include <streambuf>
\n-
19
\n-
20#include "pqxx/dbtransaction.hxx"
\n-
21
\n-
22
\n-
23namespace pqxx
\n-
24{
\n-
26
\n-
\n-
33class PQXX_LIBEXPORT largeobject
\n-
34{
\n-
35public:
\n-\n-
37
\n-
40 [[deprecated("Use blob instead.")]] largeobject() noexcept = default;
\n-
41
\n-
43
\n-
45 [[deprecated("Use blob instead.")]] explicit largeobject(dbtransaction &t);
\n-
46
\n-
48
\n-
\n-
52 [[deprecated("Use blob instead.")]] explicit largeobject(oid o) noexcept :
\n-
53 m_id{o}
\n-
54 {}
\n-
\n-
55
\n-
57
\n-
61 [[deprecated("Use blob instead.")]] largeobject(
\n-
62 dbtransaction &t, std::string_view file);
\n-
63
\n-
65
\n-
69 [[deprecated("Use blob instead.")]] largeobject(
\n-
70 largeobjectaccess const &o) noexcept;
\n-
71
\n-
73
\n-
77 [[nodiscard]] oid id() const noexcept { return m_id; }
\n-
78
\n-
88
\n-
\n-
89 [[nodiscard]] bool operator==(largeobject const &other) const
\n-
90 {
\n-
91 return m_id == other.m_id;
\n-
92 }
\n-
\n-
94
\n-
\n-
95 [[nodiscard]] bool operator!=(largeobject const &other) const
\n-
96 {
\n-
97 return m_id != other.m_id;
\n-
98 }
\n-
\n-
100
\n-
\n-
101 [[nodiscard]] bool operator<=(largeobject const &other) const
\n-
102 {
\n-
103 return m_id <= other.m_id;
\n-
104 }
\n-
\n-
106
\n-
\n-
107 [[nodiscard]] bool operator>=(largeobject const &other) const
\n-
108 {
\n-
109 return m_id >= other.m_id;
\n-
110 }
\n-
\n-
112
\n-
\n-
113 [[nodiscard]] bool operator<(largeobject const &other) const
\n-
114 {
\n-
115 return m_id < other.m_id;
\n-
116 }
\n-
\n-
118
\n-
\n-
119 [[nodiscard]] bool operator>(largeobject const &other) const
\n-
120 {
\n-
121 return m_id > other.m_id;
\n-
122 }
\n-
\n-
124
\n-
126
\n-
130 void to_file(dbtransaction &t, std::string_view file) const;
\n-
131
\n-
133
\n-
137 void remove(dbtransaction &t) const;
\n-
138
\n-
139protected:
\n-
140 PQXX_PURE static internal::pq::PGconn *
\n-
141 raw_connection(dbtransaction const &T);
\n-
142
\n-
143 PQXX_PRIVATE std::string reason(connection const &, int err) const;
\n-
144
\n-
145private:
\n-
146 oid m_id = oid_none;
\n-
147};
\n-
\n-
148
\n-
149
\n-
151
\n-
\n-
153class PQXX_LIBEXPORT largeobjectaccess : private largeobject
\n-
154{
\n-
155public:
\n-\n-\n-\n-
159
\n-
161
\n-
168 using openmode = std::ios::openmode;
\n-
169
\n-
\n-
171 static constexpr auto default_mode{
\n-
172 std::ios::in | std::ios::out | std::ios::binary};
\n-
\n-
173
\n-
175 using seekdir = std::ios::seekdir;
\n-
176
\n-
178
\n-
183 [[deprecated("Use blob instead.")]] explicit largeobjectaccess(
\n-
184 dbtransaction &t, openmode mode = default_mode);
\n-
185
\n-
187
\n-
194 [[deprecated("Use blob instead.")]] largeobjectaccess(
\n-
195 dbtransaction &t, oid o, openmode mode = default_mode);
\n-
196
\n-
198
\n-
204 [[deprecated("Use blob instead.")]] largeobjectaccess(
\n-
205 dbtransaction &t, largeobject o, openmode mode = default_mode);
\n-
206
\n-
208
\n-
213 [[deprecated("Use blob instead.")]] largeobjectaccess(
\n-
214 dbtransaction &t, std::string_view file, openmode mode = default_mode);
\n-
215
\n-
216 ~largeobjectaccess() noexcept { close(); }
\n-
217
\n-
219
\n-
222 using largeobject::id;
\n-
223
\n-
225
\n-
\n-
228 void to_file(std::string_view file) const
\n-
229 {
\n-
230 largeobject::to_file(m_trans, file);
\n-
231 }
\n-
\n-
232
\n-\n-
234
\n-
240
\n-
245 void write(char const buf[], std::size_t len);
\n-
246
\n-
248
\n-
251 void write(std::string_view buf) { write(std::data(buf), std::size(buf)); }
\n-
252
\n-
254
\n-
260 size_type read(char buf[], std::size_t len);
\n-
261
\n-
263
\n-
266 size_type seek(size_type dest, seekdir dir);
\n-
267
\n-
269
\n-
272 [[nodiscard]] size_type tell() const;
\n-
274
\n-
288
\n-
296 pos_type cseek(off_type dest, seekdir dir) noexcept;
\n-
297
\n-
299
\n-
305 off_type cwrite(char const buf[], std::size_t len) noexcept;
\n-
306
\n-
308
\n-
314 off_type cread(char buf[], std::size_t len) noexcept;
\n-
315
\n-
317
\n-
321 [[nodiscard]] pos_type ctell() const noexcept;
\n-
323
\n-
329 void process_notice(zview) noexcept;
\n-
331
\n-
332 using largeobject::remove;
\n-
333
\n-
334 using largeobject::operator==;
\n-
335 using largeobject::operator!=;
\n-
336 using largeobject::operator<;
\n-
337 using largeobject::operator<=;
\n-
338 using largeobject::operator>;
\n-
339 using largeobject::operator>=;
\n-
340
\n-\n-\n-
343 largeobjectaccess operator=(largeobjectaccess const &) = delete;
\n-
344
\n-
345private:
\n-
346 PQXX_PRIVATE std::string reason(int err) const;
\n-
347 internal::pq::PGconn *raw_connection() const
\n-
348 {
\n-
349 return largeobject::raw_connection(m_trans);
\n-
350 }
\n-
351
\n-
352 PQXX_PRIVATE void open(openmode mode);
\n-
353 void close() noexcept;
\n-
354
\n-
355 dbtransaction &m_trans;
\n-
356 int m_fd = -1;
\n-
357};
\n-
\n-
358
\n-
359
\n-
361
\n-
372template<typename CHAR = char, typename TRAITS = std::char_traits<CHAR>>
\n-
\n-
373class largeobject_streambuf : public std::basic_streambuf<CHAR, TRAITS>
\n-
374{
\n-
375 using size_type = largeobject::size_type;
\n-
376
\n-
377public:
\n-
378 using char_type = CHAR;
\n-
379 using traits_type = TRAITS;
\n-
380 using int_type = typename traits_type::int_type;
\n-
381 using pos_type = typename traits_type::pos_type;
\n-
382 using off_type = typename traits_type::off_type;
\n-\n-\n-
385
\n-
\n-
387 static constexpr auto default_mode{
\n-
388 std::ios::in | std::ios::out | std::ios::binary};
\n-
\n-
389
\n-
390#include "pqxx/internal/ignore-deprecated-pre.hxx"
\n-
\n-
391 [[deprecated("Use blob instead.")]] largeobject_streambuf(
\n-
392 dbtransaction &t, largeobject o, openmode mode = default_mode,
\n-
393 size_type buf_size = 512) :
\n-
394 m_bufsize{buf_size}, m_obj{t, o, mode}, m_g{nullptr}, m_p{nullptr}
\n-
395 {
\n-
396 initialize(mode);
\n-
397 }
\n-
\n-
398#include "pqxx/internal/ignore-deprecated-post.hxx"
\n-
399
\n-
\n-
400 [[deprecated("Use blob instead.")]] largeobject_streambuf(
\n-
401 dbtransaction &t, oid o, openmode mode = default_mode,
\n-
402 size_type buf_size = 512) :
\n-
403 m_bufsize{buf_size}, m_obj{t, o, mode}, m_g{nullptr}, m_p{nullptr}
\n-
404 {
\n-
405 initialize(mode);
\n-
406 }
\n-
\n-
407
\n-
\n-
408 virtual ~largeobject_streambuf() noexcept
\n-
409 {
\n-
410 delete[] m_p;
\n-
411 delete[] m_g;
\n-
412 }
\n-
\n-
413
\n-
415 void process_notice(zview const &s) { m_obj.process_notice(s); }
\n-
416
\n-
417protected:
\n-
\n-
418 virtual int sync() override
\n-
419 {
\n-
420 // setg() sets eback, gptr, egptr.
\n-
421 this->setg(this->eback(), this->eback(), this->egptr());
\n-
422 return overflow(eof());
\n-
423 }
\n-
\n-
424
\n-
\n-
425 virtual pos_type seekoff(off_type offset, seekdir dir, openmode) override
\n-
426 {
\n-
427 return adjust_eof(m_obj.cseek(largeobjectaccess::off_type(offset), dir));
\n-
428 }
\n-
\n-
429
\n-
\n-
430 virtual pos_type seekpos(pos_type pos, openmode) override
\n-
431 {
\n-
432 largeobjectaccess::pos_type const newpos{
\n-
433 m_obj.cseek(largeobjectaccess::off_type(pos), std::ios::beg)};
\n-
434 return adjust_eof(newpos);
\n-
435 }
\n-
\n-
436
\n-
\n-
437 virtual int_type overflow(int_type ch) override
\n-
438 {
\n-
439 auto *const pp{this->pptr()};
\n-
440 if (pp == nullptr)
\n-
441 return eof();
\n-
442 auto *const pb{this->pbase()};
\n-
443 int_type res{0};
\n-
444
\n-
445 if (pp > pb)
\n-
446 {
\n-
447 auto const write_sz{pp - pb};
\n-
448 auto const written_sz{
\n-
449 m_obj.cwrite(pb, static_cast<std::size_t>(pp - pb))};
\n-
450 if (internal::cmp_less_equal(written_sz, 0))
\n-
451 throw internal_error{
\n-
452 "pqxx::largeobject: write failed "
\n-
453 "(is transaction still valid on write or flush?), "
\n-
454 "libpq reports error"};
\n-
455 else if (write_sz != written_sz)
\n-
456 throw internal_error{
\n-
457 "pqxx::largeobject: write failed "
\n-
458 "(is transaction still valid on write or flush?), " +
\n-
459 std::to_string(written_sz) + "/" + std::to_string(write_sz) +
\n-
460 " bytes written"};
\n-
461 auto const out{adjust_eof(written_sz)};
\n-
462
\n-
463 if constexpr (std::is_arithmetic_v<decltype(out)>)
\n-
464 res = check_cast<int_type>(out, "largeobject position"sv);
\n-
465 else
\n-
466 res = int_type(out);
\n-
467 }
\n-
468 this->setp(m_p, m_p + m_bufsize);
\n-
469
\n-
470 // Write that one more character, if it's there.
\n-
471 if (ch != eof())
\n-
472 {
\n-
473 *this->pptr() = static_cast<char_type>(ch);
\n-
474 this->pbump(1);
\n-
475 }
\n-
476 return res;
\n-
477 }
\n-
\n-
478
\n-
479 virtual int_type overflow() { return overflow(eof()); }
\n-
480
\n-
\n-
481 virtual int_type underflow() override
\n-
482 {
\n-
483 if (this->gptr() == nullptr)
\n-
484 return eof();
\n-
485 auto *const eb{this->eback()};
\n-
486 auto const res{adjust_eof(
\n-
487 m_obj.cread(this->eback(), static_cast<std::size_t>(m_bufsize)))};
\n-
488 this->setg(
\n-
489 eb, eb, eb + (res == eof() ? 0 : static_cast<std::size_t>(res)));
\n-
490 return (res == eof() or res == 0) ? eof() : traits_type::to_int_type(*eb);
\n-
491 }
\n-
\n-
492
\n-
493private:
\n-
495 static int_type eof() { return traits_type::eof(); }
\n-
496
\n-
498 template<typename INTYPE> static std::streampos adjust_eof(INTYPE pos)
\n-
499 {
\n-
500 bool const at_eof{pos == -1};
\n-
501 if constexpr (std::is_arithmetic_v<std::streampos>)
\n-
502 {
\n-
503 return check_cast<std::streampos>(
\n-
504 (at_eof ? eof() : pos), "large object seek"sv);
\n-
505 }
\n-
506 else
\n-
507 {
\n-
508 return std::streampos(at_eof ? eof() : pos);
\n-
509 }
\n-
510 }
\n-
511
\n-
512 void initialize(openmode mode)
\n-
513 {
\n-
514 if ((mode & std::ios::in) != 0)
\n-
515 {
\n-
516 m_g = new char_type[unsigned(m_bufsize)];
\n-
517 this->setg(m_g, m_g, m_g);
\n-
518 }
\n-
519 if ((mode & std::ios::out) != 0)
\n-
520 {
\n-
521 m_p = new char_type[unsigned(m_bufsize)];
\n-
522 this->setp(m_p, m_p + m_bufsize);
\n-
523 }
\n-
524 }
\n-
525
\n-
526 size_type const m_bufsize;
\n-
527 largeobjectaccess m_obj;
\n-
528
\n-
530 char_type *m_g, *m_p;
\n-
531};
\n-
\n-
532
\n-
533
\n-
535
\n-
544template<typename CHAR = char, typename TRAITS = std::char_traits<CHAR>>
\n-
\n-
545class basic_ilostream : public std::basic_istream<CHAR, TRAITS>
\n-
546{
\n-
547 using super = std::basic_istream<CHAR, TRAITS>;
\n-
548
\n-
549public:
\n-
550 using char_type = CHAR;
\n-
551 using traits_type = TRAITS;
\n-
552 using int_type = typename traits_type::int_type;
\n-
553 using pos_type = typename traits_type::pos_type;
\n-
554 using off_type = typename traits_type::off_type;
\n-
555
\n-
556#include "pqxx/internal/ignore-deprecated-pre.hxx"
\n-
558
\n-
\n-
563 [[deprecated("Use blob instead.")]] basic_ilostream(
\n-
564 dbtransaction &t, largeobject o, largeobject::size_type buf_size = 512) :
\n-
565 super{nullptr},
\n-
566 m_buf{t, o, std::ios::in | std::ios::binary, buf_size}
\n-
567 {
\n-
568 super::init(&m_buf);
\n-
569 }
\n-
\n-
570#include "pqxx/internal/ignore-deprecated-post.hxx"
\n-
571
\n-
573
\n-
\n-
578 [[deprecated("Use blob instead.")]] basic_ilostream(
\n-
579 dbtransaction &t, oid o, largeobject::size_type buf_size = 512) :
\n-
580 super{nullptr},
\n-
581 m_buf{t, o, std::ios::in | std::ios::binary, buf_size}
\n-
582 {
\n-
583 super::init(&m_buf);
\n-
584 }
\n-
\n-
585
\n-
586private:
\n-\n-
588};
\n-
\n-
589
\n-\n-
591
\n-
592
\n-
594
\n-
602template<typename CHAR = char, typename TRAITS = std::char_traits<CHAR>>
\n-
\n-
603class basic_olostream : public std::basic_ostream<CHAR, TRAITS>
\n-
604{
\n-
605 using super = std::basic_ostream<CHAR, TRAITS>;
\n-
606
\n-
607public:
\n-
608 using char_type = CHAR;
\n-
609 using traits_type = TRAITS;
\n-
610 using int_type = typename traits_type::int_type;
\n-
611 using pos_type = typename traits_type::pos_type;
\n-
612 using off_type = typename traits_type::off_type;
\n-
613
\n-
614#include "pqxx/internal/ignore-deprecated-pre.hxx"
\n-
616
\n-
\n-
621 [[deprecated("Use blob instead.")]] basic_olostream(
\n-
622 dbtransaction &t, largeobject o, largeobject::size_type buf_size = 512) :
\n-
623 super{nullptr},
\n-
624 m_buf{t, o, std::ios::out | std::ios::binary, buf_size}
\n-
625 {
\n-
626 super::init(&m_buf);
\n-
627 }
\n-
\n-
628#include "pqxx/internal/ignore-deprecated-post.hxx"
\n-
629
\n-
631
\n-
\n-
636 [[deprecated("Use blob instead.")]] basic_olostream(
\n-
637 dbtransaction &t, oid o, largeobject::size_type buf_size = 512) :
\n-
638 super{nullptr},
\n-
639 m_buf{t, o, std::ios::out | std::ios::binary, buf_size}
\n-
640 {
\n-
641 super::init(&m_buf);
\n-
642 }
\n-
\n-
643
\n-
\n-\n-
645 {
\n-
646 try
\n-
647 {
\n-
648 m_buf.pubsync();
\n-
649 m_buf.pubsync();
\n-
650 }
\n-
651 catch (std::exception const &e)
\n-
652 {
\n-
653 m_buf.process_notice(e.what());
\n-
654 }
\n-
655 }
\n-
\n-
656
\n-
657private:
\n-\n-
659};
\n-
\n-
660
\n-\n-
662
\n-
663
\n-
665
\n-
674template<typename CHAR = char, typename TRAITS = std::char_traits<CHAR>>
\n-
\n-
675class basic_lostream : public std::basic_iostream<CHAR, TRAITS>
\n-
676{
\n-
677 using super = std::basic_iostream<CHAR, TRAITS>;
\n-
678
\n-
679public:
\n-
680 using char_type = CHAR;
\n-
681 using traits_type = TRAITS;
\n-
682 using int_type = typename traits_type::int_type;
\n-
683 using pos_type = typename traits_type::pos_type;
\n-
684 using off_type = typename traits_type::off_type;
\n-
685
\n-
687
\n-
\n-
692 [[deprecated("Use blob instead.")]] basic_lostream(
\n-
693 dbtransaction &t, largeobject o, largeobject::size_type buf_size = 512) :
\n-
694 super{nullptr},
\n-
695 m_buf{
\n-
696 t, o, std::ios::in | std::ios::out | std::ios::binary, buf_size}
\n-
697 {
\n-
698 super::init(&m_buf);
\n-
699 }
\n-
\n-
700
\n-
702
\n-
\n-
707 [[deprecated("Use blob instead.")]] basic_lostream(
\n-
708 dbtransaction &t, oid o, largeobject::size_type buf_size = 512) :
\n-
709 super{nullptr},
\n-
710 m_buf{
\n-
711 t, o, std::ios::in | std::ios::out | std::ios::binary, buf_size}
\n-
712 {
\n-
713 super::init(&m_buf);
\n-
714 }
\n-
\n-
715
\n-
\n-\n-
717 {
\n-
718 try
\n-
719 {
\n-
720 m_buf.pubsync();
\n-
721 m_buf.pubsync();
\n-
722 }
\n-
723 catch (std::exception const &e)
\n-
724 {
\n-
725 m_buf.process_notice(e.what());
\n-
726 }
\n-
727 }
\n-
\n-
728
\n-
729private:
\n-\n-
731};
\n-
\n-
732
\n-\n-
734} // namespace pqxx
\n-
735#endif
\n-
The home of all libpqxx classes, functions, templates, etc.
Definition array.hxx:33
\n-
constexpr oid oid_none
The "null" oid.
Definition util.hxx:342
\n-
int64_t large_object_size_type
Number of bytes in a large object.
Definition types.hxx:43
\n-\n-
constexpr bool cmp_less_equal(LEFT lhs, RIGHT rhs) noexcept
C++20 std::cmp_less_equal, or workaround if not available.
Definition util.hxx:98
\n-
Definition blob.hxx:53
\n-
Connection to a database.
Definition connection.hxx:253
\n-
Abstract transaction base class: bracket transactions on the database.
Definition dbtransaction.hxx:54
\n-
Internal error in libpqxx library.
Definition except.hxx:242
\n-
Identity of a large object.
Definition largeobject.hxx:34
\n-
bool operator==(largeobject const &other) const
Compare object identities.
Definition largeobject.hxx:89
\n-
bool operator>=(largeobject const &other) const
Compare object identities.
Definition largeobject.hxx:107
\n-
static PQXX_PURE internal::pq::PGconn * raw_connection(dbtransaction const &T)
Definition largeobject.cxx:139
\n-
bool operator<=(largeobject const &other) const
Compare object identities.
Definition largeobject.hxx:101
\n-
large_object_size_type size_type
Definition largeobject.hxx:36
\n-
bool operator<(largeobject const &other) const
Compare object identities.
Definition largeobject.hxx:113
\n-
largeobject() noexcept=default
\n-
void to_file(dbtransaction &t, std::string_view file) const
Export large object's contents to a local file.
Definition largeobject.cxx:107
\n-
bool operator!=(largeobject const &other) const
Compare object identities.
Definition largeobject.hxx:95
\n-
bool operator>(largeobject const &other) const
Compare object identities.
Definition largeobject.hxx:119
\n-
oid id() const noexcept
Object identifier.
Definition largeobject.hxx:77
\n-
Accessor for large object's contents.
Definition largeobject.hxx:154
\n-
size_type pos_type
Definition largeobject.hxx:158
\n-
std::ios::openmode openmode
Open mode: in, out (can be combined using "bitwise or").
Definition largeobject.hxx:168
\n-
std::ios::seekdir seekdir
Seek direction: beg, cur, end.
Definition largeobject.hxx:175
\n-
void to_file(std::string_view file) const
Export large object's contents to a local file.
Definition largeobject.hxx:228
\n-
~largeobjectaccess() noexcept
Definition largeobject.hxx:216
\n-
void write(std::string_view buf)
Write string to large object.
Definition largeobject.hxx:251
\n-
size_type off_type
Definition largeobject.hxx:157
\n-
Streambuf to use large objects in standard I/O streams.
Definition largeobject.hxx:374
\n-
virtual pos_type seekoff(off_type offset, seekdir dir, openmode) override
Definition largeobject.hxx:425
\n-
virtual int_type overflow(int_type ch) override
Definition largeobject.hxx:437
\n-
TRAITS traits_type
Definition largeobject.hxx:379
\n-
typename traits_type::int_type int_type
Definition largeobject.hxx:380
\n-
virtual pos_type seekpos(pos_type pos, openmode) override
Definition largeobject.hxx:430
\n-
largeobject_streambuf(dbtransaction &t, oid o, openmode mode=default_mode, size_type buf_size=512)
Definition largeobject.hxx:400
\n-
CHAR char_type
Definition largeobject.hxx:378
\n-
typename traits_type::off_type off_type
Definition largeobject.hxx:382
\n-
virtual int_type overflow()
Definition largeobject.hxx:479
\n-
virtual ~largeobject_streambuf() noexcept
Definition largeobject.hxx:408
\n-
void process_notice(zview const &s)
For use by large object stream classes.
Definition largeobject.hxx:415
\n-
virtual int sync() override
Definition largeobject.hxx:418
\n-
largeobjectaccess::seekdir seekdir
Definition largeobject.hxx:384
\n-
virtual int_type underflow() override
Definition largeobject.hxx:481
\n-
largeobjectaccess::openmode openmode
Definition largeobject.hxx:383
\n-
typename traits_type::pos_type pos_type
Definition largeobject.hxx:381
\n-
largeobject_streambuf(dbtransaction &t, largeobject o, openmode mode=default_mode, size_type buf_size=512)
Definition largeobject.hxx:391
\n-
Input stream that gets its data from a large object.
Definition largeobject.hxx:546
\n-
basic_ilostream(dbtransaction &t, oid o, largeobject::size_type buf_size=512)
Create a basic_ilostream.
Definition largeobject.hxx:578
\n-
CHAR char_type
Definition largeobject.hxx:550
\n-
basic_ilostream(dbtransaction &t, largeobject o, largeobject::size_type buf_size=512)
Create a basic_ilostream.
Definition largeobject.hxx:563
\n-
typename traits_type::int_type int_type
Definition largeobject.hxx:552
\n-
TRAITS traits_type
Definition largeobject.hxx:551
\n-
typename traits_type::off_type off_type
Definition largeobject.hxx:554
\n-
typename traits_type::pos_type pos_type
Definition largeobject.hxx:553
\n-
Output stream that writes data back to a large object.
Definition largeobject.hxx:604
\n-
typename traits_type::off_type off_type
Definition largeobject.hxx:612
\n-
typename traits_type::pos_type pos_type
Definition largeobject.hxx:611
\n-
basic_olostream(dbtransaction &t, largeobject o, largeobject::size_type buf_size=512)
Create a basic_olostream.
Definition largeobject.hxx:621
\n-
typename traits_type::int_type int_type
Definition largeobject.hxx:610
\n-
~basic_olostream()
Definition largeobject.hxx:644
\n-
CHAR char_type
Definition largeobject.hxx:608
\n-
basic_olostream(dbtransaction &t, oid o, largeobject::size_type buf_size=512)
Create a basic_olostream.
Definition largeobject.hxx:636
\n-
TRAITS traits_type
Definition largeobject.hxx:609
\n-
Stream that reads and writes a large object.
Definition largeobject.hxx:676
\n-
typename traits_type::pos_type pos_type
Definition largeobject.hxx:683
\n-
~basic_lostream()
Definition largeobject.hxx:716
\n-
typename traits_type::int_type int_type
Definition largeobject.hxx:682
\n-
typename traits_type::off_type off_type
Definition largeobject.hxx:684
\n-
basic_lostream(dbtransaction &t, largeobject o, largeobject::size_type buf_size=512)
Create a basic_lostream.
Definition largeobject.hxx:692
\n-
basic_lostream(dbtransaction &t, oid o, largeobject::size_type buf_size=512)
Create a basic_lostream.
Definition largeobject.hxx:707
\n-
TRAITS traits_type
Definition largeobject.hxx:681
\n-
CHAR char_type
Definition largeobject.hxx:680
\n-
Marker-type wrapper: zero-terminated std::string_view.
Definition zview.hxx:38
\n+
1/* Automatically generated from config.h: internal/autotools config. */
\n+
2
\n+
3#define PACKAGE "libpqxx"
\n+
4#define PACKAGE_BUGREPORT "Jeroen T. Vermeulen"
\n+
5#define PACKAGE_NAME "libpqxx"
\n+
6#define PACKAGE_STRING "libpqxx 7.8.1"
\n+
7#define PACKAGE_TARNAME "libpqxx"
\n+
8#define PACKAGE_VERSION "7.8.1"
\n+
9#define VERSION "7.8.1"
\n
\n
\n \n
\n \n
\n \n \n", "details": [{"source1": "html2text {}", "source2": "html2text {}", "unified_diff": "@@ -1,763 +1,21 @@\n \n \n \n \n \n libpqxx\u00a07.8.1\n \n-largeobject.hxx\n- 1/* Large Objects interface. Deprecated; use blob instead.\n- 2 *\n- 3 * DO NOT INCLUDE THIS FILE DIRECTLY; include pqxx/largeobject instead.\n- 4 *\n- 5 * Copyright (c) 2000-2023, Jeroen T. Vermeulen.\n- 6 *\n- 7 * See COPYING for copyright license. If you did not receive a file called\n- 8 * COPYING with this source code, please notify the distributor of this\n- 9 * mistake, or contact the author.\n- 10 */\n- 11#ifndef PQXX_H_LARGEOBJECT\n- 12#define PQXX_H_LARGEOBJECT\n- 13\n- 14#if !defined(PQXX_HEADER_PRE)\n- 15# error \"Include libpqxx headers as , not .\"\n- 16#endif\n- 17\n- 18#include \n- 19\n- 20#include \"pqxx/dbtransaction.hxx\"\n- 21\n- 22\n- 23namespace pqxx\n- 24{\n- 26\n-33class PQXX_LIBEXPORT largeobject\n- 34{\n- 35public:\n-36 using size_type = large_object_size_type;\n- 37\n-40 [[deprecated(\"Use blob instead.\")]] largeobject() noexcept = default;\n- 41\n- 43\n- 45 [[deprecated(\"Use blob instead.\")]] explicit largeobject(dbtransaction &t);\n- 46\n- 48\n-52 [[deprecated(\"Use blob instead.\")]] explicit largeobject(oid o) noexcept :\n- 53 m_id{o}\n- 54 {}\n- 55\n- 57\n- 61 [[deprecated(\"Use blob instead.\")]] largeobject(\n- 62 dbtransaction &t, std::string_view file);\n- 63\n- 65\n- 69 [[deprecated(\"Use blob instead.\")]] largeobject(\n- 70 largeobjectaccess const &o) noexcept;\n- 71\n- 73\n-77 [[nodiscard]] oid id() const noexcept { return m_id; }\n- 78\n- 88\n-89 [[nodiscard]] bool operator==(largeobject const &other) const\n- 90 {\n- 91 return m_id == other.m_id;\n- 92 }\n- 94\n-95 [[nodiscard]] bool operator!=(largeobject const &other) const\n- 96 {\n- 97 return m_id != other.m_id;\n- 98 }\n- 100\n-101 [[nodiscard]] bool operator<=(largeobject const &other) const\n- 102 {\n- 103 return m_id <= other.m_id;\n- 104 }\n- 106\n-107 [[nodiscard]] bool operator>=(largeobject const &other) const\n- 108 {\n- 109 return m_id >= other.m_id;\n- 110 }\n- 112\n-113 [[nodiscard]] bool operator<(largeobject const &other) const\n- 114 {\n- 115 return m_id < other.m_id;\n- 116 }\n- 118\n-119 [[nodiscard]] bool operator>(largeobject const &other) const\n- 120 {\n- 121 return m_id > other.m_id;\n- 122 }\n- 124\n- 126\n- 130 void to_file(dbtransaction &t, std::string_view file) const;\n- 131\n- 133\n- 137 void remove(dbtransaction &t) const;\n- 138\n- 139protected:\n- 140 PQXX_PURE static internal::pq::PGconn *\n- 141 raw_connection(dbtransaction const &T);\n- 142\n- 143 PQXX_PRIVATE std::string reason(connection const &, int err) const;\n- 144\n- 145private:\n- 146 oid m_id = oid_none;\n- 147};\n- 148\n- 149\n- 151\n-153class PQXX_LIBEXPORT largeobjectaccess : private largeobject\n- 154{\n- 155public:\n- 156 using largeobject::size_type;\n-157 using off_type = size_type;\n-158 using pos_type = size_type;\n- 159\n- 161\n-168 using openmode = std::ios::openmode;\n- 169\n-171 static constexpr auto default_mode{\n- 172 std::ios::in | std::ios::out | std::ios::binary};\n- 173\n-175 using seekdir = std::ios::seekdir;\n- 176\n- 178\n- 183 [[deprecated(\"Use blob instead.\")]] explicit largeobjectaccess(\n- 184 dbtransaction &t, openmode mode = default_mode);\n- 185\n- 187\n- 194 [[deprecated(\"Use blob instead.\")]] largeobjectaccess(\n- 195 dbtransaction &t, oid o, openmode mode = default_mode);\n- 196\n- 198\n- 204 [[deprecated(\"Use blob instead.\")]] largeobjectaccess(\n- 205 dbtransaction &t, largeobject o, openmode mode = default_mode);\n- 206\n- 208\n- 213 [[deprecated(\"Use blob instead.\")]] largeobjectaccess(\n- 214 dbtransaction &t, std::string_view file, openmode mode = default_mode);\n- 215\n-216 ~largeobjectaccess() noexcept { close(); }\n- 217\n- 219\n- 222 using largeobject::id;\n- 223\n- 225\n-228 void to_file(std::string_view file) const\n- 229 {\n- 230 largeobject::to_file(m_trans, file);\n- 231 }\n- 232\n- 233 using largeobject::to_file;\n- 234\n- 240\n- 245 void write(char const buf[], std::size_t len);\n- 246\n- 248\n-251 void write(std::string_view buf) { write(std::data(buf), std::size(buf)); }\n- 252\n- 254\n- 260 size_type read(char buf[], std::size_t len);\n- 261\n- 263\n- 266 size_type seek(size_type dest, seekdir dir);\n- 267\n- 269\n- 272 [[nodiscard]] size_type tell() const;\n- 274\n- 288\n- 296 pos_type cseek(off_type dest, seekdir dir) noexcept;\n- 297\n- 299\n- 305 off_type cwrite(char const buf[], std::size_t len) noexcept;\n- 306\n- 308\n- 314 off_type cread(char buf[], std::size_t len) noexcept;\n- 315\n- 317\n- 321 [[nodiscard]] pos_type ctell() const noexcept;\n- 323\n- 329 void process_notice(zview) noexcept;\n- 331\n- 332 using largeobject::remove;\n- 333\n- 334 using largeobject::operator==;\n- 335 using largeobject::operator!=;\n- 336 using largeobject::operator<;\n- 337 using largeobject::operator<=;\n- 338 using largeobject::operator>;\n- 339 using largeobject::operator>=;\n- 340\n-341 largeobjectaccess() = delete;\n-342 largeobjectaccess(largeobjectaccess const &) = delete;\n-343 largeobjectaccess operator=(largeobjectaccess const &) = delete;\n- 344\n- 345private:\n- 346 PQXX_PRIVATE std::string reason(int err) const;\n- 347 internal::pq::PGconn *raw_connection() const\n- 348 {\n- 349 return largeobject::raw_connection(m_trans);\n- 350 }\n- 351\n- 352 PQXX_PRIVATE void open(openmode mode);\n- 353 void close() noexcept;\n- 354\n- 355 dbtransaction &m_trans;\n- 356 int m_fd = -1;\n- 357};\n- 358\n- 359\n- 361\n- 372template>\n-373class largeobject_streambuf : public std::basic_streambuf\n- 374{\n- 375 using size_type = largeobject::size_type;\n- 376\n- 377public:\n-378 using char_type = CHAR;\n-379 using traits_type = TRAITS;\n-380 using int_type = typename traits_type::int_type;\n-381 using pos_type = typename traits_type::pos_type;\n-382 using off_type = typename traits_type::off_type;\n-383 using openmode = largeobjectaccess::openmode;\n-384 using seekdir = largeobjectaccess::seekdir;\n- 385\n-387 static constexpr auto default_mode{\n- 388 std::ios::in | std::ios::out | std::ios::binary};\n- 389\n- 390#include \"pqxx/internal/ignore-deprecated-pre.hxx\"\n-391 [[deprecated(\"Use blob instead.\")]] largeobject_streambuf(\n- 392 dbtransaction &t, largeobject o, openmode mode = default_mode,\n- 393 size_type buf_size = 512) :\n- 394 m_bufsize{buf_size}, m_obj{t, o, mode}, m_g{nullptr}, m_p{nullptr}\n- 395 {\n- 396 initialize(mode);\n- 397 }\n- 398#include \"pqxx/internal/ignore-deprecated-post.hxx\"\n- 399\n-400 [[deprecated(\"Use blob instead.\")]] largeobject_streambuf(\n- 401 dbtransaction &t, oid o, openmode mode = default_mode,\n- 402 size_type buf_size = 512) :\n- 403 m_bufsize{buf_size}, m_obj{t, o, mode}, m_g{nullptr}, m_p{nullptr}\n- 404 {\n- 405 initialize(mode);\n- 406 }\n- 407\n-408 virtual ~largeobject_streambuf() noexcept\n- 409 {\n- 410 delete[] m_p;\n- 411 delete[] m_g;\n- 412 }\n- 413\n-415 void process_notice(zview const &s) { m_obj.process_notice(s); }\n- 416\n- 417protected:\n-418 virtual int sync() override\n- 419 {\n- 420 // setg() sets eback, gptr, egptr.\n- 421 this->setg(this->eback(), this->eback(), this->egptr());\n- 422 return overflow(eof());\n- 423 }\n- 424\n-425 virtual pos_type seekoff(off_type offset, seekdir dir, openmode) override\n- 426 {\n- 427 return adjust_eof(m_obj.cseek(largeobjectaccess::off_type(offset), dir));\n- 428 }\n- 429\n-430 virtual pos_type seekpos(pos_type pos, openmode) override\n- 431 {\n- 432 largeobjectaccess::pos_type const newpos{\n- 433 m_obj.cseek(largeobjectaccess::off_type(pos), std::ios::beg)};\n- 434 return adjust_eof(newpos);\n- 435 }\n- 436\n-437 virtual int_type overflow(int_type ch) override\n- 438 {\n- 439 auto *const pp{this->pptr()};\n- 440 if (pp == nullptr)\n- 441 return eof();\n- 442 auto *const pb{this->pbase()};\n- 443 int_type res{0};\n- 444\n- 445 if (pp > pb)\n- 446 {\n- 447 auto const write_sz{pp - pb};\n- 448 auto const written_sz{\n- 449 m_obj.cwrite(pb, static_cast(pp - pb))};\n- 450 if (internal::cmp_less_equal(written_sz, 0))\n- 451 throw internal_error{\n- 452 \"pqxx::largeobject: write failed \"\n- 453 \"(is transaction still valid on write or flush?), \"\n- 454 \"libpq reports error\"};\n- 455 else if (write_sz != written_sz)\n- 456 throw internal_error{\n- 457 \"pqxx::largeobject: write failed \"\n- 458 \"(is transaction still valid on write or flush?), \" +\n- 459 std::to_string(written_sz) + \"/\" + std::to_string(write_sz) +\n- 460 \" bytes written\"};\n- 461 auto const out{adjust_eof(written_sz)};\n- 462\n- 463 if constexpr (std::is_arithmetic_v)\n- 464 res = check_cast(out, \"largeobject position\"sv);\n- 465 else\n- 466 res = int_type(out);\n- 467 }\n- 468 this->setp(m_p, m_p + m_bufsize);\n- 469\n- 470 // Write that one more character, if it's there.\n- 471 if (ch != eof())\n- 472 {\n- 473 *this->pptr() = static_cast(ch);\n- 474 this->pbump(1);\n- 475 }\n- 476 return res;\n- 477 }\n- 478\n-479 virtual int_type overflow() { return overflow(eof()); }\n- 480\n-481 virtual int_type underflow() override\n- 482 {\n- 483 if (this->gptr() == nullptr)\n- 484 return eof();\n- 485 auto *const eb{this->eback()};\n- 486 auto const res{adjust_eof(\n- 487 m_obj.cread(this->eback(), static_cast(m_bufsize)))};\n- 488 this->setg(\n- 489 eb, eb, eb + (res == eof() ? 0 : static_cast(res)));\n- 490 return (res == eof() or res == 0) ? eof() : traits_type::to_int_type(*eb);\n- 491 }\n- 492\n- 493private:\n- 495 static int_type eof() { return traits_type::eof(); }\n- 496\n- 498 template static std::streampos adjust_eof(INTYPE pos)\n- 499 {\n- 500 bool const at_eof{pos == -1};\n- 501 if constexpr (std::is_arithmetic_v)\n- 502 {\n- 503 return check_cast(\n- 504 (at_eof ? eof() : pos), \"large object seek\"sv);\n- 505 }\n- 506 else\n- 507 {\n- 508 return std::streampos(at_eof ? eof() : pos);\n- 509 }\n- 510 }\n- 511\n- 512 void initialize(openmode mode)\n- 513 {\n- 514 if ((mode & std::ios::in) != 0)\n- 515 {\n- 516 m_g = new char_type[unsigned(m_bufsize)];\n- 517 this->setg(m_g, m_g, m_g);\n- 518 }\n- 519 if ((mode & std::ios::out) != 0)\n- 520 {\n- 521 m_p = new char_type[unsigned(m_bufsize)];\n- 522 this->setp(m_p, m_p + m_bufsize);\n- 523 }\n- 524 }\n- 525\n- 526 size_type const m_bufsize;\n- 527 largeobjectaccess m_obj;\n- 528\n- 530 char_type *m_g, *m_p;\n- 531};\n- 532\n- 533\n- 535\n- 544template>\n-545class basic_ilostream : public std::basic_istream\n- 546{\n- 547 using super = std::basic_istream;\n- 548\n- 549public:\n-550 using char_type = CHAR;\n-551 using traits_type = TRAITS;\n-552 using int_type = typename traits_type::int_type;\n-553 using pos_type = typename traits_type::pos_type;\n-554 using off_type = typename traits_type::off_type;\n- 555\n- 556#include \"pqxx/internal/ignore-deprecated-pre.hxx\"\n- 558\n-563 [[deprecated(\"Use blob instead.\")]] basic_ilostream(\n- 564 dbtransaction &t, largeobject o, largeobject::size_type buf_size = 512) :\n- 565 super{nullptr},\n- 566 m_buf{t, o, std::ios::in | std::ios::binary, buf_size}\n- 567 {\n- 568 super::init(&m_buf);\n- 569 }\n- 570#include \"pqxx/internal/ignore-deprecated-post.hxx\"\n- 571\n- 573\n-578 [[deprecated(\"Use blob instead.\")]] basic_ilostream(\n- 579 dbtransaction &t, oid o, largeobject::size_type buf_size = 512) :\n- 580 super{nullptr},\n- 581 m_buf{t, o, std::ios::in | std::ios::binary, buf_size}\n- 582 {\n- 583 super::init(&m_buf);\n- 584 }\n- 585\n- 586private:\n- 587 largeobject_streambuf m_buf;\n- 588};\n- 589\n-590using ilostream = basic_ilostream;\n- 591\n- 592\n- 594\n- 602template>\n-603class basic_olostream : public std::basic_ostream\n- 604{\n- 605 using super = std::basic_ostream;\n- 606\n- 607public:\n-608 using char_type = CHAR;\n-609 using traits_type = TRAITS;\n-610 using int_type = typename traits_type::int_type;\n-611 using pos_type = typename traits_type::pos_type;\n-612 using off_type = typename traits_type::off_type;\n- 613\n- 614#include \"pqxx/internal/ignore-deprecated-pre.hxx\"\n- 616\n-621 [[deprecated(\"Use blob instead.\")]] basic_olostream(\n- 622 dbtransaction &t, largeobject o, largeobject::size_type buf_size = 512) :\n- 623 super{nullptr},\n- 624 m_buf{t, o, std::ios::out | std::ios::binary, buf_size}\n- 625 {\n- 626 super::init(&m_buf);\n- 627 }\n- 628#include \"pqxx/internal/ignore-deprecated-post.hxx\"\n- 629\n- 631\n-636 [[deprecated(\"Use blob instead.\")]] basic_olostream(\n- 637 dbtransaction &t, oid o, largeobject::size_type buf_size = 512) :\n- 638 super{nullptr},\n- 639 m_buf{t, o, std::ios::out | std::ios::binary, buf_size}\n- 640 {\n- 641 super::init(&m_buf);\n- 642 }\n- 643\n-644 ~basic_olostream()\n- 645 {\n- 646 try\n- 647 {\n- 648 m_buf.pubsync();\n- 649 m_buf.pubsync();\n- 650 }\n- 651 catch (std::exception const &e)\n- 652 {\n- 653 m_buf.process_notice(e.what());\n- 654 }\n- 655 }\n- 656\n- 657private:\n- 658 largeobject_streambuf m_buf;\n- 659};\n- 660\n-661using olostream = basic_olostream;\n- 662\n- 663\n- 665\n- 674template>\n-675class basic_lostream : public std::basic_iostream\n- 676{\n- 677 using super = std::basic_iostream;\n- 678\n- 679public:\n-680 using char_type = CHAR;\n-681 using traits_type = TRAITS;\n-682 using int_type = typename traits_type::int_type;\n-683 using pos_type = typename traits_type::pos_type;\n-684 using off_type = typename traits_type::off_type;\n- 685\n- 687\n-692 [[deprecated(\"Use blob instead.\")]] basic_lostream(\n- 693 dbtransaction &t, largeobject o, largeobject::size_type buf_size = 512) :\n- 694 super{nullptr},\n- 695 m_buf{\n- 696 t, o, std::ios::in | std::ios::out | std::ios::binary, buf_size}\n- 697 {\n- 698 super::init(&m_buf);\n- 699 }\n- 700\n- 702\n-707 [[deprecated(\"Use blob instead.\")]] basic_lostream(\n- 708 dbtransaction &t, oid o, largeobject::size_type buf_size = 512) :\n- 709 super{nullptr},\n- 710 m_buf{\n- 711 t, o, std::ios::in | std::ios::out | std::ios::binary, buf_size}\n- 712 {\n- 713 super::init(&m_buf);\n- 714 }\n- 715\n-716 ~basic_lostream()\n- 717 {\n- 718 try\n- 719 {\n- 720 m_buf.pubsync();\n- 721 m_buf.pubsync();\n- 722 }\n- 723 catch (std::exception const &e)\n- 724 {\n- 725 m_buf.process_notice(e.what());\n- 726 }\n- 727 }\n- 728\n- 729private:\n- 730 largeobject_streambuf m_buf;\n- 731};\n- 732\n-733using lostream = basic_lostream;\n- 734} // namespace pqxx\n- 735#endif\n-pqxx\n-The home of all libpqxx classes, functions, templates, etc.\n-Definition array.hxx:33\n-pqxx::oid_none\n-constexpr oid oid_none\n-The \"null\" oid.\n-Definition util.hxx:342\n-pqxx::large_object_size_type\n-int64_t large_object_size_type\n-Number of bytes in a large object.\n-Definition types.hxx:43\n-pqxx::format::binary\n-@ binary\n-pqxx::internal::cmp_less_equal\n-constexpr bool cmp_less_equal(LEFT lhs, RIGHT rhs) noexcept\n-C++20 std::cmp_less_equal, or workaround if not available.\n-Definition util.hxx:98\n-pqxx::blob\n-Definition blob.hxx:53\n-pqxx::connection\n-Connection to a database.\n-Definition connection.hxx:253\n-pqxx::dbtransaction\n-Abstract transaction base class: bracket transactions on the database.\n-Definition dbtransaction.hxx:54\n-pqxx::internal_error\n-Internal error in libpqxx library.\n-Definition except.hxx:242\n-pqxx::largeobject\n-Identity of a large object.\n-Definition largeobject.hxx:34\n-pqxx::largeobject::operator==\n-bool operator==(largeobject const &other) const\n-Compare object identities.\n-Definition largeobject.hxx:89\n-pqxx::largeobject::operator>=\n-bool operator>=(largeobject const &other) const\n-Compare object identities.\n-Definition largeobject.hxx:107\n-pqxx::largeobject::raw_connection\n-static PQXX_PURE internal::pq::PGconn * raw_connection(dbtransaction const &T)\n-Definition largeobject.cxx:139\n-pqxx::largeobject::operator<=\n-bool operator<=(largeobject const &other) const\n-Compare object identities.\n-Definition largeobject.hxx:101\n-pqxx::largeobject::size_type\n-large_object_size_type size_type\n-Definition largeobject.hxx:36\n-pqxx::largeobject::operator<\n-bool operator<(largeobject const &other) const\n-Compare object identities.\n-Definition largeobject.hxx:113\n-pqxx::largeobject::largeobject\n-largeobject() noexcept=default\n-pqxx::largeobject::to_file\n-void to_file(dbtransaction &t, std::string_view file) const\n-Export large object's contents to a local file.\n-Definition largeobject.cxx:107\n-pqxx::largeobject::operator!=\n-bool operator!=(largeobject const &other) const\n-Compare object identities.\n-Definition largeobject.hxx:95\n-pqxx::largeobject::operator>\n-bool operator>(largeobject const &other) const\n-Compare object identities.\n-Definition largeobject.hxx:119\n-pqxx::largeobject::id\n-oid id() const noexcept\n-Object identifier.\n-Definition largeobject.hxx:77\n-pqxx::largeobjectaccess\n-Accessor for large object's contents.\n-Definition largeobject.hxx:154\n-pqxx::largeobjectaccess::pos_type\n-size_type pos_type\n-Definition largeobject.hxx:158\n-pqxx::largeobjectaccess::openmode\n-std::ios::openmode openmode\n-Open mode: in, out (can be combined using \"bitwise or\").\n-Definition largeobject.hxx:168\n-pqxx::largeobjectaccess::seekdir\n-std::ios::seekdir seekdir\n-Seek direction: beg, cur, end.\n-Definition largeobject.hxx:175\n-pqxx::largeobjectaccess::to_file\n-void to_file(std::string_view file) const\n-Export large object's contents to a local file.\n-Definition largeobject.hxx:228\n-pqxx::largeobjectaccess::~largeobjectaccess\n-~largeobjectaccess() noexcept\n-Definition largeobject.hxx:216\n-pqxx::largeobjectaccess::write\n-void write(std::string_view buf)\n-Write string to large object.\n-Definition largeobject.hxx:251\n-pqxx::largeobjectaccess::off_type\n-size_type off_type\n-Definition largeobject.hxx:157\n-pqxx::largeobject_streambuf\n-Streambuf to use large objects in standard I/O streams.\n-Definition largeobject.hxx:374\n-pqxx::largeobject_streambuf::seekoff\n-virtual pos_type seekoff(off_type offset, seekdir dir, openmode) override\n-Definition largeobject.hxx:425\n-pqxx::largeobject_streambuf::overflow\n-virtual int_type overflow(int_type ch) override\n-Definition largeobject.hxx:437\n-pqxx::largeobject_streambuf::traits_type\n-TRAITS traits_type\n-Definition largeobject.hxx:379\n-pqxx::largeobject_streambuf::int_type\n-typename traits_type::int_type int_type\n-Definition largeobject.hxx:380\n-pqxx::largeobject_streambuf::seekpos\n-virtual pos_type seekpos(pos_type pos, openmode) override\n-Definition largeobject.hxx:430\n-pqxx::largeobject_streambuf::largeobject_streambuf\n-largeobject_streambuf(dbtransaction &t, oid o, openmode mode=default_mode,\n-size_type buf_size=512)\n-Definition largeobject.hxx:400\n-pqxx::largeobject_streambuf::char_type\n-CHAR char_type\n-Definition largeobject.hxx:378\n-pqxx::largeobject_streambuf::off_type\n-typename traits_type::off_type off_type\n-Definition largeobject.hxx:382\n-pqxx::largeobject_streambuf::overflow\n-virtual int_type overflow()\n-Definition largeobject.hxx:479\n-pqxx::largeobject_streambuf::~largeobject_streambuf\n-virtual ~largeobject_streambuf() noexcept\n-Definition largeobject.hxx:408\n-pqxx::largeobject_streambuf::process_notice\n-void process_notice(zview const &s)\n-For use by large object stream classes.\n-Definition largeobject.hxx:415\n-pqxx::largeobject_streambuf::sync\n-virtual int sync() override\n-Definition largeobject.hxx:418\n-pqxx::largeobject_streambuf::seekdir\n-largeobjectaccess::seekdir seekdir\n-Definition largeobject.hxx:384\n-pqxx::largeobject_streambuf::underflow\n-virtual int_type underflow() override\n-Definition largeobject.hxx:481\n-pqxx::largeobject_streambuf::openmode\n-largeobjectaccess::openmode openmode\n-Definition largeobject.hxx:383\n-pqxx::largeobject_streambuf::pos_type\n-typename traits_type::pos_type pos_type\n-Definition largeobject.hxx:381\n-pqxx::largeobject_streambuf::largeobject_streambuf\n-largeobject_streambuf(dbtransaction &t, largeobject o, openmode\n-mode=default_mode, size_type buf_size=512)\n-Definition largeobject.hxx:391\n-pqxx::basic_ilostream\n-Input stream that gets its data from a large object.\n-Definition largeobject.hxx:546\n-pqxx::basic_ilostream::basic_ilostream\n-basic_ilostream(dbtransaction &t, oid o, largeobject::size_type buf_size=512)\n-Create a basic_ilostream.\n-Definition largeobject.hxx:578\n-pqxx::basic_ilostream::char_type\n-CHAR char_type\n-Definition largeobject.hxx:550\n-pqxx::basic_ilostream::basic_ilostream\n-basic_ilostream(dbtransaction &t, largeobject o, largeobject::size_type\n-buf_size=512)\n-Create a basic_ilostream.\n-Definition largeobject.hxx:563\n-pqxx::basic_ilostream::int_type\n-typename traits_type::int_type int_type\n-Definition largeobject.hxx:552\n-pqxx::basic_ilostream::traits_type\n-TRAITS traits_type\n-Definition largeobject.hxx:551\n-pqxx::basic_ilostream::off_type\n-typename traits_type::off_type off_type\n-Definition largeobject.hxx:554\n-pqxx::basic_ilostream::pos_type\n-typename traits_type::pos_type pos_type\n-Definition largeobject.hxx:553\n-pqxx::basic_olostream\n-Output stream that writes data back to a large object.\n-Definition largeobject.hxx:604\n-pqxx::basic_olostream::off_type\n-typename traits_type::off_type off_type\n-Definition largeobject.hxx:612\n-pqxx::basic_olostream::pos_type\n-typename traits_type::pos_type pos_type\n-Definition largeobject.hxx:611\n-pqxx::basic_olostream::basic_olostream\n-basic_olostream(dbtransaction &t, largeobject o, largeobject::size_type\n-buf_size=512)\n-Create a basic_olostream.\n-Definition largeobject.hxx:621\n-pqxx::basic_olostream::int_type\n-typename traits_type::int_type int_type\n-Definition largeobject.hxx:610\n-pqxx::basic_olostream::~basic_olostream\n-~basic_olostream()\n-Definition largeobject.hxx:644\n-pqxx::basic_olostream::char_type\n-CHAR char_type\n-Definition largeobject.hxx:608\n-pqxx::basic_olostream::basic_olostream\n-basic_olostream(dbtransaction &t, oid o, largeobject::size_type buf_size=512)\n-Create a basic_olostream.\n-Definition largeobject.hxx:636\n-pqxx::basic_olostream::traits_type\n-TRAITS traits_type\n-Definition largeobject.hxx:609\n-pqxx::basic_lostream\n-Stream that reads and writes a large object.\n-Definition largeobject.hxx:676\n-pqxx::basic_lostream::pos_type\n-typename traits_type::pos_type pos_type\n-Definition largeobject.hxx:683\n-pqxx::basic_lostream::~basic_lostream\n-~basic_lostream()\n-Definition largeobject.hxx:716\n-pqxx::basic_lostream::int_type\n-typename traits_type::int_type int_type\n-Definition largeobject.hxx:682\n-pqxx::basic_lostream::off_type\n-typename traits_type::off_type off_type\n-Definition largeobject.hxx:684\n-pqxx::basic_lostream::basic_lostream\n-basic_lostream(dbtransaction &t, largeobject o, largeobject::size_type\n-buf_size=512)\n-Create a basic_lostream.\n-Definition largeobject.hxx:692\n-pqxx::basic_lostream::basic_lostream\n-basic_lostream(dbtransaction &t, oid o, largeobject::size_type buf_size=512)\n-Create a basic_lostream.\n-Definition largeobject.hxx:707\n-pqxx::basic_lostream::traits_type\n-TRAITS traits_type\n-Definition largeobject.hxx:681\n-pqxx::basic_lostream::char_type\n-CHAR char_type\n-Definition largeobject.hxx:680\n-pqxx::zview\n-Marker-type wrapper: zero-terminated std::string_view.\n-Definition zview.hxx:38\n+config-internal-autotools.h\n+ 1/* Automatically generated from config.h: internal/autotools config. */\n+ 2\n+ 3#define PACKAGE \"libpqxx\"\n+ 4#define PACKAGE_BUGREPORT \"Jeroen T. Vermeulen\"\n+ 5#define PACKAGE_NAME \"libpqxx\"\n+ 6#define PACKAGE_STRING \"libpqxx 7.8.1\"\n+ 7#define PACKAGE_TARNAME \"libpqxx\"\n+ 8#define PACKAGE_VERSION \"7.8.1\"\n+ 9#define VERSION \"7.8.1\"\n * include\n * pqxx\n- * largeobject.hxx\n+ * config-internal-autotools.h\n * Generated by [doxygen] 1.9.8\n"}]}, {"source1": "./usr/share/doc/libpqxx-doc/html/a00074_source.html", "source2": "./usr/share/doc/libpqxx-doc/html/a00074_source.html", "unified_diff": "@@ -1,15 +1,15 @@\n \n \n \n \n \n \n \n-libpqxx: result.hxx Source File\n+libpqxx: errorhandler.hxx Source File\n \n \n \n \n \n \n \n@@ -60,280 +60,99 @@\n \n
\n
\n-
result.hxx
\n+
errorhandler.hxx
\n
\n
\n-
1/* Definitions for the pqxx::result class and support classes.
\n+
1/* Definition of the pqxx::errorhandler class.
\n
2 *
\n-
3 * pqxx::result represents the set of result rows from a database query.
\n+
3 * pqxx::errorhandler handlers errors and warnings in a database session.
\n
4 *
\n-
5 * DO NOT INCLUDE THIS FILE DIRECTLY; include pqxx/result instead.
\n+
5 * DO NOT INCLUDE THIS FILE DIRECTLY; include pqxx/errorhandler instead.
\n
6 *
\n
7 * Copyright (c) 2000-2023, Jeroen T. Vermeulen.
\n
8 *
\n
9 * See COPYING for copyright license. If you did not receive a file called
\n
10 * COPYING with this source code, please notify the distributor of this
\n
11 * mistake, or contact the author.
\n
12 */
\n-
13#ifndef PQXX_H_RESULT
\n-
14#define PQXX_H_RESULT
\n+
13#ifndef PQXX_H_ERRORHANDLER
\n+
14#define PQXX_H_ERRORHANDLER
\n
15
\n
16#if !defined(PQXX_HEADER_PRE)
\n
17# error "Include libpqxx headers as <pqxx/header>, not <pqxx/header.hxx>."
\n
18#endif
\n
19
\n-
20#include <functional>
\n-
21#include <ios>
\n-
22#include <memory>
\n-
23#include <stdexcept>
\n-
24
\n-
25#include "pqxx/except.hxx"
\n-
26#include "pqxx/types.hxx"
\n-
27#include "pqxx/util.hxx"
\n-
28#include "pqxx/zview.hxx"
\n-
29
\n-
30#include "pqxx/internal/encodings.hxx"
\n-
31
\n-
32
\n-
33namespace pqxx::internal
\n-
34{
\n-
35PQXX_LIBEXPORT void clear_result(pq::PGresult const *) noexcept;
\n-
36} // namespace pqxx::internal
\n+
20#include "pqxx/types.hxx"
\n+
21
\n+
22
\n+\n+
24{
\n+
25class errorhandler_connection;
\n+
26}
\n+
27
\n+
28
\n+
29namespace pqxx
\n+
30{
\n+
35
\n
37
\n-
38
\n-\n-
40{
\n-
41class result_connection;
\n-
42class result_creation;
\n-
43class result_pipeline;
\n-
44class result_row;
\n-
45class result_sql_cursor;
\n-
46} // namespace pqxx::internal::gate
\n-
47
\n-
48
\n-
49namespace pqxx
\n-
50{
\n-
52
\n-
\n-
72class PQXX_LIBEXPORT result
\n-
73{
\n-
74public:
\n-\n-\n-
77 using reference = row;
\n-
78 using const_iterator = const_result_iterator;
\n-\n-\n-
81 using const_reverse_iterator = const_reverse_result_iterator;
\n-\n-
83
\n-
\n-
84 result() noexcept :
\n-
85 m_data{make_data_pointer()},
\n-
86 m_query{},
\n-
87 m_encoding{internal::encoding_group::MONOBYTE}
\n-
88 {}
\n+
\n+
53class PQXX_LIBEXPORT errorhandler
\n+
54{
\n+
55public:
\n+
56 explicit errorhandler(connection &);
\n+
57 virtual ~errorhandler();
\n+
58
\n+
61
\n+
65 virtual bool operator()(char const msg[]) noexcept = 0;
\n+
66
\n+
67 errorhandler() = delete;
\n+
68 errorhandler(errorhandler const &) = delete;
\n+\n+
70
\n+
71private:
\n+
72 connection *m_home;
\n+
73
\n+
74 friend class internal::gate::errorhandler_connection;
\n+
75 void unregister() noexcept;
\n+
76};
\n+
\n+
77
\n+
78
\n+
\n+\n+
81{
\n+
82public:
\n+\n+
85
\n+
87 virtual bool operator()(char const[]) noexcept override { return false; }
\n+
88};
\n
\n
89
\n-
90 result(result const &rhs) noexcept = default;
\n-
91 result(result &&rhs) noexcept = default;
\n-
92
\n-
94
\n-
97 result &operator=(result const &rhs) noexcept = default;
\n-
98
\n-
100 result &operator=(result &&rhs) noexcept = default;
\n-
101
\n-
111 [[nodiscard]] bool operator==(result const &) const noexcept;
\n-
\n-
113 [[nodiscard]] bool operator!=(result const &rhs) const noexcept
\n-
114 {
\n-
115 return not operator==(rhs);
\n-
116 }
\n-
\n-
118
\n-
120
\n-
126 template<typename... TYPE> auto iter() const;
\n-
127
\n-
128 [[nodiscard]] const_reverse_iterator rbegin() const;
\n-
129 [[nodiscard]] const_reverse_iterator crbegin() const;
\n-
130 [[nodiscard]] const_reverse_iterator rend() const;
\n-
131 [[nodiscard]] const_reverse_iterator crend() const;
\n-
132
\n-
133 [[nodiscard]] const_iterator begin() const noexcept;
\n-
134 [[nodiscard]] const_iterator cbegin() const noexcept;
\n-
135 [[nodiscard]] inline const_iterator end() const noexcept;
\n-
136 [[nodiscard]] inline const_iterator cend() const noexcept;
\n-
137
\n-
138 [[nodiscard]] reference front() const noexcept;
\n-
139 [[nodiscard]] reference back() const noexcept;
\n-
140
\n-
141 [[nodiscard]] PQXX_PURE size_type size() const noexcept;
\n-
142 [[nodiscard]] PQXX_PURE bool empty() const noexcept;
\n-
143 [[nodiscard]] size_type capacity() const noexcept { return size(); }
\n-
144
\n-
146
\n-
150 void swap(result &) noexcept;
\n-
151
\n-
153
\n-
157 [[nodiscard]] row operator[](size_type i) const noexcept;
\n-
158
\n-
159#if pqxx_have_multidim
\n-
160 [[nodiscard]] field
\n-
161 operator[](size_type row_num, row_size_type col_num) const noexcept;
\n-
162#endif // pqxx_have_multidim
\n-
163
\n-
165 row at(size_type) const;
\n-
166
\n-
168 field at(size_type, row_size_type) const;
\n-
169
\n-
171
\n-
\n-
178 void clear() noexcept
\n-
179 {
\n-
180 m_data.reset();
\n-
181 m_query = nullptr;
\n-
182 }
\n-
\n-
183
\n-
189 [[nodiscard]] PQXX_PURE row_size_type columns() const noexcept;
\n-
190
\n-
192 [[nodiscard]] row_size_type column_number(zview name) const;
\n-
193
\n-
195 [[nodiscard]] char const *column_name(row_size_type number) const &;
\n-
196
\n-
198 [[nodiscard]] oid column_type(row_size_type col_num) const;
\n-
199
\n-
\n-
201 [[nodiscard]] oid column_type(zview col_name) const
\n-
202 {
\n-
203 return column_type(column_number(col_name));
\n-
204 }
\n-
\n-
205
\n-
207 [[nodiscard]] oid column_table(row_size_type col_num) const;
\n-
208
\n-
\n-
210 [[nodiscard]] oid column_table(zview col_name) const
\n-
211 {
\n-
212 return column_table(column_number(col_name));
\n-
213 }
\n-
\n-
214
\n-
216 [[nodiscard]] row_size_type table_column(row_size_type col_num) const;
\n-
217
\n-
\n-
219 [[nodiscard]] row_size_type table_column(zview col_name) const
\n-
220 {
\n-
221 return table_column(column_number(col_name));
\n-
222 }
\n-
\n-
224
\n-
226 [[nodiscard]] PQXX_PURE std::string const &query() const &noexcept;
\n-
227
\n-
229
\n-
232 [[nodiscard]] PQXX_PURE oid inserted_oid() const;
\n-
233
\n-
235
\n-
238 [[nodiscard]] PQXX_PURE size_type affected_rows() const;
\n-
239
\n-
240 // C++20: Concept like std::invocable, but without specifying param types.
\n-
242
\n-
276 template<typename CALLABLE> inline void for_each(CALLABLE &&func) const;
\n-
277
\n-
278private:
\n-
279 using data_pointer = std::shared_ptr<internal::pq::PGresult const>;
\n-
280
\n-
282 data_pointer m_data;
\n-
283
\n-
285 static data_pointer
\n-
286 make_data_pointer(internal::pq::PGresult const *res = nullptr) noexcept
\n-
287 {
\n-
288 return {res, internal::clear_result};
\n-
289 }
\n-
290
\n-
291 friend class pqxx::internal::gate::result_pipeline;
\n-
292 PQXX_PURE std::shared_ptr<std::string const> query_ptr() const noexcept
\n-
293 {
\n-
294 return m_query;
\n-
295 }
\n-
296
\n-
298 std::shared_ptr<std::string const> m_query;
\n-
299
\n-
300 internal::encoding_group m_encoding;
\n-
301
\n-
302 static std::string const s_empty_string;
\n-
303
\n-
304 friend class pqxx::field;
\n-
305 PQXX_PURE char const *
\n-
306 get_value(size_type row, row_size_type col) const noexcept;
\n-
307 PQXX_PURE bool get_is_null(size_type row, row_size_type col) const noexcept;
\n-
308 PQXX_PURE
\n-
309 field_size_type get_length(size_type, row_size_type) const noexcept;
\n-
310
\n-
311 friend class pqxx::internal::gate::result_creation;
\n-
312 result(
\n-
313 internal::pq::PGresult *rhs, std::shared_ptr<std::string> query,
\n-
314 internal::encoding_group enc);
\n-
315
\n-
316 PQXX_PRIVATE void check_status(std::string_view desc = ""sv) const;
\n-
317
\n-
318 friend class pqxx::internal::gate::result_connection;
\n-
319 friend class pqxx::internal::gate::result_row;
\n-
320 bool operator!() const noexcept { return m_data.get() == nullptr; }
\n-
321 operator bool() const noexcept { return m_data.get() != nullptr; }
\n-
322
\n-
323 [[noreturn]] PQXX_PRIVATE PQXX_COLD void
\n-
324 throw_sql_error(std::string const &Err, std::string const &Query) const;
\n-
325 PQXX_PRIVATE PQXX_PURE int errorposition() const;
\n-
326 PQXX_PRIVATE std::string status_error() const;
\n-
327
\n-
328 friend class pqxx::internal::gate::result_sql_cursor;
\n-
329 PQXX_PURE char const *cmd_status() const noexcept;
\n-
330};
\n-
\n-
331} // namespace pqxx
\n-
332#endif
\n+
91} // namespace pqxx
\n+
92#endif
\n
The home of all libpqxx classes, functions, templates, etc.
Definition array.hxx:33
\n-
int row_size_type
Number of fields in a row of database data.
Definition types.hxx:34
\n-
std::size_t field_size_type
Number of bytes in a field of database data.
Definition types.hxx:40
\n-
int result_difference_type
Difference between result sizes.
Definition types.hxx:31
\n-
int result_size_type
Number of rows in a result set.
Definition types.hxx:28
\n-
Internal items for libpqxx' own use. Do not use these yourself.
Definition composite.hxx:84
\n-
void clear_result(pq::PGresult const *) noexcept
C++ wrapper for libpq's PQclear.
Definition result.cxx:42
\n
Definition connection.hxx:112
\n-
Reference to a field in a result set.
Definition field.hxx:35
\n-
Result set containing data returned by a query or command.
Definition result.hxx:73
\n-
const_reverse_result_iterator const_reverse_iterator
Definition result.hxx:81
\n-
result(result &&rhs) noexcept=default
\n-
row_size_type table_column(zview col_name) const
What column in its table did this column come from?
Definition result.hxx:219
\n-
result() noexcept
Definition result.hxx:84
\n-
result & operator=(result &&rhs) noexcept=default
Assign one result to another, invaliding the old one.
\n-
result_size_type size_type
Definition result.hxx:75
\n-
bool operator!=(result const &rhs) const noexcept
Compare two results for inequality.
Definition result.hxx:113
\n-
const_iterator pointer
Definition result.hxx:79
\n-
void clear() noexcept
Let go of the result's data.
Definition result.hxx:178
\n-
const_iterator iterator
Definition result.hxx:80
\n-
result_difference_type difference_type
Definition result.hxx:76
\n-
const_reverse_iterator reverse_iterator
Definition result.hxx:82
\n-
oid column_table(zview col_name) const
What table did this column come from?
Definition result.hxx:210
\n-
result & operator=(result const &rhs) noexcept=default
Assign one result to another.
\n-
const_result_iterator const_iterator
Definition result.hxx:78
\n-
result(result const &rhs) noexcept=default
\n-
auto iter() const
Iterate rows, reading them directly into a tuple of "TYPE...".
\n-
Reference to one row in a result.
Definition row.hxx:47
\n-
Marker-type wrapper: zero-terminated std::string_view.
Definition zview.hxx:38
\n+
Connection to a database.
Definition connection.hxx:253
\n+
Base class for error-handler callbacks.
Definition errorhandler.hxx:54
\n+\n+
virtual bool operator()(char const msg[]) noexcept=0
\n+
errorhandler & operator=(errorhandler const &)=delete
\n+
errorhandler(errorhandler const &)=delete
\n+
An error handler that suppresses any previously registered error handlers.
Definition errorhandler.hxx:81
\n+
virtual bool operator()(char const[]) noexcept override
Revert to previous handling of error notices.
Definition errorhandler.hxx:87
\n+
quiet_errorhandler(connection &conn)
Suppress error notices.
Definition errorhandler.hxx:84
\n
\n
\n \n
\n \n
\n \n \n", "details": [{"source1": "html2text {}", "source2": "html2text {}", "unified_diff": "@@ -1,322 +1,105 @@\n \n \n \n \n \n libpqxx\u00a07.8.1\n \n-result.hxx\n- 1/* Definitions for the pqxx::result class and support classes.\n+errorhandler.hxx\n+ 1/* Definition of the pqxx::errorhandler class.\n 2 *\n- 3 * pqxx::result represents the set of result rows from a database query.\n+ 3 * pqxx::errorhandler handlers errors and warnings in a database session.\n 4 *\n- 5 * DO NOT INCLUDE THIS FILE DIRECTLY; include pqxx/result instead.\n+ 5 * DO NOT INCLUDE THIS FILE DIRECTLY; include pqxx/errorhandler instead.\n 6 *\n 7 * Copyright (c) 2000-2023, Jeroen T. Vermeulen.\n 8 *\n 9 * See COPYING for copyright license. If you did not receive a file called\n 10 * COPYING with this source code, please notify the distributor of this\n 11 * mistake, or contact the author.\n 12 */\n- 13#ifndef PQXX_H_RESULT\n- 14#define PQXX_H_RESULT\n+ 13#ifndef PQXX_H_ERRORHANDLER\n+ 14#define PQXX_H_ERRORHANDLER\n 15\n 16#if !defined(PQXX_HEADER_PRE)\n 17# error \"Include libpqxx headers as , not .\"\n 18#endif\n 19\n- 20#include \n- 21#include \n- 22#include \n- 23#include \n- 24\n- 25#include \"pqxx/except.hxx\"\n- 26#include \"pqxx/types.hxx\"\n- 27#include \"pqxx/util.hxx\"\n- 28#include \"pqxx/zview.hxx\"\n- 29\n- 30#include \"pqxx/internal/encodings.hxx\"\n- 31\n- 32\n- 33namespace pqxx::internal\n- 34{\n- 35PQXX_LIBEXPORT void clear_result(pq::PGresult const *) noexcept;\n- 36} // namespace pqxx::internal\n+ 20#include \"pqxx/types.hxx\"\n+ 21\n+ 22\n+ 23namespace pqxx::internal::gate\n+ 24{\n+ 25class errorhandler_connection;\n+ 26}\n+ 27\n+ 28\n+ 29namespace pqxx\n+ 30{\n+ 35\n 37\n- 38\n- 39namespace pqxx::internal::gate\n- 40{\n- 41class result_connection;\n- 42class result_creation;\n- 43class result_pipeline;\n- 44class result_row;\n- 45class result_sql_cursor;\n- 46} // namespace pqxx::internal::gate\n- 47\n- 48\n- 49namespace pqxx\n- 50{\n- 52\n-72class PQXX_LIBEXPORT result\n- 73{\n- 74public:\n-75 using size_type = result_size_type;\n-76 using difference_type = result_difference_type;\n-77 using reference = row;\n-78 using const_iterator = const_result_iterator;\n-79 using pointer = const_iterator;\n-80 using iterator = const_iterator;\n-81 using const_reverse_iterator = const_reverse_result_iterator;\n-82 using reverse_iterator = const_reverse_iterator;\n- 83\n-84 result() noexcept :\n- 85 m_data{make_data_pointer()},\n- 86 m_query{},\n- 87 m_encoding{internal::encoding_group::MONOBYTE}\n- 88 {}\n+53class PQXX_LIBEXPORT errorhandler\n+ 54{\n+ 55public:\n+ 56 explicit errorhandler(connection &);\n+ 57 virtual ~errorhandler();\n+ 58\n+ 61\n+65 virtual bool operator()(char const msg[]) noexcept = 0;\n+ 66\n+67 errorhandler() = delete;\n+68 errorhandler(errorhandler const &) = delete;\n+69 errorhandler &operator=(errorhandler const &) = delete;\n+ 70\n+ 71private:\n+ 72 connection *m_home;\n+ 73\n+74 friend class internal::gate::errorhandler_connection;\n+ 75 void unregister() noexcept;\n+ 76};\n+ 77\n+ 78\n+80class quiet_errorhandler : public errorhandler\n+ 81{\n+ 82public:\n+84 quiet_errorhandler(connection &conn) : errorhandler{conn} {}\n+ 85\n+87 virtual bool operator()(char const[]) noexcept override { return false; }\n+ 88};\n 89\n-90 result(result const &rhs) noexcept = default;\n-91 result(result &&rhs) noexcept = default;\n- 92\n- 94\n-97 result &operator=(result const &rhs) noexcept = default;\n- 98\n-100 result &operator=(result &&rhs) noexcept = default;\n- 101\n- 111 [[nodiscard]] bool operator==(result const &) const noexcept;\n-113 [[nodiscard]] bool operator!=(result const &rhs) const noexcept\n- 114 {\n- 115 return not operator==(rhs);\n- 116 }\n- 118\n- 120\n-126 template auto iter() const;\n- 127\n- 128 [[nodiscard]] const_reverse_iterator rbegin() const;\n- 129 [[nodiscard]] const_reverse_iterator crbegin() const;\n- 130 [[nodiscard]] const_reverse_iterator rend() const;\n- 131 [[nodiscard]] const_reverse_iterator crend() const;\n- 132\n- 133 [[nodiscard]] const_iterator begin() const noexcept;\n- 134 [[nodiscard]] const_iterator cbegin() const noexcept;\n-135 [[nodiscard]] inline const_iterator end() const noexcept;\n-136 [[nodiscard]] inline const_iterator cend() const noexcept;\n- 137\n- 138 [[nodiscard]] reference front() const noexcept;\n- 139 [[nodiscard]] reference back() const noexcept;\n- 140\n- 141 [[nodiscard]] PQXX_PURE size_type size() const noexcept;\n- 142 [[nodiscard]] PQXX_PURE bool empty() const noexcept;\n-143 [[nodiscard]] size_type capacity() const noexcept { return size(); }\n- 144\n- 146\n- 150 void swap(result &) noexcept;\n- 151\n- 153\n- 157 [[nodiscard]] row operator[](size_type i) const noexcept;\n- 158\n- 159#if pqxx_have_multidim\n- 160 [[nodiscard]] field\n- 161 operator[](size_type row_num, row_size_type col_num) const noexcept;\n- 162#endif // pqxx_have_multidim\n- 163\n- 165 row at(size_type) const;\n- 166\n- 168 field at(size_type, row_size_type) const;\n- 169\n- 171\n-178 void clear() noexcept\n- 179 {\n- 180 m_data.reset();\n- 181 m_query = nullptr;\n- 182 }\n- 183\n- 189 [[nodiscard]] PQXX_PURE row_size_type columns() const noexcept;\n- 190\n- 192 [[nodiscard]] row_size_type column_number(zview name) const;\n- 193\n- 195 [[nodiscard]] char const *column_name(row_size_type number) const &;\n- 196\n- 198 [[nodiscard]] oid column_type(row_size_type col_num) const;\n- 199\n-201 [[nodiscard]] oid column_type(zview col_name) const\n- 202 {\n- 203 return column_type(column_number(col_name));\n- 204 }\n- 205\n- 207 [[nodiscard]] oid column_table(row_size_type col_num) const;\n- 208\n-210 [[nodiscard]] oid column_table(zview col_name) const\n- 211 {\n- 212 return column_table(column_number(col_name));\n- 213 }\n- 214\n- 216 [[nodiscard]] row_size_type table_column(row_size_type col_num) const;\n- 217\n-219 [[nodiscard]] row_size_type table_column(zview col_name) const\n- 220 {\n- 221 return table_column(column_number(col_name));\n- 222 }\n- 224\n- 226 [[nodiscard]] PQXX_PURE std::string const &query() const &noexcept;\n- 227\n- 229\n- 232 [[nodiscard]] PQXX_PURE oid inserted_oid() const;\n- 233\n- 235\n- 238 [[nodiscard]] PQXX_PURE size_type affected_rows() const;\n- 239\n- 240 // C++20: Concept like std::invocable, but without specifying param types.\n- 242\n-276 template inline void for_each(CALLABLE &&func) const;\n- 277\n- 278private:\n- 279 using data_pointer = std::shared_ptr;\n- 280\n- 282 data_pointer m_data;\n- 283\n- 285 static data_pointer\n- 286 make_data_pointer(internal::pq::PGresult const *res = nullptr) noexcept\n- 287 {\n- 288 return {res, internal::clear_result};\n- 289 }\n- 290\n-291 friend class pqxx::internal::gate::result_pipeline;\n- 292 PQXX_PURE std::shared_ptr query_ptr() const noexcept\n- 293 {\n- 294 return m_query;\n- 295 }\n- 296\n- 298 std::shared_ptr m_query;\n- 299\n- 300 internal::encoding_group m_encoding;\n- 301\n- 302 static std::string const s_empty_string;\n- 303\n-304 friend class pqxx::field;\n- 305 PQXX_PURE char const *\n- 306 get_value(size_type row, row_size_type col) const noexcept;\n- 307 PQXX_PURE bool get_is_null(size_type row, row_size_type col) const\n-noexcept;\n- 308 PQXX_PURE\n- 309 field_size_type get_length(size_type, row_size_type) const noexcept;\n- 310\n-311 friend class pqxx::internal::gate::result_creation;\n- 312 result(\n- 313 internal::pq::PGresult *rhs, std::shared_ptr query,\n- 314 internal::encoding_group enc);\n- 315\n- 316 PQXX_PRIVATE void check_status(std::string_view desc = \"\"sv) const;\n- 317\n-318 friend class pqxx::internal::gate::result_connection;\n-319 friend class pqxx::internal::gate::result_row;\n- 320 bool operator!() const noexcept { return m_data.get() == nullptr; }\n- 321 operator bool() const noexcept { return m_data.get() != nullptr; }\n- 322\n- 323 [[noreturn]] PQXX_PRIVATE PQXX_COLD void\n- 324 throw_sql_error(std::string const &Err, std::string const &Query) const;\n- 325 PQXX_PRIVATE PQXX_PURE int errorposition() const;\n- 326 PQXX_PRIVATE std::string status_error() const;\n- 327\n-328 friend class pqxx::internal::gate::result_sql_cursor;\n- 329 PQXX_PURE char const *cmd_status() const noexcept;\n- 330};\n- 331} // namespace pqxx\n- 332#endif\n+ 91} // namespace pqxx\n+ 92#endif\n pqxx\n The home of all libpqxx classes, functions, templates, etc.\n Definition array.hxx:33\n-pqxx::row_size_type\n-int row_size_type\n-Number of fields in a row of database data.\n-Definition types.hxx:34\n-pqxx::field_size_type\n-std::size_t field_size_type\n-Number of bytes in a field of database data.\n-Definition types.hxx:40\n-pqxx::result_difference_type\n-int result_difference_type\n-Difference between result sizes.\n-Definition types.hxx:31\n-pqxx::result_size_type\n-int result_size_type\n-Number of rows in a result set.\n-Definition types.hxx:28\n-pqxx::internal\n-Internal items for libpqxx' own use. Do not use these yourself.\n-Definition composite.hxx:84\n-pqxx::internal::clear_result\n-void clear_result(pq::PGresult const *) noexcept\n-C++ wrapper for libpq's PQclear.\n-Definition result.cxx:42\n pqxx::internal::gate\n Definition connection.hxx:112\n-pqxx::field\n-Reference to a field in a result set.\n-Definition field.hxx:35\n-pqxx::result\n-Result set containing data returned by a query or command.\n-Definition result.hxx:73\n-pqxx::result::const_reverse_iterator\n-const_reverse_result_iterator const_reverse_iterator\n-Definition result.hxx:81\n-pqxx::result::result\n-result(result &&rhs) noexcept=default\n-pqxx::result::table_column\n-row_size_type table_column(zview col_name) const\n-What column in its table did this column come from?\n-Definition result.hxx:219\n-pqxx::result::result\n-result() noexcept\n-Definition result.hxx:84\n-pqxx::result::operator=\n-result & operator=(result &&rhs) noexcept=default\n-Assign one result to another, invaliding the old one.\n-pqxx::result::size_type\n-result_size_type size_type\n-Definition result.hxx:75\n-pqxx::result::operator!=\n-bool operator!=(result const &rhs) const noexcept\n-Compare two results for inequality.\n-Definition result.hxx:113\n-pqxx::result::pointer\n-const_iterator pointer\n-Definition result.hxx:79\n-pqxx::result::clear\n-void clear() noexcept\n-Let go of the result's data.\n-Definition result.hxx:178\n-pqxx::result::iterator\n-const_iterator iterator\n-Definition result.hxx:80\n-pqxx::result::difference_type\n-result_difference_type difference_type\n-Definition result.hxx:76\n-pqxx::result::reverse_iterator\n-const_reverse_iterator reverse_iterator\n-Definition result.hxx:82\n-pqxx::result::column_table\n-oid column_table(zview col_name) const\n-What table did this column come from?\n-Definition result.hxx:210\n-pqxx::result::operator=\n-result & operator=(result const &rhs) noexcept=default\n-Assign one result to another.\n-pqxx::result::const_iterator\n-const_result_iterator const_iterator\n-Definition result.hxx:78\n-pqxx::result::result\n-result(result const &rhs) noexcept=default\n-pqxx::result::iter\n-auto iter() const\n-Iterate rows, reading them directly into a tuple of \"TYPE...\".\n-pqxx::row\n-Reference to one row in a result.\n-Definition row.hxx:47\n-pqxx::zview\n-Marker-type wrapper: zero-terminated std::string_view.\n-Definition zview.hxx:38\n+pqxx::connection\n+Connection to a database.\n+Definition connection.hxx:253\n+pqxx::errorhandler\n+Base class for error-handler callbacks.\n+Definition errorhandler.hxx:54\n+pqxx::errorhandler::errorhandler\n+errorhandler()=delete\n+pqxx::errorhandler::operator()\n+virtual bool operator()(char const msg[]) noexcept=0\n+pqxx::errorhandler::operator=\n+errorhandler & operator=(errorhandler const &)=delete\n+pqxx::errorhandler::errorhandler\n+errorhandler(errorhandler const &)=delete\n+pqxx::quiet_errorhandler\n+An error handler that suppresses any previously registered error handlers.\n+Definition errorhandler.hxx:81\n+pqxx::quiet_errorhandler::operator()\n+virtual bool operator()(char const[]) noexcept override\n+Revert to previous handling of error notices.\n+Definition errorhandler.hxx:87\n+pqxx::quiet_errorhandler::quiet_errorhandler\n+quiet_errorhandler(connection &conn)\n+Suppress error notices.\n+Definition errorhandler.hxx:84\n * include\n * pqxx\n- * result.hxx\n+ * errorhandler.hxx\n * Generated by [doxygen] 1.9.8\n"}]}, {"source1": "./usr/share/doc/libpqxx-doc/html/a00077_source.html", "source2": "./usr/share/doc/libpqxx-doc/html/a00077_source.html", "unified_diff": "@@ -1,15 +1,15 @@\n \n \n \n \n \n \n \n-libpqxx: robusttransaction.hxx Source File\n+libpqxx: config.h Source File\n \n \n \n \n \n \n \n@@ -60,112 +60,136 @@\n \n
\n
\n-
robusttransaction.hxx
\n+
config.h
\n
\n
\n-
1/* Definition of the pqxx::robusttransaction class.
\n-
2 *
\n-
3 * pqxx::robusttransaction is a slower but safer transaction class.
\n-
4 *
\n-
5 * DO NOT INCLUDE THIS FILE DIRECTLY; include pqxx/robusttransaction instead.
\n-
6 *
\n-
7 * Copyright (c) 2000-2023, Jeroen T. Vermeulen.
\n-
8 *
\n-
9 * See COPYING for copyright license. If you did not receive a file called
\n-
10 * COPYING with this source code, please notify the distributor of this
\n-
11 * mistake, or contact the author.
\n-
12 */
\n-
13#ifndef PQXX_H_ROBUSTTRANSACTION
\n-
14#define PQXX_H_ROBUSTTRANSACTION
\n+
1/* include/pqxx/config.h. Generated from config.h.in by configure. */
\n+
2/* include/pqxx/config.h.in. Generated from configure.ac by autoheader. */
\n+
3
\n+
4/* Define to 1 if you have the <dlfcn.h> header file. */
\n+
5#define HAVE_DLFCN_H 1
\n+
6
\n+
7/* Define to 1 if you have the <inttypes.h> header file. */
\n+
8#define HAVE_INTTYPES_H 1
\n+
9
\n+
10/* Define to 1 if you have the `pq' library (-lpq). */
\n+
11#define HAVE_LIBPQ 1
\n+
12
\n+
13/* Define to 1 if you have the <stdint.h> header file. */
\n+
14#define HAVE_STDINT_H 1
\n
15
\n-
16#if !defined(PQXX_HEADER_PRE)
\n-
17# error "Include libpqxx headers as <pqxx/header>, not <pqxx/header.hxx>."
\n-
18#endif
\n-
19
\n-
20#include "pqxx/dbtransaction.hxx"
\n+
16/* Define to 1 if you have the <stdio.h> header file. */
\n+
17#define HAVE_STDIO_H 1
\n+
18
\n+
19/* Define to 1 if you have the <stdlib.h> header file. */
\n+
20#define HAVE_STDLIB_H 1
\n
21
\n-
22namespace pqxx::internal
\n-
23{
\n-
\n-
25class PQXX_LIBEXPORT PQXX_NOVTABLE basic_robusttransaction
\n-
26 : public dbtransaction
\n-
27{
\n-
28public:
\n-
29 virtual ~basic_robusttransaction() override = 0;
\n+
22/* Define to 1 if you have the <strings.h> header file. */
\n+
23#define HAVE_STRINGS_H 1
\n+
24
\n+
25/* Define to 1 if you have the <string.h> header file. */
\n+
26#define HAVE_STRING_H 1
\n+
27
\n+
28/* Define to 1 if you have the <sys/stat.h> header file. */
\n+
29#define HAVE_SYS_STAT_H 1
\n
30
\n-
31protected:
\n-\n-
33 connection &c, zview begin_command, std::string_view tname);
\n-
34 basic_robusttransaction(connection &c, zview begin_command);
\n-
35
\n-
36private:
\n-
37 using IDType = unsigned long;
\n-
38
\n-
39 std::string m_conn_string;
\n-
40 std::string m_xid;
\n-
41 int m_backendpid = -1;
\n+
31/* Define to 1 if you have the <sys/types.h> header file. */
\n+
32#define HAVE_SYS_TYPES_H 1
\n+
33
\n+
34/* Define to 1 if you have the <unistd.h> header file. */
\n+
35#define HAVE_UNISTD_H 1
\n+
36
\n+
37/* Define to the sub-directory where libtool stores uninstalled libraries. */
\n+
38#define LT_OBJDIR ".libs/"
\n+
39
\n+
40/* Name of package */
\n+
41#define PACKAGE "libpqxx"
\n
42
\n-
43 void init(zview begin_command);
\n-
44
\n-
45 // @warning This function will become `final`.
\n-
46 virtual void do_commit() override;
\n-
47};
\n-
\n-
48} // namespace pqxx::internal
\n-
49
\n-
50
\n-
51namespace pqxx
\n-
52{
\n+
43/* Define to the address where bug reports for this package should be sent. */
\n+
44#define PACKAGE_BUGREPORT "Jeroen T. Vermeulen"
\n+
45
\n+
46/* Define to the full name of this package. */
\n+
47#define PACKAGE_NAME "libpqxx"
\n+
48
\n+
49/* Define to the full name and version of this package. */
\n+
50#define PACKAGE_STRING "libpqxx 7.8.1"
\n+
51
\n+
52/* Define to the one symbol short name of this package. */
\n+
53#define PACKAGE_TARNAME "libpqxx"
\n+
54
\n+
55/* Define to the home page for this package. */
\n+
56#define PACKAGE_URL ""
\n+
57
\n+
58/* Define to the version of this package. */
\n+
59#define PACKAGE_VERSION "7.8.1"
\n
60
\n-
81template<isolation_level ISOLATION = read_committed>
\n-
82class robusttransaction final : public internal::basic_robusttransaction
\n-
83{
\n-
84public:
\n-
89 robusttransaction(connection &c, std::string_view tname) :
\n-\n-
91 c, pqxx::internal::begin_cmd<ISOLATION, write_policy::read_write>,
\n-
92 tname}
\n-
93 {}
\n-
94
\n-
99 robusttransaction(connection &c, std::string &&tname) :
\n-
100 internal::basic_robusttransaction{
\n-
101 c, pqxx::internal::begin_cmd<ISOLATION, write_policy::read_write>,
\n-
102 std::move(tname)}
\n-
103 {}
\n-
104
\n-
108 explicit robusttransaction(connection &c) :
\n-
109 internal::basic_robusttransaction{
\n-
110 c, pqxx::internal::begin_cmd<ISOLATION, write_policy::read_write>}
\n-
111 {}
\n-
112
\n-
113 virtual ~robusttransaction() noexcept override { close(); }
\n-
114};
\n-
115
\n-
119} // namespace pqxx
\n-
120#endif
\n-
The home of all libpqxx classes, functions, templates, etc.
Definition array.hxx:33
\n-
write_policy
Should a transaction be read-only, or read-write?
Definition isolation.hxx:27
\n-\n-
Internal items for libpqxx' own use. Do not use these yourself.
Definition composite.hxx:84
\n-
Connection to a database.
Definition connection.hxx:253
\n-
Abstract transaction base class: bracket transactions on the database.
Definition dbtransaction.hxx:54
\n-
Helper base class for the robusttransaction class template.
Definition robusttransaction.hxx:27
\n-
virtual ~basic_robusttransaction() override=0
\n-
basic_robusttransaction(connection &c, zview begin_command, std::string_view tname)
Definition robusttransaction.cxx:104
\n-
void close() noexcept
End transaction. To be called by implementing class' destructor.
Definition transaction_base.cxx:343
\n-
Marker-type wrapper: zero-terminated std::string_view.
Definition zview.hxx:38
\n+
61/* Define if <charconv> supports floating-point conversion. */
\n+
62#define PQXX_HAVE_CHARCONV_FLOAT 1
\n+
63
\n+
64/* Define if <charconv> supports integer conversion. */
\n+
65#define PQXX_HAVE_CHARCONV_INT 1
\n+
66
\n+
67/* Define if compiler has C++20 std::cmp_greater etc. */
\n+
68/* #undef PQXX_HAVE_CMP */
\n+
69
\n+
70/* Define if compiler supports Concepts and <ranges> header. */
\n+
71/* #undef PQXX_HAVE_CONCEPTS */
\n+
72
\n+
73/* Define if compiler supports __cxa_demangle */
\n+
74#define PQXX_HAVE_CXA_DEMANGLE 1
\n+
75
\n+
76/* Define if g++ supports pure attribute */
\n+
77#define PQXX_HAVE_GCC_PURE 1
\n+
78
\n+
79/* Define if g++ supports visibility attribute. */
\n+
80#define PQXX_HAVE_GCC_VISIBILITY 1
\n+
81
\n+
82/* Define if likely & unlikely work. */
\n+
83/* #undef PQXX_HAVE_LIKELY */
\n+
84
\n+
85/* Define if compiler has usable std::filesystem::path. */
\n+
86#define PQXX_HAVE_PATH 1
\n+
87
\n+
88/* Define if poll() is available. */
\n+
89#define PQXX_HAVE_POLL 1
\n+
90
\n+
91/* Define if std::this_thread::sleep_for works. */
\n+
92#define PQXX_HAVE_SLEEP_FOR 1
\n+
93
\n+
94/* Define if compiler has std::span. */
\n+
95/* #undef PQXX_HAVE_SPAN */
\n+
96
\n+
97/* Define if strerror_r() is available. */
\n+
98#define PQXX_HAVE_STRERROR_R 1
\n+
99
\n+
100/* Define if strerror_s() is available. */
\n+
101/* #undef PQXX_HAVE_STRERROR_S */
\n+
102
\n+
103/* Define if thread_local is fully supported. */
\n+
104#define PQXX_HAVE_THREAD_LOCAL 1
\n+
105
\n+
106/* Define if std::chrono has year_month_day etc. */
\n+
107/* #undef PQXX_HAVE_YEAR_MONTH_DAY */
\n+
108
\n+
109/* Define to 1 if all of the C90 standard headers exist (not just the ones
\n+
110 required in a freestanding environment). This macro is provided for
\n+
111 backward compatibility; new code need not use it. */
\n+
112#define STDC_HEADERS 1
\n+
113
\n+
114/* Version number of package */
\n+
115#define VERSION "7.8.1"
\n
\n
\n \n
\n \n
\n \n \n", "details": [{"source1": "html2text {}", "source2": "html2text {}", "unified_diff": "@@ -1,124 +1,129 @@\n \n \n \n \n \n libpqxx\u00a07.8.1\n \n-robusttransaction.hxx\n- 1/* Definition of the pqxx::robusttransaction class.\n- 2 *\n- 3 * pqxx::robusttransaction is a slower but safer transaction class.\n- 4 *\n- 5 * DO NOT INCLUDE THIS FILE DIRECTLY; include pqxx/robusttransaction instead.\n- 6 *\n- 7 * Copyright (c) 2000-2023, Jeroen T. Vermeulen.\n- 8 *\n- 9 * See COPYING for copyright license. If you did not receive a file called\n- 10 * COPYING with this source code, please notify the distributor of this\n- 11 * mistake, or contact the author.\n- 12 */\n- 13#ifndef PQXX_H_ROBUSTTRANSACTION\n- 14#define PQXX_H_ROBUSTTRANSACTION\n+config.h\n+ 1/* include/pqxx/config.h. Generated from config.h.in by configure. */\n+ 2/* include/pqxx/config.h.in. Generated from configure.ac by autoheader. */\n+ 3\n+ 4/* Define to 1 if you have the header file. */\n+ 5#define HAVE_DLFCN_H 1\n+ 6\n+ 7/* Define to 1 if you have the header file. */\n+ 8#define HAVE_INTTYPES_H 1\n+ 9\n+ 10/* Define to 1 if you have the `pq' library (-lpq). */\n+ 11#define HAVE_LIBPQ 1\n+ 12\n+ 13/* Define to 1 if you have the header file. */\n+ 14#define HAVE_STDINT_H 1\n 15\n- 16#if !defined(PQXX_HEADER_PRE)\n- 17# error \"Include libpqxx headers as , not .\"\n- 18#endif\n- 19\n- 20#include \"pqxx/dbtransaction.hxx\"\n+ 16/* Define to 1 if you have the header file. */\n+ 17#define HAVE_STDIO_H 1\n+ 18\n+ 19/* Define to 1 if you have the header file. */\n+ 20#define HAVE_STDLIB_H 1\n 21\n- 22namespace pqxx::internal\n- 23{\n-25class PQXX_LIBEXPORT PQXX_NOVTABLE basic_robusttransaction\n- 26 : public dbtransaction\n- 27{\n- 28public:\n-29 virtual ~basic_robusttransaction() override = 0;\n+ 22/* Define to 1 if you have the header file. */\n+ 23#define HAVE_STRINGS_H 1\n+ 24\n+ 25/* Define to 1 if you have the header file. */\n+ 26#define HAVE_STRING_H 1\n+ 27\n+ 28/* Define to 1 if you have the header file. */\n+ 29#define HAVE_SYS_STAT_H 1\n 30\n- 31protected:\n- 32 basic_robusttransaction(\n- 33 connection &c, zview begin_command, std::string_view tname);\n- 34 basic_robusttransaction(connection &c, zview begin_command);\n- 35\n- 36private:\n- 37 using IDType = unsigned long;\n- 38\n- 39 std::string m_conn_string;\n- 40 std::string m_xid;\n- 41 int m_backendpid = -1;\n+ 31/* Define to 1 if you have the header file. */\n+ 32#define HAVE_SYS_TYPES_H 1\n+ 33\n+ 34/* Define to 1 if you have the header file. */\n+ 35#define HAVE_UNISTD_H 1\n+ 36\n+ 37/* Define to the sub-directory where libtool stores uninstalled libraries.\n+*/\n+ 38#define LT_OBJDIR \".libs/\"\n+ 39\n+ 40/* Name of package */\n+ 41#define PACKAGE \"libpqxx\"\n 42\n- 43 void init(zview begin_command);\n- 44\n- 45 // @warning This function will become `final`.\n- 46 virtual void do_commit() override;\n- 47};\n- 48} // namespace pqxx::internal\n- 49\n- 50\n- 51namespace pqxx\n- 52{\n+ 43/* Define to the address where bug reports for this package should be sent.\n+*/\n+ 44#define PACKAGE_BUGREPORT \"Jeroen T. Vermeulen\"\n+ 45\n+ 46/* Define to the full name of this package. */\n+ 47#define PACKAGE_NAME \"libpqxx\"\n+ 48\n+ 49/* Define to the full name and version of this package. */\n+ 50#define PACKAGE_STRING \"libpqxx 7.8.1\"\n+ 51\n+ 52/* Define to the one symbol short name of this package. */\n+ 53#define PACKAGE_TARNAME \"libpqxx\"\n+ 54\n+ 55/* Define to the home page for this package. */\n+ 56#define PACKAGE_URL \"\"\n+ 57\n+ 58/* Define to the version of this package. */\n+ 59#define PACKAGE_VERSION \"7.8.1\"\n 60\n- 81template\n- 82class robusttransaction final : public internal::basic_robusttransaction\n- 83{\n- 84public:\n- 89 robusttransaction(connection &c, std::string_view tname) :\n- 90 internal::basic_robusttransaction{\n- 91 c, pqxx::internal::begin_cmd,\n- 92 tname}\n- 93 {}\n- 94\n- 99 robusttransaction(connection &c, std::string &&tname) :\n- 100 internal::basic_robusttransaction{\n- 101 c, pqxx::internal::begin_cmd,\n- 102 std::move(tname)}\n- 103 {}\n- 104\n- 108 explicit robusttransaction(connection &c) :\n- 109 internal::basic_robusttransaction{\n- 110 c, pqxx::internal::begin_cmd}\n- 111 {}\n- 112\n- 113 virtual ~robusttransaction() noexcept override { close(); }\n- 114};\n- 115\n- 119} // namespace pqxx\n- 120#endif\n-pqxx\n-The home of all libpqxx classes, functions, templates, etc.\n-Definition array.hxx:33\n-pqxx::write_policy\n-write_policy\n-Should a transaction be read-only, or read-write?\n-Definition isolation.hxx:27\n-pqxx::write_policy::read_write\n-@ read_write\n-pqxx::internal\n-Internal items for libpqxx' own use. Do not use these yourself.\n-Definition composite.hxx:84\n-pqxx::connection\n-Connection to a database.\n-Definition connection.hxx:253\n-pqxx::dbtransaction\n-Abstract transaction base class: bracket transactions on the database.\n-Definition dbtransaction.hxx:54\n-pqxx::internal::basic_robusttransaction\n-Helper base class for the robusttransaction class template.\n-Definition robusttransaction.hxx:27\n-pqxx::internal::basic_robusttransaction::~basic_robusttransaction\n-virtual ~basic_robusttransaction() override=0\n-pqxx::internal::basic_robusttransaction::basic_robusttransaction\n-basic_robusttransaction(connection &c, zview begin_command, std::string_view\n-tname)\n-Definition robusttransaction.cxx:104\n-pqxx::transaction_base::close\n-void close() noexcept\n-End transaction. To be called by implementing class' destructor.\n-Definition transaction_base.cxx:343\n-pqxx::zview\n-Marker-type wrapper: zero-terminated std::string_view.\n-Definition zview.hxx:38\n+ 61/* Define if supports floating-point conversion. */\n+ 62#define PQXX_HAVE_CHARCONV_FLOAT 1\n+ 63\n+ 64/* Define if supports integer conversion. */\n+ 65#define PQXX_HAVE_CHARCONV_INT 1\n+ 66\n+ 67/* Define if compiler has C++20 std::cmp_greater etc. */\n+ 68/* #undef PQXX_HAVE_CMP */\n+ 69\n+ 70/* Define if compiler supports Concepts and header. */\n+ 71/* #undef PQXX_HAVE_CONCEPTS */\n+ 72\n+ 73/* Define if compiler supports __cxa_demangle */\n+ 74#define PQXX_HAVE_CXA_DEMANGLE 1\n+ 75\n+ 76/* Define if g++ supports pure attribute */\n+ 77#define PQXX_HAVE_GCC_PURE 1\n+ 78\n+ 79/* Define if g++ supports visibility attribute. */\n+ 80#define PQXX_HAVE_GCC_VISIBILITY 1\n+ 81\n+ 82/* Define if likely & unlikely work. */\n+ 83/* #undef PQXX_HAVE_LIKELY */\n+ 84\n+ 85/* Define if compiler has usable std::filesystem::path. */\n+ 86#define PQXX_HAVE_PATH 1\n+ 87\n+ 88/* Define if poll() is available. */\n+ 89#define PQXX_HAVE_POLL 1\n+ 90\n+ 91/* Define if std::this_thread::sleep_for works. */\n+ 92#define PQXX_HAVE_SLEEP_FOR 1\n+ 93\n+ 94/* Define if compiler has std::span. */\n+ 95/* #undef PQXX_HAVE_SPAN */\n+ 96\n+ 97/* Define if strerror_r() is available. */\n+ 98#define PQXX_HAVE_STRERROR_R 1\n+ 99\n+ 100/* Define if strerror_s() is available. */\n+ 101/* #undef PQXX_HAVE_STRERROR_S */\n+ 102\n+ 103/* Define if thread_local is fully supported. */\n+ 104#define PQXX_HAVE_THREAD_LOCAL 1\n+ 105\n+ 106/* Define if std::chrono has year_month_day etc. */\n+ 107/* #undef PQXX_HAVE_YEAR_MONTH_DAY */\n+ 108\n+ 109/* Define to 1 if all of the C90 standard headers exist (not just the ones\n+ 110 required in a freestanding environment). This macro is provided for\n+ 111 backward compatibility; new code need not use it. */\n+ 112#define STDC_HEADERS 1\n+ 113\n+ 114/* Version number of package */\n+ 115#define VERSION \"7.8.1\"\n * include\n * pqxx\n- * robusttransaction.hxx\n+ * config.h\n * Generated by [doxygen] 1.9.8\n"}]}, {"source1": "./usr/share/doc/libpqxx-doc/html/a00080_source.html", "source2": "./usr/share/doc/libpqxx-doc/html/a00080_source.html", "unified_diff": "@@ -1,15 +1,15 @@\n \n \n \n \n \n \n \n-libpqxx: config.h Source File\n+libpqxx: util.hxx Source File\n \n \n \n \n \n \n \n@@ -60,136 +60,550 @@\n \n
\n
\n-
config.h
\n+
util.hxx
\n
\n
\n-
1/* include/pqxx/config.h. Generated from config.h.in by configure. */
\n-
2/* include/pqxx/config.h.in. Generated from configure.ac by autoheader. */
\n-
3
\n-
4/* Define to 1 if you have the <dlfcn.h> header file. */
\n-
5#define HAVE_DLFCN_H 1
\n-
6
\n-
7/* Define to 1 if you have the <inttypes.h> header file. */
\n-
8#define HAVE_INTTYPES_H 1
\n-
9
\n-
10/* Define to 1 if you have the `pq' library (-lpq). */
\n-
11#define HAVE_LIBPQ 1
\n-
12
\n-
13/* Define to 1 if you have the <stdint.h> header file. */
\n-
14#define HAVE_STDINT_H 1
\n-
15
\n-
16/* Define to 1 if you have the <stdio.h> header file. */
\n-
17#define HAVE_STDIO_H 1
\n-
18
\n-
19/* Define to 1 if you have the <stdlib.h> header file. */
\n-
20#define HAVE_STDLIB_H 1
\n-
21
\n-
22/* Define to 1 if you have the <strings.h> header file. */
\n-
23#define HAVE_STRINGS_H 1
\n-
24
\n-
25/* Define to 1 if you have the <string.h> header file. */
\n-
26#define HAVE_STRING_H 1
\n-
27
\n-
28/* Define to 1 if you have the <sys/stat.h> header file. */
\n-
29#define HAVE_SYS_STAT_H 1
\n-
30
\n-
31/* Define to 1 if you have the <sys/types.h> header file. */
\n-
32#define HAVE_SYS_TYPES_H 1
\n-
33
\n-
34/* Define to 1 if you have the <unistd.h> header file. */
\n-
35#define HAVE_UNISTD_H 1
\n-
36
\n-
37/* Define to the sub-directory where libtool stores uninstalled libraries. */
\n-
38#define LT_OBJDIR ".libs/"
\n+
1/* Various utility definitions for libpqxx.
\n+
2 *
\n+
3 * DO NOT INCLUDE THIS FILE DIRECTLY; include pqxx/util instead.
\n+
4 *
\n+
5 * Copyright (c) 2000-2023, Jeroen T. Vermeulen.
\n+
6 *
\n+
7 * See COPYING for copyright license. If you did not receive a file called
\n+
8 * COPYING with this source code, please notify the distributor of this
\n+
9 * mistake, or contact the author.
\n+
10 */
\n+
11#ifndef PQXX_H_UTIL
\n+
12#define PQXX_H_UTIL
\n+
13
\n+
14#if !defined(PQXX_HEADER_PRE)
\n+
15# error "Include libpqxx headers as <pqxx/header>, not <pqxx/header.hxx>."
\n+
16#endif
\n+
17
\n+
18#include <cassert>
\n+
19#include <cctype>
\n+
20#include <cerrno>
\n+
21#include <cstdio>
\n+
22#include <cstring>
\n+
23#include <functional>
\n+
24#include <iterator>
\n+
25#include <limits>
\n+
26#include <memory>
\n+
27#include <stdexcept>
\n+
28#include <string>
\n+
29#include <string_view>
\n+
30#include <type_traits>
\n+
31#include <typeinfo>
\n+
32#include <utility>
\n+
33#include <vector>
\n+
34
\n+
35#include "pqxx/except.hxx"
\n+
36#include "pqxx/types.hxx"
\n+
37#include "pqxx/version.hxx"
\n+
38
\n
39
\n-
40/* Name of package */
\n-
41#define PACKAGE "libpqxx"
\n-
42
\n-
43/* Define to the address where bug reports for this package should be sent. */
\n-
44#define PACKAGE_BUGREPORT "Jeroen T. Vermeulen"
\n+
41namespace pqxx
\n+
42{}
\n+
43
\n+
44#include <pqxx/internal/libpq-forward.hxx>
\n
45
\n-
46/* Define to the full name of this package. */
\n-
47#define PACKAGE_NAME "libpqxx"
\n-
48
\n-
49/* Define to the full name and version of this package. */
\n-
50#define PACKAGE_STRING "libpqxx 7.8.1"
\n-
51
\n-
52/* Define to the one symbol short name of this package. */
\n-
53#define PACKAGE_TARNAME "libpqxx"
\n+
46
\n+
47// C++23: Retire wrapper.
\n+
48#if pqxx_have_unreachable
\n+
50# define PQXX_UNREACHABLE std::unreachable()
\n+
51#else
\n+
52# define PQXX_UNREACHABLE assert(false)
\n+
53#endif
\n
54
\n-
55/* Define to the home page for this package. */
\n-
56#define PACKAGE_URL ""
\n-
57
\n-
58/* Define to the version of this package. */
\n-
59#define PACKAGE_VERSION "7.8.1"
\n-
60
\n-
61/* Define if <charconv> supports floating-point conversion. */
\n-
62#define PQXX_HAVE_CHARCONV_FLOAT 1
\n-
63
\n-
64/* Define if <charconv> supports integer conversion. */
\n-
65#define PQXX_HAVE_CHARCONV_INT 1
\n-
66
\n-
67/* Define if compiler has C++20 std::cmp_greater etc. */
\n-
68/* #undef PQXX_HAVE_CMP */
\n-
69
\n-
70/* Define if compiler supports Concepts and <ranges> header. */
\n-
71/* #undef PQXX_HAVE_CONCEPTS */
\n-
72
\n-
73/* Define if compiler supports __cxa_demangle */
\n-
74#define PQXX_HAVE_CXA_DEMANGLE 1
\n-
75
\n-
76/* Define if g++ supports pure attribute */
\n-
77#define PQXX_HAVE_GCC_PURE 1
\n-
78
\n-
79/* Define if g++ supports visibility attribute. */
\n-
80#define PQXX_HAVE_GCC_VISIBILITY 1
\n+
55
\n+
57namespace pqxx::internal
\n+
58{
\n+
59
\n+
60// C++20: Retire wrapper.
\n+
62template<typename LEFT, typename RIGHT>
\n+
\n+
63inline constexpr bool cmp_less(LEFT lhs, RIGHT rhs) noexcept
\n+
64{
\n+
65#if defined(PQXX_HAVE_CMP)
\n+
66 return std::cmp_less(lhs, rhs);
\n+
67#else
\n+
68 // We need a variable just because lgtm.com gives off a false positive
\n+
69 // warning when we compare the values directly. It considers that a
\n+
70 // "self-comparison."
\n+
71 constexpr bool left_signed{std::is_signed_v<LEFT>};
\n+
72 if constexpr (left_signed == std::is_signed_v<RIGHT>)
\n+
73 return lhs < rhs;
\n+
74 else if constexpr (std::is_signed_v<LEFT>)
\n+
75 return (lhs <= 0) ? true : (std::make_unsigned_t<LEFT>(lhs) < rhs);
\n+
76 else
\n+
77 return (rhs <= 0) ? false : (lhs < std::make_unsigned_t<RIGHT>(rhs));
\n+
78#endif
\n+
79}
\n+
\n+
80
\n
81
\n-
82/* Define if likely & unlikely work. */
\n-
83/* #undef PQXX_HAVE_LIKELY */
\n-
84
\n-
85/* Define if compiler has usable std::filesystem::path. */
\n-
86#define PQXX_HAVE_PATH 1
\n-
87
\n-
88/* Define if poll() is available. */
\n-
89#define PQXX_HAVE_POLL 1
\n-
90
\n-
91/* Define if std::this_thread::sleep_for works. */
\n-
92#define PQXX_HAVE_SLEEP_FOR 1
\n+
82// C++20: Retire wrapper.
\n+
84template<typename LEFT, typename RIGHT>
\n+
\n+
85inline constexpr bool cmp_greater(LEFT lhs, RIGHT rhs) noexcept
\n+
86{
\n+
87#if defined(PQXX_HAVE_CMP)
\n+
88 return std::cmp_greater(lhs, rhs);
\n+
89#else
\n+
90 return cmp_less(rhs, lhs);
\n+
91#endif
\n+
92}
\n+
\n
93
\n-
94/* Define if compiler has std::span. */
\n-
95/* #undef PQXX_HAVE_SPAN */
\n-
96
\n-
97/* Define if strerror_r() is available. */
\n-
98#define PQXX_HAVE_STRERROR_R 1
\n-
99
\n-
100/* Define if strerror_s() is available. */
\n-
101/* #undef PQXX_HAVE_STRERROR_S */
\n-
102
\n-
103/* Define if thread_local is fully supported. */
\n-
104#define PQXX_HAVE_THREAD_LOCAL 1
\n-
105
\n-
106/* Define if std::chrono has year_month_day etc. */
\n-
107/* #undef PQXX_HAVE_YEAR_MONTH_DAY */
\n-
108
\n-
109/* Define to 1 if all of the C90 standard headers exist (not just the ones
\n-
110 required in a freestanding environment). This macro is provided for
\n-
111 backward compatibility; new code need not use it. */
\n-
112#define STDC_HEADERS 1
\n-
113
\n-
114/* Version number of package */
\n-
115#define VERSION "7.8.1"
\n+
94
\n+
95// C++20: Retire wrapper.
\n+
97template<typename LEFT, typename RIGHT>
\n+
\n+
98inline constexpr bool cmp_less_equal(LEFT lhs, RIGHT rhs) noexcept
\n+
99{
\n+
100#if defined(PQXX_HAVE_CMP)
\n+
101 return std::cmp_less_equal(lhs, rhs);
\n+
102#else
\n+
103 return not cmp_less(rhs, lhs);
\n+
104#endif
\n+
105}
\n+
\n+
106
\n+
107
\n+
108// C++20: Retire wrapper.
\n+
110template<typename LEFT, typename RIGHT>
\n+
\n+
111inline constexpr bool cmp_greater_equal(LEFT lhs, RIGHT rhs) noexcept
\n+
112{
\n+
113#if defined(PQXX_HAVE_CMP)
\n+
114 return std::cmp_greater_equal(lhs, rhs);
\n+
115#else
\n+
116 return not cmp_less(lhs, rhs);
\n+
117#endif
\n+
118}
\n+
\n+
119
\n+
120
\n+
122
\n+
\n+
125[[nodiscard]] inline std::string cat2(std::string_view x, std::string_view y)
\n+
126{
\n+
127 std::string buf;
\n+
128 auto const xs{std::size(x)}, ys{std::size(y)};
\n+
129 buf.resize(xs + ys);
\n+
130 x.copy(std::data(buf), xs);
\n+
131 y.copy(std::data(buf) + xs, ys);
\n+
132 return buf;
\n+
133}
\n+
\n+
134} // namespace pqxx::internal
\n+
135
\n+
136
\n+
137namespace pqxx
\n+
138{
\n+
139using namespace std::literals;
\n+
140
\n+
\n+
142template<typename... T> inline constexpr void ignore_unused(T &&...) noexcept
\n+
143{}
\n+
\n+
144
\n+
145
\n+
147
\n+
150template<typename TO, typename FROM>
\n+
\n+
151inline TO check_cast(FROM value, std::string_view description)
\n+
152{
\n+
153 static_assert(std::is_arithmetic_v<FROM>);
\n+
154 static_assert(std::is_arithmetic_v<TO>);
\n+
155 static_assert(std::is_integral_v<FROM> == std::is_integral_v<TO>);
\n+
156
\n+
157 // The rest of this code won't quite work for bool, but bool is trivially
\n+
158 // convertible to other arithmetic types as far as I can see.
\n+
159 if constexpr (std::is_same_v<FROM, bool>)
\n+
160 return static_cast<TO>(value);
\n+
161
\n+
162 // Depending on our "if constexpr" conditions, this parameter may not be
\n+
163 // needed. Some compilers will warn.
\n+
164 ignore_unused(description);
\n+
165
\n+
166 using from_limits = std::numeric_limits<decltype(value)>;
\n+
167 using to_limits = std::numeric_limits<TO>;
\n+
168 if constexpr (std::is_signed_v<FROM>)
\n+
169 {
\n+
170 if constexpr (std::is_signed_v<TO>)
\n+
171 {
\n+
172 if (value < to_limits::lowest())
\n+
173 throw range_error{internal::cat2("Cast underflow: "sv, description)};
\n+
174 }
\n+
175 else
\n+
176 {
\n+
177 // FROM is signed, but TO is not. Treat this as a special case, because
\n+
178 // there may not be a good broader type in which the compiler can even
\n+
179 // perform our check.
\n+
180 if (value < 0)
\n+\n+
182 "Casting negative value to unsigned type: "sv, description)};
\n+
183 }
\n+
184 }
\n+
185 else
\n+
186 {
\n+
187 // No need to check: the value is unsigned so can't fall below the range
\n+
188 // of the TO type.
\n+
189 }
\n+
190
\n+
191 if constexpr (std::is_integral_v<FROM>)
\n+
192 {
\n+
193 using unsigned_from = std::make_unsigned_t<FROM>;
\n+
194 using unsigned_to = std::make_unsigned_t<TO>;
\n+
195 constexpr auto from_max{static_cast<unsigned_from>((from_limits::max)())};
\n+
196 constexpr auto to_max{static_cast<unsigned_to>((to_limits::max)())};
\n+
197 if constexpr (from_max > to_max)
\n+
198 {
\n+
199 if (internal::cmp_greater(value, to_max))
\n+
200 throw range_error{internal::cat2("Cast overflow: "sv, description)};
\n+
201 }
\n+
202 }
\n+
203 else if constexpr ((from_limits::max)() > (to_limits::max)())
\n+
204 {
\n+
205 if (value > (to_limits::max)())
\n+
206 throw range_error{internal::cat2("Cast overflow: ", description)};
\n+
207 }
\n+
208
\n+
209 return static_cast<TO>(value);
\n+
210}
\n+
\n+
211
\n+
212
\n+
\n+
234inline PQXX_PRIVATE void check_version() noexcept
\n+
235{
\n+
236 // There is no particular reason to do this here in @ref connection, except
\n+
237 // to ensure that every meaningful libpqxx client will execute it. The call
\n+
238 // must be in the execution path somewhere or the compiler won't try to link
\n+
239 // it. We can't use it to initialise a global or class-static variable,
\n+
240 // because a smart compiler might resolve it at compile time.
\n+
241 //
\n+
242 // On the other hand, we don't want to make a useless function call too
\n+
243 // often for performance reasons. A local static variable is initialised
\n+
244 // only on the definition's first execution. Compilers will be well
\n+
245 // optimised for this behaviour, so there's a minimal one-time cost.
\n+
246 static auto const version_ok{internal::PQXX_VERSION_CHECK()};
\n+
247 ignore_unused(version_ok);
\n+
248}
\n+
\n+
249
\n+
250
\n+
252
\n+
\n+
254struct PQXX_LIBEXPORT thread_safety_model
\n+
255{
\n+
257 bool safe_libpq = false;
\n+
258
\n+
260
\n+
266 bool safe_kerberos = false;
\n+
267
\n+
269 std::string description;
\n+
270};
\n+
\n+
271
\n+
272
\n+
274[[nodiscard]] PQXX_LIBEXPORT thread_safety_model describe_thread_safety();
\n+
275
\n+
276
\n+
277#if defined(PQXX_HAVE_CONCEPTS)
\n+
278# define PQXX_POTENTIAL_BINARY_ARG pqxx::potential_binary
\n+
279#else
\n+
280# define PQXX_POTENTIAL_BINARY_ARG typename
\n+
281#endif
\n+
282
\n+
283
\n+
285
\n+
302template<PQXX_POTENTIAL_BINARY_ARG TYPE>
\n+
\n+
303std::basic_string_view<std::byte> binary_cast(TYPE const &data)
\n+
304{
\n+
305 static_assert(sizeof(value_type<TYPE>) == 1);
\n+
306 // C++20: Use std::as_bytes.
\n+
307 return {
\n+
308 reinterpret_cast<std::byte const *>(
\n+
309 const_cast<strip_t<decltype(*std::data(data))> const *>(
\n+
310 std::data(data))),
\n+
311 std::size(data)};
\n+
312}
\n+
\n+
313
\n+
314
\n+
315#if defined(PQXX_HAVE_CONCEPTS)
\n+
316template<typename CHAR>
\n+
317concept char_sized = (sizeof(CHAR) == 1);
\n+
318# define PQXX_CHAR_SIZED_ARG char_sized
\n+
319#else
\n+
320# define PQXX_CHAR_SIZED_ARG typename
\n+
321#endif
\n+
322
\n+
324
\n+
331template<PQXX_CHAR_SIZED_ARG CHAR, typename SIZE>
\n+
\n+
332std::basic_string_view<std::byte> binary_cast(CHAR const *data, SIZE size)
\n+
333{
\n+
334 static_assert(sizeof(CHAR) == 1);
\n+
335 return {
\n+
336 reinterpret_cast<std::byte const *>(data),
\n+
337 check_cast<std::size_t>(size, "binary data size")};
\n+
338}
\n+
\n+
339
\n+
340
\n+
342constexpr oid oid_none{0};
\n+
343} // namespace pqxx
\n+
344
\n+
345
\n+
347
\n+
356namespace pqxx::internal
\n+
357{
\n+
358using namespace std::literals;
\n+
359
\n+
360
\n+
362
\n+
\n+
366template<typename CHAR> inline constexpr bool is_digit(CHAR c) noexcept
\n+
367{
\n+
368 return (c >= '0') and (c <= '9');
\n+
369}
\n+
\n+
370
\n+
371
\n+
373
\n+
375[[nodiscard]] std::string
\n+
376describe_object(std::string_view class_name, std::string_view name);
\n+
377
\n+
378
\n+
380
\n+\n+
392 void const *old_guest, std::string_view old_class, std::string_view old_name,
\n+
393 void const *new_guest, std::string_view new_class,
\n+
394 std::string_view new_name);
\n+
395
\n+
396
\n+
398
\n+\n+
402 void const *old_guest, std::string_view old_class, std::string_view old_name,
\n+
403 void const *new_guest, std::string_view new_class,
\n+
404 std::string_view new_name);
\n+
405
\n+
406
\n+
408
\n+
\n+
411inline constexpr std::size_t size_esc_bin(std::size_t binary_bytes) noexcept
\n+
412{
\n+
413 return 2 + (2 * binary_bytes) + 1;
\n+
414}
\n+
\n+
415
\n+
416
\n+
418
\n+
\n+
420inline constexpr std::size_t size_unesc_bin(std::size_t escaped_bytes) noexcept
\n+
421{
\n+
422 return (escaped_bytes - 2) / 2;
\n+
423}
\n+
\n+
424
\n+
425
\n+
426// TODO: Use actual binary type for "data".
\n+
428
\n+
433void PQXX_LIBEXPORT
\n+
434esc_bin(std::basic_string_view<std::byte> binary_data, char buffer[]) noexcept;
\n+
435
\n+
436
\n+
438std::string PQXX_LIBEXPORT
\n+
439esc_bin(std::basic_string_view<std::byte> binary_data);
\n+
440
\n+
441
\n+
443void PQXX_LIBEXPORT
\n+
444unesc_bin(std::string_view escaped_data, std::byte buffer[]);
\n+
445
\n+
446
\n+
448std::basic_string<std::byte>
\n+
449 PQXX_LIBEXPORT unesc_bin(std::string_view escaped_data);
\n+
450
\n+
451
\n+
\n+
453template<typename T> auto ssize(T const &c)
\n+
454{
\n+
455#if pqxx_have_ssize
\n+
456 return std::ssize(c);
\n+
457#else
\n+
458 using signed_t = std::make_signed_t<decltype(std::size(c))>;
\n+
459 return static_cast<signed_t>(std::size(c));
\n+
460#endif // pqxx_have_ssize
\n+
461}
\n+
\n+
462
\n+
463
\n+
465
\n+
469template<typename RETURN, typename... ARGS>
\n+
470std::tuple<ARGS...> args_f(RETURN (&func)(ARGS...));
\n+
471
\n+
472
\n+
474
\n+
478template<typename RETURN, typename... ARGS>
\n+
479std::tuple<ARGS...> args_f(std::function<RETURN(ARGS...)> const &);
\n+
480
\n+
481
\n+
483
\n+
487template<typename CLASS, typename RETURN, typename... ARGS>
\n+
488std::tuple<ARGS...> member_args_f(RETURN (CLASS::*)(ARGS...));
\n+
489
\n+
490
\n+
492
\n+
496template<typename CLASS, typename RETURN, typename... ARGS>
\n+
497std::tuple<ARGS...> member_args_f(RETURN (CLASS::*)(ARGS...) const);
\n+
498
\n+
499
\n+
501
\n+
507template<typename CALLABLE>
\n+
508auto args_f(CALLABLE const &f)
\n+
509 -> decltype(member_args_f(&CALLABLE::operator()));
\n+
510
\n+
511
\n+
513template<typename CALLABLE>
\n+
514using args_t = decltype(args_f(std::declval<CALLABLE>()));
\n+
515
\n+
516
\n+
518
\n+
521template<typename... TYPES>
\n+
522std::tuple<strip_t<TYPES>...> strip_types(std::tuple<TYPES...> const &);
\n+
523
\n+
524
\n+
526template<typename... TYPES>
\n+
527using strip_types_t = decltype(strip_types(std::declval<TYPES...>()));
\n+
528
\n+
529
\n+
\n+
531inline constexpr char unescape_char(char escaped) noexcept
\n+
532{
\n+
533 switch (escaped)
\n+
534 {
\n+
535 case 'b': // Backspace.
\n+
536 PQXX_UNLIKELY return '\\b';
\n+
537 case 'f': // Form feed
\n+
538 PQXX_UNLIKELY return '\\f';
\n+
539 case 'n': // Line feed.
\n+
540 return '\\n';
\n+
541 case 'r': // Carriage return.
\n+
542 return '\\r';
\n+
543 case 't': // Horizontal tab.
\n+
544 return '\\t';
\n+
545 case 'v': // Vertical tab.
\n+
546 return '\\v';
\n+
547 default: break;
\n+
548 }
\n+
549 // Regular character ("self-escaped").
\n+
550 return escaped;
\n+
551}
\n+
\n+
552
\n+
553
\n+
554// C++20: std::span?
\n+
556template<std::size_t BYTES>
\n+
557char const *PQXX_COLD
\n+
\n+
558error_string(int err_num, std::array<char, BYTES> &buffer)
\n+
559{
\n+
560 // Not entirely clear whether strerror_s will be in std or global namespace.
\n+
561 using namespace std;
\n+
562
\n+
563#if defined(PQXX_HAVE_STERROR_S) || defined(PQXX_HAVE_STRERROR_R)
\n+
564# if defined(PQXX_HAVE_STRERROR_S)
\n+
565 auto const err_result{strerror_s(std::data(buffer), BYTES, err_num)};
\n+
566# else
\n+
567 auto const err_result{strerror_r(err_num, std::data(buffer), BYTES)};
\n+
568# endif
\n+
569 if constexpr (std::is_same_v<pqxx::strip_t<decltype(err_result)>, char *>)
\n+
570 {
\n+
571 // GNU version of strerror_r; returns the error string, which may or may
\n+
572 // not reside within buffer.
\n+
573 return err_result;
\n+
574 }
\n+
575 else
\n+
576 {
\n+
577 // Either strerror_s or POSIX strerror_r; returns an error code.
\n+
578 // Sorry for being lazy here: Not reporting error string for the case
\n+
579 // where we can't retrieve an error string.
\n+
580 if (err_result == 0)
\n+
581 return std::data(buffer);
\n+
582 else
\n+
583 return "Compound errors.";
\n+
584 }
\n+
585
\n+
586#else
\n+
587 // Fallback case, hopefully for no actual platforms out there.
\n+
588 pqxx::ignore_unused(err_num, buffer);
\n+
589 return "(No error information available.)";
\n+
590#endif
\n+
591}
\n+
\n+
592} // namespace pqxx::internal
\n+
593
\n+
594
\n+
\n+\n+
596{
\n+
598PQXX_LIBEXPORT void pqfreemem(void const *) noexcept;
\n+
599} // namespace pqxx::internal::pq
\n+
\n+
600#endif
\n+
The home of all libpqxx classes, functions, templates, etc.
Definition array.hxx:33
\n+
std::remove_cv_t< std::remove_reference_t< TYPE > > strip_t
Remove any constness, volatile, and reference-ness from a type.
Definition types.hxx:91
\n+
std::basic_string_view< std::byte > binary_cast(TYPE const &data)
Cast binary data to a type that libpqxx will recognise as binary.
Definition util.hxx:303
\n+
strip_t< decltype(*std::begin(std::declval< CONTAINER >()))> value_type
The type of a container's elements.
Definition types.hxx:107
\n+
void check_version() noexcept
Definition util.hxx:234
\n+
thread_safety_model describe_thread_safety()
Describe thread safety available in this build.
Definition util.cxx:33
\n+
constexpr void ignore_unused(T &&...) noexcept
Suppress compiler warning about an unused item.
Definition util.hxx:142
\n+
constexpr oid oid_none
The "null" oid.
Definition util.hxx:342
\n+
TO check_cast(FROM value, std::string_view description)
Cast a numeric value to another type, or throw if it underflows/overflows.
Definition util.hxx:151
\n+
Internal items for libpqxx' own use. Do not use these yourself.
Definition composite.hxx:84
\n+
void unesc_bin(std::string_view escaped_data, std::byte buffer[])
Reconstitute binary data from its escaped version.
Definition util.cxx:158
\n+
int PQXX_VERSION_CHECK() noexcept
Library version check stub.
Definition version.cxx:23
\n+
char const *PQXX_COLD error_string(int err_num, std::array< char, BYTES > &buffer)
Get error string for a given errno value.
Definition util.hxx:558
\n+
void esc_bin(std::basic_string_view< std::byte > binary_data, char buffer[]) noexcept
Hex-escape binary data into a buffer.
Definition util.cxx:126
\n+
constexpr std::size_t size_esc_bin(std::size_t binary_bytes) noexcept
Compute buffer size needed to escape binary data for use as a BYTEA.
Definition util.hxx:411
\n+
std::tuple< ARGS... > member_args_f(RETURN(CLASS::*)(ARGS...))
Helper for determining a member function's parameter types.
\n+
constexpr bool cmp_less(LEFT lhs, RIGHT rhs) noexcept
Same as std::cmp_less, or a workaround where that's not available.
Definition util.hxx:63
\n+
void check_unique_unregister(void const *old_guest, std::string_view old_class, std::string_view old_name, void const *new_guest, std::string_view new_class, std::string_view new_name)
Like check_unique_register, but for un-registering a guest.
Definition util.cxx:78
\n+
decltype(strip_types(std::declval< TYPES... >())) strip_types_t
Take a tuple type and apply strip_t to its component types.
Definition util.hxx:527
\n+
void check_unique_register(void const *old_guest, std::string_view old_class, std::string_view old_name, void const *new_guest, std::string_view new_class, std::string_view new_name)
Check validity of registering a new "guest" in a "host.".
Definition util.cxx:61
\n+
std::tuple< strip_t< TYPES >... > strip_types(std::tuple< TYPES... > const &)
Helper: Apply strip_t to each of a tuple type's component types.
\n+
std::string describe_object(std::string_view class_name, std::string_view name)
Describe an object for humans, based on class name and optional name.
Definition util.cxx:51
\n+
std::tuple< ARGS... > args_f(RETURN(&func)(ARGS...))
Helper for determining a function's parameter types.
\n+
constexpr bool cmp_greater(LEFT lhs, RIGHT rhs) noexcept
C++20 std::cmp_greater, or workaround if not available.
Definition util.hxx:85
\n+
decltype(args_f(std::declval< CALLABLE >())) args_t
A callable's parameter types, as a tuple.
Definition util.hxx:514
\n+
constexpr bool is_digit(CHAR c) noexcept
A safer and more generic replacement for std::isdigit.
Definition util.hxx:366
\n+
constexpr char unescape_char(char escaped) noexcept
Return original byte for escaped character.
Definition util.hxx:531
\n+
constexpr bool cmp_greater_equal(LEFT lhs, RIGHT rhs) noexcept
C++20 std::cmp_greater_equal, or workaround if not available.
Definition util.hxx:111
\n+
std::string cat2(std::string_view x, std::string_view y)
Efficiently concatenate two strings.
Definition util.hxx:125
\n+
constexpr bool cmp_less_equal(LEFT lhs, RIGHT rhs) noexcept
C++20 std::cmp_less_equal, or workaround if not available.
Definition util.hxx:98
\n+
auto ssize(T const &c)
Transitional: std::ssize(), or custom implementation if not available.
Definition util.hxx:453
\n+
constexpr std::size_t size_unesc_bin(std::size_t escaped_bytes) noexcept
Compute binary size from the size of its escaped version.
Definition util.hxx:420
\n+
Definition util.hxx:596
\n+
void pqfreemem(void const *) noexcept
Wrapper for PQfreemem(), with C++ linkage.
Definition util.cxx:199
\n+
Something is out of range, similar to std::out_of_range.
Definition except.hxx:326
\n+
Descriptor of library's thread-safety model.
Definition util.hxx:255
\n+
std::string description
A human-readable description of any thread-safety issues.
Definition util.hxx:269
\n
\n
\n \n
\n \n
\n \n \n", "details": [{"source1": "html2text {}", "source2": "html2text {}", "unified_diff": "@@ -1,129 +1,622 @@\n \n \n \n \n \n libpqxx\u00a07.8.1\n \n-config.h\n- 1/* include/pqxx/config.h. Generated from config.h.in by configure. */\n- 2/* include/pqxx/config.h.in. Generated from configure.ac by autoheader. */\n- 3\n- 4/* Define to 1 if you have the header file. */\n- 5#define HAVE_DLFCN_H 1\n- 6\n- 7/* Define to 1 if you have the header file. */\n- 8#define HAVE_INTTYPES_H 1\n- 9\n- 10/* Define to 1 if you have the `pq' library (-lpq). */\n- 11#define HAVE_LIBPQ 1\n- 12\n- 13/* Define to 1 if you have the header file. */\n- 14#define HAVE_STDINT_H 1\n- 15\n- 16/* Define to 1 if you have the header file. */\n- 17#define HAVE_STDIO_H 1\n- 18\n- 19/* Define to 1 if you have the header file. */\n- 20#define HAVE_STDLIB_H 1\n- 21\n- 22/* Define to 1 if you have the header file. */\n- 23#define HAVE_STRINGS_H 1\n- 24\n- 25/* Define to 1 if you have the header file. */\n- 26#define HAVE_STRING_H 1\n- 27\n- 28/* Define to 1 if you have the header file. */\n- 29#define HAVE_SYS_STAT_H 1\n- 30\n- 31/* Define to 1 if you have the header file. */\n- 32#define HAVE_SYS_TYPES_H 1\n- 33\n- 34/* Define to 1 if you have the header file. */\n- 35#define HAVE_UNISTD_H 1\n- 36\n- 37/* Define to the sub-directory where libtool stores uninstalled libraries.\n-*/\n- 38#define LT_OBJDIR \".libs/\"\n+util.hxx\n+ 1/* Various utility definitions for libpqxx.\n+ 2 *\n+ 3 * DO NOT INCLUDE THIS FILE DIRECTLY; include pqxx/util instead.\n+ 4 *\n+ 5 * Copyright (c) 2000-2023, Jeroen T. Vermeulen.\n+ 6 *\n+ 7 * See COPYING for copyright license. If you did not receive a file called\n+ 8 * COPYING with this source code, please notify the distributor of this\n+ 9 * mistake, or contact the author.\n+ 10 */\n+ 11#ifndef PQXX_H_UTIL\n+ 12#define PQXX_H_UTIL\n+ 13\n+ 14#if !defined(PQXX_HEADER_PRE)\n+ 15# error \"Include libpqxx headers as , not .\"\n+ 16#endif\n+ 17\n+ 18#include \n+ 19#include \n+ 20#include \n+ 21#include \n+ 22#include \n+ 23#include \n+ 24#include \n+ 25#include \n+ 26#include \n+ 27#include \n+ 28#include \n+ 29#include \n+ 30#include \n+ 31#include \n+ 32#include \n+ 33#include \n+ 34\n+ 35#include \"pqxx/except.hxx\"\n+ 36#include \"pqxx/types.hxx\"\n+ 37#include \"pqxx/version.hxx\"\n+ 38\n 39\n- 40/* Name of package */\n- 41#define PACKAGE \"libpqxx\"\n- 42\n- 43/* Define to the address where bug reports for this package should be sent.\n-*/\n- 44#define PACKAGE_BUGREPORT \"Jeroen T. Vermeulen\"\n+ 41namespace pqxx\n+ 42{}\n+ 43\n+ 44#include \n 45\n- 46/* Define to the full name of this package. */\n- 47#define PACKAGE_NAME \"libpqxx\"\n- 48\n- 49/* Define to the full name and version of this package. */\n- 50#define PACKAGE_STRING \"libpqxx 7.8.1\"\n- 51\n- 52/* Define to the one symbol short name of this package. */\n- 53#define PACKAGE_TARNAME \"libpqxx\"\n+ 46\n+ 47// C++23: Retire wrapper.\n+ 48#if pqxx_have_unreachable\n+ 50# define PQXX_UNREACHABLE std::unreachable()\n+ 51#else\n+ 52# define PQXX_UNREACHABLE assert(false)\n+ 53#endif\n 54\n- 55/* Define to the home page for this package. */\n- 56#define PACKAGE_URL \"\"\n- 57\n- 58/* Define to the version of this package. */\n- 59#define PACKAGE_VERSION \"7.8.1\"\n- 60\n- 61/* Define if supports floating-point conversion. */\n- 62#define PQXX_HAVE_CHARCONV_FLOAT 1\n- 63\n- 64/* Define if supports integer conversion. */\n- 65#define PQXX_HAVE_CHARCONV_INT 1\n- 66\n- 67/* Define if compiler has C++20 std::cmp_greater etc. */\n- 68/* #undef PQXX_HAVE_CMP */\n- 69\n- 70/* Define if compiler supports Concepts and header. */\n- 71/* #undef PQXX_HAVE_CONCEPTS */\n- 72\n- 73/* Define if compiler supports __cxa_demangle */\n- 74#define PQXX_HAVE_CXA_DEMANGLE 1\n- 75\n- 76/* Define if g++ supports pure attribute */\n- 77#define PQXX_HAVE_GCC_PURE 1\n- 78\n- 79/* Define if g++ supports visibility attribute. */\n- 80#define PQXX_HAVE_GCC_VISIBILITY 1\n+ 55\n+ 57namespace pqxx::internal\n+ 58{\n+ 59\n+ 60// C++20: Retire wrapper.\n+ 62template\n+63inline constexpr bool cmp_less(LEFT lhs, RIGHT rhs) noexcept\n+ 64{\n+ 65#if defined(PQXX_HAVE_CMP)\n+ 66 return std::cmp_less(lhs, rhs);\n+ 67#else\n+ 68 // We need a variable just because lgtm.com gives off a false positive\n+ 69 // warning when we compare the values directly. It considers that a\n+ 70 // \"self-comparison.\"\n+ 71 constexpr bool left_signed{std::is_signed_v};\n+ 72 if constexpr (left_signed == std::is_signed_v)\n+ 73 return lhs < rhs;\n+ 74 else if constexpr (std::is_signed_v)\n+ 75 return (lhs <= 0) ? true : (std::make_unsigned_t(lhs) < rhs);\n+ 76 else\n+ 77 return (rhs <= 0) ? false : (lhs < std::make_unsigned_t(rhs));\n+ 78#endif\n+ 79}\n+ 80\n 81\n- 82/* Define if likely & unlikely work. */\n- 83/* #undef PQXX_HAVE_LIKELY */\n- 84\n- 85/* Define if compiler has usable std::filesystem::path. */\n- 86#define PQXX_HAVE_PATH 1\n- 87\n- 88/* Define if poll() is available. */\n- 89#define PQXX_HAVE_POLL 1\n- 90\n- 91/* Define if std::this_thread::sleep_for works. */\n- 92#define PQXX_HAVE_SLEEP_FOR 1\n+ 82// C++20: Retire wrapper.\n+ 84template\n+85inline constexpr bool cmp_greater(LEFT lhs, RIGHT rhs) noexcept\n+ 86{\n+ 87#if defined(PQXX_HAVE_CMP)\n+ 88 return std::cmp_greater(lhs, rhs);\n+ 89#else\n+ 90 return cmp_less(rhs, lhs);\n+ 91#endif\n+ 92}\n 93\n- 94/* Define if compiler has std::span. */\n- 95/* #undef PQXX_HAVE_SPAN */\n- 96\n- 97/* Define if strerror_r() is available. */\n- 98#define PQXX_HAVE_STRERROR_R 1\n- 99\n- 100/* Define if strerror_s() is available. */\n- 101/* #undef PQXX_HAVE_STRERROR_S */\n- 102\n- 103/* Define if thread_local is fully supported. */\n- 104#define PQXX_HAVE_THREAD_LOCAL 1\n- 105\n- 106/* Define if std::chrono has year_month_day etc. */\n- 107/* #undef PQXX_HAVE_YEAR_MONTH_DAY */\n- 108\n- 109/* Define to 1 if all of the C90 standard headers exist (not just the ones\n- 110 required in a freestanding environment). This macro is provided for\n- 111 backward compatibility; new code need not use it. */\n- 112#define STDC_HEADERS 1\n- 113\n- 114/* Version number of package */\n- 115#define VERSION \"7.8.1\"\n+ 94\n+ 95// C++20: Retire wrapper.\n+ 97template\n+98inline constexpr bool cmp_less_equal(LEFT lhs, RIGHT rhs) noexcept\n+ 99{\n+ 100#if defined(PQXX_HAVE_CMP)\n+ 101 return std::cmp_less_equal(lhs, rhs);\n+ 102#else\n+ 103 return not cmp_less(rhs, lhs);\n+ 104#endif\n+ 105}\n+ 106\n+ 107\n+ 108// C++20: Retire wrapper.\n+ 110template\n+111inline constexpr bool cmp_greater_equal(LEFT lhs, RIGHT rhs) noexcept\n+ 112{\n+ 113#if defined(PQXX_HAVE_CMP)\n+ 114 return std::cmp_greater_equal(lhs, rhs);\n+ 115#else\n+ 116 return not cmp_less(lhs, rhs);\n+ 117#endif\n+ 118}\n+ 119\n+ 120\n+ 122\n+125[[nodiscard]] inline std::string cat2(std::string_view x, std::string_view\n+y)\n+ 126{\n+ 127 std::string buf;\n+ 128 auto const xs{std::size(x)}, ys{std::size(y)};\n+ 129 buf.resize(xs + ys);\n+ 130 x.copy(std::data(buf), xs);\n+ 131 y.copy(std::data(buf) + xs, ys);\n+ 132 return buf;\n+ 133}\n+ 134} // namespace pqxx::internal\n+ 135\n+ 136\n+ 137namespace pqxx\n+ 138{\n+ 139using namespace std::literals;\n+ 140\n+142template inline constexpr void ignore_unused(T &&...)\n+noexcept\n+ 143{}\n+ 144\n+ 145\n+ 147\n+ 150template\n+151inline TO check_cast(FROM value, std::string_view description)\n+ 152{\n+ 153 static_assert(std::is_arithmetic_v);\n+ 154 static_assert(std::is_arithmetic_v);\n+ 155 static_assert(std::is_integral_v == std::is_integral_v);\n+ 156\n+ 157 // The rest of this code won't quite work for bool, but bool is trivially\n+ 158 // convertible to other arithmetic types as far as I can see.\n+ 159 if constexpr (std::is_same_v)\n+ 160 return static_cast(value);\n+ 161\n+ 162 // Depending on our \"if constexpr\" conditions, this parameter may not be\n+ 163 // needed. Some compilers will warn.\n+ 164 ignore_unused(description);\n+ 165\n+ 166 using from_limits = std::numeric_limits;\n+ 167 using to_limits = std::numeric_limits;\n+ 168 if constexpr (std::is_signed_v)\n+ 169 {\n+ 170 if constexpr (std::is_signed_v)\n+ 171 {\n+ 172 if (value < to_limits::lowest())\n+ 173 throw range_error{internal::cat2(\"Cast underflow: \"sv, description)};\n+ 174 }\n+ 175 else\n+ 176 {\n+ 177 // FROM is signed, but TO is not. Treat this as a special case, because\n+ 178 // there may not be a good broader type in which the compiler can even\n+ 179 // perform our check.\n+ 180 if (value < 0)\n+ 181 throw range_error{internal::cat2(\n+ 182 \"Casting negative value to unsigned type: \"sv, description)};\n+ 183 }\n+ 184 }\n+ 185 else\n+ 186 {\n+ 187 // No need to check: the value is unsigned so can't fall below the range\n+ 188 // of the TO type.\n+ 189 }\n+ 190\n+ 191 if constexpr (std::is_integral_v)\n+ 192 {\n+ 193 using unsigned_from = std::make_unsigned_t;\n+ 194 using unsigned_to = std::make_unsigned_t;\n+ 195 constexpr auto from_max{static_cast((from_limits::max)())};\n+ 196 constexpr auto to_max{static_cast((to_limits::max)())};\n+ 197 if constexpr (from_max > to_max)\n+ 198 {\n+ 199 if (internal::cmp_greater(value, to_max))\n+ 200 throw range_error{internal::cat2(\"Cast overflow: \"sv, description)};\n+ 201 }\n+ 202 }\n+ 203 else if constexpr ((from_limits::max)() > (to_limits::max)())\n+ 204 {\n+ 205 if (value > (to_limits::max)())\n+ 206 throw range_error{internal::cat2(\"Cast overflow: \", description)};\n+ 207 }\n+ 208\n+ 209 return static_cast(value);\n+ 210}\n+ 211\n+ 212\n+234inline PQXX_PRIVATE void check_version() noexcept\n+ 235{\n+ 236 // There is no particular reason to do this here in @ref connection,\n+except\n+ 237 // to ensure that every meaningful libpqxx client will execute it. The\n+call\n+ 238 // must be in the execution path somewhere or the compiler won't try to\n+link\n+ 239 // it. We can't use it to initialise a global or class-static variable,\n+ 240 // because a smart compiler might resolve it at compile time.\n+ 241 //\n+ 242 // On the other hand, we don't want to make a useless function call too\n+ 243 // often for performance reasons. A local static variable is initialised\n+ 244 // only on the definition's first execution. Compilers will be well\n+ 245 // optimised for this behaviour, so there's a minimal one-time cost.\n+ 246 static auto const version_ok{internal::PQXX_VERSION_CHECK()};\n+ 247 ignore_unused(version_ok);\n+ 248}\n+ 249\n+ 250\n+ 252\n+254struct PQXX_LIBEXPORT thread_safety_model\n+ 255{\n+257 bool safe_libpq = false;\n+ 258\n+ 260\n+266 bool safe_kerberos = false;\n+ 267\n+269 std::string description;\n+ 270};\n+ 271\n+ 272\n+ 274[[nodiscard]] PQXX_LIBEXPORT thread_safety_model describe_thread_safety();\n+ 275\n+ 276\n+ 277#if defined(PQXX_HAVE_CONCEPTS)\n+ 278# define PQXX_POTENTIAL_BINARY_ARG pqxx::potential_binary\n+ 279#else\n+ 280# define PQXX_POTENTIAL_BINARY_ARG typename\n+ 281#endif\n+ 282\n+ 283\n+ 285\n+ 302template\n+303std::basic_string_view binary_cast(TYPE const &data)\n+ 304{\n+ 305 static_assert(sizeof(value_type) == 1);\n+ 306 // C++20: Use std::as_bytes.\n+ 307 return {\n+ 308 reinterpret_cast(\n+ 309 const_cast const *>(\n+ 310 std::data(data))),\n+ 311 std::size(data)};\n+ 312}\n+ 313\n+ 314\n+ 315#if defined(PQXX_HAVE_CONCEPTS)\n+ 316template\n+ 317concept char_sized = (sizeof(CHAR) == 1);\n+ 318# define PQXX_CHAR_SIZED_ARG char_sized\n+ 319#else\n+ 320# define PQXX_CHAR_SIZED_ARG typename\n+ 321#endif\n+ 322\n+ 324\n+ 331template\n+332std::basic_string_view binary_cast(CHAR const *data, SIZE size)\n+ 333{\n+ 334 static_assert(sizeof(CHAR) == 1);\n+ 335 return {\n+ 336 reinterpret_cast(data),\n+ 337 check_cast(size, \"binary data size\")};\n+ 338}\n+ 339\n+ 340\n+342constexpr oid oid_none{0};\n+ 343} // namespace pqxx\n+ 344\n+ 345\n+ 347\n+ 356namespace pqxx::internal\n+ 357{\n+ 358using namespace std::literals;\n+ 359\n+ 360\n+ 362\n+366template inline constexpr bool is_digit(CHAR c) noexcept\n+ 367{\n+ 368 return (c >= '0') and (c <= '9');\n+ 369}\n+ 370\n+ 371\n+ 373\n+ 375[[nodiscard]] std::string\n+ 376describe_object(std::string_view class_name, std::string_view name);\n+ 377\n+ 378\n+ 380\n+ 391void check_unique_register(\n+ 392 void const *old_guest, std::string_view old_class, std::string_view\n+old_name,\n+ 393 void const *new_guest, std::string_view new_class,\n+ 394 std::string_view new_name);\n+ 395\n+ 396\n+ 398\n+ 401void check_unique_unregister(\n+ 402 void const *old_guest, std::string_view old_class, std::string_view\n+old_name,\n+ 403 void const *new_guest, std::string_view new_class,\n+ 404 std::string_view new_name);\n+ 405\n+ 406\n+ 408\n+411inline constexpr std::size_t size_esc_bin(std::size_t binary_bytes) noexcept\n+ 412{\n+ 413 return 2 + (2 * binary_bytes) + 1;\n+ 414}\n+ 415\n+ 416\n+ 418\n+420inline constexpr std::size_t size_unesc_bin(std::size_t escaped_bytes)\n+noexcept\n+ 421{\n+ 422 return (escaped_bytes - 2) / 2;\n+ 423}\n+ 424\n+ 425\n+ 426// TODO: Use actual binary type for \"data\".\n+ 428\n+ 433void PQXX_LIBEXPORT\n+ 434esc_bin(std::basic_string_view binary_data, char buffer[])\n+noexcept;\n+ 435\n+ 436\n+ 438std::string PQXX_LIBEXPORT\n+ 439esc_bin(std::basic_string_view binary_data);\n+ 440\n+ 441\n+ 443void PQXX_LIBEXPORT\n+ 444unesc_bin(std::string_view escaped_data, std::byte buffer[]);\n+ 445\n+ 446\n+ 448std::basic_string\n+ 449 PQXX_LIBEXPORT unesc_bin(std::string_view escaped_data);\n+ 450\n+ 451\n+453template auto ssize(T const &c)\n+ 454{\n+ 455#if pqxx_have_ssize\n+ 456 return std::ssize(c);\n+ 457#else\n+ 458 using signed_t = std::make_signed_t;\n+ 459 return static_cast(std::size(c));\n+ 460#endif // pqxx_have_ssize\n+ 461}\n+ 462\n+ 463\n+ 465\n+ 469template\n+470std::tuple args_f(RETURN (&func)(ARGS...));\n+ 471\n+ 472\n+ 474\n+ 478template\n+479std::tuple args_f(std::function const &);\n+ 480\n+ 481\n+ 483\n+ 487template\n+488std::tuple member_args_f(RETURN (CLASS::*)(ARGS...));\n+ 489\n+ 490\n+ 492\n+ 496template\n+ 497std::tuple member_args_f(RETURN (CLASS::*)(ARGS...) const);\n+ 498\n+ 499\n+ 501\n+ 507template\n+508auto args_f(CALLABLE const &f)\n+ 509 -> decltype(member_args_f(&CALLABLE::operator()));\n+ 510\n+ 511\n+ 513template\n+514using args_t = decltype(args_f(std::declval()));\n+ 515\n+ 516\n+ 518\n+ 521template\n+522std::tuple...> strip_types(std::tuple const &);\n+ 523\n+ 524\n+ 526template\n+527using strip_types_t = decltype(strip_types(std::declval()));\n+ 528\n+ 529\n+531inline constexpr char unescape_char(char escaped) noexcept\n+ 532{\n+ 533 switch (escaped)\n+ 534 {\n+ 535 case 'b': // Backspace.\n+ 536 PQXX_UNLIKELY return '\\b';\n+ 537 case 'f': // Form feed\n+ 538 PQXX_UNLIKELY return '\\f';\n+ 539 case 'n': // Line feed.\n+ 540 return '\\n';\n+ 541 case 'r': // Carriage return.\n+ 542 return '\\r';\n+ 543 case 't': // Horizontal tab.\n+ 544 return '\\t';\n+ 545 case 'v': // Vertical tab.\n+ 546 return '\\v';\n+ 547 default: break;\n+ 548 }\n+ 549 // Regular character (\"self-escaped\").\n+ 550 return escaped;\n+ 551}\n+ 552\n+ 553\n+ 554// C++20: std::span?\n+ 556template\n+ 557char const *PQXX_COLD\n+558error_string(int err_num, std::array &buffer)\n+ 559{\n+ 560 // Not entirely clear whether strerror_s will be in std or global\n+namespace.\n+ 561 using namespace std;\n+ 562\n+ 563#if defined(PQXX_HAVE_STERROR_S) || defined(PQXX_HAVE_STRERROR_R)\n+ 564# if defined(PQXX_HAVE_STRERROR_S)\n+ 565 auto const err_result{strerror_s(std::data(buffer), BYTES, err_num)};\n+ 566# else\n+ 567 auto const err_result{strerror_r(err_num, std::data(buffer), BYTES)};\n+ 568# endif\n+ 569 if constexpr (std::is_same_v, char *>)\n+ 570 {\n+ 571 // GNU version of strerror_r; returns the error string, which may or may\n+ 572 // not reside within buffer.\n+ 573 return err_result;\n+ 574 }\n+ 575 else\n+ 576 {\n+ 577 // Either strerror_s or POSIX strerror_r; returns an error code.\n+ 578 // Sorry for being lazy here: Not reporting error string for the case\n+ 579 // where we can't retrieve an error string.\n+ 580 if (err_result == 0)\n+ 581 return std::data(buffer);\n+ 582 else\n+ 583 return \"Compound errors.\";\n+ 584 }\n+ 585\n+ 586#else\n+ 587 // Fallback case, hopefully for no actual platforms out there.\n+ 588 pqxx::ignore_unused(err_num, buffer);\n+ 589 return \"(No error information available.)\";\n+ 590#endif\n+ 591}\n+ 592} // namespace pqxx::internal\n+ 593\n+ 594\n+595namespace pqxx::internal::pq\n+ 596{\n+ 598PQXX_LIBEXPORT void pqfreemem(void const *) noexcept;\n+ 599} // namespace pqxx::internal::pq\n+ 600#endif\n+pqxx\n+The home of all libpqxx classes, functions, templates, etc.\n+Definition array.hxx:33\n+pqxx::strip_t\n+std::remove_cv_t< std::remove_reference_t< TYPE > > strip_t\n+Remove any constness, volatile, and reference-ness from a type.\n+Definition types.hxx:91\n+pqxx::binary_cast\n+std::basic_string_view< std::byte > binary_cast(TYPE const &data)\n+Cast binary data to a type that libpqxx will recognise as binary.\n+Definition util.hxx:303\n+pqxx::value_type\n+strip_t< decltype(*std::begin(std::declval< CONTAINER >()))> value_type\n+The type of a container's elements.\n+Definition types.hxx:107\n+pqxx::check_version\n+void check_version() noexcept\n+Definition util.hxx:234\n+pqxx::describe_thread_safety\n+thread_safety_model describe_thread_safety()\n+Describe thread safety available in this build.\n+Definition util.cxx:33\n+pqxx::ignore_unused\n+constexpr void ignore_unused(T &&...) noexcept\n+Suppress compiler warning about an unused item.\n+Definition util.hxx:142\n+pqxx::oid_none\n+constexpr oid oid_none\n+The \"null\" oid.\n+Definition util.hxx:342\n+pqxx::check_cast\n+TO check_cast(FROM value, std::string_view description)\n+Cast a numeric value to another type, or throw if it underflows/overflows.\n+Definition util.hxx:151\n+pqxx::internal\n+Internal items for libpqxx' own use. Do not use these yourself.\n+Definition composite.hxx:84\n+pqxx::internal::unesc_bin\n+void unesc_bin(std::string_view escaped_data, std::byte buffer[])\n+Reconstitute binary data from its escaped version.\n+Definition util.cxx:158\n+pqxx::internal::PQXX_VERSION_CHECK\n+int PQXX_VERSION_CHECK() noexcept\n+Library version check stub.\n+Definition version.cxx:23\n+pqxx::internal::error_string\n+char const *PQXX_COLD error_string(int err_num, std::array< char, BYTES >\n+&buffer)\n+Get error string for a given errno value.\n+Definition util.hxx:558\n+pqxx::internal::esc_bin\n+void esc_bin(std::basic_string_view< std::byte > binary_data, char buffer[])\n+noexcept\n+Hex-escape binary data into a buffer.\n+Definition util.cxx:126\n+pqxx::internal::size_esc_bin\n+constexpr std::size_t size_esc_bin(std::size_t binary_bytes) noexcept\n+Compute buffer size needed to escape binary data for use as a BYTEA.\n+Definition util.hxx:411\n+pqxx::internal::member_args_f\n+std::tuple< ARGS... > member_args_f(RETURN(CLASS::*)(ARGS...))\n+Helper for determining a member function's parameter types.\n+pqxx::internal::cmp_less\n+constexpr bool cmp_less(LEFT lhs, RIGHT rhs) noexcept\n+Same as std::cmp_less, or a workaround where that's not available.\n+Definition util.hxx:63\n+pqxx::internal::check_unique_unregister\n+void check_unique_unregister(void const *old_guest, std::string_view old_class,\n+std::string_view old_name, void const *new_guest, std::string_view new_class,\n+std::string_view new_name)\n+Like check_unique_register, but for un-registering a guest.\n+Definition util.cxx:78\n+pqxx::internal::strip_types_t\n+decltype(strip_types(std::declval< TYPES... >())) strip_types_t\n+Take a tuple type and apply strip_t to its component types.\n+Definition util.hxx:527\n+pqxx::internal::check_unique_register\n+void check_unique_register(void const *old_guest, std::string_view old_class,\n+std::string_view old_name, void const *new_guest, std::string_view new_class,\n+std::string_view new_name)\n+Check validity of registering a new \"guest\" in a \"host.\".\n+Definition util.cxx:61\n+pqxx::internal::strip_types\n+std::tuple< strip_t< TYPES >... > strip_types(std::tuple< TYPES... > const &)\n+Helper: Apply strip_t to each of a tuple type's component types.\n+pqxx::internal::describe_object\n+std::string describe_object(std::string_view class_name, std::string_view name)\n+Describe an object for humans, based on class name and optional name.\n+Definition util.cxx:51\n+pqxx::internal::args_f\n+std::tuple< ARGS... > args_f(RETURN(&func)(ARGS...))\n+Helper for determining a function's parameter types.\n+pqxx::internal::cmp_greater\n+constexpr bool cmp_greater(LEFT lhs, RIGHT rhs) noexcept\n+C++20 std::cmp_greater, or workaround if not available.\n+Definition util.hxx:85\n+pqxx::internal::args_t\n+decltype(args_f(std::declval< CALLABLE >())) args_t\n+A callable's parameter types, as a tuple.\n+Definition util.hxx:514\n+pqxx::internal::is_digit\n+constexpr bool is_digit(CHAR c) noexcept\n+A safer and more generic replacement for std::isdigit.\n+Definition util.hxx:366\n+pqxx::internal::unescape_char\n+constexpr char unescape_char(char escaped) noexcept\n+Return original byte for escaped character.\n+Definition util.hxx:531\n+pqxx::internal::cmp_greater_equal\n+constexpr bool cmp_greater_equal(LEFT lhs, RIGHT rhs) noexcept\n+C++20 std::cmp_greater_equal, or workaround if not available.\n+Definition util.hxx:111\n+pqxx::internal::cat2\n+std::string cat2(std::string_view x, std::string_view y)\n+Efficiently concatenate two strings.\n+Definition util.hxx:125\n+pqxx::internal::cmp_less_equal\n+constexpr bool cmp_less_equal(LEFT lhs, RIGHT rhs) noexcept\n+C++20 std::cmp_less_equal, or workaround if not available.\n+Definition util.hxx:98\n+pqxx::internal::ssize\n+auto ssize(T const &c)\n+Transitional: std::ssize(), or custom implementation if not available.\n+Definition util.hxx:453\n+pqxx::internal::size_unesc_bin\n+constexpr std::size_t size_unesc_bin(std::size_t escaped_bytes) noexcept\n+Compute binary size from the size of its escaped version.\n+Definition util.hxx:420\n+pqxx::internal::pq\n+Definition util.hxx:596\n+pqxx::internal::pq::pqfreemem\n+void pqfreemem(void const *) noexcept\n+Wrapper for PQfreemem(), with C++ linkage.\n+Definition util.cxx:199\n+pqxx::range_error\n+Something is out of range, similar to std::out_of_range.\n+Definition except.hxx:326\n+pqxx::thread_safety_model\n+Descriptor of library's thread-safety model.\n+Definition util.hxx:255\n+pqxx::thread_safety_model::description\n+std::string description\n+A human-readable description of any thread-safety issues.\n+Definition util.hxx:269\n * include\n * pqxx\n- * config.h\n+ * util.hxx\n * Generated by [doxygen] 1.9.8\n"}]}, {"source1": "./usr/share/doc/libpqxx-doc/html/a00086_source.html", "source2": "./usr/share/doc/libpqxx-doc/html/a00086_source.html", "unified_diff": "@@ -1,15 +1,15 @@\n \n \n \n \n \n \n \n-libpqxx: separated_list.hxx Source File\n+libpqxx: version.hxx Source File\n \n \n \n \n \n \n \n@@ -60,165 +60,54 @@\n \n
\n
\n-
separated_list.hxx
\n+
version.hxx
\n
\n
\n-
1/* Helper similar to Python's `str.join()`.
\n+
1/* Version info for libpqxx.
\n
2 *
\n-
3 * DO NOT INCLUDE THIS FILE DIRECTLY; include pqxx/separated_list instead.
\n+
3 * DO NOT INCLUDE THIS FILE DIRECTLY; include pqxx/version instead.
\n
4 *
\n
5 * Copyright (c) 2000-2023, Jeroen T. Vermeulen.
\n
6 *
\n
7 * See COPYING for copyright license. If you did not receive a file called
\n
8 * COPYING with this source code, please notify the distributor of this
\n
9 * mistake, or contact the author.
\n
10 */
\n-
11#ifndef PQXX_H_SEPARATED_LIST
\n-
12#define PQXX_H_SEPARATED_LIST
\n+
11#if !defined(PQXX_H_VERSION)
\n+
12# define PQXX_H_VERSION
\n
13
\n-
14#if !defined(PQXX_HEADER_PRE)
\n-
15# error "Include libpqxx headers as <pqxx/header>, not <pqxx/header.hxx>."
\n-
16#endif
\n+
14# if !defined(PQXX_HEADER_PRE)
\n+
15# error "Include libpqxx headers as <pqxx/header>, not <pqxx/header.hxx>."
\n+
16# endif
\n
17
\n-
18#include <algorithm>
\n-
19#include <numeric>
\n-
20
\n-
21#include "pqxx/strconv.hxx"
\n+
19# define PQXX_VERSION "7.8.1"
\n+
21# define PQXX_ABI "7.8"
\n
22
\n-
23// C++20: Simplify using std::ranges::range.
\n-
24// C++20: Optimise buffer allocation using random_access_range/iterator.
\n-
25// TODO: Can we pass separators at compile time?
\n-
26namespace pqxx
\n-
27{
\n-
32
\n-
34
\n-
42template<typename ITER, typename ACCESS>
\n-
43[[nodiscard]] inline std::string
\n-
\n-
44separated_list(std::string_view sep, ITER begin, ITER end, ACCESS access)
\n-
45{
\n-
46 if (end == begin)
\n-
47 return {};
\n-
48 auto next{begin};
\n-
49 ++next;
\n-
50 if (next == end)
\n-
51 return to_string(access(begin));
\n-
52
\n-
53 // From here on, we've got at least 2 elements -- meaning that we need sep.
\n-
54 using elt_type = strip_t<decltype(access(begin))>;
\n-
55 using traits = string_traits<elt_type>;
\n-
56
\n-
57 std::size_t budget{0};
\n-
58 for (ITER cnt{begin}; cnt != end; ++cnt)
\n-
59 budget += traits::size_buffer(access(cnt));
\n-
60 budget +=
\n-
61 static_cast<std::size_t>(std::distance(begin, end)) * std::size(sep);
\n-
62
\n-
63 std::string result;
\n-
64 result.resize(budget);
\n-
65
\n-
66 char *const data{result.data()};
\n-
67 char *here{data};
\n-
68 char *stop{data + budget};
\n-
69 here = traits::into_buf(here, stop, access(begin)) - 1;
\n-
70 for (++begin; begin != end; ++begin)
\n-
71 {
\n-
72 here += sep.copy(here, std::size(sep));
\n-
73 here = traits::into_buf(here, stop, access(begin)) - 1;
\n-
74 }
\n-
75 result.resize(static_cast<std::size_t>(here - data));
\n-
76 return result;
\n-
77}
\n-
\n-
78
\n-
79
\n-
81template<typename ITER>
\n-
82[[nodiscard]] inline std::string
\n-
\n-
83separated_list(std::string_view sep, ITER begin, ITER end)
\n-
84{
\n-
85 return separated_list(sep, begin, end, [](ITER i) { return *i; });
\n-
86}
\n-
\n-
87
\n-
88
\n-
89// C++20: Use a concept.
\n-
91template<typename CONTAINER>
\n-
92[[nodiscard]] inline auto
\n-
\n-
93separated_list(std::string_view sep, CONTAINER const &c)
\n-
94 /*
\n-
95 Always std::string; necessary because SFINAE doesn't work with the
\n-
96 contents of function bodies, so the check for iterability has to be in
\n-
97 the signature.
\n-
98 */
\n-
99 -> typename std::enable_if<
\n-
100 (not std::is_void<decltype(std::begin(c))>::value and
\n-
101 not std::is_void<decltype(std::end(c))>::value),
\n-
102 std::string>::type
\n-
103{
\n-
104 return separated_list(sep, std::begin(c), std::end(c));
\n-
105}
\n-
\n-
106
\n-
107
\n-
109template<
\n-
110 typename TUPLE, std::size_t INDEX = 0, typename ACCESS,
\n-
111 typename std::enable_if<
\n-
112 (INDEX == std::tuple_size<TUPLE>::value - 1), int>::type = 0>
\n-
\n-
113[[nodiscard]] inline std::string separated_list(
\n-
114 std::string_view /* sep */, TUPLE const &t, ACCESS const &access)
\n-
115{
\n-
116 return to_string(access(&std::get<INDEX>(t)));
\n-
117}
\n-
\n-
118
\n-
119template<
\n-
120 typename TUPLE, std::size_t INDEX = 0, typename ACCESS,
\n-
121 typename std::enable_if<
\n-
122 (INDEX < std::tuple_size<TUPLE>::value - 1), int>::type = 0>
\n-
123[[nodiscard]] inline std::string
\n-
124separated_list(std::string_view sep, TUPLE const &t, ACCESS const &access)
\n-
125{
\n-
126 std::string out{to_string(access(&std::get<INDEX>(t)))};
\n-
127 out.append(sep);
\n-
128 out.append(separated_list<TUPLE, INDEX + 1>(sep, t, access));
\n-
129 return out;
\n-
130}
\n-
131
\n-
132template<
\n-
133 typename TUPLE, std::size_t INDEX = 0,
\n-
134 typename std::enable_if<
\n-
135 (INDEX <= std::tuple_size<TUPLE>::value), int>::type = 0>
\n-
136[[nodiscard]] inline std::string
\n-
\n-
137separated_list(std::string_view sep, TUPLE const &t)
\n-
138{
\n-
139 // TODO: Optimise allocation.
\n-
140 return separated_list(sep, t, [](TUPLE const &tup) { return *tup; });
\n-
141}
\n-
\n-
143} // namespace pqxx
\n-
144#endif
\n-
The home of all libpqxx classes, functions, templates, etc.
Definition array.hxx:33
\n-
std::string separated_list(std::string_view sep, ITER begin, ITER end, ACCESS access)
Represent sequence of values as a string, joined by a given separator.
Definition separated_list.hxx:44
\n-
std::remove_cv_t< std::remove_reference_t< TYPE > > strip_t
Remove any constness, volatile, and reference-ness from a type.
Definition types.hxx:91
\n-
std::string to_string(field const &value)
Convert a field to a string.
Definition result.cxx:549
\n-
Result set containing data returned by a query or command.
Definition result.hxx:73
\n-
Traits class for use in string conversions.
Definition strconv.hxx:155
\n+
24# define PQXX_VERSION_MAJOR 7
\n+
26# define PQXX_VERSION_MINOR 8
\n+
27
\n+
28# define PQXX_VERSION_CHECK check_pqxx_version_7_8
\n+
29
\n+
30namespace pqxx::internal
\n+
31{
\n+
33
\n+
54PQXX_LIBEXPORT int PQXX_VERSION_CHECK() noexcept;
\n+
55} // namespace pqxx::internal
\n+
56#endif
\n+
Internal items for libpqxx' own use. Do not use these yourself.
Definition composite.hxx:84
\n+
int PQXX_VERSION_CHECK() noexcept
Library version check stub.
Definition version.cxx:23
\n
\n
\n \n
\n \n
\n \n \n", "details": [{"source1": "html2text {}", "source2": "html2text {}", "unified_diff": "@@ -1,162 +1,50 @@\n \n \n \n \n \n libpqxx\u00a07.8.1\n \n-separated_list.hxx\n- 1/* Helper similar to Python's `str.join()`.\n+version.hxx\n+ 1/* Version info for libpqxx.\n 2 *\n- 3 * DO NOT INCLUDE THIS FILE DIRECTLY; include pqxx/separated_list instead.\n+ 3 * DO NOT INCLUDE THIS FILE DIRECTLY; include pqxx/version instead.\n 4 *\n 5 * Copyright (c) 2000-2023, Jeroen T. Vermeulen.\n 6 *\n 7 * See COPYING for copyright license. If you did not receive a file called\n 8 * COPYING with this source code, please notify the distributor of this\n 9 * mistake, or contact the author.\n 10 */\n- 11#ifndef PQXX_H_SEPARATED_LIST\n- 12#define PQXX_H_SEPARATED_LIST\n+ 11#if !defined(PQXX_H_VERSION)\n+ 12# define PQXX_H_VERSION\n 13\n- 14#if !defined(PQXX_HEADER_PRE)\n+ 14# if !defined(PQXX_HEADER_PRE)\n 15# error \"Include libpqxx headers as , not .\"\n- 16#endif\n+ 16# endif\n 17\n- 18#include \n- 19#include \n- 20\n- 21#include \"pqxx/strconv.hxx\"\n+ 19# define PQXX_VERSION \"7.8.1\"\n+ 21# define PQXX_ABI \"7.8\"\n 22\n- 23// C++20: Simplify using std::ranges::range.\n- 24// C++20: Optimise buffer allocation using random_access_range/iterator.\n- 25// TODO: Can we pass separators at compile time?\n- 26namespace pqxx\n- 27{\n- 32\n- 34\n- 42template\n- 43[[nodiscard]] inline std::string\n-44separated_list(std::string_view sep, ITER begin, ITER end, ACCESS access)\n- 45{\n- 46 if (end == begin)\n- 47 return {};\n- 48 auto next{begin};\n- 49 ++next;\n- 50 if (next == end)\n- 51 return to_string(access(begin));\n- 52\n- 53 // From here on, we've got at least 2 elements -- meaning that we need sep.\n- 54 using elt_type = strip_t;\n- 55 using traits = string_traits;\n- 56\n- 57 std::size_t budget{0};\n- 58 for (ITER cnt{begin}; cnt != end; ++cnt)\n- 59 budget += traits::size_buffer(access(cnt));\n- 60 budget +=\n- 61 static_cast(std::distance(begin, end)) * std::size(sep);\n- 62\n- 63 std::string result;\n- 64 result.resize(budget);\n- 65\n- 66 char *const data{result.data()};\n- 67 char *here{data};\n- 68 char *stop{data + budget};\n- 69 here = traits::into_buf(here, stop, access(begin)) - 1;\n- 70 for (++begin; begin != end; ++begin)\n- 71 {\n- 72 here += sep.copy(here, std::size(sep));\n- 73 here = traits::into_buf(here, stop, access(begin)) - 1;\n- 74 }\n- 75 result.resize(static_cast(here - data));\n- 76 return result;\n- 77}\n- 78\n- 79\n- 81template\n- 82[[nodiscard]] inline std::string\n-83separated_list(std::string_view sep, ITER begin, ITER end)\n- 84{\n- 85 return separated_list(sep, begin, end, [](ITER i) { return *i; });\n- 86}\n- 87\n- 88\n- 89// C++20: Use a concept.\n- 91template\n- 92[[nodiscard]] inline auto\n-93separated_list(std::string_view sep, CONTAINER const &c)\n- 94 /*\n- 95 Always std::string; necessary because SFINAE doesn't work with the\n- 96 contents of function bodies, so the check for iterability has to be in\n- 97 the signature.\n- 98 */\n- 99 -> typename std::enable_if<\n- 100 (not std::is_void::value and\n- 101 not std::is_void::value),\n- 102 std::string>::type\n- 103{\n- 104 return separated_list(sep, std::begin(c), std::end(c));\n- 105}\n- 106\n- 107\n- 109template<\n- 110 typename TUPLE, std::size_t INDEX = 0, typename ACCESS,\n- 111 typename std::enable_if<\n- 112 (INDEX == std::tuple_size::value - 1), int>::type = 0>\n-113[[nodiscard]] inline std::string separated_list(\n- 114 std::string_view /* sep */, TUPLE const &t, ACCESS const &access)\n- 115{\n- 116 return to_string(access(&std::get(t)));\n- 117}\n- 118\n- 119template<\n- 120 typename TUPLE, std::size_t INDEX = 0, typename ACCESS,\n- 121 typename std::enable_if<\n- 122 (INDEX < std::tuple_size::value - 1), int>::type = 0>\n- 123[[nodiscard]] inline std::string\n- 124separated_list(std::string_view sep, TUPLE const &t, ACCESS const &access)\n- 125{\n- 126 std::string out{to_string(access(&std::get(t)))};\n- 127 out.append(sep);\n- 128 out.append(separated_list(sep, t, access));\n- 129 return out;\n- 130}\n- 131\n- 132template<\n- 133 typename TUPLE, std::size_t INDEX = 0,\n- 134 typename std::enable_if<\n- 135 (INDEX <= std::tuple_size::value), int>::type = 0>\n- 136[[nodiscard]] inline std::string\n-137separated_list(std::string_view sep, TUPLE const &t)\n- 138{\n- 139 // TODO: Optimise allocation.\n- 140 return separated_list(sep, t, [](TUPLE const &tup) { return *tup; });\n- 141}\n- 143} // namespace pqxx\n- 144#endif\n-pqxx\n-The home of all libpqxx classes, functions, templates, etc.\n-Definition array.hxx:33\n-pqxx::separated_list\n-std::string separated_list(std::string_view sep, ITER begin, ITER end, ACCESS\n-access)\n-Represent sequence of values as a string, joined by a given separator.\n-Definition separated_list.hxx:44\n-pqxx::strip_t\n-std::remove_cv_t< std::remove_reference_t< TYPE > > strip_t\n-Remove any constness, volatile, and reference-ness from a type.\n-Definition types.hxx:91\n-pqxx::to_string\n-std::string to_string(field const &value)\n-Convert a field to a string.\n-Definition result.cxx:549\n-pqxx::result\n-Result set containing data returned by a query or command.\n-Definition result.hxx:73\n-pqxx::string_traits\n-Traits class for use in string conversions.\n-Definition strconv.hxx:155\n+ 24# define PQXX_VERSION_MAJOR 7\n+ 26# define PQXX_VERSION_MINOR 8\n+ 27\n+ 28# define PQXX_VERSION_CHECK check_pqxx_version_7_8\n+ 29\n+ 30namespace pqxx::internal\n+ 31{\n+ 33\n+ 54PQXX_LIBEXPORT int PQXX_VERSION_CHECK() noexcept;\n+ 55} // namespace pqxx::internal\n+ 56#endif\n+pqxx::internal\n+Internal items for libpqxx' own use. Do not use these yourself.\n+Definition composite.hxx:84\n+pqxx::internal::PQXX_VERSION_CHECK\n+int PQXX_VERSION_CHECK() noexcept\n+Library version check stub.\n+Definition version.cxx:23\n * include\n * pqxx\n- * separated_list.hxx\n+ * version.hxx\n * Generated by [doxygen] 1.9.8\n"}]}, {"source1": "./usr/share/doc/libpqxx-doc/html/a00092_source.html", "source2": "./usr/share/doc/libpqxx-doc/html/a00092_source.html", "unified_diff": "@@ -1,15 +1,15 @@\n \n \n \n \n \n \n \n-libpqxx: stream_to.hxx Source File\n+libpqxx: array.hxx Source File\n \n \n \n \n \n \n \n@@ -60,386 +60,519 @@\n \n
\n
\n-
stream_to.hxx
\n+
array.hxx
\n
\n
\n-
1/* Definition of the pqxx::stream_to class.
\n+
1/* Handling of SQL arrays.
\n
2 *
\n-
3 * pqxx::stream_to enables optimized batch updates to a database table.
\n+
3 * DO NOT INCLUDE THIS FILE DIRECTLY; include pqxx/field instead.
\n
4 *
\n-
5 * DO NOT INCLUDE THIS FILE DIRECTLY; include pqxx/stream_to.hxx instead.
\n+
5 * Copyright (c) 2000-2023, Jeroen T. Vermeulen.
\n
6 *
\n-
7 * Copyright (c) 2000-2023, Jeroen T. Vermeulen.
\n-
8 *
\n-
9 * See COPYING for copyright license. If you did not receive a file called
\n-
10 * COPYING with this source code, please notify the distributor of this
\n-
11 * mistake, or contact the author.
\n-
12 */
\n-
13#ifndef PQXX_H_STREAM_TO
\n-
14#define PQXX_H_STREAM_TO
\n-
15
\n-
16#if !defined(PQXX_HEADER_PRE)
\n-
17# error "Include libpqxx headers as <pqxx/header>, not <pqxx/header.hxx>."
\n-
18#endif
\n-
19
\n-
20#include "pqxx/separated_list.hxx"
\n-
21#include "pqxx/transaction_base.hxx"
\n-
22
\n-
23
\n-
24namespace pqxx
\n-
25{
\n-
27
\n-
\n-
80class PQXX_LIBEXPORT stream_to : transaction_focus
\n-
81{
\n-
82public:
\n-
84
\n-
\n-\n-
105 transaction_base &tx, std::string_view path, std::string_view columns = "")
\n-
106 {
\n-
107 return {tx, path, columns};
\n-
108 }
\n-
\n-
109
\n-
111
\n-
\n-\n-\n-
122 std::initializer_list<std::string_view> columns = {})
\n-
123 {
\n-
124 auto const &conn{tx.conn()};
\n-
125 return raw_table(tx, conn.quote_table(path), conn.quote_columns(columns));
\n-
126 }
\n-
\n-
127
\n-
128#if defined(PQXX_HAVE_CONCEPTS)
\n+
7 * See COPYING for copyright license. If you did not receive a file called
\n+
8 * COPYING with this source code, please notify the distributor of this
\n+
9 * mistake, or contact the author.
\n+
10 */
\n+
11#ifndef PQXX_H_ARRAY
\n+
12#define PQXX_H_ARRAY
\n+
13
\n+
14#if !defined(PQXX_HEADER_PRE)
\n+
15# error "Include libpqxx headers as <pqxx/header>, not <pqxx/header.hxx>."
\n+
16#endif
\n+
17
\n+
18#include <algorithm>
\n+
19#include <cassert>
\n+
20#include <stdexcept>
\n+
21#include <string>
\n+
22#include <type_traits>
\n+
23#include <utility>
\n+
24#include <vector>
\n+
25
\n+
26#include "pqxx/connection.hxx"
\n+
27#include "pqxx/internal/array-composite.hxx"
\n+
28#include "pqxx/internal/encoding_group.hxx"
\n+
29#include "pqxx/internal/encodings.hxx"
\n+
30
\n+
31
\n+
\n+
32namespace pqxx
\n+
33{
\n+
34// TODO: Specialise for string_view/zview, allocate all strings in one buffer.
\n+
35
\n+
37
\n+
52template<
\n+
53 typename ELEMENT, std::size_t DIMENSIONS = 1u,
\n+
54 char SEPARATOR = array_separator<ELEMENT>>
\n+
\n+
55class array final
\n+
56{
\n+
57public:
\n+
59
\n+
\n+
68 array(std::string_view data, connection const &conn) :
\n+
69 array{data, pqxx::internal::enc_group(conn.encoding_id())}
\n+
70 {}
\n+
\n+
71
\n+
73
\n+
75 constexpr std::size_t dimensions() noexcept { return DIMENSIONS; }
\n+
76
\n+
78
\n+
\n+
82 std::array<std::size_t, DIMENSIONS> const &sizes() noexcept
\n+
83 {
\n+
84 return m_extents;
\n+
85 }
\n+
\n+
86
\n+
\n+
87 template<typename... INDEX> ELEMENT const &at(INDEX... index) const
\n+
88 {
\n+
89 static_assert(sizeof...(index) == DIMENSIONS);
\n+
90 check_bounds(index...);
\n+
91 return m_elts.at(locate(index...));
\n+
92 }
\n+
\n+
93
\n+
95
\n+
\n+
103 template<typename... INDEX> ELEMENT const &operator[](INDEX... index) const
\n+
104 {
\n+
105 static_assert(sizeof...(index) == DIMENSIONS);
\n+
106 return m_elts[locate(index...)];
\n+
107 }
\n+
\n+
108
\n+
110
\n+
115 constexpr auto cbegin() const noexcept { return m_elts.cbegin(); }
\n+
117 constexpr auto cend() const noexcept { return m_elts.cend(); }
\n+
119 constexpr auto crbegin() const noexcept { return m_elts.crbegin(); }
\n+
121 constexpr auto crend() const noexcept { return m_elts.crend(); }
\n+
122
\n+
124
\n+
127 constexpr std::size_t size() const noexcept { return m_elts.size(); }
\n+
128
\n
130
\n-
137 template<PQXX_CHAR_STRINGS_ARG COLUMNS>
\n-
138 static stream_to
\n-
139 table(transaction_base &tx, table_path path, COLUMNS const &columns)
\n-
140 {
\n-
141 auto const &conn{tx.conn()};
\n-\n-
143 tx, conn.quote_table(path), tx.conn().quote_columns(columns));
\n-
144 }
\n-
145
\n-
147
\n-
154 template<PQXX_CHAR_STRINGS_ARG COLUMNS>
\n-
155 static stream_to
\n-
156 table(transaction_base &tx, std::string_view path, COLUMNS const &columns)
\n-
157 {
\n-
158 return stream_to::raw_table(tx, path, tx.conn().quote_columns(columns));
\n-
159 }
\n-
160#endif // PQXX_HAVE_CONCEPTS
\n-
161
\n-
163
\n-
\n-
172 [[deprecated("Use table() or raw_table() factory.")]] stream_to(
\n-
173 transaction_base &tx, std::string_view table_name) :
\n-
174 stream_to{tx, table_name, ""sv}
\n-
175 {}
\n-
\n-
176
\n-
178
\n-
180 template<typename Columns>
\n-
181 [[deprecated("Use table() or raw_table() factory.")]] stream_to(
\n-
182 transaction_base &, std::string_view table_name, Columns const &columns);
\n-
183
\n-
185
\n-
187 template<typename Iter>
\n-
188 [[deprecated("Use table() or raw_table() factory.")]] stream_to(
\n-
189 transaction_base &, std::string_view table_name, Iter columns_begin,
\n-
190 Iter columns_end);
\n-
191
\n-
\n-
192 explicit stream_to(stream_to &&other) :
\n-
193 // (This first step only moves the transaction_focus base-class
\n-
194 // object.)
\n-
195 transaction_focus{std::move(other)},
\n-
196 m_finished{other.m_finished},
\n-
197 m_buffer{std::move(other.m_buffer)},
\n-
198 m_field_buf{std::move(other.m_field_buf)},
\n-
199 m_finder{other.m_finder}
\n-
200 {
\n-
201 other.m_finished = true;
\n-
202 }
\n-
\n-
203 ~stream_to() noexcept;
\n-
204
\n-
\n-
206 [[nodiscard]] constexpr operator bool() const noexcept
\n-
207 {
\n-
208 return not m_finished;
\n-
209 }
\n-
\n-
\n-
211 [[nodiscard]] constexpr bool operator!() const noexcept
\n-
212 {
\n-
213 return m_finished;
\n-
214 }
\n-
\n-
215
\n-
217
\n-
223 void complete();
\n-
224
\n-
226
\n-
\n-
235 template<typename Row> stream_to &operator<<(Row const &row)
\n-
236 {
\n-
237 write_row(row);
\n-
238 return *this;
\n-
239 }
\n-
\n-
240
\n-
242
\n-\n-
247
\n-
249
\n-
\n-
255 template<typename Row> void write_row(Row const &row)
\n-
256 {
\n-
257 fill_buffer(row);
\n-
258 write_buffer();
\n-
259 }
\n-
\n-
260
\n-
262
\n-
\n-
265 template<typename... Ts> void write_values(Ts const &...fields)
\n-
266 {
\n-
267 fill_buffer(fields...);
\n-
268 write_buffer();
\n-
269 }
\n-
\n-
270
\n-
271private:
\n-
273 stream_to(
\n-
274 transaction_base &tx, std::string_view path, std::string_view columns);
\n-
275
\n-
276 bool m_finished = false;
\n-
277
\n-
279 std::string m_buffer;
\n-
280
\n-
282 std::string m_field_buf;
\n+
\n+
145 constexpr auto ssize() const noexcept
\n+
146 {
\n+
147 return static_cast<std::ptrdiff_t>(size());
\n+
148 }
\n+
\n+
149
\n+
151
\n+
153 constexpr auto front() const noexcept { return m_elts.front(); }
\n+
154
\n+
156
\n+
158 constexpr auto back() const noexcept { return m_elts.back(); }
\n+
159
\n+
160private:
\n+
162
\n+
170 void check_dims(std::string_view data)
\n+
171 {
\n+
172 auto sz{std::size(data)};
\n+
173 if (sz < DIMENSIONS * 2)
\n+
174 throw conversion_error{pqxx::internal::concat(
\n+
175 "Trying to parse a ", DIMENSIONS, "-dimensional array out of '", data,
\n+
176 "'.")};
\n+
177
\n+
178 // Making some assumptions here:
\n+
179 // * The array holds no extraneous whitespace.
\n+
180 // * None of the sub-arrays can be null.
\n+
181 // * Only ASCII characters start off with a byte in the 0-127 range.
\n+
182 //
\n+
183 // Given those, the input must start with a sequence of DIMENSIONS bytes
\n+
184 // with the ASCII value for '{'; and likewise it must end with a sequence
\n+
185 // of DIMENSIONS bytes with the ASCII value for '}'.
\n+
186
\n+
187 if (data[0] != '{')
\n+
188 throw conversion_error{"Malformed array: does not start with '{'."};
\n+
189 for (std::size_t i{0}; i < DIMENSIONS; ++i)
\n+
190 if (data[i] != '{')
\n+
191 throw conversion_error{pqxx::internal::concat(
\n+
192 "Expecting ", DIMENSIONS, "-dimensional array, but found ", i, ".")};
\n+
193 if (data[DIMENSIONS] == '{')
\n+
194 throw conversion_error{pqxx::internal::concat(
\n+
195 "Tried to parse ", DIMENSIONS,
\n+
196 "-dimensional array from array data that has more dimensions.")};
\n+
197 for (std::size_t i{0}; i < DIMENSIONS; ++i)
\n+
198 if (data[sz - 1 - i] != '}')
\n+
199 throw conversion_error{
\n+
200 "Malformed array: does not end in the right number of '}'."};
\n+
201 }
\n+
202
\n+
203 explicit array(std::string_view data, pqxx::internal::encoding_group enc)
\n+
204 {
\n+
205 using group = pqxx::internal::encoding_group;
\n+
206 switch (enc)
\n+
207 {
\n+
208 case group::MONOBYTE: parse<group::MONOBYTE>(data); break;
\n+
209 case group::BIG5: parse<group::BIG5>(data); break;
\n+
210 case group::EUC_CN: parse<group::EUC_CN>(data); break;
\n+
211 case group::EUC_JP: parse<group::EUC_JP>(data); break;
\n+
212 case group::EUC_KR: parse<group::EUC_KR>(data); break;
\n+
213 case group::EUC_TW: parse<group::EUC_TW>(data); break;
\n+
214 case group::GB18030: parse<group::GB18030>(data); break;
\n+
215 case group::GBK: parse<group::GBK>(data); break;
\n+
216 case group::JOHAB: parse<group::JOHAB>(data); break;
\n+
217 case group::MULE_INTERNAL: parse<group::MULE_INTERNAL>(data); break;
\n+
218 case group::SJIS: parse<group::SJIS>(data); break;
\n+
219 case group::UHC: parse<group::UHC>(data); break;
\n+
220 case group::UTF8: parse<group::UTF8>(data); break;
\n+
221 }
\n+
222 }
\n+
223
\n+
225
\n+
228 std::size_t parse_field_end(std::string_view data, std::size_t here) const
\n+
229 {
\n+
230 auto const sz{std::size(data)};
\n+
231 if (here < sz)
\n+
232 switch (data[here])
\n+
233 {
\n+
234 case SEPARATOR:
\n+
235 ++here;
\n+
236 if (here >= sz)
\n+
237 throw conversion_error{"Array looks truncated."};
\n+
238 switch (data[here])
\n+
239 {
\n+
240 case SEPARATOR:
\n+
241 throw conversion_error{"Array contains double separator."};
\n+
242 case '}': throw conversion_error{"Array contains trailing separator."};
\n+
243 default: break;
\n+
244 }
\n+
245 break;
\n+
246 case '}': break;
\n+
247 default:
\n+
248 throw conversion_error{pqxx::internal::concat(
\n+
249 "Unexpected character in array: ",
\n+
250 static_cast<unsigned>(static_cast<unsigned char>(data[here])),
\n+
251 " where separator or closing brace expected.")};
\n+
252 }
\n+
253 return here;
\n+
254 }
\n+
255
\n+
257
\n+
262 constexpr std::size_t estimate_elements(std::string_view data) const noexcept
\n+
263 {
\n+
264 // Dirty trick: just count the number of bytes that look as if they may be
\n+
265 // separators. At the very worst we may overestimate by a factor of two or
\n+
266 // so, in exceedingly rare cases, on some encodings.
\n+
267 auto const separators{
\n+
268 std::count(std::begin(data), std::end(data), SEPARATOR)};
\n+
269 // The number of dimensions makes no difference here. It's still one
\n+
270 // separator between consecutive elements, just possibly with some extra
\n+
271 // braces as well.
\n+
272 return static_cast<std::size_t>(separators + 1);
\n+
273 }
\n+
274
\n+
275 template<pqxx::internal::encoding_group ENC>
\n+
276 void parse(std::string_view data)
\n+
277 {
\n+
278 static_assert(DIMENSIONS > 0u, "Can't create a zero-dimensional array.");
\n+
279 auto const sz{std::size(data)};
\n+
280 check_dims(data);
\n+
281
\n+
282 m_elts.reserve(estimate_elements(data));
\n
283
\n-
285 internal::char_finder_func *m_finder;
\n-
286
\n-
288 void write_raw_line(std::string_view);
\n+
284 // We discover the array's extents along each of the dimensions, starting
\n+
285 // with the final dimension and working our way towards the first. At any
\n+
286 // given point during parsing, we know the extents starting at this
\n+
287 // dimension.
\n+
288 std::size_t know_extents_from{DIMENSIONS};
\n
289
\n-
291
\n-
293 void write_buffer();
\n-
294
\n-
296 static constexpr std::string_view null_field{"\\\\N\\t"};
\n+
290 // Currently parsing this dimension. We start off at -1, relying on C++'s
\n+
291 // well-defined rollover for unsigned numbers.
\n+
292 // The actual outermost dimension of the array is 0, and the innermost is
\n+
293 // at the end. But, the array as a whole is enclosed in braces just like
\n+
294 // each row. So we act like there's an anomalous "outer" dimension holding
\n+
295 // the entire array.
\n+
296 constexpr std::size_t outer{std::size_t{0u} - std::size_t{1u}};
\n
297
\n-
299 template<typename T>
\n-
300 static std::enable_if_t<nullness<T>::always_null, std::size_t>
\n-
301 estimate_buffer(T const &)
\n-
302 {
\n-
303 return std::size(null_field);
\n-
304 }
\n-
305
\n-
307
\n-
310 template<typename T>
\n-
311 static std::enable_if_t<not nullness<T>::always_null, std::size_t>
\n-
312 estimate_buffer(T const &field)
\n-
313 {
\n-
314 return is_null(field) ? std::size(null_field) : size_buffer(field);
\n-
315 }
\n-
316
\n-
318 void escape_field_to_buffer(std::string_view data);
\n-
319
\n-
321
\n-
327 template<typename Field>
\n-
328 std::enable_if_t<not nullness<Field>::always_null>
\n-
329 append_to_buffer(Field const &f)
\n-
330 {
\n-
331 // We append each field, terminated by a tab. That will leave us with
\n-
332 // one tab too many, assuming we write any fields at all; we remove that
\n-
333 // at the end.
\n-
334 if (is_null(f))
\n-
335 {
\n-
336 // Easy. Append null and tab in one go.
\n-
337 m_buffer.append(null_field);
\n-
338 }
\n-
339 else
\n-
340 {
\n-
341 // Convert f into m_buffer.
\n-
342
\n-
343 using traits = string_traits<Field>;
\n-
344 auto const budget{estimate_buffer(f)};
\n-
345 auto const offset{std::size(m_buffer)};
\n-
346
\n-
347 if constexpr (std::is_arithmetic_v<Field>)
\n-
348 {
\n-
349 // Specially optimised for "safe" types, which never need any
\n-
350 // escaping. Convert straight into m_buffer.
\n-
351
\n-
352 // The budget we get from size_buffer() includes room for the trailing
\n-
353 // zero, which we must remove. But we're also inserting tabs between
\n-
354 // fields, so we re-purpose the extra byte for that.
\n-
355 auto const total{offset + budget};
\n-
356 m_buffer.resize(total);
\n-
357 auto const data{m_buffer.data()};
\n-
358 char *const end{traits::into_buf(data + offset, data + total, f)};
\n-
359 *(end - 1) = '\\t';
\n-
360 // Shrink to fit. Keep the tab though.
\n-
361 m_buffer.resize(static_cast<std::size_t>(end - data));
\n-
362 }
\n-
363 else if constexpr (
\n-
364 std::is_same_v<Field, std::string> or
\n-
365 std::is_same_v<Field, std::string_view> or
\n-
366 std::is_same_v<Field, zview>)
\n-
367 {
\n-
368 // This string may need escaping.
\n-
369 m_field_buf.resize(budget);
\n-
370 escape_field_to_buffer(f);
\n-
371 }
\n-
372 else if constexpr (
\n-
373 std::is_same_v<Field, std::optional<std::string>> or
\n-
374 std::is_same_v<Field, std::optional<std::string_view>> or
\n-
375 std::is_same_v<Field, std::optional<zview>>)
\n-
376 {
\n-
377 // Optional string. It's not null (we checked for that above), so...
\n-
378 // Treat like a string.
\n-
379 m_field_buf.resize(budget);
\n-
380 escape_field_to_buffer(f.value());
\n-
381 }
\n-
382 // TODO: Support deleter template argument on unique_ptr.
\n-
383 else if constexpr (
\n-
384 std::is_same_v<Field, std::unique_ptr<std::string>> or
\n-
385 std::is_same_v<Field, std::unique_ptr<std::string_view>> or
\n-
386 std::is_same_v<Field, std::unique_ptr<zview>> or
\n-
387 std::is_same_v<Field, std::shared_ptr<std::string>> or
\n-
388 std::is_same_v<Field, std::shared_ptr<std::string_view>> or
\n-
389 std::is_same_v<Field, std::shared_ptr<zview>>)
\n-
390 {
\n-
391 // TODO: Can we generalise this elegantly without Concepts?
\n-
392 // Effectively also an optional string. It's not null (we checked
\n-
393 // for that above).
\n-
394 m_field_buf.resize(budget);
\n-
395 escape_field_to_buffer(*f);
\n-
396 }
\n-
397 else
\n-
398 {
\n-
399 // This field needs to be converted to a string, and after that,
\n-
400 // escaped as well.
\n-
401 m_field_buf.resize(budget);
\n-
402 auto const data{m_field_buf.data()};
\n-
403 escape_field_to_buffer(
\n-
404 traits::to_buf(data, data + std::size(m_field_buf), f));
\n-
405 }
\n-
406 }
\n-
407 }
\n-
408
\n-
410
\n-
416 template<typename Field>
\n-
417 std::enable_if_t<nullness<Field>::always_null>
\n-
418 append_to_buffer(Field const &)
\n-
419 {
\n-
420 m_buffer.append(null_field);
\n-
421 }
\n+
298 // We start parsing at the fictional outer dimension. The input begins
\n+
299 // with opening braces, one for each dimension, so we'll start off by
\n+
300 // bumping all the way to the innermost dimension.
\n+
301 std::size_t dim{outer};
\n+
302
\n+
303 // Extent counters, one per "real" dimension.
\n+
304 // Note initialiser syntax; this should zero-initialise all elements.
\n+
305 std::array<std::size_t, DIMENSIONS> extents{};
\n+
306#if !defined(NDEBUG)
\n+
307 for (auto const e : extents) assert(e == 0u);
\n+
308#endif
\n+
309
\n+
310 // Current parsing position.
\n+
311 std::size_t here{0};
\n+
312 while (here < sz)
\n+
313 {
\n+
314 if (data[here] == '{')
\n+
315 {
\n+
316 if (dim == outer)
\n+
317 {
\n+
318 // This must be the initial opening brace.
\n+
319 if (know_extents_from != DIMENSIONS)
\n+
320 throw conversion_error{
\n+
321 "Array text representation closed and reopened its outside "
\n+
322 "brace pair."};
\n+
323 assert(here == 0);
\n+
324 }
\n+
325 else
\n+
326 {
\n+
327 if (dim >= (DIMENSIONS - 1))
\n+
328 throw conversion_error{
\n+
329 "Array seems to have inconsistent number of dimensions."};
\n+
330 ++extents[dim];
\n+
331 }
\n+
332 // (Rolls over to zero if we're coming from the outer dimension.)
\n+
333 ++dim;
\n+
334 extents[dim] = 0u;
\n+
335 ++here;
\n+
336 }
\n+
337 else if (data[here] == '}')
\n+
338 {
\n+
339 if (dim == outer)
\n+
340 throw conversion_error{"Array has spurious '}'."};
\n+
341 if (dim < know_extents_from)
\n+
342 {
\n+
343 // We just finished parsing our first row in this dimension.
\n+
344 // Now we know the array dimension's extent.
\n+
345 m_extents[dim] = extents[dim];
\n+
346 know_extents_from = dim;
\n+
347 }
\n+
348 else
\n+
349 {
\n+
350 if (extents[dim] != m_extents[dim])
\n+
351 throw conversion_error{"Rows in array have inconsistent sizes."};
\n+
352 }
\n+
353 // Bump back down to the next-lower dimension. Which may be the outer
\n+
354 // dimension, through underflow.
\n+
355 --dim;
\n+
356 ++here;
\n+
357 here = parse_field_end(data, here);
\n+
358 }
\n+
359 else
\n+
360 {
\n+
361 // Found an array element. The actual elements always live in the
\n+
362 // "inner" dimension.
\n+
363 if (dim != DIMENSIONS - 1)
\n+
364 throw conversion_error{
\n+
365 "Malformed array: found element where sub-array was expected."};
\n+
366 assert(dim != outer);
\n+
367 ++extents[dim];
\n+
368 std::size_t end;
\n+
369 switch (data[here])
\n+
370 {
\n+
371 case '\\0': throw conversion_error{"Unexpected zero byte in array."};
\n+
372 case ',': throw conversion_error{"Array contains empty field."};
\n+
373 case '"': {
\n+
374 // Double-quoted string. We parse it into a buffer before parsing
\n+
375 // the resulting string as an element. This seems wasteful: the
\n+
376 // string might not contain any special characters. So it's
\n+
377 // tempting to check, and try to use a string_view and avoid a
\n+
378 // useless copy step. But. Even besides the branch prediction
\n+
379 // risk, the very fact that the back-end chose to quote the string
\n+
380 // indicates that there is some kind of special character in there.
\n+
381 // So in practice, this optimisation would only apply if the only
\n+
382 // special characters in the string were commas.
\n+
383 end = pqxx::internal::scan_double_quoted_string<ENC>(
\n+
384 std::data(data), std::size(data), here);
\n+
385 // TODO: scan_double_quoted_string() with reusable buffer.
\n+
386 std::string const buf{
\n+
387 pqxx::internal::parse_double_quoted_string<ENC>(
\n+
388 std::data(data), end, here)};
\n+
389 m_elts.emplace_back(from_string<ELEMENT>(buf));
\n+
390 }
\n+
391 break;
\n+
392 default: {
\n+
393 // Unquoted string. An unquoted string is always literal, no
\n+
394 // escaping or encoding, so we don't need to parse it into a
\n+
395 // buffer. We can just read it as a string_view.
\n+
396 end = pqxx::internal::scan_unquoted_string<ENC, SEPARATOR, '}'>(
\n+
397 std::data(data), std::size(data), here);
\n+
398 std::string_view const field{
\n+
399 std::string_view{std::data(data) + here, end - here}};
\n+
400 if (field == "NULL")
\n+
401 {
\n+
402 if constexpr (nullness<ELEMENT>::has_null)
\n+
403 m_elts.emplace_back(nullness<ELEMENT>::null());
\n+
404 else
\n+
405 throw unexpected_null{pqxx::internal::concat(
\n+
406 "Array contains a null ", type_name<ELEMENT>,
\n+
407 ". Consider making it an array of std::optional<",
\n+
408 type_name<ELEMENT>, "> instead.")};
\n+
409 }
\n+
410 else
\n+
411 m_elts.emplace_back(from_string<ELEMENT>(field));
\n+
412 }
\n+
413 }
\n+
414 here = end;
\n+
415 here = parse_field_end(data, here);
\n+
416 }
\n+
417 }
\n+
418
\n+
419 if (dim != outer)
\n+
420 throw conversion_error{"Malformed array; may be truncated."};
\n+
421 assert(know_extents_from == 0);
\n
422
\n-
424 template<typename Container>
\n-
425 std::enable_if_t<not std::is_same_v<typename Container::value_type, char>>
\n-
426 fill_buffer(Container const &c)
\n-
427 {
\n-
428 // To avoid unnecessary allocations and deallocations, we run through c
\n-
429 // twice: once to determine how much buffer space we may need, and once to
\n-
430 // actually write it into the buffer.
\n-
431 std::size_t budget{0};
\n-
432 for (auto const &f : c) budget += estimate_buffer(f);
\n-
433 m_buffer.reserve(budget);
\n-
434 for (auto const &f : c) append_to_buffer(f);
\n+
423 init_factors();
\n+
424 }
\n+
425
\n+
427 void init_factors() noexcept
\n+
428 {
\n+
429 std::size_t factor{1};
\n+
430 for (std::size_t dim{DIMENSIONS - 1}; dim > 0; --dim)
\n+
431 {
\n+
432 factor *= m_extents[dim];
\n+
433 m_factors[dim - 1] = factor;
\n+
434 }
\n
435 }
\n
436
\n-
438 template<typename Tuple, std::size_t... indexes>
\n-
439 static std::size_t
\n-
440 budget_tuple(Tuple const &t, std::index_sequence<indexes...>)
\n-
441 {
\n-
442 return (estimate_buffer(std::get<indexes>(t)) + ...);
\n-
443 }
\n-
444
\n-
446 template<typename Tuple, std::size_t... indexes>
\n-
447 void append_tuple(Tuple const &t, std::index_sequence<indexes...>)
\n+
438 template<typename... INDEX> std::size_t locate(INDEX... index) const noexcept
\n+
439 {
\n+
440 static_assert(
\n+
441 sizeof...(index) == DIMENSIONS,
\n+
442 "Indexing array with wrong number of dimensions.");
\n+
443 return add_index(index...);
\n+
444 }
\n+
445
\n+
446 template<typename OUTER, typename... INDEX>
\n+
447 constexpr std::size_t add_index(OUTER outer, INDEX... indexes) const noexcept
\n
448 {
\n-
449 (append_to_buffer(std::get<indexes>(t)), ...);
\n-
450 }
\n-
451
\n-
453 template<typename... Elts> void fill_buffer(std::tuple<Elts...> const &t)
\n-
454 {
\n-
455 using indexes = std::make_index_sequence<sizeof...(Elts)>;
\n-
456
\n-
457 m_buffer.reserve(budget_tuple(t, indexes{}));
\n-
458 append_tuple(t, indexes{});
\n-
459 }
\n-
460
\n-
462 template<typename... Ts> void fill_buffer(const Ts &...fields)
\n-
463 {
\n-
464 (..., append_to_buffer(fields));
\n-
465 }
\n-
466
\n-
467 constexpr static std::string_view s_classname{"stream_to"};
\n-
468};
\n-
\n-
469
\n-
470
\n-
471template<typename Columns>
\n-
\n-\n-
473 transaction_base &tx, std::string_view table_name, Columns const &columns) :
\n-
474 stream_to{tx, table_name, std::begin(columns), std::end(columns)}
\n-
475{}
\n-
\n-
476
\n-
477
\n-
478template<typename Iter>
\n-
\n-\n-
480 transaction_base &tx, std::string_view table_name, Iter columns_begin,
\n-
481 Iter columns_end) :
\n-
482 stream_to{
\n-
483 tx,
\n-
484 tx.quote_name(
\n-
485 table_name,
\n-
486 separated_list(",", columns_begin, columns_end, [&tx](auto col) {
\n-
487 return tx.quote_name(*col);
\n-
488 }))}
\n-
489{}
\n+
449 std::size_t const first{check_cast<std::size_t>(outer, "array index"sv)};
\n+
450 if constexpr (sizeof...(indexes) == 0)
\n+
451 {
\n+
452 return first;
\n+
453 }
\n+
454 else
\n+
455 {
\n+
456 static_assert(sizeof...(indexes) < DIMENSIONS);
\n+
457 // (Offset by 1 here because the outer dimension is not in there.)
\n+
458 constexpr auto dimension{DIMENSIONS - (sizeof...(indexes) + 1)};
\n+
459 static_assert(dimension < DIMENSIONS);
\n+
460 return first * m_factors[dimension] + add_index(indexes...);
\n+
461 }
\n+
462 }
\n+
463
\n+
465
\n+
467 template<typename OUTER, typename... INDEX>
\n+
468 constexpr void check_bounds(OUTER outer, INDEX... indexes) const
\n+
469 {
\n+
470 std::size_t const first{check_cast<std::size_t>(outer, "array index"sv)};
\n+
471 static_assert(sizeof...(indexes) < DIMENSIONS);
\n+
472 // (Offset by 1 here because the outer dimension is not in there.)
\n+
473 constexpr auto dimension{DIMENSIONS - (sizeof...(indexes) + 1)};
\n+
474 static_assert(dimension < DIMENSIONS);
\n+
475 if (first >= m_extents[dimension])
\n+
476 throw range_error{pqxx::internal::concat(
\n+
477 "Array index for dimension ", dimension, " is out of bounds: ", first,
\n+
478 " >= ", m_extents[dimension])};
\n+
479
\n+
480 // Now check the rest of the indexes, if any.
\n+
481 if constexpr (sizeof...(indexes) > 0)
\n+
482 check_bounds(indexes...);
\n+
483 }
\n+
484
\n+
486 std::vector<ELEMENT> m_elts;
\n+
487
\n+
489 std::array<std::size_t, DIMENSIONS> m_extents;
\n+
490
\n+
492
\n+
499 std::array<std::size_t, DIMENSIONS - 1> m_factors;
\n+
500};
\n+
\n+
501
\n+
502
\n+
504
\n+
\n+
526class PQXX_LIBEXPORT array_parser
\n+
527{
\n+
528public:
\n+
\n+
530 enum class juncture
\n+
531 {
\n+
533 row_start,
\n+
535 row_end,
\n+
537 null_value,
\n+
539 string_value,
\n+
541 done,
\n+
542 };
\n+
\n+
543
\n+
545
\n+
549 explicit array_parser(
\n+
550 std::string_view input,
\n+
551 internal::encoding_group = internal::encoding_group::MONOBYTE);
\n+
552
\n+
554
\n+
560 std::pair<juncture, std::string> get_next() { return (this->*m_impl)(); }
\n+
561
\n+
562private:
\n+
563 std::string_view m_input;
\n+
564
\n+
566 std::size_t m_pos = 0u;
\n+
567
\n+
569
\n+
574 using implementation = std::pair<juncture, std::string> (array_parser::*)();
\n+
575
\n+
577 static implementation
\n+
578 specialize_for_encoding(pqxx::internal::encoding_group enc);
\n+
579
\n+
581 implementation m_impl;
\n+
582
\n+
584 template<pqxx::internal::encoding_group>
\n+
585 std::pair<juncture, std::string> parse_array_step();
\n+
586
\n+
587 template<pqxx::internal::encoding_group>
\n+
588 std::string::size_type scan_double_quoted_string() const;
\n+
589 template<pqxx::internal::encoding_group>
\n+
590 std::string parse_double_quoted_string(std::string::size_type end) const;
\n+
591 template<pqxx::internal::encoding_group>
\n+
592 std::string::size_type scan_unquoted_string() const;
\n+
593 template<pqxx::internal::encoding_group>
\n+
594 std::string parse_unquoted_string(std::string::size_type end) const;
\n+
595
\n+
596 template<pqxx::internal::encoding_group>
\n+
597 std::string::size_type scan_glyph(std::string::size_type pos) const;
\n+
598 template<pqxx::internal::encoding_group>
\n+
599 std::string::size_type
\n+
600 scan_glyph(std::string::size_type pos, std::string::size_type end) const;
\n+
601};
\n+
\n+
602} // namespace pqxx
\n
\n-
490} // namespace pqxx
\n-
491#endif
\n+
603#endif
\n
The home of all libpqxx classes, functions, templates, etc.
Definition array.hxx:33
\n-
std::string separated_list(std::string_view sep, ITER begin, ITER end, ACCESS access)
Represent sequence of values as a string, joined by a given separator.
Definition separated_list.hxx:44
\n-
std::basic_ostream< CHAR > & operator<<(std::basic_ostream< CHAR > &s, field const &value)
Write a result field to any type of stream.
Definition field.hxx:509
\n-
std::initializer_list< std::string_view > table_path
Representation of a PostgreSQL table path.
Definition connection.hxx:188
\n-
Reference to one row in a result.
Definition row.hxx:47
\n-
Stream data from the database.
Definition stream_from.hxx:79
\n-
Efficiently write data directly to a database table.
Definition stream_to.hxx:81
\n-
static stream_to raw_table(transaction_base &tx, std::string_view path, std::string_view columns="")
Stream data to a pre-quoted table and columns.
Definition stream_to.hxx:104
\n-
constexpr bool operator!() const noexcept
Has this stream been through its concluding complete()?
Definition stream_to.hxx:211
\n-
static stream_to table(transaction_base &tx, table_path path, std::initializer_list< std::string_view > columns={})
Create a stream_to writing to a named table and columns.
Definition stream_to.hxx:120
\n-
void write_values(Ts const &...fields)
Insert values as a row.
Definition stream_to.hxx:265
\n-
stream_to(transaction_base &tx, std::string_view table_name)
Create a stream, without specifying columns.
Definition stream_to.hxx:172
\n-
stream_to(stream_to &&other)
Definition stream_to.hxx:192
\n-
stream_to & operator<<(Row const &row)
Insert a row of data.
Definition stream_to.hxx:235
\n-
void write_row(Row const &row)
Insert a row of data, given in the form of a std::tuple or container.
Definition stream_to.hxx:255
\n-
Interface definition (and common code) for "transaction" classes.
Definition transaction_base.hxx:88
\n-
constexpr connection & conn() const noexcept
The connection in which this transaction lives.
Definition transaction_base.hxx:780
\n-
std::string quote_name(std::string_view identifier) const
Escape an SQL identifier for use in a query.
Definition transaction_base.hxx:231
\n-
Base class for things that monopolise a transaction's attention.
Definition transaction_focus.hxx:29
\n+
An SQL array received from the database.
Definition array.hxx:56
\n+
constexpr auto back() const noexcept
Refer to the last element, if any.
Definition array.hxx:158
\n+
constexpr auto cend() const noexcept
Return end point of iteration.
Definition array.hxx:117
\n+
constexpr auto crbegin() const noexcept
Begin reverse iteration.
Definition array.hxx:119
\n+
ELEMENT const & operator[](INDEX... index) const
Access element (without bounds check).
Definition array.hxx:103
\n+
constexpr std::size_t size() const noexcept
Number of elements in the array.
Definition array.hxx:127
\n+
constexpr auto ssize() const noexcept
Number of elements in the array (as a signed number).
Definition array.hxx:145
\n+
constexpr std::size_t dimensions() noexcept
How many dimensions does this array have?
Definition array.hxx:75
\n+
constexpr auto cbegin() const noexcept
Begin iteration of individual elements.
Definition array.hxx:115
\n+
ELEMENT const & at(INDEX... index) const
Definition array.hxx:87
\n+
array(std::string_view data, connection const &conn)
Parse an SQL array, read as text from a pqxx::result or stream.
Definition array.hxx:68
\n+
constexpr auto crend() const noexcept
Return end point of reverse iteration.
Definition array.hxx:121
\n+
std::array< std::size_t, DIMENSIONS > const & sizes() noexcept
Return the sizes of this array in each of its dimensions.
Definition array.hxx:82
\n+
constexpr auto front() const noexcept
Refer to the first element, if any.
Definition array.hxx:153
\n+
Low-level array parser.
Definition array.hxx:527
\n+
juncture
What's the latest thing found in the array?
Definition array.hxx:531
\n+
std::pair< juncture, std::string > get_next()
Parse the next step in the array.
Definition array.hxx:560
\n+
Connection to a database.
Definition connection.hxx:253
\n+
static TYPE null()
Return a null value.
\n+
static bool has_null
Does this type have a null value?
Definition strconv.hxx:95
\n
\n
\n \n
\n \n
\n \n \n", "details": [{"source1": "html2text {}", "source2": "html2text {}", "unified_diff": "@@ -1,409 +1,554 @@\n \n \n \n \n \n libpqxx\u00a07.8.1\n \n-stream_to.hxx\n- 1/* Definition of the pqxx::stream_to class.\n+array.hxx\n+ 1/* Handling of SQL arrays.\n 2 *\n- 3 * pqxx::stream_to enables optimized batch updates to a database table.\n+ 3 * DO NOT INCLUDE THIS FILE DIRECTLY; include pqxx/field instead.\n 4 *\n- 5 * DO NOT INCLUDE THIS FILE DIRECTLY; include pqxx/stream_to.hxx instead.\n+ 5 * Copyright (c) 2000-2023, Jeroen T. Vermeulen.\n 6 *\n- 7 * Copyright (c) 2000-2023, Jeroen T. Vermeulen.\n- 8 *\n- 9 * See COPYING for copyright license. If you did not receive a file called\n- 10 * COPYING with this source code, please notify the distributor of this\n- 11 * mistake, or contact the author.\n- 12 */\n- 13#ifndef PQXX_H_STREAM_TO\n- 14#define PQXX_H_STREAM_TO\n- 15\n- 16#if !defined(PQXX_HEADER_PRE)\n- 17# error \"Include libpqxx headers as , not .\"\n- 18#endif\n- 19\n- 20#include \"pqxx/separated_list.hxx\"\n- 21#include \"pqxx/transaction_base.hxx\"\n- 22\n- 23\n- 24namespace pqxx\n- 25{\n- 27\n-80class PQXX_LIBEXPORT stream_to : transaction_focus\n- 81{\n- 82public:\n- 84\n-104 static stream_to raw_table(\n- 105 transaction_base &tx, std::string_view path, std::string_view columns =\n-\"\")\n- 106 {\n- 107 return {tx, path, columns};\n- 108 }\n- 109\n- 111\n-120 static stream_to table(\n- 121 transaction_base &tx, table_path path,\n- 122 std::initializer_list columns = {})\n- 123 {\n- 124 auto const &conn{tx.conn()};\n- 125 return raw_table(tx, conn.quote_table(path), conn.quote_columns(columns));\n- 126 }\n- 127\n- 128#if defined(PQXX_HAVE_CONCEPTS)\n+ 7 * See COPYING for copyright license. If you did not receive a file called\n+ 8 * COPYING with this source code, please notify the distributor of this\n+ 9 * mistake, or contact the author.\n+ 10 */\n+ 11#ifndef PQXX_H_ARRAY\n+ 12#define PQXX_H_ARRAY\n+ 13\n+ 14#if !defined(PQXX_HEADER_PRE)\n+ 15# error \"Include libpqxx headers as , not .\"\n+ 16#endif\n+ 17\n+ 18#include \n+ 19#include \n+ 20#include \n+ 21#include \n+ 22#include \n+ 23#include \n+ 24#include \n+ 25\n+ 26#include \"pqxx/connection.hxx\"\n+ 27#include \"pqxx/internal/array-composite.hxx\"\n+ 28#include \"pqxx/internal/encoding_group.hxx\"\n+ 29#include \"pqxx/internal/encodings.hxx\"\n+ 30\n+ 31\n+32namespace pqxx\n+ 33{\n+ 34// TODO: Specialise for string_view/zview, allocate all strings in one\n+buffer.\n+ 35\n+ 37\n+ 52template<\n+ 53 typename ELEMENT, std::size_t DIMENSIONS = 1u,\n+ 54 char SEPARATOR = array_separator>\n+55class array final\n+ 56{\n+ 57public:\n+ 59\n+68 array(std::string_view data, connection const &conn) :\n+ 69 array{data, pqxx::internal::enc_group(conn.encoding_id())}\n+ 70 {}\n+ 71\n+ 73\n+75 constexpr std::size_t dimensions() noexcept { return DIMENSIONS; }\n+ 76\n+ 78\n+82 std::array const &sizes() noexcept\n+ 83 {\n+ 84 return m_extents;\n+ 85 }\n+ 86\n+87 template ELEMENT const &at(INDEX... index) const\n+ 88 {\n+ 89 static_assert(sizeof...(index) == DIMENSIONS);\n+ 90 check_bounds(index...);\n+ 91 return m_elts.at(locate(index...));\n+ 92 }\n+ 93\n+ 95\n+103 template ELEMENT const &operator[](INDEX... index) const\n+ 104 {\n+ 105 static_assert(sizeof...(index) == DIMENSIONS);\n+ 106 return m_elts[locate(index...)];\n+ 107 }\n+ 108\n+ 110\n+115 constexpr auto cbegin() const noexcept { return m_elts.cbegin(); }\n+117 constexpr auto cend() const noexcept { return m_elts.cend(); }\n+119 constexpr auto crbegin() const noexcept { return m_elts.crbegin(); }\n+121 constexpr auto crend() const noexcept { return m_elts.crend(); }\n+ 122\n+ 124\n+127 constexpr std::size_t size() const noexcept { return m_elts.size(); }\n+ 128\n 130\n- 137 template\n- 138 static stream_to\n- 139 table(transaction_base &tx, table_path path, COLUMNS const &columns)\n- 140 {\n- 141 auto const &conn{tx.conn()};\n- 142 return stream_to::raw_table(\n- 143 tx, conn.quote_table(path), tx.conn().quote_columns(columns));\n- 144 }\n- 145\n- 147\n- 154 template\n- 155 static stream_to\n- 156 table(transaction_base &tx, std::string_view path, COLUMNS const &columns)\n- 157 {\n- 158 return stream_to::raw_table(tx, path, tx.conn().quote_columns(columns));\n- 159 }\n- 160#endif // PQXX_HAVE_CONCEPTS\n- 161\n- 163\n-172 [[deprecated(\"Use table() or raw_table() factory.\")]] stream_to(\n- 173 transaction_base &tx, std::string_view table_name) :\n- 174 stream_to{tx, table_name, \"\"sv}\n- 175 {}\n- 176\n- 178\n- 180 template\n- 181 [[deprecated(\"Use table() or raw_table() factory.\")]] stream_to(\n- 182 transaction_base &, std::string_view table_name, Columns const &columns);\n- 183\n- 185\n- 187 template\n- 188 [[deprecated(\"Use table() or raw_table() factory.\")]] stream_to(\n- 189 transaction_base &, std::string_view table_name, Iter columns_begin,\n- 190 Iter columns_end);\n- 191\n-192 explicit stream_to(stream_to &&other) :\n- 193 // (This first step only moves the transaction_focus base-class\n- 194 // object.)\n- 195 transaction_focus{std::move(other)},\n- 196 m_finished{other.m_finished},\n- 197 m_buffer{std::move(other.m_buffer)},\n- 198 m_field_buf{std::move(other.m_field_buf)},\n- 199 m_finder{other.m_finder}\n- 200 {\n- 201 other.m_finished = true;\n- 202 }\n- 203 ~stream_to() noexcept;\n- 204\n-206 [[nodiscard]] constexpr operator bool() const noexcept\n+145 constexpr auto ssize() const noexcept\n+ 146 {\n+ 147 return static_cast(size());\n+ 148 }\n+ 149\n+ 151\n+153 constexpr auto front() const noexcept { return m_elts.front(); }\n+ 154\n+ 156\n+158 constexpr auto back() const noexcept { return m_elts.back(); }\n+ 159\n+ 160private:\n+ 162\n+ 170 void check_dims(std::string_view data)\n+ 171 {\n+ 172 auto sz{std::size(data)};\n+ 173 if (sz < DIMENSIONS * 2)\n+ 174 throw conversion_error{pqxx::internal::concat(\n+ 175 \"Trying to parse a \", DIMENSIONS, \"-dimensional array out of '\", data,\n+ 176 \"'.\")};\n+ 177\n+ 178 // Making some assumptions here:\n+ 179 // * The array holds no extraneous whitespace.\n+ 180 // * None of the sub-arrays can be null.\n+ 181 // * Only ASCII characters start off with a byte in the 0-127 range.\n+ 182 //\n+ 183 // Given those, the input must start with a sequence of DIMENSIONS bytes\n+ 184 // with the ASCII value for '{'; and likewise it must end with a sequence\n+ 185 // of DIMENSIONS bytes with the ASCII value for '}'.\n+ 186\n+ 187 if (data[0] != '{')\n+ 188 throw conversion_error{\"Malformed array: does not start with '{'.\"};\n+ 189 for (std::size_t i{0}; i < DIMENSIONS; ++i)\n+ 190 if (data[i] != '{')\n+ 191 throw conversion_error{pqxx::internal::concat(\n+ 192 \"Expecting \", DIMENSIONS, \"-dimensional array, but found \", i, \".\")};\n+ 193 if (data[DIMENSIONS] == '{')\n+ 194 throw conversion_error{pqxx::internal::concat(\n+ 195 \"Tried to parse \", DIMENSIONS,\n+ 196 \"-dimensional array from array data that has more dimensions.\")};\n+ 197 for (std::size_t i{0}; i < DIMENSIONS; ++i)\n+ 198 if (data[sz - 1 - i] != '}')\n+ 199 throw conversion_error{\n+ 200 \"Malformed array: does not end in the right number of '}'.\"};\n+ 201 }\n+ 202\n+ 203 explicit array(std::string_view data, pqxx::internal::encoding_group enc)\n+ 204 {\n+ 205 using group = pqxx::internal::encoding_group;\n+ 206 switch (enc)\n 207 {\n- 208 return not m_finished;\n- 209 }\n-211 [[nodiscard]] constexpr bool operator!() const noexcept\n- 212 {\n- 213 return m_finished;\n- 214 }\n- 215\n- 217\n- 223 void complete();\n- 224\n- 226\n-235 template stream_to &operator<<(Row const &row)\n- 236 {\n- 237 write_row(row);\n- 238 return *this;\n- 239 }\n- 240\n- 242\n- 246 stream_to &operator<<(stream_from &);\n- 247\n- 249\n-255 template void write_row(Row const &row)\n- 256 {\n- 257 fill_buffer(row);\n- 258 write_buffer();\n- 259 }\n- 260\n- 262\n-265 template void write_values(Ts const &...fields)\n- 266 {\n- 267 fill_buffer(fields...);\n- 268 write_buffer();\n- 269 }\n- 270\n- 271private:\n- 273 stream_to(\n- 274 transaction_base &tx, std::string_view path, std::string_view columns);\n- 275\n- 276 bool m_finished = false;\n- 277\n- 279 std::string m_buffer;\n- 280\n- 282 std::string m_field_buf;\n+ 208 case group::MONOBYTE: parse(data); break;\n+ 209 case group::BIG5: parse(data); break;\n+ 210 case group::EUC_CN: parse(data); break;\n+ 211 case group::EUC_JP: parse(data); break;\n+ 212 case group::EUC_KR: parse(data); break;\n+ 213 case group::EUC_TW: parse(data); break;\n+ 214 case group::GB18030: parse(data); break;\n+ 215 case group::GBK: parse(data); break;\n+ 216 case group::JOHAB: parse(data); break;\n+ 217 case group::MULE_INTERNAL: parse(data); break;\n+ 218 case group::SJIS: parse(data); break;\n+ 219 case group::UHC: parse(data); break;\n+ 220 case group::UTF8: parse(data); break;\n+ 221 }\n+ 222 }\n+ 223\n+ 225\n+ 228 std::size_t parse_field_end(std::string_view data, std::size_t here) const\n+ 229 {\n+ 230 auto const sz{std::size(data)};\n+ 231 if (here < sz)\n+ 232 switch (data[here])\n+ 233 {\n+ 234 case SEPARATOR:\n+ 235 ++here;\n+ 236 if (here >= sz)\n+ 237 throw conversion_error{\"Array looks truncated.\"};\n+ 238 switch (data[here])\n+ 239 {\n+ 240 case SEPARATOR:\n+ 241 throw conversion_error{\"Array contains double separator.\"};\n+ 242 case '}': throw conversion_error{\"Array contains trailing separator.\"};\n+ 243 default: break;\n+ 244 }\n+ 245 break;\n+ 246 case '}': break;\n+ 247 default:\n+ 248 throw conversion_error{pqxx::internal::concat(\n+ 249 \"Unexpected character in array: \",\n+ 250 static_cast(static_cast(data[here])),\n+ 251 \" where separator or closing brace expected.\")};\n+ 252 }\n+ 253 return here;\n+ 254 }\n+ 255\n+ 257\n+ 262 constexpr std::size_t estimate_elements(std::string_view data) const\n+noexcept\n+ 263 {\n+ 264 // Dirty trick: just count the number of bytes that look as if they may be\n+ 265 // separators. At the very worst we may overestimate by a factor of two or\n+ 266 // so, in exceedingly rare cases, on some encodings.\n+ 267 auto const separators{\n+ 268 std::count(std::begin(data), std::end(data), SEPARATOR)};\n+ 269 // The number of dimensions makes no difference here. It's still one\n+ 270 // separator between consecutive elements, just possibly with some extra\n+ 271 // braces as well.\n+ 272 return static_cast(separators + 1);\n+ 273 }\n+ 274\n+ 275 template\n+ 276 void parse(std::string_view data)\n+ 277 {\n+ 278 static_assert(DIMENSIONS > 0u, \"Can't create a zero-dimensional array.\");\n+ 279 auto const sz{std::size(data)};\n+ 280 check_dims(data);\n+ 281\n+ 282 m_elts.reserve(estimate_elements(data));\n 283\n- 285 internal::char_finder_func *m_finder;\n- 286\n- 288 void write_raw_line(std::string_view);\n+ 284 // We discover the array's extents along each of the dimensions, starting\n+ 285 // with the final dimension and working our way towards the first. At any\n+ 286 // given point during parsing, we know the extents starting at this\n+ 287 // dimension.\n+ 288 std::size_t know_extents_from{DIMENSIONS};\n 289\n- 291\n- 293 void write_buffer();\n- 294\n- 296 static constexpr std::string_view null_field{\"\\\\N\\t\"};\n+ 290 // Currently parsing this dimension. We start off at -1, relying on C++'s\n+ 291 // well-defined rollover for unsigned numbers.\n+ 292 // The actual outermost dimension of the array is 0, and the innermost is\n+ 293 // at the end. But, the array as a whole is enclosed in braces just like\n+ 294 // each row. So we act like there's an anomalous \"outer\" dimension holding\n+ 295 // the entire array.\n+ 296 constexpr std::size_t outer{std::size_t{0u} - std::size_t{1u}};\n 297\n- 299 template\n- 300 static std::enable_if_t::always_null, std::size_t>\n- 301 estimate_buffer(T const &)\n- 302 {\n- 303 return std::size(null_field);\n- 304 }\n- 305\n- 307\n- 310 template\n- 311 static std::enable_if_t::always_null, std::size_t>\n- 312 estimate_buffer(T const &field)\n+ 298 // We start parsing at the fictional outer dimension. The input begins\n+ 299 // with opening braces, one for each dimension, so we'll start off by\n+ 300 // bumping all the way to the innermost dimension.\n+ 301 std::size_t dim{outer};\n+ 302\n+ 303 // Extent counters, one per \"real\" dimension.\n+ 304 // Note initialiser syntax; this should zero-initialise all elements.\n+ 305 std::array extents{};\n+ 306#if !defined(NDEBUG)\n+ 307 for (auto const e : extents) assert(e == 0u);\n+ 308#endif\n+ 309\n+ 310 // Current parsing position.\n+ 311 std::size_t here{0};\n+ 312 while (here < sz)\n 313 {\n- 314 return is_null(field) ? std::size(null_field) : size_buffer(field);\n- 315 }\n- 316\n- 318 void escape_field_to_buffer(std::string_view data);\n- 319\n- 321\n- 327 template\n- 328 std::enable_if_t::always_null>\n- 329 append_to_buffer(Field const &f)\n- 330 {\n- 331 // We append each field, terminated by a tab. That will leave us with\n- 332 // one tab too many, assuming we write any fields at all; we remove that\n- 333 // at the end.\n- 334 if (is_null(f))\n- 335 {\n- 336 // Easy. Append null and tab in one go.\n- 337 m_buffer.append(null_field);\n- 338 }\n- 339 else\n- 340 {\n- 341 // Convert f into m_buffer.\n- 342\n- 343 using traits = string_traits;\n- 344 auto const budget{estimate_buffer(f)};\n- 345 auto const offset{std::size(m_buffer)};\n- 346\n- 347 if constexpr (std::is_arithmetic_v)\n- 348 {\n- 349 // Specially optimised for \"safe\" types, which never need any\n- 350 // escaping. Convert straight into m_buffer.\n- 351\n- 352 // The budget we get from size_buffer() includes room for the trailing\n- 353 // zero, which we must remove. But we're also inserting tabs between\n- 354 // fields, so we re-purpose the extra byte for that.\n- 355 auto const total{offset + budget};\n- 356 m_buffer.resize(total);\n- 357 auto const data{m_buffer.data()};\n- 358 char *const end{traits::into_buf(data + offset, data + total, f)};\n- 359 *(end - 1) = '\\t';\n- 360 // Shrink to fit. Keep the tab though.\n- 361 m_buffer.resize(static_cast(end - data));\n- 362 }\n- 363 else if constexpr (\n- 364 std::is_same_v or\n- 365 std::is_same_v or\n- 366 std::is_same_v)\n- 367 {\n- 368 // This string may need escaping.\n- 369 m_field_buf.resize(budget);\n- 370 escape_field_to_buffer(f);\n- 371 }\n- 372 else if constexpr (\n- 373 std::is_same_v> or\n- 374 std::is_same_v> or\n- 375 std::is_same_v>)\n- 376 {\n- 377 // Optional string. It's not null (we checked for that above), so...\n- 378 // Treat like a string.\n- 379 m_field_buf.resize(budget);\n- 380 escape_field_to_buffer(f.value());\n- 381 }\n- 382 // TODO: Support deleter template argument on unique_ptr.\n- 383 else if constexpr (\n- 384 std::is_same_v> or\n- 385 std::is_same_v> or\n- 386 std::is_same_v> or\n- 387 std::is_same_v> or\n- 388 std::is_same_v> or\n- 389 std::is_same_v>)\n- 390 {\n- 391 // TODO: Can we generalise this elegantly without Concepts?\n- 392 // Effectively also an optional string. It's not null (we checked\n- 393 // for that above).\n- 394 m_field_buf.resize(budget);\n- 395 escape_field_to_buffer(*f);\n- 396 }\n- 397 else\n- 398 {\n- 399 // This field needs to be converted to a string, and after that,\n- 400 // escaped as well.\n- 401 m_field_buf.resize(budget);\n- 402 auto const data{m_field_buf.data()};\n- 403 escape_field_to_buffer(\n- 404 traits::to_buf(data, data + std::size(m_field_buf), f));\n- 405 }\n- 406 }\n- 407 }\n- 408\n- 410\n- 416 template\n- 417 std::enable_if_t::always_null>\n- 418 append_to_buffer(Field const &)\n- 419 {\n- 420 m_buffer.append(null_field);\n- 421 }\n+ 314 if (data[here] == '{')\n+ 315 {\n+ 316 if (dim == outer)\n+ 317 {\n+ 318 // This must be the initial opening brace.\n+ 319 if (know_extents_from != DIMENSIONS)\n+ 320 throw conversion_error{\n+ 321 \"Array text representation closed and reopened its outside \"\n+ 322 \"brace pair.\"};\n+ 323 assert(here == 0);\n+ 324 }\n+ 325 else\n+ 326 {\n+ 327 if (dim >= (DIMENSIONS - 1))\n+ 328 throw conversion_error{\n+ 329 \"Array seems to have inconsistent number of dimensions.\"};\n+ 330 ++extents[dim];\n+ 331 }\n+ 332 // (Rolls over to zero if we're coming from the outer dimension.)\n+ 333 ++dim;\n+ 334 extents[dim] = 0u;\n+ 335 ++here;\n+ 336 }\n+ 337 else if (data[here] == '}')\n+ 338 {\n+ 339 if (dim == outer)\n+ 340 throw conversion_error{\"Array has spurious '}'.\"};\n+ 341 if (dim < know_extents_from)\n+ 342 {\n+ 343 // We just finished parsing our first row in this dimension.\n+ 344 // Now we know the array dimension's extent.\n+ 345 m_extents[dim] = extents[dim];\n+ 346 know_extents_from = dim;\n+ 347 }\n+ 348 else\n+ 349 {\n+ 350 if (extents[dim] != m_extents[dim])\n+ 351 throw conversion_error{\"Rows in array have inconsistent sizes.\"};\n+ 352 }\n+ 353 // Bump back down to the next-lower dimension. Which may be the outer\n+ 354 // dimension, through underflow.\n+ 355 --dim;\n+ 356 ++here;\n+ 357 here = parse_field_end(data, here);\n+ 358 }\n+ 359 else\n+ 360 {\n+ 361 // Found an array element. The actual elements always live in the\n+ 362 // \"inner\" dimension.\n+ 363 if (dim != DIMENSIONS - 1)\n+ 364 throw conversion_error{\n+ 365 \"Malformed array: found element where sub-array was expected.\"};\n+ 366 assert(dim != outer);\n+ 367 ++extents[dim];\n+ 368 std::size_t end;\n+ 369 switch (data[here])\n+ 370 {\n+ 371 case '\\0': throw conversion_error{\"Unexpected zero byte in array.\"};\n+ 372 case ',': throw conversion_error{\"Array contains empty field.\"};\n+ 373 case '\"': {\n+ 374 // Double-quoted string. We parse it into a buffer before parsing\n+ 375 // the resulting string as an element. This seems wasteful: the\n+ 376 // string might not contain any special characters. So it's\n+ 377 // tempting to check, and try to use a string_view and avoid a\n+ 378 // useless copy step. But. Even besides the branch prediction\n+ 379 // risk, the very fact that the back-end chose to quote the string\n+ 380 // indicates that there is some kind of special character in there.\n+ 381 // So in practice, this optimisation would only apply if the only\n+ 382 // special characters in the string were commas.\n+ 383 end = pqxx::internal::scan_double_quoted_string(\n+ 384 std::data(data), std::size(data), here);\n+ 385 // TODO: scan_double_quoted_string() with reusable buffer.\n+ 386 std::string const buf{\n+ 387 pqxx::internal::parse_double_quoted_string(\n+ 388 std::data(data), end, here)};\n+ 389 m_elts.emplace_back(from_string(buf));\n+ 390 }\n+ 391 break;\n+ 392 default: {\n+ 393 // Unquoted string. An unquoted string is always literal, no\n+ 394 // escaping or encoding, so we don't need to parse it into a\n+ 395 // buffer. We can just read it as a string_view.\n+ 396 end = pqxx::internal::scan_unquoted_string(\n+ 397 std::data(data), std::size(data), here);\n+ 398 std::string_view const field{\n+ 399 std::string_view{std::data(data) + here, end - here}};\n+ 400 if (field == \"NULL\")\n+ 401 {\n+ 402 if constexpr (nullness::has_null)\n+ 403 m_elts.emplace_back(nullness::null());\n+ 404 else\n+ 405 throw unexpected_null{pqxx::internal::concat(\n+ 406 \"Array contains a null \", type_name,\n+ 407 \". Consider making it an array of std::optional<\",\n+ 408 type_name, \"> instead.\")};\n+ 409 }\n+ 410 else\n+ 411 m_elts.emplace_back(from_string(field));\n+ 412 }\n+ 413 }\n+ 414 here = end;\n+ 415 here = parse_field_end(data, here);\n+ 416 }\n+ 417 }\n+ 418\n+ 419 if (dim != outer)\n+ 420 throw conversion_error{\"Malformed array; may be truncated.\"};\n+ 421 assert(know_extents_from == 0);\n 422\n- 424 template\n- 425 std::enable_if_t>\n- 426 fill_buffer(Container const &c)\n- 427 {\n- 428 // To avoid unnecessary allocations and deallocations, we run through c\n- 429 // twice: once to determine how much buffer space we may need, and once to\n- 430 // actually write it into the buffer.\n- 431 std::size_t budget{0};\n- 432 for (auto const &f : c) budget += estimate_buffer(f);\n- 433 m_buffer.reserve(budget);\n- 434 for (auto const &f : c) append_to_buffer(f);\n+ 423 init_factors();\n+ 424 }\n+ 425\n+ 427 void init_factors() noexcept\n+ 428 {\n+ 429 std::size_t factor{1};\n+ 430 for (std::size_t dim{DIMENSIONS - 1}; dim > 0; --dim)\n+ 431 {\n+ 432 factor *= m_extents[dim];\n+ 433 m_factors[dim - 1] = factor;\n+ 434 }\n 435 }\n 436\n- 438 template\n- 439 static std::size_t\n- 440 budget_tuple(Tuple const &t, std::index_sequence)\n- 441 {\n- 442 return (estimate_buffer(std::get(t)) + ...);\n- 443 }\n- 444\n- 446 template\n- 447 void append_tuple(Tuple const &t, std::index_sequence)\n+ 438 template std::size_t locate(INDEX... index) const\n+noexcept\n+ 439 {\n+ 440 static_assert(\n+ 441 sizeof...(index) == DIMENSIONS,\n+ 442 \"Indexing array with wrong number of dimensions.\");\n+ 443 return add_index(index...);\n+ 444 }\n+ 445\n+ 446 template\n+ 447 constexpr std::size_t add_index(OUTER outer, INDEX... indexes) const\n+noexcept\n 448 {\n- 449 (append_to_buffer(std::get(t)), ...);\n- 450 }\n- 451\n- 453 template void fill_buffer(std::tuple const &t)\n- 454 {\n- 455 using indexes = std::make_index_sequence;\n- 456\n- 457 m_buffer.reserve(budget_tuple(t, indexes{}));\n- 458 append_tuple(t, indexes{});\n- 459 }\n- 460\n- 462 template void fill_buffer(const Ts &...fields)\n- 463 {\n- 464 (..., append_to_buffer(fields));\n- 465 }\n- 466\n- 467 constexpr static std::string_view s_classname{\"stream_to\"};\n- 468};\n- 469\n- 470\n- 471template\n-472inline stream_to::stream_to(\n- 473 transaction_base &tx, std::string_view table_name, Columns const &columns)\n-:\n- 474 stream_to{tx, table_name, std::begin(columns), std::end(columns)}\n- 475{}\n- 476\n- 477\n- 478template\n-479inline stream_to::stream_to(\n- 480 transaction_base &tx, std::string_view table_name, Iter columns_begin,\n- 481 Iter columns_end) :\n- 482 stream_to{\n- 483 tx,\n- 484 tx.quote_name(\n- 485 table_name,\n- 486 separated_list(\",\", columns_begin, columns_end, [&tx](auto col) {\n- 487 return tx.quote_name(*col);\n- 488 }))}\n- 489{}\n- 490} // namespace pqxx\n- 491#endif\n+ 449 std::size_t const first{check_cast(outer, \"array index\"sv)};\n+ 450 if constexpr (sizeof...(indexes) == 0)\n+ 451 {\n+ 452 return first;\n+ 453 }\n+ 454 else\n+ 455 {\n+ 456 static_assert(sizeof...(indexes) < DIMENSIONS);\n+ 457 // (Offset by 1 here because the outer dimension is not in there.)\n+ 458 constexpr auto dimension{DIMENSIONS - (sizeof...(indexes) + 1)};\n+ 459 static_assert(dimension < DIMENSIONS);\n+ 460 return first * m_factors[dimension] + add_index(indexes...);\n+ 461 }\n+ 462 }\n+ 463\n+ 465\n+ 467 template\n+ 468 constexpr void check_bounds(OUTER outer, INDEX... indexes) const\n+ 469 {\n+ 470 std::size_t const first{check_cast(outer, \"array index\"sv)};\n+ 471 static_assert(sizeof...(indexes) < DIMENSIONS);\n+ 472 // (Offset by 1 here because the outer dimension is not in there.)\n+ 473 constexpr auto dimension{DIMENSIONS - (sizeof...(indexes) + 1)};\n+ 474 static_assert(dimension < DIMENSIONS);\n+ 475 if (first >= m_extents[dimension])\n+ 476 throw range_error{pqxx::internal::concat(\n+ 477 \"Array index for dimension \", dimension, \" is out of bounds: \", first,\n+ 478 \" >= \", m_extents[dimension])};\n+ 479\n+ 480 // Now check the rest of the indexes, if any.\n+ 481 if constexpr (sizeof...(indexes) > 0)\n+ 482 check_bounds(indexes...);\n+ 483 }\n+ 484\n+ 486 std::vector m_elts;\n+ 487\n+ 489 std::array m_extents;\n+ 490\n+ 492\n+ 499 std::array m_factors;\n+ 500};\n+ 501\n+ 502\n+ 504\n+526class PQXX_LIBEXPORT array_parser\n+ 527{\n+ 528public:\n+530 enum class juncture\n+ 531 {\n+ 533 row_start,\n+ 535 row_end,\n+ 537 null_value,\n+ 539 string_value,\n+ 541 done,\n+ 542 };\n+ 543\n+ 545\n+ 549 explicit array_parser(\n+ 550 std::string_view input,\n+ 551 internal::encoding_group = internal::encoding_group::MONOBYTE);\n+ 552\n+ 554\n+560 std::pair get_next() { return (this->*m_impl)(); }\n+ 561\n+ 562private:\n+ 563 std::string_view m_input;\n+ 564\n+ 566 std::size_t m_pos = 0u;\n+ 567\n+ 569\n+ 574 using implementation = std::pair (array_parser::*)\n+();\n+ 575\n+ 577 static implementation\n+ 578 specialize_for_encoding(pqxx::internal::encoding_group enc);\n+ 579\n+ 581 implementation m_impl;\n+ 582\n+ 584 template\n+ 585 std::pair parse_array_step();\n+ 586\n+ 587 template\n+ 588 std::string::size_type scan_double_quoted_string() const;\n+ 589 template\n+ 590 std::string parse_double_quoted_string(std::string::size_type end) const;\n+ 591 template\n+ 592 std::string::size_type scan_unquoted_string() const;\n+ 593 template\n+ 594 std::string parse_unquoted_string(std::string::size_type end) const;\n+ 595\n+ 596 template\n+ 597 std::string::size_type scan_glyph(std::string::size_type pos) const;\n+ 598 template\n+ 599 std::string::size_type\n+ 600 scan_glyph(std::string::size_type pos, std::string::size_type end) const;\n+ 601};\n+ 602} // namespace pqxx\n+ 603#endif\n pqxx\n The home of all libpqxx classes, functions, templates, etc.\n Definition array.hxx:33\n-pqxx::separated_list\n-std::string separated_list(std::string_view sep, ITER begin, ITER end, ACCESS\n-access)\n-Represent sequence of values as a string, joined by a given separator.\n-Definition separated_list.hxx:44\n-pqxx::operator<<\n-std::basic_ostream< CHAR > & operator<<(std::basic_ostream< CHAR > &s, field\n-const &value)\n-Write a result field to any type of stream.\n-Definition field.hxx:509\n-pqxx::table_path\n-std::initializer_list< std::string_view > table_path\n-Representation of a PostgreSQL table path.\n-Definition connection.hxx:188\n-pqxx::row\n-Reference to one row in a result.\n-Definition row.hxx:47\n-pqxx::stream_from\n-Stream data from the database.\n-Definition stream_from.hxx:79\n-pqxx::stream_to\n-Efficiently write data directly to a database table.\n-Definition stream_to.hxx:81\n-pqxx::stream_to::raw_table\n-static stream_to raw_table(transaction_base &tx, std::string_view path, std::\n-string_view columns=\"\")\n-Stream data to a pre-quoted table and columns.\n-Definition stream_to.hxx:104\n-pqxx::stream_to::operator!\n-constexpr bool operator!() const noexcept\n-Has this stream been through its concluding complete()?\n-Definition stream_to.hxx:211\n-pqxx::stream_to::table\n-static stream_to table(transaction_base &tx, table_path path, std::\n-initializer_list< std::string_view > columns={})\n-Create a stream_to writing to a named table and columns.\n-Definition stream_to.hxx:120\n-pqxx::stream_to::write_values\n-void write_values(Ts const &...fields)\n-Insert values as a row.\n-Definition stream_to.hxx:265\n-pqxx::stream_to::stream_to\n-stream_to(transaction_base &tx, std::string_view table_name)\n-Create a stream, without specifying columns.\n-Definition stream_to.hxx:172\n-pqxx::stream_to::stream_to\n-stream_to(stream_to &&other)\n-Definition stream_to.hxx:192\n-pqxx::stream_to::operator<<\n-stream_to & operator<<(Row const &row)\n-Insert a row of data.\n-Definition stream_to.hxx:235\n-pqxx::stream_to::write_row\n-void write_row(Row const &row)\n-Insert a row of data, given in the form of a std::tuple or container.\n-Definition stream_to.hxx:255\n-pqxx::transaction_base\n-Interface definition (and common code) for \"transaction\" classes.\n-Definition transaction_base.hxx:88\n-pqxx::transaction_base::conn\n-constexpr connection & conn() const noexcept\n-The connection in which this transaction lives.\n-Definition transaction_base.hxx:780\n-pqxx::transaction_base::quote_name\n-std::string quote_name(std::string_view identifier) const\n-Escape an SQL identifier for use in a query.\n-Definition transaction_base.hxx:231\n-pqxx::transaction_focus\n-Base class for things that monopolise a transaction's attention.\n-Definition transaction_focus.hxx:29\n+pqxx::array\n+An SQL array received from the database.\n+Definition array.hxx:56\n+pqxx::array::back\n+constexpr auto back() const noexcept\n+Refer to the last element, if any.\n+Definition array.hxx:158\n+pqxx::array::cend\n+constexpr auto cend() const noexcept\n+Return end point of iteration.\n+Definition array.hxx:117\n+pqxx::array::crbegin\n+constexpr auto crbegin() const noexcept\n+Begin reverse iteration.\n+Definition array.hxx:119\n+pqxx::array::operator[]\n+ELEMENT const & operator[](INDEX... index) const\n+Access element (without bounds check).\n+Definition array.hxx:103\n+pqxx::array::size\n+constexpr std::size_t size() const noexcept\n+Number of elements in the array.\n+Definition array.hxx:127\n+pqxx::array::ssize\n+constexpr auto ssize() const noexcept\n+Number of elements in the array (as a signed number).\n+Definition array.hxx:145\n+pqxx::array::dimensions\n+constexpr std::size_t dimensions() noexcept\n+How many dimensions does this array have?\n+Definition array.hxx:75\n+pqxx::array::cbegin\n+constexpr auto cbegin() const noexcept\n+Begin iteration of individual elements.\n+Definition array.hxx:115\n+pqxx::array::at\n+ELEMENT const & at(INDEX... index) const\n+Definition array.hxx:87\n+pqxx::array::array\n+array(std::string_view data, connection const &conn)\n+Parse an SQL array, read as text from a pqxx::result or stream.\n+Definition array.hxx:68\n+pqxx::array::crend\n+constexpr auto crend() const noexcept\n+Return end point of reverse iteration.\n+Definition array.hxx:121\n+pqxx::array::sizes\n+std::array< std::size_t, DIMENSIONS > const & sizes() noexcept\n+Return the sizes of this array in each of its dimensions.\n+Definition array.hxx:82\n+pqxx::array::front\n+constexpr auto front() const noexcept\n+Refer to the first element, if any.\n+Definition array.hxx:153\n+pqxx::array_parser\n+Low-level array parser.\n+Definition array.hxx:527\n+pqxx::array_parser::juncture\n+juncture\n+What's the latest thing found in the array?\n+Definition array.hxx:531\n+pqxx::array_parser::get_next\n+std::pair< juncture, std::string > get_next()\n+Parse the next step in the array.\n+Definition array.hxx:560\n+pqxx::connection\n+Connection to a database.\n+Definition connection.hxx:253\n+pqxx::nullness::null\n+static TYPE null()\n+Return a null value.\n+pqxx::nullness::has_null\n+static bool has_null\n+Does this type have a null value?\n+Definition strconv.hxx:95\n * include\n * pqxx\n- * stream_to.hxx\n+ * array.hxx\n * Generated by [doxygen] 1.9.8\n"}]}, {"source1": "./usr/share/doc/libpqxx-doc/html/a00095_source.html", "source2": "./usr/share/doc/libpqxx-doc/html/a00095_source.html", "unified_diff": "@@ -1,15 +1,15 @@\n \n \n \n \n \n \n \n-libpqxx: row.hxx Source File\n+libpqxx: notification.hxx Source File\n \n \n \n \n \n \n \n@@ -60,620 +60,82 @@\n \n
\n
\n-
row.hxx
\n+
notification.hxx
\n
\n
\n-
1/* Definitions for the pqxx::result class and support classes.
\n+
1/* Definition of the pqxx::notification_receiver functor interface.
\n
2 *
\n-
3 * pqxx::result represents the set of result rows from a database query.
\n+
3 * pqxx::notification_receiver handles incoming notifications.
\n
4 *
\n-
5 * DO NOT INCLUDE THIS FILE DIRECTLY; include pqxx/result instead.
\n+
5 * DO NOT INCLUDE THIS FILE DIRECTLY; include pqxx/notification instead.
\n
6 *
\n
7 * Copyright (c) 2000-2023, Jeroen T. Vermeulen.
\n
8 *
\n
9 * See COPYING for copyright license. If you did not receive a file called
\n
10 * COPYING with this source code, please notify the distributor of this
\n
11 * mistake, or contact the author.
\n
12 */
\n-
13#ifndef PQXX_H_ROW
\n-
14#define PQXX_H_ROW
\n+
13#ifndef PQXX_H_NOTIFICATION
\n+
14#define PQXX_H_NOTIFICATION
\n
15
\n
16#if !defined(PQXX_HEADER_PRE)
\n
17# error "Include libpqxx headers as <pqxx/header>, not <pqxx/header.hxx>."
\n
18#endif
\n
19
\n-
20#include "pqxx/except.hxx"
\n-
21#include "pqxx/field.hxx"
\n-
22#include "pqxx/result.hxx"
\n+
20#include <string>
\n+
21
\n+
22#include "pqxx/types.hxx"
\n
23
\n-
24#include "pqxx/internal/concat.hxx"
\n-
25
\n-
26namespace pqxx::internal
\n-
27{
\n-
28template<typename... T> class result_iter;
\n-
29} // namespace pqxx::internal
\n-
30
\n-
31
\n-
32namespace pqxx
\n-
33{
\n-
35
\n-
\n-
46class PQXX_LIBEXPORT row
\n-
47{
\n-
48public:
\n-\n-\n-\n-\n-\n-\n-\n-\n-
57
\n-
58 row() noexcept = default;
\n-
59 row(row &&) noexcept = default;
\n-
60 row(row const &) noexcept = default;
\n-
61 row &operator=(row const &) noexcept = default;
\n-
62 row &operator=(row &&) noexcept = default;
\n-
63
\n-
68 [[nodiscard]] PQXX_PURE bool operator==(row const &) const noexcept;
\n-
\n-
69 [[nodiscard]] bool operator!=(row const &rhs) const noexcept
\n-
70 {
\n-
71 return not operator==(rhs);
\n-
72 }
\n-
\n+
24
\n+
25namespace pqxx
\n+
26{
\n+
28
\n+
\n+
56class PQXX_LIBEXPORT PQXX_NOVTABLE notification_receiver
\n+
57{
\n+
58public:
\n+
60
\n+
64 notification_receiver(connection &c, std::string_view channel);
\n+\n+\n+
70 virtual ~notification_receiver();
\n+
71
\n+
73 [[nodiscard]] std::string const &channel() const & { return m_channel; }
\n
74
\n-
75 [[nodiscard]] const_iterator begin() const noexcept;
\n-
76 [[nodiscard]] const_iterator cbegin() const noexcept;
\n-
77 [[nodiscard]] const_iterator end() const noexcept;
\n-
78 [[nodiscard]] const_iterator cend() const noexcept;
\n-
79
\n-
84 [[nodiscard]] reference front() const noexcept;
\n-
85 [[nodiscard]] reference back() const noexcept;
\n-
86
\n-
87 [[nodiscard]] const_reverse_row_iterator rbegin() const noexcept;
\n-
88 [[nodiscard]] const_reverse_row_iterator crbegin() const noexcept;
\n-
89 [[nodiscard]] const_reverse_row_iterator rend() const noexcept;
\n-
90 [[nodiscard]] const_reverse_row_iterator crend() const noexcept;
\n-
91
\n-
92 [[nodiscard]] reference operator[](size_type) const noexcept;
\n-
96 [[nodiscard]] reference operator[](zview col_name) const;
\n-
97
\n-
98 reference at(size_type) const;
\n-
102 reference at(zview col_name) const;
\n-
103
\n-
\n-
104 [[nodiscard]] constexpr size_type size() const noexcept
\n-
105 {
\n-
106 return m_end - m_begin;
\n-
107 }
\n-
\n-
108
\n-
109 [[deprecated("Swap iterators, not rows.")]] void swap(row &) noexcept;
\n-
110
\n-
\n-
112 [[nodiscard]] constexpr result::size_type rownumber() const noexcept
\n-
113 {
\n-
114 return m_index;
\n-
115 }
\n-
\n-
116
\n-
122 [[nodiscard]] size_type column_number(zview col_name) const;
\n-
123
\n-
125 [[nodiscard]] oid column_type(size_type) const;
\n-
126
\n-
\n-
128 [[nodiscard]] oid column_type(zview col_name) const
\n-
129 {
\n-
130 return column_type(column_number(col_name));
\n-
131 }
\n-
\n-
132
\n-
134 [[nodiscard]] oid column_table(size_type col_num) const;
\n-
135
\n-
\n-
137 [[nodiscard]] oid column_table(zview col_name) const
\n-
138 {
\n-
139 return column_table(column_number(col_name));
\n-
140 }
\n-
\n-
141
\n-
143
\n-
150 [[nodiscard]] size_type table_column(size_type) const;
\n-
151
\n-
\n-
153 [[nodiscard]] size_type table_column(zview col_name) const
\n-
154 {
\n-
155 return table_column(column_number(col_name));
\n-
156 }
\n-
\n-
158
\n-
\n-
159 [[nodiscard]] constexpr result::size_type num() const noexcept
\n-
160 {
\n-
161 return rownumber();
\n-
162 }
\n-
\n-
163
\n-
175 [[deprecated("Row slicing is going away. File a bug if you need it.")]] row
\n-
176 slice(size_type sbegin, size_type send) const;
\n-
177
\n-
179 [[nodiscard, deprecated("Row slicing is going away.")]] PQXX_PURE bool
\n-
180 empty() const noexcept;
\n-
181
\n-
183
\n-
\n-
188 template<typename Tuple> void to(Tuple &t) const
\n-
189 {
\n-
190 check_size(std::tuple_size_v<Tuple>);
\n-
191 convert(t);
\n-
192 }
\n-
\n-
193
\n-
195
\n-
\n-
200 template<typename... TYPE> std::tuple<TYPE...> as() const
\n-
201 {
\n-
202 check_size(sizeof...(TYPE));
\n-
203 using seq = std::make_index_sequence<sizeof...(TYPE)>;
\n-
204 return get_tuple<std::tuple<TYPE...>>(seq{});
\n-
205 }
\n-
\n-
206
\n-
207protected:
\n-
208 friend class const_row_iterator;
\n-
209 friend class result;
\n-
210 row(result const &r, result_size_type index, size_type cols) noexcept;
\n-
211
\n-
\n-
213 void check_size(size_type expected) const
\n-
214 {
\n-
215 if (size() != expected)
\n-
216 throw usage_error{internal::concat(
\n-
217 "Tried to extract ", expected, " field(s) from a row of ", size(),
\n-
218 ".")};
\n-
219 }
\n-
\n-
220
\n-
222
\n-
\n-
225 template<typename TUPLE> TUPLE as_tuple() const
\n-
226 {
\n-
227 using seq = std::make_index_sequence<std::tuple_size_v<TUPLE>>;
\n-
228 return get_tuple<TUPLE>(seq{});
\n-
229 }
\n-
\n-
230
\n-
231 template<typename... T> friend class pqxx::internal::result_iter;
\n-
\n-
233 template<typename Tuple> void convert(Tuple &t) const
\n-
234 {
\n-
235 extract_fields(t, std::make_index_sequence<std::tuple_size_v<Tuple>>{});
\n-
236 }
\n-
\n-
237
\n-
238 friend class field;
\n-
239
\n-\n-
242
\n-
244
\n-
248 result::size_type m_index = 0;
\n-
249
\n-
250 // TODO: Remove m_begin and (if possible) m_end when we remove slice().
\n-
252 size_type m_begin = 0;
\n-
254 size_type m_end = 0;
\n-
255
\n-
256private:
\n-
257 template<typename Tuple, std::size_t... indexes>
\n-
258 void extract_fields(Tuple &t, std::index_sequence<indexes...>) const
\n-
259 {
\n-
260 (extract_value<Tuple, indexes>(t), ...);
\n-
261 }
\n-
262
\n-
263 template<typename Tuple, std::size_t index>
\n-
264 void extract_value(Tuple &t) const;
\n-
265
\n-
267 template<typename TUPLE, std::size_t... indexes>
\n-
268 auto get_tuple(std::index_sequence<indexes...>) const
\n-
269 {
\n-
270 return std::make_tuple(get_field<TUPLE, indexes>()...);
\n-
271 }
\n-
272
\n-
274 template<typename TUPLE, std::size_t index> auto get_field() const
\n-
275 {
\n-
276 return (*this)[index].as<std::tuple_element_t<index, TUPLE>>();
\n-
277 }
\n-
278};
\n-
\n-
279
\n-
280
\n-
\n-
282class PQXX_LIBEXPORT const_row_iterator : public field
\n-
283{
\n-
284public:
\n-
285 using iterator_category = std::random_access_iterator_tag;
\n-
286 using value_type = field const;
\n-
287 using pointer = field const *;
\n-\n-\n-\n-
291
\n-
292#include "pqxx/internal/ignore-deprecated-pre.hxx"
\n-
293 const_row_iterator() noexcept = default;
\n-
294#include "pqxx/internal/ignore-deprecated-post.hxx"
\n-
\n-
295 const_row_iterator(row const &t, row_size_type c) noexcept :
\n-
296 field{t.m_result, t.m_index, c}
\n-
297 {}
\n-
\n-
298 const_row_iterator(field const &F) noexcept : field{F} {}
\n-
299 const_row_iterator(const_row_iterator const &) noexcept = default;
\n-\n-
301
\n-
306 [[nodiscard]] constexpr pointer operator->() const noexcept { return this; }
\n-
307 [[nodiscard]] reference operator*() const noexcept { return {*this}; }
\n-
309
\n-
314 const_row_iterator &operator=(const_row_iterator const &) noexcept = default;
\n-\n-
316
\n-
317 const_row_iterator operator++(int) noexcept;
\n-
\n-
318 const_row_iterator &operator++() noexcept
\n-
319 {
\n-
320 ++m_col;
\n-
321 return *this;
\n-
322 }
\n-
\n-
323 const_row_iterator operator--(int) noexcept;
\n-
\n-\n-
325 {
\n-
326 --m_col;
\n-
327 return *this;
\n-
328 }
\n-
\n-
329
\n-
\n-\n-
331 {
\n-
332 m_col = size_type(difference_type(m_col) + i);
\n-
333 return *this;
\n-
334 }
\n-
\n-
\n-\n-
336 {
\n-
337 m_col = size_type(difference_type(m_col) - i);
\n-
338 return *this;
\n-
339 }
\n-
\n-
341
\n-
346 [[nodiscard]] constexpr bool
\n-
\n-
347 operator==(const_row_iterator const &i) const noexcept
\n-
348 {
\n-
349 return col() == i.col();
\n-
350 }
\n-
\n-
351 [[nodiscard]] constexpr bool
\n-
\n-
352 operator!=(const_row_iterator const &i) const noexcept
\n-
353 {
\n-
354 return col() != i.col();
\n-
355 }
\n-
\n-
\n-
356 [[nodiscard]] constexpr bool
\n-
357 operator<(const_row_iterator const &i) const noexcept
\n-
358 {
\n-
359 return col() < i.col();
\n-
360 }
\n-
\n-
\n-
361 [[nodiscard]] constexpr bool
\n-
362 operator<=(const_row_iterator const &i) const noexcept
\n-
363 {
\n-
364 return col() <= i.col();
\n-
365 }
\n-
\n-
366 [[nodiscard]] constexpr bool
\n-
\n-
367 operator>(const_row_iterator const &i) const noexcept
\n-
368 {
\n-
369 return col() > i.col();
\n-
370 }
\n-
\n-
371 [[nodiscard]] constexpr bool
\n-
\n-
372 operator>=(const_row_iterator const &i) const noexcept
\n-
373 {
\n-
374 return col() >= i.col();
\n-
375 }
\n-
\n-
377
\n-
382 [[nodiscard]] inline const_row_iterator
\n-
383 operator+(difference_type) const noexcept;
\n-
384
\n-
385 friend const_row_iterator
\n-
386 operator+(difference_type, const_row_iterator const &) noexcept;
\n-
387
\n-
388 [[nodiscard]] inline const_row_iterator
\n-
\n-
389 operator-(difference_type) const noexcept;
\n-
390 [[nodiscard]] inline difference_type
\n-
\n-
391 operator-(const_row_iterator const &) const noexcept;
\n-
393};
\n-
394
\n-
395
\n-
\n-
397class PQXX_LIBEXPORT const_reverse_row_iterator : private const_row_iterator
\n-
398{
\n-
399public:
\n-\n-\n-\n-\n-\n-\n-\n-
407
\n-
408 const_reverse_row_iterator() noexcept = default;
\n-\n-
410 default;
\n-\n-
412
\n-
\n-
413 explicit const_reverse_row_iterator(super const &rhs) noexcept :
\n-\n-
415 {
\n-
416 super::operator--();
\n-
417 }
\n-
\n-
418
\n-
419 [[nodiscard]] PQXX_PURE iterator_type base() const noexcept;
\n-
420
\n-
425 using iterator_type::operator->;
\n-
426 using iterator_type::operator*;
\n-
428
\n-
433 const_reverse_row_iterator &
\n-
\n-
434 operator=(const_reverse_row_iterator const &r) noexcept
\n-
435 {
\n-
436 iterator_type::operator=(r);
\n-
437 return *this;
\n-
438 }
\n-
\n-
\n-\n-
440 {
\n-
441 iterator_type::operator--();
\n-
442 return *this;
\n-
443 }
\n-
\n-
444 const_reverse_row_iterator operator++(int) noexcept;
\n-
\n-\n-
446 {
\n-
447 iterator_type::operator++();
\n-
448 return *this;
\n-
449 }
\n-
\n-
450 const_reverse_row_iterator operator--(int);
\n-
\n-\n-
452 {
\n-
453 iterator_type::operator-=(i);
\n-
454 return *this;
\n-
455 }
\n-
\n-
\n-\n-
457 {
\n-
458 iterator_type::operator+=(i);
\n-
459 return *this;
\n-
460 }
\n-
\n-
462
\n-
467 [[nodiscard]] const_reverse_row_iterator
\n-
\n-
468 operator+(difference_type i) const noexcept
\n-
469 {
\n-
470 return const_reverse_row_iterator{base() - i};
\n-
471 }
\n-
\n-
472 [[nodiscard]] const_reverse_row_iterator
\n-
\n-\n-
474 {
\n-
475 return const_reverse_row_iterator{base() + i};
\n-
476 }
\n-
\n-
477 [[nodiscard]] difference_type
\n-
\n-
478 operator-(const_reverse_row_iterator const &rhs) const noexcept
\n-
479 {
\n-
480 return rhs.const_row_iterator::operator-(*this);
\n-
481 }
\n-
\n-
483
\n-
488 [[nodiscard]] bool
\n-
\n-
489 operator==(const_reverse_row_iterator const &rhs) const noexcept
\n-
490 {
\n-
491 return iterator_type::operator==(rhs);
\n-
492 }
\n-
\n-
493 [[nodiscard]] bool
\n-
\n-
494 operator!=(const_reverse_row_iterator const &rhs) const noexcept
\n-
495 {
\n-
496 return !operator==(rhs);
\n-
497 }
\n-
\n-
498
\n-
\n-
499 [[nodiscard]] constexpr bool
\n-
500 operator<(const_reverse_row_iterator const &rhs) const noexcept
\n-
501 {
\n-
502 return iterator_type::operator>(rhs);
\n-
503 }
\n-
\n-
\n-
504 [[nodiscard]] constexpr bool
\n-
505 operator<=(const_reverse_row_iterator const &rhs) const noexcept
\n-
506 {
\n-
507 return iterator_type::operator>=(rhs);
\n-
508 }
\n-
\n-
509 [[nodiscard]] constexpr bool
\n-
\n-
510 operator>(const_reverse_row_iterator const &rhs) const noexcept
\n-
511 {
\n-
512 return iterator_type::operator<(rhs);
\n-
513 }
\n-
\n-
514 [[nodiscard]] constexpr bool
\n-
\n-
515 operator>=(const_reverse_row_iterator const &rhs) const noexcept
\n-
516 {
\n-
517 return iterator_type::operator<=(rhs);
\n-
518 }
\n-
\n-
520};
\n-
\n-
521
\n-
522
\n-
523const_row_iterator
\n-
\n-\n-
525{
\n-
526 // TODO:: More direct route to home().columns()?
\n-
527 return {
\n-
528 row{home(), idx(), home().columns()},
\n-
529 size_type(difference_type(col()) + o)};
\n-
530}
\n-
\n-
531
\n-
\n-\n-\n-
534{
\n-
535 return i + o;
\n-
536}
\n-
\n-
537
\n-\n-
\n-\n-
540{
\n-
541 // TODO:: More direct route to home().columns()?
\n-
542 return {
\n-
543 row{home(), idx(), home().columns()},
\n-
544 size_type(difference_type(col()) - o)};
\n-
545}
\n-
\n-
546
\n-\n-
\n-\n-
549{
\n-
550 return difference_type(num() - i.num());
\n-
551}
\n-
\n-
\n-
552
\n-
553
\n-
554template<typename Tuple, std::size_t index>
\n-
555inline void row::extract_value(Tuple &t) const
\n-
556{
\n-
557 using field_type = strip_t<decltype(std::get<index>(t))>;
\n-
558 field const f{m_result, m_index, index};
\n-
559 std::get<index>(t) = from_string<field_type>(f);
\n-
560}
\n-
561} // namespace pqxx
\n-
562#endif
\n-
\n+
75 // TODO: Change API to take payload as zview instead of string ref.
\n+
77
\n+
84 virtual void operator()(std::string const &payload, int backend_pid) = 0;
\n+
85
\n+
86protected:
\n+
87 connection &conn() const noexcept { return m_conn; }
\n+
88
\n+
89private:
\n+
90 connection &m_conn;
\n+
91 std::string m_channel;
\n+
92};
\n
\n+
93} // namespace pqxx
\n+
94#endif
\n
The home of all libpqxx classes, functions, templates, etc.
Definition array.hxx:33
\n-
int row_size_type
Number of fields in a row of database data.
Definition types.hxx:34
\n-
std::remove_cv_t< std::remove_reference_t< TYPE > > strip_t
Remove any constness, volatile, and reference-ness from a type.
Definition types.hxx:91
\n-
int row_difference_type
Difference between row sizes.
Definition types.hxx:37
\n-
const_row_iterator operator+(const_row_iterator::difference_type o, const_row_iterator const &i) noexcept
Definition row.hxx:532
\n-
int result_size_type
Number of rows in a result set.
Definition types.hxx:28
\n-
Internal items for libpqxx' own use. Do not use these yourself.
Definition composite.hxx:84
\n-
Error in usage of libpqxx library, similar to std::logic_error.
Definition except.hxx:249
\n-
Reference to a field in a result set.
Definition field.hxx:35
\n-
Result set containing data returned by a query or command.
Definition result.hxx:73
\n-
result_size_type size_type
Definition result.hxx:75
\n-
Definition row.hxx:28
\n-
Reference to one row in a result.
Definition row.hxx:47
\n-
std::tuple< TYPE... > as() const
Extract entire row's values into a tuple.
Definition row.hxx:200
\n-
row_size_type size_type
Definition row.hxx:49
\n-
oid column_type(zview col_name) const
Return a column's type.
Definition row.hxx:128
\n-
row_difference_type difference_type
Definition row.hxx:50
\n-
result m_result
Result set of which this is one row.
Definition row.hxx:241
\n-
result::size_type m_index
Row number.
Definition row.hxx:248
\n-
constexpr result::size_type num() const noexcept
Definition row.hxx:159
\n-
row() noexcept=default
\n-
constexpr result::size_type rownumber() const noexcept
Row number, assuming this is a real row and not end()/rend().
Definition row.hxx:112
\n-
TUPLE as_tuple() const
Convert to a given tuple of values, don't check sizes.
Definition row.hxx:225
\n-
void check_size(size_type expected) const
Throw usage_error if row size is not expected.
Definition row.hxx:213
\n-
size_type table_column(zview col_name) const
What column number in its table did this result column come from?
Definition row.hxx:153
\n-
void convert(Tuple &t) const
Convert entire row to tuple fields, without checking row size.
Definition row.hxx:233
\n-
oid column_table(zview col_name) const
What table did this column come from?
Definition row.hxx:137
\n-
Iterator for fields in a row. Use as row::const_iterator.
Definition row.hxx:283
\n-
const_row_iterator operator-(difference_type) const noexcept
Definition row.hxx:539
\n-
const_row_iterator & operator=(const_row_iterator &&) noexcept=default
\n-
reference operator*() const noexcept
Definition row.hxx:307
\n-
const_row_iterator(field const &F) noexcept
Definition row.hxx:298
\n-
friend const_row_iterator operator+(difference_type, const_row_iterator const &) noexcept
Definition row.hxx:532
\n-
constexpr bool operator>=(const_row_iterator const &i) const noexcept
Definition row.hxx:372
\n-
const_row_iterator(const_row_iterator const &) noexcept=default
\n-
const_row_iterator & operator=(const_row_iterator const &) noexcept=default
\n-
std::random_access_iterator_tag iterator_category
Definition row.hxx:285
\n-
constexpr bool operator==(const_row_iterator const &i) const noexcept
Definition row.hxx:347
\n-
field const * pointer
Definition row.hxx:287
\n-
field const value_type
Definition row.hxx:286
\n-
constexpr bool operator!=(const_row_iterator const &i) const noexcept
Definition row.hxx:352
\n-
const_row_iterator(const_row_iterator &&) noexcept=default
\n-
row_size_type size_type
Definition row.hxx:288
\n-
const_row_iterator & operator--() noexcept
Definition row.hxx:324
\n-
const_row_iterator() noexcept=default
\n-
row_difference_type difference_type
Definition row.hxx:289
\n-
const_row_iterator & operator-=(difference_type i) noexcept
Definition row.hxx:335
\n-
const_row_iterator & operator+=(difference_type i) noexcept
Definition row.hxx:330
\n-
const_row_iterator(row const &t, row_size_type c) noexcept
Definition row.hxx:295
\n-
constexpr bool operator>(const_row_iterator const &i) const noexcept
Definition row.hxx:367
\n-
Reverse iterator for a row. Use as row::const_reverse_iterator.
Definition row.hxx:398
\n-
const_reverse_row_iterator operator++() noexcept
Definition row.hxx:439
\n-
bool operator!=(const_reverse_row_iterator const &rhs) const noexcept
Definition row.hxx:494
\n-
constexpr bool operator>=(const_reverse_row_iterator const &rhs) const noexcept
Definition row.hxx:515
\n-
constexpr bool operator>(const_reverse_row_iterator const &rhs) const noexcept
Definition row.hxx:510
\n-
difference_type operator-(const_reverse_row_iterator const &rhs) const noexcept
Definition row.hxx:478
\n-
const_reverse_row_iterator & operator+=(difference_type i) noexcept
Definition row.hxx:451
\n-
const_reverse_row_iterator operator+(difference_type i) const noexcept
Definition row.hxx:468
\n-
const_reverse_row_iterator & operator-=(difference_type i) noexcept
Definition row.hxx:456
\n-
const_reverse_row_iterator & operator--() noexcept
Definition row.hxx:445
\n-
row_difference_type difference_type
Definition row.hxx:289
\n-
bool operator==(const_reverse_row_iterator const &rhs) const noexcept
Definition row.hxx:489
\n-
const_reverse_row_iterator() noexcept=default
\n-
const_reverse_row_iterator operator-(difference_type i) noexcept
Definition row.hxx:473
\n-
iterator_type::value_type value_type
Definition row.hxx:405
\n-
Marker-type wrapper: zero-terminated std::string_view.
Definition zview.hxx:38
\n+
Connection to a database.
Definition connection.hxx:253
\n+
Definition notification.hxx:57
\n+
notification_receiver(notification_receiver const &)=delete
Register the receiver with a connection.
\n+
std::string const & channel() const &
The channel that this receiver listens on.
Definition notification.hxx:73
\n+
virtual void operator()(std::string const &payload, int backend_pid)=0
Overridable: action to invoke when notification arrives.
\n+
connection & conn() const noexcept
Definition notification.hxx:87
\n+
notification_receiver & operator=(notification_receiver const &)=delete
Register the receiver with a connection.
\n
\n
\n \n
\n \n
\n \n \n", "details": [{"source1": "html2text {}", "source2": "html2text {}", "unified_diff": "@@ -1,662 +1,87 @@\n \n \n \n \n \n libpqxx\u00a07.8.1\n \n-row.hxx\n- 1/* Definitions for the pqxx::result class and support classes.\n+notification.hxx\n+ 1/* Definition of the pqxx::notification_receiver functor interface.\n 2 *\n- 3 * pqxx::result represents the set of result rows from a database query.\n+ 3 * pqxx::notification_receiver handles incoming notifications.\n 4 *\n- 5 * DO NOT INCLUDE THIS FILE DIRECTLY; include pqxx/result instead.\n+ 5 * DO NOT INCLUDE THIS FILE DIRECTLY; include pqxx/notification instead.\n 6 *\n 7 * Copyright (c) 2000-2023, Jeroen T. Vermeulen.\n 8 *\n 9 * See COPYING for copyright license. If you did not receive a file called\n 10 * COPYING with this source code, please notify the distributor of this\n 11 * mistake, or contact the author.\n 12 */\n- 13#ifndef PQXX_H_ROW\n- 14#define PQXX_H_ROW\n+ 13#ifndef PQXX_H_NOTIFICATION\n+ 14#define PQXX_H_NOTIFICATION\n 15\n 16#if !defined(PQXX_HEADER_PRE)\n 17# error \"Include libpqxx headers as , not .\"\n 18#endif\n 19\n- 20#include \"pqxx/except.hxx\"\n- 21#include \"pqxx/field.hxx\"\n- 22#include \"pqxx/result.hxx\"\n+ 20#include \n+ 21\n+ 22#include \"pqxx/types.hxx\"\n 23\n- 24#include \"pqxx/internal/concat.hxx\"\n- 25\n- 26namespace pqxx::internal\n- 27{\n-28template class result_iter;\n- 29} // namespace pqxx::internal\n- 30\n- 31\n- 32namespace pqxx\n- 33{\n- 35\n-46class PQXX_LIBEXPORT row\n- 47{\n- 48public:\n-49 using size_type = row_size_type;\n-50 using difference_type = row_difference_type;\n-51 using const_iterator = const_row_iterator;\n-52 using iterator = const_iterator;\n-53 using reference = field;\n-54 using pointer = const_row_iterator;\n-55 using const_reverse_iterator = const_reverse_row_iterator;\n-56 using reverse_iterator = const_reverse_iterator;\n- 57\n-58 row() noexcept = default;\n-59 row(row &&) noexcept = default;\n-60 row(row const &) noexcept = default;\n-61 row &operator=(row const &) noexcept = default;\n-62 row &operator=(row &&) noexcept = default;\n- 63\n- 68 [[nodiscard]] PQXX_PURE bool operator==(row const &) const noexcept;\n-69 [[nodiscard]] bool operator!=(row const &rhs) const noexcept\n- 70 {\n- 71 return not operator==(rhs);\n- 72 }\n+ 24\n+ 25namespace pqxx\n+ 26{\n+ 28\n+56class PQXX_LIBEXPORT PQXX_NOVTABLE notification_receiver\n+ 57{\n+ 58public:\n+ 60\n+ 64 notification_receiver(connection &c, std::string_view channel);\n+66 notification_receiver(notification_receiver const &) = delete;\n+68 notification_receiver &operator=(notification_receiver const &) = delete;\n+ 70 virtual ~notification_receiver();\n+ 71\n+73 [[nodiscard]] std::string const &channel() const & { return m_channel; }\n 74\n- 75 [[nodiscard]] const_iterator begin() const noexcept;\n- 76 [[nodiscard]] const_iterator cbegin() const noexcept;\n- 77 [[nodiscard]] const_iterator end() const noexcept;\n- 78 [[nodiscard]] const_iterator cend() const noexcept;\n- 79\n- 84 [[nodiscard]] reference front() const noexcept;\n- 85 [[nodiscard]] reference back() const noexcept;\n- 86\n- 87 [[nodiscard]] const_reverse_row_iterator rbegin() const noexcept;\n- 88 [[nodiscard]] const_reverse_row_iterator crbegin() const noexcept;\n- 89 [[nodiscard]] const_reverse_row_iterator rend() const noexcept;\n- 90 [[nodiscard]] const_reverse_row_iterator crend() const noexcept;\n- 91\n- 92 [[nodiscard]] reference operator[](size_type) const noexcept;\n- 96 [[nodiscard]] reference operator[](zview col_name) const;\n- 97\n- 98 reference at(size_type) const;\n- 102 reference at(zview col_name) const;\n- 103\n-104 [[nodiscard]] constexpr size_type size() const noexcept\n- 105 {\n- 106 return m_end - m_begin;\n- 107 }\n- 108\n- 109 [[deprecated(\"Swap iterators, not rows.\")]] void swap(row &) noexcept;\n- 110\n-112 [[nodiscard]] constexpr result::size_type rownumber() const noexcept\n- 113 {\n- 114 return m_index;\n- 115 }\n- 116\n- 122 [[nodiscard]] size_type column_number(zview col_name) const;\n- 123\n- 125 [[nodiscard]] oid column_type(size_type) const;\n- 126\n-128 [[nodiscard]] oid column_type(zview col_name) const\n- 129 {\n- 130 return column_type(column_number(col_name));\n- 131 }\n- 132\n- 134 [[nodiscard]] oid column_table(size_type col_num) const;\n- 135\n-137 [[nodiscard]] oid column_table(zview col_name) const\n- 138 {\n- 139 return column_table(column_number(col_name));\n- 140 }\n- 141\n- 143\n- 150 [[nodiscard]] size_type table_column(size_type) const;\n- 151\n-153 [[nodiscard]] size_type table_column(zview col_name) const\n- 154 {\n- 155 return table_column(column_number(col_name));\n- 156 }\n- 158\n-159 [[nodiscard]] constexpr result::size_type num() const noexcept\n- 160 {\n- 161 return rownumber();\n- 162 }\n- 163\n- 175 [[deprecated(\"Row slicing is going away. File a bug if you need it.\")]]\n-row\n- 176 slice(size_type sbegin, size_type send) const;\n- 177\n- 179 [[nodiscard, deprecated(\"Row slicing is going away.\")]] PQXX_PURE bool\n- 180 empty() const noexcept;\n- 181\n- 183\n-188 template void to(Tuple &t) const\n- 189 {\n- 190 check_size(std::tuple_size_v);\n- 191 convert(t);\n- 192 }\n- 193\n- 195\n-200 template std::tuple as() const\n- 201 {\n- 202 check_size(sizeof...(TYPE));\n- 203 using seq = std::make_index_sequence;\n- 204 return get_tuple>(seq{});\n- 205 }\n- 206\n- 207protected:\n-208 friend class const_row_iterator;\n-209 friend class result;\n- 210 row(result const &r, result_size_type index, size_type cols) noexcept;\n- 211\n-213 void check_size(size_type expected) const\n- 214 {\n- 215 if (size() != expected)\n- 216 throw usage_error{internal::concat(\n- 217 \"Tried to extract \", expected, \" field(s) from a row of \", size(),\n- 218 \".\")};\n- 219 }\n- 220\n- 222\n-225 template TUPLE as_tuple() const\n- 226 {\n- 227 using seq = std::make_index_sequence>;\n- 228 return get_tuple(seq{});\n- 229 }\n- 230\n-231 template friend class pqxx::internal::result_iter;\n-233 template void convert(Tuple &t) const\n- 234 {\n- 235 extract_fields(t, std::make_index_sequence>{});\n- 236 }\n- 237\n-238 friend class field;\n- 239\n-241 result m_result;\n- 242\n- 244\n-248 result::size_type m_index = 0;\n- 249\n- 250 // TODO: Remove m_begin and (if possible) m_end when we remove slice().\n-252 size_type m_begin = 0;\n-254 size_type m_end = 0;\n- 255\n- 256private:\n- 257 template\n- 258 void extract_fields(Tuple &t, std::index_sequence) const\n- 259 {\n- 260 (extract_value(t), ...);\n- 261 }\n- 262\n- 263 template\n- 264 void extract_value(Tuple &t) const;\n- 265\n- 267 template\n- 268 auto get_tuple(std::index_sequence) const\n- 269 {\n- 270 return std::make_tuple(get_field()...);\n- 271 }\n- 272\n- 274 template auto get_field() const\n- 275 {\n- 276 return (*this)[index].as>();\n- 277 }\n- 278};\n- 279\n- 280\n-282class PQXX_LIBEXPORT const_row_iterator : public field\n- 283{\n- 284public:\n-285 using iterator_category = std::random_access_iterator_tag;\n-286 using value_type = field const;\n-287 using pointer = field const *;\n-288 using size_type = row_size_type;\n-289 using difference_type = row_difference_type;\n-290 using reference = field;\n- 291\n- 292#include \"pqxx/internal/ignore-deprecated-pre.hxx\"\n-293 const_row_iterator() noexcept = default;\n- 294#include \"pqxx/internal/ignore-deprecated-post.hxx\"\n-295 const_row_iterator(row const &t, row_size_type c) noexcept :\n- 296 field{t.m_result, t.m_index, c}\n- 297 {}\n-298 const_row_iterator(field const &F) noexcept : field{F} {}\n-299 const_row_iterator(const_row_iterator const &) noexcept = default;\n-300 const_row_iterator(const_row_iterator &&) noexcept = default;\n- 301\n-306 [[nodiscard]] constexpr pointer operator->() const noexcept { return this;\n-}\n-307 [[nodiscard]] reference operator*() const noexcept { return {*this}; }\n- 309\n-314 const_row_iterator &operator=(const_row_iterator const &) noexcept =\n-default;\n-315 const_row_iterator &operator=(const_row_iterator &&) noexcept = default;\n- 316\n- 317 const_row_iterator operator++(int) noexcept;\n-318 const_row_iterator &operator++() noexcept\n- 319 {\n- 320 ++m_col;\n- 321 return *this;\n- 322 }\n- 323 const_row_iterator operator--(int) noexcept;\n-324 const_row_iterator &operator--() noexcept\n- 325 {\n- 326 --m_col;\n- 327 return *this;\n- 328 }\n- 329\n-330 const_row_iterator &operator+=(difference_type i) noexcept\n- 331 {\n- 332 m_col = size_type(difference_type(m_col) + i);\n- 333 return *this;\n- 334 }\n-335 const_row_iterator &operator-=(difference_type i) noexcept\n- 336 {\n- 337 m_col = size_type(difference_type(m_col) - i);\n- 338 return *this;\n- 339 }\n- 341\n- 346 [[nodiscard]] constexpr bool\n-347 operator==(const_row_iterator const &i) const noexcept\n- 348 {\n- 349 return col() == i.col();\n- 350 }\n- 351 [[nodiscard]] constexpr bool\n-352 operator!=(const_row_iterator const &i) const noexcept\n- 353 {\n- 354 return col() != i.col();\n- 355 }\n-356 [[nodiscard]] constexpr bool\n- 357 operator<(const_row_iterator const &i) const noexcept\n- 358 {\n- 359 return col() < i.col();\n- 360 }\n-361 [[nodiscard]] constexpr bool\n- 362 operator<=(const_row_iterator const &i) const noexcept\n- 363 {\n- 364 return col() <= i.col();\n- 365 }\n- 366 [[nodiscard]] constexpr bool\n-367 operator>(const_row_iterator const &i) const noexcept\n- 368 {\n- 369 return col() > i.col();\n- 370 }\n- 371 [[nodiscard]] constexpr bool\n-372 operator>=(const_row_iterator const &i) const noexcept\n- 373 {\n- 374 return col() >= i.col();\n- 375 }\n- 377\n- 382 [[nodiscard]] inline const_row_iterator\n- 383 operator+(difference_type) const noexcept;\n- 384\n- 385 friend const_row_iterator\n- 386 operator+(difference_type, const_row_iterator const &) noexcept;\n- 387\n- 388 [[nodiscard]] inline const_row_iterator\n-389 operator-(difference_type) const noexcept;\n- 390 [[nodiscard]] inline difference_type\n-391 operator-(const_row_iterator const &) const noexcept;\n- 393};\n- 394\n- 395\n-397class PQXX_LIBEXPORT const_reverse_row_iterator : private const_row_iterator\n- 398{\n- 399public:\n-400 using super = const_row_iterator;\n-401 using iterator_type = const_row_iterator;\n- 402 using iterator_type::difference_type;\n- 403 using iterator_type::iterator_category;\n- 404 using iterator_type::pointer;\n-405 using value_type = iterator_type::value_type;\n-406 using reference = iterator_type::reference;\n- 407\n-408 const_reverse_row_iterator() noexcept = default;\n-409 const_reverse_row_iterator(const_reverse_row_iterator const &) noexcept =\n- 410 default;\n-411 const_reverse_row_iterator(const_reverse_row_iterator &&) noexcept =\n-default;\n- 412\n-413 explicit const_reverse_row_iterator(super const &rhs) noexcept :\n- 414 const_row_iterator{rhs}\n- 415 {\n- 416 super::operator--();\n- 417 }\n- 418\n- 419 [[nodiscard]] PQXX_PURE iterator_type base() const noexcept;\n- 420\n- 425 using iterator_type::operator->;\n- 426 using iterator_type::operator*;\n- 428\n- 433 const_reverse_row_iterator &\n-434 operator=(const_reverse_row_iterator const &r) noexcept\n- 435 {\n- 436 iterator_type::operator=(r);\n- 437 return *this;\n- 438 }\n-439 const_reverse_row_iterator operator++() noexcept\n- 440 {\n- 441 iterator_type::operator--();\n- 442 return *this;\n- 443 }\n- 444 const_reverse_row_iterator operator++(int) noexcept;\n-445 const_reverse_row_iterator &operator--() noexcept\n- 446 {\n- 447 iterator_type::operator++();\n- 448 return *this;\n- 449 }\n- 450 const_reverse_row_iterator operator--(int);\n-451 const_reverse_row_iterator &operator+=(difference_type i) noexcept\n- 452 {\n- 453 iterator_type::operator-=(i);\n- 454 return *this;\n- 455 }\n-456 const_reverse_row_iterator &operator-=(difference_type i) noexcept\n- 457 {\n- 458 iterator_type::operator+=(i);\n- 459 return *this;\n- 460 }\n- 462\n- 467 [[nodiscard]] const_reverse_row_iterator\n-468 operator+(difference_type i) const noexcept\n- 469 {\n- 470 return const_reverse_row_iterator{base() - i};\n- 471 }\n- 472 [[nodiscard]] const_reverse_row_iterator\n-473 operator-(difference_type i) noexcept\n- 474 {\n- 475 return const_reverse_row_iterator{base() + i};\n- 476 }\n- 477 [[nodiscard]] difference_type\n-478 operator-(const_reverse_row_iterator const &rhs) const noexcept\n- 479 {\n- 480 return rhs.const_row_iterator::operator-(*this);\n- 481 }\n- 483\n- 488 [[nodiscard]] bool\n-489 operator==(const_reverse_row_iterator const &rhs) const noexcept\n- 490 {\n- 491 return iterator_type::operator==(rhs);\n- 492 }\n- 493 [[nodiscard]] bool\n-494 operator!=(const_reverse_row_iterator const &rhs) const noexcept\n- 495 {\n- 496 return !operator==(rhs);\n- 497 }\n- 498\n-499 [[nodiscard]] constexpr bool\n- 500 operator<(const_reverse_row_iterator const &rhs) const noexcept\n- 501 {\n- 502 return iterator_type::operator>(rhs);\n- 503 }\n-504 [[nodiscard]] constexpr bool\n- 505 operator<=(const_reverse_row_iterator const &rhs) const noexcept\n- 506 {\n- 507 return iterator_type::operator>=(rhs);\n- 508 }\n- 509 [[nodiscard]] constexpr bool\n-510 operator>(const_reverse_row_iterator const &rhs) const noexcept\n- 511 {\n- 512 return iterator_type::operator<(rhs);\n- 513 }\n- 514 [[nodiscard]] constexpr bool\n-515 operator>=(const_reverse_row_iterator const &rhs) const noexcept\n- 516 {\n- 517 return iterator_type::operator<=(rhs);\n- 518 }\n- 520};\n- 521\n- 522\n- 523const_row_iterator\n-524const_row_iterator::operator+(difference_type o) const noexcept\n- 525{\n- 526 // TODO:: More direct route to home().columns()?\n- 527 return {\n- 528 row{home(), idx(), home().columns()},\n- 529 size_type(difference_type(col()) + o)};\n- 530}\n- 531\n-532inline const_row_iterator operator+(\n- 533 const_row_iterator::difference_type o, const_row_iterator const &i)\n-noexcept\n- 534{\n- 535 return i + o;\n- 536}\n- 537\n- 538inline const_row_iterator\n-539const_row_iterator::operator-(difference_type o) const noexcept\n- 540{\n- 541 // TODO:: More direct route to home().columns()?\n- 542 return {\n- 543 row{home(), idx(), home().columns()},\n- 544 size_type(difference_type(col()) - o)};\n- 545}\n- 546\n- 547inline const_row_iterator::difference_type\n-548const_row_iterator::operator-(const_row_iterator const &i) const noexcept\n- 549{\n- 550 return difference_type(num() - i.num());\n- 551}\n- 552\n- 553\n- 554template\n- 555inline void row::extract_value(Tuple &t) const\n- 556{\n- 557 using field_type = strip_t(t))>;\n- 558 field const f{m_result, m_index, index};\n- 559 std::get(t) = from_string(f);\n- 560}\n- 561} // namespace pqxx\n- 562#endif\n+ 75 // TODO: Change API to take payload as zview instead of string ref.\n+ 77\n+84 virtual void operator()(std::string const &payload, int backend_pid) = 0;\n+ 85\n+ 86protected:\n+87 connection &conn() const noexcept { return m_conn; }\n+ 88\n+ 89private:\n+ 90 connection &m_conn;\n+ 91 std::string m_channel;\n+ 92};\n+ 93} // namespace pqxx\n+ 94#endif\n pqxx\n The home of all libpqxx classes, functions, templates, etc.\n Definition array.hxx:33\n-pqxx::row_size_type\n-int row_size_type\n-Number of fields in a row of database data.\n-Definition types.hxx:34\n-pqxx::strip_t\n-std::remove_cv_t< std::remove_reference_t< TYPE > > strip_t\n-Remove any constness, volatile, and reference-ness from a type.\n-Definition types.hxx:91\n-pqxx::row_difference_type\n-int row_difference_type\n-Difference between row sizes.\n-Definition types.hxx:37\n-pqxx::operator+\n-const_row_iterator operator+(const_row_iterator::difference_type o,\n-const_row_iterator const &i) noexcept\n-Definition row.hxx:532\n-pqxx::result_size_type\n-int result_size_type\n-Number of rows in a result set.\n-Definition types.hxx:28\n-pqxx::internal\n-Internal items for libpqxx' own use. Do not use these yourself.\n-Definition composite.hxx:84\n-pqxx::usage_error\n-Error in usage of libpqxx library, similar to std::logic_error.\n-Definition except.hxx:249\n-pqxx::field\n-Reference to a field in a result set.\n-Definition field.hxx:35\n-pqxx::result\n-Result set containing data returned by a query or command.\n-Definition result.hxx:73\n-pqxx::result::size_type\n-result_size_type size_type\n-Definition result.hxx:75\n-pqxx::internal::result_iter\n-Definition row.hxx:28\n-pqxx::row\n-Reference to one row in a result.\n-Definition row.hxx:47\n-pqxx::row::as\n-std::tuple< TYPE... > as() const\n-Extract entire row's values into a tuple.\n-Definition row.hxx:200\n-pqxx::row::size_type\n-row_size_type size_type\n-Definition row.hxx:49\n-pqxx::row::column_type\n-oid column_type(zview col_name) const\n-Return a column's type.\n-Definition row.hxx:128\n-pqxx::row::difference_type\n-row_difference_type difference_type\n-Definition row.hxx:50\n-pqxx::row::m_result\n-result m_result\n-Result set of which this is one row.\n-Definition row.hxx:241\n-pqxx::row::m_index\n-result::size_type m_index\n-Row number.\n-Definition row.hxx:248\n-pqxx::row::num\n-constexpr result::size_type num() const noexcept\n-Definition row.hxx:159\n-pqxx::row::row\n-row() noexcept=default\n-pqxx::row::rownumber\n-constexpr result::size_type rownumber() const noexcept\n-Row number, assuming this is a real row and not end()/rend().\n-Definition row.hxx:112\n-pqxx::row::as_tuple\n-TUPLE as_tuple() const\n-Convert to a given tuple of values, don't check sizes.\n-Definition row.hxx:225\n-pqxx::row::check_size\n-void check_size(size_type expected) const\n-Throw usage_error if row size is not expected.\n-Definition row.hxx:213\n-pqxx::row::table_column\n-size_type table_column(zview col_name) const\n-What column number in its table did this result column come from?\n-Definition row.hxx:153\n-pqxx::row::convert\n-void convert(Tuple &t) const\n-Convert entire row to tuple fields, without checking row size.\n-Definition row.hxx:233\n-pqxx::row::column_table\n-oid column_table(zview col_name) const\n-What table did this column come from?\n-Definition row.hxx:137\n-pqxx::const_row_iterator\n-Iterator for fields in a row. Use as row::const_iterator.\n-Definition row.hxx:283\n-pqxx::const_row_iterator::operator-\n-const_row_iterator operator-(difference_type) const noexcept\n-Definition row.hxx:539\n-pqxx::const_row_iterator::operator=\n-const_row_iterator & operator=(const_row_iterator &&) noexcept=default\n-pqxx::const_row_iterator::operator*\n-reference operator*() const noexcept\n-Definition row.hxx:307\n-pqxx::const_row_iterator::const_row_iterator\n-const_row_iterator(field const &F) noexcept\n-Definition row.hxx:298\n-pqxx::const_row_iterator::operator+\n-friend const_row_iterator operator+(difference_type, const_row_iterator const\n-&) noexcept\n-Definition row.hxx:532\n-pqxx::const_row_iterator::operator>=\n-constexpr bool operator>=(const_row_iterator const &i) const noexcept\n-Definition row.hxx:372\n-pqxx::const_row_iterator::const_row_iterator\n-const_row_iterator(const_row_iterator const &) noexcept=default\n-pqxx::const_row_iterator::operator=\n-const_row_iterator & operator=(const_row_iterator const &) noexcept=default\n-pqxx::const_row_iterator::iterator_category\n-std::random_access_iterator_tag iterator_category\n-Definition row.hxx:285\n-pqxx::const_row_iterator::operator==\n-constexpr bool operator==(const_row_iterator const &i) const noexcept\n-Definition row.hxx:347\n-pqxx::const_row_iterator::pointer\n-field const * pointer\n-Definition row.hxx:287\n-pqxx::const_row_iterator::value_type\n-field const value_type\n-Definition row.hxx:286\n-pqxx::const_row_iterator::operator!=\n-constexpr bool operator!=(const_row_iterator const &i) const noexcept\n-Definition row.hxx:352\n-pqxx::const_row_iterator::const_row_iterator\n-const_row_iterator(const_row_iterator &&) noexcept=default\n-pqxx::const_row_iterator::size_type\n-row_size_type size_type\n-Definition row.hxx:288\n-pqxx::const_row_iterator::operator--\n-const_row_iterator & operator--() noexcept\n-Definition row.hxx:324\n-pqxx::const_row_iterator::const_row_iterator\n-const_row_iterator() noexcept=default\n-pqxx::const_row_iterator::difference_type\n-row_difference_type difference_type\n-Definition row.hxx:289\n-pqxx::const_row_iterator::operator-=\n-const_row_iterator & operator-=(difference_type i) noexcept\n-Definition row.hxx:335\n-pqxx::const_row_iterator::operator+=\n-const_row_iterator & operator+=(difference_type i) noexcept\n-Definition row.hxx:330\n-pqxx::const_row_iterator::const_row_iterator\n-const_row_iterator(row const &t, row_size_type c) noexcept\n-Definition row.hxx:295\n-pqxx::const_row_iterator::operator>\n-constexpr bool operator>(const_row_iterator const &i) const noexcept\n-Definition row.hxx:367\n-pqxx::const_reverse_row_iterator\n-Reverse iterator for a row. Use as row::const_reverse_iterator.\n-Definition row.hxx:398\n-pqxx::const_reverse_row_iterator::operator++\n-const_reverse_row_iterator operator++() noexcept\n-Definition row.hxx:439\n-pqxx::const_reverse_row_iterator::operator!=\n-bool operator!=(const_reverse_row_iterator const &rhs) const noexcept\n-Definition row.hxx:494\n-pqxx::const_reverse_row_iterator::operator>=\n-constexpr bool operator>=(const_reverse_row_iterator const &rhs) const noexcept\n-Definition row.hxx:515\n-pqxx::const_reverse_row_iterator::operator>\n-constexpr bool operator>(const_reverse_row_iterator const &rhs) const noexcept\n-Definition row.hxx:510\n-pqxx::const_reverse_row_iterator::operator-\n-difference_type operator-(const_reverse_row_iterator const &rhs) const noexcept\n-Definition row.hxx:478\n-pqxx::const_reverse_row_iterator::operator+=\n-const_reverse_row_iterator & operator+=(difference_type i) noexcept\n-Definition row.hxx:451\n-pqxx::const_reverse_row_iterator::operator+\n-const_reverse_row_iterator operator+(difference_type i) const noexcept\n-Definition row.hxx:468\n-pqxx::const_reverse_row_iterator::operator-=\n-const_reverse_row_iterator & operator-=(difference_type i) noexcept\n-Definition row.hxx:456\n-pqxx::const_reverse_row_iterator::operator--\n-const_reverse_row_iterator & operator--() noexcept\n-Definition row.hxx:445\n-pqxx::const_reverse_row_iterator::difference_type\n-row_difference_type difference_type\n-Definition row.hxx:289\n-pqxx::const_reverse_row_iterator::operator==\n-bool operator==(const_reverse_row_iterator const &rhs) const noexcept\n-Definition row.hxx:489\n-pqxx::const_reverse_row_iterator::const_reverse_row_iterator\n-const_reverse_row_iterator() noexcept=default\n-pqxx::const_reverse_row_iterator::operator-\n-const_reverse_row_iterator operator-(difference_type i) noexcept\n-Definition row.hxx:473\n-pqxx::const_reverse_row_iterator::value_type\n-iterator_type::value_type value_type\n-Definition row.hxx:405\n-pqxx::zview\n-Marker-type wrapper: zero-terminated std::string_view.\n-Definition zview.hxx:38\n+pqxx::connection\n+Connection to a database.\n+Definition connection.hxx:253\n+pqxx::notification_receiver\n+Definition notification.hxx:57\n+pqxx::notification_receiver::notification_receiver\n+notification_receiver(notification_receiver const &)=delete\n+Register the receiver with a connection.\n+pqxx::notification_receiver::channel\n+std::string const & channel() const &\n+The channel that this receiver listens on.\n+Definition notification.hxx:73\n+pqxx::notification_receiver::operator()\n+virtual void operator()(std::string const &payload, int backend_pid)=0\n+Overridable: action to invoke when notification arrives.\n+pqxx::notification_receiver::conn\n+connection & conn() const noexcept\n+Definition notification.hxx:87\n+pqxx::notification_receiver::operator=\n+notification_receiver & operator=(notification_receiver const &)=delete\n+Register the receiver with a connection.\n * include\n * pqxx\n- * row.hxx\n+ * notification.hxx\n * Generated by [doxygen] 1.9.8\n"}]}, {"source1": "./usr/share/doc/libpqxx-doc/html/a00098_source.html", "source2": "./usr/share/doc/libpqxx-doc/html/a00098_source.html", "unified_diff": "@@ -1,15 +1,15 @@\n \n \n \n \n \n \n \n-libpqxx: types.hxx Source File\n+libpqxx: largeobject.hxx Source File\n \n \n \n \n \n \n \n@@ -60,185 +60,664 @@\n \n
\n
\n-
types.hxx
\n+
largeobject.hxx
\n
\n
\n-
1/* Basic type aliases and forward declarations.
\n+
1/* Large Objects interface. Deprecated; use blob instead.
\n
2 *
\n-
3 * Copyright (c) 2000-2023, Jeroen T. Vermeulen
\n+
3 * DO NOT INCLUDE THIS FILE DIRECTLY; include pqxx/largeobject instead.
\n
4 *
\n-
5 * See COPYING for copyright license. If you did not receive a file called
\n-
6 * COPYING with this source code, please notify the distributor of this
\n-
7 * mistake, or contact the author.
\n-
8 */
\n-
9#ifndef PQXX_H_TYPES
\n-
10#define PQXX_H_TYPES
\n-
11
\n-
12#if !defined(PQXX_HEADER_PRE)
\n-
13# error "Include libpqxx headers as <pqxx/header>, not <pqxx/header.hxx>."
\n-
14#endif
\n-
15
\n-
16#include <cstddef>
\n-
17#include <cstdint>
\n-
18#include <iterator>
\n+
5 * Copyright (c) 2000-2023, Jeroen T. Vermeulen.
\n+
6 *
\n+
7 * See COPYING for copyright license. If you did not receive a file called
\n+
8 * COPYING with this source code, please notify the distributor of this
\n+
9 * mistake, or contact the author.
\n+
10 */
\n+
11#ifndef PQXX_H_LARGEOBJECT
\n+
12#define PQXX_H_LARGEOBJECT
\n+
13
\n+
14#if !defined(PQXX_HEADER_PRE)
\n+
15# error "Include libpqxx headers as <pqxx/header>, not <pqxx/header.hxx>."
\n+
16#endif
\n+
17
\n+
18#include <streambuf>
\n
19
\n-
20#if defined(PQXX_HAVE_CONCEPTS) && __has_include(<ranges>)
\n-
21# include <ranges>
\n-
22#endif
\n-
23
\n-
24
\n-
25namespace pqxx
\n-
26{
\n-
28using result_size_type = int;
\n-
29
\n-\n-
32
\n-
34using row_size_type = int;
\n-
35
\n-\n-
38
\n-
40using field_size_type = std::size_t;
\n+
20#include "pqxx/dbtransaction.hxx"
\n+
21
\n+
22
\n+
23namespace pqxx
\n+
24{
\n+
26
\n+
\n+
33class PQXX_LIBEXPORT largeobject
\n+
34{
\n+
35public:
\n+\n+
37
\n+
40 [[deprecated("Use blob instead.")]] largeobject() noexcept = default;
\n
41
\n-
43using large_object_size_type = int64_t;
\n-
44
\n-
45
\n-
46// Forward declarations, to help break compilation dependencies.
\n-
47// These won't necessarily include all classes in libpqxx.
\n-
48class binarystring;
\n-
49class connection;
\n-
50class const_result_iterator;
\n-
51class const_reverse_result_iterator;
\n-\n-\n-
54class dbtransaction;
\n-
55class field;
\n-\n-\n-
58struct range_error;
\n-
59class result;
\n-
60class row;
\n-
61class stream_from;
\n-\n+
43
\n+
45 [[deprecated("Use blob instead.")]] explicit largeobject(dbtransaction &t);
\n+
46
\n+
48
\n+
\n+
52 [[deprecated("Use blob instead.")]] explicit largeobject(oid o) noexcept :
\n+
53 m_id{o}
\n+
54 {}
\n+
\n+
55
\n+
57
\n+
61 [[deprecated("Use blob instead.")]] largeobject(
\n+
62 dbtransaction &t, std::string_view file);
\n
63
\n
65
\n-
\n-\n-
68{};
\n-
\n-
69
\n+
69 [[deprecated("Use blob instead.")]] largeobject(
\n+
70 largeobjectaccess const &o) noexcept;
\n
71
\n-
\n-\n-
74{};
\n-
\n-
75
\n-
76
\n+
73
\n+
77 [[nodiscard]] oid id() const noexcept { return m_id; }
\n
78
\n-
\n-
80enum class format : int
\n-
81{
\n-
82 text = 0,
\n-
83 binary = 1,
\n-
84};
\n-
\n-
85
\n-
86
\n
88
\n-
90template<typename TYPE>
\n-
91using strip_t = std::remove_cv_t<std::remove_reference_t<TYPE>>;
\n-
92
\n-
93
\n-
94#if defined(PQXX_HAVE_CONCEPTS)
\n-
96
\n-
99template<std::ranges::range CONTAINER>
\n-\n-
101#else // PQXX_HAVE_CONCEPTS
\n-
103
\n-
106template<typename CONTAINER>
\n-\n-
108#endif // PQXX_HAVE_CONCEPTS
\n-
109
\n-
110
\n-
111#if defined(PQXX_HAVE_CONCEPTS)
\n-
113template<typename STRING>
\n-
114concept char_string = std::ranges::contiguous_range<STRING> and
\n-
115 std::same_as<strip_t<value_type<STRING>>, char>;
\n-
116
\n-
118template<typename RANGE>
\n-
119concept char_strings =
\n-
120 std::ranges::range<RANGE> and char_string<strip_t<value_type<RANGE>>>;
\n-
121
\n-
123template<typename DATA>
\n-
124concept potential_binary = std::ranges::contiguous_range<DATA> and
\n-
125 (sizeof(value_type<DATA>) == 1);
\n-
126#endif // PQXX_HAVE_CONCEPTS
\n-
127
\n-
128
\n-
129// C++20: Retire these compatibility definitions.
\n-
130#if defined(PQXX_HAVE_CONCEPTS)
\n+
\n+
89 [[nodiscard]] bool operator==(largeobject const &other) const
\n+
90 {
\n+
91 return m_id == other.m_id;
\n+
92 }
\n+
\n+
94
\n+
\n+
95 [[nodiscard]] bool operator!=(largeobject const &other) const
\n+
96 {
\n+
97 return m_id != other.m_id;
\n+
98 }
\n+
\n+
100
\n+
\n+
101 [[nodiscard]] bool operator<=(largeobject const &other) const
\n+
102 {
\n+
103 return m_id <= other.m_id;
\n+
104 }
\n+
\n+
106
\n+
\n+
107 [[nodiscard]] bool operator>=(largeobject const &other) const
\n+
108 {
\n+
109 return m_id >= other.m_id;
\n+
110 }
\n+
\n+
112
\n+
\n+
113 [[nodiscard]] bool operator<(largeobject const &other) const
\n+
114 {
\n+
115 return m_id < other.m_id;
\n+
116 }
\n+
\n+
118
\n+
\n+
119 [[nodiscard]] bool operator>(largeobject const &other) const
\n+
120 {
\n+
121 return m_id > other.m_id;
\n+
122 }
\n+
\n+
124
\n+
126
\n+
130 void to_file(dbtransaction &t, std::string_view file) const;
\n
131
\n
133
\n-
136# define PQXX_RANGE_ARG std::ranges::range
\n-
137
\n-
139
\n-
142# define PQXX_CHAR_STRING_ARG pqxx::char_string
\n-
143
\n-
145
\n-
148# define PQXX_CHAR_STRINGS_ARG pqxx::char_strings
\n+
137 void remove(dbtransaction &t) const;
\n+
138
\n+
139protected:
\n+
140 PQXX_PURE static internal::pq::PGconn *
\n+
141 raw_connection(dbtransaction const &T);
\n+
142
\n+
143 PQXX_PRIVATE std::string reason(connection const &, int err) const;
\n+
144
\n+
145private:
\n+
146 oid m_id = oid_none;
\n+
147};
\n+
\n+
148
\n
149
\n-
150#else // PQXX_HAVE_CONCEPTS
\n
151
\n-
153
\n-
156# define PQXX_RANGE_ARG typename
\n-
157
\n+
\n+
153class PQXX_LIBEXPORT largeobjectaccess : private largeobject
\n+
154{
\n+
155public:
\n+\n+\n+\n
159
\n-
162# define PQXX_CHAR_STRING_ARG typename
\n-
163
\n-
165
\n-
168# define PQXX_CHAR_STRINGS_ARG typename
\n+
161
\n+
168 using openmode = std::ios::openmode;
\n
169
\n-
170#endif // PQXX_HAVE_CONCEPTS
\n-
171} // namespace pqxx
\n-
172#endif
\n+
\n+
171 static constexpr auto default_mode{
\n+
172 std::ios::in | std::ios::out | std::ios::binary};
\n+
\n+
173
\n+
175 using seekdir = std::ios::seekdir;
\n+
176
\n+
178
\n+
183 [[deprecated("Use blob instead.")]] explicit largeobjectaccess(
\n+
184 dbtransaction &t, openmode mode = default_mode);
\n+
185
\n+
187
\n+
194 [[deprecated("Use blob instead.")]] largeobjectaccess(
\n+
195 dbtransaction &t, oid o, openmode mode = default_mode);
\n+
196
\n+
198
\n+
204 [[deprecated("Use blob instead.")]] largeobjectaccess(
\n+
205 dbtransaction &t, largeobject o, openmode mode = default_mode);
\n+
206
\n+
208
\n+
213 [[deprecated("Use blob instead.")]] largeobjectaccess(
\n+
214 dbtransaction &t, std::string_view file, openmode mode = default_mode);
\n+
215
\n+
216 ~largeobjectaccess() noexcept { close(); }
\n+
217
\n+
219
\n+
222 using largeobject::id;
\n+
223
\n+
225
\n+
\n+
228 void to_file(std::string_view file) const
\n+
229 {
\n+
230 largeobject::to_file(m_trans, file);
\n+
231 }
\n+
\n+
232
\n+\n+
234
\n+
240
\n+
245 void write(char const buf[], std::size_t len);
\n+
246
\n+
248
\n+
251 void write(std::string_view buf) { write(std::data(buf), std::size(buf)); }
\n+
252
\n+
254
\n+
260 size_type read(char buf[], std::size_t len);
\n+
261
\n+
263
\n+
266 size_type seek(size_type dest, seekdir dir);
\n+
267
\n+
269
\n+
272 [[nodiscard]] size_type tell() const;
\n+
274
\n+
288
\n+
296 pos_type cseek(off_type dest, seekdir dir) noexcept;
\n+
297
\n+
299
\n+
305 off_type cwrite(char const buf[], std::size_t len) noexcept;
\n+
306
\n+
308
\n+
314 off_type cread(char buf[], std::size_t len) noexcept;
\n+
315
\n+
317
\n+
321 [[nodiscard]] pos_type ctell() const noexcept;
\n+
323
\n+
329 void process_notice(zview) noexcept;
\n+
331
\n+
332 using largeobject::remove;
\n+
333
\n+
334 using largeobject::operator==;
\n+
335 using largeobject::operator!=;
\n+
336 using largeobject::operator<;
\n+
337 using largeobject::operator<=;
\n+
338 using largeobject::operator>;
\n+
339 using largeobject::operator>=;
\n+
340
\n+\n+\n+
343 largeobjectaccess operator=(largeobjectaccess const &) = delete;
\n+
344
\n+
345private:
\n+
346 PQXX_PRIVATE std::string reason(int err) const;
\n+
347 internal::pq::PGconn *raw_connection() const
\n+
348 {
\n+
349 return largeobject::raw_connection(m_trans);
\n+
350 }
\n+
351
\n+
352 PQXX_PRIVATE void open(openmode mode);
\n+
353 void close() noexcept;
\n+
354
\n+
355 dbtransaction &m_trans;
\n+
356 int m_fd = -1;
\n+
357};
\n+
\n+
358
\n+
359
\n+
361
\n+
372template<typename CHAR = char, typename TRAITS = std::char_traits<CHAR>>
\n+
\n+
373class largeobject_streambuf : public std::basic_streambuf<CHAR, TRAITS>
\n+
374{
\n+
375 using size_type = largeobject::size_type;
\n+
376
\n+
377public:
\n+
378 using char_type = CHAR;
\n+
379 using traits_type = TRAITS;
\n+
380 using int_type = typename traits_type::int_type;
\n+
381 using pos_type = typename traits_type::pos_type;
\n+
382 using off_type = typename traits_type::off_type;
\n+\n+\n+
385
\n+
\n+
387 static constexpr auto default_mode{
\n+
388 std::ios::in | std::ios::out | std::ios::binary};
\n+
\n+
389
\n+
390#include "pqxx/internal/ignore-deprecated-pre.hxx"
\n+
\n+
391 [[deprecated("Use blob instead.")]] largeobject_streambuf(
\n+
392 dbtransaction &t, largeobject o, openmode mode = default_mode,
\n+
393 size_type buf_size = 512) :
\n+
394 m_bufsize{buf_size}, m_obj{t, o, mode}, m_g{nullptr}, m_p{nullptr}
\n+
395 {
\n+
396 initialize(mode);
\n+
397 }
\n+
\n+
398#include "pqxx/internal/ignore-deprecated-post.hxx"
\n+
399
\n+
\n+
400 [[deprecated("Use blob instead.")]] largeobject_streambuf(
\n+
401 dbtransaction &t, oid o, openmode mode = default_mode,
\n+
402 size_type buf_size = 512) :
\n+
403 m_bufsize{buf_size}, m_obj{t, o, mode}, m_g{nullptr}, m_p{nullptr}
\n+
404 {
\n+
405 initialize(mode);
\n+
406 }
\n+
\n+
407
\n+
\n+
408 virtual ~largeobject_streambuf() noexcept
\n+
409 {
\n+
410 delete[] m_p;
\n+
411 delete[] m_g;
\n+
412 }
\n+
\n+
413
\n+
415 void process_notice(zview const &s) { m_obj.process_notice(s); }
\n+
416
\n+
417protected:
\n+
\n+
418 virtual int sync() override
\n+
419 {
\n+
420 // setg() sets eback, gptr, egptr.
\n+
421 this->setg(this->eback(), this->eback(), this->egptr());
\n+
422 return overflow(eof());
\n+
423 }
\n+
\n+
424
\n+
\n+
425 virtual pos_type seekoff(off_type offset, seekdir dir, openmode) override
\n+
426 {
\n+
427 return adjust_eof(m_obj.cseek(largeobjectaccess::off_type(offset), dir));
\n+
428 }
\n+
\n+
429
\n+
\n+
430 virtual pos_type seekpos(pos_type pos, openmode) override
\n+
431 {
\n+
432 largeobjectaccess::pos_type const newpos{
\n+
433 m_obj.cseek(largeobjectaccess::off_type(pos), std::ios::beg)};
\n+
434 return adjust_eof(newpos);
\n+
435 }
\n+
\n+
436
\n+
\n+
437 virtual int_type overflow(int_type ch) override
\n+
438 {
\n+
439 auto *const pp{this->pptr()};
\n+
440 if (pp == nullptr)
\n+
441 return eof();
\n+
442 auto *const pb{this->pbase()};
\n+
443 int_type res{0};
\n+
444
\n+
445 if (pp > pb)
\n+
446 {
\n+
447 auto const write_sz{pp - pb};
\n+
448 auto const written_sz{
\n+
449 m_obj.cwrite(pb, static_cast<std::size_t>(pp - pb))};
\n+
450 if (internal::cmp_less_equal(written_sz, 0))
\n+
451 throw internal_error{
\n+
452 "pqxx::largeobject: write failed "
\n+
453 "(is transaction still valid on write or flush?), "
\n+
454 "libpq reports error"};
\n+
455 else if (write_sz != written_sz)
\n+
456 throw internal_error{
\n+
457 "pqxx::largeobject: write failed "
\n+
458 "(is transaction still valid on write or flush?), " +
\n+
459 std::to_string(written_sz) + "/" + std::to_string(write_sz) +
\n+
460 " bytes written"};
\n+
461 auto const out{adjust_eof(written_sz)};
\n+
462
\n+
463 if constexpr (std::is_arithmetic_v<decltype(out)>)
\n+
464 res = check_cast<int_type>(out, "largeobject position"sv);
\n+
465 else
\n+
466 res = int_type(out);
\n+
467 }
\n+
468 this->setp(m_p, m_p + m_bufsize);
\n+
469
\n+
470 // Write that one more character, if it's there.
\n+
471 if (ch != eof())
\n+
472 {
\n+
473 *this->pptr() = static_cast<char_type>(ch);
\n+
474 this->pbump(1);
\n+
475 }
\n+
476 return res;
\n+
477 }
\n+
\n+
478
\n+
479 virtual int_type overflow() { return overflow(eof()); }
\n+
480
\n+
\n+
481 virtual int_type underflow() override
\n+
482 {
\n+
483 if (this->gptr() == nullptr)
\n+
484 return eof();
\n+
485 auto *const eb{this->eback()};
\n+
486 auto const res{adjust_eof(
\n+
487 m_obj.cread(this->eback(), static_cast<std::size_t>(m_bufsize)))};
\n+
488 this->setg(
\n+
489 eb, eb, eb + (res == eof() ? 0 : static_cast<std::size_t>(res)));
\n+
490 return (res == eof() or res == 0) ? eof() : traits_type::to_int_type(*eb);
\n+
491 }
\n+
\n+
492
\n+
493private:
\n+
495 static int_type eof() { return traits_type::eof(); }
\n+
496
\n+
498 template<typename INTYPE> static std::streampos adjust_eof(INTYPE pos)
\n+
499 {
\n+
500 bool const at_eof{pos == -1};
\n+
501 if constexpr (std::is_arithmetic_v<std::streampos>)
\n+
502 {
\n+
503 return check_cast<std::streampos>(
\n+
504 (at_eof ? eof() : pos), "large object seek"sv);
\n+
505 }
\n+
506 else
\n+
507 {
\n+
508 return std::streampos(at_eof ? eof() : pos);
\n+
509 }
\n+
510 }
\n+
511
\n+
512 void initialize(openmode mode)
\n+
513 {
\n+
514 if ((mode & std::ios::in) != 0)
\n+
515 {
\n+
516 m_g = new char_type[unsigned(m_bufsize)];
\n+
517 this->setg(m_g, m_g, m_g);
\n+
518 }
\n+
519 if ((mode & std::ios::out) != 0)
\n+
520 {
\n+
521 m_p = new char_type[unsigned(m_bufsize)];
\n+
522 this->setp(m_p, m_p + m_bufsize);
\n+
523 }
\n+
524 }
\n+
525
\n+
526 size_type const m_bufsize;
\n+
527 largeobjectaccess m_obj;
\n+
528
\n+
530 char_type *m_g, *m_p;
\n+
531};
\n+
\n+
532
\n+
533
\n+
535
\n+
544template<typename CHAR = char, typename TRAITS = std::char_traits<CHAR>>
\n+
\n+
545class basic_ilostream : public std::basic_istream<CHAR, TRAITS>
\n+
546{
\n+
547 using super = std::basic_istream<CHAR, TRAITS>;
\n+
548
\n+
549public:
\n+
550 using char_type = CHAR;
\n+
551 using traits_type = TRAITS;
\n+
552 using int_type = typename traits_type::int_type;
\n+
553 using pos_type = typename traits_type::pos_type;
\n+
554 using off_type = typename traits_type::off_type;
\n+
555
\n+
556#include "pqxx/internal/ignore-deprecated-pre.hxx"
\n+
558
\n+
\n+
563 [[deprecated("Use blob instead.")]] basic_ilostream(
\n+
564 dbtransaction &t, largeobject o, largeobject::size_type buf_size = 512) :
\n+
565 super{nullptr},
\n+
566 m_buf{t, o, std::ios::in | std::ios::binary, buf_size}
\n+
567 {
\n+
568 super::init(&m_buf);
\n+
569 }
\n+
\n+
570#include "pqxx/internal/ignore-deprecated-post.hxx"
\n+
571
\n+
573
\n+
\n+
578 [[deprecated("Use blob instead.")]] basic_ilostream(
\n+
579 dbtransaction &t, oid o, largeobject::size_type buf_size = 512) :
\n+
580 super{nullptr},
\n+
581 m_buf{t, o, std::ios::in | std::ios::binary, buf_size}
\n+
582 {
\n+
583 super::init(&m_buf);
\n+
584 }
\n+
\n+
585
\n+
586private:
\n+\n+
588};
\n+
\n+
589
\n+\n+
591
\n+
592
\n+
594
\n+
602template<typename CHAR = char, typename TRAITS = std::char_traits<CHAR>>
\n+
\n+
603class basic_olostream : public std::basic_ostream<CHAR, TRAITS>
\n+
604{
\n+
605 using super = std::basic_ostream<CHAR, TRAITS>;
\n+
606
\n+
607public:
\n+
608 using char_type = CHAR;
\n+
609 using traits_type = TRAITS;
\n+
610 using int_type = typename traits_type::int_type;
\n+
611 using pos_type = typename traits_type::pos_type;
\n+
612 using off_type = typename traits_type::off_type;
\n+
613
\n+
614#include "pqxx/internal/ignore-deprecated-pre.hxx"
\n+
616
\n+
\n+
621 [[deprecated("Use blob instead.")]] basic_olostream(
\n+
622 dbtransaction &t, largeobject o, largeobject::size_type buf_size = 512) :
\n+
623 super{nullptr},
\n+
624 m_buf{t, o, std::ios::out | std::ios::binary, buf_size}
\n+
625 {
\n+
626 super::init(&m_buf);
\n+
627 }
\n+
\n+
628#include "pqxx/internal/ignore-deprecated-post.hxx"
\n+
629
\n+
631
\n+
\n+
636 [[deprecated("Use blob instead.")]] basic_olostream(
\n+
637 dbtransaction &t, oid o, largeobject::size_type buf_size = 512) :
\n+
638 super{nullptr},
\n+
639 m_buf{t, o, std::ios::out | std::ios::binary, buf_size}
\n+
640 {
\n+
641 super::init(&m_buf);
\n+
642 }
\n+
\n+
643
\n+
\n+\n+
645 {
\n+
646 try
\n+
647 {
\n+
648 m_buf.pubsync();
\n+
649 m_buf.pubsync();
\n+
650 }
\n+
651 catch (std::exception const &e)
\n+
652 {
\n+
653 m_buf.process_notice(e.what());
\n+
654 }
\n+
655 }
\n+
\n+
656
\n+
657private:
\n+\n+
659};
\n+
\n+
660
\n+\n+
662
\n+
663
\n+
665
\n+
674template<typename CHAR = char, typename TRAITS = std::char_traits<CHAR>>
\n+
\n+
675class basic_lostream : public std::basic_iostream<CHAR, TRAITS>
\n+
676{
\n+
677 using super = std::basic_iostream<CHAR, TRAITS>;
\n+
678
\n+
679public:
\n+
680 using char_type = CHAR;
\n+
681 using traits_type = TRAITS;
\n+
682 using int_type = typename traits_type::int_type;
\n+
683 using pos_type = typename traits_type::pos_type;
\n+
684 using off_type = typename traits_type::off_type;
\n+
685
\n+
687
\n+
\n+
692 [[deprecated("Use blob instead.")]] basic_lostream(
\n+
693 dbtransaction &t, largeobject o, largeobject::size_type buf_size = 512) :
\n+
694 super{nullptr},
\n+
695 m_buf{
\n+
696 t, o, std::ios::in | std::ios::out | std::ios::binary, buf_size}
\n+
697 {
\n+
698 super::init(&m_buf);
\n+
699 }
\n+
\n+
700
\n+
702
\n+
\n+
707 [[deprecated("Use blob instead.")]] basic_lostream(
\n+
708 dbtransaction &t, oid o, largeobject::size_type buf_size = 512) :
\n+
709 super{nullptr},
\n+
710 m_buf{
\n+
711 t, o, std::ios::in | std::ios::out | std::ios::binary, buf_size}
\n+
712 {
\n+
713 super::init(&m_buf);
\n+
714 }
\n+
\n+
715
\n+
\n+\n+
717 {
\n+
718 try
\n+
719 {
\n+
720 m_buf.pubsync();
\n+
721 m_buf.pubsync();
\n+
722 }
\n+
723 catch (std::exception const &e)
\n+
724 {
\n+
725 m_buf.process_notice(e.what());
\n+
726 }
\n+
727 }
\n+
\n+
728
\n+
729private:
\n+\n+
731};
\n+
\n+
732
\n+\n+
734} // namespace pqxx
\n+
735#endif
\n
The home of all libpqxx classes, functions, templates, etc.
Definition array.hxx:33
\n-
int row_size_type
Number of fields in a row of database data.
Definition types.hxx:34
\n-
std::remove_cv_t< std::remove_reference_t< TYPE > > strip_t
Remove any constness, volatile, and reference-ness from a type.
Definition types.hxx:91
\n-
int row_difference_type
Difference between row sizes.
Definition types.hxx:37
\n-
std::size_t field_size_type
Number of bytes in a field of database data.
Definition types.hxx:40
\n-
int result_difference_type
Difference between result sizes.
Definition types.hxx:31
\n-
strip_t< decltype(*std::begin(std::declval< CONTAINER >()))> value_type
The type of a container's elements.
Definition types.hxx:107
\n-
int result_size_type
Number of rows in a result set.
Definition types.hxx:28
\n+
constexpr oid oid_none
The "null" oid.
Definition util.hxx:342
\n
int64_t large_object_size_type
Number of bytes in a large object.
Definition types.hxx:43
\n-
format
Format code: is data text or binary?
Definition types.hxx:81
\n-\n \n-
Binary data corresponding to PostgreSQL's "BYTEA" binary-string type.
Definition binarystring.hxx:59
\n+
constexpr bool cmp_less_equal(LEFT lhs, RIGHT rhs) noexcept
C++20 std::cmp_less_equal, or workaround if not available.
Definition util.hxx:98
\n+
Definition blob.hxx:53
\n
Connection to a database.
Definition connection.hxx:253
\n
Abstract transaction base class: bracket transactions on the database.
Definition dbtransaction.hxx:54
\n-
Something is out of range, similar to std::out_of_range.
Definition except.hxx:326
\n-
Reference to a field in a result set.
Definition field.hxx:35
\n+
Internal error in libpqxx library.
Definition except.hxx:242
\n+
Identity of a large object.
Definition largeobject.hxx:34
\n+
bool operator==(largeobject const &other) const
Compare object identities.
Definition largeobject.hxx:89
\n+
bool operator>=(largeobject const &other) const
Compare object identities.
Definition largeobject.hxx:107
\n+
static PQXX_PURE internal::pq::PGconn * raw_connection(dbtransaction const &T)
Definition largeobject.cxx:139
\n+
bool operator<=(largeobject const &other) const
Compare object identities.
Definition largeobject.hxx:101
\n+
large_object_size_type size_type
Definition largeobject.hxx:36
\n+
bool operator<(largeobject const &other) const
Compare object identities.
Definition largeobject.hxx:113
\n+
largeobject() noexcept=default
\n+
void to_file(dbtransaction &t, std::string_view file) const
Export large object's contents to a local file.
Definition largeobject.cxx:107
\n+
bool operator!=(largeobject const &other) const
Compare object identities.
Definition largeobject.hxx:95
\n+
bool operator>(largeobject const &other) const
Compare object identities.
Definition largeobject.hxx:119
\n+
oid id() const noexcept
Object identifier.
Definition largeobject.hxx:77
\n
Accessor for large object's contents.
Definition largeobject.hxx:154
\n-
Definition notification.hxx:57
\n-
Result set containing data returned by a query or command.
Definition result.hxx:73
\n-
Reference to one row in a result.
Definition row.hxx:47
\n-
Iterator for fields in a row. Use as row::const_iterator.
Definition row.hxx:283
\n-
Reverse iterator for a row. Use as row::const_reverse_iterator.
Definition row.hxx:398
\n-
Stream data from the database.
Definition stream_from.hxx:79
\n-
Interface definition (and common code) for "transaction" classes.
Definition transaction_base.hxx:88
\n-
Marker for stream_from constructors: "stream from table.".
Definition types.hxx:68
\n-
Marker for stream_from constructors: "stream from query.".
Definition types.hxx:74
\n+
size_type pos_type
Definition largeobject.hxx:158
\n+
std::ios::openmode openmode
Open mode: in, out (can be combined using "bitwise or").
Definition largeobject.hxx:168
\n+
std::ios::seekdir seekdir
Seek direction: beg, cur, end.
Definition largeobject.hxx:175
\n+
void to_file(std::string_view file) const
Export large object's contents to a local file.
Definition largeobject.hxx:228
\n+
~largeobjectaccess() noexcept
Definition largeobject.hxx:216
\n+
void write(std::string_view buf)
Write string to large object.
Definition largeobject.hxx:251
\n+
size_type off_type
Definition largeobject.hxx:157
\n+
Streambuf to use large objects in standard I/O streams.
Definition largeobject.hxx:374
\n+
virtual pos_type seekoff(off_type offset, seekdir dir, openmode) override
Definition largeobject.hxx:425
\n+
virtual int_type overflow(int_type ch) override
Definition largeobject.hxx:437
\n+
TRAITS traits_type
Definition largeobject.hxx:379
\n+
typename traits_type::int_type int_type
Definition largeobject.hxx:380
\n+
virtual pos_type seekpos(pos_type pos, openmode) override
Definition largeobject.hxx:430
\n+
largeobject_streambuf(dbtransaction &t, oid o, openmode mode=default_mode, size_type buf_size=512)
Definition largeobject.hxx:400
\n+
CHAR char_type
Definition largeobject.hxx:378
\n+
typename traits_type::off_type off_type
Definition largeobject.hxx:382
\n+
virtual int_type overflow()
Definition largeobject.hxx:479
\n+
virtual ~largeobject_streambuf() noexcept
Definition largeobject.hxx:408
\n+
void process_notice(zview const &s)
For use by large object stream classes.
Definition largeobject.hxx:415
\n+
virtual int sync() override
Definition largeobject.hxx:418
\n+
largeobjectaccess::seekdir seekdir
Definition largeobject.hxx:384
\n+
virtual int_type underflow() override
Definition largeobject.hxx:481
\n+
largeobjectaccess::openmode openmode
Definition largeobject.hxx:383
\n+
typename traits_type::pos_type pos_type
Definition largeobject.hxx:381
\n+
largeobject_streambuf(dbtransaction &t, largeobject o, openmode mode=default_mode, size_type buf_size=512)
Definition largeobject.hxx:391
\n+
Input stream that gets its data from a large object.
Definition largeobject.hxx:546
\n+
basic_ilostream(dbtransaction &t, oid o, largeobject::size_type buf_size=512)
Create a basic_ilostream.
Definition largeobject.hxx:578
\n+
CHAR char_type
Definition largeobject.hxx:550
\n+
basic_ilostream(dbtransaction &t, largeobject o, largeobject::size_type buf_size=512)
Create a basic_ilostream.
Definition largeobject.hxx:563
\n+
typename traits_type::int_type int_type
Definition largeobject.hxx:552
\n+
TRAITS traits_type
Definition largeobject.hxx:551
\n+
typename traits_type::off_type off_type
Definition largeobject.hxx:554
\n+
typename traits_type::pos_type pos_type
Definition largeobject.hxx:553
\n+
Output stream that writes data back to a large object.
Definition largeobject.hxx:604
\n+
typename traits_type::off_type off_type
Definition largeobject.hxx:612
\n+
typename traits_type::pos_type pos_type
Definition largeobject.hxx:611
\n+
basic_olostream(dbtransaction &t, largeobject o, largeobject::size_type buf_size=512)
Create a basic_olostream.
Definition largeobject.hxx:621
\n+
typename traits_type::int_type int_type
Definition largeobject.hxx:610
\n+
~basic_olostream()
Definition largeobject.hxx:644
\n+
CHAR char_type
Definition largeobject.hxx:608
\n+
basic_olostream(dbtransaction &t, oid o, largeobject::size_type buf_size=512)
Create a basic_olostream.
Definition largeobject.hxx:636
\n+
TRAITS traits_type
Definition largeobject.hxx:609
\n+
Stream that reads and writes a large object.
Definition largeobject.hxx:676
\n+
typename traits_type::pos_type pos_type
Definition largeobject.hxx:683
\n+
~basic_lostream()
Definition largeobject.hxx:716
\n+
typename traits_type::int_type int_type
Definition largeobject.hxx:682
\n+
typename traits_type::off_type off_type
Definition largeobject.hxx:684
\n+
basic_lostream(dbtransaction &t, largeobject o, largeobject::size_type buf_size=512)
Create a basic_lostream.
Definition largeobject.hxx:692
\n+
basic_lostream(dbtransaction &t, oid o, largeobject::size_type buf_size=512)
Create a basic_lostream.
Definition largeobject.hxx:707
\n+
TRAITS traits_type
Definition largeobject.hxx:681
\n+
CHAR char_type
Definition largeobject.hxx:680
\n+
Marker-type wrapper: zero-terminated std::string_view.
Definition zview.hxx:38
\n
\n
\n \n
\n \n
\n \n \n", "details": [{"source1": "html2text {}", "source2": "html2text {}", "unified_diff": "@@ -1,232 +1,763 @@\n \n \n \n \n \n libpqxx\u00a07.8.1\n \n-types.hxx\n- 1/* Basic type aliases and forward declarations.\n+largeobject.hxx\n+ 1/* Large Objects interface. Deprecated; use blob instead.\n 2 *\n- 3 * Copyright (c) 2000-2023, Jeroen T. Vermeulen\n+ 3 * DO NOT INCLUDE THIS FILE DIRECTLY; include pqxx/largeobject instead.\n 4 *\n- 5 * See COPYING for copyright license. If you did not receive a file called\n- 6 * COPYING with this source code, please notify the distributor of this\n- 7 * mistake, or contact the author.\n- 8 */\n- 9#ifndef PQXX_H_TYPES\n- 10#define PQXX_H_TYPES\n- 11\n- 12#if !defined(PQXX_HEADER_PRE)\n- 13# error \"Include libpqxx headers as , not .\"\n- 14#endif\n- 15\n- 16#include \n- 17#include \n- 18#include \n+ 5 * Copyright (c) 2000-2023, Jeroen T. Vermeulen.\n+ 6 *\n+ 7 * See COPYING for copyright license. If you did not receive a file called\n+ 8 * COPYING with this source code, please notify the distributor of this\n+ 9 * mistake, or contact the author.\n+ 10 */\n+ 11#ifndef PQXX_H_LARGEOBJECT\n+ 12#define PQXX_H_LARGEOBJECT\n+ 13\n+ 14#if !defined(PQXX_HEADER_PRE)\n+ 15# error \"Include libpqxx headers as , not .\"\n+ 16#endif\n+ 17\n+ 18#include \n 19\n- 20#if defined(PQXX_HAVE_CONCEPTS) && __has_include()\n- 21# include \n- 22#endif\n- 23\n- 24\n- 25namespace pqxx\n- 26{\n-28using result_size_type = int;\n- 29\n-31using result_difference_type = int;\n- 32\n-34using row_size_type = int;\n- 35\n-37using row_difference_type = int;\n- 38\n-40using field_size_type = std::size_t;\n+ 20#include \"pqxx/dbtransaction.hxx\"\n+ 21\n+ 22\n+ 23namespace pqxx\n+ 24{\n+ 26\n+33class PQXX_LIBEXPORT largeobject\n+ 34{\n+ 35public:\n+36 using size_type = large_object_size_type;\n+ 37\n+40 [[deprecated(\"Use blob instead.\")]] largeobject() noexcept = default;\n 41\n-43using large_object_size_type = int64_t;\n- 44\n- 45\n- 46// Forward declarations, to help break compilation dependencies.\n- 47// These won't necessarily include all classes in libpqxx.\n- 48class binarystring;\n- 49class connection;\n- 50class const_result_iterator;\n- 51class const_reverse_result_iterator;\n- 52class const_reverse_row_iterator;\n- 53class const_row_iterator;\n- 54class dbtransaction;\n- 55class field;\n- 56class largeobjectaccess;\n- 57class notification_receiver;\n- 58struct range_error;\n- 59class result;\n- 60class row;\n- 61class stream_from;\n- 62class transaction_base;\n+ 43\n+ 45 [[deprecated(\"Use blob instead.\")]] explicit largeobject(dbtransaction &t);\n+ 46\n+ 48\n+52 [[deprecated(\"Use blob instead.\")]] explicit largeobject(oid o) noexcept :\n+ 53 m_id{o}\n+ 54 {}\n+ 55\n+ 57\n+ 61 [[deprecated(\"Use blob instead.\")]] largeobject(\n+ 62 dbtransaction &t, std::string_view file);\n 63\n 65\n-67struct from_table_t\n- 68{};\n- 69\n+ 69 [[deprecated(\"Use blob instead.\")]] largeobject(\n+ 70 largeobjectaccess const &o) noexcept;\n 71\n-73struct from_query_t\n- 74{};\n- 75\n- 76\n+ 73\n+77 [[nodiscard]] oid id() const noexcept { return m_id; }\n 78\n-80enum class format : int\n- 81{\n- 82 text = 0,\n- 83 binary = 1,\n- 84};\n- 85\n- 86\n 88\n- 90template\n-91using strip_t = std::remove_cv_t>;\n- 92\n- 93\n- 94#if defined(PQXX_HAVE_CONCEPTS)\n- 96\n- 99template\n- 100using value_type = strip_t\n-()))>;\n- 101#else // PQXX_HAVE_CONCEPTS\n- 103\n- 106template\n-107using value_type = strip_t\n-()))>;\n- 108#endif // PQXX_HAVE_CONCEPTS\n- 109\n- 110\n- 111#if defined(PQXX_HAVE_CONCEPTS)\n- 113template\n- 114concept char_string = std::ranges::contiguous_range and\n- 115 std::same_as>, char>;\n- 116\n- 118template\n- 119concept char_strings =\n- 120 std::ranges::range and char_string>>;\n- 121\n- 123template\n- 124concept potential_binary = std::ranges::contiguous_range and\n- 125 (sizeof(value_type) == 1);\n- 126#endif // PQXX_HAVE_CONCEPTS\n- 127\n- 128\n- 129// C++20: Retire these compatibility definitions.\n- 130#if defined(PQXX_HAVE_CONCEPTS)\n+89 [[nodiscard]] bool operator==(largeobject const &other) const\n+ 90 {\n+ 91 return m_id == other.m_id;\n+ 92 }\n+ 94\n+95 [[nodiscard]] bool operator!=(largeobject const &other) const\n+ 96 {\n+ 97 return m_id != other.m_id;\n+ 98 }\n+ 100\n+101 [[nodiscard]] bool operator<=(largeobject const &other) const\n+ 102 {\n+ 103 return m_id <= other.m_id;\n+ 104 }\n+ 106\n+107 [[nodiscard]] bool operator>=(largeobject const &other) const\n+ 108 {\n+ 109 return m_id >= other.m_id;\n+ 110 }\n+ 112\n+113 [[nodiscard]] bool operator<(largeobject const &other) const\n+ 114 {\n+ 115 return m_id < other.m_id;\n+ 116 }\n+ 118\n+119 [[nodiscard]] bool operator>(largeobject const &other) const\n+ 120 {\n+ 121 return m_id > other.m_id;\n+ 122 }\n+ 124\n+ 126\n+ 130 void to_file(dbtransaction &t, std::string_view file) const;\n 131\n 133\n- 136# define PQXX_RANGE_ARG std::ranges::range\n- 137\n- 139\n- 142# define PQXX_CHAR_STRING_ARG pqxx::char_string\n- 143\n- 145\n- 148# define PQXX_CHAR_STRINGS_ARG pqxx::char_strings\n+ 137 void remove(dbtransaction &t) const;\n+ 138\n+ 139protected:\n+ 140 PQXX_PURE static internal::pq::PGconn *\n+ 141 raw_connection(dbtransaction const &T);\n+ 142\n+ 143 PQXX_PRIVATE std::string reason(connection const &, int err) const;\n+ 144\n+ 145private:\n+ 146 oid m_id = oid_none;\n+ 147};\n+ 148\n 149\n- 150#else // PQXX_HAVE_CONCEPTS\n 151\n- 153\n- 156# define PQXX_RANGE_ARG typename\n- 157\n+153class PQXX_LIBEXPORT largeobjectaccess : private largeobject\n+ 154{\n+ 155public:\n+ 156 using largeobject::size_type;\n+157 using off_type = size_type;\n+158 using pos_type = size_type;\n 159\n- 162# define PQXX_CHAR_STRING_ARG typename\n- 163\n- 165\n- 168# define PQXX_CHAR_STRINGS_ARG typename\n+ 161\n+168 using openmode = std::ios::openmode;\n 169\n- 170#endif // PQXX_HAVE_CONCEPTS\n- 171} // namespace pqxx\n- 172#endif\n+171 static constexpr auto default_mode{\n+ 172 std::ios::in | std::ios::out | std::ios::binary};\n+ 173\n+175 using seekdir = std::ios::seekdir;\n+ 176\n+ 178\n+ 183 [[deprecated(\"Use blob instead.\")]] explicit largeobjectaccess(\n+ 184 dbtransaction &t, openmode mode = default_mode);\n+ 185\n+ 187\n+ 194 [[deprecated(\"Use blob instead.\")]] largeobjectaccess(\n+ 195 dbtransaction &t, oid o, openmode mode = default_mode);\n+ 196\n+ 198\n+ 204 [[deprecated(\"Use blob instead.\")]] largeobjectaccess(\n+ 205 dbtransaction &t, largeobject o, openmode mode = default_mode);\n+ 206\n+ 208\n+ 213 [[deprecated(\"Use blob instead.\")]] largeobjectaccess(\n+ 214 dbtransaction &t, std::string_view file, openmode mode = default_mode);\n+ 215\n+216 ~largeobjectaccess() noexcept { close(); }\n+ 217\n+ 219\n+ 222 using largeobject::id;\n+ 223\n+ 225\n+228 void to_file(std::string_view file) const\n+ 229 {\n+ 230 largeobject::to_file(m_trans, file);\n+ 231 }\n+ 232\n+ 233 using largeobject::to_file;\n+ 234\n+ 240\n+ 245 void write(char const buf[], std::size_t len);\n+ 246\n+ 248\n+251 void write(std::string_view buf) { write(std::data(buf), std::size(buf)); }\n+ 252\n+ 254\n+ 260 size_type read(char buf[], std::size_t len);\n+ 261\n+ 263\n+ 266 size_type seek(size_type dest, seekdir dir);\n+ 267\n+ 269\n+ 272 [[nodiscard]] size_type tell() const;\n+ 274\n+ 288\n+ 296 pos_type cseek(off_type dest, seekdir dir) noexcept;\n+ 297\n+ 299\n+ 305 off_type cwrite(char const buf[], std::size_t len) noexcept;\n+ 306\n+ 308\n+ 314 off_type cread(char buf[], std::size_t len) noexcept;\n+ 315\n+ 317\n+ 321 [[nodiscard]] pos_type ctell() const noexcept;\n+ 323\n+ 329 void process_notice(zview) noexcept;\n+ 331\n+ 332 using largeobject::remove;\n+ 333\n+ 334 using largeobject::operator==;\n+ 335 using largeobject::operator!=;\n+ 336 using largeobject::operator<;\n+ 337 using largeobject::operator<=;\n+ 338 using largeobject::operator>;\n+ 339 using largeobject::operator>=;\n+ 340\n+341 largeobjectaccess() = delete;\n+342 largeobjectaccess(largeobjectaccess const &) = delete;\n+343 largeobjectaccess operator=(largeobjectaccess const &) = delete;\n+ 344\n+ 345private:\n+ 346 PQXX_PRIVATE std::string reason(int err) const;\n+ 347 internal::pq::PGconn *raw_connection() const\n+ 348 {\n+ 349 return largeobject::raw_connection(m_trans);\n+ 350 }\n+ 351\n+ 352 PQXX_PRIVATE void open(openmode mode);\n+ 353 void close() noexcept;\n+ 354\n+ 355 dbtransaction &m_trans;\n+ 356 int m_fd = -1;\n+ 357};\n+ 358\n+ 359\n+ 361\n+ 372template>\n+373class largeobject_streambuf : public std::basic_streambuf\n+ 374{\n+ 375 using size_type = largeobject::size_type;\n+ 376\n+ 377public:\n+378 using char_type = CHAR;\n+379 using traits_type = TRAITS;\n+380 using int_type = typename traits_type::int_type;\n+381 using pos_type = typename traits_type::pos_type;\n+382 using off_type = typename traits_type::off_type;\n+383 using openmode = largeobjectaccess::openmode;\n+384 using seekdir = largeobjectaccess::seekdir;\n+ 385\n+387 static constexpr auto default_mode{\n+ 388 std::ios::in | std::ios::out | std::ios::binary};\n+ 389\n+ 390#include \"pqxx/internal/ignore-deprecated-pre.hxx\"\n+391 [[deprecated(\"Use blob instead.\")]] largeobject_streambuf(\n+ 392 dbtransaction &t, largeobject o, openmode mode = default_mode,\n+ 393 size_type buf_size = 512) :\n+ 394 m_bufsize{buf_size}, m_obj{t, o, mode}, m_g{nullptr}, m_p{nullptr}\n+ 395 {\n+ 396 initialize(mode);\n+ 397 }\n+ 398#include \"pqxx/internal/ignore-deprecated-post.hxx\"\n+ 399\n+400 [[deprecated(\"Use blob instead.\")]] largeobject_streambuf(\n+ 401 dbtransaction &t, oid o, openmode mode = default_mode,\n+ 402 size_type buf_size = 512) :\n+ 403 m_bufsize{buf_size}, m_obj{t, o, mode}, m_g{nullptr}, m_p{nullptr}\n+ 404 {\n+ 405 initialize(mode);\n+ 406 }\n+ 407\n+408 virtual ~largeobject_streambuf() noexcept\n+ 409 {\n+ 410 delete[] m_p;\n+ 411 delete[] m_g;\n+ 412 }\n+ 413\n+415 void process_notice(zview const &s) { m_obj.process_notice(s); }\n+ 416\n+ 417protected:\n+418 virtual int sync() override\n+ 419 {\n+ 420 // setg() sets eback, gptr, egptr.\n+ 421 this->setg(this->eback(), this->eback(), this->egptr());\n+ 422 return overflow(eof());\n+ 423 }\n+ 424\n+425 virtual pos_type seekoff(off_type offset, seekdir dir, openmode) override\n+ 426 {\n+ 427 return adjust_eof(m_obj.cseek(largeobjectaccess::off_type(offset), dir));\n+ 428 }\n+ 429\n+430 virtual pos_type seekpos(pos_type pos, openmode) override\n+ 431 {\n+ 432 largeobjectaccess::pos_type const newpos{\n+ 433 m_obj.cseek(largeobjectaccess::off_type(pos), std::ios::beg)};\n+ 434 return adjust_eof(newpos);\n+ 435 }\n+ 436\n+437 virtual int_type overflow(int_type ch) override\n+ 438 {\n+ 439 auto *const pp{this->pptr()};\n+ 440 if (pp == nullptr)\n+ 441 return eof();\n+ 442 auto *const pb{this->pbase()};\n+ 443 int_type res{0};\n+ 444\n+ 445 if (pp > pb)\n+ 446 {\n+ 447 auto const write_sz{pp - pb};\n+ 448 auto const written_sz{\n+ 449 m_obj.cwrite(pb, static_cast(pp - pb))};\n+ 450 if (internal::cmp_less_equal(written_sz, 0))\n+ 451 throw internal_error{\n+ 452 \"pqxx::largeobject: write failed \"\n+ 453 \"(is transaction still valid on write or flush?), \"\n+ 454 \"libpq reports error\"};\n+ 455 else if (write_sz != written_sz)\n+ 456 throw internal_error{\n+ 457 \"pqxx::largeobject: write failed \"\n+ 458 \"(is transaction still valid on write or flush?), \" +\n+ 459 std::to_string(written_sz) + \"/\" + std::to_string(write_sz) +\n+ 460 \" bytes written\"};\n+ 461 auto const out{adjust_eof(written_sz)};\n+ 462\n+ 463 if constexpr (std::is_arithmetic_v)\n+ 464 res = check_cast(out, \"largeobject position\"sv);\n+ 465 else\n+ 466 res = int_type(out);\n+ 467 }\n+ 468 this->setp(m_p, m_p + m_bufsize);\n+ 469\n+ 470 // Write that one more character, if it's there.\n+ 471 if (ch != eof())\n+ 472 {\n+ 473 *this->pptr() = static_cast(ch);\n+ 474 this->pbump(1);\n+ 475 }\n+ 476 return res;\n+ 477 }\n+ 478\n+479 virtual int_type overflow() { return overflow(eof()); }\n+ 480\n+481 virtual int_type underflow() override\n+ 482 {\n+ 483 if (this->gptr() == nullptr)\n+ 484 return eof();\n+ 485 auto *const eb{this->eback()};\n+ 486 auto const res{adjust_eof(\n+ 487 m_obj.cread(this->eback(), static_cast(m_bufsize)))};\n+ 488 this->setg(\n+ 489 eb, eb, eb + (res == eof() ? 0 : static_cast(res)));\n+ 490 return (res == eof() or res == 0) ? eof() : traits_type::to_int_type(*eb);\n+ 491 }\n+ 492\n+ 493private:\n+ 495 static int_type eof() { return traits_type::eof(); }\n+ 496\n+ 498 template static std::streampos adjust_eof(INTYPE pos)\n+ 499 {\n+ 500 bool const at_eof{pos == -1};\n+ 501 if constexpr (std::is_arithmetic_v)\n+ 502 {\n+ 503 return check_cast(\n+ 504 (at_eof ? eof() : pos), \"large object seek\"sv);\n+ 505 }\n+ 506 else\n+ 507 {\n+ 508 return std::streampos(at_eof ? eof() : pos);\n+ 509 }\n+ 510 }\n+ 511\n+ 512 void initialize(openmode mode)\n+ 513 {\n+ 514 if ((mode & std::ios::in) != 0)\n+ 515 {\n+ 516 m_g = new char_type[unsigned(m_bufsize)];\n+ 517 this->setg(m_g, m_g, m_g);\n+ 518 }\n+ 519 if ((mode & std::ios::out) != 0)\n+ 520 {\n+ 521 m_p = new char_type[unsigned(m_bufsize)];\n+ 522 this->setp(m_p, m_p + m_bufsize);\n+ 523 }\n+ 524 }\n+ 525\n+ 526 size_type const m_bufsize;\n+ 527 largeobjectaccess m_obj;\n+ 528\n+ 530 char_type *m_g, *m_p;\n+ 531};\n+ 532\n+ 533\n+ 535\n+ 544template>\n+545class basic_ilostream : public std::basic_istream\n+ 546{\n+ 547 using super = std::basic_istream;\n+ 548\n+ 549public:\n+550 using char_type = CHAR;\n+551 using traits_type = TRAITS;\n+552 using int_type = typename traits_type::int_type;\n+553 using pos_type = typename traits_type::pos_type;\n+554 using off_type = typename traits_type::off_type;\n+ 555\n+ 556#include \"pqxx/internal/ignore-deprecated-pre.hxx\"\n+ 558\n+563 [[deprecated(\"Use blob instead.\")]] basic_ilostream(\n+ 564 dbtransaction &t, largeobject o, largeobject::size_type buf_size = 512) :\n+ 565 super{nullptr},\n+ 566 m_buf{t, o, std::ios::in | std::ios::binary, buf_size}\n+ 567 {\n+ 568 super::init(&m_buf);\n+ 569 }\n+ 570#include \"pqxx/internal/ignore-deprecated-post.hxx\"\n+ 571\n+ 573\n+578 [[deprecated(\"Use blob instead.\")]] basic_ilostream(\n+ 579 dbtransaction &t, oid o, largeobject::size_type buf_size = 512) :\n+ 580 super{nullptr},\n+ 581 m_buf{t, o, std::ios::in | std::ios::binary, buf_size}\n+ 582 {\n+ 583 super::init(&m_buf);\n+ 584 }\n+ 585\n+ 586private:\n+ 587 largeobject_streambuf m_buf;\n+ 588};\n+ 589\n+590using ilostream = basic_ilostream;\n+ 591\n+ 592\n+ 594\n+ 602template>\n+603class basic_olostream : public std::basic_ostream\n+ 604{\n+ 605 using super = std::basic_ostream;\n+ 606\n+ 607public:\n+608 using char_type = CHAR;\n+609 using traits_type = TRAITS;\n+610 using int_type = typename traits_type::int_type;\n+611 using pos_type = typename traits_type::pos_type;\n+612 using off_type = typename traits_type::off_type;\n+ 613\n+ 614#include \"pqxx/internal/ignore-deprecated-pre.hxx\"\n+ 616\n+621 [[deprecated(\"Use blob instead.\")]] basic_olostream(\n+ 622 dbtransaction &t, largeobject o, largeobject::size_type buf_size = 512) :\n+ 623 super{nullptr},\n+ 624 m_buf{t, o, std::ios::out | std::ios::binary, buf_size}\n+ 625 {\n+ 626 super::init(&m_buf);\n+ 627 }\n+ 628#include \"pqxx/internal/ignore-deprecated-post.hxx\"\n+ 629\n+ 631\n+636 [[deprecated(\"Use blob instead.\")]] basic_olostream(\n+ 637 dbtransaction &t, oid o, largeobject::size_type buf_size = 512) :\n+ 638 super{nullptr},\n+ 639 m_buf{t, o, std::ios::out | std::ios::binary, buf_size}\n+ 640 {\n+ 641 super::init(&m_buf);\n+ 642 }\n+ 643\n+644 ~basic_olostream()\n+ 645 {\n+ 646 try\n+ 647 {\n+ 648 m_buf.pubsync();\n+ 649 m_buf.pubsync();\n+ 650 }\n+ 651 catch (std::exception const &e)\n+ 652 {\n+ 653 m_buf.process_notice(e.what());\n+ 654 }\n+ 655 }\n+ 656\n+ 657private:\n+ 658 largeobject_streambuf m_buf;\n+ 659};\n+ 660\n+661using olostream = basic_olostream;\n+ 662\n+ 663\n+ 665\n+ 674template>\n+675class basic_lostream : public std::basic_iostream\n+ 676{\n+ 677 using super = std::basic_iostream;\n+ 678\n+ 679public:\n+680 using char_type = CHAR;\n+681 using traits_type = TRAITS;\n+682 using int_type = typename traits_type::int_type;\n+683 using pos_type = typename traits_type::pos_type;\n+684 using off_type = typename traits_type::off_type;\n+ 685\n+ 687\n+692 [[deprecated(\"Use blob instead.\")]] basic_lostream(\n+ 693 dbtransaction &t, largeobject o, largeobject::size_type buf_size = 512) :\n+ 694 super{nullptr},\n+ 695 m_buf{\n+ 696 t, o, std::ios::in | std::ios::out | std::ios::binary, buf_size}\n+ 697 {\n+ 698 super::init(&m_buf);\n+ 699 }\n+ 700\n+ 702\n+707 [[deprecated(\"Use blob instead.\")]] basic_lostream(\n+ 708 dbtransaction &t, oid o, largeobject::size_type buf_size = 512) :\n+ 709 super{nullptr},\n+ 710 m_buf{\n+ 711 t, o, std::ios::in | std::ios::out | std::ios::binary, buf_size}\n+ 712 {\n+ 713 super::init(&m_buf);\n+ 714 }\n+ 715\n+716 ~basic_lostream()\n+ 717 {\n+ 718 try\n+ 719 {\n+ 720 m_buf.pubsync();\n+ 721 m_buf.pubsync();\n+ 722 }\n+ 723 catch (std::exception const &e)\n+ 724 {\n+ 725 m_buf.process_notice(e.what());\n+ 726 }\n+ 727 }\n+ 728\n+ 729private:\n+ 730 largeobject_streambuf m_buf;\n+ 731};\n+ 732\n+733using lostream = basic_lostream;\n+ 734} // namespace pqxx\n+ 735#endif\n pqxx\n The home of all libpqxx classes, functions, templates, etc.\n Definition array.hxx:33\n-pqxx::row_size_type\n-int row_size_type\n-Number of fields in a row of database data.\n-Definition types.hxx:34\n-pqxx::strip_t\n-std::remove_cv_t< std::remove_reference_t< TYPE > > strip_t\n-Remove any constness, volatile, and reference-ness from a type.\n-Definition types.hxx:91\n-pqxx::row_difference_type\n-int row_difference_type\n-Difference between row sizes.\n-Definition types.hxx:37\n-pqxx::field_size_type\n-std::size_t field_size_type\n-Number of bytes in a field of database data.\n-Definition types.hxx:40\n-pqxx::result_difference_type\n-int result_difference_type\n-Difference between result sizes.\n-Definition types.hxx:31\n-pqxx::value_type\n-strip_t< decltype(*std::begin(std::declval< CONTAINER >()))> value_type\n-The type of a container's elements.\n-Definition types.hxx:107\n-pqxx::result_size_type\n-int result_size_type\n-Number of rows in a result set.\n-Definition types.hxx:28\n+pqxx::oid_none\n+constexpr oid oid_none\n+The \"null\" oid.\n+Definition util.hxx:342\n pqxx::large_object_size_type\n int64_t large_object_size_type\n Number of bytes in a large object.\n Definition types.hxx:43\n-pqxx::format\n-format\n-Format code: is data text or binary?\n-Definition types.hxx:81\n-pqxx::format::text\n-@ text\n pqxx::format::binary\n @ binary\n-pqxx::binarystring\n-Binary data corresponding to PostgreSQL's \"BYTEA\" binary-string type.\n-Definition binarystring.hxx:59\n+pqxx::internal::cmp_less_equal\n+constexpr bool cmp_less_equal(LEFT lhs, RIGHT rhs) noexcept\n+C++20 std::cmp_less_equal, or workaround if not available.\n+Definition util.hxx:98\n+pqxx::blob\n+Definition blob.hxx:53\n pqxx::connection\n Connection to a database.\n Definition connection.hxx:253\n pqxx::dbtransaction\n Abstract transaction base class: bracket transactions on the database.\n Definition dbtransaction.hxx:54\n-pqxx::range_error\n-Something is out of range, similar to std::out_of_range.\n-Definition except.hxx:326\n-pqxx::field\n-Reference to a field in a result set.\n-Definition field.hxx:35\n+pqxx::internal_error\n+Internal error in libpqxx library.\n+Definition except.hxx:242\n+pqxx::largeobject\n+Identity of a large object.\n+Definition largeobject.hxx:34\n+pqxx::largeobject::operator==\n+bool operator==(largeobject const &other) const\n+Compare object identities.\n+Definition largeobject.hxx:89\n+pqxx::largeobject::operator>=\n+bool operator>=(largeobject const &other) const\n+Compare object identities.\n+Definition largeobject.hxx:107\n+pqxx::largeobject::raw_connection\n+static PQXX_PURE internal::pq::PGconn * raw_connection(dbtransaction const &T)\n+Definition largeobject.cxx:139\n+pqxx::largeobject::operator<=\n+bool operator<=(largeobject const &other) const\n+Compare object identities.\n+Definition largeobject.hxx:101\n+pqxx::largeobject::size_type\n+large_object_size_type size_type\n+Definition largeobject.hxx:36\n+pqxx::largeobject::operator<\n+bool operator<(largeobject const &other) const\n+Compare object identities.\n+Definition largeobject.hxx:113\n+pqxx::largeobject::largeobject\n+largeobject() noexcept=default\n+pqxx::largeobject::to_file\n+void to_file(dbtransaction &t, std::string_view file) const\n+Export large object's contents to a local file.\n+Definition largeobject.cxx:107\n+pqxx::largeobject::operator!=\n+bool operator!=(largeobject const &other) const\n+Compare object identities.\n+Definition largeobject.hxx:95\n+pqxx::largeobject::operator>\n+bool operator>(largeobject const &other) const\n+Compare object identities.\n+Definition largeobject.hxx:119\n+pqxx::largeobject::id\n+oid id() const noexcept\n+Object identifier.\n+Definition largeobject.hxx:77\n pqxx::largeobjectaccess\n Accessor for large object's contents.\n Definition largeobject.hxx:154\n-pqxx::notification_receiver\n-Definition notification.hxx:57\n-pqxx::result\n-Result set containing data returned by a query or command.\n-Definition result.hxx:73\n-pqxx::row\n-Reference to one row in a result.\n-Definition row.hxx:47\n-pqxx::const_row_iterator\n-Iterator for fields in a row. Use as row::const_iterator.\n-Definition row.hxx:283\n-pqxx::const_reverse_row_iterator\n-Reverse iterator for a row. Use as row::const_reverse_iterator.\n-Definition row.hxx:398\n-pqxx::stream_from\n-Stream data from the database.\n-Definition stream_from.hxx:79\n-pqxx::transaction_base\n-Interface definition (and common code) for \"transaction\" classes.\n-Definition transaction_base.hxx:88\n-pqxx::from_table_t\n-Marker for stream_from constructors: \"stream from table.\".\n-Definition types.hxx:68\n-pqxx::from_query_t\n-Marker for stream_from constructors: \"stream from query.\".\n-Definition types.hxx:74\n+pqxx::largeobjectaccess::pos_type\n+size_type pos_type\n+Definition largeobject.hxx:158\n+pqxx::largeobjectaccess::openmode\n+std::ios::openmode openmode\n+Open mode: in, out (can be combined using \"bitwise or\").\n+Definition largeobject.hxx:168\n+pqxx::largeobjectaccess::seekdir\n+std::ios::seekdir seekdir\n+Seek direction: beg, cur, end.\n+Definition largeobject.hxx:175\n+pqxx::largeobjectaccess::to_file\n+void to_file(std::string_view file) const\n+Export large object's contents to a local file.\n+Definition largeobject.hxx:228\n+pqxx::largeobjectaccess::~largeobjectaccess\n+~largeobjectaccess() noexcept\n+Definition largeobject.hxx:216\n+pqxx::largeobjectaccess::write\n+void write(std::string_view buf)\n+Write string to large object.\n+Definition largeobject.hxx:251\n+pqxx::largeobjectaccess::off_type\n+size_type off_type\n+Definition largeobject.hxx:157\n+pqxx::largeobject_streambuf\n+Streambuf to use large objects in standard I/O streams.\n+Definition largeobject.hxx:374\n+pqxx::largeobject_streambuf::seekoff\n+virtual pos_type seekoff(off_type offset, seekdir dir, openmode) override\n+Definition largeobject.hxx:425\n+pqxx::largeobject_streambuf::overflow\n+virtual int_type overflow(int_type ch) override\n+Definition largeobject.hxx:437\n+pqxx::largeobject_streambuf::traits_type\n+TRAITS traits_type\n+Definition largeobject.hxx:379\n+pqxx::largeobject_streambuf::int_type\n+typename traits_type::int_type int_type\n+Definition largeobject.hxx:380\n+pqxx::largeobject_streambuf::seekpos\n+virtual pos_type seekpos(pos_type pos, openmode) override\n+Definition largeobject.hxx:430\n+pqxx::largeobject_streambuf::largeobject_streambuf\n+largeobject_streambuf(dbtransaction &t, oid o, openmode mode=default_mode,\n+size_type buf_size=512)\n+Definition largeobject.hxx:400\n+pqxx::largeobject_streambuf::char_type\n+CHAR char_type\n+Definition largeobject.hxx:378\n+pqxx::largeobject_streambuf::off_type\n+typename traits_type::off_type off_type\n+Definition largeobject.hxx:382\n+pqxx::largeobject_streambuf::overflow\n+virtual int_type overflow()\n+Definition largeobject.hxx:479\n+pqxx::largeobject_streambuf::~largeobject_streambuf\n+virtual ~largeobject_streambuf() noexcept\n+Definition largeobject.hxx:408\n+pqxx::largeobject_streambuf::process_notice\n+void process_notice(zview const &s)\n+For use by large object stream classes.\n+Definition largeobject.hxx:415\n+pqxx::largeobject_streambuf::sync\n+virtual int sync() override\n+Definition largeobject.hxx:418\n+pqxx::largeobject_streambuf::seekdir\n+largeobjectaccess::seekdir seekdir\n+Definition largeobject.hxx:384\n+pqxx::largeobject_streambuf::underflow\n+virtual int_type underflow() override\n+Definition largeobject.hxx:481\n+pqxx::largeobject_streambuf::openmode\n+largeobjectaccess::openmode openmode\n+Definition largeobject.hxx:383\n+pqxx::largeobject_streambuf::pos_type\n+typename traits_type::pos_type pos_type\n+Definition largeobject.hxx:381\n+pqxx::largeobject_streambuf::largeobject_streambuf\n+largeobject_streambuf(dbtransaction &t, largeobject o, openmode\n+mode=default_mode, size_type buf_size=512)\n+Definition largeobject.hxx:391\n+pqxx::basic_ilostream\n+Input stream that gets its data from a large object.\n+Definition largeobject.hxx:546\n+pqxx::basic_ilostream::basic_ilostream\n+basic_ilostream(dbtransaction &t, oid o, largeobject::size_type buf_size=512)\n+Create a basic_ilostream.\n+Definition largeobject.hxx:578\n+pqxx::basic_ilostream::char_type\n+CHAR char_type\n+Definition largeobject.hxx:550\n+pqxx::basic_ilostream::basic_ilostream\n+basic_ilostream(dbtransaction &t, largeobject o, largeobject::size_type\n+buf_size=512)\n+Create a basic_ilostream.\n+Definition largeobject.hxx:563\n+pqxx::basic_ilostream::int_type\n+typename traits_type::int_type int_type\n+Definition largeobject.hxx:552\n+pqxx::basic_ilostream::traits_type\n+TRAITS traits_type\n+Definition largeobject.hxx:551\n+pqxx::basic_ilostream::off_type\n+typename traits_type::off_type off_type\n+Definition largeobject.hxx:554\n+pqxx::basic_ilostream::pos_type\n+typename traits_type::pos_type pos_type\n+Definition largeobject.hxx:553\n+pqxx::basic_olostream\n+Output stream that writes data back to a large object.\n+Definition largeobject.hxx:604\n+pqxx::basic_olostream::off_type\n+typename traits_type::off_type off_type\n+Definition largeobject.hxx:612\n+pqxx::basic_olostream::pos_type\n+typename traits_type::pos_type pos_type\n+Definition largeobject.hxx:611\n+pqxx::basic_olostream::basic_olostream\n+basic_olostream(dbtransaction &t, largeobject o, largeobject::size_type\n+buf_size=512)\n+Create a basic_olostream.\n+Definition largeobject.hxx:621\n+pqxx::basic_olostream::int_type\n+typename traits_type::int_type int_type\n+Definition largeobject.hxx:610\n+pqxx::basic_olostream::~basic_olostream\n+~basic_olostream()\n+Definition largeobject.hxx:644\n+pqxx::basic_olostream::char_type\n+CHAR char_type\n+Definition largeobject.hxx:608\n+pqxx::basic_olostream::basic_olostream\n+basic_olostream(dbtransaction &t, oid o, largeobject::size_type buf_size=512)\n+Create a basic_olostream.\n+Definition largeobject.hxx:636\n+pqxx::basic_olostream::traits_type\n+TRAITS traits_type\n+Definition largeobject.hxx:609\n+pqxx::basic_lostream\n+Stream that reads and writes a large object.\n+Definition largeobject.hxx:676\n+pqxx::basic_lostream::pos_type\n+typename traits_type::pos_type pos_type\n+Definition largeobject.hxx:683\n+pqxx::basic_lostream::~basic_lostream\n+~basic_lostream()\n+Definition largeobject.hxx:716\n+pqxx::basic_lostream::int_type\n+typename traits_type::int_type int_type\n+Definition largeobject.hxx:682\n+pqxx::basic_lostream::off_type\n+typename traits_type::off_type off_type\n+Definition largeobject.hxx:684\n+pqxx::basic_lostream::basic_lostream\n+basic_lostream(dbtransaction &t, largeobject o, largeobject::size_type\n+buf_size=512)\n+Create a basic_lostream.\n+Definition largeobject.hxx:692\n+pqxx::basic_lostream::basic_lostream\n+basic_lostream(dbtransaction &t, oid o, largeobject::size_type buf_size=512)\n+Create a basic_lostream.\n+Definition largeobject.hxx:707\n+pqxx::basic_lostream::traits_type\n+TRAITS traits_type\n+Definition largeobject.hxx:681\n+pqxx::basic_lostream::char_type\n+CHAR char_type\n+Definition largeobject.hxx:680\n+pqxx::zview\n+Marker-type wrapper: zero-terminated std::string_view.\n+Definition zview.hxx:38\n * include\n * pqxx\n- * types.hxx\n+ * largeobject.hxx\n * Generated by [doxygen] 1.9.8\n"}]}, {"source1": "./usr/share/doc/libpqxx-doc/html/a00101_source.html", "source2": "./usr/share/doc/libpqxx-doc/html/a00101_source.html", "unified_diff": "@@ -1,15 +1,15 @@\n \n \n \n \n \n \n \n-libpqxx: errorhandler.hxx Source File\n+libpqxx: dbtransaction.hxx Source File\n \n \n \n \n \n \n \n@@ -60,99 +60,73 @@\n \n
\n
\n-
errorhandler.hxx
\n+
dbtransaction.hxx
\n
\n
\n-
1/* Definition of the pqxx::errorhandler class.
\n+
1/* Definition of the pqxx::dbtransaction abstract base class.
\n
2 *
\n-
3 * pqxx::errorhandler handlers errors and warnings in a database session.
\n+
3 * pqxx::dbransaction defines a real transaction on the database.
\n
4 *
\n-
5 * DO NOT INCLUDE THIS FILE DIRECTLY; include pqxx/errorhandler instead.
\n+
5 * DO NOT INCLUDE THIS FILE DIRECTLY; include pqxx/dbtransaction instead.
\n
6 *
\n
7 * Copyright (c) 2000-2023, Jeroen T. Vermeulen.
\n
8 *
\n
9 * See COPYING for copyright license. If you did not receive a file called
\n
10 * COPYING with this source code, please notify the distributor of this
\n
11 * mistake, or contact the author.
\n
12 */
\n-
13#ifndef PQXX_H_ERRORHANDLER
\n-
14#define PQXX_H_ERRORHANDLER
\n+
13#ifndef PQXX_H_DBTRANSACTION
\n+
14#define PQXX_H_DBTRANSACTION
\n
15
\n
16#if !defined(PQXX_HEADER_PRE)
\n
17# error "Include libpqxx headers as <pqxx/header>, not <pqxx/header.hxx>."
\n
18#endif
\n
19
\n-
20#include "pqxx/types.hxx"
\n+
20#include "pqxx/transaction_base.hxx"
\n
21
\n-
22
\n-\n-
24{
\n-
25class errorhandler_connection;
\n-
26}
\n-
27
\n-
28
\n-
29namespace pqxx
\n-
30{
\n-
35
\n-
37
\n+
22namespace pqxx
\n+
23{
\n+
25
\n
\n-
53class PQXX_LIBEXPORT errorhandler
\n+
53class PQXX_LIBEXPORT PQXX_NOVTABLE dbtransaction : public transaction_base
\n
54{
\n-
55public:
\n-
56 explicit errorhandler(connection &);
\n-
57 virtual ~errorhandler();
\n-
58
\n-
61
\n-
65 virtual bool operator()(char const msg[]) noexcept = 0;
\n-
66
\n-
67 errorhandler() = delete;
\n-
68 errorhandler(errorhandler const &) = delete;
\n-\n-
70
\n-
71private:
\n-
72 connection *m_home;
\n-
73
\n-
74 friend class internal::gate::errorhandler_connection;
\n-
75 void unregister() noexcept;
\n-
76};
\n-
\n-
77
\n-
78
\n-
\n-\n-
81{
\n-
82public:
\n-\n-
85
\n-
87 virtual bool operator()(char const[]) noexcept override { return false; }
\n-
88};
\n-
\n-
89
\n-
91} // namespace pqxx
\n-
92#endif
\n+
55protected:
\n+\n+
\n+
59 dbtransaction(connection &c, std::string_view tname) :
\n+
60 transaction_base{c, tname}
\n+
61 {}
\n+
\n+
\n+\n+
64 connection &c, std::string_view tname,
\n+
65 std::shared_ptr<std::string> rollback_cmd) :
\n+
66 transaction_base{c, tname, rollback_cmd}
\n+
67 {}
\n+
\n+
68};
\n+
\n+
69} // namespace pqxx
\n+
70#endif
\n
The home of all libpqxx classes, functions, templates, etc.
Definition array.hxx:33
\n-
Definition connection.hxx:112
\n
Connection to a database.
Definition connection.hxx:253
\n-
Base class for error-handler callbacks.
Definition errorhandler.hxx:54
\n-\n-
virtual bool operator()(char const msg[]) noexcept=0
\n-
errorhandler & operator=(errorhandler const &)=delete
\n-
errorhandler(errorhandler const &)=delete
\n-
An error handler that suppresses any previously registered error handlers.
Definition errorhandler.hxx:81
\n-
virtual bool operator()(char const[]) noexcept override
Revert to previous handling of error notices.
Definition errorhandler.hxx:87
\n-
quiet_errorhandler(connection &conn)
Suppress error notices.
Definition errorhandler.hxx:84
\n+
Abstract transaction base class: bracket transactions on the database.
Definition dbtransaction.hxx:54
\n+
dbtransaction(connection &c, std::string_view tname, std::shared_ptr< std::string > rollback_cmd)
Begin transaction.
Definition dbtransaction.hxx:63
\n+
dbtransaction(connection &c)
Begin transaction.
Definition dbtransaction.hxx:57
\n+
dbtransaction(connection &c, std::string_view tname)
Begin transaction.
Definition dbtransaction.hxx:59
\n+
Interface definition (and common code) for "transaction" classes.
Definition transaction_base.hxx:88
\n
\n
\n \n
\n \n
\n \n \n", "details": [{"source1": "html2text {}", "source2": "html2text {}", "unified_diff": "@@ -1,105 +1,76 @@\n \n \n \n \n \n libpqxx\u00a07.8.1\n \n-errorhandler.hxx\n- 1/* Definition of the pqxx::errorhandler class.\n+dbtransaction.hxx\n+ 1/* Definition of the pqxx::dbtransaction abstract base class.\n 2 *\n- 3 * pqxx::errorhandler handlers errors and warnings in a database session.\n+ 3 * pqxx::dbransaction defines a real transaction on the database.\n 4 *\n- 5 * DO NOT INCLUDE THIS FILE DIRECTLY; include pqxx/errorhandler instead.\n+ 5 * DO NOT INCLUDE THIS FILE DIRECTLY; include pqxx/dbtransaction instead.\n 6 *\n 7 * Copyright (c) 2000-2023, Jeroen T. Vermeulen.\n 8 *\n 9 * See COPYING for copyright license. If you did not receive a file called\n 10 * COPYING with this source code, please notify the distributor of this\n 11 * mistake, or contact the author.\n 12 */\n- 13#ifndef PQXX_H_ERRORHANDLER\n- 14#define PQXX_H_ERRORHANDLER\n+ 13#ifndef PQXX_H_DBTRANSACTION\n+ 14#define PQXX_H_DBTRANSACTION\n 15\n 16#if !defined(PQXX_HEADER_PRE)\n 17# error \"Include libpqxx headers as , not .\"\n 18#endif\n 19\n- 20#include \"pqxx/types.hxx\"\n+ 20#include \"pqxx/transaction_base.hxx\"\n 21\n- 22\n- 23namespace pqxx::internal::gate\n- 24{\n- 25class errorhandler_connection;\n- 26}\n- 27\n- 28\n- 29namespace pqxx\n- 30{\n- 35\n- 37\n-53class PQXX_LIBEXPORT errorhandler\n+ 22namespace pqxx\n+ 23{\n+ 25\n+53class PQXX_LIBEXPORT PQXX_NOVTABLE dbtransaction : public transaction_base\n 54{\n- 55public:\n- 56 explicit errorhandler(connection &);\n- 57 virtual ~errorhandler();\n- 58\n- 61\n-65 virtual bool operator()(char const msg[]) noexcept = 0;\n- 66\n-67 errorhandler() = delete;\n-68 errorhandler(errorhandler const &) = delete;\n-69 errorhandler &operator=(errorhandler const &) = delete;\n- 70\n- 71private:\n- 72 connection *m_home;\n- 73\n-74 friend class internal::gate::errorhandler_connection;\n- 75 void unregister() noexcept;\n- 76};\n- 77\n- 78\n-80class quiet_errorhandler : public errorhandler\n- 81{\n- 82public:\n-84 quiet_errorhandler(connection &conn) : errorhandler{conn} {}\n- 85\n-87 virtual bool operator()(char const[]) noexcept override { return false; }\n- 88};\n- 89\n- 91} // namespace pqxx\n- 92#endif\n+ 55protected:\n+57 explicit dbtransaction(connection &c) : transaction_base{c} {}\n+59 dbtransaction(connection &c, std::string_view tname) :\n+ 60 transaction_base{c, tname}\n+ 61 {}\n+63 dbtransaction(\n+ 64 connection &c, std::string_view tname,\n+ 65 std::shared_ptr rollback_cmd) :\n+ 66 transaction_base{c, tname, rollback_cmd}\n+ 67 {}\n+ 68};\n+ 69} // namespace pqxx\n+ 70#endif\n pqxx\n The home of all libpqxx classes, functions, templates, etc.\n Definition array.hxx:33\n-pqxx::internal::gate\n-Definition connection.hxx:112\n pqxx::connection\n Connection to a database.\n Definition connection.hxx:253\n-pqxx::errorhandler\n-Base class for error-handler callbacks.\n-Definition errorhandler.hxx:54\n-pqxx::errorhandler::errorhandler\n-errorhandler()=delete\n-pqxx::errorhandler::operator()\n-virtual bool operator()(char const msg[]) noexcept=0\n-pqxx::errorhandler::operator=\n-errorhandler & operator=(errorhandler const &)=delete\n-pqxx::errorhandler::errorhandler\n-errorhandler(errorhandler const &)=delete\n-pqxx::quiet_errorhandler\n-An error handler that suppresses any previously registered error handlers.\n-Definition errorhandler.hxx:81\n-pqxx::quiet_errorhandler::operator()\n-virtual bool operator()(char const[]) noexcept override\n-Revert to previous handling of error notices.\n-Definition errorhandler.hxx:87\n-pqxx::quiet_errorhandler::quiet_errorhandler\n-quiet_errorhandler(connection &conn)\n-Suppress error notices.\n-Definition errorhandler.hxx:84\n+pqxx::dbtransaction\n+Abstract transaction base class: bracket transactions on the database.\n+Definition dbtransaction.hxx:54\n+pqxx::dbtransaction::dbtransaction\n+dbtransaction(connection &c, std::string_view tname, std::shared_ptr< std::\n+string > rollback_cmd)\n+Begin transaction.\n+Definition dbtransaction.hxx:63\n+pqxx::dbtransaction::dbtransaction\n+dbtransaction(connection &c)\n+Begin transaction.\n+Definition dbtransaction.hxx:57\n+pqxx::dbtransaction::dbtransaction\n+dbtransaction(connection &c, std::string_view tname)\n+Begin transaction.\n+Definition dbtransaction.hxx:59\n+pqxx::transaction_base\n+Interface definition (and common code) for \"transaction\" classes.\n+Definition transaction_base.hxx:88\n * include\n * pqxx\n- * errorhandler.hxx\n+ * dbtransaction.hxx\n * Generated by [doxygen] 1.9.8\n"}]}, {"source1": "./usr/share/doc/libpqxx-doc/html/a00104_source.html", "source2": "./usr/share/doc/libpqxx-doc/html/a00104_source.html", "unified_diff": "@@ -1,15 +1,15 @@\n \n \n \n \n \n \n \n-libpqxx: strconv.hxx Source File\n+libpqxx: isolation.hxx Source File\n \n \n \n \n \n \n \n@@ -60,435 +60,74 @@\n \n
\n
\n-
strconv.hxx
\n+
isolation.hxx
\n
\n
\n-
1/* String conversion definitions.
\n+
1/* Definitions for transaction isolation levels, and such.
\n
2 *
\n-
3 * DO NOT INCLUDE THIS FILE DIRECTLY; include pqxx/stringconv instead.
\n+
3 * DO NOT INCLUDE THIS FILE DIRECTLY; include pqxx/isolation instead.
\n
4 *
\n
5 * Copyright (c) 2000-2023, Jeroen T. Vermeulen.
\n
6 *
\n
7 * See COPYING for copyright license. If you did not receive a file called
\n
8 * COPYING with this source code, please notify the distributor of this
\n
9 * mistake, or contact the author.
\n
10 */
\n-
11#ifndef PQXX_H_STRCONV
\n-
12#define PQXX_H_STRCONV
\n+
11#ifndef PQXX_H_ISOLATION
\n+
12#define PQXX_H_ISOLATION
\n
13
\n
14#if !defined(PQXX_HEADER_PRE)
\n
15# error "Include libpqxx headers as <pqxx/header>, not <pqxx/header.hxx>."
\n
16#endif
\n
17
\n-
18#include <algorithm>
\n-
19#include <cstring>
\n-
20#include <limits>
\n-
21#include <sstream>
\n-
22#include <stdexcept>
\n-
23#include <typeinfo>
\n-
24
\n-
25#if __has_include(<charconv>)
\n-
26# include <charconv>
\n-
27#endif
\n-
28
\n-
29#if defined(PQXX_HAVE_RANGES) && __has_include(<ranges>)
\n-
30# include <ranges>
\n-
31#endif
\n-
32
\n-
33#include "pqxx/except.hxx"
\n-
34#include "pqxx/util.hxx"
\n-
35#include "pqxx/zview.hxx"
\n-
36
\n-
37
\n-
38namespace pqxx::internal
\n-
39{
\n-
41PQXX_LIBEXPORT std::string demangle_type_name(char const[]);
\n-
42} // namespace pqxx::internal
\n-
43
\n-
44
\n-
45namespace pqxx
\n-
46{
\n-
71
\n-
73
\n-
81template<typename TYPE>
\n-
82std::string const type_name{internal::demangle_type_name(typeid(TYPE).name())};
\n-
83
\n-
84
\n-
86
\n-
\n-
92template<typename TYPE, typename ENABLE = void> struct nullness
\n-
93{
\n-
95 static bool has_null;
\n-
96
\n-
98 static bool always_null;
\n-
99
\n-
101 static bool is_null(TYPE const &value);
\n-
102
\n-
104
\n-
109 [[nodiscard]] static TYPE null();
\n-
110};
\n-
\n-
111
\n-
112
\n-
\n-
114template<typename TYPE> struct no_null
\n-
115{
\n-
117
\n-
127 static constexpr bool has_null = false;
\n-
128
\n-
130
\n-
133 static constexpr bool always_null = false;
\n-
134
\n-
136
\n-
\n-
140 [[nodiscard]] static constexpr bool is_null(TYPE const &) noexcept
\n-
141 {
\n-
142 return false;
\n-
143 }
\n-
\n-
144};
\n-
\n-
145
\n-
146
\n-
148
\n-
\n-
154template<typename TYPE> struct string_traits
\n-
155{
\n-
157
\n-
160 static constexpr bool converts_to_string{false};
\n-
161
\n-
163
\n-
166 static constexpr bool converts_from_string{false};
\n-
167
\n-
169
\n-
188 [[nodiscard]] static inline zview
\n-
189 to_buf(char *begin, char *end, TYPE const &value);
\n-
190
\n-
192 /* @warning A null value has no string representation. Do not pass a null.
\n-
193 *
\n-
194 * Writes value's string representation into the buffer, starting exactly at
\n-
195 * @c begin, and ensuring a trailing zero. Returns the address just beyond
\n-
196 * the trailing zero, so the caller could use it as the @c begin for another
\n-
197 * call to @c into_buf writing a next value.
\n-
198 */
\n-
199 static inline char *into_buf(char *begin, char *end, TYPE const &value);
\n-
200
\n-
202
\n-
207 [[nodiscard]] static inline TYPE from_string(std::string_view text);
\n-
208
\n-
209 // C++20: Can we make these all constexpr?
\n-
211
\n-
215 [[nodiscard]] static inline std::size_t
\n-
216 size_buffer(TYPE const &value) noexcept;
\n-
217
\n-
218 // TODO: Move is_unquoted_string into the traits after all?
\n-
219};
\n-
\n-
220
\n-
221
\n-
223
\n-
239template<typename TYPE> [[noreturn]] void oops_forbidden_conversion() noexcept;
\n-
240
\n-
241
\n-
243
\n-
\n-
248template<typename TYPE> struct forbidden_conversion
\n-
249{
\n-
250 static constexpr bool converts_to_string{false};
\n-
251 static constexpr bool converts_from_string{false};
\n-
\n-
252 [[noreturn]] static zview to_buf(char *, char *, TYPE const &)
\n-
253 {
\n-
254 oops_forbidden_conversion<TYPE>();
\n-
255 }
\n-
\n-
\n-
256 [[noreturn]] static char *into_buf(char *, char *, TYPE const &)
\n-
257 {
\n-
258 oops_forbidden_conversion<TYPE>();
\n-
259 }
\n-
\n-
\n-
260 [[noreturn]] static TYPE from_string(std::string_view)
\n-
261 {
\n-
262 oops_forbidden_conversion<TYPE>();
\n-
263 }
\n-
\n-
\n-
264 [[noreturn]] static std::size_t size_buffer(TYPE const &) noexcept
\n-
265 {
\n-
266 oops_forbidden_conversion<TYPE>();
\n-
267 }
\n-
\n-
268};
\n-
\n-
269
\n-
270
\n-
272
\n-
\n-
288template<> struct string_traits<char> : forbidden_conversion<char>
\n-
289{};
\n+
18#include "pqxx/util.hxx"
\n+
19
\n+
20namespace pqxx
\n+
21{
\n+
23
\n+
\n+
26enum class write_policy
\n+
27{
\n+\n+\n+
30};
\n
\n-
290
\n-
291
\n-
293
\n-
307template<>
\n-
\n-
308struct string_traits<unsigned char> : forbidden_conversion<unsigned char>
\n-
309{};
\n-
\n-
310
\n-
311
\n-
313
\n-
327template<>
\n-
\n-
328struct string_traits<signed char> : forbidden_conversion<signed char>
\n-
329{};
\n-
\n-
330
\n-
331
\n-
333
\n-
\n-
338template<> struct string_traits<std::byte> : forbidden_conversion<std::byte>
\n-
339{};
\n-
\n-
340
\n-
341
\n-
343template<typename ENUM>
\n-
\n-
344struct nullness<ENUM, std::enable_if_t<std::is_enum_v<ENUM>>> : no_null<ENUM>
\n-
345{};
\n-
\n-
346
\n-
347
\n-
348// C++20: Concepts for "converts from string" & "converts to string."
\n-
349} // namespace pqxx
\n-
350
\n-
351
\n-
352namespace pqxx::internal
\n-
353{
\n-
355
\n-
\n-
364template<typename ENUM> struct enum_traits
\n-
365{
\n-
366 using impl_type = std::underlying_type_t<ENUM>;
\n-\n-
368
\n-
369 static constexpr bool converts_to_string{true};
\n-
370 static constexpr bool converts_from_string{true};
\n-
371
\n-
372 [[nodiscard]] static constexpr zview
\n-
\n-
373 to_buf(char *begin, char *end, ENUM const &value)
\n-
374 {
\n-
375 return impl_traits::to_buf(begin, end, to_underlying(value));
\n-
376 }
\n-
\n-
377
\n-
\n-
378 static constexpr char *into_buf(char *begin, char *end, ENUM const &value)
\n-
379 {
\n-
380 return impl_traits::into_buf(begin, end, to_underlying(value));
\n-
381 }
\n-
\n-
382
\n-
\n-
383 [[nodiscard]] static ENUM from_string(std::string_view text)
\n-
384 {
\n-
385 return static_cast<ENUM>(impl_traits::from_string(text));
\n-
386 }
\n-
\n-
387
\n-
\n-
388 [[nodiscard]] static std::size_t size_buffer(ENUM const &value) noexcept
\n-
389 {
\n-
390 return impl_traits::size_buffer(to_underlying(value));
\n-
391 }
\n-
\n-
392
\n-
393private:
\n-
394 // C++23: Replace with std::to_underlying.
\n-
395 static constexpr impl_type to_underlying(ENUM const &value) noexcept
\n-
396 {
\n-
397 return static_cast<impl_type>(value);
\n-
398 }
\n-
399};
\n+
31
\n+
32
\n+
34
\n+
\n+\n+
66{
\n+
67 // PostgreSQL only has the better isolation levels.
\n+
68 // read_uncommitted,
\n+
69
\n+\n+\n+\n+
73};
\n
\n-
400} // namespace pqxx::internal
\n-
401
\n-
402
\n-
403// We used to inline type_name<ENUM>, but this triggered a "double free" error
\n-
404// on program exit, when libpqxx was built as a shared library on Debian with
\n-
405// gcc 12.
\n-
406
\n-
408
\n-
419#define PQXX_DECLARE_ENUM_CONVERSION(ENUM) \\
\n-
420 template<> struct string_traits<ENUM> : pqxx::internal::enum_traits<ENUM> \\
\n-
421 {}; \\
\n-
422 template<> inline std::string_view const type_name<ENUM> \\
\n-
423 { \\
\n-
424# ENUM \\
\n-
425 }
\n-
426
\n-
427
\n-
428namespace pqxx
\n-
429{
\n-
431
\n-
443template<typename TYPE>
\n-
444[[nodiscard]] inline TYPE from_string(std::string_view text)
\n-
445{
\n-\n-
447}
\n-
448
\n-
449
\n-
451
\n-
457template<>
\n-
458[[nodiscard]] inline std::string_view from_string(std::string_view text)
\n-
459{
\n-
460 return text;
\n-
461}
\n-
462
\n-
463
\n-
465
\n-
472template<typename T> inline void from_string(std::string_view text, T &value)
\n-
473{
\n-
474 value = from_string<T>(text);
\n-
475}
\n-
476
\n-
477
\n-
479
\n-
484template<typename TYPE> inline std::string to_string(TYPE const &value);
\n-
485
\n-
486
\n-
488
\n-
495template<typename... TYPE>
\n-
496[[nodiscard]] inline std::vector<std::string_view>
\n-
497to_buf(char *here, char const *end, TYPE... value)
\n-
498{
\n-
499 return {[&here, end](auto v) {
\n-
500 auto begin = here;
\n-
501 here = string_traits<decltype(v)>::into_buf(begin, end, v);
\n-
502 // Exclude the trailing zero out of the string_view.
\n-
503 auto len{static_cast<std::size_t>(here - begin) - 1};
\n-
504 return std::string_view{begin, len};
\n-
505 }(value)...};
\n-
506}
\n-
507
\n-
509
\n-
512template<typename TYPE>
\n-
513inline void into_string(TYPE const &value, std::string &out);
\n-
514
\n-
515
\n-
517template<typename TYPE>
\n-
518[[nodiscard]] inline constexpr bool is_null(TYPE const &value) noexcept
\n-
519{
\n-
520 return nullness<strip_t<TYPE>>::is_null(value);
\n-
521}
\n-
522
\n-
523
\n-
525
\n-
528template<typename... TYPE>
\n-
529[[nodiscard]] inline std::size_t size_buffer(TYPE const &...value) noexcept
\n-
530{
\n-
531 return (string_traits<strip_t<TYPE>>::size_buffer(value) + ...);
\n-
532}
\n-
533
\n-
534
\n-
536
\n-
542template<typename TYPE> inline constexpr bool is_sql_array{false};
\n-
543
\n-
544
\n-
546
\n-
558template<typename TYPE> inline constexpr bool is_unquoted_safe{false};
\n-
559
\n-
560
\n-
562template<typename T> inline constexpr char array_separator{','};
\n-
563
\n-
564
\n-
566
\n-
573template<typename TYPE> inline constexpr format param_format(TYPE const &)
\n-
574{
\n-
575 return format::text;
\n-
576}
\n-
577
\n-
578
\n-
580
\n-
589template<typename TYPE>
\n-
590inline zview generic_to_buf(char *begin, char *end, TYPE const &value)
\n-
591{
\n-
592 using traits = string_traits<TYPE>;
\n-
593 // The trailing zero does not count towards the zview's size, so subtract 1
\n-
594 // from the result we get from into_buf().
\n-
595 if (is_null(value))
\n-
596 return {};
\n-
597 else
\n-
598 return {begin, traits::into_buf(begin, end, value) - begin - 1};
\n-
599}
\n-
600
\n-
601
\n-
602#if defined(PQXX_HAVE_CONCEPTS)
\n-
604
\n-
610template<class TYPE>
\n-
611concept binary = std::ranges::contiguous_range<TYPE> and
\n-
612 std::is_same_v<strip_t<value_type<TYPE>>, std::byte>;
\n-
613#endif
\n-
615} // namespace pqxx
\n-
616
\n-
617
\n-
618#include "pqxx/internal/conversions.hxx"
\n-
619#endif
\n+
74} // namespace pqxx
\n+
75#endif
\n
The home of all libpqxx classes, functions, templates, etc.
Definition array.hxx:33
\n-
std::string const type_name
A human-readable name for a type, used in error messages and such.
Definition strconv.hxx:82
\n-
void oops_forbidden_conversion() noexcept
Nonexistent function to indicate a disallowed type conversion.
\n-
std::string to_string(field const &value)
Convert a field to a string.
Definition result.cxx:549
\n-
T from_string(field const &value)
Convert a field's value to type T.
Definition field.hxx:520
\n-
format
Format code: is data text or binary?
Definition types.hxx:81
\n-\n-\n-
Internal items for libpqxx' own use. Do not use these yourself.
Definition composite.hxx:84
\n-
std::string demangle_type_name(char const[])
Attempt to demangle std::type_info::name() to something human-readable.
Definition strconv.cxx:230
\n-
Traits describing a type's "null value," if any.
Definition strconv.hxx:93
\n-
static bool is_null(TYPE const &value)
Is value a null?
\n-
static TYPE null()
Return a null value.
\n-
static bool has_null
Does this type have a null value?
Definition strconv.hxx:95
\n-
static bool always_null
Is this type always null?
Definition strconv.hxx:98
\n-
Nullness traits describing a type which does not have a null value.
Definition strconv.hxx:115
\n-
static constexpr bool always_null
Are all values of this type null?
Definition strconv.hxx:133
\n-
static constexpr bool has_null
Does TYPE have a "built-in null value"?
Definition strconv.hxx:127
\n-
static constexpr bool is_null(TYPE const &) noexcept
Does a given value correspond to an SQL null value?
Definition strconv.hxx:140
\n-
Traits class for use in string conversions.
Definition strconv.hxx:155
\n-
static std::size_t size_buffer(TYPE const &value) noexcept
Estimate how much buffer space is needed to represent value.
\n-
static zview to_buf(char *begin, char *end, TYPE const &value)
Return a string_view representing value, plus terminating zero.
\n-
static TYPE from_string(std::string_view text)
Parse a string representation of a TYPE value.
Definition strconv.cxx:740
\n-
static constexpr bool converts_to_string
Is conversion from TYPE to strings supported?
Definition strconv.hxx:160
\n-
static char * into_buf(char *begin, char *end, TYPE const &value)
Write value's string representation into buffer at begin.
\n-
static constexpr bool converts_from_string
Is conversion from string_view to TYPE supported?
Definition strconv.hxx:166
\n-
String traits for a forbidden type conversion.
Definition strconv.hxx:249
\n-
static char * into_buf(char *, char *, TYPE const &)
Definition strconv.hxx:256
\n-
static TYPE from_string(std::string_view)
Definition strconv.hxx:260
\n-
static std::size_t size_buffer(TYPE const &) noexcept
Definition strconv.hxx:264
\n-
static zview to_buf(char *, char *, TYPE const &)
Definition strconv.hxx:252
\n-
Helper class for defining enum conversions.
Definition strconv.hxx:365
\n-
static std::size_t size_buffer(ENUM const &value) noexcept
Definition strconv.hxx:388
\n-
static constexpr zview to_buf(char *begin, char *end, ENUM const &value)
Definition strconv.hxx:373
\n-
static constexpr bool converts_from_string
Definition strconv.hxx:370
\n-
std::underlying_type_t< ENUM > impl_type
Definition strconv.hxx:366
\n-
static ENUM from_string(std::string_view text)
Definition strconv.hxx:383
\n-
static constexpr char * into_buf(char *begin, char *end, ENUM const &value)
Definition strconv.hxx:378
\n-
static constexpr bool converts_to_string
Definition strconv.hxx:369
\n-
Marker-type wrapper: zero-terminated std::string_view.
Definition zview.hxx:38
\n+
write_policy
Should a transaction be read-only, or read-write?
Definition isolation.hxx:27
\n+\n+\n+
isolation_level
Transaction isolation levels.
Definition isolation.hxx:66
\n+
@ serializable
Definition isolation.hxx:72
\n+
@ read_committed
Definition isolation.hxx:70
\n+
@ repeatable_read
Definition isolation.hxx:71
\n
\n
\n \n
\n \n
\n \n \n", "details": [{"source1": "html2text {}", "source2": "html2text {}", "unified_diff": "@@ -1,489 +1,77 @@\n \n \n \n \n \n libpqxx\u00a07.8.1\n \n-strconv.hxx\n- 1/* String conversion definitions.\n+isolation.hxx\n+ 1/* Definitions for transaction isolation levels, and such.\n 2 *\n- 3 * DO NOT INCLUDE THIS FILE DIRECTLY; include pqxx/stringconv instead.\n+ 3 * DO NOT INCLUDE THIS FILE DIRECTLY; include pqxx/isolation instead.\n 4 *\n 5 * Copyright (c) 2000-2023, Jeroen T. Vermeulen.\n 6 *\n 7 * See COPYING for copyright license. If you did not receive a file called\n 8 * COPYING with this source code, please notify the distributor of this\n 9 * mistake, or contact the author.\n 10 */\n- 11#ifndef PQXX_H_STRCONV\n- 12#define PQXX_H_STRCONV\n+ 11#ifndef PQXX_H_ISOLATION\n+ 12#define PQXX_H_ISOLATION\n 13\n 14#if !defined(PQXX_HEADER_PRE)\n 15# error \"Include libpqxx headers as , not .\"\n 16#endif\n 17\n- 18#include \n- 19#include \n- 20#include \n- 21#include \n- 22#include \n- 23#include \n- 24\n- 25#if __has_include()\n- 26# include \n- 27#endif\n- 28\n- 29#if defined(PQXX_HAVE_RANGES) && __has_include()\n- 30# include \n- 31#endif\n+ 18#include \"pqxx/util.hxx\"\n+ 19\n+ 20namespace pqxx\n+ 21{\n+ 23\n+26enum class write_policy\n+ 27{\n+ 28 read_only,\n+ 29 read_write\n+ 30};\n+ 31\n 32\n- 33#include \"pqxx/except.hxx\"\n- 34#include \"pqxx/util.hxx\"\n- 35#include \"pqxx/zview.hxx\"\n- 36\n- 37\n- 38namespace pqxx::internal\n- 39{\n- 41PQXX_LIBEXPORT std::string demangle_type_name(char const[]);\n- 42} // namespace pqxx::internal\n- 43\n- 44\n- 45namespace pqxx\n- 46{\n- 71\n- 73\n- 81template\n-82std::string const type_name{internal::demangle_type_name(typeid(TYPE).name\n-())};\n- 83\n- 84\n- 86\n-92template struct nullness\n- 93{\n-95 static bool has_null;\n- 96\n-98 static bool always_null;\n- 99\n-101 static bool is_null(TYPE const &value);\n- 102\n- 104\n-109 [[nodiscard]] static TYPE null();\n- 110};\n- 111\n- 112\n-114template struct no_null\n- 115{\n- 117\n-127 static constexpr bool has_null = false;\n- 128\n- 130\n-133 static constexpr bool always_null = false;\n- 134\n- 136\n-140 [[nodiscard]] static constexpr bool is_null(TYPE const &) noexcept\n- 141 {\n- 142 return false;\n- 143 }\n- 144};\n- 145\n- 146\n- 148\n-154template struct string_traits\n- 155{\n- 157\n-160 static constexpr bool converts_to_string{false};\n- 161\n- 163\n-166 static constexpr bool converts_from_string{false};\n- 167\n- 169\n- 188 [[nodiscard]] static inline zview\n-189 to_buf(char *begin, char *end, TYPE const &value);\n- 190\n- 192 /* @warning A null value has no string representation. Do not pass a null.\n- 193 *\n- 194 * Writes value's string representation into the buffer, starting exactly\n-at\n- 195 * @c begin, and ensuring a trailing zero. Returns the address just beyond\n- 196 * the trailing zero, so the caller could use it as the @c begin for\n-another\n- 197 * call to @c into_buf writing a next value.\n- 198 */\n-199 static inline char *into_buf(char *begin, char *end, TYPE const &value);\n- 200\n- 202\n- 207 [[nodiscard]] static inline TYPE from_string(std::string_view text);\n- 208\n- 209 // C++20: Can we make these all constexpr?\n- 211\n- 215 [[nodiscard]] static inline std::size_t\n-216 size_buffer(TYPE const &value) noexcept;\n- 217\n- 218 // TODO: Move is_unquoted_string into the traits after all?\n- 219};\n- 220\n- 221\n- 223\n-239template [[noreturn]] void oops_forbidden_conversion()\n-noexcept;\n- 240\n- 241\n- 243\n-248template struct forbidden_conversion\n- 249{\n-250 static constexpr bool converts_to_string{false};\n-251 static constexpr bool converts_from_string{false};\n-252 [[noreturn]] static zview to_buf(char *, char *, TYPE const &)\n- 253 {\n- 254 oops_forbidden_conversion();\n- 255 }\n-256 [[noreturn]] static char *into_buf(char *, char *, TYPE const &)\n- 257 {\n- 258 oops_forbidden_conversion();\n- 259 }\n-260 [[noreturn]] static TYPE from_string(std::string_view)\n- 261 {\n- 262 oops_forbidden_conversion();\n- 263 }\n-264 [[noreturn]] static std::size_t size_buffer(TYPE const &) noexcept\n- 265 {\n- 266 oops_forbidden_conversion();\n- 267 }\n- 268};\n- 269\n- 270\n- 272\n-288template<> struct string_traits : forbidden_conversion\n- 289{};\n- 290\n- 291\n- 293\n- 307template<>\n-308struct string_traits : forbidden_conversion\n- 309{};\n- 310\n- 311\n- 313\n- 327template<>\n-328struct string_traits : forbidden_conversion\n- 329{};\n- 330\n- 331\n- 333\n-338template<> struct string_traits : forbidden_conversion\n- 339{};\n- 340\n- 341\n- 343template\n-344struct nullness>> :\n-no_null\n- 345{};\n- 346\n- 347\n- 348// C++20: Concepts for \"converts from string\" & \"converts to string.\"\n- 349} // namespace pqxx\n- 350\n- 351\n- 352namespace pqxx::internal\n- 353{\n- 355\n-364template struct enum_traits\n- 365{\n-366 using impl_type = std::underlying_type_t;\n-367 using impl_traits = string_traits;\n- 368\n-369 static constexpr bool converts_to_string{true};\n-370 static constexpr bool converts_from_string{true};\n- 371\n- 372 [[nodiscard]] static constexpr zview\n-373 to_buf(char *begin, char *end, ENUM const &value)\n- 374 {\n- 375 return impl_traits::to_buf(begin, end, to_underlying(value));\n- 376 }\n- 377\n-378 static constexpr char *into_buf(char *begin, char *end, ENUM const &value)\n- 379 {\n- 380 return impl_traits::into_buf(begin, end, to_underlying(value));\n- 381 }\n- 382\n-383 [[nodiscard]] static ENUM from_string(std::string_view text)\n- 384 {\n- 385 return static_cast(impl_traits::from_string(text));\n- 386 }\n- 387\n-388 [[nodiscard]] static std::size_t size_buffer(ENUM const &value) noexcept\n- 389 {\n- 390 return impl_traits::size_buffer(to_underlying(value));\n- 391 }\n- 392\n- 393private:\n- 394 // C++23: Replace with std::to_underlying.\n- 395 static constexpr impl_type to_underlying(ENUM const &value) noexcept\n- 396 {\n- 397 return static_cast(value);\n- 398 }\n- 399};\n- 400} // namespace pqxx::internal\n- 401\n- 402\n- 403// We used to inline type_name, but this triggered a \"double free\"\n-error\n- 404// on program exit, when libpqxx was built as a shared library on Debian\n-with\n- 405// gcc 12.\n- 406\n- 408\n- 419#define PQXX_DECLARE_ENUM_CONVERSION(ENUM) \\\n- 420 template<> struct string_traits : pqxx::internal::enum_traits\n-\\\n- 421 {}; \\\n- 422 template<> inline std::string_view const type_name \\\n- 423 { \\\n- 424# ENUM \\\n- 425 }\n- 426\n- 427\n- 428namespace pqxx\n- 429{\n- 431\n- 443template\n- 444[[nodiscard]] inline TYPE from_string(std::string_view text)\n- 445{\n- 446 return string_traits::from_string(text);\n- 447}\n- 448\n- 449\n- 451\n- 457template<>\n- 458[[nodiscard]] inline std::string_view from_string(std::string_view text)\n- 459{\n- 460 return text;\n- 461}\n- 462\n- 463\n- 465\n- 472template inline void from_string(std::string_view text, T\n-&value)\n- 473{\n- 474 value = from_string(text);\n- 475}\n- 476\n- 477\n- 479\n- 484template inline std::string to_string(TYPE const &value);\n- 485\n- 486\n- 488\n- 495template\n- 496[[nodiscard]] inline std::vector\n- 497to_buf(char *here, char const *end, TYPE... value)\n- 498{\n- 499 return {[&here, end](auto v) {\n- 500 auto begin = here;\n- 501 here = string_traits::into_buf(begin, end, v);\n- 502 // Exclude the trailing zero out of the string_view.\n- 503 auto len{static_cast(here - begin) - 1};\n- 504 return std::string_view{begin, len};\n- 505 }(value)...};\n- 506}\n- 507\n- 509\n- 512template\n- 513inline void into_string(TYPE const &value, std::string &out);\n- 514\n- 515\n- 517template\n- 518[[nodiscard]] inline constexpr bool is_null(TYPE const &value) noexcept\n- 519{\n- 520 return nullness>::is_null(value);\n- 521}\n- 522\n- 523\n- 525\n- 528template\n- 529[[nodiscard]] inline std::size_t size_buffer(TYPE const &...value) noexcept\n- 530{\n- 531 return (string_traits>::size_buffer(value) + ...);\n- 532}\n- 533\n- 534\n- 536\n- 542template inline constexpr bool is_sql_array{false};\n- 543\n- 544\n- 546\n- 558template inline constexpr bool is_unquoted_safe{false};\n- 559\n- 560\n- 562template inline constexpr char array_separator{','};\n- 563\n- 564\n- 566\n- 573template inline constexpr format param_format(TYPE const &)\n- 574{\n- 575 return format::text;\n- 576}\n- 577\n- 578\n- 580\n- 589template\n- 590inline zview generic_to_buf(char *begin, char *end, TYPE const &value)\n- 591{\n- 592 using traits = string_traits;\n- 593 // The trailing zero does not count towards the zview's size, so subtract\n-1\n- 594 // from the result we get from into_buf().\n- 595 if (is_null(value))\n- 596 return {};\n- 597 else\n- 598 return {begin, traits::into_buf(begin, end, value) - begin - 1};\n- 599}\n- 600\n- 601\n- 602#if defined(PQXX_HAVE_CONCEPTS)\n- 604\n- 610template\n- 611concept binary = std::ranges::contiguous_range and\n- 612 std::is_same_v>, std::byte>;\n- 613#endif\n- 615} // namespace pqxx\n- 616\n- 617\n- 618#include \"pqxx/internal/conversions.hxx\"\n- 619#endif\n+ 34\n+65enum isolation_level\n+ 66{\n+ 67 // PostgreSQL only has the better isolation levels.\n+ 68 // read_uncommitted,\n+ 69\n+70 read_committed,\n+71 repeatable_read,\n+72 serializable,\n+ 73};\n+ 74} // namespace pqxx\n+ 75#endif\n pqxx\n The home of all libpqxx classes, functions, templates, etc.\n Definition array.hxx:33\n-pqxx::type_name\n-std::string const type_name\n-A human-readable name for a type, used in error messages and such.\n-Definition strconv.hxx:82\n-pqxx::oops_forbidden_conversion\n-void oops_forbidden_conversion() noexcept\n-Nonexistent function to indicate a disallowed type conversion.\n-pqxx::to_string\n-std::string to_string(field const &value)\n-Convert a field to a string.\n-Definition result.cxx:549\n-pqxx::from_string\n-T from_string(field const &value)\n-Convert a field's value to type T.\n-Definition field.hxx:520\n-pqxx::format\n-format\n-Format code: is data text or binary?\n-Definition types.hxx:81\n-pqxx::format::text\n-@ text\n-pqxx::format::binary\n-@ binary\n-pqxx::internal\n-Internal items for libpqxx' own use. Do not use these yourself.\n-Definition composite.hxx:84\n-pqxx::internal::demangle_type_name\n-std::string demangle_type_name(char const[])\n-Attempt to demangle std::type_info::name() to something human-readable.\n-Definition strconv.cxx:230\n-pqxx::nullness\n-Traits describing a type's \"null value,\" if any.\n-Definition strconv.hxx:93\n-pqxx::nullness::is_null\n-static bool is_null(TYPE const &value)\n-Is value a null?\n-pqxx::nullness::null\n-static TYPE null()\n-Return a null value.\n-pqxx::nullness::has_null\n-static bool has_null\n-Does this type have a null value?\n-Definition strconv.hxx:95\n-pqxx::nullness::always_null\n-static bool always_null\n-Is this type always null?\n-Definition strconv.hxx:98\n-pqxx::no_null\n-Nullness traits describing a type which does not have a null value.\n-Definition strconv.hxx:115\n-pqxx::no_null::always_null\n-static constexpr bool always_null\n-Are all values of this type null?\n-Definition strconv.hxx:133\n-pqxx::no_null::has_null\n-static constexpr bool has_null\n-Does TYPE have a \"built-in null value\"?\n-Definition strconv.hxx:127\n-pqxx::no_null::is_null\n-static constexpr bool is_null(TYPE const &) noexcept\n-Does a given value correspond to an SQL null value?\n-Definition strconv.hxx:140\n-pqxx::string_traits\n-Traits class for use in string conversions.\n-Definition strconv.hxx:155\n-pqxx::string_traits::size_buffer\n-static std::size_t size_buffer(TYPE const &value) noexcept\n-Estimate how much buffer space is needed to represent value.\n-pqxx::string_traits::to_buf\n-static zview to_buf(char *begin, char *end, TYPE const &value)\n-Return a string_view representing value, plus terminating zero.\n-pqxx::string_traits::from_string\n-static TYPE from_string(std::string_view text)\n-Parse a string representation of a TYPE value.\n-Definition strconv.cxx:740\n-pqxx::string_traits::converts_to_string\n-static constexpr bool converts_to_string\n-Is conversion from TYPE to strings supported?\n-Definition strconv.hxx:160\n-pqxx::string_traits::into_buf\n-static char * into_buf(char *begin, char *end, TYPE const &value)\n-Write value's string representation into buffer at begin.\n-pqxx::string_traits::converts_from_string\n-static constexpr bool converts_from_string\n-Is conversion from string_view to TYPE supported?\n-Definition strconv.hxx:166\n-pqxx::forbidden_conversion\n-String traits for a forbidden type conversion.\n-Definition strconv.hxx:249\n-pqxx::forbidden_conversion::into_buf\n-static char * into_buf(char *, char *, TYPE const &)\n-Definition strconv.hxx:256\n-pqxx::forbidden_conversion::from_string\n-static TYPE from_string(std::string_view)\n-Definition strconv.hxx:260\n-pqxx::forbidden_conversion::size_buffer\n-static std::size_t size_buffer(TYPE const &) noexcept\n-Definition strconv.hxx:264\n-pqxx::forbidden_conversion::to_buf\n-static zview to_buf(char *, char *, TYPE const &)\n-Definition strconv.hxx:252\n-pqxx::internal::enum_traits\n-Helper class for defining enum conversions.\n-Definition strconv.hxx:365\n-pqxx::internal::enum_traits::size_buffer\n-static std::size_t size_buffer(ENUM const &value) noexcept\n-Definition strconv.hxx:388\n-pqxx::internal::enum_traits::to_buf\n-static constexpr zview to_buf(char *begin, char *end, ENUM const &value)\n-Definition strconv.hxx:373\n-pqxx::internal::enum_traits::converts_from_string\n-static constexpr bool converts_from_string\n-Definition strconv.hxx:370\n-pqxx::internal::enum_traits::impl_type\n-std::underlying_type_t< ENUM > impl_type\n-Definition strconv.hxx:366\n-pqxx::internal::enum_traits::from_string\n-static ENUM from_string(std::string_view text)\n-Definition strconv.hxx:383\n-pqxx::internal::enum_traits::into_buf\n-static constexpr char * into_buf(char *begin, char *end, ENUM const &value)\n-Definition strconv.hxx:378\n-pqxx::internal::enum_traits::converts_to_string\n-static constexpr bool converts_to_string\n-Definition strconv.hxx:369\n-pqxx::zview\n-Marker-type wrapper: zero-terminated std::string_view.\n-Definition zview.hxx:38\n+pqxx::write_policy\n+write_policy\n+Should a transaction be read-only, or read-write?\n+Definition isolation.hxx:27\n+pqxx::write_policy::read_write\n+@ read_write\n+pqxx::write_policy::read_only\n+@ read_only\n+pqxx::isolation_level\n+isolation_level\n+Transaction isolation levels.\n+Definition isolation.hxx:66\n+pqxx::serializable\n+@ serializable\n+Definition isolation.hxx:72\n+pqxx::read_committed\n+@ read_committed\n+Definition isolation.hxx:70\n+pqxx::repeatable_read\n+@ repeatable_read\n+Definition isolation.hxx:71\n * include\n * pqxx\n- * strconv.hxx\n+ * isolation.hxx\n * Generated by [doxygen] 1.9.8\n"}]}, {"source1": "./usr/share/doc/libpqxx-doc/html/a00107_source.html", "source2": "./usr/share/doc/libpqxx-doc/html/a00107_source.html", "unified_diff": "@@ -1,15 +1,15 @@\n \n \n \n \n \n \n \n-libpqxx: config-internal-autotools.h Source File\n+libpqxx: stream_to.hxx Source File\n \n \n \n \n \n \n \n@@ -60,30 +60,386 @@\n \n
\n
\n-
config-internal-autotools.h
\n+
stream_to.hxx
\n
\n
\n-
1/* Automatically generated from config.h: internal/autotools config. */
\n-
2
\n-
3#define PACKAGE "libpqxx"
\n-
4#define PACKAGE_BUGREPORT "Jeroen T. Vermeulen"
\n-
5#define PACKAGE_NAME "libpqxx"
\n-
6#define PACKAGE_STRING "libpqxx 7.8.1"
\n-
7#define PACKAGE_TARNAME "libpqxx"
\n-
8#define PACKAGE_VERSION "7.8.1"
\n-
9#define VERSION "7.8.1"
\n+
1/* Definition of the pqxx::stream_to class.
\n+
2 *
\n+
3 * pqxx::stream_to enables optimized batch updates to a database table.
\n+
4 *
\n+
5 * DO NOT INCLUDE THIS FILE DIRECTLY; include pqxx/stream_to.hxx instead.
\n+
6 *
\n+
7 * Copyright (c) 2000-2023, Jeroen T. Vermeulen.
\n+
8 *
\n+
9 * See COPYING for copyright license. If you did not receive a file called
\n+
10 * COPYING with this source code, please notify the distributor of this
\n+
11 * mistake, or contact the author.
\n+
12 */
\n+
13#ifndef PQXX_H_STREAM_TO
\n+
14#define PQXX_H_STREAM_TO
\n+
15
\n+
16#if !defined(PQXX_HEADER_PRE)
\n+
17# error "Include libpqxx headers as <pqxx/header>, not <pqxx/header.hxx>."
\n+
18#endif
\n+
19
\n+
20#include "pqxx/separated_list.hxx"
\n+
21#include "pqxx/transaction_base.hxx"
\n+
22
\n+
23
\n+
24namespace pqxx
\n+
25{
\n+
27
\n+
\n+
80class PQXX_LIBEXPORT stream_to : transaction_focus
\n+
81{
\n+
82public:
\n+
84
\n+
\n+\n+
105 transaction_base &tx, std::string_view path, std::string_view columns = "")
\n+
106 {
\n+
107 return {tx, path, columns};
\n+
108 }
\n+
\n+
109
\n+
111
\n+
\n+\n+\n+
122 std::initializer_list<std::string_view> columns = {})
\n+
123 {
\n+
124 auto const &conn{tx.conn()};
\n+
125 return raw_table(tx, conn.quote_table(path), conn.quote_columns(columns));
\n+
126 }
\n+
\n+
127
\n+
128#if defined(PQXX_HAVE_CONCEPTS)
\n+
130
\n+
137 template<PQXX_CHAR_STRINGS_ARG COLUMNS>
\n+
138 static stream_to
\n+
139 table(transaction_base &tx, table_path path, COLUMNS const &columns)
\n+
140 {
\n+
141 auto const &conn{tx.conn()};
\n+\n+
143 tx, conn.quote_table(path), tx.conn().quote_columns(columns));
\n+
144 }
\n+
145
\n+
147
\n+
154 template<PQXX_CHAR_STRINGS_ARG COLUMNS>
\n+
155 static stream_to
\n+
156 table(transaction_base &tx, std::string_view path, COLUMNS const &columns)
\n+
157 {
\n+
158 return stream_to::raw_table(tx, path, tx.conn().quote_columns(columns));
\n+
159 }
\n+
160#endif // PQXX_HAVE_CONCEPTS
\n+
161
\n+
163
\n+
\n+
172 [[deprecated("Use table() or raw_table() factory.")]] stream_to(
\n+
173 transaction_base &tx, std::string_view table_name) :
\n+
174 stream_to{tx, table_name, ""sv}
\n+
175 {}
\n+
\n+
176
\n+
178
\n+
180 template<typename Columns>
\n+
181 [[deprecated("Use table() or raw_table() factory.")]] stream_to(
\n+
182 transaction_base &, std::string_view table_name, Columns const &columns);
\n+
183
\n+
185
\n+
187 template<typename Iter>
\n+
188 [[deprecated("Use table() or raw_table() factory.")]] stream_to(
\n+
189 transaction_base &, std::string_view table_name, Iter columns_begin,
\n+
190 Iter columns_end);
\n+
191
\n+
\n+
192 explicit stream_to(stream_to &&other) :
\n+
193 // (This first step only moves the transaction_focus base-class
\n+
194 // object.)
\n+
195 transaction_focus{std::move(other)},
\n+
196 m_finished{other.m_finished},
\n+
197 m_buffer{std::move(other.m_buffer)},
\n+
198 m_field_buf{std::move(other.m_field_buf)},
\n+
199 m_finder{other.m_finder}
\n+
200 {
\n+
201 other.m_finished = true;
\n+
202 }
\n+
\n+
203 ~stream_to() noexcept;
\n+
204
\n+
\n+
206 [[nodiscard]] constexpr operator bool() const noexcept
\n+
207 {
\n+
208 return not m_finished;
\n+
209 }
\n+
\n+
\n+
211 [[nodiscard]] constexpr bool operator!() const noexcept
\n+
212 {
\n+
213 return m_finished;
\n+
214 }
\n+
\n+
215
\n+
217
\n+
223 void complete();
\n+
224
\n+
226
\n+
\n+
235 template<typename Row> stream_to &operator<<(Row const &row)
\n+
236 {
\n+
237 write_row(row);
\n+
238 return *this;
\n+
239 }
\n+
\n+
240
\n+
242
\n+\n+
247
\n+
249
\n+
\n+
255 template<typename Row> void write_row(Row const &row)
\n+
256 {
\n+
257 fill_buffer(row);
\n+
258 write_buffer();
\n+
259 }
\n+
\n+
260
\n+
262
\n+
\n+
265 template<typename... Ts> void write_values(Ts const &...fields)
\n+
266 {
\n+
267 fill_buffer(fields...);
\n+
268 write_buffer();
\n+
269 }
\n+
\n+
270
\n+
271private:
\n+
273 stream_to(
\n+
274 transaction_base &tx, std::string_view path, std::string_view columns);
\n+
275
\n+
276 bool m_finished = false;
\n+
277
\n+
279 std::string m_buffer;
\n+
280
\n+
282 std::string m_field_buf;
\n+
283
\n+
285 internal::char_finder_func *m_finder;
\n+
286
\n+
288 void write_raw_line(std::string_view);
\n+
289
\n+
291
\n+
293 void write_buffer();
\n+
294
\n+
296 static constexpr std::string_view null_field{"\\\\N\\t"};
\n+
297
\n+
299 template<typename T>
\n+
300 static std::enable_if_t<nullness<T>::always_null, std::size_t>
\n+
301 estimate_buffer(T const &)
\n+
302 {
\n+
303 return std::size(null_field);
\n+
304 }
\n+
305
\n+
307
\n+
310 template<typename T>
\n+
311 static std::enable_if_t<not nullness<T>::always_null, std::size_t>
\n+
312 estimate_buffer(T const &field)
\n+
313 {
\n+
314 return is_null(field) ? std::size(null_field) : size_buffer(field);
\n+
315 }
\n+
316
\n+
318 void escape_field_to_buffer(std::string_view data);
\n+
319
\n+
321
\n+
327 template<typename Field>
\n+
328 std::enable_if_t<not nullness<Field>::always_null>
\n+
329 append_to_buffer(Field const &f)
\n+
330 {
\n+
331 // We append each field, terminated by a tab. That will leave us with
\n+
332 // one tab too many, assuming we write any fields at all; we remove that
\n+
333 // at the end.
\n+
334 if (is_null(f))
\n+
335 {
\n+
336 // Easy. Append null and tab in one go.
\n+
337 m_buffer.append(null_field);
\n+
338 }
\n+
339 else
\n+
340 {
\n+
341 // Convert f into m_buffer.
\n+
342
\n+
343 using traits = string_traits<Field>;
\n+
344 auto const budget{estimate_buffer(f)};
\n+
345 auto const offset{std::size(m_buffer)};
\n+
346
\n+
347 if constexpr (std::is_arithmetic_v<Field>)
\n+
348 {
\n+
349 // Specially optimised for "safe" types, which never need any
\n+
350 // escaping. Convert straight into m_buffer.
\n+
351
\n+
352 // The budget we get from size_buffer() includes room for the trailing
\n+
353 // zero, which we must remove. But we're also inserting tabs between
\n+
354 // fields, so we re-purpose the extra byte for that.
\n+
355 auto const total{offset + budget};
\n+
356 m_buffer.resize(total);
\n+
357 auto const data{m_buffer.data()};
\n+
358 char *const end{traits::into_buf(data + offset, data + total, f)};
\n+
359 *(end - 1) = '\\t';
\n+
360 // Shrink to fit. Keep the tab though.
\n+
361 m_buffer.resize(static_cast<std::size_t>(end - data));
\n+
362 }
\n+
363 else if constexpr (
\n+
364 std::is_same_v<Field, std::string> or
\n+
365 std::is_same_v<Field, std::string_view> or
\n+
366 std::is_same_v<Field, zview>)
\n+
367 {
\n+
368 // This string may need escaping.
\n+
369 m_field_buf.resize(budget);
\n+
370 escape_field_to_buffer(f);
\n+
371 }
\n+
372 else if constexpr (
\n+
373 std::is_same_v<Field, std::optional<std::string>> or
\n+
374 std::is_same_v<Field, std::optional<std::string_view>> or
\n+
375 std::is_same_v<Field, std::optional<zview>>)
\n+
376 {
\n+
377 // Optional string. It's not null (we checked for that above), so...
\n+
378 // Treat like a string.
\n+
379 m_field_buf.resize(budget);
\n+
380 escape_field_to_buffer(f.value());
\n+
381 }
\n+
382 // TODO: Support deleter template argument on unique_ptr.
\n+
383 else if constexpr (
\n+
384 std::is_same_v<Field, std::unique_ptr<std::string>> or
\n+
385 std::is_same_v<Field, std::unique_ptr<std::string_view>> or
\n+
386 std::is_same_v<Field, std::unique_ptr<zview>> or
\n+
387 std::is_same_v<Field, std::shared_ptr<std::string>> or
\n+
388 std::is_same_v<Field, std::shared_ptr<std::string_view>> or
\n+
389 std::is_same_v<Field, std::shared_ptr<zview>>)
\n+
390 {
\n+
391 // TODO: Can we generalise this elegantly without Concepts?
\n+
392 // Effectively also an optional string. It's not null (we checked
\n+
393 // for that above).
\n+
394 m_field_buf.resize(budget);
\n+
395 escape_field_to_buffer(*f);
\n+
396 }
\n+
397 else
\n+
398 {
\n+
399 // This field needs to be converted to a string, and after that,
\n+
400 // escaped as well.
\n+
401 m_field_buf.resize(budget);
\n+
402 auto const data{m_field_buf.data()};
\n+
403 escape_field_to_buffer(
\n+
404 traits::to_buf(data, data + std::size(m_field_buf), f));
\n+
405 }
\n+
406 }
\n+
407 }
\n+
408
\n+
410
\n+
416 template<typename Field>
\n+
417 std::enable_if_t<nullness<Field>::always_null>
\n+
418 append_to_buffer(Field const &)
\n+
419 {
\n+
420 m_buffer.append(null_field);
\n+
421 }
\n+
422
\n+
424 template<typename Container>
\n+
425 std::enable_if_t<not std::is_same_v<typename Container::value_type, char>>
\n+
426 fill_buffer(Container const &c)
\n+
427 {
\n+
428 // To avoid unnecessary allocations and deallocations, we run through c
\n+
429 // twice: once to determine how much buffer space we may need, and once to
\n+
430 // actually write it into the buffer.
\n+
431 std::size_t budget{0};
\n+
432 for (auto const &f : c) budget += estimate_buffer(f);
\n+
433 m_buffer.reserve(budget);
\n+
434 for (auto const &f : c) append_to_buffer(f);
\n+
435 }
\n+
436
\n+
438 template<typename Tuple, std::size_t... indexes>
\n+
439 static std::size_t
\n+
440 budget_tuple(Tuple const &t, std::index_sequence<indexes...>)
\n+
441 {
\n+
442 return (estimate_buffer(std::get<indexes>(t)) + ...);
\n+
443 }
\n+
444
\n+
446 template<typename Tuple, std::size_t... indexes>
\n+
447 void append_tuple(Tuple const &t, std::index_sequence<indexes...>)
\n+
448 {
\n+
449 (append_to_buffer(std::get<indexes>(t)), ...);
\n+
450 }
\n+
451
\n+
453 template<typename... Elts> void fill_buffer(std::tuple<Elts...> const &t)
\n+
454 {
\n+
455 using indexes = std::make_index_sequence<sizeof...(Elts)>;
\n+
456
\n+
457 m_buffer.reserve(budget_tuple(t, indexes{}));
\n+
458 append_tuple(t, indexes{});
\n+
459 }
\n+
460
\n+
462 template<typename... Ts> void fill_buffer(const Ts &...fields)
\n+
463 {
\n+
464 (..., append_to_buffer(fields));
\n+
465 }
\n+
466
\n+
467 constexpr static std::string_view s_classname{"stream_to"};
\n+
468};
\n+
\n+
469
\n+
470
\n+
471template<typename Columns>
\n+
\n+\n+
473 transaction_base &tx, std::string_view table_name, Columns const &columns) :
\n+
474 stream_to{tx, table_name, std::begin(columns), std::end(columns)}
\n+
475{}
\n+
\n+
476
\n+
477
\n+
478template<typename Iter>
\n+
\n+\n+
480 transaction_base &tx, std::string_view table_name, Iter columns_begin,
\n+
481 Iter columns_end) :
\n+
482 stream_to{
\n+
483 tx,
\n+
484 tx.quote_name(
\n+
485 table_name,
\n+
486 separated_list(",", columns_begin, columns_end, [&tx](auto col) {
\n+
487 return tx.quote_name(*col);
\n+
488 }))}
\n+
489{}
\n+
\n+
490} // namespace pqxx
\n+
491#endif
\n+
The home of all libpqxx classes, functions, templates, etc.
Definition array.hxx:33
\n+
std::string separated_list(std::string_view sep, ITER begin, ITER end, ACCESS access)
Represent sequence of values as a string, joined by a given separator.
Definition separated_list.hxx:44
\n+
std::basic_ostream< CHAR > & operator<<(std::basic_ostream< CHAR > &s, field const &value)
Write a result field to any type of stream.
Definition field.hxx:509
\n+
std::initializer_list< std::string_view > table_path
Representation of a PostgreSQL table path.
Definition connection.hxx:188
\n+
Reference to one row in a result.
Definition row.hxx:47
\n+
Stream data from the database.
Definition stream_from.hxx:79
\n+
Efficiently write data directly to a database table.
Definition stream_to.hxx:81
\n+
static stream_to raw_table(transaction_base &tx, std::string_view path, std::string_view columns="")
Stream data to a pre-quoted table and columns.
Definition stream_to.hxx:104
\n+
constexpr bool operator!() const noexcept
Has this stream been through its concluding complete()?
Definition stream_to.hxx:211
\n+
static stream_to table(transaction_base &tx, table_path path, std::initializer_list< std::string_view > columns={})
Create a stream_to writing to a named table and columns.
Definition stream_to.hxx:120
\n+
void write_values(Ts const &...fields)
Insert values as a row.
Definition stream_to.hxx:265
\n+
stream_to(transaction_base &tx, std::string_view table_name)
Create a stream, without specifying columns.
Definition stream_to.hxx:172
\n+
stream_to(stream_to &&other)
Definition stream_to.hxx:192
\n+
stream_to & operator<<(Row const &row)
Insert a row of data.
Definition stream_to.hxx:235
\n+
void write_row(Row const &row)
Insert a row of data, given in the form of a std::tuple or container.
Definition stream_to.hxx:255
\n+
Interface definition (and common code) for "transaction" classes.
Definition transaction_base.hxx:88
\n+
constexpr connection & conn() const noexcept
The connection in which this transaction lives.
Definition transaction_base.hxx:780
\n+
std::string quote_name(std::string_view identifier) const
Escape an SQL identifier for use in a query.
Definition transaction_base.hxx:231
\n+
Base class for things that monopolise a transaction's attention.
Definition transaction_focus.hxx:29
\n
\n
\n \n
\n \n
\n \n \n", "details": [{"source1": "html2text {}", "source2": "html2text {}", "unified_diff": "@@ -1,21 +1,409 @@\n \n \n \n \n \n libpqxx\u00a07.8.1\n \n-config-internal-autotools.h\n- 1/* Automatically generated from config.h: internal/autotools config. */\n- 2\n- 3#define PACKAGE \"libpqxx\"\n- 4#define PACKAGE_BUGREPORT \"Jeroen T. Vermeulen\"\n- 5#define PACKAGE_NAME \"libpqxx\"\n- 6#define PACKAGE_STRING \"libpqxx 7.8.1\"\n- 7#define PACKAGE_TARNAME \"libpqxx\"\n- 8#define PACKAGE_VERSION \"7.8.1\"\n- 9#define VERSION \"7.8.1\"\n+stream_to.hxx\n+ 1/* Definition of the pqxx::stream_to class.\n+ 2 *\n+ 3 * pqxx::stream_to enables optimized batch updates to a database table.\n+ 4 *\n+ 5 * DO NOT INCLUDE THIS FILE DIRECTLY; include pqxx/stream_to.hxx instead.\n+ 6 *\n+ 7 * Copyright (c) 2000-2023, Jeroen T. Vermeulen.\n+ 8 *\n+ 9 * See COPYING for copyright license. If you did not receive a file called\n+ 10 * COPYING with this source code, please notify the distributor of this\n+ 11 * mistake, or contact the author.\n+ 12 */\n+ 13#ifndef PQXX_H_STREAM_TO\n+ 14#define PQXX_H_STREAM_TO\n+ 15\n+ 16#if !defined(PQXX_HEADER_PRE)\n+ 17# error \"Include libpqxx headers as , not .\"\n+ 18#endif\n+ 19\n+ 20#include \"pqxx/separated_list.hxx\"\n+ 21#include \"pqxx/transaction_base.hxx\"\n+ 22\n+ 23\n+ 24namespace pqxx\n+ 25{\n+ 27\n+80class PQXX_LIBEXPORT stream_to : transaction_focus\n+ 81{\n+ 82public:\n+ 84\n+104 static stream_to raw_table(\n+ 105 transaction_base &tx, std::string_view path, std::string_view columns =\n+\"\")\n+ 106 {\n+ 107 return {tx, path, columns};\n+ 108 }\n+ 109\n+ 111\n+120 static stream_to table(\n+ 121 transaction_base &tx, table_path path,\n+ 122 std::initializer_list columns = {})\n+ 123 {\n+ 124 auto const &conn{tx.conn()};\n+ 125 return raw_table(tx, conn.quote_table(path), conn.quote_columns(columns));\n+ 126 }\n+ 127\n+ 128#if defined(PQXX_HAVE_CONCEPTS)\n+ 130\n+ 137 template\n+ 138 static stream_to\n+ 139 table(transaction_base &tx, table_path path, COLUMNS const &columns)\n+ 140 {\n+ 141 auto const &conn{tx.conn()};\n+ 142 return stream_to::raw_table(\n+ 143 tx, conn.quote_table(path), tx.conn().quote_columns(columns));\n+ 144 }\n+ 145\n+ 147\n+ 154 template\n+ 155 static stream_to\n+ 156 table(transaction_base &tx, std::string_view path, COLUMNS const &columns)\n+ 157 {\n+ 158 return stream_to::raw_table(tx, path, tx.conn().quote_columns(columns));\n+ 159 }\n+ 160#endif // PQXX_HAVE_CONCEPTS\n+ 161\n+ 163\n+172 [[deprecated(\"Use table() or raw_table() factory.\")]] stream_to(\n+ 173 transaction_base &tx, std::string_view table_name) :\n+ 174 stream_to{tx, table_name, \"\"sv}\n+ 175 {}\n+ 176\n+ 178\n+ 180 template\n+ 181 [[deprecated(\"Use table() or raw_table() factory.\")]] stream_to(\n+ 182 transaction_base &, std::string_view table_name, Columns const &columns);\n+ 183\n+ 185\n+ 187 template\n+ 188 [[deprecated(\"Use table() or raw_table() factory.\")]] stream_to(\n+ 189 transaction_base &, std::string_view table_name, Iter columns_begin,\n+ 190 Iter columns_end);\n+ 191\n+192 explicit stream_to(stream_to &&other) :\n+ 193 // (This first step only moves the transaction_focus base-class\n+ 194 // object.)\n+ 195 transaction_focus{std::move(other)},\n+ 196 m_finished{other.m_finished},\n+ 197 m_buffer{std::move(other.m_buffer)},\n+ 198 m_field_buf{std::move(other.m_field_buf)},\n+ 199 m_finder{other.m_finder}\n+ 200 {\n+ 201 other.m_finished = true;\n+ 202 }\n+ 203 ~stream_to() noexcept;\n+ 204\n+206 [[nodiscard]] constexpr operator bool() const noexcept\n+ 207 {\n+ 208 return not m_finished;\n+ 209 }\n+211 [[nodiscard]] constexpr bool operator!() const noexcept\n+ 212 {\n+ 213 return m_finished;\n+ 214 }\n+ 215\n+ 217\n+ 223 void complete();\n+ 224\n+ 226\n+235 template stream_to &operator<<(Row const &row)\n+ 236 {\n+ 237 write_row(row);\n+ 238 return *this;\n+ 239 }\n+ 240\n+ 242\n+ 246 stream_to &operator<<(stream_from &);\n+ 247\n+ 249\n+255 template void write_row(Row const &row)\n+ 256 {\n+ 257 fill_buffer(row);\n+ 258 write_buffer();\n+ 259 }\n+ 260\n+ 262\n+265 template void write_values(Ts const &...fields)\n+ 266 {\n+ 267 fill_buffer(fields...);\n+ 268 write_buffer();\n+ 269 }\n+ 270\n+ 271private:\n+ 273 stream_to(\n+ 274 transaction_base &tx, std::string_view path, std::string_view columns);\n+ 275\n+ 276 bool m_finished = false;\n+ 277\n+ 279 std::string m_buffer;\n+ 280\n+ 282 std::string m_field_buf;\n+ 283\n+ 285 internal::char_finder_func *m_finder;\n+ 286\n+ 288 void write_raw_line(std::string_view);\n+ 289\n+ 291\n+ 293 void write_buffer();\n+ 294\n+ 296 static constexpr std::string_view null_field{\"\\\\N\\t\"};\n+ 297\n+ 299 template\n+ 300 static std::enable_if_t::always_null, std::size_t>\n+ 301 estimate_buffer(T const &)\n+ 302 {\n+ 303 return std::size(null_field);\n+ 304 }\n+ 305\n+ 307\n+ 310 template\n+ 311 static std::enable_if_t::always_null, std::size_t>\n+ 312 estimate_buffer(T const &field)\n+ 313 {\n+ 314 return is_null(field) ? std::size(null_field) : size_buffer(field);\n+ 315 }\n+ 316\n+ 318 void escape_field_to_buffer(std::string_view data);\n+ 319\n+ 321\n+ 327 template\n+ 328 std::enable_if_t::always_null>\n+ 329 append_to_buffer(Field const &f)\n+ 330 {\n+ 331 // We append each field, terminated by a tab. That will leave us with\n+ 332 // one tab too many, assuming we write any fields at all; we remove that\n+ 333 // at the end.\n+ 334 if (is_null(f))\n+ 335 {\n+ 336 // Easy. Append null and tab in one go.\n+ 337 m_buffer.append(null_field);\n+ 338 }\n+ 339 else\n+ 340 {\n+ 341 // Convert f into m_buffer.\n+ 342\n+ 343 using traits = string_traits;\n+ 344 auto const budget{estimate_buffer(f)};\n+ 345 auto const offset{std::size(m_buffer)};\n+ 346\n+ 347 if constexpr (std::is_arithmetic_v)\n+ 348 {\n+ 349 // Specially optimised for \"safe\" types, which never need any\n+ 350 // escaping. Convert straight into m_buffer.\n+ 351\n+ 352 // The budget we get from size_buffer() includes room for the trailing\n+ 353 // zero, which we must remove. But we're also inserting tabs between\n+ 354 // fields, so we re-purpose the extra byte for that.\n+ 355 auto const total{offset + budget};\n+ 356 m_buffer.resize(total);\n+ 357 auto const data{m_buffer.data()};\n+ 358 char *const end{traits::into_buf(data + offset, data + total, f)};\n+ 359 *(end - 1) = '\\t';\n+ 360 // Shrink to fit. Keep the tab though.\n+ 361 m_buffer.resize(static_cast(end - data));\n+ 362 }\n+ 363 else if constexpr (\n+ 364 std::is_same_v or\n+ 365 std::is_same_v or\n+ 366 std::is_same_v)\n+ 367 {\n+ 368 // This string may need escaping.\n+ 369 m_field_buf.resize(budget);\n+ 370 escape_field_to_buffer(f);\n+ 371 }\n+ 372 else if constexpr (\n+ 373 std::is_same_v> or\n+ 374 std::is_same_v> or\n+ 375 std::is_same_v>)\n+ 376 {\n+ 377 // Optional string. It's not null (we checked for that above), so...\n+ 378 // Treat like a string.\n+ 379 m_field_buf.resize(budget);\n+ 380 escape_field_to_buffer(f.value());\n+ 381 }\n+ 382 // TODO: Support deleter template argument on unique_ptr.\n+ 383 else if constexpr (\n+ 384 std::is_same_v> or\n+ 385 std::is_same_v> or\n+ 386 std::is_same_v> or\n+ 387 std::is_same_v> or\n+ 388 std::is_same_v> or\n+ 389 std::is_same_v>)\n+ 390 {\n+ 391 // TODO: Can we generalise this elegantly without Concepts?\n+ 392 // Effectively also an optional string. It's not null (we checked\n+ 393 // for that above).\n+ 394 m_field_buf.resize(budget);\n+ 395 escape_field_to_buffer(*f);\n+ 396 }\n+ 397 else\n+ 398 {\n+ 399 // This field needs to be converted to a string, and after that,\n+ 400 // escaped as well.\n+ 401 m_field_buf.resize(budget);\n+ 402 auto const data{m_field_buf.data()};\n+ 403 escape_field_to_buffer(\n+ 404 traits::to_buf(data, data + std::size(m_field_buf), f));\n+ 405 }\n+ 406 }\n+ 407 }\n+ 408\n+ 410\n+ 416 template\n+ 417 std::enable_if_t::always_null>\n+ 418 append_to_buffer(Field const &)\n+ 419 {\n+ 420 m_buffer.append(null_field);\n+ 421 }\n+ 422\n+ 424 template\n+ 425 std::enable_if_t>\n+ 426 fill_buffer(Container const &c)\n+ 427 {\n+ 428 // To avoid unnecessary allocations and deallocations, we run through c\n+ 429 // twice: once to determine how much buffer space we may need, and once to\n+ 430 // actually write it into the buffer.\n+ 431 std::size_t budget{0};\n+ 432 for (auto const &f : c) budget += estimate_buffer(f);\n+ 433 m_buffer.reserve(budget);\n+ 434 for (auto const &f : c) append_to_buffer(f);\n+ 435 }\n+ 436\n+ 438 template\n+ 439 static std::size_t\n+ 440 budget_tuple(Tuple const &t, std::index_sequence)\n+ 441 {\n+ 442 return (estimate_buffer(std::get(t)) + ...);\n+ 443 }\n+ 444\n+ 446 template\n+ 447 void append_tuple(Tuple const &t, std::index_sequence)\n+ 448 {\n+ 449 (append_to_buffer(std::get(t)), ...);\n+ 450 }\n+ 451\n+ 453 template void fill_buffer(std::tuple const &t)\n+ 454 {\n+ 455 using indexes = std::make_index_sequence;\n+ 456\n+ 457 m_buffer.reserve(budget_tuple(t, indexes{}));\n+ 458 append_tuple(t, indexes{});\n+ 459 }\n+ 460\n+ 462 template void fill_buffer(const Ts &...fields)\n+ 463 {\n+ 464 (..., append_to_buffer(fields));\n+ 465 }\n+ 466\n+ 467 constexpr static std::string_view s_classname{\"stream_to\"};\n+ 468};\n+ 469\n+ 470\n+ 471template\n+472inline stream_to::stream_to(\n+ 473 transaction_base &tx, std::string_view table_name, Columns const &columns)\n+:\n+ 474 stream_to{tx, table_name, std::begin(columns), std::end(columns)}\n+ 475{}\n+ 476\n+ 477\n+ 478template\n+479inline stream_to::stream_to(\n+ 480 transaction_base &tx, std::string_view table_name, Iter columns_begin,\n+ 481 Iter columns_end) :\n+ 482 stream_to{\n+ 483 tx,\n+ 484 tx.quote_name(\n+ 485 table_name,\n+ 486 separated_list(\",\", columns_begin, columns_end, [&tx](auto col) {\n+ 487 return tx.quote_name(*col);\n+ 488 }))}\n+ 489{}\n+ 490} // namespace pqxx\n+ 491#endif\n+pqxx\n+The home of all libpqxx classes, functions, templates, etc.\n+Definition array.hxx:33\n+pqxx::separated_list\n+std::string separated_list(std::string_view sep, ITER begin, ITER end, ACCESS\n+access)\n+Represent sequence of values as a string, joined by a given separator.\n+Definition separated_list.hxx:44\n+pqxx::operator<<\n+std::basic_ostream< CHAR > & operator<<(std::basic_ostream< CHAR > &s, field\n+const &value)\n+Write a result field to any type of stream.\n+Definition field.hxx:509\n+pqxx::table_path\n+std::initializer_list< std::string_view > table_path\n+Representation of a PostgreSQL table path.\n+Definition connection.hxx:188\n+pqxx::row\n+Reference to one row in a result.\n+Definition row.hxx:47\n+pqxx::stream_from\n+Stream data from the database.\n+Definition stream_from.hxx:79\n+pqxx::stream_to\n+Efficiently write data directly to a database table.\n+Definition stream_to.hxx:81\n+pqxx::stream_to::raw_table\n+static stream_to raw_table(transaction_base &tx, std::string_view path, std::\n+string_view columns=\"\")\n+Stream data to a pre-quoted table and columns.\n+Definition stream_to.hxx:104\n+pqxx::stream_to::operator!\n+constexpr bool operator!() const noexcept\n+Has this stream been through its concluding complete()?\n+Definition stream_to.hxx:211\n+pqxx::stream_to::table\n+static stream_to table(transaction_base &tx, table_path path, std::\n+initializer_list< std::string_view > columns={})\n+Create a stream_to writing to a named table and columns.\n+Definition stream_to.hxx:120\n+pqxx::stream_to::write_values\n+void write_values(Ts const &...fields)\n+Insert values as a row.\n+Definition stream_to.hxx:265\n+pqxx::stream_to::stream_to\n+stream_to(transaction_base &tx, std::string_view table_name)\n+Create a stream, without specifying columns.\n+Definition stream_to.hxx:172\n+pqxx::stream_to::stream_to\n+stream_to(stream_to &&other)\n+Definition stream_to.hxx:192\n+pqxx::stream_to::operator<<\n+stream_to & operator<<(Row const &row)\n+Insert a row of data.\n+Definition stream_to.hxx:235\n+pqxx::stream_to::write_row\n+void write_row(Row const &row)\n+Insert a row of data, given in the form of a std::tuple or container.\n+Definition stream_to.hxx:255\n+pqxx::transaction_base\n+Interface definition (and common code) for \"transaction\" classes.\n+Definition transaction_base.hxx:88\n+pqxx::transaction_base::conn\n+constexpr connection & conn() const noexcept\n+The connection in which this transaction lives.\n+Definition transaction_base.hxx:780\n+pqxx::transaction_base::quote_name\n+std::string quote_name(std::string_view identifier) const\n+Escape an SQL identifier for use in a query.\n+Definition transaction_base.hxx:231\n+pqxx::transaction_focus\n+Base class for things that monopolise a transaction's attention.\n+Definition transaction_focus.hxx:29\n * include\n * pqxx\n- * config-internal-autotools.h\n+ * stream_to.hxx\n * Generated by [doxygen] 1.9.8\n"}]}, {"source1": "./usr/share/doc/libpqxx-doc/html/a00110_source.html", "source2": "./usr/share/doc/libpqxx-doc/html/a00110_source.html", "unified_diff": "@@ -1,15 +1,15 @@\n \n \n \n \n \n \n \n-libpqxx: zview.hxx Source File\n+libpqxx: time.hxx Source File\n \n \n \n \n \n \n \n@@ -60,180 +60,80 @@\n \n
\n
\n-
zview.hxx
\n+
time.hxx
\n
\n
\n-
1/* Zero-terminated string view.
\n-
2 *
\n-
3 * DO NOT INCLUDE THIS FILE DIRECTLY; include pqxx/zview instead.
\n-
4 *
\n-
5 * Copyright (c) 2000-2023, Jeroen T. Vermeulen.
\n-
6 *
\n-
7 * See COPYING for copyright license. If you did not receive a file called
\n-
8 * COPYING with this source code, please notify the distributor of this
\n-
9 * mistake, or contact the author.
\n-
10 */
\n-
11#ifndef PQXX_H_ZVIEW
\n-
12#define PQXX_H_ZVIEW
\n-
13
\n-
14#include <string>
\n-
15#include <string_view>
\n-
16#include <type_traits>
\n+
1
\n+
5#ifndef PQXX_H_TIME
\n+
6#define PQXX_H_TIME
\n+
7
\n+
8#if !defined(PQXX_HEADER_PRE)
\n+
9# error "Include libpqxx headers as <pqxx/header>, not <pqxx/header.hxx>."
\n+
10#endif
\n+
11
\n+
12#include <chrono>
\n+
13#include <cstdlib>
\n+
14
\n+
15#include "pqxx/internal/concat.hxx"
\n+
16#include "pqxx/strconv.hxx"
\n
17
\n-
18#include "pqxx/types.hxx"
\n-
19
\n+
18
\n+
19#if defined(PQXX_HAVE_YEAR_MONTH_DAY)
\n
20
\n
21namespace pqxx
\n
22{
\n+
23using namespace std::literals;
\n
24
\n-
\n-
37class zview : public std::string_view
\n-
38{
\n-
39public:
\n-
40 constexpr zview() noexcept = default;
\n-
41
\n-
\n-
43 constexpr zview(char const text[], std::ptrdiff_t len) noexcept(
\n-
44 noexcept(std::string_view{text, static_cast<std::size_t>(len)})) :
\n-
45 std::string_view{text, static_cast<std::size_t>(len)}
\n-
46 {}
\n-
\n-
47
\n-
\n-
49 constexpr zview(char text[], std::ptrdiff_t len) noexcept(
\n-
50 noexcept(std::string_view{text, static_cast<std::size_t>(len)})) :
\n-
51 std::string_view{text, static_cast<std::size_t>(len)}
\n-
52 {}
\n-
\n-
53
\n-
\n-
55 explicit constexpr zview(std::string_view other) noexcept :
\n-
56 std::string_view{other}
\n-
57 {}
\n-
\n-
58
\n-
60
\n-
62 template<typename... Args>
\n-
\n-
63 explicit constexpr zview(Args &&...args) :
\n-
64 std::string_view(std::forward<Args>(args)...)
\n-
65 {}
\n-
\n-
66
\n-
67 // C++20: constexpr.
\n-
\n-
69 zview(std::string const &str) noexcept :
\n-
70 std::string_view{str.c_str(), str.size()}
\n-
71 {}
\n-
\n-
72
\n-
74
\n-
\n-
78 constexpr zview(char const str[]) noexcept(noexcept(std::string_view{str})) :
\n-
79 std::string_view{str}
\n-
80 {}
\n-
\n+
25template<>
\n+
26struct nullness<std::chrono::year_month_day>
\n+
27 : no_null<std::chrono::year_month_day>
\n+
28{};
\n+
29
\n+
30
\n+
32
\n+
60template<> struct PQXX_LIBEXPORT string_traits<std::chrono::year_month_day>
\n+
61{
\n+
62 [[nodiscard]] static zview
\n+
63 to_buf(char *begin, char *end, std::chrono::year_month_day const &value)
\n+
64 {
\n+
65 return generic_to_buf(begin, end, value);
\n+
66 }
\n+
67
\n+
68 static char *
\n+
69 into_buf(char *begin, char *end, std::chrono::year_month_day const &value);
\n+
70
\n+
71 [[nodiscard]] static std::chrono::year_month_day
\n+
72 from_string(std::string_view text);
\n+
73
\n+
74 [[nodiscard]] static std::size_t
\n+
75 size_buffer(std::chrono::year_month_day const &) noexcept
\n+
76 {
\n+
77 static_assert(int{(std::chrono::year::min)()} >= -99999);
\n+
78 static_assert(int{(std::chrono::year::max)()} <= 99999);
\n+
79 return 5 + 1 + 2 + 1 + 2 + std::size(s_bc) + 1;
\n+
80 }
\n
81
\n-
83
\n-
91 template<size_t size>
\n-
\n-
92 constexpr zview(char const (&literal)[size]) : zview(literal, size - 1)
\n-
93 {}
\n-
\n-
94
\n-
\n-
96 [[nodiscard]] constexpr char const *c_str() const &noexcept
\n-
97 {
\n-
98 return data();
\n-
99 }
\n-
\n-
100};
\n-
\n-
101
\n-
102
\n-
104
\n-
\n-
111constexpr zview operator"" _zv(char const str[], std::size_t len) noexcept
\n-
112{
\n-
113 return zview{str, len};
\n-
114}
\n-
\n-
115} // namespace pqxx
\n-
116
\n-
117
\n-
118#if defined(PQXX_HAVE_CONCEPTS)
\n-
120template<> inline constexpr bool std::ranges::enable_view<pqxx::zview>{true};
\n-
121
\n-
122
\n-
124template<>
\n-
125inline constexpr bool std::ranges::enable_borrowed_range<pqxx::zview>{true};
\n-
126
\n-
127namespace pqxx::internal
\n-
128{
\n-
130
\n-
134template<typename T>
\n-
135concept ZString = std::is_convertible_v<strip_t<T>, char const *> or
\n-
136 std::is_convertible_v<strip_t<T>, zview> or
\n-
137 std::is_convertible_v<T, std::string const &>;
\n-
138} // namespace pqxx::internal
\n-
139#endif // PQXX_HAVE_CONCEPTS
\n-
140
\n-
141
\n-
142namespace pqxx::internal
\n-
143{
\n-
\n-
145inline constexpr char const *as_c_string(char const str[]) noexcept
\n-
146{
\n-
147 return str;
\n-
148}
\n-
\n-
150template<std::size_t N>
\n-
\n-
151inline constexpr char const *as_c_string(char (&str)[N]) noexcept
\n-
152{
\n-
153 return str;
\n-
154}
\n-
\n-
\n-
156inline constexpr char const *as_c_string(pqxx::zview str) noexcept
\n-
157{
\n-
158 return str.c_str();
\n-
159}
\n-
\n-
160// C++20: Make this constexpr.
\n-
\n-
162inline char const *as_c_string(std::string const &str) noexcept
\n-
163{
\n-
164 return str.c_str();
\n-
165}
\n-
\n-
166} // namespace pqxx::internal
\n-
167#endif
\n+
82private:
\n+
84 static constexpr std::string_view s_bc{" BC"sv};
\n+
85};
\n+
86} // namespace pqxx
\n+
87#endif // PQXX_HAVE_YEAR_MONTH_DAY
\n+
88#endif
\n
The home of all libpqxx classes, functions, templates, etc.
Definition array.hxx:33
\n+
T from_string(field const &value)
Convert a field's value to type T.
Definition field.hxx:520
\n \n-
Internal items for libpqxx' own use. Do not use these yourself.
Definition composite.hxx:84
\n-
constexpr char const * as_c_string(char const str[]) noexcept
Get a raw C string pointer.
Definition zview.hxx:145
\n-
Marker-type wrapper: zero-terminated std::string_view.
Definition zview.hxx:38
\n-
constexpr zview(char const (&literal)[size])
Construct a zview from a string literal.
Definition zview.hxx:92
\n-
constexpr char const * c_str() const &noexcept
Either a null pointer, or a zero-terminated text buffer.
Definition zview.hxx:96
\n-
constexpr zview(Args &&...args)
Construct from any initialiser you might use for std::string_view.
Definition zview.hxx:63
\n-
constexpr zview(char text[], std::ptrdiff_t len) noexcept(noexcept(std::string_view{text, static_cast< std::size_t >(len)}))
Convenience overload: construct using pointer and signed length.
Definition zview.hxx:49
\n-
constexpr zview() noexcept=default
\n-
constexpr zview(char const str[]) noexcept(noexcept(std::string_view{str}))
Construct a zview from a C-style string.
Definition zview.hxx:78
\n-
constexpr zview(std::string_view other) noexcept
Explicitly promote a string_view to a zview.
Definition zview.hxx:55
\n-
zview(std::string const &str) noexcept
Definition zview.hxx:69
\n
\n
\n \n
\n \n
\n \n \n", "details": [{"source1": "html2text {}", "source2": "html2text {}", "unified_diff": "@@ -1,178 +1,77 @@\n \n \n \n \n \n libpqxx\u00a07.8.1\n \n-zview.hxx\n- 1/* Zero-terminated string view.\n- 2 *\n- 3 * DO NOT INCLUDE THIS FILE DIRECTLY; include pqxx/zview instead.\n- 4 *\n- 5 * Copyright (c) 2000-2023, Jeroen T. Vermeulen.\n- 6 *\n- 7 * See COPYING for copyright license. If you did not receive a file called\n- 8 * COPYING with this source code, please notify the distributor of this\n- 9 * mistake, or contact the author.\n- 10 */\n- 11#ifndef PQXX_H_ZVIEW\n- 12#define PQXX_H_ZVIEW\n- 13\n- 14#include \n- 15#include \n- 16#include \n+time.hxx\n+ 1\n+ 5#ifndef PQXX_H_TIME\n+ 6#define PQXX_H_TIME\n+ 7\n+ 8#if !defined(PQXX_HEADER_PRE)\n+ 9# error \"Include libpqxx headers as , not .\"\n+ 10#endif\n+ 11\n+ 12#include \n+ 13#include \n+ 14\n+ 15#include \"pqxx/internal/concat.hxx\"\n+ 16#include \"pqxx/strconv.hxx\"\n 17\n- 18#include \"pqxx/types.hxx\"\n- 19\n+ 18\n+ 19#if defined(PQXX_HAVE_YEAR_MONTH_DAY)\n 20\n 21namespace pqxx\n 22{\n+ 23using namespace std::literals;\n 24\n-37class zview : public std::string_view\n- 38{\n- 39public:\n-40 constexpr zview() noexcept = default;\n- 41\n-43 constexpr zview(char const text[], std::ptrdiff_t len) noexcept(\n- 44 noexcept(std::string_view{text, static_cast(len)})) :\n- 45 std::string_view{text, static_cast(len)}\n- 46 {}\n- 47\n-49 constexpr zview(char text[], std::ptrdiff_t len) noexcept(\n- 50 noexcept(std::string_view{text, static_cast(len)})) :\n- 51 std::string_view{text, static_cast(len)}\n- 52 {}\n- 53\n-55 explicit constexpr zview(std::string_view other) noexcept :\n- 56 std::string_view{other}\n- 57 {}\n- 58\n- 60\n- 62 template\n-63 explicit constexpr zview(Args &&...args) :\n- 64 std::string_view(std::forward(args)...)\n- 65 {}\n- 66\n- 67 // C++20: constexpr.\n-69 zview(std::string const &str) noexcept :\n- 70 std::string_view{str.c_str(), str.size()}\n- 71 {}\n- 72\n- 74\n-78 constexpr zview(char const str[]) noexcept(noexcept(std::string_view{str}))\n-:\n- 79 std::string_view{str}\n- 80 {}\n+ 25template<>\n+ 26struct nullness\n+ 27 : no_null\n+ 28{};\n+ 29\n+ 30\n+ 32\n+ 60template<> struct PQXX_LIBEXPORT string_traits\n+ 61{\n+ 62 [[nodiscard]] static zview\n+ 63 to_buf(char *begin, char *end, std::chrono::year_month_day const &value)\n+ 64 {\n+ 65 return generic_to_buf(begin, end, value);\n+ 66 }\n+ 67\n+ 68 static char *\n+ 69 into_buf(char *begin, char *end, std::chrono::year_month_day const &value);\n+ 70\n+ 71 [[nodiscard]] static std::chrono::year_month_day\n+ 72 from_string(std::string_view text);\n+ 73\n+ 74 [[nodiscard]] static std::size_t\n+ 75 size_buffer(std::chrono::year_month_day const &) noexcept\n+ 76 {\n+ 77 static_assert(int{(std::chrono::year::min)()} >= -99999);\n+ 78 static_assert(int{(std::chrono::year::max)()} <= 99999);\n+ 79 return 5 + 1 + 2 + 1 + 2 + std::size(s_bc) + 1;\n+ 80 }\n 81\n- 83\n- 91 template\n-92 constexpr zview(char const (&literal)[size]) : zview(literal, size - 1)\n- 93 {}\n- 94\n-96 [[nodiscard]] constexpr char const *c_str() const &noexcept\n- 97 {\n- 98 return data();\n- 99 }\n- 100};\n- 101\n- 102\n- 104\n-111constexpr zview operator\"\" _zv(char const str[], std::size_t len) noexcept\n- 112{\n- 113 return zview{str, len};\n- 114}\n- 115} // namespace pqxx\n- 116\n- 117\n- 118#if defined(PQXX_HAVE_CONCEPTS)\n- 120template<> inline constexpr bool std::ranges::enable_view\n-{true};\n- 121\n- 122\n- 124template<>\n- 125inline constexpr bool std::ranges::enable_borrowed_range\n-{true};\n- 126\n- 127namespace pqxx::internal\n- 128{\n- 130\n- 134template\n- 135concept ZString = std::is_convertible_v, char const *> or\n- 136 std::is_convertible_v, zview> or\n- 137 std::is_convertible_v;\n- 138} // namespace pqxx::internal\n- 139#endif // PQXX_HAVE_CONCEPTS\n- 140\n- 141\n- 142namespace pqxx::internal\n- 143{\n-145inline constexpr char const *as_c_string(char const str[]) noexcept\n- 146{\n- 147 return str;\n- 148}\n- 150template\n-151inline constexpr char const *as_c_string(char (&str)[N]) noexcept\n- 152{\n- 153 return str;\n- 154}\n-156inline constexpr char const *as_c_string(pqxx::zview str) noexcept\n- 157{\n- 158 return str.c_str();\n- 159}\n- 160// C++20: Make this constexpr.\n-162inline char const *as_c_string(std::string const &str) noexcept\n- 163{\n- 164 return str.c_str();\n- 165}\n- 166} // namespace pqxx::internal\n- 167#endif\n+ 82private:\n+ 84 static constexpr std::string_view s_bc{\" BC\"sv};\n+ 85};\n+ 86} // namespace pqxx\n+ 87#endif // PQXX_HAVE_YEAR_MONTH_DAY\n+ 88#endif\n pqxx\n The home of all libpqxx classes, functions, templates, etc.\n Definition array.hxx:33\n+pqxx::from_string\n+T from_string(field const &value)\n+Convert a field's value to type T.\n+Definition field.hxx:520\n pqxx::format::text\n @ text\n-pqxx::internal\n-Internal items for libpqxx' own use. Do not use these yourself.\n-Definition composite.hxx:84\n-pqxx::internal::as_c_string\n-constexpr char const * as_c_string(char const str[]) noexcept\n-Get a raw C string pointer.\n-Definition zview.hxx:145\n-pqxx::zview\n-Marker-type wrapper: zero-terminated std::string_view.\n-Definition zview.hxx:38\n-pqxx::zview::zview\n-constexpr zview(char const (&literal)[size])\n-Construct a zview from a string literal.\n-Definition zview.hxx:92\n-pqxx::zview::c_str\n-constexpr char const * c_str() const &noexcept\n-Either a null pointer, or a zero-terminated text buffer.\n-Definition zview.hxx:96\n-pqxx::zview::zview\n-constexpr zview(Args &&...args)\n-Construct from any initialiser you might use for std::string_view.\n-Definition zview.hxx:63\n-pqxx::zview::zview\n-constexpr zview(char text[], std::ptrdiff_t len) noexcept(noexcept(std::\n-string_view{text, static_cast< std::size_t >(len)}))\n-Convenience overload: construct using pointer and signed length.\n-Definition zview.hxx:49\n-pqxx::zview::zview\n-constexpr zview() noexcept=default\n-pqxx::zview::zview\n-constexpr zview(char const str[]) noexcept(noexcept(std::string_view{str}))\n-Construct a zview from a C-style string.\n-Definition zview.hxx:78\n-pqxx::zview::zview\n-constexpr zview(std::string_view other) noexcept\n-Explicitly promote a string_view to a zview.\n-Definition zview.hxx:55\n-pqxx::zview::zview\n-zview(std::string const &str) noexcept\n-Definition zview.hxx:69\n * include\n * pqxx\n- * zview.hxx\n+ * time.hxx\n * Generated by [doxygen] 1.9.8\n"}]}, {"source1": "./usr/share/doc/libpqxx-doc/html/a00113_source.html", "source2": "./usr/share/doc/libpqxx-doc/html/a00113_source.html", "unified_diff": "@@ -1,15 +1,15 @@\n \n \n \n \n \n \n \n-libpqxx: subtransaction.hxx Source File\n+libpqxx: transaction_focus.hxx Source File\n \n \n \n \n \n \n \n@@ -60,71 +60,154 @@\n \n
\n
\n-
subtransaction.hxx
\n+
transaction_focus.hxx
\n
\n
\n-
1/* Definition of the pqxx::subtransaction class.
\n-
2 *
\n-
3 * pqxx::subtransaction is a nested transaction, i.e. one within a transaction.
\n-
4 *
\n-
5 * DO NOT INCLUDE THIS FILE DIRECTLY; include pqxx/subtransaction instead.
\n-
6 *
\n-
7 * Copyright (c) 2000-2023, Jeroen T. Vermeulen.
\n-
8 *
\n-
9 * See COPYING for copyright license. If you did not receive a file called
\n-
10 * COPYING with this source code, please notify the distributor of this
\n-
11 * mistake, or contact the author.
\n-
12 */
\n-
13#ifndef PQXX_H_SUBTRANSACTION
\n-
14#define PQXX_H_SUBTRANSACTION
\n+
1
\n+
9#ifndef PQXX_H_TRANSACTION_FOCUS
\n+
10#define PQXX_H_TRANSACTION_FOCUS
\n+
11
\n+
12#if !defined(PQXX_HEADER_PRE)
\n+
13# error "Include libpqxx headers as <pqxx/header>, not <pqxx/header.hxx>."
\n+
14#endif
\n
15
\n-
16#if !defined(PQXX_HEADER_PRE)
\n-
17# error "Include libpqxx headers as <pqxx/header>, not <pqxx/header.hxx>."
\n-
18#endif
\n-
19
\n-
20#include "pqxx/dbtransaction.hxx"
\n+
16#include "pqxx/util.hxx"
\n+
17
\n+
18namespace pqxx
\n+
19{
\n
21
\n-
22namespace pqxx
\n-
23{
\n-
28
\n-
\n-
76class PQXX_LIBEXPORT subtransaction : public transaction_focus,
\n-
77 public dbtransaction
\n-
78{
\n-
79public:
\n-
81 explicit subtransaction(dbtransaction &t, std::string_view tname = ""sv);
\n-
82
\n-
84 explicit subtransaction(subtransaction &t, std::string_view name = ""sv);
\n-
85
\n-
86 virtual ~subtransaction() noexcept override;
\n-
87
\n-
88private:
\n-
89 std::string quoted_name() const
\n-
90 {
\n-
91 return quote_name(transaction_focus::name());
\n-
92 }
\n-
93 virtual void do_commit() override;
\n-
94};
\n+
\n+
28class PQXX_LIBEXPORT transaction_focus
\n+
29{
\n+
30public:
\n+
\n+\n+
32 transaction_base &t, std::string_view cname, std::string_view oname) :
\n+
33 m_trans{&t}, m_classname{cname}, m_name{oname}
\n+
34 {}
\n
\n-
95} // namespace pqxx
\n-
96#endif
\n+
35
\n+
\n+\n+
37 transaction_base &t, std::string_view cname, std::string &&oname) :
\n+
38 m_trans{&t}, m_classname{cname}, m_name{std::move(oname)}
\n+
39 {}
\n+
\n+
40
\n+
\n+
41 transaction_focus(transaction_base &t, std::string_view cname) :
\n+
42 m_trans{&t}, m_classname{cname}
\n+
43 {}
\n+
\n+
44
\n+\n+\n+\n+
48
\n+
\n+
50 [[nodiscard]] constexpr std::string_view classname() const noexcept
\n+
51 {
\n+
52 return m_classname;
\n+
53 }
\n+
\n+
54
\n+
56 [[nodiscard]] std::string_view name() const &noexcept { return m_name; }
\n+
57
\n+
\n+
58 [[nodiscard]] std::string description() const
\n+
59 {
\n+
60 return pqxx::internal::describe_object(m_classname, m_name);
\n+
61 }
\n+
\n+
62
\n+
\n+\n+
64 m_trans{other.m_trans},
\n+
65 m_registered{other.m_registered},
\n+
66 m_classname{other.m_classname},
\n+
67 // We can't move the name until later.
\n+
68 m_name{}
\n+
69 {
\n+
70 // This is a bit more complicated than you might expect. The transaction
\n+
71 // has a backpointer to the focus, and we need to transfer that to the new
\n+
72 // focus.
\n+
73 move_name_and_registration(other);
\n+
74 }
\n+
\n+
75
\n+
\n+\n+
77 {
\n+
78 if (&other != this)
\n+
79 {
\n+
80 if (m_registered)
\n+
81 unregister_me();
\n+
82 m_trans = other.m_trans;
\n+
83 m_classname = other.m_classname;
\n+
84 move_name_and_registration(other);
\n+
85 }
\n+
86 return *this;
\n+
87 }
\n+
\n+
88
\n+
89protected:
\n+
90 void register_me();
\n+
91 void unregister_me() noexcept;
\n+
92 void reg_pending_error(std::string const &) noexcept;
\n+
93 bool registered() const noexcept { return m_registered; }
\n+
94
\n+\n+
96
\n+
97private:
\n+
98 bool m_registered = false;
\n+
99 std::string_view m_classname;
\n+
100 std::string m_name;
\n+
101
\n+
103 void move_name_and_registration(transaction_focus &other)
\n+
104 {
\n+
105 bool const reg{other.m_registered};
\n+
106 // Unregister the original while it still owns its name.
\n+
107 if (reg)
\n+
108 other.unregister_me();
\n+
109 // Now! Quick! Steal that name.
\n+
110 m_name = std::move(other.m_name);
\n+
111 // Now that we own the name, register ourselves instead.
\n+
112 if (reg)
\n+
113 this->register_me();
\n+
114 }
\n+
115};
\n+
\n+
116} // namespace pqxx
\n+
117#endif
\n
The home of all libpqxx classes, functions, templates, etc.
Definition array.hxx:33
\n-
Abstract transaction base class: bracket transactions on the database.
Definition dbtransaction.hxx:54
\n-
"Transaction" nested within another transaction
Definition subtransaction.hxx:78
\n+
std::string describe_object(std::string_view class_name, std::string_view name)
Describe an object for humans, based on class name and optional name.
Definition util.cxx:51
\n+
Interface definition (and common code) for "transaction" classes.
Definition transaction_base.hxx:88
\n
Base class for things that monopolise a transaction's attention.
Definition transaction_focus.hxx:29
\n+
std::string description() const
Definition transaction_focus.hxx:58
\n+\n+
transaction_focus(transaction_base &t, std::string_view cname)
Definition transaction_focus.hxx:41
\n+
void unregister_me() noexcept
Definition transaction_base.cxx:527
\n
std::string_view name() const &noexcept
Name for this object, if the caller passed one; empty string otherwise.
Definition transaction_focus.hxx:56
\n+
constexpr std::string_view classname() const noexcept
Class name, for human consumption.
Definition transaction_focus.hxx:50
\n+
transaction_focus(transaction_base &t, std::string_view cname, std::string &&oname)
Definition transaction_focus.hxx:36
\n+
transaction_focus(transaction_focus const &)=delete
\n+
transaction_focus(transaction_focus &&other)
Definition transaction_focus.hxx:63
\n+
transaction_focus & operator=(transaction_focus &&other)
Definition transaction_focus.hxx:76
\n+
transaction_focus(transaction_base &t, std::string_view cname, std::string_view oname)
Definition transaction_focus.hxx:31
\n+
transaction_base * m_trans
Definition transaction_focus.hxx:95
\n+
transaction_focus & operator=(transaction_focus const &)=delete
\n
\n
\n \n
\n \n
\n \n \n", "details": [{"source1": "html2text {}", "source2": "html2text {}", "unified_diff": "@@ -1,72 +1,165 @@\n \n \n \n \n \n libpqxx\u00a07.8.1\n \n-subtransaction.hxx\n- 1/* Definition of the pqxx::subtransaction class.\n- 2 *\n- 3 * pqxx::subtransaction is a nested transaction, i.e. one within a\n-transaction.\n- 4 *\n- 5 * DO NOT INCLUDE THIS FILE DIRECTLY; include pqxx/subtransaction instead.\n- 6 *\n- 7 * Copyright (c) 2000-2023, Jeroen T. Vermeulen.\n- 8 *\n- 9 * See COPYING for copyright license. If you did not receive a file called\n- 10 * COPYING with this source code, please notify the distributor of this\n- 11 * mistake, or contact the author.\n- 12 */\n- 13#ifndef PQXX_H_SUBTRANSACTION\n- 14#define PQXX_H_SUBTRANSACTION\n+transaction_focus.hxx\n+ 1\n+ 9#ifndef PQXX_H_TRANSACTION_FOCUS\n+ 10#define PQXX_H_TRANSACTION_FOCUS\n+ 11\n+ 12#if !defined(PQXX_HEADER_PRE)\n+ 13# error \"Include libpqxx headers as , not .\"\n+ 14#endif\n 15\n- 16#if !defined(PQXX_HEADER_PRE)\n- 17# error \"Include libpqxx headers as , not .\"\n- 18#endif\n- 19\n- 20#include \"pqxx/dbtransaction.hxx\"\n+ 16#include \"pqxx/util.hxx\"\n+ 17\n+ 18namespace pqxx\n+ 19{\n 21\n- 22namespace pqxx\n- 23{\n- 28\n-76class PQXX_LIBEXPORT subtransaction : public transaction_focus,\n- 77 public dbtransaction\n- 78{\n- 79public:\n- 81 explicit subtransaction(dbtransaction &t, std::string_view tname = \"\"sv);\n- 82\n- 84 explicit subtransaction(subtransaction &t, std::string_view name = \"\"sv);\n- 85\n- 86 virtual ~subtransaction() noexcept override;\n- 87\n- 88private:\n- 89 std::string quoted_name() const\n- 90 {\n- 91 return quote_name(transaction_focus::name());\n- 92 }\n- 93 virtual void do_commit() override;\n- 94};\n- 95} // namespace pqxx\n- 96#endif\n+28class PQXX_LIBEXPORT transaction_focus\n+ 29{\n+ 30public:\n+31 transaction_focus(\n+ 32 transaction_base &t, std::string_view cname, std::string_view oname) :\n+ 33 m_trans{&t}, m_classname{cname}, m_name{oname}\n+ 34 {}\n+ 35\n+36 transaction_focus(\n+ 37 transaction_base &t, std::string_view cname, std::string &&oname) :\n+ 38 m_trans{&t}, m_classname{cname}, m_name{std::move(oname)}\n+ 39 {}\n+ 40\n+41 transaction_focus(transaction_base &t, std::string_view cname) :\n+ 42 m_trans{&t}, m_classname{cname}\n+ 43 {}\n+ 44\n+45 transaction_focus() = delete;\n+46 transaction_focus(transaction_focus const &) = delete;\n+47 transaction_focus &operator=(transaction_focus const &) = delete;\n+ 48\n+50 [[nodiscard]] constexpr std::string_view classname() const noexcept\n+ 51 {\n+ 52 return m_classname;\n+ 53 }\n+ 54\n+56 [[nodiscard]] std::string_view name() const &noexcept { return m_name; }\n+ 57\n+58 [[nodiscard]] std::string description() const\n+ 59 {\n+ 60 return pqxx::internal::describe_object(m_classname, m_name);\n+ 61 }\n+ 62\n+63 transaction_focus(transaction_focus &&other) :\n+ 64 m_trans{other.m_trans},\n+ 65 m_registered{other.m_registered},\n+ 66 m_classname{other.m_classname},\n+ 67 // We can't move the name until later.\n+ 68 m_name{}\n+ 69 {\n+ 70 // This is a bit more complicated than you might expect. The transaction\n+ 71 // has a backpointer to the focus, and we need to transfer that to the new\n+ 72 // focus.\n+ 73 move_name_and_registration(other);\n+ 74 }\n+ 75\n+76 transaction_focus &operator=(transaction_focus &&other)\n+ 77 {\n+ 78 if (&other != this)\n+ 79 {\n+ 80 if (m_registered)\n+ 81 unregister_me();\n+ 82 m_trans = other.m_trans;\n+ 83 m_classname = other.m_classname;\n+ 84 move_name_and_registration(other);\n+ 85 }\n+ 86 return *this;\n+ 87 }\n+ 88\n+ 89protected:\n+ 90 void register_me();\n+ 91 void unregister_me() noexcept;\n+ 92 void reg_pending_error(std::string const &) noexcept;\n+93 bool registered() const noexcept { return m_registered; }\n+ 94\n+95 transaction_base *m_trans;\n+ 96\n+ 97private:\n+ 98 bool m_registered = false;\n+ 99 std::string_view m_classname;\n+ 100 std::string m_name;\n+ 101\n+ 103 void move_name_and_registration(transaction_focus &other)\n+ 104 {\n+ 105 bool const reg{other.m_registered};\n+ 106 // Unregister the original while it still owns its name.\n+ 107 if (reg)\n+ 108 other.unregister_me();\n+ 109 // Now! Quick! Steal that name.\n+ 110 m_name = std::move(other.m_name);\n+ 111 // Now that we own the name, register ourselves instead.\n+ 112 if (reg)\n+ 113 this->register_me();\n+ 114 }\n+ 115};\n+ 116} // namespace pqxx\n+ 117#endif\n pqxx\n The home of all libpqxx classes, functions, templates, etc.\n Definition array.hxx:33\n-pqxx::dbtransaction\n-Abstract transaction base class: bracket transactions on the database.\n-Definition dbtransaction.hxx:54\n-pqxx::subtransaction\n-\"Transaction\" nested within another transaction\n-Definition subtransaction.hxx:78\n+pqxx::internal::describe_object\n+std::string describe_object(std::string_view class_name, std::string_view name)\n+Describe an object for humans, based on class name and optional name.\n+Definition util.cxx:51\n+pqxx::transaction_base\n+Interface definition (and common code) for \"transaction\" classes.\n+Definition transaction_base.hxx:88\n pqxx::transaction_focus\n Base class for things that monopolise a transaction's attention.\n Definition transaction_focus.hxx:29\n+pqxx::transaction_focus::description\n+std::string description() const\n+Definition transaction_focus.hxx:58\n+pqxx::transaction_focus::transaction_focus\n+transaction_focus()=delete\n+pqxx::transaction_focus::transaction_focus\n+transaction_focus(transaction_base &t, std::string_view cname)\n+Definition transaction_focus.hxx:41\n+pqxx::transaction_focus::unregister_me\n+void unregister_me() noexcept\n+Definition transaction_base.cxx:527\n pqxx::transaction_focus::name\n std::string_view name() const &noexcept\n Name for this object, if the caller passed one; empty string otherwise.\n Definition transaction_focus.hxx:56\n+pqxx::transaction_focus::classname\n+constexpr std::string_view classname() const noexcept\n+Class name, for human consumption.\n+Definition transaction_focus.hxx:50\n+pqxx::transaction_focus::transaction_focus\n+transaction_focus(transaction_base &t, std::string_view cname, std::string\n+&&oname)\n+Definition transaction_focus.hxx:36\n+pqxx::transaction_focus::transaction_focus\n+transaction_focus(transaction_focus const &)=delete\n+pqxx::transaction_focus::transaction_focus\n+transaction_focus(transaction_focus &&other)\n+Definition transaction_focus.hxx:63\n+pqxx::transaction_focus::operator=\n+transaction_focus & operator=(transaction_focus &&other)\n+Definition transaction_focus.hxx:76\n+pqxx::transaction_focus::transaction_focus\n+transaction_focus(transaction_base &t, std::string_view cname, std::string_view\n+oname)\n+Definition transaction_focus.hxx:31\n+pqxx::transaction_focus::m_trans\n+transaction_base * m_trans\n+Definition transaction_focus.hxx:95\n+pqxx::transaction_focus::operator=\n+transaction_focus & operator=(transaction_focus const &)=delete\n * include\n * pqxx\n- * subtransaction.hxx\n+ * transaction_focus.hxx\n * Generated by [doxygen] 1.9.8\n"}]}, {"source1": "./usr/share/doc/libpqxx-doc/html/a00116_source.html", "source2": "./usr/share/doc/libpqxx-doc/html/a00116_source.html", "unified_diff": "@@ -1,15 +1,15 @@\n \n \n \n \n \n \n \n-libpqxx: nontransaction.hxx Source File\n+libpqxx: binarystring.hxx Source File\n \n \n \n \n \n \n \n@@ -60,76 +60,284 @@\n \n
\n
\n-
nontransaction.hxx
\n+
binarystring.hxx
\n
\n
\n-
1/* Definition of the pqxx::nontransaction class.
\n+
1/* Deprecated representation for raw, binary data.
\n
2 *
\n-
3 * pqxx::nontransaction provides nontransactional database access
\n+
3 * DO NOT INCLUDE THIS FILE DIRECTLY; include pqxx/binarystring instead.
\n
4 *
\n-
5 * DO NOT INCLUDE THIS FILE DIRECTLY; include pqxx/nontransaction instead.
\n+
5 * Copyright (c) 2000-2023, Jeroen T. Vermeulen.
\n
6 *
\n-
7 * Copyright (c) 2000-2023, Jeroen T. Vermeulen.
\n-
8 *
\n-
9 * See COPYING for copyright license. If you did not receive a file called
\n-
10 * COPYING with this source code, please notify the distributor of this
\n-
11 * mistake, or contact the author.
\n-
12 */
\n-
13#ifndef PQXX_H_NONTRANSACTION
\n-
14#define PQXX_H_NONTRANSACTION
\n-
15
\n-
16#if !defined(PQXX_HEADER_PRE)
\n-
17# error "Include libpqxx headers as <pqxx/header>, not <pqxx/header.hxx>."
\n-
18#endif
\n-
19
\n-
20#include "pqxx/connection.hxx"
\n-
21#include "pqxx/result.hxx"
\n-
22#include "pqxx/transaction.hxx"
\n-
23
\n-
24namespace pqxx
\n-
25{
\n-
26using namespace std::literals;
\n-
27
\n+
7 * See COPYING for copyright license. If you did not receive a file called
\n+
8 * COPYING with this source code, please notify the distributor of this
\n+
9 * mistake, or contact the author.
\n+
10 */
\n+
11#ifndef PQXX_H_BINARYSTRING
\n+
12#define PQXX_H_BINARYSTRING
\n+
13
\n+
14#if !defined(PQXX_HEADER_PRE)
\n+
15# error "Include libpqxx headers as <pqxx/header>, not <pqxx/header.hxx>."
\n+
16#endif
\n+
17
\n+
18#include <memory>
\n+
19#include <string>
\n+
20#include <string_view>
\n+
21
\n+
22#include "pqxx/result.hxx"
\n+
23#include "pqxx/strconv.hxx"
\n+
24
\n+
25namespace pqxx
\n+
26{
\n+
27class binarystring;
\n+
28template<> struct string_traits<binarystring>;
\n
29
\n-
\n-
55class PQXX_LIBEXPORT nontransaction final : public transaction_base
\n-
56{
\n-
57public:
\n-
59
\n-
\n-
64 nontransaction(connection &c, std::string_view tname = ""sv) :
\n-
65 transaction_base{c, tname, std::shared_ptr<std::string>{}}
\n-
66 {
\n-
67 register_transaction();
\n-
68 }
\n-
\n+
30
\n+
32
\n+
\n+
58class PQXX_LIBEXPORT binarystring
\n+
59{
\n+
60public:
\n+
61 using char_type = unsigned char;
\n+
62 using value_type = std::char_traits<char_type>::char_type;
\n+
63 using size_type = std::size_t;
\n+
64 using difference_type = long;
\n+
65 using const_reference = value_type const &;
\n+
66 using const_pointer = value_type const *;
\n+\n+
68 using const_reverse_iterator = std::reverse_iterator<const_iterator>;
\n
69
\n-
70 virtual ~nontransaction() override { close(); }
\n-
71
\n-
72private:
\n-
73 virtual void do_commit() override {}
\n-
74};
\n+
70 [[deprecated("Use std::byte for binary data.")]] binarystring(
\n+
71 binarystring const &) = default;
\n+
72
\n+
74
\n+
78 [[deprecated("Use std::byte for binary data.")]] explicit binarystring(
\n+
79 field const &);
\n+
80
\n+
82
\n+
85 [[deprecated("Use std::byte for binary data.")]] explicit binarystring(
\n+
86 std::string_view);
\n+
87
\n+
89 [[deprecated("Use std::byte for binary data.")]] binarystring(
\n+
90 void const *, std::size_t);
\n+
91
\n+
\n+
93 [[deprecated("Use std::byte for binary data.")]] binarystring(
\n+
94 std::shared_ptr<value_type> ptr, size_type size) :
\n+
95 m_buf{std::move(ptr)}, m_size{size}
\n+
96 {}
\n+
\n+
97
\n+
99 [[nodiscard]] size_type size() const noexcept { return m_size; }
\n+
101 [[nodiscard]] size_type length() const noexcept { return size(); }
\n+
102 [[nodiscard]] bool empty() const noexcept { return size() == 0; }
\n+
103
\n+
104 [[nodiscard]] const_iterator begin() const noexcept { return data(); }
\n+
105 [[nodiscard]] const_iterator cbegin() const noexcept { return begin(); }
\n+
106 [[nodiscard]] const_iterator end() const noexcept { return data() + m_size; }
\n+
107 [[nodiscard]] const_iterator cend() const noexcept { return end(); }
\n+
108
\n+
109 [[nodiscard]] const_reference front() const noexcept { return *begin(); }
\n+
\n+
110 [[nodiscard]] const_reference back() const noexcept
\n+
111 {
\n+
112 return *(data() + m_size - 1);
\n+
113 }
\n+
\n+
114
\n+
\n+
115 [[nodiscard]] const_reverse_iterator rbegin() const
\n+
116 {
\n+
117 return const_reverse_iterator{end()};
\n+
118 }
\n+
\n+
119 [[nodiscard]] const_reverse_iterator crbegin() const { return rbegin(); }
\n+
\n+
120 [[nodiscard]] const_reverse_iterator rend() const
\n+
121 {
\n+
122 return const_reverse_iterator{begin()};
\n+
123 }
\n+
\n+
124 [[nodiscard]] const_reverse_iterator crend() const { return rend(); }
\n+
125
\n+
127 [[nodiscard]] value_type const *data() const noexcept { return m_buf.get(); }
\n+
128
\n+
\n+
129 [[nodiscard]] const_reference operator[](size_type i) const noexcept
\n+
130 {
\n+
131 return data()[i];
\n+
132 }
\n+
\n+
133
\n+
134 [[nodiscard]] PQXX_PURE bool operator==(binarystring const &) const noexcept;
\n+
\n+
135 [[nodiscard]] bool operator!=(binarystring const &rhs) const noexcept
\n+
136 {
\n+
137 return not operator==(rhs);
\n+
138 }
\n+
\n+
139
\n+\n+
141
\n+
143 const_reference at(size_type) const;
\n+
144
\n+
146 void swap(binarystring &);
\n+
147
\n+
149
\n+
\n+
152 [[nodiscard]] char const *get() const noexcept
\n+
153 {
\n+
154 return reinterpret_cast<char const *>(m_buf.get());
\n+
155 }
\n+
\n+
156
\n+
\n+
158 [[nodiscard]] std::string_view view() const noexcept
\n+
159 {
\n+
160 return std::string_view(get(), size());
\n+
161 }
\n+
\n+
162
\n+
164
\n+
169 [[nodiscard]] std::string str() const;
\n+
170
\n+
\n+
172 [[nodiscard]] std::byte const *bytes() const
\n+
173 {
\n+
174 return reinterpret_cast<std::byte const *>(get());
\n+
175 }
\n+
\n+
176
\n+
\n+
178 [[nodiscard]] std::basic_string_view<std::byte> bytes_view() const
\n+
179 {
\n+
180 return std::basic_string_view<std::byte>{bytes(), size()};
\n+
181 }
\n+
\n+
182
\n+
183private:
\n+
184 std::shared_ptr<value_type> m_buf;
\n+
185 size_type m_size{0};
\n+
186};
\n+
\n+
187
\n+
188
\n+
\n+
189template<> struct nullness<binarystring> : no_null<binarystring>
\n+
190{};
\n+
\n+
191
\n+
192
\n+
194
\n+
\n+
201template<> struct string_traits<binarystring>
\n+
202{
\n+
\n+
203 static std::size_t size_buffer(binarystring const &value) noexcept
\n+
204 {
\n+
205 return internal::size_esc_bin(std::size(value));
\n+
206 }
\n+
\n+
207
\n+
\n+
208 static zview to_buf(char *begin, char *end, binarystring const &value)
\n+
209 {
\n+
210 return generic_to_buf(begin, end, value);
\n+
211 }
\n+
\n+
212
\n+
\n+
213 static char *into_buf(char *begin, char *end, binarystring const &value)
\n+
214 {
\n+
215 auto const budget{size_buffer(value)};
\n+
216 if (internal::cmp_less(end - begin, budget))
\n+
217 throw conversion_overrun{
\n+
218 "Not enough buffer space to escape binary data."};
\n+
219 std::string_view text{value.view()};
\n+\n+
221 return begin + budget;
\n+
222 }
\n+
\n+
223
\n+
\n+
224 static binarystring from_string(std::string_view text)
\n+
225 {
\n+
226 auto const size{pqxx::internal::size_unesc_bin(std::size(text))};
\n+
227 std::shared_ptr<unsigned char> buf{
\n+
228 new unsigned char[size], [](unsigned char const *x) { delete[] x; }};
\n+
229 pqxx::internal::unesc_bin(text, reinterpret_cast<std::byte *>(buf.get()));
\n+
230#include "pqxx/internal/ignore-deprecated-pre.hxx"
\n+
231 return binarystring{std::move(buf), size};
\n+
232#include "pqxx/internal/ignore-deprecated-post.hxx"
\n+
233 }
\n+
\n+
234};
\n
\n-
75} // namespace pqxx
\n-
76#endif
\n+
235} // namespace pqxx
\n+
236#endif
\n
The home of all libpqxx classes, functions, templates, etc.
Definition array.hxx:33
\n-
Connection to a database.
Definition connection.hxx:253
\n-
Simple "transaction" class offering no transactional integrity.
Definition nontransaction.hxx:56
\n-
nontransaction(connection &c, std::string_view tname=""sv)
Constructor.
Definition nontransaction.hxx:64
\n-
virtual ~nontransaction() override
Definition nontransaction.hxx:70
\n-
Interface definition (and common code) for "transaction" classes.
Definition transaction_base.hxx:88
\n+
std::basic_string_view< std::byte > binary_cast(TYPE const &data)
Cast binary data to a type that libpqxx will recognise as binary.
Definition util.hxx:303
\n+\n+
void unesc_bin(std::string_view escaped_data, std::byte buffer[])
Reconstitute binary data from its escaped version.
Definition util.cxx:158
\n+
void esc_bin(std::basic_string_view< std::byte > binary_data, char buffer[]) noexcept
Hex-escape binary data into a buffer.
Definition util.cxx:126
\n+
constexpr std::size_t size_esc_bin(std::size_t binary_bytes) noexcept
Compute buffer size needed to escape binary data for use as a BYTEA.
Definition util.hxx:411
\n+
constexpr bool cmp_less(LEFT lhs, RIGHT rhs) noexcept
Same as std::cmp_less, or a workaround where that's not available.
Definition util.hxx:63
\n+
constexpr std::size_t size_unesc_bin(std::size_t escaped_bytes) noexcept
Compute binary size from the size of its escaped version.
Definition util.hxx:420
\n+
Binary data corresponding to PostgreSQL's "BYTEA" binary-string type.
Definition binarystring.hxx:59
\n+
const_reverse_iterator crend() const
Definition binarystring.hxx:124
\n+
char const * get() const noexcept
Raw character buffer (no terminating zero is added).
Definition binarystring.hxx:152
\n+
const_reverse_iterator rbegin() const
Definition binarystring.hxx:115
\n+
bool operator!=(binarystring const &rhs) const noexcept
Definition binarystring.hxx:135
\n+
const_pointer const_iterator
Definition binarystring.hxx:67
\n+
const_iterator end() const noexcept
Definition binarystring.hxx:106
\n+
std::basic_string_view< std::byte > bytes_view() const
Read data as a std::basic_string_view<std::byte>.
Definition binarystring.hxx:178
\n+
const_iterator begin() const noexcept
Definition binarystring.hxx:104
\n+
std::char_traits< char_type >::char_type value_type
Definition binarystring.hxx:62
\n+
value_type const & const_reference
Definition binarystring.hxx:65
\n+
long difference_type
Definition binarystring.hxx:64
\n+
binarystring(std::shared_ptr< value_type > ptr, size_type size)
Efficiently wrap a buffer of binary data in a binarystring.
Definition binarystring.hxx:93
\n+
const_reverse_iterator crbegin() const
Definition binarystring.hxx:119
\n+
std::size_t size_type
Definition binarystring.hxx:63
\n+
const_reference front() const noexcept
Definition binarystring.hxx:109
\n+
const_reference back() const noexcept
Definition binarystring.hxx:110
\n+
std::string_view view() const noexcept
Read contents as a std::string_view.
Definition binarystring.hxx:158
\n+
bool empty() const noexcept
Definition binarystring.hxx:102
\n+
std::byte const * bytes() const
Access data as a pointer to std::byte.
Definition binarystring.hxx:172
\n+
const_reference operator[](size_type i) const noexcept
Definition binarystring.hxx:129
\n+
const_iterator cend() const noexcept
Definition binarystring.hxx:107
\n+
value_type const * data() const noexcept
Unescaped field contents.
Definition binarystring.hxx:127
\n+
const_reverse_iterator rend() const
Definition binarystring.hxx:120
\n+
size_type length() const noexcept
Size of converted string in bytes.
Definition binarystring.hxx:101
\n+
binarystring & operator=(binarystring const &)
\n+
unsigned char char_type
Definition binarystring.hxx:61
\n+
std::reverse_iterator< const_iterator > const_reverse_iterator
Definition binarystring.hxx:68
\n+
const_iterator cbegin() const noexcept
Definition binarystring.hxx:105
\n+
binarystring(binarystring const &)=default
\n+
value_type const * const_pointer
Definition binarystring.hxx:66
\n+
size_type size() const noexcept
Size of converted string in bytes.
Definition binarystring.hxx:99
\n+
static char * into_buf(char *begin, char *end, binarystring const &value)
Definition binarystring.hxx:213
\n+
static std::size_t size_buffer(binarystring const &value) noexcept
Definition binarystring.hxx:203
\n+
static zview to_buf(char *begin, char *end, binarystring const &value)
Definition binarystring.hxx:208
\n+
static binarystring from_string(std::string_view text)
Definition binarystring.hxx:224
\n+
Could not convert value to string: not enough buffer space.
Definition except.hxx:313
\n+
Reference to a field in a result set.
Definition field.hxx:35
\n+
Traits describing a type's "null value," if any.
Definition strconv.hxx:93
\n+
Nullness traits describing a type which does not have a null value.
Definition strconv.hxx:115
\n+
Traits class for use in string conversions.
Definition strconv.hxx:155
\n+
static std::size_t size_buffer(TYPE const &value) noexcept
Estimate how much buffer space is needed to represent value.
\n+
Marker-type wrapper: zero-terminated std::string_view.
Definition zview.hxx:38
\n
\n
\n \n
\n \n
\n \n \n", "details": [{"source1": "html2text {}", "source2": "html2text {}", "unified_diff": "@@ -1,76 +1,358 @@\n \n \n \n \n \n libpqxx\u00a07.8.1\n \n-nontransaction.hxx\n- 1/* Definition of the pqxx::nontransaction class.\n+binarystring.hxx\n+ 1/* Deprecated representation for raw, binary data.\n 2 *\n- 3 * pqxx::nontransaction provides nontransactional database access\n+ 3 * DO NOT INCLUDE THIS FILE DIRECTLY; include pqxx/binarystring instead.\n 4 *\n- 5 * DO NOT INCLUDE THIS FILE DIRECTLY; include pqxx/nontransaction instead.\n+ 5 * Copyright (c) 2000-2023, Jeroen T. Vermeulen.\n 6 *\n- 7 * Copyright (c) 2000-2023, Jeroen T. Vermeulen.\n- 8 *\n- 9 * See COPYING for copyright license. If you did not receive a file called\n- 10 * COPYING with this source code, please notify the distributor of this\n- 11 * mistake, or contact the author.\n- 12 */\n- 13#ifndef PQXX_H_NONTRANSACTION\n- 14#define PQXX_H_NONTRANSACTION\n- 15\n- 16#if !defined(PQXX_HEADER_PRE)\n- 17# error \"Include libpqxx headers as , not .\"\n- 18#endif\n- 19\n- 20#include \"pqxx/connection.hxx\"\n- 21#include \"pqxx/result.hxx\"\n- 22#include \"pqxx/transaction.hxx\"\n- 23\n- 24namespace pqxx\n- 25{\n- 26using namespace std::literals;\n- 27\n+ 7 * See COPYING for copyright license. If you did not receive a file called\n+ 8 * COPYING with this source code, please notify the distributor of this\n+ 9 * mistake, or contact the author.\n+ 10 */\n+ 11#ifndef PQXX_H_BINARYSTRING\n+ 12#define PQXX_H_BINARYSTRING\n+ 13\n+ 14#if !defined(PQXX_HEADER_PRE)\n+ 15# error \"Include libpqxx headers as , not .\"\n+ 16#endif\n+ 17\n+ 18#include \n+ 19#include \n+ 20#include \n+ 21\n+ 22#include \"pqxx/result.hxx\"\n+ 23#include \"pqxx/strconv.hxx\"\n+ 24\n+ 25namespace pqxx\n+ 26{\n+ 27class binarystring;\n+ 28template<> struct string_traits;\n 29\n-55class PQXX_LIBEXPORT nontransaction final : public transaction_base\n- 56{\n- 57public:\n- 59\n-64 nontransaction(connection &c, std::string_view tname = \"\"sv) :\n- 65 transaction_base{c, tname, std::shared_ptr{}}\n- 66 {\n- 67 register_transaction();\n- 68 }\n+ 30\n+ 32\n+58class PQXX_LIBEXPORT binarystring\n+ 59{\n+ 60public:\n+61 using char_type = unsigned char;\n+62 using value_type = std::char_traits::char_type;\n+63 using size_type = std::size_t;\n+64 using difference_type = long;\n+65 using const_reference = value_type const &;\n+66 using const_pointer = value_type const *;\n+67 using const_iterator = const_pointer;\n+68 using const_reverse_iterator = std::reverse_iterator;\n 69\n-70 virtual ~nontransaction() override { close(); }\n- 71\n- 72private:\n- 73 virtual void do_commit() override {}\n- 74};\n- 75} // namespace pqxx\n- 76#endif\n+70 [[deprecated(\"Use std::byte for binary data.\")]] binarystring(\n+ 71 binarystring const &) = default;\n+ 72\n+ 74\n+ 78 [[deprecated(\"Use std::byte for binary data.\")]] explicit binarystring(\n+ 79 field const &);\n+ 80\n+ 82\n+ 85 [[deprecated(\"Use std::byte for binary data.\")]] explicit binarystring(\n+ 86 std::string_view);\n+ 87\n+ 89 [[deprecated(\"Use std::byte for binary data.\")]] binarystring(\n+ 90 void const *, std::size_t);\n+ 91\n+93 [[deprecated(\"Use std::byte for binary data.\")]] binarystring(\n+ 94 std::shared_ptr ptr, size_type size) :\n+ 95 m_buf{std::move(ptr)}, m_size{size}\n+ 96 {}\n+ 97\n+99 [[nodiscard]] size_type size() const noexcept { return m_size; }\n+101 [[nodiscard]] size_type length() const noexcept { return size(); }\n+102 [[nodiscard]] bool empty() const noexcept { return size() == 0; }\n+ 103\n+104 [[nodiscard]] const_iterator begin() const noexcept { return data(); }\n+105 [[nodiscard]] const_iterator cbegin() const noexcept { return begin(); }\n+106 [[nodiscard]] const_iterator end() const noexcept { return data() + m_size;\n+}\n+107 [[nodiscard]] const_iterator cend() const noexcept { return end(); }\n+ 108\n+109 [[nodiscard]] const_reference front() const noexcept { return *begin(); }\n+110 [[nodiscard]] const_reference back() const noexcept\n+ 111 {\n+ 112 return *(data() + m_size - 1);\n+ 113 }\n+ 114\n+115 [[nodiscard]] const_reverse_iterator rbegin() const\n+ 116 {\n+ 117 return const_reverse_iterator{end()};\n+ 118 }\n+119 [[nodiscard]] const_reverse_iterator crbegin() const { return rbegin(); }\n+120 [[nodiscard]] const_reverse_iterator rend() const\n+ 121 {\n+ 122 return const_reverse_iterator{begin()};\n+ 123 }\n+124 [[nodiscard]] const_reverse_iterator crend() const { return rend(); }\n+ 125\n+127 [[nodiscard]] value_type const *data() const noexcept { return m_buf.get();\n+}\n+ 128\n+129 [[nodiscard]] const_reference operator[](size_type i) const noexcept\n+ 130 {\n+ 131 return data()[i];\n+ 132 }\n+ 133\n+ 134 [[nodiscard]] PQXX_PURE bool operator==(binarystring const &) const\n+noexcept;\n+135 [[nodiscard]] bool operator!=(binarystring const &rhs) const noexcept\n+ 136 {\n+ 137 return not operator==(rhs);\n+ 138 }\n+ 139\n+140 binarystring &operator=(binarystring const &);\n+ 141\n+ 143 const_reference at(size_type) const;\n+ 144\n+ 146 void swap(binarystring &);\n+ 147\n+ 149\n+152 [[nodiscard]] char const *get() const noexcept\n+ 153 {\n+ 154 return reinterpret_cast(m_buf.get());\n+ 155 }\n+ 156\n+158 [[nodiscard]] std::string_view view() const noexcept\n+ 159 {\n+ 160 return std::string_view(get(), size());\n+ 161 }\n+ 162\n+ 164\n+ 169 [[nodiscard]] std::string str() const;\n+ 170\n+172 [[nodiscard]] std::byte const *bytes() const\n+ 173 {\n+ 174 return reinterpret_cast(get());\n+ 175 }\n+ 176\n+178 [[nodiscard]] std::basic_string_view bytes_view() const\n+ 179 {\n+ 180 return std::basic_string_view{bytes(), size()};\n+ 181 }\n+ 182\n+ 183private:\n+ 184 std::shared_ptr m_buf;\n+ 185 size_type m_size{0};\n+ 186};\n+ 187\n+ 188\n+189template<> struct nullness : no_null\n+ 190{};\n+ 191\n+ 192\n+ 194\n+201template<> struct string_traits\n+ 202{\n+203 static std::size_t size_buffer(binarystring const &value) noexcept\n+ 204 {\n+ 205 return internal::size_esc_bin(std::size(value));\n+ 206 }\n+ 207\n+208 static zview to_buf(char *begin, char *end, binarystring const &value)\n+ 209 {\n+ 210 return generic_to_buf(begin, end, value);\n+ 211 }\n+ 212\n+213 static char *into_buf(char *begin, char *end, binarystring const &value)\n+ 214 {\n+ 215 auto const budget{size_buffer(value)};\n+ 216 if (internal::cmp_less(end - begin, budget))\n+ 217 throw conversion_overrun{\n+ 218 \"Not enough buffer space to escape binary data.\"};\n+ 219 std::string_view text{value.view()};\n+ 220 internal::esc_bin(binary_cast(text), begin);\n+ 221 return begin + budget;\n+ 222 }\n+ 223\n+224 static binarystring from_string(std::string_view text)\n+ 225 {\n+ 226 auto const size{pqxx::internal::size_unesc_bin(std::size(text))};\n+ 227 std::shared_ptr buf{\n+ 228 new unsigned char[size], [](unsigned char const *x) { delete[] x; }};\n+ 229 pqxx::internal::unesc_bin(text, reinterpret_cast(buf.get()));\n+ 230#include \"pqxx/internal/ignore-deprecated-pre.hxx\"\n+ 231 return binarystring{std::move(buf), size};\n+ 232#include \"pqxx/internal/ignore-deprecated-post.hxx\"\n+ 233 }\n+ 234};\n+ 235} // namespace pqxx\n+ 236#endif\n pqxx\n The home of all libpqxx classes, functions, templates, etc.\n Definition array.hxx:33\n-pqxx::connection\n-Connection to a database.\n-Definition connection.hxx:253\n-pqxx::nontransaction\n-Simple \"transaction\" class offering no transactional integrity.\n-Definition nontransaction.hxx:56\n-pqxx::nontransaction::nontransaction\n-nontransaction(connection &c, std::string_view tname=\"\"sv)\n-Constructor.\n-Definition nontransaction.hxx:64\n-pqxx::nontransaction::~nontransaction\n-virtual ~nontransaction() override\n-Definition nontransaction.hxx:70\n-pqxx::transaction_base\n-Interface definition (and common code) for \"transaction\" classes.\n-Definition transaction_base.hxx:88\n+pqxx::binary_cast\n+std::basic_string_view< std::byte > binary_cast(TYPE const &data)\n+Cast binary data to a type that libpqxx will recognise as binary.\n+Definition util.hxx:303\n+pqxx::format::text\n+@ text\n+pqxx::internal::unesc_bin\n+void unesc_bin(std::string_view escaped_data, std::byte buffer[])\n+Reconstitute binary data from its escaped version.\n+Definition util.cxx:158\n+pqxx::internal::esc_bin\n+void esc_bin(std::basic_string_view< std::byte > binary_data, char buffer[])\n+noexcept\n+Hex-escape binary data into a buffer.\n+Definition util.cxx:126\n+pqxx::internal::size_esc_bin\n+constexpr std::size_t size_esc_bin(std::size_t binary_bytes) noexcept\n+Compute buffer size needed to escape binary data for use as a BYTEA.\n+Definition util.hxx:411\n+pqxx::internal::cmp_less\n+constexpr bool cmp_less(LEFT lhs, RIGHT rhs) noexcept\n+Same as std::cmp_less, or a workaround where that's not available.\n+Definition util.hxx:63\n+pqxx::internal::size_unesc_bin\n+constexpr std::size_t size_unesc_bin(std::size_t escaped_bytes) noexcept\n+Compute binary size from the size of its escaped version.\n+Definition util.hxx:420\n+pqxx::binarystring\n+Binary data corresponding to PostgreSQL's \"BYTEA\" binary-string type.\n+Definition binarystring.hxx:59\n+pqxx::binarystring::crend\n+const_reverse_iterator crend() const\n+Definition binarystring.hxx:124\n+pqxx::binarystring::get\n+char const * get() const noexcept\n+Raw character buffer (no terminating zero is added).\n+Definition binarystring.hxx:152\n+pqxx::binarystring::rbegin\n+const_reverse_iterator rbegin() const\n+Definition binarystring.hxx:115\n+pqxx::binarystring::operator!=\n+bool operator!=(binarystring const &rhs) const noexcept\n+Definition binarystring.hxx:135\n+pqxx::binarystring::const_iterator\n+const_pointer const_iterator\n+Definition binarystring.hxx:67\n+pqxx::binarystring::end\n+const_iterator end() const noexcept\n+Definition binarystring.hxx:106\n+pqxx::binarystring::bytes_view\n+std::basic_string_view< std::byte > bytes_view() const\n+Read data as a std::basic_string_view.\n+Definition binarystring.hxx:178\n+pqxx::binarystring::begin\n+const_iterator begin() const noexcept\n+Definition binarystring.hxx:104\n+pqxx::binarystring::value_type\n+std::char_traits< char_type >::char_type value_type\n+Definition binarystring.hxx:62\n+pqxx::binarystring::const_reference\n+value_type const & const_reference\n+Definition binarystring.hxx:65\n+pqxx::binarystring::difference_type\n+long difference_type\n+Definition binarystring.hxx:64\n+pqxx::binarystring::binarystring\n+binarystring(std::shared_ptr< value_type > ptr, size_type size)\n+Efficiently wrap a buffer of binary data in a binarystring.\n+Definition binarystring.hxx:93\n+pqxx::binarystring::crbegin\n+const_reverse_iterator crbegin() const\n+Definition binarystring.hxx:119\n+pqxx::binarystring::size_type\n+std::size_t size_type\n+Definition binarystring.hxx:63\n+pqxx::binarystring::front\n+const_reference front() const noexcept\n+Definition binarystring.hxx:109\n+pqxx::binarystring::back\n+const_reference back() const noexcept\n+Definition binarystring.hxx:110\n+pqxx::binarystring::view\n+std::string_view view() const noexcept\n+Read contents as a std::string_view.\n+Definition binarystring.hxx:158\n+pqxx::binarystring::empty\n+bool empty() const noexcept\n+Definition binarystring.hxx:102\n+pqxx::binarystring::bytes\n+std::byte const * bytes() const\n+Access data as a pointer to std::byte.\n+Definition binarystring.hxx:172\n+pqxx::binarystring::operator[]\n+const_reference operator[](size_type i) const noexcept\n+Definition binarystring.hxx:129\n+pqxx::binarystring::cend\n+const_iterator cend() const noexcept\n+Definition binarystring.hxx:107\n+pqxx::binarystring::data\n+value_type const * data() const noexcept\n+Unescaped field contents.\n+Definition binarystring.hxx:127\n+pqxx::binarystring::rend\n+const_reverse_iterator rend() const\n+Definition binarystring.hxx:120\n+pqxx::binarystring::length\n+size_type length() const noexcept\n+Size of converted string in bytes.\n+Definition binarystring.hxx:101\n+pqxx::binarystring::operator=\n+binarystring & operator=(binarystring const &)\n+pqxx::binarystring::char_type\n+unsigned char char_type\n+Definition binarystring.hxx:61\n+pqxx::binarystring::const_reverse_iterator\n+std::reverse_iterator< const_iterator > const_reverse_iterator\n+Definition binarystring.hxx:68\n+pqxx::binarystring::cbegin\n+const_iterator cbegin() const noexcept\n+Definition binarystring.hxx:105\n+pqxx::binarystring::binarystring\n+binarystring(binarystring const &)=default\n+pqxx::binarystring::const_pointer\n+value_type const * const_pointer\n+Definition binarystring.hxx:66\n+pqxx::binarystring::size\n+size_type size() const noexcept\n+Size of converted string in bytes.\n+Definition binarystring.hxx:99\n+pqxx::string_traits<_binarystring_>::into_buf\n+static char * into_buf(char *begin, char *end, binarystring const &value)\n+Definition binarystring.hxx:213\n+pqxx::string_traits<_binarystring_>::size_buffer\n+static std::size_t size_buffer(binarystring const &value) noexcept\n+Definition binarystring.hxx:203\n+pqxx::string_traits<_binarystring_>::to_buf\n+static zview to_buf(char *begin, char *end, binarystring const &value)\n+Definition binarystring.hxx:208\n+pqxx::string_traits<_binarystring_>::from_string\n+static binarystring from_string(std::string_view text)\n+Definition binarystring.hxx:224\n+pqxx::conversion_overrun\n+Could not convert value to string: not enough buffer space.\n+Definition except.hxx:313\n+pqxx::field\n+Reference to a field in a result set.\n+Definition field.hxx:35\n+pqxx::nullness\n+Traits describing a type's \"null value,\" if any.\n+Definition strconv.hxx:93\n+pqxx::no_null\n+Nullness traits describing a type which does not have a null value.\n+Definition strconv.hxx:115\n+pqxx::string_traits\n+Traits class for use in string conversions.\n+Definition strconv.hxx:155\n+pqxx::string_traits::size_buffer\n+static std::size_t size_buffer(TYPE const &value) noexcept\n+Estimate how much buffer space is needed to represent value.\n+pqxx::zview\n+Marker-type wrapper: zero-terminated std::string_view.\n+Definition zview.hxx:38\n * include\n * pqxx\n- * nontransaction.hxx\n+ * binarystring.hxx\n * Generated by [doxygen] 1.9.8\n"}]}, {"source1": "./usr/share/doc/libpqxx-doc/html/a00119_source.html", "source2": "./usr/share/doc/libpqxx-doc/html/a00119_source.html", "unified_diff": "@@ -1,15 +1,15 @@\n \n \n \n \n \n \n \n-libpqxx: isolation.hxx Source File\n+libpqxx: zview.hxx Source File\n \n \n \n \n \n \n \n@@ -60,74 +60,180 @@\n \n
\n
\n-
isolation.hxx
\n+
zview.hxx
\n
\n
\n-
1/* Definitions for transaction isolation levels, and such.
\n+
1/* Zero-terminated string view.
\n
2 *
\n-
3 * DO NOT INCLUDE THIS FILE DIRECTLY; include pqxx/isolation instead.
\n+
3 * DO NOT INCLUDE THIS FILE DIRECTLY; include pqxx/zview instead.
\n
4 *
\n
5 * Copyright (c) 2000-2023, Jeroen T. Vermeulen.
\n
6 *
\n
7 * See COPYING for copyright license. If you did not receive a file called
\n
8 * COPYING with this source code, please notify the distributor of this
\n
9 * mistake, or contact the author.
\n
10 */
\n-
11#ifndef PQXX_H_ISOLATION
\n-
12#define PQXX_H_ISOLATION
\n+
11#ifndef PQXX_H_ZVIEW
\n+
12#define PQXX_H_ZVIEW
\n
13
\n-
14#if !defined(PQXX_HEADER_PRE)
\n-
15# error "Include libpqxx headers as <pqxx/header>, not <pqxx/header.hxx>."
\n-
16#endif
\n+
14#include <string>
\n+
15#include <string_view>
\n+
16#include <type_traits>
\n
17
\n-
18#include "pqxx/util.hxx"
\n+
18#include "pqxx/types.hxx"
\n
19
\n-
20namespace pqxx
\n-
21{
\n-
23
\n-
\n-
26enum class write_policy
\n-
27{
\n-\n-\n-
30};
\n-
\n-
31
\n-
32
\n-
34
\n-
\n-\n-
66{
\n-
67 // PostgreSQL only has the better isolation levels.
\n-
68 // read_uncommitted,
\n-
69
\n-\n-\n-\n-
73};
\n+
20
\n+
21namespace pqxx
\n+
22{
\n+
24
\n+
\n+
37class zview : public std::string_view
\n+
38{
\n+
39public:
\n+
40 constexpr zview() noexcept = default;
\n+
41
\n+
\n+
43 constexpr zview(char const text[], std::ptrdiff_t len) noexcept(
\n+
44 noexcept(std::string_view{text, static_cast<std::size_t>(len)})) :
\n+
45 std::string_view{text, static_cast<std::size_t>(len)}
\n+
46 {}
\n
\n-
74} // namespace pqxx
\n-
75#endif
\n+
47
\n+
\n+
49 constexpr zview(char text[], std::ptrdiff_t len) noexcept(
\n+
50 noexcept(std::string_view{text, static_cast<std::size_t>(len)})) :
\n+
51 std::string_view{text, static_cast<std::size_t>(len)}
\n+
52 {}
\n+
\n+
53
\n+
\n+
55 explicit constexpr zview(std::string_view other) noexcept :
\n+
56 std::string_view{other}
\n+
57 {}
\n+
\n+
58
\n+
60
\n+
62 template<typename... Args>
\n+
\n+
63 explicit constexpr zview(Args &&...args) :
\n+
64 std::string_view(std::forward<Args>(args)...)
\n+
65 {}
\n+
\n+
66
\n+
67 // C++20: constexpr.
\n+
\n+
69 zview(std::string const &str) noexcept :
\n+
70 std::string_view{str.c_str(), str.size()}
\n+
71 {}
\n+
\n+
72
\n+
74
\n+
\n+
78 constexpr zview(char const str[]) noexcept(noexcept(std::string_view{str})) :
\n+
79 std::string_view{str}
\n+
80 {}
\n+
\n+
81
\n+
83
\n+
91 template<size_t size>
\n+
\n+
92 constexpr zview(char const (&literal)[size]) : zview(literal, size - 1)
\n+
93 {}
\n+
\n+
94
\n+
\n+
96 [[nodiscard]] constexpr char const *c_str() const &noexcept
\n+
97 {
\n+
98 return data();
\n+
99 }
\n+
\n+
100};
\n+
\n+
101
\n+
102
\n+
104
\n+
\n+
111constexpr zview operator"" _zv(char const str[], std::size_t len) noexcept
\n+
112{
\n+
113 return zview{str, len};
\n+
114}
\n+
\n+
115} // namespace pqxx
\n+
116
\n+
117
\n+
118#if defined(PQXX_HAVE_CONCEPTS)
\n+
120template<> inline constexpr bool std::ranges::enable_view<pqxx::zview>{true};
\n+
121
\n+
122
\n+
124template<>
\n+
125inline constexpr bool std::ranges::enable_borrowed_range<pqxx::zview>{true};
\n+
126
\n+
127namespace pqxx::internal
\n+
128{
\n+
130
\n+
134template<typename T>
\n+
135concept ZString = std::is_convertible_v<strip_t<T>, char const *> or
\n+
136 std::is_convertible_v<strip_t<T>, zview> or
\n+
137 std::is_convertible_v<T, std::string const &>;
\n+
138} // namespace pqxx::internal
\n+
139#endif // PQXX_HAVE_CONCEPTS
\n+
140
\n+
141
\n+
142namespace pqxx::internal
\n+
143{
\n+
\n+
145inline constexpr char const *as_c_string(char const str[]) noexcept
\n+
146{
\n+
147 return str;
\n+
148}
\n+
\n+
150template<std::size_t N>
\n+
\n+
151inline constexpr char const *as_c_string(char (&str)[N]) noexcept
\n+
152{
\n+
153 return str;
\n+
154}
\n+
\n+
\n+
156inline constexpr char const *as_c_string(pqxx::zview str) noexcept
\n+
157{
\n+
158 return str.c_str();
\n+
159}
\n+
\n+
160// C++20: Make this constexpr.
\n+
\n+
162inline char const *as_c_string(std::string const &str) noexcept
\n+
163{
\n+
164 return str.c_str();
\n+
165}
\n+
\n+
166} // namespace pqxx::internal
\n+
167#endif
\n
The home of all libpqxx classes, functions, templates, etc.
Definition array.hxx:33
\n-
write_policy
Should a transaction be read-only, or read-write?
Definition isolation.hxx:27
\n-\n-\n-
isolation_level
Transaction isolation levels.
Definition isolation.hxx:66
\n-
@ serializable
Definition isolation.hxx:72
\n-
@ read_committed
Definition isolation.hxx:70
\n-
@ repeatable_read
Definition isolation.hxx:71
\n+\n+
Internal items for libpqxx' own use. Do not use these yourself.
Definition composite.hxx:84
\n+
constexpr char const * as_c_string(char const str[]) noexcept
Get a raw C string pointer.
Definition zview.hxx:145
\n+
Marker-type wrapper: zero-terminated std::string_view.
Definition zview.hxx:38
\n+
constexpr zview(char const (&literal)[size])
Construct a zview from a string literal.
Definition zview.hxx:92
\n+
constexpr char const * c_str() const &noexcept
Either a null pointer, or a zero-terminated text buffer.
Definition zview.hxx:96
\n+
constexpr zview(Args &&...args)
Construct from any initialiser you might use for std::string_view.
Definition zview.hxx:63
\n+
constexpr zview(char text[], std::ptrdiff_t len) noexcept(noexcept(std::string_view{text, static_cast< std::size_t >(len)}))
Convenience overload: construct using pointer and signed length.
Definition zview.hxx:49
\n+
constexpr zview() noexcept=default
\n+
constexpr zview(char const str[]) noexcept(noexcept(std::string_view{str}))
Construct a zview from a C-style string.
Definition zview.hxx:78
\n+
constexpr zview(std::string_view other) noexcept
Explicitly promote a string_view to a zview.
Definition zview.hxx:55
\n+
zview(std::string const &str) noexcept
Definition zview.hxx:69
\n
\n
\n \n
\n \n
\n \n \n", "details": [{"source1": "html2text {}", "source2": "html2text {}", "unified_diff": "@@ -1,77 +1,178 @@\n \n \n \n \n \n libpqxx\u00a07.8.1\n \n-isolation.hxx\n- 1/* Definitions for transaction isolation levels, and such.\n+zview.hxx\n+ 1/* Zero-terminated string view.\n 2 *\n- 3 * DO NOT INCLUDE THIS FILE DIRECTLY; include pqxx/isolation instead.\n+ 3 * DO NOT INCLUDE THIS FILE DIRECTLY; include pqxx/zview instead.\n 4 *\n 5 * Copyright (c) 2000-2023, Jeroen T. Vermeulen.\n 6 *\n 7 * See COPYING for copyright license. If you did not receive a file called\n 8 * COPYING with this source code, please notify the distributor of this\n 9 * mistake, or contact the author.\n 10 */\n- 11#ifndef PQXX_H_ISOLATION\n- 12#define PQXX_H_ISOLATION\n+ 11#ifndef PQXX_H_ZVIEW\n+ 12#define PQXX_H_ZVIEW\n 13\n- 14#if !defined(PQXX_HEADER_PRE)\n- 15# error \"Include libpqxx headers as , not .\"\n- 16#endif\n+ 14#include \n+ 15#include \n+ 16#include \n 17\n- 18#include \"pqxx/util.hxx\"\n+ 18#include \"pqxx/types.hxx\"\n 19\n- 20namespace pqxx\n- 21{\n- 23\n-26enum class write_policy\n- 27{\n- 28 read_only,\n- 29 read_write\n- 30};\n- 31\n- 32\n- 34\n-65enum isolation_level\n- 66{\n- 67 // PostgreSQL only has the better isolation levels.\n- 68 // read_uncommitted,\n- 69\n-70 read_committed,\n-71 repeatable_read,\n-72 serializable,\n- 73};\n- 74} // namespace pqxx\n- 75#endif\n+ 20\n+ 21namespace pqxx\n+ 22{\n+ 24\n+37class zview : public std::string_view\n+ 38{\n+ 39public:\n+40 constexpr zview() noexcept = default;\n+ 41\n+43 constexpr zview(char const text[], std::ptrdiff_t len) noexcept(\n+ 44 noexcept(std::string_view{text, static_cast(len)})) :\n+ 45 std::string_view{text, static_cast(len)}\n+ 46 {}\n+ 47\n+49 constexpr zview(char text[], std::ptrdiff_t len) noexcept(\n+ 50 noexcept(std::string_view{text, static_cast(len)})) :\n+ 51 std::string_view{text, static_cast(len)}\n+ 52 {}\n+ 53\n+55 explicit constexpr zview(std::string_view other) noexcept :\n+ 56 std::string_view{other}\n+ 57 {}\n+ 58\n+ 60\n+ 62 template\n+63 explicit constexpr zview(Args &&...args) :\n+ 64 std::string_view(std::forward(args)...)\n+ 65 {}\n+ 66\n+ 67 // C++20: constexpr.\n+69 zview(std::string const &str) noexcept :\n+ 70 std::string_view{str.c_str(), str.size()}\n+ 71 {}\n+ 72\n+ 74\n+78 constexpr zview(char const str[]) noexcept(noexcept(std::string_view{str}))\n+:\n+ 79 std::string_view{str}\n+ 80 {}\n+ 81\n+ 83\n+ 91 template\n+92 constexpr zview(char const (&literal)[size]) : zview(literal, size - 1)\n+ 93 {}\n+ 94\n+96 [[nodiscard]] constexpr char const *c_str() const &noexcept\n+ 97 {\n+ 98 return data();\n+ 99 }\n+ 100};\n+ 101\n+ 102\n+ 104\n+111constexpr zview operator\"\" _zv(char const str[], std::size_t len) noexcept\n+ 112{\n+ 113 return zview{str, len};\n+ 114}\n+ 115} // namespace pqxx\n+ 116\n+ 117\n+ 118#if defined(PQXX_HAVE_CONCEPTS)\n+ 120template<> inline constexpr bool std::ranges::enable_view\n+{true};\n+ 121\n+ 122\n+ 124template<>\n+ 125inline constexpr bool std::ranges::enable_borrowed_range\n+{true};\n+ 126\n+ 127namespace pqxx::internal\n+ 128{\n+ 130\n+ 134template\n+ 135concept ZString = std::is_convertible_v, char const *> or\n+ 136 std::is_convertible_v, zview> or\n+ 137 std::is_convertible_v;\n+ 138} // namespace pqxx::internal\n+ 139#endif // PQXX_HAVE_CONCEPTS\n+ 140\n+ 141\n+ 142namespace pqxx::internal\n+ 143{\n+145inline constexpr char const *as_c_string(char const str[]) noexcept\n+ 146{\n+ 147 return str;\n+ 148}\n+ 150template\n+151inline constexpr char const *as_c_string(char (&str)[N]) noexcept\n+ 152{\n+ 153 return str;\n+ 154}\n+156inline constexpr char const *as_c_string(pqxx::zview str) noexcept\n+ 157{\n+ 158 return str.c_str();\n+ 159}\n+ 160// C++20: Make this constexpr.\n+162inline char const *as_c_string(std::string const &str) noexcept\n+ 163{\n+ 164 return str.c_str();\n+ 165}\n+ 166} // namespace pqxx::internal\n+ 167#endif\n pqxx\n The home of all libpqxx classes, functions, templates, etc.\n Definition array.hxx:33\n-pqxx::write_policy\n-write_policy\n-Should a transaction be read-only, or read-write?\n-Definition isolation.hxx:27\n-pqxx::write_policy::read_write\n-@ read_write\n-pqxx::write_policy::read_only\n-@ read_only\n-pqxx::isolation_level\n-isolation_level\n-Transaction isolation levels.\n-Definition isolation.hxx:66\n-pqxx::serializable\n-@ serializable\n-Definition isolation.hxx:72\n-pqxx::read_committed\n-@ read_committed\n-Definition isolation.hxx:70\n-pqxx::repeatable_read\n-@ repeatable_read\n-Definition isolation.hxx:71\n+pqxx::format::text\n+@ text\n+pqxx::internal\n+Internal items for libpqxx' own use. Do not use these yourself.\n+Definition composite.hxx:84\n+pqxx::internal::as_c_string\n+constexpr char const * as_c_string(char const str[]) noexcept\n+Get a raw C string pointer.\n+Definition zview.hxx:145\n+pqxx::zview\n+Marker-type wrapper: zero-terminated std::string_view.\n+Definition zview.hxx:38\n+pqxx::zview::zview\n+constexpr zview(char const (&literal)[size])\n+Construct a zview from a string literal.\n+Definition zview.hxx:92\n+pqxx::zview::c_str\n+constexpr char const * c_str() const &noexcept\n+Either a null pointer, or a zero-terminated text buffer.\n+Definition zview.hxx:96\n+pqxx::zview::zview\n+constexpr zview(Args &&...args)\n+Construct from any initialiser you might use for std::string_view.\n+Definition zview.hxx:63\n+pqxx::zview::zview\n+constexpr zview(char text[], std::ptrdiff_t len) noexcept(noexcept(std::\n+string_view{text, static_cast< std::size_t >(len)}))\n+Convenience overload: construct using pointer and signed length.\n+Definition zview.hxx:49\n+pqxx::zview::zview\n+constexpr zview() noexcept=default\n+pqxx::zview::zview\n+constexpr zview(char const str[]) noexcept(noexcept(std::string_view{str}))\n+Construct a zview from a C-style string.\n+Definition zview.hxx:78\n+pqxx::zview::zview\n+constexpr zview(std::string_view other) noexcept\n+Explicitly promote a string_view to a zview.\n+Definition zview.hxx:55\n+pqxx::zview::zview\n+zview(std::string const &str) noexcept\n+Definition zview.hxx:69\n * include\n * pqxx\n- * isolation.hxx\n+ * zview.hxx\n * Generated by [doxygen] 1.9.8\n"}]}, {"source1": "./usr/share/doc/libpqxx-doc/html/a01086.html", "source2": "./usr/share/doc/libpqxx-doc/html/a01086.html", "unified_diff": "@@ -65,15 +65,15 @@\n
pqxx::array< ELEMENT, DIMENSIONS, SEPARATOR > Class Template Referencefinal
\n
\n
\n \n

An SQL array received from the database. \n More...

\n \n-

#include <array.hxx>

\n+

#include <array.hxx>

\n \n \n \n \n \n \n@@ -510,15 +510,15 @@\n

In practice however, I don't think ssize() could ever overflow. You'd need an array where each element takes up just one byte, such as Booleans, filling up more than half your address space. But the input string for that array would need at least two bytes per value: one for the value, one for the separating comma between elements. So even then you wouldn't have enough address space to create the array, even if your system allowed you to use your full address space.

\n \n

References pqxx::array< ELEMENT, DIMENSIONS, SEPARATOR >::size().

\n \n \n \n
The documentation for this class was generated from the following file:\n \n \n \n
\n
    \n
  • pqxx
  • array
  • \n"}, {"source1": "./usr/share/doc/libpqxx-doc/html/a01090.html", "source2": "./usr/share/doc/libpqxx-doc/html/a01090.html", "unified_diff": "@@ -66,15 +66,15 @@\n
    pqxx::array_parser Class Reference
    \n
\n
\n \n

Low-level array parser. \n More...

\n \n-

#include <array.hxx>

\n+

#include <array.hxx>

\n

\n Public Member Functions

 array (std::string_view data, connection const &conn)
 Parse an SQL array, read as text from a pqxx::result or stream.
 
constexpr std::size_t dimensions () noexcept
\n \n \n

\n Public Types

enum class  juncture {
\n   row_start\n , row_end\n , null_value\n@@ -200,15 +200,15 @@\n

Parse the next step in the array.

\n

Returns what it found. If the juncture is juncture::string_value, the string will contain the value. Otherwise, it will be empty.

\n

Call this until the array_parser::juncture it returns is juncture::done.

\n \n \n \n
The documentation for this class was generated from the following files:\n \n \n \n
\n
    \n"}, {"source1": "./usr/share/doc/libpqxx-doc/html/a01094.html", "source2": "./usr/share/doc/libpqxx-doc/html/a01094.html", "unified_diff": "@@ -66,15 +66,15 @@\n
    pqxx::binarystring Class Reference
    \n
\n
\n \n

Binary data corresponding to PostgreSQL's \"BYTEA\" binary-string type. \n More...

\n \n-

#include <binarystring.hxx>

\n+

#include <binarystring.hxx>

\n \n \n \n \n \n \n@@ -1032,15 +1032,15 @@\n

Read contents as a std::string_view.

\n \n

Referenced by pqxx::string_traits< binarystring >::into_buf().

\n \n \n \n
The documentation for this class was generated from the following files:\n \n \n \n
\n
    \n"}, {"source1": "./usr/share/doc/libpqxx-doc/html/a01098.html", "source2": "./usr/share/doc/libpqxx-doc/html/a01098.html", "unified_diff": "@@ -61,15 +61,15 @@\n
    \n \n
    pqxx::nullness< binarystring > Struct Reference
    \n
    \n
    \n \n-

    #include <binarystring.hxx>

    \n+

    #include <binarystring.hxx>

    \n
    \n Inheritance diagram for pqxx::nullness< binarystring >:
    \n
    \n
    \"Inheritance
    \n \n \"\"\n \"\"\n@@ -90,15 +90,15 @@\n
\n \n \n \n \n

\n Public Types

using char_type = unsigned char
 
using value_type = std::char_traits< char_type >::char_type
 
 Does TYPE have a \"built-in null value\"?
 
static constexpr bool always_null
 Are all values of this type null?
 
\n
The documentation for this struct was generated from the following file:\n
\n \n \n
\n
    \n
  • pqxx
  • nullness< binarystring >
  • \n"}, {"source1": "./usr/share/doc/libpqxx-doc/html/a01102.html", "source2": "./usr/share/doc/libpqxx-doc/html/a01102.html", "unified_diff": "@@ -65,15 +65,15 @@\n
    pqxx::string_traits< binarystring > Struct Reference
    \n
\n
\n \n

String conversion traits for binarystring. \n More...

\n \n-

#include <binarystring.hxx>

\n+

#include <binarystring.hxx>

\n \n \n \n \n \n \n@@ -226,15 +226,15 @@\n \n

\n Static Public Member Functions

static std::size_t size_buffer (binarystring const &value) noexcept
 
static zview to_buf (char *begin, char *end, binarystring const &value)
 
\n
\n \n
\n \n
The documentation for this struct was generated from the following file:\n \n \n \n
\n
\n
pqxx::blob Class Reference
\n \n
\n \n-

#include <blob.hxx>

\n+

#include <blob.hxx>

\n \n \n \n \n \n \n@@ -1065,15 +1065,15 @@\n

Maximum number of bytes that can be read or written at a time.

\n

The underlying protocol only supports reads and writes up to 2 GB exclusive.

\n

If you need to read or write more data to or from a binary large object, you'll have to break it up into chunks.

\n \n \n \n
The documentation for this class was generated from the following files:\n \n \n \n
\n
    \n"}, {"source1": "./usr/share/doc/libpqxx-doc/html/a01110.html", "source2": "./usr/share/doc/libpqxx-doc/html/a01110.html", "unified_diff": "@@ -65,15 +65,15 @@\n
    pqxx::connection Class Reference
    \n
\n
\n \n

Connection to a database. \n More...

\n \n-

#include <connection.hxx>

\n+

#include <connection.hxx>

\n

\n Public Member Functions

 blob ()=default
 You can default-construct a blob, but it won't do anything useful.
 
 blob (blob &&)
\n \n \n \n \n \n@@ -334,15 +334,15 @@\n

Connection to a database.

\n

This is the first class to look at when you wish to work with a database through libpqxx. As per RAII principles, the connection opens during construction, and closes upon destruction. If the connection attempt fails, you will not get a connection object; the constructor will fail with a pqxx::broken_connection exception.

\n

When creating a connection, you can pass a connection URI or a postgres connection string, to specify the database server's address, a login username, and so on. If you don't, the connection will try to obtain them from certain environment variables. If those are not set either, the default is to try and connect to the local system's port 5432.

\n

Find more about connection strings here:

\n

https://www.postgresql.org/docs/current/libpq-connect.html#LIBPQ-CONNSTRING

\n

The variables are documented here:

\n

https://www.postgresql.org/docs/current/libpq-envars.html

\n-

To query or manipulate the database once connected, use one of the transaction classes (see pqxx/transaction_base.hxx) and perhaps also the transactor framework (see pqxx/transactor.hxx).

\n+

To query or manipulate the database once connected, use one of the transaction classes (see pqxx/transaction_base.hxx) and perhaps also the transactor framework (see pqxx/transactor.hxx).

\n

When a connection breaks, or fails to establish itself in the first place, you will typically get a broken_connection exception. This can happen at almost any point.

\n
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.
\n

Constructor & Destructor Documentation

\n \n

◆ connection() [1/5]

\n \n
\n@@ -2268,15 +2268,15 @@\n \n

\n Public Member Functions

 connection ()
 
 connection (char const options[])
 Connect to a database, using options string.
\n
\n \n
\n \n
The documentation for this class was generated from the following files:\n \n \n \n
\n
    \n"}, {"source1": "./usr/share/doc/libpqxx-doc/html/a01114.html", "source2": "./usr/share/doc/libpqxx-doc/html/a01114.html", "unified_diff": "@@ -65,15 +65,15 @@\n
    pqxx::connecting Class Reference
    \n
\n
\n \n

An ongoing, non-blocking stepping stone to a connection. \n More...

\n \n-

#include <connection.hxx>

\n+

#include <connection.hxx>

\n \n \n \n \n \n \n@@ -396,15 +396,15 @@\n
\n \n

Should we currently wait to be able to write to the socket?

\n \n
\n \n
The documentation for this class was generated from the following file:\n \n \n \n
\n
    \n
  • pqxx
  • connecting
  • \n"}, {"source1": "./usr/share/doc/libpqxx-doc/html/a01118.html", "source2": "./usr/share/doc/libpqxx-doc/html/a01118.html", "unified_diff": "@@ -66,15 +66,15 @@\n
    pqxx::cursor_base Class Reference
    \n
\n
\n \n

Common definitions for cursor types. \n More...

\n \n-

#include <cursor.hxx>

\n+

#include <cursor.hxx>

\n

\n Public Member Functions

 connecting (zview connection_string=""_zv)
 Start connecting.
 
 connecting (connecting const &)=delete
\n \n \n \n@@ -517,15 +517,15 @@\n \n

\n Public Types

enum  access_policy { forward_only\n , random_access\n }
 Cursor access-pattern policy. More...
\n
\n \n
\n \n
The documentation for this class was generated from the following files:\n \n \n \n
\n
    \n"}, {"source1": "./usr/share/doc/libpqxx-doc/html/a01122.html", "source2": "./usr/share/doc/libpqxx-doc/html/a01122.html", "unified_diff": "@@ -66,15 +66,15 @@\n
    pqxx::stateless_cursor< up, op > Class Template Reference
    \n
\n
\n \n

\"Stateless cursor\" class: easy API for retrieving parts of result sets \n More...

\n \n-

#include <cursor.hxx>

\n+

#include <cursor.hxx>

\n \n \n \n \n \n \n@@ -358,15 +358,15 @@\n
Note
This function is not const; it may need to scroll to find the size of the result set.
\n \n

Referenced by pqxx::stateless_cursor< up, op >::retrieve().

\n \n \n \n
The documentation for this class was generated from the following file:\n \n \n \n
\n
    \n
  • pqxx
  • stateless_cursor
  • \n"}, {"source1": "./usr/share/doc/libpqxx-doc/html/a01134.html", "source2": "./usr/share/doc/libpqxx-doc/html/a01134.html", "unified_diff": "@@ -65,15 +65,15 @@\n
    pqxx::dbtransaction Class Reference
    \n
\n
\n \n

Abstract transaction base class: bracket transactions on the database. \n More...

\n \n-

#include <dbtransaction.hxx>

\n+

#include <dbtransaction.hxx>

\n
\n Inheritance diagram for pqxx::dbtransaction:
\n
\n
\"Inheritance
\n \n \"\"\n \"\"\n@@ -421,15 +421,15 @@\n
\n \n

Begin transaction.

\n \n
\n
\n
The documentation for this class was generated from the following file:\n \n \n \n
\n
    \n
  • pqxx
  • dbtransaction
  • \n"}, {"source1": "./usr/share/doc/libpqxx-doc/html/a01138.html", "source2": "./usr/share/doc/libpqxx-doc/html/a01138.html", "unified_diff": "@@ -66,15 +66,15 @@\n
    pqxx::errorhandler Class Referenceabstract
    \n
\n
\n \n

Base class for error-handler callbacks. \n More...

\n \n-

#include <errorhandler.hxx>

\n+

#include <errorhandler.hxx>

\n
\n Inheritance diagram for pqxx::errorhandler:
\n
\n
\"Inheritance
\n \n \"\"\n \"\"\n@@ -290,15 +290,15 @@\n \n

\n Public Types

using size_type = result_size_type
 
using difference_type = result_difference_type
 
\n
\n \n
\n \n
The documentation for this class was generated from the following files:\n \n \n \n
\n
    \n"}, {"source1": "./usr/share/doc/libpqxx-doc/html/a01142.html", "source2": "./usr/share/doc/libpqxx-doc/html/a01142.html", "unified_diff": "@@ -65,15 +65,15 @@\n
    pqxx::quiet_errorhandler Class Reference
    \n
\n
\n \n

An error handler that suppresses any previously registered error handlers. \n More...

\n \n-

#include <errorhandler.hxx>

\n+

#include <errorhandler.hxx>

\n
\n Inheritance diagram for pqxx::quiet_errorhandler:
\n
\n
\"Inheritance
\n \n \"\"\n \"\"\n@@ -152,15 +152,15 @@\n

Revert to previous handling of error notices.

\n \n

Implements pqxx::errorhandler.

\n \n
\n
\n
The documentation for this class was generated from the following file:\n \n \n \n
\n
    \n
  • pqxx
  • quiet_errorhandler
  • \n"}, {"source1": "./usr/share/doc/libpqxx-doc/html/a01146.html", "source2": "./usr/share/doc/libpqxx-doc/html/a01146.html", "unified_diff": "@@ -65,15 +65,15 @@\n
    pqxx::failure Struct Reference
    \n
\n
\n \n

Run-time failure encountered by libpqxx, similar to std::runtime_error. \n More...

\n \n-

#include <except.hxx>

\n+

#include <except.hxx>

\n
\n Inheritance diagram for pqxx::failure:
\n
\n
\"Inheritance
\n \n \"\"\n \"\"\n@@ -183,15 +183,15 @@\n

Implementation of libpqxx exception classes.

\n

Copyright (c) 2000-2023, Jeroen T. Vermeulen.

\n

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.

\n \n
\n
\n
The documentation for this struct was generated from the following files:\n \n \n \n
\n
    \n"}, {"source1": "./usr/share/doc/libpqxx-doc/html/a01150.html", "source2": "./usr/share/doc/libpqxx-doc/html/a01150.html", "unified_diff": "@@ -65,15 +65,15 @@\n
    pqxx::broken_connection Struct Reference
    \n
\n
\n \n

Exception class for lost or failed backend connection. \n More...

\n \n-

#include <except.hxx>

\n+

#include <except.hxx>

\n
\n Inheritance diagram for pqxx::broken_connection:
\n
\n
\"Inheritance
\n \n \"\"\n \"\"\n@@ -151,15 +151,15 @@\n
\n
\n \n
\n
\n
The documentation for this struct was generated from the following files:\n
\n
\n \n
\n
    \n"}, {"source1": "./usr/share/doc/libpqxx-doc/html/a01154.html", "source2": "./usr/share/doc/libpqxx-doc/html/a01154.html", "unified_diff": "@@ -65,15 +65,15 @@\n
    pqxx::protocol_violation Struct Reference
    \n
\n
\n \n

Exception class for micommunication with the server. \n More...

\n \n-

#include <except.hxx>

\n+

#include <except.hxx>

\n
\n Inheritance diagram for pqxx::protocol_violation:
\n
\n
\"Inheritance
\n \n \"\"\n \"\"\n@@ -128,15 +128,15 @@\n \n \n
\n \n
\n
\n
The documentation for this struct was generated from the following files:\n
\n
\n \n
\n
    \n"}, {"source1": "./usr/share/doc/libpqxx-doc/html/a01158.html", "source2": "./usr/share/doc/libpqxx-doc/html/a01158.html", "unified_diff": "@@ -65,15 +65,15 @@\n
    pqxx::variable_set_to_null Struct Reference
    \n
\n
\n \n

The caller attempted to set a variable to null, which is not allowed. \n More...

\n \n-

#include <except.hxx>

\n+

#include <except.hxx>

\n
\n Inheritance diagram for pqxx::variable_set_to_null:
\n
\n
\"Inheritance
\n \n \"\"\n \"\"\n@@ -119,15 +119,15 @@\n \n \n
\n \n
\n
\n
The documentation for this struct was generated from the following files:\n
\n
\n \n
\n
    \n"}, {"source1": "./usr/share/doc/libpqxx-doc/html/a01162.html", "source2": "./usr/share/doc/libpqxx-doc/html/a01162.html", "unified_diff": "@@ -65,15 +65,15 @@\n
    pqxx::sql_error Class Reference
    \n
\n
\n \n

Exception class for failed queries. \n More...

\n \n-

#include <except.hxx>

\n+

#include <except.hxx>

\n
\n Inheritance diagram for pqxx::sql_error:
\n \n
\n
The documentation for this class was generated from the following files:\n
\n
\n \n
\n
    \n"}, {"source1": "./usr/share/doc/libpqxx-doc/html/a01166.html", "source2": "./usr/share/doc/libpqxx-doc/html/a01166.html", "unified_diff": "@@ -65,15 +65,15 @@\n
    pqxx::in_doubt_error Struct Reference
    \n
\n
\n \n

\"Help, I don't know whether transaction was committed successfully!\" \n More...

\n \n-

#include <except.hxx>

\n+

#include <except.hxx>

\n
\n Inheritance diagram for pqxx::in_doubt_error:
\n
\n
\"Inheritance
\n \n \"\"\n \"\"\n@@ -120,15 +120,15 @@\n \n \n
\n \n
\n
\n
The documentation for this struct was generated from the following files:\n
\n
\n \n
\n
    \n"}, {"source1": "./usr/share/doc/libpqxx-doc/html/a01170.html", "source2": "./usr/share/doc/libpqxx-doc/html/a01170.html", "unified_diff": "@@ -65,15 +65,15 @@\n
    pqxx::transaction_rollback Struct Reference
    \n
\n
\n \n

The backend saw itself forced to roll back the ongoing transaction. \n More...

\n \n-

#include <except.hxx>

\n+

#include <except.hxx>

\n
\n Inheritance diagram for pqxx::transaction_rollback:
\n
\n
\"Inheritance
\n \n \"\"\n \"\"\n@@ -156,15 +156,15 @@\n
\n \n

References pqxx::sql_error::sqlstate().

\n \n
\n
\n
The documentation for this struct was generated from the following files:\n
\n
\n \n
\n
    \n"}, {"source1": "./usr/share/doc/libpqxx-doc/html/a01174.html", "source2": "./usr/share/doc/libpqxx-doc/html/a01174.html", "unified_diff": "@@ -65,15 +65,15 @@\n
    pqxx::serialization_failure Struct Reference
    \n
\n
\n \n

Transaction failed to serialize. Please retry it. \n More...

\n \n-

#include <except.hxx>

\n+

#include <except.hxx>

\n
\n Inheritance diagram for pqxx::serialization_failure:
\n
\n
\"Inheritance
\n \n \"\"\n \"\"\n@@ -157,15 +157,15 @@\n
\n \n

References pqxx::sql_error::sqlstate().

\n \n
\n
\n
The documentation for this struct was generated from the following files:\n
\n
\n \n
\n
    \n"}, {"source1": "./usr/share/doc/libpqxx-doc/html/a01178.html", "source2": "./usr/share/doc/libpqxx-doc/html/a01178.html", "unified_diff": "@@ -65,15 +65,15 @@\n
    pqxx::statement_completion_unknown Struct Reference
    \n
\n
\n \n

We can't tell whether our last statement succeeded. \n More...

\n \n-

#include <except.hxx>

\n+

#include <except.hxx>

\n
\n Inheritance diagram for pqxx::statement_completion_unknown:
\n
\n
\"Inheritance
\n \n \"\"\n \"\"\n@@ -155,15 +155,15 @@\n
\n \n

References pqxx::sql_error::sqlstate().

\n \n
\n
\n
The documentation for this struct was generated from the following files:\n
\n
\n \n
\n
    \n"}, {"source1": "./usr/share/doc/libpqxx-doc/html/a01182.html", "source2": "./usr/share/doc/libpqxx-doc/html/a01182.html", "unified_diff": "@@ -65,15 +65,15 @@\n
    pqxx::deadlock_detected Struct Reference
    \n
\n
\n \n

The ongoing transaction has deadlocked. Retrying it may help. \n More...

\n \n-

#include <except.hxx>

\n+

#include <except.hxx>

\n
\n Inheritance diagram for pqxx::deadlock_detected:
\n
\n
\"Inheritance
\n \n \"\"\n \"\"\n@@ -155,15 +155,15 @@\n
\n \n

References pqxx::sql_error::sqlstate().

\n \n
\n
\n
The documentation for this struct was generated from the following files:\n
\n
\n \n
\n
    \n"}, {"source1": "./usr/share/doc/libpqxx-doc/html/a01186.html", "source2": "./usr/share/doc/libpqxx-doc/html/a01186.html", "unified_diff": "@@ -65,15 +65,15 @@\n
    pqxx::internal_error Struct Reference
    \n
\n
\n \n

Internal error in libpqxx library. \n More...

\n \n-

#include <except.hxx>

\n+

#include <except.hxx>

\n
\n Inheritance diagram for pqxx::internal_error:
\n
\n
\"Inheritance
\n \n \"\"\n \"\"\n@@ -114,15 +114,15 @@\n \n \n
\n \n
\n
\n
The documentation for this struct was generated from the following files:\n
\n
\n \n
\n
    \n"}, {"source1": "./usr/share/doc/libpqxx-doc/html/a01190.html", "source2": "./usr/share/doc/libpqxx-doc/html/a01190.html", "unified_diff": "@@ -65,15 +65,15 @@\n
    pqxx::usage_error Struct Reference
    \n
\n
\n \n

Error in usage of libpqxx library, similar to std::logic_error. \n More...

\n \n-

#include <except.hxx>

\n+

#include <except.hxx>

\n
\n Inheritance diagram for pqxx::usage_error:
\n
\n
\"Inheritance
\n \n \"\"\n \"\"\n@@ -114,15 +114,15 @@\n \n \n
\n \n
\n
\n
The documentation for this struct was generated from the following files:\n
\n
\n \n
\n
    \n"}, {"source1": "./usr/share/doc/libpqxx-doc/html/a01194.html", "source2": "./usr/share/doc/libpqxx-doc/html/a01194.html", "unified_diff": "@@ -65,15 +65,15 @@\n
    pqxx::argument_error Struct Reference
    \n
\n
\n \n

Invalid argument passed to libpqxx, similar to std::invalid_argument. \n More...

\n \n-

#include <except.hxx>

\n+

#include <except.hxx>

\n
\n Inheritance diagram for pqxx::argument_error:
\n
\n
\"Inheritance
\n \n \"\"\n \"\"\n@@ -116,15 +116,15 @@\n \n \n
\n \n
\n
\n
The documentation for this struct was generated from the following files:\n
\n
\n \n
\n
    \n"}, {"source1": "./usr/share/doc/libpqxx-doc/html/a01198.html", "source2": "./usr/share/doc/libpqxx-doc/html/a01198.html", "unified_diff": "@@ -65,15 +65,15 @@\n
    pqxx::conversion_error Struct Reference
    \n
\n
\n \n

Value conversion failed, e.g. when converting \"Hello\" to int. \n More...

\n \n-

#include <except.hxx>

\n+

#include <except.hxx>

\n
\n Inheritance diagram for pqxx::conversion_error:
\n
\n
\"Inheritance
\n \n \"\"\n \"\"\n@@ -120,15 +120,15 @@\n \n \n
\n \n
\n
\n
The documentation for this struct was generated from the following files:\n
\n
\n \n
\n
    \n"}, {"source1": "./usr/share/doc/libpqxx-doc/html/a01202.html", "source2": "./usr/share/doc/libpqxx-doc/html/a01202.html", "unified_diff": "@@ -65,15 +65,15 @@\n
    pqxx::unexpected_null Struct Reference
    \n
\n
\n \n

Could not convert null value: target type does not support null. \n More...

\n \n-

#include <except.hxx>

\n+

#include <except.hxx>

\n
\n Inheritance diagram for pqxx::unexpected_null:
\n
\n
\"Inheritance
\n \n \"\"\n \"\"\n@@ -121,15 +121,15 @@\n \n \n
\n \n
\n
\n
The documentation for this struct was generated from the following files:\n
\n
\n \n
\n
    \n"}, {"source1": "./usr/share/doc/libpqxx-doc/html/a01206.html", "source2": "./usr/share/doc/libpqxx-doc/html/a01206.html", "unified_diff": "@@ -65,15 +65,15 @@\n
    pqxx::conversion_overrun Struct Reference
    \n
\n
\n \n

Could not convert value to string: not enough buffer space. \n More...

\n \n-

#include <except.hxx>

\n+

#include <except.hxx>

\n
\n Inheritance diagram for pqxx::conversion_overrun:
\n
\n
\"Inheritance
\n \n \"\"\n \"\"\n@@ -121,15 +121,15 @@\n \n \n
\n \n
\n
\n
The documentation for this struct was generated from the following files:\n
\n
\n \n
\n
    \n"}, {"source1": "./usr/share/doc/libpqxx-doc/html/a01210.html", "source2": "./usr/share/doc/libpqxx-doc/html/a01210.html", "unified_diff": "@@ -65,15 +65,15 @@\n
    pqxx::range_error Struct Reference
    \n
\n
\n \n

Something is out of range, similar to std::out_of_range. \n More...

\n \n-

#include <except.hxx>

\n+

#include <except.hxx>

\n
\n Inheritance diagram for pqxx::range_error:
\n
\n
\"Inheritance
\n \n \"\"\n \"\"\n@@ -118,15 +118,15 @@\n \n \n
\n \n
\n
\n
The documentation for this struct was generated from the following files:\n
\n
\n \n
\n
    \n"}, {"source1": "./usr/share/doc/libpqxx-doc/html/a01214.html", "source2": "./usr/share/doc/libpqxx-doc/html/a01214.html", "unified_diff": "@@ -65,15 +65,15 @@\n
    pqxx::unexpected_rows Struct Reference
    \n
\n
\n \n

Query returned an unexpected number of rows. \n More...

\n \n-

#include <except.hxx>

\n+

#include <except.hxx>

\n
\n Inheritance diagram for pqxx::unexpected_rows:
\n
\n
\"Inheritance
\n \n \"\"\n \"\"\n@@ -121,15 +121,15 @@\n \n \n
\n \n
\n
\n
The documentation for this struct was generated from the following file:\n
\n
\n \n
\n
    \n
  • pqxx
  • unexpected_rows
  • \n"}, {"source1": "./usr/share/doc/libpqxx-doc/html/a01218.html", "source2": "./usr/share/doc/libpqxx-doc/html/a01218.html", "unified_diff": "@@ -65,15 +65,15 @@\n
    pqxx::feature_not_supported Struct Reference
    \n
\n
\n \n

Database feature not supported in current setup. \n More...

\n \n-

#include <except.hxx>

\n+

#include <except.hxx>

\n
\n Inheritance diagram for pqxx::feature_not_supported:
\n
\n
\"Inheritance
\n \n \"\"\n \"\"\n@@ -148,15 +148,15 @@\n \n \n
\n \n
\n
\n
The documentation for this struct was generated from the following file:\n
\n
\n \n
\n
    \n
  • pqxx
  • feature_not_supported
  • \n"}, {"source1": "./usr/share/doc/libpqxx-doc/html/a01222.html", "source2": "./usr/share/doc/libpqxx-doc/html/a01222.html", "unified_diff": "@@ -65,15 +65,15 @@\n
    pqxx::data_exception Struct Reference
    \n
\n
\n \n

Error in data provided to SQL statement. \n More...

\n \n-

#include <except.hxx>

\n+

#include <except.hxx>

\n
\n Inheritance diagram for pqxx::data_exception:
\n
\n
\"Inheritance
\n \n \"\"\n \"\"\n@@ -148,15 +148,15 @@\n \n \n
\n \n
\n
\n
The documentation for this struct was generated from the following file:\n
\n
\n \n
\n
\n
\n \n-

#include <except.hxx>

\n+

#include <except.hxx>

\n
\n Inheritance diagram for pqxx::integrity_constraint_violation:
\n
\n
\"Inheritance
\n \n \"\"\n \"\"\n@@ -153,15 +153,15 @@\n \n \n
\n \n
\n
\n
The documentation for this struct was generated from the following file:\n
\n
\n \n
\n
\n
\n \n-

#include <except.hxx>

\n+

#include <except.hxx>

\n
\n Inheritance diagram for pqxx::restrict_violation:
\n
\n
\"Inheritance
\n \n \"\"\n \"\"\n@@ -148,15 +148,15 @@\n \n \n
\n \n
\n
\n
The documentation for this struct was generated from the following file:\n
\n
\n \n
\n
\n
\n \n-

#include <except.hxx>

\n+

#include <except.hxx>

\n
\n Inheritance diagram for pqxx::not_null_violation:
\n
\n
\"Inheritance
\n \n \"\"\n \"\"\n@@ -148,15 +148,15 @@\n \n \n
\n \n
\n
\n
The documentation for this struct was generated from the following file:\n
\n
\n \n
\n
\n
\n \n-

#include <except.hxx>

\n+

#include <except.hxx>

\n
\n Inheritance diagram for pqxx::foreign_key_violation:
\n
\n
\"Inheritance
\n \n \"\"\n \"\"\n@@ -148,15 +148,15 @@\n \n \n
\n \n
\n
\n
The documentation for this struct was generated from the following file:\n
\n
\n \n
\n
\n
\n \n-

#include <except.hxx>

\n+

#include <except.hxx>

\n
\n Inheritance diagram for pqxx::unique_violation:
\n
\n
\"Inheritance
\n \n \"\"\n \"\"\n@@ -148,15 +148,15 @@\n \n \n
\n \n
\n
\n
The documentation for this struct was generated from the following file:\n
\n
\n \n
\n
\n
\n \n-

#include <except.hxx>

\n+

#include <except.hxx>

\n
\n Inheritance diagram for pqxx::check_violation:
\n
\n
\"Inheritance
\n \n \"\"\n \"\"\n@@ -148,15 +148,15 @@\n \n \n
\n \n
\n
\n
The documentation for this struct was generated from the following file:\n
\n
\n \n
\n
\n
\n \n-

#include <except.hxx>

\n+

#include <except.hxx>

\n
\n Inheritance diagram for pqxx::invalid_cursor_state:
\n
\n
\"Inheritance
\n \n \"\"\n \"\"\n@@ -143,15 +143,15 @@\n \n \n
\n \n
\n
\n
The documentation for this struct was generated from the following file:\n
\n
\n \n
\n
\n
\n \n-

#include <except.hxx>

\n+

#include <except.hxx>

\n
\n Inheritance diagram for pqxx::invalid_sql_statement_name:
\n
\n
\"Inheritance
\n \n \"\"\n \"\"\n@@ -143,15 +143,15 @@\n \n \n
\n \n
\n
\n
The documentation for this struct was generated from the following file:\n
\n
\n \n
\n
\n
\n \n-

#include <except.hxx>

\n+

#include <except.hxx>

\n
\n Inheritance diagram for pqxx::invalid_cursor_name:
\n
\n
\"Inheritance
\n \n \"\"\n \"\"\n@@ -143,15 +143,15 @@\n \n \n
\n \n
\n
\n
The documentation for this struct was generated from the following file:\n
\n
\n \n
\n
\n
pqxx::syntax_error Struct Reference
\n
\n
\n \n-

#include <except.hxx>

\n+

#include <except.hxx>

\n
\n Inheritance diagram for pqxx::syntax_error:
\n
\n
\"Inheritance
\n \n \"\"\n \"\"\n@@ -179,15 +179,15 @@\n
\n \n

Approximate position in string where error occurred, or -1 if unknown.

\n \n
\n
\n
The documentation for this struct was generated from the following file:\n
\n
\n \n
\n
\n
\n \n-

#include <except.hxx>

\n+

#include <except.hxx>

\n
\n Inheritance diagram for pqxx::undefined_column:
\n
\n
\"Inheritance
\n \n \"\"\n \"\"\n@@ -155,15 +155,15 @@\n \n \n
\n \n
\n
\n
The documentation for this struct was generated from the following file:\n
\n
\n \n
\n
\n
\n \n-

#include <except.hxx>

\n+

#include <except.hxx>

\n
\n Inheritance diagram for pqxx::undefined_function:
\n
\n
\"Inheritance
\n \n \"\"\n \"\"\n@@ -155,15 +155,15 @@\n \n \n
\n \n
\n
\n
The documentation for this struct was generated from the following file:\n
\n
\n \n
\n
\n
\n \n-

#include <except.hxx>

\n+

#include <except.hxx>

\n
\n Inheritance diagram for pqxx::undefined_table:
\n
\n
\"Inheritance
\n \n \"\"\n \"\"\n@@ -155,15 +155,15 @@\n \n \n
\n \n
\n
\n
The documentation for this struct was generated from the following file:\n
\n
\n \n
\n
\n
\n \n-

#include <except.hxx>

\n+

#include <except.hxx>

\n
\n Inheritance diagram for pqxx::insufficient_privilege:
\n
\n
\"Inheritance
\n \n \"\"\n \"\"\n@@ -143,15 +143,15 @@\n \n \n
\n \n
\n
\n
The documentation for this struct was generated from the following file:\n
\n
\n \n
\n
    \n
  • pqxx
  • insufficient_privilege
  • \n"}, {"source1": "./usr/share/doc/libpqxx-doc/html/a01282.html", "source2": "./usr/share/doc/libpqxx-doc/html/a01282.html", "unified_diff": "@@ -65,15 +65,15 @@\n
    pqxx::insufficient_resources Struct Reference
    \n
\n
\n \n

Resource shortage on the server. \n More...

\n \n-

#include <except.hxx>

\n+

#include <except.hxx>

\n
\n Inheritance diagram for pqxx::insufficient_resources:
\n
\n
\"Inheritance
\n \n \"\"\n \"\"\n@@ -152,15 +152,15 @@\n \n \n
\n \n
\n
\n
The documentation for this struct was generated from the following file:\n
\n
\n \n
\n
\n
\n \n-

#include <except.hxx>

\n+

#include <except.hxx>

\n
\n Inheritance diagram for pqxx::disk_full:
\n
\n
\"Inheritance
\n \n \"\"\n \"\"\n@@ -148,15 +148,15 @@\n \n \n
\n \n
\n
\n
The documentation for this struct was generated from the following file:\n
\n \n \n
\n
\n
\n \n-

#include <except.hxx>

\n+

#include <except.hxx>

\n
\n Inheritance diagram for pqxx::out_of_memory:
\n
\n
\"Inheritance
\n \n \"\"\n \"\"\n@@ -148,15 +148,15 @@\n \n \n
\n \n
\n
\n
The documentation for this struct was generated from the following file:\n \n \n \n
\n
\n
\n \n-

#include <except.hxx>

\n+

#include <except.hxx>

\n
\n Inheritance diagram for pqxx::too_many_connections:
\n
\n
\"Inheritance
\n \n \"\"\n \"\"\n@@ -121,15 +121,15 @@\n \n \n
\n \n
\n
\n
The documentation for this struct was generated from the following file:\n \n \n \n
\n
\n
\n \n

PL/pgSQL error. \n More...

\n \n-

#include <except.hxx>

\n+

#include <except.hxx>

\n
\n Inheritance diagram for pqxx::plpgsql_error:
\n
\n
\"Inheritance
\n \n \"\"\n \"\"\n@@ -155,15 +155,15 @@\n \n \n
\n \n
\n
\n
The documentation for this struct was generated from the following file:\n \n \n \n
\n
\n
\n \n

Exception raised in PL/pgSQL procedure. \n More...

\n \n-

#include <except.hxx>

\n+

#include <except.hxx>

\n
\n Inheritance diagram for pqxx::plpgsql_raise:
\n
\n
\"Inheritance
\n \n \"\"\n \"\"\n@@ -153,15 +153,15 @@\n \n \n
\n \n
\n
\n
The documentation for this struct was generated from the following file:\n \n \n \n
\n
\n
\n \n-

#include <except.hxx>

\n+

#include <except.hxx>

\n
\n Inheritance diagram for pqxx::plpgsql_no_data_found:
\n
\n
\"Inheritance
\n \n \"\"\n \"\"\n@@ -148,15 +148,15 @@\n \n \n
\n \n
\n
\n
The documentation for this struct was generated from the following file:\n \n \n \n
\n
\n
\n \n-

#include <except.hxx>

\n+

#include <except.hxx>

\n
\n Inheritance diagram for pqxx::plpgsql_too_many_rows:
\n
\n
\"Inheritance
\n \n \"\"\n \"\"\n@@ -148,15 +148,15 @@\n \n \n
\n \n
\n
\n
The documentation for this struct was generated from the following file:\n \n \n \n
\n
\n
\n \n

Reference to a field in a result set. \n More...

\n \n-

#include <field.hxx>

\n+

#include <field.hxx>

\n
\n Inheritance diagram for pqxx::field:
\n
\n
\"Inheritance
\n \n \"\"\n \"\"\n@@ -1089,15 +1089,15 @@\n \n
\n

You'd expect this to be unsigned, but due to the way reverse iterators are related to regular iterators, it must be allowed to underflow to -1.

\n \n
\n
\n
The documentation for this class was generated from the following files:\n \n \n \n
\n
\n
pqxx::field_streambuf< CHAR, TRAITS > Class Template Reference
\n \n
\n \n-

#include <field.hxx>

\n+

#include <field.hxx>

\n
\n Inheritance diagram for pqxx::field_streambuf< CHAR, TRAITS >:
\n
\n
\"Inheritance
\n \n \"\"\n \"\"\n@@ -421,15 +421,15 @@\n \n \n
\n \n
\n
\n
The documentation for this class was generated from the following file:\n \n \n \n
\n
\n
\n \n

Input stream that gets its data from a result field. \n More...

\n \n-

#include <field.hxx>

\n+

#include <field.hxx>

\n
\n Inheritance diagram for pqxx::basic_fieldstream< CHAR, TRAITS >:
\n
\n
\"Inheritance
\n \n \"\"\n \"\"\n@@ -209,15 +209,15 @@\n \n \n
\n \n
\n
\n
The documentation for this class was generated from the following file:\n \n \n \n
\n
\n
\n \n

Identity of a large object. \n More...

\n \n-

#include <largeobject.hxx>

\n+

#include <largeobject.hxx>

\n
\n Inheritance diagram for pqxx::largeobject:
\n
\n
\"Inheritance
\n \n \"\"\n \"\"\n@@ -618,15 +618,15 @@\n

References pqxx::transaction_base::conn(), and pqxx::oid_none.

\n \n

Referenced by pqxx::largeobjectaccess::to_file().

\n \n
\n
\n
The documentation for this class was generated from the following files:\n \n \n \n
\n
\n
\n \n

Accessor for large object's contents. \n More...

\n \n-

#include <largeobject.hxx>

\n+

#include <largeobject.hxx>

\n
\n Inheritance diagram for pqxx::largeobjectaccess:
\n
\n
\"Inheritance
\n \n \"\"\n \"\"\n@@ -1183,15 +1183,15 @@\n
std::ios::in | std::ios::out | std::ios::binary}
\n
\n

Default open mode: in, out, binary.

\n \n
\n \n
The documentation for this class was generated from the following files:\n \n \n \n
\n
\n
\n \n

Streambuf to use large objects in standard I/O streams. \n More...

\n \n-

#include <largeobject.hxx>

\n+

#include <largeobject.hxx>

\n
\n Inheritance diagram for pqxx::largeobject_streambuf< CHAR, TRAITS >:
\n
\n
\"Inheritance
\n \n \"\"\n \"\"\n@@ -613,15 +613,15 @@\n
std::ios::in | std::ios::out | std::ios::binary}
\n
\n

Default open mode: in, out, binary.

\n \n
\n \n
The documentation for this class was generated from the following file:\n \n \n \n
\n
\n
\n \n

Input stream that gets its data from a large object. \n More...

\n \n-

#include <largeobject.hxx>

\n+

#include <largeobject.hxx>

\n
\n Inheritance diagram for pqxx::basic_ilostream< CHAR, TRAITS >:
\n
\n
\"Inheritance
\n \n \"\"\n \"\"\n@@ -289,15 +289,15 @@\n \n \n

References pqxx::binary.

\n \n
\n
\n
The documentation for this class was generated from the following file:\n \n \n \n
\n
\n
\n \n

Output stream that writes data back to a large object. \n More...

\n \n-

#include <largeobject.hxx>

\n+

#include <largeobject.hxx>

\n
\n Inheritance diagram for pqxx::basic_olostream< CHAR, TRAITS >:
\n
\n
\"Inheritance
\n \n \"\"\n \"\"\n@@ -310,15 +310,15 @@\n \n \n
\n \n
\n
\n
The documentation for this class was generated from the following file:\n \n \n \n
\n
\n
\n \n

Stream that reads and writes a large object. \n More...

\n \n-

#include <largeobject.hxx>

\n+

#include <largeobject.hxx>

\n
\n Inheritance diagram for pqxx::basic_lostream< CHAR, TRAITS >:
\n
\n
\"Inheritance
\n \n \"\"\n \"\"\n@@ -315,15 +315,15 @@\n \n \n
\n \n
\n
\n
The documentation for this class was generated from the following file:\n \n \n \n
\n
\n
\n \n

Simple \"transaction\" class offering no transactional integrity. \n More...

\n \n-

#include <nontransaction.hxx>

\n+

#include <nontransaction.hxx>

\n
\n Inheritance diagram for pqxx::nontransaction:
\n
\n
\"Inheritance
\n \n \"\"\n \"\"\n@@ -360,15 +360,15 @@\n \n \n
\n \n
\n
\n
The documentation for this class was generated from the following file:\n \n \n \n
\n
\n
pqxx::notification_receiver Class Referenceabstract
\n \n
\n \n-

#include <notification.hxx>

\n+

#include <notification.hxx>

\n \n \n \n \n \n \n@@ -307,15 +307,15 @@\n
\n \n

Register the receiver with a connection.

\n \n
\n \n
The documentation for this class was generated from the following files:\n \n \n \n
\n
\n
\n \n

Generate parameter placeholders for use in an SQL statement. \n More...

\n \n-

#include <params.hxx>

\n+

#include <params.hxx>

\n

\n Public Member Functions

 notification_receiver (connection &c, std::string_view channel)
 Register the receiver with a connection.
 
 notification_receiver (notification_receiver const &)=delete
\n \n \n \n \n \n@@ -253,15 +253,15 @@\n

Maximum number of parameters we support.

\n \n

Referenced by pqxx::placeholders< COUNTER >::next().

\n \n \n \n
The documentation for this class was generated from the following file:\n \n \n \n
\n
\n
\n \n

Build a parameter list for a parameterised or prepared statement. \n More...

\n \n-

#include <params.hxx>

\n+

#include <params.hxx>

\n

\n Public Member Functions

 placeholders ()
 
constexpr zview view () const &noexcept
 Read an ephemeral version of the current placeholder text.
\n \n \n \n \n \n@@ -551,15 +551,15 @@\n

Unlike size(), this is not yet noexcept. That's because C++17's std::vector does not have a ssize() member function. These member functions are noexcept, but std::size() and std::ssize() are not.

\n \n

References pqxx::internal::ssize().

\n \n \n \n
The documentation for this class was generated from the following files:\n \n \n \n
\n
\n
\n \n

Processes several queries in FIFO manner, optimized for high throughput. \n More...

\n \n-

#include <pipeline.hxx>

\n+

#include <pipeline.hxx>

\n
\n Inheritance diagram for pqxx::pipeline:
\n
\n
\"Inheritance
\n \n \"\"\n \"\"\n@@ -605,15 +605,15 @@\n \n

Retrieve result for given query.

\n

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.
\n \n
\n
\n
The documentation for this class was generated from the following files:\n \n \n \n
\n
\n
\n \n

An unlimited boundary value to a pqxx::range. \n More...

\n \n-

#include <range.hxx>

\n+

#include <range.hxx>

\n

\n Public Member Functions

 params ()=default
 
template<typename... Args>
constexpr params (Args &&...args)
\n \n \n \n \n \n@@ -138,15 +138,15 @@\n \n

\n Public Member Functions

template<typename TYPE >
constexpr bool extends_down_to (TYPE const &) const noexcept
 
template<typename TYPE >
\n
\n \n
\n \n
The documentation for this struct was generated from the following file:\n \n \n \n
\n
\n
\n \n

An inclusive boundary value to a pqxx::range. \n More...

\n \n-

#include <range.hxx>

\n+

#include <range.hxx>

\n \n \n \n \n \n \n@@ -231,15 +231,15 @@\n \n

\n Public Member Functions

 inclusive_bound ()=delete
 
constexpr inclusive_bound (TYPE const &value)
 
\n
\n \n
\n \n
The documentation for this class was generated from the following file:\n \n \n \n
\n
\n
\n \n

An exclusive boundary value to a pqxx::range. \n More...

\n \n-

#include <range.hxx>

\n+

#include <range.hxx>

\n \n \n \n \n \n \n@@ -231,15 +231,15 @@\n \n

\n Public Member Functions

 exclusive_bound ()=delete
 
constexpr exclusive_bound (TYPE const &value)
 
\n
\n \n
\n \n
The documentation for this class was generated from the following file:\n \n \n \n
\n
\n
\n \n

A range boundary value. \n More...

\n \n-

#include <range.hxx>

\n+

#include <range.hxx>

\n \n \n \n \n \n \n@@ -582,15 +582,15 @@\n

Return bound value, or nullptr if it's not limited.

\n \n

Referenced by pqxx::range_bound< TYPE >::extends_down_to(), pqxx::range_bound< TYPE >::extends_up_to(), pqxx::range_bound< TYPE >::operator==(), and pqxx::range< TYPE >::range().

\n \n \n \n
The documentation for this class was generated from the following file:\n \n \n \n
\n
\n
\n \n

A C++ equivalent to PostgreSQL's range types. \n More...

\n \n-

#include <range.hxx>

\n+

#include <range.hxx>

\n

\n Public Member Functions

 range_bound ()=delete
 
constexpr range_bound (no_bound) noexcept
 
\n \n \n \n \n \n@@ -568,15 +568,15 @@\n
\n \n

Referenced by pqxx::string_traits< range< TYPE > >::into_buf(), and pqxx::range< TYPE >::operator&().

\n \n
\n \n
The documentation for this class was generated from the following file:\n \n \n \n
\n
\n
\n \n

String conversions for a range type. \n More...

\n \n-

#include <range.hxx>

\n+

#include <range.hxx>

\n

\n Public Member Functions

constexpr range (range_bound< TYPE > lower, range_bound< TYPE > upper)
 Create a range.
 
constexpr range () noexcept(noexcept(exclusive_bound< TYPE >{TYPE{}}))
\n \n \n \n \n \n@@ -232,15 +232,15 @@\n \n

\n Static Public Member Functions

static zview to_buf (char *begin, char *end, range< TYPE > const &value)
 
static char * into_buf (char *begin, char *end, range< TYPE > const &value)
 
\n
\n \n
\n \n
The documentation for this struct was generated from the following file:\n \n \n \n
\n
\n
\n \n

A range type does not have an innate null value. \n More...

\n \n-

#include <range.hxx>

\n+

#include <range.hxx>

\n
\n Inheritance diagram for pqxx::nullness< range< TYPE > >:
\n
\n
\"Inheritance
\n \n \"\"\n \"\"\n@@ -96,15 +96,15 @@\n  Are all values of this type null?
\n  \n \n

Detailed Description

\n
template<typename TYPE>
\n struct pqxx::nullness< range< TYPE > >

A range type does not have an innate null value.

\n

The documentation for this struct was generated from the following file:\n
\n
\n \n
\n
\n
\n \n

Result set containing data returned by a query or command. \n More...

\n \n-

#include <result.hxx>

\n+

#include <result.hxx>

\n \n \n \n \n \n \n@@ -1417,15 +1417,15 @@\n \n

\n Public Types

using size_type = result_size_type
 
using difference_type = result_difference_type
 
\n
\n \n
\n \n
The documentation for this class was generated from the following files:\n \n \n \n
\n
\n
\n \n

Helper base class for the robusttransaction class template. \n More...

\n \n-

#include <robusttransaction.hxx>

\n+

#include <robusttransaction.hxx>

\n
\n Inheritance diagram for pqxx::internal::basic_robusttransaction:
\n
\n
\"Inheritance
\n \n \"\"\n \"\"\n@@ -410,15 +410,15 @@\n \n \n
\n \n
\n
\n
The documentation for this class was generated from the following files:\n \n \n \n
\n
\n
The documentation for this class was generated from the following files:\n \n \n \n
\n
\n
\n \n

Reverse iterator for a row. Use as row::const_reverse_iterator. \n More...

\n \n-

#include <row.hxx>

\n+

#include <row.hxx>

\n
\n Inheritance diagram for pqxx::const_reverse_row_iterator:
\n
\n
\"Inheritance
\n \n \"\"\n \"\"\n@@ -867,15 +867,15 @@\n \n \n
\n \n
\n
\n
The documentation for this class was generated from the following files:\n \n \n \n
\n
\n
\n \n

Traits describing a type's \"null value,\" if any. \n More...

\n \n-

#include <strconv.hxx>

\n+

#include <strconv.hxx>

\n \n \n \n \n \n \n@@ -208,15 +208,15 @@\n
\n \n

Does this type have a null value?

\n \n
\n \n
The documentation for this struct was generated from the following file:\n \n \n \n
\n
\n
\n \n

Nullness traits describing a type which does not have a null value. \n More...

\n \n-

#include <strconv.hxx>

\n+

#include <strconv.hxx>

\n
\n Inheritance diagram for pqxx::no_null< TYPE >:
\n
\n
\"Inheritance
\n \n \"\"\n \"\"\n@@ -196,15 +196,15 @@\n

For example, a pointer can equal nullptr, which makes a very natural representation of an SQL null value. For such types, the code sometimes needs to make special allowances.

\n

for most types, such as int or std::string, there is no built-in null. If you want to represent an SQL null value for such a type, you would have to wrap it in something that does have a null value. For example, you could use std::optional<int> for \"either an @c int or a\n null value.\"

\n \n
\n
\n
The documentation for this struct was generated from the following file:\n \n \n \n
\n
\n
\n \n

Traits class for use in string conversions. \n More...

\n \n-

#include <strconv.hxx>

\n+

#include <strconv.hxx>

\n

\n Static Public Member Functions

static bool is_null (TYPE const &value)
 Is value a null?
 
static TYPE null ()
\n \n \n \n \n \n@@ -330,15 +330,15 @@\n \n

Is conversion from TYPE to strings supported?

\n

When defining your own conversions, specialise this as true to indicate that your string traits support the conversions to strings.

\n \n \n \n
The documentation for this struct was generated from the following files:\n \n \n \n
\n
\n
\n \n

String traits for a forbidden type conversion. \n More...

\n \n-

#include <strconv.hxx>

\n+

#include <strconv.hxx>

\n
\n Inheritance diagram for pqxx::forbidden_conversion< TYPE >:
\n
\n
\"Inheritance
\n \n \"\"\n \"\"\n@@ -309,15 +309,15 @@\n \n

\n Static Public Member Functions

static zview to_buf (char *begin, char *end, TYPE const &value)
 Return a string_view representing value, plus terminating zero.
 
static char * into_buf (char *begin, char *end, TYPE const &value)
\n
\n \n
\n \n
The documentation for this struct was generated from the following file:\n \n \n \n
\n
\n
\n \n

You cannot convert a char to/from SQL. \n More...

\n \n-

#include <strconv.hxx>

\n+

#include <strconv.hxx>

\n
\n Inheritance diagram for pqxx::string_traits< char >:
\n
\n
\"Inheritance
\n \n \"\"\n \"\"\n@@ -102,15 +102,15 @@\n

Detailed Description

\n

You cannot convert a char to/from SQL.

\n

Converting this type may seem simple enough, but it's ambiguous: Did you mean the char value as a small integer? If so, did you mean it to be signed or unsigned? (The C++ Standard allows the system to implement char as either a signed type or an unsigned type.) Or were you thinking of a single-character string (and if so, using what encoding)? Or perhaps it's just a raw byte value?

\n

If you meant it as an integer, use an appropriate integral type such as int or short or unsigned int etc.

\n

If you wanted a single-character string, use std::string_view (or a similar type such as std::string).

\n

Or if you had a raw byte in mind, try std::basic_string_view<std::byte> instead.

\n

The documentation for this struct was generated from the following file:\n
\n
\n \n
\n
\n
\n \n

You cannot convert an unsigned char to/from SQL. \n More...

\n \n-

#include <strconv.hxx>

\n+

#include <strconv.hxx>

\n
\n Inheritance diagram for pqxx::string_traits< unsigned char >:
\n
\n
\"Inheritance
\n \n \"\"\n \"\"\n@@ -102,15 +102,15 @@\n

Detailed Description

\n

You cannot convert an unsigned char to/from SQL.

\n

Converting this type may seem simple enough, but it's ambiguous: Did you mean the char value as a small integer? Or were you thinking of a single-character string (and if so, using what encoding)? Or perhaps it's just a raw byte value?

\n

If you meant it as an integer, use an appropriate integral type such as int or short or unsigned int etc.

\n

If you wanted a single-character string, use std::string_view (or a similar type such as std::string).

\n

Or if you had a raw byte in mind, try std::basic_string_view<std::byte> instead.

\n

The documentation for this struct was generated from the following file:\n
\n
\n \n
\n
\n
\n \n

You cannot convert a signed char to/from SQL. \n More...

\n \n-

#include <strconv.hxx>

\n+

#include <strconv.hxx>

\n
\n Inheritance diagram for pqxx::string_traits< signed char >:
\n
\n
\"Inheritance
\n \n \"\"\n \"\"\n@@ -102,15 +102,15 @@\n

Detailed Description

\n

You cannot convert a signed char to/from SQL.

\n

Converting this type may seem simple enough, but it's ambiguous: Did you mean the value as a small integer? Or were you thinking of a single-character string (and if so, in what encoding)? Or perhaps it's just a raw byte value?

\n

If you meant it as an integer, use an appropriate integral type such as int or short etc.

\n

If you wanted a single-character string, use std::string_view (or a similar type such as std::string).

\n

Or if you had a raw byte in mind, try std::basic_string_view<std::byte> instead.

\n

The documentation for this struct was generated from the following file:\n
\n
\n \n
\n
\n
\n \n

You cannot convert a std::byte to/from SQL. \n More...

\n \n-

#include <strconv.hxx>

\n+

#include <strconv.hxx>

\n
\n Inheritance diagram for pqxx::string_traits< std::byte >:
\n
\n
\"Inheritance
\n \n \"\"\n \"\"\n@@ -100,15 +100,15 @@\n  \n \n

Detailed Description

\n

You cannot convert a std::byte to/from SQL.

\n

To convert a raw byte value, use a std::basic_string_view<std::byte>.

\n

For example, to convert a byte b from C++ to SQL, convert the value std::basic_string_view<std::byte>{&b, 1} instead.

\n

The documentation for this struct was generated from the following file:\n
\n
\n \n
\n
\n
\n \n

Nullness: Enums do not have an inherent null value. \n More...

\n \n-

#include <strconv.hxx>

\n+

#include <strconv.hxx>

\n
\n Inheritance diagram for pqxx::nullness< ENUM, std::enable_if_t< std::is_enum_v< ENUM > > >:
\n
\n
\"Inheritance
\n \n \"\"\n \"\"\n@@ -96,15 +96,15 @@\n  Are all values of this type null?
\n  \n \n

Detailed Description

\n
template<typename ENUM>
\n struct pqxx::nullness< ENUM, std::enable_if_t< std::is_enum_v< ENUM > > >

Nullness: Enums do not have an inherent null value.

\n

The documentation for this struct was generated from the following file:\n
\n
\n \n
\n
\n
\n \n

Helper class for defining enum conversions. \n More...

\n \n-

#include <strconv.hxx>

\n+

#include <strconv.hxx>

\n \n \n \n \n \n \n@@ -336,15 +336,15 @@\n \n

\n Public Types

using impl_type = std::underlying_type_t< ENUM >
 
using impl_traits = string_traits< impl_type >
 
\n
\n \n
\n \n
The documentation for this struct was generated from the following file:\n \n \n \n
\n
\n
\n \n

Stream data from the database. \n More...

\n \n-

#include <stream_from.hxx>

\n+

#include <stream_from.hxx>

\n
\n Inheritance diagram for pqxx::stream_from:
\n
\n
\"Inheritance
\n \n \"\"\n \"\"\n@@ -893,15 +893,15 @@\n

References pqxx::transaction_base::conn().

\n \n

Referenced by stream_from().

\n \n
\n
\n
The documentation for this class was generated from the following files:\n \n \n \n
\n
\n
\n \n

Efficiently write data directly to a database table. \n More...

\n \n-

#include <stream_to.hxx>

\n+

#include <stream_to.hxx>

\n
\n Inheritance diagram for pqxx::stream_to:
\n
\n
\"Inheritance
\n \n \"\"\n \"\"\n@@ -594,15 +594,15 @@\n \n

Insert values as a row.

\n

This is the recommended way of inserting data. Pass your field values, of any convertible type.

\n \n
\n
\n
The documentation for this class was generated from the following files:\n \n \n \n
\n
\n
\n \n

\"Transaction\" nested within another transaction \n More...

\n \n-

#include <subtransaction.hxx>

\n+

#include <subtransaction.hxx>

\n
\n Inheritance diagram for pqxx::subtransaction:
\n
\n
\"Inheritance
\n \n \"\"\n \"\"\n@@ -482,15 +482,15 @@\n \n \n
\n \n
\n
\n
The documentation for this class was generated from the following files:\n \n \n \n
\n
\n
\n \n

Interface definition (and common code) for \"transaction\" classes. \n More...

\n \n-

#include <transaction_base.hxx>

\n+

#include <transaction_base.hxx>

\n
\n Inheritance diagram for pqxx::transaction_base:
\n
\n
\"Inheritance
\n \n \"\"\n \"\"\n@@ -2294,15 +2294,15 @@\n \n \n
\n \n
\n
\n
The documentation for this class was generated from the following files:\n \n \n \n
\n
\n
\n \n

Base class for things that monopolise a transaction's attention. \n More...

\n \n-

#include <transaction_focus.hxx>

\n+

#include <transaction_focus.hxx>

\n
\n Inheritance diagram for pqxx::transaction_focus:
\n
\n
\"Inheritance
\n \n \"\"\n \"\"\n@@ -545,15 +545,15 @@\n \n \n
\n \n
\n
\n
The documentation for this class was generated from the following files:\n \n \n \n
\n
\n
\n \n

Marker for stream_from constructors: \"stream from table.\". \n More...

\n \n-

#include <types.hxx>

\n+

#include <types.hxx>

\n

Detailed Description

\n

Marker for stream_from constructors: \"stream from table.\".

\n
Deprecated:
Use stream_from::table() instead.
\n

The documentation for this struct was generated from the following file:\n
\n \n \n
\n
\n
\n \n

Marker for stream_from constructors: \"stream from query.\". \n More...

\n \n-

#include <types.hxx>

\n+

#include <types.hxx>

\n

Detailed Description

\n

Marker for stream_from constructors: \"stream from query.\".

\n
Deprecated:
Use stream_from::query() instead.
\n

The documentation for this struct was generated from the following file:\n
\n \n \n
\n
\n
\n \n

Descriptor of library's thread-safety model. \n More...

\n \n-

#include <util.hxx>

\n+

#include <util.hxx>

\n \n \n \n \n \n \n@@ -140,15 +140,15 @@\n

Is the underlying libpq build thread-safe?

\n \n

Referenced by pqxx::describe_thread_safety().

\n \n \n \n
The documentation for this struct was generated from the following file:\n \n \n \n
\n
\n
\n \n

Marker-type wrapper: zero-terminated std::string_view. \n More...

\n \n-

#include <zview.hxx>

\n+

#include <zview.hxx>

\n
\n Inheritance diagram for pqxx::zview:
\n
\n
\"Inheritance
\n \n \"\"\n \"\"\n@@ -399,15 +399,15 @@\n

Either a null pointer, or a zero-terminated text buffer.

\n \n

Referenced by pqxx::result::column_number(), pqxx::encrypt_password(), and pqxx::connection::encrypt_password().

\n \n
\n
\n
The documentation for this class was generated from the following file:\n \n \n \n
\n
\n \n \n

\n Public Attributes

bool safe_libpq = false
 Is the underlying libpq build thread-safe?
 
bool safe_kerberos = false

\n Directories

 doc
 
\n \n-\n+\n \n-\n+\n \n-\n+\n \n \n \n-\n+\n \n-\n+\n \n-\n+\n \n-\n+\n \n-\n+\n \n-\n+\n \n-\n+\n \n-\n+\n \n-\n+\n \n-\n+\n \n-\n+\n \n-\n+\n \n-\n+\n \n-\n+\n \n-\n+\n \n-\n+\n \n-\n+\n \n-\n+\n \n-\n+\n \n-\n+\n \n-\n+\n \n-\n+\n \n-\n+\n \n-\n+\n \n-\n+\n \n-\n+\n \n-\n+\n \n-\n+\n \n \n \n-\n+\n \n-\n+\n \n-\n+\n \n-\n+\n \n-\n+\n \n-\n+\n \n-\n+\n \n

\n Files

 array.hxx
 array.hxx
 
 binarystring.hxx
 binarystring.hxx
 
 blob.hxx
 blob.hxx
 
 composite.hxx
 
 config-internal-autotools.h
 config-internal-autotools.h
 
 config-internal-compiler.h
 config-internal-compiler.h
 
 config-public-autotools.h
 config-public-autotools.h
 
 config-public-compiler.h
 config-public-compiler.h
 
 config.h
 config.h
 
 connection.hxx
 connection.hxx
 
 cursor.hxx
 cursor.hxx
 
 dbtransaction.hxx
 dbtransaction.hxx
 
 errorhandler.hxx
 errorhandler.hxx
 
 except.hxx
 except.hxx
 
 field.hxx
 field.hxx
 
 isolation.hxx
 isolation.hxx
 
 largeobject.hxx
 largeobject.hxx
 
 nontransaction.hxx
 nontransaction.hxx
 
 notification.hxx
 notification.hxx
 
 params.hxx
 params.hxx
 
 pipeline.hxx
 pipeline.hxx
 
 prepared_statement.hxx
 prepared_statement.hxx
 
 range.hxx
 range.hxx
 
 result.hxx
 result.hxx
 
 robusttransaction.hxx
 robusttransaction.hxx
 
 row.hxx
 row.hxx
 
 separated_list.hxx
 separated_list.hxx
 
 strconv.hxx
 strconv.hxx
 
 stream_from.hxx
 stream_from.hxx
 
 stream_to.hxx
 stream_to.hxx
 
 subtransaction.hxx
 subtransaction.hxx
 
 time.hxx
 time.hxx
 
 transaction.hxx
 
 transaction_base.hxx
 transaction_base.hxx
 
 transaction_focus.hxx
 transaction_focus.hxx
 
 transactor.hxx
 transactor.hxx
 
 types.hxx
 types.hxx
 
 util.hxx
 util.hxx
 
 version.hxx
 version.hxx
 
 zview.hxx
 zview.hxx
 
\n
\n \n \n
\n
\n \n
\n
\n
\n
\n \n \n
\n
\n
pqxx-source.hxx
\n
\n
\n"}]}]}]}]}