aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--LICENSE2
-rw-r--r--Makefile.am1
-rwxr-xr-xbootstrap1
-rw-r--r--build/bootstrap.build1
-rw-r--r--build/bootstrap.make1
-rw-r--r--build/export.build1
-rw-r--r--build/export/libodb-pgsql/stub.make1
-rw-r--r--build/import/cli/LICENSE21
-rw-r--r--build/import/cli/cli-cxx.make1
-rw-r--r--build/import/cli/configuration-rules.make1
-rwxr-xr-xbuild/import/cli/configure1
-rw-r--r--build/import/cli/stub.make1
l---------build/import/libodb-pgsql/LICENSE1
-rw-r--r--build/import/libodb-pgsql/configuration-rules.make1
-rwxr-xr-xbuild/import/libodb-pgsql/configure1
-rw-r--r--build/import/libodb-pgsql/stub.make1
-rw-r--r--build/import/libodb/LICENSE12
-rw-r--r--build/import/libodb/configuration-rules.make1
-rwxr-xr-xbuild/import/libodb/configure1
-rw-r--r--build/import/libodb/stub.make1
-rw-r--r--build/import/libpq/LICENSE340
-rw-r--r--build/import/libpq/configuration-rules.make1
-rwxr-xr-xbuild/import/libpq/configure1
-rw-r--r--build/import/libpq/rules.make1
-rw-r--r--build/import/libpq/stub.make1
-rw-r--r--build/root.build11
-rw-r--r--buildfile3
-rw-r--r--configure.ac1
-rw-r--r--libodb-pgsql.pc.in1
-rw-r--r--m4/disable-rpath.m41
-rw-r--r--m4/libodb.m41
-rw-r--r--m4/libpq.m41
-rw-r--r--m4/libtool-link.m41
-rw-r--r--m4/pkgconfig.m41
-rw-r--r--m4/static-lib.m41
-rw-r--r--m4/threads.m41
-rw-r--r--makefile5
-rw-r--r--manifest18
-rw-r--r--odb/pgsql/Makefile.am1
-rw-r--r--odb/pgsql/auto-handle.cxx1
-rw-r--r--odb/pgsql/auto-handle.hxx1
-rw-r--r--odb/pgsql/binding.hxx19
-rw-r--r--odb/pgsql/buildfile106
-rw-r--r--odb/pgsql/connection-factory.cxx1
-rw-r--r--odb/pgsql/connection-factory.hxx1
-rw-r--r--odb/pgsql/connection.cxx1
-rw-r--r--odb/pgsql/connection.hxx1
-rw-r--r--odb/pgsql/connection.ixx1
-rw-r--r--odb/pgsql/container-statements.hxx1
-rw-r--r--odb/pgsql/container-statements.txx1
-rw-r--r--odb/pgsql/database.cxx13
-rw-r--r--odb/pgsql/database.hxx31
-rw-r--r--odb/pgsql/database.ixx31
-rw-r--r--odb/pgsql/details/.gitignore2
-rw-r--r--odb/pgsql/details/build2/config-stub.h1
-rw-r--r--odb/pgsql/details/build2/config-vc-stub.h1
-rw-r--r--odb/pgsql/details/build2/config-vc.h1
-rw-r--r--odb/pgsql/details/build2/config.h1
-rw-r--r--odb/pgsql/details/config-vc.h1
-rw-r--r--odb/pgsql/details/config.h.in1
-rw-r--r--odb/pgsql/details/config.hxx1
-rw-r--r--odb/pgsql/details/conversion.hxx1
-rw-r--r--odb/pgsql/details/endian-traits.cxx1
-rw-r--r--odb/pgsql/details/endian-traits.hxx1
-rw-r--r--odb/pgsql/details/export.hxx1
-rw-r--r--odb/pgsql/details/options.cli1
-rw-r--r--odb/pgsql/details/pregenerated/odb/pgsql/details/options.cxx1114
-rw-r--r--odb/pgsql/details/pregenerated/odb/pgsql/details/options.hxx562
-rw-r--r--odb/pgsql/details/pregenerated/odb/pgsql/details/options.ixx372
-rw-r--r--odb/pgsql/error.cxx60
-rw-r--r--odb/pgsql/error.hxx19
-rw-r--r--odb/pgsql/error.ixx15
-rw-r--r--odb/pgsql/exceptions.cxx6
-rw-r--r--odb/pgsql/exceptions.hxx1
-rw-r--r--odb/pgsql/forward.hxx1
-rw-r--r--odb/pgsql/makefile3
-rw-r--r--odb/pgsql/no-id-object-result.hxx1
-rw-r--r--odb/pgsql/no-id-object-result.txx1
-rw-r--r--odb/pgsql/no-id-object-statements.hxx9
-rw-r--r--odb/pgsql/no-id-object-statements.txx9
-rw-r--r--odb/pgsql/pgsql-fwd.hxx1
-rw-r--r--odb/pgsql/pgsql-oid.hxx1
-rw-r--r--odb/pgsql/pgsql-types.hxx20
-rw-r--r--odb/pgsql/polymorphic-object-result.hxx1
-rw-r--r--odb/pgsql/polymorphic-object-result.txx1
-rw-r--r--odb/pgsql/polymorphic-object-statements.hxx1
-rw-r--r--odb/pgsql/polymorphic-object-statements.txx3
-rw-r--r--odb/pgsql/prepared-query.cxx1
-rw-r--r--odb/pgsql/prepared-query.hxx1
-rw-r--r--odb/pgsql/query-const-expr.cxx1
-rw-r--r--odb/pgsql/query-dynamic.cxx1
-rw-r--r--odb/pgsql/query-dynamic.hxx1
-rw-r--r--odb/pgsql/query-dynamic.ixx1
-rw-r--r--odb/pgsql/query-dynamic.txx1
-rw-r--r--odb/pgsql/query.cxx1
-rw-r--r--odb/pgsql/query.hxx18
-rw-r--r--odb/pgsql/query.ixx1
-rw-r--r--odb/pgsql/query.txx1
-rw-r--r--odb/pgsql/section-statements.hxx1
-rw-r--r--odb/pgsql/section-statements.txx1
-rw-r--r--odb/pgsql/simple-object-result.hxx1
-rw-r--r--odb/pgsql/simple-object-result.txx1
-rw-r--r--odb/pgsql/simple-object-statements.cxx1
-rw-r--r--odb/pgsql/simple-object-statements.hxx29
-rw-r--r--odb/pgsql/simple-object-statements.ixx1
-rw-r--r--odb/pgsql/simple-object-statements.txx37
-rw-r--r--odb/pgsql/statement-cache.hxx1
-rw-r--r--odb/pgsql/statement-cache.txx1
-rw-r--r--odb/pgsql/statement.cxx701
-rw-r--r--odb/pgsql/statement.hxx71
-rw-r--r--odb/pgsql/statements-base.cxx1
-rw-r--r--odb/pgsql/statements-base.hxx1
-rw-r--r--odb/pgsql/tracer.cxx1
-rw-r--r--odb/pgsql/tracer.hxx1
-rw-r--r--odb/pgsql/traits-calls.hxx1
-rw-r--r--odb/pgsql/traits.cxx1
-rw-r--r--odb/pgsql/traits.hxx1
-rw-r--r--odb/pgsql/transaction-impl.cxx1
-rw-r--r--odb/pgsql/transaction-impl.hxx6
-rw-r--r--odb/pgsql/transaction-impl.ixx15
-rw-r--r--odb/pgsql/transaction.cxx1
-rw-r--r--odb/pgsql/transaction.hxx4
-rw-r--r--odb/pgsql/transaction.ixx9
-rw-r--r--odb/pgsql/version-build2-stub.hxx1
-rw-r--r--odb/pgsql/version-build2.hxx.in1
-rw-r--r--odb/pgsql/version.hxx7
-rw-r--r--odb/pgsql/view-result.hxx1
-rw-r--r--odb/pgsql/view-result.txx1
-rw-r--r--odb/pgsql/view-statements.hxx1
-rw-r--r--odb/pgsql/view-statements.txx1
-rw-r--r--repositories.manifest6
-rw-r--r--tests/basics/buildfile1
-rw-r--r--tests/basics/driver.cxx1
-rw-r--r--tests/build/bootstrap.build1
-rw-r--r--tests/build/root.build1
-rw-r--r--tests/buildfile1
-rw-r--r--version1
-rw-r--r--version.txt1
138 files changed, 3079 insertions, 731 deletions
diff --git a/LICENSE b/LICENSE
index 612c66c..9d92da1 100644
--- a/LICENSE
+++ b/LICENSE
@@ -1,3 +1,5 @@
+Copyright (c) 2009-2024 Code Synthesis Tools CC.
+
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License version 2 as
published by the Free Software Foundation.
diff --git a/Makefile.am b/Makefile.am
index d4c93b8..2c34934 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -1,5 +1,4 @@
# file : Makefile.am
-# copyright : Copyright (c) 2009-2019 Code Synthesis Tools CC
# license : GNU GPL v2; see accompanying LICENSE file
SUBDIRS = __path__(dirs)
diff --git a/bootstrap b/bootstrap
index 0e786df..85d1399 100755
--- a/bootstrap
+++ b/bootstrap
@@ -1,7 +1,6 @@
#! /bin/sh
# file : bootstrap
-# copyright : Copyright (c) 2009-2019 Code Synthesis Tools CC
# license : GNU GPL v2; see accompanying LICENSE file
#
diff --git a/build/bootstrap.build b/build/bootstrap.build
index d752fd7..fb6b7df 100644
--- a/build/bootstrap.build
+++ b/build/bootstrap.build
@@ -1,5 +1,4 @@
# file : build/bootstrap.build
-# copyright : Copyright (c) 2009-2019 Code Synthesis Tools CC
# license : GNU GPL v2; see accompanying LICENSE file
project = libodb-pgsql
diff --git a/build/bootstrap.make b/build/bootstrap.make
index 83a4ccb..26da3c4 100644
--- a/build/bootstrap.make
+++ b/build/bootstrap.make
@@ -1,5 +1,4 @@
# file : build/bootstrap.make
-# copyright : Copyright (c) 2009-2019 Code Synthesis Tools CC
# license : GNU GPL v2; see accompanying LICENSE file
project_name := libodb-pgsql
diff --git a/build/export.build b/build/export.build
index 01d806d..80aba23 100644
--- a/build/export.build
+++ b/build/export.build
@@ -1,5 +1,4 @@
# file : build/export.build
-# copyright : Copyright (c) 2009-2019 Code Synthesis Tools CC
# license : GNU GPL v2; see accompanying LICENSE file
$out_root/
diff --git a/build/export/libodb-pgsql/stub.make b/build/export/libodb-pgsql/stub.make
index 8dd5e22..9e646aa 100644
--- a/build/export/libodb-pgsql/stub.make
+++ b/build/export/libodb-pgsql/stub.make
@@ -1,5 +1,4 @@
# file : build/export/libodb-pgsql/stub.make
-# copyright : Copyright (c) 2009-2019 Code Synthesis Tools CC
# license : GNU GPL v2; see accompanying LICENSE file
$(call include-once,$(src_root)/odb/pgsql/makefile,$(out_root))
diff --git a/build/import/cli/LICENSE b/build/import/cli/LICENSE
deleted file mode 100644
index f6b2d2b..0000000
--- a/build/import/cli/LICENSE
+++ /dev/null
@@ -1,21 +0,0 @@
-Copyright (c) 2009-2019 Code Synthesis Tools CC.
-
-Permission is hereby granted, free of charge, to any person obtaining
-a copy of this software and associated documentation files (the
-"Software"), to deal in the Software without restriction, including
-without limitation the rights to use, copy, modify, merge, publish,
-distribute, sublicense, and/or sell copies of the Software, and to
-permit persons to whom the Software is furnished to do so, subject to
-the following conditions:
-
-The above copyright notice and this permission notice shall be included
-in all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
-EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
-IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
-CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
-TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
-SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-
diff --git a/build/import/cli/cli-cxx.make b/build/import/cli/cli-cxx.make
index 3d01453..9bdf238 100644
--- a/build/import/cli/cli-cxx.make
+++ b/build/import/cli/cli-cxx.make
@@ -1,5 +1,4 @@
# file : build/import/cli/cli-cxx.make
-# copyright : Copyright (c) 2009-2019 Code Synthesis Tools CC
# license : MIT; see accompanying LICENSE file
# Here we are operating in the importing project's space, not in
diff --git a/build/import/cli/configuration-rules.make b/build/import/cli/configuration-rules.make
index f13d01b..6355000 100644
--- a/build/import/cli/configuration-rules.make
+++ b/build/import/cli/configuration-rules.make
@@ -1,5 +1,4 @@
# file : build/import/cli/configuration-rules.make
-# copyright : Copyright (c) 2009-2019 Code Synthesis Tools CC
# license : MIT; see accompanying LICENSE file
$(dcf_root)/import/cli/configuration-dynamic.make: | $(dcf_root)/import/cli/.
diff --git a/build/import/cli/configure b/build/import/cli/configure
index 944f48c..2a1fde4 100755
--- a/build/import/cli/configure
+++ b/build/import/cli/configure
@@ -1,7 +1,6 @@
#! /usr/bin/env bash
# file : build/import/cli/configure
-# copyright : Copyright (c) 2009-2019 Code Synthesis Tools CC
# license : MIT; see accompanying LICENSE file
diff --git a/build/import/cli/stub.make b/build/import/cli/stub.make
index 047ba40..741b371 100644
--- a/build/import/cli/stub.make
+++ b/build/import/cli/stub.make
@@ -1,5 +1,4 @@
# file : build/import/cli/stub.make
-# copyright : Copyright (c) 2009-2019 Code Synthesis Tools CC
# license : MIT; see accompanying LICENSE file
$(call include-once,$(scf_root)/import/cli/configuration-rules.make,$(dcf_root))
diff --git a/build/import/libodb-pgsql/LICENSE b/build/import/libodb-pgsql/LICENSE
deleted file mode 120000
index 5853aae..0000000
--- a/build/import/libodb-pgsql/LICENSE
+++ /dev/null
@@ -1 +0,0 @@
-../../../LICENSE \ No newline at end of file
diff --git a/build/import/libodb-pgsql/configuration-rules.make b/build/import/libodb-pgsql/configuration-rules.make
index 7ba6f62..326a60c 100644
--- a/build/import/libodb-pgsql/configuration-rules.make
+++ b/build/import/libodb-pgsql/configuration-rules.make
@@ -1,5 +1,4 @@
# file : build/import/libodb-pgsql/configuration-rules.make
-# copyright : Copyright (c) 2009-2019 Code Synthesis Tools CC
# license : GNU GPL v2; see accompanying LICENSE file
$(dcf_root)/import/libodb-pgsql/configuration-dynamic.make: | $(dcf_root)/import/libodb-pgsql/.
diff --git a/build/import/libodb-pgsql/configure b/build/import/libodb-pgsql/configure
index 3918fb9..9d75cad 100755
--- a/build/import/libodb-pgsql/configure
+++ b/build/import/libodb-pgsql/configure
@@ -1,7 +1,6 @@
#! /usr/bin/env bash
# file : build/import/libodb-pgsql/configure
-# copyright : Copyright (c) 2009-2019 Code Synthesis Tools CC
# license : GNU GPL v2; see accompanying LICENSE file
diff --git a/build/import/libodb-pgsql/stub.make b/build/import/libodb-pgsql/stub.make
index 2e5a38d..b770a63 100644
--- a/build/import/libodb-pgsql/stub.make
+++ b/build/import/libodb-pgsql/stub.make
@@ -1,5 +1,4 @@
# file : build/import/libodb-pgsql/stub.make
-# copyright : Copyright (c) 2009-2019 Code Synthesis Tools CC
# license : GNU GPL v2; see accompanying LICENSE file
$(call include-once,$(scf_root)/import/libodb-pgsql/configuration-rules.make,$(dcf_root))
diff --git a/build/import/libodb/LICENSE b/build/import/libodb/LICENSE
deleted file mode 100644
index ed9c55c..0000000
--- a/build/import/libodb/LICENSE
+++ /dev/null
@@ -1,12 +0,0 @@
-This program is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License version 2 as
-published by the Free Software Foundation.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for details.
-
-You should have received a copy of the GNU General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
diff --git a/build/import/libodb/configuration-rules.make b/build/import/libodb/configuration-rules.make
index 872cbb3..340c418 100644
--- a/build/import/libodb/configuration-rules.make
+++ b/build/import/libodb/configuration-rules.make
@@ -1,5 +1,4 @@
# file : build/import/libodb/configuration-rules.make
-# copyright : Copyright (c) 2009-2019 Code Synthesis Tools CC
# license : GNU GPL v2; see accompanying LICENSE file
$(dcf_root)/import/libodb/configuration-dynamic.make: | $(dcf_root)/import/libodb/.
diff --git a/build/import/libodb/configure b/build/import/libodb/configure
index 0d57a5f..261a202 100755
--- a/build/import/libodb/configure
+++ b/build/import/libodb/configure
@@ -1,7 +1,6 @@
#! /usr/bin/env bash
# file : build/import/libodb/configure
-# copyright : Copyright (c) 2009-2019 Code Synthesis Tools CC
# license : GNU GPL v2; see accompanying LICENSE file
diff --git a/build/import/libodb/stub.make b/build/import/libodb/stub.make
index 6b7088d..04dc786 100644
--- a/build/import/libodb/stub.make
+++ b/build/import/libodb/stub.make
@@ -1,5 +1,4 @@
# file : build/import/libodb/stub.make
-# copyright : Copyright (c) 2009-2019 Code Synthesis Tools CC
# license : GNU GPL v2; see accompanying LICENSE file
$(call include-once,$(scf_root)/import/libodb/configuration-rules.make,$(dcf_root))
diff --git a/build/import/libpq/LICENSE b/build/import/libpq/LICENSE
deleted file mode 100644
index 3912109..0000000
--- a/build/import/libpq/LICENSE
+++ /dev/null
@@ -1,340 +0,0 @@
- GNU GENERAL PUBLIC LICENSE
- Version 2, June 1991
-
- Copyright (C) 1989, 1991 Free Software Foundation, Inc.
- 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- Everyone is permitted to copy and distribute verbatim copies
- of this license document, but changing it is not allowed.
-
- Preamble
-
- The licenses for most software are designed to take away your
-freedom to share and change it. By contrast, the GNU General Public
-License is intended to guarantee your freedom to share and change free
-software--to make sure the software is free for all its users. This
-General Public License applies to most of the Free Software
-Foundation's software and to any other program whose authors commit to
-using it. (Some other Free Software Foundation software is covered by
-the GNU Library General Public License instead.) You can apply it to
-your programs, too.
-
- When we speak of free software, we are referring to freedom, not
-price. Our General Public Licenses are designed to make sure that you
-have the freedom to distribute copies of free software (and charge for
-this service if you wish), that you receive source code or can get it
-if you want it, that you can change the software or use pieces of it
-in new free programs; and that you know you can do these things.
-
- To protect your rights, we need to make restrictions that forbid
-anyone to deny you these rights or to ask you to surrender the rights.
-These restrictions translate to certain responsibilities for you if you
-distribute copies of the software, or if you modify it.
-
- For example, if you distribute copies of such a program, whether
-gratis or for a fee, you must give the recipients all the rights that
-you have. You must make sure that they, too, receive or can get the
-source code. And you must show them these terms so they know their
-rights.
-
- We protect your rights with two steps: (1) copyright the software, and
-(2) offer you this license which gives you legal permission to copy,
-distribute and/or modify the software.
-
- Also, for each author's protection and ours, we want to make certain
-that everyone understands that there is no warranty for this free
-software. If the software is modified by someone else and passed on, we
-want its recipients to know that what they have is not the original, so
-that any problems introduced by others will not reflect on the original
-authors' reputations.
-
- Finally, any free program is threatened constantly by software
-patents. We wish to avoid the danger that redistributors of a free
-program will individually obtain patent licenses, in effect making the
-program proprietary. To prevent this, we have made it clear that any
-patent must be licensed for everyone's free use or not licensed at all.
-
- The precise terms and conditions for copying, distribution and
-modification follow.
-
- GNU GENERAL PUBLIC LICENSE
- TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
-
- 0. This License applies to any program or other work which contains
-a notice placed by the copyright holder saying it may be distributed
-under the terms of this General Public License. The "Program", below,
-refers to any such program or work, and a "work based on the Program"
-means either the Program or any derivative work under copyright law:
-that is to say, a work containing the Program or a portion of it,
-either verbatim or with modifications and/or translated into another
-language. (Hereinafter, translation is included without limitation in
-the term "modification".) Each licensee is addressed as "you".
-
-Activities other than copying, distribution and modification are not
-covered by this License; they are outside its scope. The act of
-running the Program is not restricted, and the output from the Program
-is covered only if its contents constitute a work based on the
-Program (independent of having been made by running the Program).
-Whether that is true depends on what the Program does.
-
- 1. You may copy and distribute verbatim copies of the Program's
-source code as you receive it, in any medium, provided that you
-conspicuously and appropriately publish on each copy an appropriate
-copyright notice and disclaimer of warranty; keep intact all the
-notices that refer to this License and to the absence of any warranty;
-and give any other recipients of the Program a copy of this License
-along with the Program.
-
-You may charge a fee for the physical act of transferring a copy, and
-you may at your option offer warranty protection in exchange for a fee.
-
- 2. You may modify your copy or copies of the Program or any portion
-of it, thus forming a work based on the Program, and copy and
-distribute such modifications or work under the terms of Section 1
-above, provided that you also meet all of these conditions:
-
- a) You must cause the modified files to carry prominent notices
- stating that you changed the files and the date of any change.
-
- b) You must cause any work that you distribute or publish, that in
- whole or in part contains or is derived from the Program or any
- part thereof, to be licensed as a whole at no charge to all third
- parties under the terms of this License.
-
- c) If the modified program normally reads commands interactively
- when run, you must cause it, when started running for such
- interactive use in the most ordinary way, to print or display an
- announcement including an appropriate copyright notice and a
- notice that there is no warranty (or else, saying that you provide
- a warranty) and that users may redistribute the program under
- these conditions, and telling the user how to view a copy of this
- License. (Exception: if the Program itself is interactive but
- does not normally print such an announcement, your work based on
- the Program is not required to print an announcement.)
-
-These requirements apply to the modified work as a whole. If
-identifiable sections of that work are not derived from the Program,
-and can be reasonably considered independent and separate works in
-themselves, then this License, and its terms, do not apply to those
-sections when you distribute them as separate works. But when you
-distribute the same sections as part of a whole which is a work based
-on the Program, the distribution of the whole must be on the terms of
-this License, whose permissions for other licensees extend to the
-entire whole, and thus to each and every part regardless of who wrote it.
-
-Thus, it is not the intent of this section to claim rights or contest
-your rights to work written entirely by you; rather, the intent is to
-exercise the right to control the distribution of derivative or
-collective works based on the Program.
-
-In addition, mere aggregation of another work not based on the Program
-with the Program (or with a work based on the Program) on a volume of
-a storage or distribution medium does not bring the other work under
-the scope of this License.
-
- 3. You may copy and distribute the Program (or a work based on it,
-under Section 2) in object code or executable form under the terms of
-Sections 1 and 2 above provided that you also do one of the following:
-
- a) Accompany it with the complete corresponding machine-readable
- source code, which must be distributed under the terms of Sections
- 1 and 2 above on a medium customarily used for software interchange; or,
-
- b) Accompany it with a written offer, valid for at least three
- years, to give any third party, for a charge no more than your
- cost of physically performing source distribution, a complete
- machine-readable copy of the corresponding source code, to be
- distributed under the terms of Sections 1 and 2 above on a medium
- customarily used for software interchange; or,
-
- c) Accompany it with the information you received as to the offer
- to distribute corresponding source code. (This alternative is
- allowed only for noncommercial distribution and only if you
- received the program in object code or executable form with such
- an offer, in accord with Subsection b above.)
-
-The source code for a work means the preferred form of the work for
-making modifications to it. For an executable work, complete source
-code means all the source code for all modules it contains, plus any
-associated interface definition files, plus the scripts used to
-control compilation and installation of the executable. However, as a
-special exception, the source code distributed need not include
-anything that is normally distributed (in either source or binary
-form) with the major components (compiler, kernel, and so on) of the
-operating system on which the executable runs, unless that component
-itself accompanies the executable.
-
-If distribution of executable or object code is made by offering
-access to copy from a designated place, then offering equivalent
-access to copy the source code from the same place counts as
-distribution of the source code, even though third parties are not
-compelled to copy the source along with the object code.
-
- 4. You may not copy, modify, sublicense, or distribute the Program
-except as expressly provided under this License. Any attempt
-otherwise to copy, modify, sublicense or distribute the Program is
-void, and will automatically terminate your rights under this License.
-However, parties who have received copies, or rights, from you under
-this License will not have their licenses terminated so long as such
-parties remain in full compliance.
-
- 5. You are not required to accept this License, since you have not
-signed it. However, nothing else grants you permission to modify or
-distribute the Program or its derivative works. These actions are
-prohibited by law if you do not accept this License. Therefore, by
-modifying or distributing the Program (or any work based on the
-Program), you indicate your acceptance of this License to do so, and
-all its terms and conditions for copying, distributing or modifying
-the Program or works based on it.
-
- 6. Each time you redistribute the Program (or any work based on the
-Program), the recipient automatically receives a license from the
-original licensor to copy, distribute or modify the Program subject to
-these terms and conditions. You may not impose any further
-restrictions on the recipients' exercise of the rights granted herein.
-You are not responsible for enforcing compliance by third parties to
-this License.
-
- 7. If, as a consequence of a court judgment or allegation of patent
-infringement or for any other reason (not limited to patent issues),
-conditions are imposed on you (whether by court order, agreement or
-otherwise) that contradict the conditions of this License, they do not
-excuse you from the conditions of this License. If you cannot
-distribute so as to satisfy simultaneously your obligations under this
-License and any other pertinent obligations, then as a consequence you
-may not distribute the Program at all. For example, if a patent
-license would not permit royalty-free redistribution of the Program by
-all those who receive copies directly or indirectly through you, then
-the only way you could satisfy both it and this License would be to
-refrain entirely from distribution of the Program.
-
-If any portion of this section is held invalid or unenforceable under
-any particular circumstance, the balance of the section is intended to
-apply and the section as a whole is intended to apply in other
-circumstances.
-
-It is not the purpose of this section to induce you to infringe any
-patents or other property right claims or to contest validity of any
-such claims; this section has the sole purpose of protecting the
-integrity of the free software distribution system, which is
-implemented by public license practices. Many people have made
-generous contributions to the wide range of software distributed
-through that system in reliance on consistent application of that
-system; it is up to the author/donor to decide if he or she is willing
-to distribute software through any other system and a licensee cannot
-impose that choice.
-
-This section is intended to make thoroughly clear what is believed to
-be a consequence of the rest of this License.
-
- 8. If the distribution and/or use of the Program is restricted in
-certain countries either by patents or by copyrighted interfaces, the
-original copyright holder who places the Program under this License
-may add an explicit geographical distribution limitation excluding
-those countries, so that distribution is permitted only in or among
-countries not thus excluded. In such case, this License incorporates
-the limitation as if written in the body of this License.
-
- 9. The Free Software Foundation may publish revised and/or new versions
-of the General Public License from time to time. Such new versions will
-be similar in spirit to the present version, but may differ in detail to
-address new problems or concerns.
-
-Each version is given a distinguishing version number. If the Program
-specifies a version number of this License which applies to it and "any
-later version", you have the option of following the terms and conditions
-either of that version or of any later version published by the Free
-Software Foundation. If the Program does not specify a version number of
-this License, you may choose any version ever published by the Free Software
-Foundation.
-
- 10. If you wish to incorporate parts of the Program into other free
-programs whose distribution conditions are different, write to the author
-to ask for permission. For software which is copyrighted by the Free
-Software Foundation, write to the Free Software Foundation; we sometimes
-make exceptions for this. Our decision will be guided by the two goals
-of preserving the free status of all derivatives of our free software and
-of promoting the sharing and reuse of software generally.
-
- NO WARRANTY
-
- 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
-FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
-OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
-PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
-OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
-MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
-TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
-PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
-REPAIR OR CORRECTION.
-
- 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
-WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
-REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
-INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
-OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
-TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
-YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
-PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
-POSSIBILITY OF SUCH DAMAGES.
-
- END OF TERMS AND CONDITIONS
-
- How to Apply These Terms to Your New Programs
-
- If you develop a new program, and you want it to be of the greatest
-possible use to the public, the best way to achieve this is to make it
-free software which everyone can redistribute and change under these terms.
-
- To do so, attach the following notices to the program. It is safest
-to attach them to the start of each source file to most effectively
-convey the exclusion of warranty; and each file should have at least
-the "copyright" line and a pointer to where the full notice is found.
-
- <one line to give the program's name and a brief idea of what it does.>
- Copyright (C) <year> <name of author>
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
-
-
-Also add information on how to contact you by electronic and paper mail.
-
-If the program is interactive, make it output a short notice like this
-when it starts in an interactive mode:
-
- Gnomovision version 69, Copyright (C) year name of author
- Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
- This is free software, and you are welcome to redistribute it
- under certain conditions; type `show c' for details.
-
-The hypothetical commands `show w' and `show c' should show the appropriate
-parts of the General Public License. Of course, the commands you use may
-be called something other than `show w' and `show c'; they could even be
-mouse-clicks or menu items--whatever suits your program.
-
-You should also get your employer (if you work as a programmer) or your
-school, if any, to sign a "copyright disclaimer" for the program, if
-necessary. Here is a sample; alter the names:
-
- Yoyodyne, Inc., hereby disclaims all copyright interest in the program
- `Gnomovision' (which makes passes at compilers) written by James Hacker.
-
- <signature of Ty Coon>, 1 April 1989
- Ty Coon, President of Vice
-
-This General Public License does not permit incorporating your program into
-proprietary programs. If your program is a subroutine library, you may
-consider it more useful to permit linking proprietary applications with the
-library. If this is what you want to do, use the GNU Library General
-Public License instead of this License.
diff --git a/build/import/libpq/configuration-rules.make b/build/import/libpq/configuration-rules.make
index b117767..3b43941 100644
--- a/build/import/libpq/configuration-rules.make
+++ b/build/import/libpq/configuration-rules.make
@@ -1,5 +1,4 @@
# file : build/import/libpq/configuration-rules.make
-# copyright : Copyright (c) 2005-2019 Code Synthesis Tools CC
# license : GNU GPL v2; see accompanying LICENSE file
$(dcf_root)/import/libpq/configuration-dynamic.make: | $(dcf_root)/import/libpq/.
diff --git a/build/import/libpq/configure b/build/import/libpq/configure
index 56f5c3f..91b196f 100755
--- a/build/import/libpq/configure
+++ b/build/import/libpq/configure
@@ -1,7 +1,6 @@
#! /usr/bin/env bash
# file : build/import/libpq/configure
-# copyright : Copyright (c) 2009-2019 Code Synthesis Tools CC
# license : GNU GPL v2; see accompanying LICENSE file
diff --git a/build/import/libpq/rules.make b/build/import/libpq/rules.make
index dee718f..016a671 100644
--- a/build/import/libpq/rules.make
+++ b/build/import/libpq/rules.make
@@ -1,5 +1,4 @@
# file : build/import/libpq/rules.make
-# copyright : Copyright (c) 2009-2019 Code Synthesis Tools CC
# license : GNU GPL v2; see accompanying LICENSE file
$(dcf_root)/import/libpq/%: root := $(libpq_root)
diff --git a/build/import/libpq/stub.make b/build/import/libpq/stub.make
index a8f8824..94ba269 100644
--- a/build/import/libpq/stub.make
+++ b/build/import/libpq/stub.make
@@ -1,5 +1,4 @@
# file : build/import/libpq/stub.make
-# copyright : Copyright (c) 2009-2019 Code Synthesis Tools CC
# license : GNU GPL v2; see accompanying LICENSE file
$(call include-once,$(scf_root)/import/libpq/configuration-rules.make,$(dcf_root))
diff --git a/build/root.build b/build/root.build
index ece30fb..329cc45 100644
--- a/build/root.build
+++ b/build/root.build
@@ -1,7 +1,8 @@
# file : build/root.build
-# copyright : Copyright (c) 2009-2019 Code Synthesis Tools CC
# license : GNU GPL v2; see accompanying LICENSE file
+config [bool] config.libodb_pgsql.develop ?= false
+
cxx.std = latest
using cxx
@@ -16,11 +17,3 @@ if ($cxx.target.system == 'win32-msvc')
if ($cxx.class == 'msvc')
cxx.coptions += /wd4251 /wd4275 /wd4800
-
-# Load the cli module but only if it's available. This way a distribution
-# that includes pre-generated files can be built without installing cli.
-# This is also the reason why we need to explicitly spell out individual
-# source file prerequisites instead of using the cli.cxx{} group (it won't
-# be there unless the module is configured).
-#
-using? cli
diff --git a/buildfile b/buildfile
index bf7778e..406853f 100644
--- a/buildfile
+++ b/buildfile
@@ -1,8 +1,7 @@
# file : buildfile
-# copyright : Copyright (c) 2009-2019 Code Synthesis Tools CC
# license : GNU GPL v2; see accompanying LICENSE file
-./: {*/ -build/ -m4/} doc{GPLv2 INSTALL LICENSE NEWS README} manifest
+./: {*/ -build/ -m4/} doc{INSTALL NEWS README} legal{GPLv2 LICENSE} manifest
# Don't install tests or the INSTALL file.
#
diff --git a/configure.ac b/configure.ac
index 3e609fe..f09dc37 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1,5 +1,4 @@
# file : configure.ac
-# copyright : Copyright (c) 2009-2019 Code Synthesis Tools CC
# license : GNU GPL v2; see accompanying LICENSE file
AC_PREREQ(2.60)
diff --git a/libodb-pgsql.pc.in b/libodb-pgsql.pc.in
index a3cefb4..63c6966 100644
--- a/libodb-pgsql.pc.in
+++ b/libodb-pgsql.pc.in
@@ -1,5 +1,4 @@
# file : libodb-pgsql.pc.in
-# copyright : Copyright (c) 2009-2019 Code Synthesis Tools CC
# license : GNU GPL v2; see accompanying LICENSE file
prefix=@prefix@
diff --git a/m4/disable-rpath.m4 b/m4/disable-rpath.m4
index 7874d4b..0864209 100644
--- a/m4/disable-rpath.m4
+++ b/m4/disable-rpath.m4
@@ -1,5 +1,4 @@
dnl file : m4/disable-rpath.m4
-dnl copyright : Copyright (c) 2009-2019 Code Synthesis Tools CC
dnl license : GNU GPL v2; see accompanying LICENSE file
dnl
AC_DEFUN([DISABLE_RPATH],[
diff --git a/m4/libodb.m4 b/m4/libodb.m4
index 5f140bd..0dba7c4 100644
--- a/m4/libodb.m4
+++ b/m4/libodb.m4
@@ -1,5 +1,4 @@
dnl file : m4/libodb.m4
-dnl copyright : Copyright (c) 2009-2019 Code Synthesis Tools CC
dnl license : GNU GPL v2; see accompanying LICENSE file
dnl
dnl LIBODB([ACTION-IF-FOUND[, ACTION-IF-NOT-FOUND]])
diff --git a/m4/libpq.m4 b/m4/libpq.m4
index 1529fbd..a29ae2d 100644
--- a/m4/libpq.m4
+++ b/m4/libpq.m4
@@ -1,5 +1,4 @@
dnl file : m4/libpq.m4
-dnl copyright : Copyright (c) 2009-2019 Code Synthesis Tools CC
dnl license : GNU GPL v2; see accompanying LICENSE file
dnl
dnl LIBPQ([ACTION-IF-FOUND[,
diff --git a/m4/libtool-link.m4 b/m4/libtool-link.m4
index 635793f..302639f 100644
--- a/m4/libtool-link.m4
+++ b/m4/libtool-link.m4
@@ -1,5 +1,4 @@
dnl file : m4/libtool-link.m4
-dnl copyright : Copyright (c) 2009-2019 Code Synthesis Tools CC
dnl license : GNU GPL v2; see accompanying LICENSE file
dnl
dnl
diff --git a/m4/pkgconfig.m4 b/m4/pkgconfig.m4
index d5aa2d0..c48ea56 100644
--- a/m4/pkgconfig.m4
+++ b/m4/pkgconfig.m4
@@ -1,5 +1,4 @@
dnl file : m4/pkgconfig.m4
-dnl copyright : Copyright (c) 2009-2019 Code Synthesis Tools CC
dnl license : GNU GPL v2; see accompanying LICENSE file
dnl
AC_DEFUN([PKGCONFIG],[
diff --git a/m4/static-lib.m4 b/m4/static-lib.m4
index 79b89cd..5fb1c11 100644
--- a/m4/static-lib.m4
+++ b/m4/static-lib.m4
@@ -1,5 +1,4 @@
dnl file : m4/static-lib.m4
-dnl copyright : Copyright (c) 2009-2019 Code Synthesis Tools CC
dnl license : GNU GPL v2; see accompanying LICENSE file
dnl
dnl STATIC_LIB(MACRO, DESCRIPTION)
diff --git a/m4/threads.m4 b/m4/threads.m4
index 10bdfdd..6f2e25f 100644
--- a/m4/threads.m4
+++ b/m4/threads.m4
@@ -1,5 +1,4 @@
dnl file : m4/threads.m4
-dnl copyright : Copyright (c) 2009-2019 Code Synthesis Tools CC
dnl license : GNU GPL v2; see accompanying LICENSE file
dnl
AC_DEFUN([THREADS],[
diff --git a/makefile b/makefile
index 2d07774..4031289 100644
--- a/makefile
+++ b/makefile
@@ -1,5 +1,4 @@
# file : makefile
-# copyright : Copyright (c) 2009-2019 Code Synthesis Tools CC
# license : GNU GPL v2; see accompanying LICENSE file
include $(dir $(lastword $(MAKEFILE_LIST)))build/bootstrap.make
@@ -13,12 +12,12 @@ clean := $(out_base)/.clean
$(default): $(addprefix $(out_base)/,$(addsuffix /,$(dirs)))
$(dist): export dirs := $(dirs)
-$(dist): export docs := GPLv2 LICENSE README NEWS version
+$(dist): export docs := GPLv2 LICENSE README NEWS version.txt
$(dist): data_dist := INSTALL libodb-pgsql-vc8.sln libodb-pgsql-vc9.sln \
libodb-pgsql-vc10.sln libodb-pgsql-vc11.sln libodb-pgsql-vc12.sln
$(dist): exec_dist := bootstrap
$(dist): export extra_dist := $(data_dist) $(exec_dist)
-$(dist): export version = $(shell cat $(src_root)/version)
+$(dist): export version = $(shell cat $(src_root)/version.txt)
$(dist): $(addprefix $(out_base)/,$(addsuffix /.dist,$(dirs)))
$(call dist-data,$(docs) $(data_dist) libodb-pgsql.pc.in)
diff --git a/manifest b/manifest
index c718442..7a523d7 100644
--- a/manifest
+++ b/manifest
@@ -1,10 +1,10 @@
: 1
name: libodb-pgsql
-version: 2.5.0-b.16.z
+version: 2.5.0-b.26.z
project: odb
summary: PostgreSQL ODB runtime library
-license: GPLv2
-license: proprietary
+license: GPL-2.0-only
+license: other: proprietary ; Not free/open source.
topics: C++, ORM, PostgreSQL, SQL
description-file: README
changes-file: NEWS
@@ -12,10 +12,12 @@ url: https://www.codesynthesis.com/products/odb/
doc-url: https://www.codesynthesis.com/products/odb/doc/manual.xhtml
src-url: https://git.codesynthesis.com/cgit/odb/libodb-pgsql/
email: odb-users@codesynthesis.com
-build-email: odb-builds@codesynthesis.com
+build-warning-email: odb-builds@codesynthesis.com
builds: all
+builds: -wasm
requires: c++11
-depends: * build2 >= 0.11.0
-depends: * bpkg >= 0.11.0
-depends: libpq ^9.0.0
-depends: libodb [2.5.0-b.16.1 2.5.0-b.17)
+depends: * build2 >= 0.16.0-
+depends: * bpkg >= 0.16.0-
+depends: libpq >=7.4.0
+depends: libodb [2.5.0-b.26.1 2.5.0-b.27)
+depends: * cli ^1.2.0- ? ($config.libodb_pgsql.develop)
diff --git a/odb/pgsql/Makefile.am b/odb/pgsql/Makefile.am
index 47410bc..8a95b93 100644
--- a/odb/pgsql/Makefile.am
+++ b/odb/pgsql/Makefile.am
@@ -1,5 +1,4 @@
# file : odb/pgsql/Makefile.am
-# copyright : Copyright (c) 2009-2019 Code Synthesis Tools CC
# license : GNU GPL v2; see accompanying LICENSE file
lib_LTLIBRARIES = libodb-pgsql.la
diff --git a/odb/pgsql/auto-handle.cxx b/odb/pgsql/auto-handle.cxx
index e8e426a..d6c0565 100644
--- a/odb/pgsql/auto-handle.cxx
+++ b/odb/pgsql/auto-handle.cxx
@@ -1,5 +1,4 @@
// file : odb/pgsql/auto-handle.cxx
-// copyright : Copyright (c) 2005-2019 Code Synthesis Tools CC
// license : GNU GPL v2; see accompanying LICENSE file
#include <libpq-fe.h>
diff --git a/odb/pgsql/auto-handle.hxx b/odb/pgsql/auto-handle.hxx
index a2dd92b..49b396d 100644
--- a/odb/pgsql/auto-handle.hxx
+++ b/odb/pgsql/auto-handle.hxx
@@ -1,5 +1,4 @@
// file : odb/pgsql/auto-handle.hxx
-// copyright : Copyright (c) 2005-2019 Code Synthesis Tools CC
// license : GNU GPL v2; see accompanying LICENSE file
#ifndef ODB_PGSQL_AUTO_HANDLE_HXX
diff --git a/odb/pgsql/binding.hxx b/odb/pgsql/binding.hxx
index 468a6e9..1adf144 100644
--- a/odb/pgsql/binding.hxx
+++ b/odb/pgsql/binding.hxx
@@ -1,5 +1,4 @@
// file : odb/pgsql/binding.hxx
-// copyright : Copyright (c) 2005-2019 Code Synthesis Tools CC
// license : GNU GPL v2; see accompanying LICENSE file
#ifndef ODB_PGSQL_BINDING_HXX
@@ -42,17 +41,27 @@ namespace odb
public:
typedef pgsql::bind bind_type;
- binding (): bind (0), count (0), version (0) {}
+ binding ()
+ : bind (0), count (0), version (0),
+ batch (0), skip (0), status (0) {}
binding (bind_type* b, std::size_t n)
- : bind (b), count (n), version (0)
- {
- }
+ : bind (b), count (n), version (0),
+ batch (0), skip (0), status (0) {}
+
+ binding (bind_type* b, std::size_t n,
+ std::size_t bt, std::size_t s, unsigned long long* st)
+ : bind (b), count (n), version (0),
+ batch (bt), skip (s), status (st) {}
bind_type* bind;
std::size_t count;
std::size_t version;
+ std::size_t batch;
+ std::size_t skip;
+ unsigned long long* status; // Batch status array.
+
private:
binding (const binding&);
binding& operator= (const binding&);
diff --git a/odb/pgsql/buildfile b/odb/pgsql/buildfile
index c2bb0d4..f1d05b6 100644
--- a/odb/pgsql/buildfile
+++ b/odb/pgsql/buildfile
@@ -1,13 +1,15 @@
# file : odb/pgsql/buildfile
-# copyright : Copyright (c) 2009-2019 Code Synthesis Tools CC
# license : GNU GPL v2; see accompanying LICENSE file
+define cli: file
+cli{*}: extension = cli
+
import int_libs = libodb%lib{odb}
import imp_libs = libpq%lib{pq}
-lib{odb-pgsql}: {hxx ixx txx cxx}{* -version-build2} {hxx}{version-build2} \
- details/{hxx ixx txx cxx}{* -options} details/{hxx ixx cxx}{options} \
- details/build2/{h}{*} \
+lib{odb-pgsql}: {hxx ixx txx cxx}{* -version-build2} {hxx}{version-build2} \
+ details/{hxx ixx txx cxx}{* -options} \
+ details/build2/{h}{*} \
$imp_libs $int_libs
# Include the generated version header into the distribution (so that we don't
@@ -48,36 +50,76 @@ if $version.pre_release
else
lib{odb-pgsql}: bin.lib.version = @"-$version.major.$version.minor"
-# Generated options parser.
+develop = $config.libodb_pgsql.develop
+
+## Consumption build ($develop == false).
+#
+
+# Use pregenerated versions in the consumption build.
+#
+lib{odb-pgsql}: details/pregenerated/{hxx ixx cxx}{**}: include = (!$develop)
+
+if! $develop
+ cxx.poptions =+ "-I($src_base/details/pregenerated)" # Note: must come first.
+
+# Don't install pregenerated headers since they are only used internally in
+# the database implementation (also below).
+#
+details/pregenerated/{hxx ixx}{*}: install = false
+
+# Distribute pregenerated versions only in the consumption build.
+#
+details/pregenerated/{hxx ixx cxx}{*}: dist = (!$develop)
+
#
-details/
+##
+
+## Development build ($develop == true).
+#
+
+lib{odb-pgsql}: details/{hxx ixx cxx}{options}: include = $develop
+
+if $develop
+ import! [metadata] cli = cli%exe{cli}
+
+# In the development build distribute regenerated {hxx ixx cxx}{options},
+# remapping their locations to the paths of the pregenerated versions (which
+# are only distributed in the consumption build; see above). This way we make
+# sure that the distributed files are always up-to-date.
+#
+<details/{hxx ixx cxx}{options}>: details/cli{options} $cli
{
- if $cli.configured
- {
- cli.cxx{options}: cli{options}
-
- cli.options += --include-with-brackets --include-prefix odb/pgsql/details \
---guard-prefix LIBODB_PGSQL_DETAILS --generate-file-scanner \
---cli-namespace odb::pgsql::details::cli --long-usage --generate-specifier \
---no-combined-flags
-
- # Include generated cli files into the distribution and don't remove them
- # when cleaning in src (so that clean results in a state identical to
- # distributed). But don't install their headers since they are only used
- # internally in the database implementation.
- #
- cli.cxx{*}:
- {
- dist = true
- clean = ($src_root != $out_root)
- install = false
- }
- }
- else
- # No install for the pre-generated case.
- #
- hxx{options}@./ ixx{options}@./: install = false
+ install = false
+ dist = ($develop ? pregenerated/odb/pgsql/details/ : false)
+
+ # Symlink the generated code in src for convenience of development.
+ #
+ backlink = true
}
+%
+if $develop
+{{
+ options = --include-with-brackets --include-prefix odb/pgsql/details \
+ --guard-prefix LIBODB_PGSQL_DETAILS --generate-file-scanner \
+ --cli-namespace odb::pgsql::details::cli --long-usage \
+ --generate-specifier --no-combined-flags
+
+ $cli $options -o $out_base/details/ $path($<[0])
+
+ # If the result differs from the pregenerated version, copy it over.
+ #
+ d = [dir_path] $src_base/details/pregenerated/odb/pgsql/details/
+
+ if diff $d/options.hxx $path($>[0]) >- && \
+ diff $d/options.ixx $path($>[1]) >- && \
+ diff $d/options.cxx $path($>[2]) >-
+ exit
+ end
+
+ cp $path($>[0]) $d/options.hxx
+ cp $path($>[1]) $d/options.ixx
+ cp $path($>[2]) $d/options.cxx
+}}
# Install into the odb/pgsql/ subdirectory of, say, /usr/include/
# recreating subdirectories.
@@ -100,7 +142,7 @@ details/build2/
{
h{*}: install = false
- if ($cxx.class == 'msvc')
+ if ($cxx.target.system == 'win32-msvc')
{
h{config-vc}@./: install = $install_include/details/
h{config-vc-stub}@./: install = $install_include/details/build2/config-vc.h
diff --git a/odb/pgsql/connection-factory.cxx b/odb/pgsql/connection-factory.cxx
index 6597c8b..855a9bc 100644
--- a/odb/pgsql/connection-factory.cxx
+++ b/odb/pgsql/connection-factory.cxx
@@ -1,5 +1,4 @@
// file : odb/pgsql/connection-factory.cxx
-// copyright : Copyright (c) 2009-2019 Code Synthesis Tools CC
// license : GNU GPL v2; see accompanying LICENSE file
#include <odb/pgsql/connection-factory.hxx>
diff --git a/odb/pgsql/connection-factory.hxx b/odb/pgsql/connection-factory.hxx
index c3b95a0..2f300a8 100644
--- a/odb/pgsql/connection-factory.hxx
+++ b/odb/pgsql/connection-factory.hxx
@@ -1,5 +1,4 @@
// file : odb/pgsql/connection-factory.hxx
-// copyright : Copyright (c) 2009-2019 Code Synthesis Tools CC
// license : GNU GPL v2; see accompanying LICENSE file
#ifndef ODB_PGSQL_CONNECTION_FACTORY_HXX
diff --git a/odb/pgsql/connection.cxx b/odb/pgsql/connection.cxx
index cc6620a..80a1dd2 100644
--- a/odb/pgsql/connection.cxx
+++ b/odb/pgsql/connection.cxx
@@ -1,5 +1,4 @@
// file : odb/pgsql/connection.cxx
-// copyright : Copyright (c) 2005-2019 Code Synthesis Tools CC
// license : GNU GPL v2; see accompanying LICENSE file
#include <new> // std::bad_alloc
diff --git a/odb/pgsql/connection.hxx b/odb/pgsql/connection.hxx
index 4f8b8b0..d779273 100644
--- a/odb/pgsql/connection.hxx
+++ b/odb/pgsql/connection.hxx
@@ -1,5 +1,4 @@
// file : odb/pgsql/connection.hxx
-// copyright : Copyright (c) 2005-2019 Code Synthesis Tools CC
// license : GNU GPL v2; see accompanying LICENSE file
#ifndef ODB_PGSQL_CONNECTION_HXX
diff --git a/odb/pgsql/connection.ixx b/odb/pgsql/connection.ixx
index 4b29999..76d558b 100644
--- a/odb/pgsql/connection.ixx
+++ b/odb/pgsql/connection.ixx
@@ -1,5 +1,4 @@
// file : odb/pgsql/connection.ixx
-// copyright : Copyright (c) 2005-2019 Code Synthesis Tools CC
// license : GNU GPL v2; see accompanying LICENSE file
namespace odb
diff --git a/odb/pgsql/container-statements.hxx b/odb/pgsql/container-statements.hxx
index c387dce..1856bb9 100644
--- a/odb/pgsql/container-statements.hxx
+++ b/odb/pgsql/container-statements.hxx
@@ -1,5 +1,4 @@
// file : odb/pgsql/container-statements.hxx
-// copyright : Copyright (c) 2005-2019 Code Synthesis Tools CC
// license : GNU GPL v2; see accompanying LICENSE file
#ifndef ODB_PGSQL_CONTAINER_STATEMENTS_HXX
diff --git a/odb/pgsql/container-statements.txx b/odb/pgsql/container-statements.txx
index 86fea2a..34eb99f 100644
--- a/odb/pgsql/container-statements.txx
+++ b/odb/pgsql/container-statements.txx
@@ -1,5 +1,4 @@
// file : odb/pgsql/container-statements.txx
-// copyright : Copyright (c) 2005-2019 Code Synthesis Tools CC
// license : GNU GPL v2; see accompanying LICENSE file
#include <cstddef> // std::size_t
diff --git a/odb/pgsql/database.cxx b/odb/pgsql/database.cxx
index 8c4c99f..09bf6f0 100644
--- a/odb/pgsql/database.cxx
+++ b/odb/pgsql/database.cxx
@@ -1,5 +1,4 @@
// file : odb/pgsql/database.cxx
-// copyright : Copyright (c) 2009-2019 Code Synthesis Tools CC
// license : GNU GPL v2; see accompanying LICENSE file
#include <cstring> // strlen()
@@ -250,10 +249,11 @@ namespace odb
// Bind parameters and results.
//
+ char* pbuf[1] = {const_cast<char*> (name.c_str ())};
size_t psize[1] = {name.size ()};
bool pnull[1] = {false};
bind pbind[1] = {{bind::text,
- const_cast<char*> (name.c_str ()),
+ &pbuf[0],
&psize[0],
psize[0],
&pnull[0],
@@ -283,7 +283,9 @@ namespace odb
cp = factory_->connect ();
pgsql::connection& c (
- cp != 0 ? *cp : transaction::current ().connection ());
+ cp != 0
+ ? *cp
+ : transaction::current ().connection (const_cast<database&> (*this)));
// If we are in the user's transaction then things are complicated. When
// we try to execute SELECT on a non-existent table, PG "poisons" the
@@ -301,10 +303,11 @@ namespace odb
bool exists (true);
if (cp == 0 && c.server_version () >= 90400)
{
+ char* pbuf[1] = {const_cast<char*> (table)};
size_t psize[1] = {strlen (table)};
bool pnull[1] = {false};
bind pbind[1] = {{bind::text,
- const_cast<char*> (table),
+ &pbuf[0],
&psize[0],
psize[0],
&pnull[0],
@@ -320,7 +323,7 @@ namespace odb
native_binding nparam (values, lengths, formats, 1);
bool rnull[1];
- bind rbind[1] = {{bind::boolean_, &exists, 0, 0, &rnull[1], 0}};
+ bind rbind[1] = {{bind::boolean_, &exists, 0, 0, &rnull[0], 0}};
binding result (rbind, 1);
result.version++;
diff --git a/odb/pgsql/database.hxx b/odb/pgsql/database.hxx
index 2e5f158..950cad1 100644
--- a/odb/pgsql/database.hxx
+++ b/odb/pgsql/database.hxx
@@ -1,5 +1,4 @@
// file : odb/pgsql/database.hxx
-// copyright : Copyright (c) 2009-2019 Code Synthesis Tools CC
// license : GNU GPL v2; see accompanying LICENSE file
#ifndef ODB_PGSQL_DATABASE_HXX
@@ -80,6 +79,9 @@ namespace odb
// Move-constructible but not move-assignable.
//
+ // Note: noexcept is not specified since odb::database(odb::database&&)
+ // can throw.
+ //
#ifdef ODB_CXX11
database (database&&);
#endif
@@ -125,6 +127,13 @@ namespace odb
typename object_traits<T>::id_type
persist (const typename object_traits<T>::pointer_type& obj_ptr);
+ // Bulk persist. Can be a range of references or pointers (including
+ // smart pointers) to objects.
+ //
+ template <typename I>
+ void
+ persist (I begin, I end, bool continue_failed = true);
+
// Load an object. Throw object_not_persistent if not found.
//
template <typename T>
@@ -211,6 +220,13 @@ namespace odb
void
update (const typename object_traits<T>::pointer_type& obj_ptr);
+ // Bulk update. Can be a range of references or pointers (including
+ // smart pointers) to objects.
+ //
+ template <typename I>
+ void
+ update (I begin, I end, bool continue_failed = true);
+
// Update a section of an object. Throws the section_not_loaded
// exception if the section is not loaded. Note also that this
// function does not clear the changed flag if it is set.
@@ -254,6 +270,19 @@ namespace odb
void
erase (const typename object_traits<T>::pointer_type& obj_ptr);
+ // Bulk erase.
+ //
+ template <typename T, typename I>
+ void
+ erase (I id_begin, I id_end, bool continue_failed = true);
+
+ // Can be a range of references or pointers (including smart pointers)
+ // to objects.
+ //
+ template <typename I>
+ void
+ erase (I obj_begin, I obj_end, bool continue_failed = true);
+
// Erase multiple objects matching a query predicate.
//
template <typename T>
diff --git a/odb/pgsql/database.ixx b/odb/pgsql/database.ixx
index 67c8470..f04c3e6 100644
--- a/odb/pgsql/database.ixx
+++ b/odb/pgsql/database.ixx
@@ -1,5 +1,4 @@
// file : odb/pgsql/database.ixx
-// copyright : Copyright (c) 2009-2019 Code Synthesis Tools CC
// license : GNU GPL v2; see accompanying LICENSE file
#include <utility> // move()
@@ -120,6 +119,13 @@ namespace odb
return persist_<T, id_pgsql> (pobj);
}
+ template <typename I>
+ inline void database::
+ persist (I b, I e, bool cont)
+ {
+ persist_<I, id_pgsql> (b, e, cont);
+ }
+
template <typename T>
inline typename object_traits<T>::pointer_type database::
load (const typename object_traits<T>::id_type& id)
@@ -281,6 +287,13 @@ namespace odb
update_<T, id_pgsql> (pobj);
}
+ template <typename I>
+ inline void database::
+ update (I b, I e, bool cont)
+ {
+ update_<I, id_pgsql> (b, e, cont);
+ }
+
template <typename T>
inline void database::
update (const T& obj, const section& s)
@@ -370,6 +383,20 @@ namespace odb
erase_<T, id_pgsql> (pobj);
}
+ template <typename T, typename I>
+ inline void database::
+ erase (I idb, I ide, bool cont)
+ {
+ erase_id_<I, T, id_pgsql> (idb, ide, cont);
+ }
+
+ template <typename I>
+ inline void database::
+ erase (I ob, I oe, bool cont)
+ {
+ erase_object_<I, id_pgsql> (ob, oe, cont);
+ }
+
template <typename T>
inline unsigned long long database::
erase_query ()
@@ -595,7 +622,7 @@ namespace odb
{
// Throws if not in transaction.
//
- pgsql::connection& c (transaction::current ().connection ());
+ pgsql::connection& c (transaction::current ().connection (*this));
return c.prepare_query<T> (n, q);
}
diff --git a/odb/pgsql/details/.gitignore b/odb/pgsql/details/.gitignore
index c6e608b..b298f89 100644
--- a/odb/pgsql/details/.gitignore
+++ b/odb/pgsql/details/.gitignore
@@ -1 +1 @@
-options.?xx
+/options.?xx
diff --git a/odb/pgsql/details/build2/config-stub.h b/odb/pgsql/details/build2/config-stub.h
index 24aed55..00c5940 100644
--- a/odb/pgsql/details/build2/config-stub.h
+++ b/odb/pgsql/details/build2/config-stub.h
@@ -1,5 +1,4 @@
/* file : odb/pgsql/details/build2/config-stub.h
- * copyright : Copyright (c) 2009-2019 Code Synthesis Tools CC
* license : GNU GPL v2; see accompanying LICENSE file
*/
diff --git a/odb/pgsql/details/build2/config-vc-stub.h b/odb/pgsql/details/build2/config-vc-stub.h
index 3bf175e..473cd96 100644
--- a/odb/pgsql/details/build2/config-vc-stub.h
+++ b/odb/pgsql/details/build2/config-vc-stub.h
@@ -1,5 +1,4 @@
/* file : odb/pgsql/details/build2/config-vc-stub.h
- * copyright : Copyright (c) 2009-2019 Code Synthesis Tools CC
* license : GNU GPL v2; see accompanying LICENSE file
*/
diff --git a/odb/pgsql/details/build2/config-vc.h b/odb/pgsql/details/build2/config-vc.h
index 006837d..e9d9ade 100644
--- a/odb/pgsql/details/build2/config-vc.h
+++ b/odb/pgsql/details/build2/config-vc.h
@@ -1,5 +1,4 @@
/* file : odb/pgsql/details/build2/config-vc.h
- * copyright : Copyright (c) 2009-2019 Code Synthesis Tools CC
* license : GNU GPL v2; see accompanying LICENSE file
*/
diff --git a/odb/pgsql/details/build2/config.h b/odb/pgsql/details/build2/config.h
index 3de4c9c..b2a81b5 100644
--- a/odb/pgsql/details/build2/config.h
+++ b/odb/pgsql/details/build2/config.h
@@ -1,5 +1,4 @@
/* file : odb/pgsql/details/build2/config.h
- * copyright : Copyright (c) 2009-2019 Code Synthesis Tools CC
* license : GNU GPL v2; see accompanying LICENSE file
*/
diff --git a/odb/pgsql/details/config-vc.h b/odb/pgsql/details/config-vc.h
index 0614fde..77a0be5 100644
--- a/odb/pgsql/details/config-vc.h
+++ b/odb/pgsql/details/config-vc.h
@@ -1,5 +1,4 @@
/* file : odb/pgsql/details/config-vc.h
- * copyright : Copyright (c) 2009-2019 Code Synthesis Tools CC
* license : GNU GPL v2; see accompanying LICENSE file
*/
diff --git a/odb/pgsql/details/config.h.in b/odb/pgsql/details/config.h.in
index fcf2202..889023c 100644
--- a/odb/pgsql/details/config.h.in
+++ b/odb/pgsql/details/config.h.in
@@ -1,5 +1,4 @@
/* file : odb/pgsql/details/config.h.in
- * copyright : Copyright (c) 2009-2019 Code Synthesis Tools CC
* license : GNU GPL v2; see accompanying LICENSE file
*/
diff --git a/odb/pgsql/details/config.hxx b/odb/pgsql/details/config.hxx
index 07cf541..1340622 100644
--- a/odb/pgsql/details/config.hxx
+++ b/odb/pgsql/details/config.hxx
@@ -1,5 +1,4 @@
// file : odb/pgsql/details/config.hxx
-// copyright : Copyright (c) 2005-2019 Code Synthesis Tools CC
// license : GNU GPL v2; see accompanying LICENSE file
#ifndef ODB_PGSQL_DETAILS_CONFIG_HXX
diff --git a/odb/pgsql/details/conversion.hxx b/odb/pgsql/details/conversion.hxx
index 1033c29..b4d7e4f 100644
--- a/odb/pgsql/details/conversion.hxx
+++ b/odb/pgsql/details/conversion.hxx
@@ -1,5 +1,4 @@
// file : odb/pgsql/details/conversion.hxx
-// copyright : Copyright (c) 2009-2019 Code Synthesis Tools CC
// license : GNU GPL v2; see accompanying LICENSE file
#ifndef ODB_PGSQL_DETAILS_CONVERSION_HXX
diff --git a/odb/pgsql/details/endian-traits.cxx b/odb/pgsql/details/endian-traits.cxx
index 1c74878..77fdc95 100644
--- a/odb/pgsql/details/endian-traits.cxx
+++ b/odb/pgsql/details/endian-traits.cxx
@@ -1,5 +1,4 @@
// file : odb/pgsql/details/endian-traits.cxx
-// copyright : Copyright (c) 2009-2019 Code Synthesis Tools CC
// license : GNU GPL v2; see accompanying LICENSE file
#include <odb/pgsql/details/endian-traits.hxx>
diff --git a/odb/pgsql/details/endian-traits.hxx b/odb/pgsql/details/endian-traits.hxx
index d02a7b2..532a4a3 100644
--- a/odb/pgsql/details/endian-traits.hxx
+++ b/odb/pgsql/details/endian-traits.hxx
@@ -1,5 +1,4 @@
// file : odb/pgsql/details/endian-traits.hxx
-// copyright : Copyright (c) 2009-2019 Code Synthesis Tools CC
// license : GNU GPL v2; see accompanying LICENSE file
#ifndef ODB_PGSQL_DETAILS_ENDIAN_TRAITS_HXX
diff --git a/odb/pgsql/details/export.hxx b/odb/pgsql/details/export.hxx
index 3b86702..81ff6a0 100644
--- a/odb/pgsql/details/export.hxx
+++ b/odb/pgsql/details/export.hxx
@@ -1,5 +1,4 @@
// file : odb/pgsql/details/export.hxx
-// copyright : Copyright (c) 2005-2019 Code Synthesis Tools CC
// license : GNU GPL v2; see accompanying LICENSE file
#ifndef ODB_PGSQL_DETAILS_EXPORT_HXX
diff --git a/odb/pgsql/details/options.cli b/odb/pgsql/details/options.cli
index 886a869..f568236 100644
--- a/odb/pgsql/details/options.cli
+++ b/odb/pgsql/details/options.cli
@@ -1,5 +1,4 @@
// file : odb/pgsql/details/options.cli
-// copyright : Copyright (c) 2009-2019 Code Synthesis Tools CC
// license : GNU GPL v2; see accompanying LICENSE file
include <string>;
diff --git a/odb/pgsql/details/pregenerated/odb/pgsql/details/options.cxx b/odb/pgsql/details/pregenerated/odb/pgsql/details/options.cxx
new file mode 100644
index 0000000..a4a5da6
--- /dev/null
+++ b/odb/pgsql/details/pregenerated/odb/pgsql/details/options.cxx
@@ -0,0 +1,1114 @@
+// -*- C++ -*-
+//
+// This file was generated by CLI, a command line interface
+// compiler for C++.
+//
+
+// Begin prologue.
+//
+//
+// End prologue.
+
+#include <odb/pgsql/details/options.hxx>
+
+#include <map>
+#include <set>
+#include <string>
+#include <vector>
+#include <utility>
+#include <ostream>
+#include <sstream>
+#include <cstring>
+#include <fstream>
+
+namespace odb
+{
+ namespace pgsql
+ {
+ namespace details
+ {
+ namespace cli
+ {
+ // unknown_option
+ //
+ unknown_option::
+ ~unknown_option () throw ()
+ {
+ }
+
+ void unknown_option::
+ print (::std::ostream& os) const
+ {
+ os << "unknown option '" << option ().c_str () << "'";
+ }
+
+ const char* unknown_option::
+ what () const throw ()
+ {
+ return "unknown option";
+ }
+
+ // unknown_argument
+ //
+ unknown_argument::
+ ~unknown_argument () throw ()
+ {
+ }
+
+ void unknown_argument::
+ print (::std::ostream& os) const
+ {
+ os << "unknown argument '" << argument ().c_str () << "'";
+ }
+
+ const char* unknown_argument::
+ what () const throw ()
+ {
+ return "unknown argument";
+ }
+
+ // missing_value
+ //
+ missing_value::
+ ~missing_value () throw ()
+ {
+ }
+
+ void missing_value::
+ print (::std::ostream& os) const
+ {
+ os << "missing value for option '" << option ().c_str () << "'";
+ }
+
+ const char* missing_value::
+ what () const throw ()
+ {
+ return "missing option value";
+ }
+
+ // invalid_value
+ //
+ invalid_value::
+ ~invalid_value () throw ()
+ {
+ }
+
+ void invalid_value::
+ print (::std::ostream& os) const
+ {
+ os << "invalid value '" << value ().c_str () << "' for option '"
+ << option ().c_str () << "'";
+
+ if (!message ().empty ())
+ os << ": " << message ().c_str ();
+ }
+
+ const char* invalid_value::
+ what () const throw ()
+ {
+ return "invalid option value";
+ }
+
+ // eos_reached
+ //
+ void eos_reached::
+ print (::std::ostream& os) const
+ {
+ os << what ();
+ }
+
+ const char* eos_reached::
+ what () const throw ()
+ {
+ return "end of argument stream reached";
+ }
+
+ // file_io_failure
+ //
+ file_io_failure::
+ ~file_io_failure () throw ()
+ {
+ }
+
+ void file_io_failure::
+ print (::std::ostream& os) const
+ {
+ os << "unable to open file '" << file ().c_str () << "' or read failure";
+ }
+
+ const char* file_io_failure::
+ what () const throw ()
+ {
+ return "unable to open file or read failure";
+ }
+
+ // unmatched_quote
+ //
+ unmatched_quote::
+ ~unmatched_quote () throw ()
+ {
+ }
+
+ void unmatched_quote::
+ print (::std::ostream& os) const
+ {
+ os << "unmatched quote in argument '" << argument ().c_str () << "'";
+ }
+
+ const char* unmatched_quote::
+ what () const throw ()
+ {
+ return "unmatched quote";
+ }
+
+ // scanner
+ //
+ scanner::
+ ~scanner ()
+ {
+ }
+
+ // argv_scanner
+ //
+ bool argv_scanner::
+ more ()
+ {
+ return i_ < argc_;
+ }
+
+ const char* argv_scanner::
+ peek ()
+ {
+ if (i_ < argc_)
+ return argv_[i_];
+ else
+ throw eos_reached ();
+ }
+
+ const char* argv_scanner::
+ next ()
+ {
+ if (i_ < argc_)
+ {
+ const char* r (argv_[i_]);
+
+ if (erase_)
+ {
+ for (int i (i_ + 1); i < argc_; ++i)
+ argv_[i - 1] = argv_[i];
+
+ --argc_;
+ argv_[argc_] = 0;
+ }
+ else
+ ++i_;
+
+ ++start_position_;
+ return r;
+ }
+ else
+ throw eos_reached ();
+ }
+
+ void argv_scanner::
+ skip ()
+ {
+ if (i_ < argc_)
+ {
+ ++i_;
+ ++start_position_;
+ }
+ else
+ throw eos_reached ();
+ }
+
+ std::size_t argv_scanner::
+ position ()
+ {
+ return start_position_;
+ }
+
+ // argv_file_scanner
+ //
+ int argv_file_scanner::zero_argc_ = 0;
+ std::string argv_file_scanner::empty_string_;
+
+ bool argv_file_scanner::
+ more ()
+ {
+ if (!args_.empty ())
+ return true;
+
+ while (base::more ())
+ {
+ // See if the next argument is the file option.
+ //
+ const char* a (base::peek ());
+ const option_info* oi = 0;
+ const char* ov = 0;
+
+ if (!skip_)
+ {
+ if ((oi = find (a)) != 0)
+ {
+ base::next ();
+
+ if (!base::more ())
+ throw missing_value (a);
+
+ ov = base::next ();
+ }
+ else if (std::strncmp (a, "-", 1) == 0)
+ {
+ if ((ov = std::strchr (a, '=')) != 0)
+ {
+ std::string o (a, 0, ov - a);
+ if ((oi = find (o.c_str ())) != 0)
+ {
+ base::next ();
+ ++ov;
+ }
+ }
+ }
+ }
+
+ if (oi != 0)
+ {
+ if (oi->search_func != 0)
+ {
+ std::string f (oi->search_func (ov, oi->arg));
+
+ if (!f.empty ())
+ load (f);
+ }
+ else
+ load (ov);
+
+ if (!args_.empty ())
+ return true;
+ }
+ else
+ {
+ if (!skip_)
+ skip_ = (std::strcmp (a, "--") == 0);
+
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ const char* argv_file_scanner::
+ peek ()
+ {
+ if (!more ())
+ throw eos_reached ();
+
+ return args_.empty () ? base::peek () : args_.front ().value.c_str ();
+ }
+
+ const std::string& argv_file_scanner::
+ peek_file ()
+ {
+ if (!more ())
+ throw eos_reached ();
+
+ return args_.empty () ? empty_string_ : *args_.front ().file;
+ }
+
+ std::size_t argv_file_scanner::
+ peek_line ()
+ {
+ if (!more ())
+ throw eos_reached ();
+
+ return args_.empty () ? 0 : args_.front ().line;
+ }
+
+ const char* argv_file_scanner::
+ next ()
+ {
+ if (!more ())
+ throw eos_reached ();
+
+ if (args_.empty ())
+ return base::next ();
+ else
+ {
+ hold_[i_ == 0 ? ++i_ : --i_].swap (args_.front ().value);
+ args_.pop_front ();
+ ++start_position_;
+ return hold_[i_].c_str ();
+ }
+ }
+
+ void argv_file_scanner::
+ skip ()
+ {
+ if (!more ())
+ throw eos_reached ();
+
+ if (args_.empty ())
+ return base::skip ();
+ else
+ {
+ args_.pop_front ();
+ ++start_position_;
+ }
+ }
+
+ const argv_file_scanner::option_info* argv_file_scanner::
+ find (const char* a) const
+ {
+ for (std::size_t i (0); i < options_count_; ++i)
+ if (std::strcmp (a, options_[i].option) == 0)
+ return &options_[i];
+
+ return 0;
+ }
+
+ std::size_t argv_file_scanner::
+ position ()
+ {
+ return start_position_;
+ }
+
+ void argv_file_scanner::
+ load (const std::string& file)
+ {
+ using namespace std;
+
+ ifstream is (file.c_str ());
+
+ if (!is.is_open ())
+ throw file_io_failure (file);
+
+ files_.push_back (file);
+
+ arg a;
+ a.file = &*files_.rbegin ();
+
+ for (a.line = 1; !is.eof (); ++a.line)
+ {
+ string line;
+ getline (is, line);
+
+ if (is.fail () && !is.eof ())
+ throw file_io_failure (file);
+
+ string::size_type n (line.size ());
+
+ // Trim the line from leading and trailing whitespaces.
+ //
+ if (n != 0)
+ {
+ const char* f (line.c_str ());
+ const char* l (f + n);
+
+ const char* of (f);
+ while (f < l && (*f == ' ' || *f == '\t' || *f == '\r'))
+ ++f;
+
+ --l;
+
+ const char* ol (l);
+ while (l > f && (*l == ' ' || *l == '\t' || *l == '\r'))
+ --l;
+
+ if (f != of || l != ol)
+ line = f <= l ? string (f, l - f + 1) : string ();
+ }
+
+ // Ignore empty lines, those that start with #.
+ //
+ if (line.empty () || line[0] == '#')
+ continue;
+
+ string::size_type p (string::npos);
+ if (line.compare (0, 1, "-") == 0)
+ {
+ p = line.find (' ');
+
+ string::size_type q (line.find ('='));
+ if (q != string::npos && q < p)
+ p = q;
+ }
+
+ string s1;
+ if (p != string::npos)
+ {
+ s1.assign (line, 0, p);
+
+ // Skip leading whitespaces in the argument.
+ //
+ if (line[p] == '=')
+ ++p;
+ else
+ {
+ n = line.size ();
+ for (++p; p < n; ++p)
+ {
+ char c (line[p]);
+ if (c != ' ' && c != '\t' && c != '\r')
+ break;
+ }
+ }
+ }
+ else if (!skip_)
+ skip_ = (line == "--");
+
+ string s2 (line, p != string::npos ? p : 0);
+
+ // If the string (which is an option value or argument) is
+ // wrapped in quotes, remove them.
+ //
+ n = s2.size ();
+ char cf (s2[0]), cl (s2[n - 1]);
+
+ if (cf == '"' || cf == '\'' || cl == '"' || cl == '\'')
+ {
+ if (n == 1 || cf != cl)
+ throw unmatched_quote (s2);
+
+ s2 = string (s2, 1, n - 2);
+ }
+
+ if (!s1.empty ())
+ {
+ // See if this is another file option.
+ //
+ const option_info* oi;
+ if (!skip_ && (oi = find (s1.c_str ())))
+ {
+ if (s2.empty ())
+ throw missing_value (oi->option);
+
+ if (oi->search_func != 0)
+ {
+ string f (oi->search_func (s2.c_str (), oi->arg));
+ if (!f.empty ())
+ load (f);
+ }
+ else
+ {
+ // If the path of the file being parsed is not simple and the
+ // path of the file that needs to be loaded is relative, then
+ // complete the latter using the former as a base.
+ //
+#ifndef _WIN32
+ string::size_type p (file.find_last_of ('/'));
+ bool c (p != string::npos && s2[0] != '/');
+#else
+ string::size_type p (file.find_last_of ("/\\"));
+ bool c (p != string::npos && s2[1] != ':');
+#endif
+ if (c)
+ s2.insert (0, file, 0, p + 1);
+
+ load (s2);
+ }
+
+ continue;
+ }
+
+ a.value = s1;
+ args_.push_back (a);
+ }
+
+ a.value = s2;
+ args_.push_back (a);
+ }
+ }
+
+ template <typename X>
+ struct parser
+ {
+ static void
+ parse (X& x, bool& xs, scanner& s)
+ {
+ using namespace std;
+
+ const char* o (s.next ());
+ if (s.more ())
+ {
+ string v (s.next ());
+ istringstream is (v);
+ if (!(is >> x && is.peek () == istringstream::traits_type::eof ()))
+ throw invalid_value (o, v);
+ }
+ else
+ throw missing_value (o);
+
+ xs = true;
+ }
+ };
+
+ template <>
+ struct parser<bool>
+ {
+ static void
+ parse (bool& x, bool& xs, scanner& s)
+ {
+ const char* o (s.next ());
+
+ if (s.more ())
+ {
+ const char* v (s.next ());
+
+ if (std::strcmp (v, "1") == 0 ||
+ std::strcmp (v, "true") == 0 ||
+ std::strcmp (v, "TRUE") == 0 ||
+ std::strcmp (v, "True") == 0)
+ x = true;
+ else if (std::strcmp (v, "0") == 0 ||
+ std::strcmp (v, "false") == 0 ||
+ std::strcmp (v, "FALSE") == 0 ||
+ std::strcmp (v, "False") == 0)
+ x = false;
+ else
+ throw invalid_value (o, v);
+ }
+ else
+ throw missing_value (o);
+
+ xs = true;
+ }
+ };
+
+ template <>
+ struct parser<std::string>
+ {
+ static void
+ parse (std::string& x, bool& xs, scanner& s)
+ {
+ const char* o (s.next ());
+
+ if (s.more ())
+ x = s.next ();
+ else
+ throw missing_value (o);
+
+ xs = true;
+ }
+ };
+
+ template <typename X>
+ struct parser<std::pair<X, std::size_t> >
+ {
+ static void
+ parse (std::pair<X, std::size_t>& x, bool& xs, scanner& s)
+ {
+ x.second = s.position ();
+ parser<X>::parse (x.first, xs, s);
+ }
+ };
+
+ template <typename X>
+ struct parser<std::vector<X> >
+ {
+ static void
+ parse (std::vector<X>& c, bool& xs, scanner& s)
+ {
+ X x;
+ bool dummy;
+ parser<X>::parse (x, dummy, s);
+ c.push_back (x);
+ xs = true;
+ }
+ };
+
+ template <typename X, typename C>
+ struct parser<std::set<X, C> >
+ {
+ static void
+ parse (std::set<X, C>& c, bool& xs, scanner& s)
+ {
+ X x;
+ bool dummy;
+ parser<X>::parse (x, dummy, s);
+ c.insert (x);
+ xs = true;
+ }
+ };
+
+ template <typename K, typename V, typename C>
+ struct parser<std::map<K, V, C> >
+ {
+ static void
+ parse (std::map<K, V, C>& m, bool& xs, scanner& s)
+ {
+ const char* o (s.next ());
+
+ if (s.more ())
+ {
+ std::size_t pos (s.position ());
+ std::string ov (s.next ());
+ std::string::size_type p = ov.find ('=');
+
+ K k = K ();
+ V v = V ();
+ std::string kstr (ov, 0, p);
+ std::string vstr (ov, (p != std::string::npos ? p + 1 : ov.size ()));
+
+ int ac (2);
+ char* av[] =
+ {
+ const_cast<char*> (o),
+ 0
+ };
+
+ bool dummy;
+ if (!kstr.empty ())
+ {
+ av[1] = const_cast<char*> (kstr.c_str ());
+ argv_scanner s (0, ac, av, false, pos);
+ parser<K>::parse (k, dummy, s);
+ }
+
+ if (!vstr.empty ())
+ {
+ av[1] = const_cast<char*> (vstr.c_str ());
+ argv_scanner s (0, ac, av, false, pos);
+ parser<V>::parse (v, dummy, s);
+ }
+
+ m[k] = v;
+ }
+ else
+ throw missing_value (o);
+
+ xs = true;
+ }
+ };
+
+ template <typename K, typename V, typename C>
+ struct parser<std::multimap<K, V, C> >
+ {
+ static void
+ parse (std::multimap<K, V, C>& m, bool& xs, scanner& s)
+ {
+ const char* o (s.next ());
+
+ if (s.more ())
+ {
+ std::size_t pos (s.position ());
+ std::string ov (s.next ());
+ std::string::size_type p = ov.find ('=');
+
+ K k = K ();
+ V v = V ();
+ std::string kstr (ov, 0, p);
+ std::string vstr (ov, (p != std::string::npos ? p + 1 : ov.size ()));
+
+ int ac (2);
+ char* av[] =
+ {
+ const_cast<char*> (o),
+ 0
+ };
+
+ bool dummy;
+ if (!kstr.empty ())
+ {
+ av[1] = const_cast<char*> (kstr.c_str ());
+ argv_scanner s (0, ac, av, false, pos);
+ parser<K>::parse (k, dummy, s);
+ }
+
+ if (!vstr.empty ())
+ {
+ av[1] = const_cast<char*> (vstr.c_str ());
+ argv_scanner s (0, ac, av, false, pos);
+ parser<V>::parse (v, dummy, s);
+ }
+
+ m.insert (typename std::multimap<K, V, C>::value_type (k, v));
+ }
+ else
+ throw missing_value (o);
+
+ xs = true;
+ }
+ };
+
+ template <typename X, typename T, T X::*M>
+ void
+ thunk (X& x, scanner& s)
+ {
+ parser<T>::parse (x.*M, s);
+ }
+
+ template <typename X, bool X::*M>
+ void
+ thunk (X& x, scanner& s)
+ {
+ s.next ();
+ x.*M = true;
+ }
+
+ template <typename X, typename T, T X::*M, bool X::*S>
+ void
+ thunk (X& x, scanner& s)
+ {
+ parser<T>::parse (x.*M, x.*S, s);
+ }
+ }
+ }
+ }
+}
+
+#include <map>
+
+namespace odb
+{
+ namespace pgsql
+ {
+ namespace details
+ {
+ // options
+ //
+
+ options::
+ options ()
+ : user_ (),
+ user_specified_ (false),
+ password_ (),
+ password_specified_ (false),
+ database_ (),
+ database_specified_ (false),
+ host_ (),
+ host_specified_ (false),
+ port_ (),
+ port_specified_ (false),
+ options_file_ (),
+ options_file_specified_ (false)
+ {
+ }
+
+ options::
+ options (int& argc,
+ char** argv,
+ bool erase,
+ ::odb::pgsql::details::cli::unknown_mode opt,
+ ::odb::pgsql::details::cli::unknown_mode arg)
+ : user_ (),
+ user_specified_ (false),
+ password_ (),
+ password_specified_ (false),
+ database_ (),
+ database_specified_ (false),
+ host_ (),
+ host_specified_ (false),
+ port_ (),
+ port_specified_ (false),
+ options_file_ (),
+ options_file_specified_ (false)
+ {
+ ::odb::pgsql::details::cli::argv_scanner s (argc, argv, erase);
+ _parse (s, opt, arg);
+ }
+
+ options::
+ options (int start,
+ int& argc,
+ char** argv,
+ bool erase,
+ ::odb::pgsql::details::cli::unknown_mode opt,
+ ::odb::pgsql::details::cli::unknown_mode arg)
+ : user_ (),
+ user_specified_ (false),
+ password_ (),
+ password_specified_ (false),
+ database_ (),
+ database_specified_ (false),
+ host_ (),
+ host_specified_ (false),
+ port_ (),
+ port_specified_ (false),
+ options_file_ (),
+ options_file_specified_ (false)
+ {
+ ::odb::pgsql::details::cli::argv_scanner s (start, argc, argv, erase);
+ _parse (s, opt, arg);
+ }
+
+ options::
+ options (int& argc,
+ char** argv,
+ int& end,
+ bool erase,
+ ::odb::pgsql::details::cli::unknown_mode opt,
+ ::odb::pgsql::details::cli::unknown_mode arg)
+ : user_ (),
+ user_specified_ (false),
+ password_ (),
+ password_specified_ (false),
+ database_ (),
+ database_specified_ (false),
+ host_ (),
+ host_specified_ (false),
+ port_ (),
+ port_specified_ (false),
+ options_file_ (),
+ options_file_specified_ (false)
+ {
+ ::odb::pgsql::details::cli::argv_scanner s (argc, argv, erase);
+ _parse (s, opt, arg);
+ end = s.end ();
+ }
+
+ options::
+ options (int start,
+ int& argc,
+ char** argv,
+ int& end,
+ bool erase,
+ ::odb::pgsql::details::cli::unknown_mode opt,
+ ::odb::pgsql::details::cli::unknown_mode arg)
+ : user_ (),
+ user_specified_ (false),
+ password_ (),
+ password_specified_ (false),
+ database_ (),
+ database_specified_ (false),
+ host_ (),
+ host_specified_ (false),
+ port_ (),
+ port_specified_ (false),
+ options_file_ (),
+ options_file_specified_ (false)
+ {
+ ::odb::pgsql::details::cli::argv_scanner s (start, argc, argv, erase);
+ _parse (s, opt, arg);
+ end = s.end ();
+ }
+
+ options::
+ options (::odb::pgsql::details::cli::scanner& s,
+ ::odb::pgsql::details::cli::unknown_mode opt,
+ ::odb::pgsql::details::cli::unknown_mode arg)
+ : user_ (),
+ user_specified_ (false),
+ password_ (),
+ password_specified_ (false),
+ database_ (),
+ database_specified_ (false),
+ host_ (),
+ host_specified_ (false),
+ port_ (),
+ port_specified_ (false),
+ options_file_ (),
+ options_file_specified_ (false)
+ {
+ _parse (s, opt, arg);
+ }
+
+ ::odb::pgsql::details::cli::usage_para options::
+ print_usage (::std::ostream& os, ::odb::pgsql::details::cli::usage_para p)
+ {
+ CLI_POTENTIALLY_UNUSED (os);
+
+ if (p != ::odb::pgsql::details::cli::usage_para::none)
+ os << ::std::endl;
+
+ os << "--user|--username <name> PostgreSQL database user." << ::std::endl;
+
+ os << std::endl
+ << "--password <str> PostgreSQL database password." << ::std::endl;
+
+ os << std::endl
+ << "--database|--dbname <name> PostgreSQL database name." << ::std::endl;
+
+ os << std::endl
+ << "--host <str> PostgreSQL database host name or address (localhost" << ::std::endl
+ << " by default)." << ::std::endl;
+
+ os << std::endl
+ << "--port <str> PostgreSQL database port number or socket file name" << ::std::endl
+ << " extension for Unix-domain connections." << ::std::endl;
+
+ os << std::endl
+ << "--options-file <file> Read additional options from <file>. Each option" << ::std::endl
+ << " should appear on a separate line optionally followed" << ::std::endl
+ << " by space or equal sign (=) and an option value." << ::std::endl
+ << " Empty lines and lines starting with # are ignored." << ::std::endl;
+
+ p = ::odb::pgsql::details::cli::usage_para::option;
+
+ return p;
+ }
+
+ typedef
+ std::map<std::string, void (*) (options&, ::odb::pgsql::details::cli::scanner&)>
+ _cli_options_map;
+
+ static _cli_options_map _cli_options_map_;
+
+ struct _cli_options_map_init
+ {
+ _cli_options_map_init ()
+ {
+ _cli_options_map_["--user"] =
+ &::odb::pgsql::details::cli::thunk< options, std::string, &options::user_,
+ &options::user_specified_ >;
+ _cli_options_map_["--username"] =
+ &::odb::pgsql::details::cli::thunk< options, std::string, &options::user_,
+ &options::user_specified_ >;
+ _cli_options_map_["--password"] =
+ &::odb::pgsql::details::cli::thunk< options, std::string, &options::password_,
+ &options::password_specified_ >;
+ _cli_options_map_["--database"] =
+ &::odb::pgsql::details::cli::thunk< options, std::string, &options::database_,
+ &options::database_specified_ >;
+ _cli_options_map_["--dbname"] =
+ &::odb::pgsql::details::cli::thunk< options, std::string, &options::database_,
+ &options::database_specified_ >;
+ _cli_options_map_["--host"] =
+ &::odb::pgsql::details::cli::thunk< options, std::string, &options::host_,
+ &options::host_specified_ >;
+ _cli_options_map_["--port"] =
+ &::odb::pgsql::details::cli::thunk< options, std::string, &options::port_,
+ &options::port_specified_ >;
+ _cli_options_map_["--options-file"] =
+ &::odb::pgsql::details::cli::thunk< options, std::string, &options::options_file_,
+ &options::options_file_specified_ >;
+ }
+ };
+
+ static _cli_options_map_init _cli_options_map_init_;
+
+ bool options::
+ _parse (const char* o, ::odb::pgsql::details::cli::scanner& s)
+ {
+ _cli_options_map::const_iterator i (_cli_options_map_.find (o));
+
+ if (i != _cli_options_map_.end ())
+ {
+ (*(i->second)) (*this, s);
+ return true;
+ }
+
+ return false;
+ }
+
+ bool options::
+ _parse (::odb::pgsql::details::cli::scanner& s,
+ ::odb::pgsql::details::cli::unknown_mode opt_mode,
+ ::odb::pgsql::details::cli::unknown_mode arg_mode)
+ {
+ bool r = false;
+ bool opt = true;
+
+ while (s.more ())
+ {
+ const char* o = s.peek ();
+
+ if (std::strcmp (o, "--") == 0)
+ {
+ opt = false;
+ s.skip ();
+ r = true;
+ continue;
+ }
+
+ if (opt)
+ {
+ if (_parse (o, s))
+ {
+ r = true;
+ continue;
+ }
+
+ if (std::strncmp (o, "-", 1) == 0 && o[1] != '\0')
+ {
+ // Handle combined option values.
+ //
+ std::string co;
+ if (const char* v = std::strchr (o, '='))
+ {
+ co.assign (o, 0, v - o);
+ ++v;
+
+ int ac (2);
+ char* av[] =
+ {
+ const_cast<char*> (co.c_str ()),
+ const_cast<char*> (v)
+ };
+
+ ::odb::pgsql::details::cli::argv_scanner ns (0, ac, av);
+
+ if (_parse (co.c_str (), ns))
+ {
+ // Parsed the option but not its value?
+ //
+ if (ns.end () != 2)
+ throw ::odb::pgsql::details::cli::invalid_value (co, v);
+
+ s.next ();
+ r = true;
+ continue;
+ }
+ else
+ {
+ // Set the unknown option and fall through.
+ //
+ o = co.c_str ();
+ }
+ }
+
+ switch (opt_mode)
+ {
+ case ::odb::pgsql::details::cli::unknown_mode::skip:
+ {
+ s.skip ();
+ r = true;
+ continue;
+ }
+ case ::odb::pgsql::details::cli::unknown_mode::stop:
+ {
+ break;
+ }
+ case ::odb::pgsql::details::cli::unknown_mode::fail:
+ {
+ throw ::odb::pgsql::details::cli::unknown_option (o);
+ }
+ }
+
+ break;
+ }
+ }
+
+ switch (arg_mode)
+ {
+ case ::odb::pgsql::details::cli::unknown_mode::skip:
+ {
+ s.skip ();
+ r = true;
+ continue;
+ }
+ case ::odb::pgsql::details::cli::unknown_mode::stop:
+ {
+ break;
+ }
+ case ::odb::pgsql::details::cli::unknown_mode::fail:
+ {
+ throw ::odb::pgsql::details::cli::unknown_argument (o);
+ }
+ }
+
+ break;
+ }
+
+ return r;
+ }
+ }
+ }
+}
+
+// Begin epilogue.
+//
+//
+// End epilogue.
+
diff --git a/odb/pgsql/details/pregenerated/odb/pgsql/details/options.hxx b/odb/pgsql/details/pregenerated/odb/pgsql/details/options.hxx
new file mode 100644
index 0000000..4d264d4
--- /dev/null
+++ b/odb/pgsql/details/pregenerated/odb/pgsql/details/options.hxx
@@ -0,0 +1,562 @@
+// -*- C++ -*-
+//
+// This file was generated by CLI, a command line interface
+// compiler for C++.
+//
+
+#ifndef LIBODB_PGSQL_DETAILS_OPTIONS_HXX
+#define LIBODB_PGSQL_DETAILS_OPTIONS_HXX
+
+// Begin prologue.
+//
+//
+// End prologue.
+
+#include <list>
+#include <deque>
+#include <iosfwd>
+#include <string>
+#include <cstddef>
+#include <exception>
+
+#ifndef CLI_POTENTIALLY_UNUSED
+# if defined(_MSC_VER) || defined(__xlC__)
+# define CLI_POTENTIALLY_UNUSED(x) (void*)&x
+# else
+# define CLI_POTENTIALLY_UNUSED(x) (void)x
+# endif
+#endif
+
+namespace odb
+{
+ namespace pgsql
+ {
+ namespace details
+ {
+ namespace cli
+ {
+ class usage_para
+ {
+ public:
+ enum value
+ {
+ none,
+ text,
+ option
+ };
+
+ usage_para (value);
+
+ operator value () const
+ {
+ return v_;
+ }
+
+ private:
+ value v_;
+ };
+
+ class unknown_mode
+ {
+ public:
+ enum value
+ {
+ skip,
+ stop,
+ fail
+ };
+
+ unknown_mode (value);
+
+ operator value () const
+ {
+ return v_;
+ }
+
+ private:
+ value v_;
+ };
+
+ // Exceptions.
+ //
+
+ class exception: public std::exception
+ {
+ public:
+ virtual void
+ print (::std::ostream&) const = 0;
+ };
+
+ ::std::ostream&
+ operator<< (::std::ostream&, const exception&);
+
+ class unknown_option: public exception
+ {
+ public:
+ virtual
+ ~unknown_option () throw ();
+
+ unknown_option (const std::string& option);
+
+ const std::string&
+ option () const;
+
+ virtual void
+ print (::std::ostream&) const;
+
+ virtual const char*
+ what () const throw ();
+
+ private:
+ std::string option_;
+ };
+
+ class unknown_argument: public exception
+ {
+ public:
+ virtual
+ ~unknown_argument () throw ();
+
+ unknown_argument (const std::string& argument);
+
+ const std::string&
+ argument () const;
+
+ virtual void
+ print (::std::ostream&) const;
+
+ virtual const char*
+ what () const throw ();
+
+ private:
+ std::string argument_;
+ };
+
+ class missing_value: public exception
+ {
+ public:
+ virtual
+ ~missing_value () throw ();
+
+ missing_value (const std::string& option);
+
+ const std::string&
+ option () const;
+
+ virtual void
+ print (::std::ostream&) const;
+
+ virtual const char*
+ what () const throw ();
+
+ private:
+ std::string option_;
+ };
+
+ class invalid_value: public exception
+ {
+ public:
+ virtual
+ ~invalid_value () throw ();
+
+ invalid_value (const std::string& option,
+ const std::string& value,
+ const std::string& message = std::string ());
+
+ const std::string&
+ option () const;
+
+ const std::string&
+ value () const;
+
+ const std::string&
+ message () const;
+
+ virtual void
+ print (::std::ostream&) const;
+
+ virtual const char*
+ what () const throw ();
+
+ private:
+ std::string option_;
+ std::string value_;
+ std::string message_;
+ };
+
+ class eos_reached: public exception
+ {
+ public:
+ virtual void
+ print (::std::ostream&) const;
+
+ virtual const char*
+ what () const throw ();
+ };
+
+ class file_io_failure: public exception
+ {
+ public:
+ virtual
+ ~file_io_failure () throw ();
+
+ file_io_failure (const std::string& file);
+
+ const std::string&
+ file () const;
+
+ virtual void
+ print (::std::ostream&) const;
+
+ virtual const char*
+ what () const throw ();
+
+ private:
+ std::string file_;
+ };
+
+ class unmatched_quote: public exception
+ {
+ public:
+ virtual
+ ~unmatched_quote () throw ();
+
+ unmatched_quote (const std::string& argument);
+
+ const std::string&
+ argument () const;
+
+ virtual void
+ print (::std::ostream&) const;
+
+ virtual const char*
+ what () const throw ();
+
+ private:
+ std::string argument_;
+ };
+
+ // Command line argument scanner interface.
+ //
+ // The values returned by next() are guaranteed to be valid
+ // for the two previous arguments up until a call to a third
+ // peek() or next().
+ //
+ // The position() function returns a monotonically-increasing
+ // number which, if stored, can later be used to determine the
+ // relative position of the argument returned by the following
+ // call to next(). Note that if multiple scanners are used to
+ // extract arguments from multiple sources, then the end
+ // position of the previous scanner should be used as the
+ // start position of the next.
+ //
+ class scanner
+ {
+ public:
+ virtual
+ ~scanner ();
+
+ virtual bool
+ more () = 0;
+
+ virtual const char*
+ peek () = 0;
+
+ virtual const char*
+ next () = 0;
+
+ virtual void
+ skip () = 0;
+
+ virtual std::size_t
+ position () = 0;
+ };
+
+ class argv_scanner: public scanner
+ {
+ public:
+ argv_scanner (int& argc,
+ char** argv,
+ bool erase = false,
+ std::size_t start_position = 0);
+
+ argv_scanner (int start,
+ int& argc,
+ char** argv,
+ bool erase = false,
+ std::size_t start_position = 0);
+
+ int
+ end () const;
+
+ virtual bool
+ more ();
+
+ virtual const char*
+ peek ();
+
+ virtual const char*
+ next ();
+
+ virtual void
+ skip ();
+
+ virtual std::size_t
+ position ();
+
+ protected:
+ std::size_t start_position_;
+ int i_;
+ int& argc_;
+ char** argv_;
+ bool erase_;
+ };
+
+ class argv_file_scanner: public argv_scanner
+ {
+ public:
+ argv_file_scanner (int& argc,
+ char** argv,
+ const std::string& option,
+ bool erase = false,
+ std::size_t start_position = 0);
+
+ argv_file_scanner (int start,
+ int& argc,
+ char** argv,
+ const std::string& option,
+ bool erase = false,
+ std::size_t start_position = 0);
+
+ argv_file_scanner (const std::string& file,
+ const std::string& option,
+ std::size_t start_position = 0);
+
+ struct option_info
+ {
+ // If search_func is not NULL, it is called, with the arg
+ // value as the second argument, to locate the options file.
+ // If it returns an empty string, then the file is ignored.
+ //
+ const char* option;
+ std::string (*search_func) (const char*, void* arg);
+ void* arg;
+ };
+
+ argv_file_scanner (int& argc,
+ char** argv,
+ const option_info* options,
+ std::size_t options_count,
+ bool erase = false,
+ std::size_t start_position = 0);
+
+ argv_file_scanner (int start,
+ int& argc,
+ char** argv,
+ const option_info* options,
+ std::size_t options_count,
+ bool erase = false,
+ std::size_t start_position = 0);
+
+ argv_file_scanner (const std::string& file,
+ const option_info* options = 0,
+ std::size_t options_count = 0,
+ std::size_t start_position = 0);
+
+ virtual bool
+ more ();
+
+ virtual const char*
+ peek ();
+
+ virtual const char*
+ next ();
+
+ virtual void
+ skip ();
+
+ virtual std::size_t
+ position ();
+
+ // Return the file path if the peeked at argument came from a file and
+ // the empty string otherwise. The reference is guaranteed to be valid
+ // till the end of the scanner lifetime.
+ //
+ const std::string&
+ peek_file ();
+
+ // Return the 1-based line number if the peeked at argument came from
+ // a file and zero otherwise.
+ //
+ std::size_t
+ peek_line ();
+
+ private:
+ const option_info*
+ find (const char*) const;
+
+ void
+ load (const std::string& file);
+
+ typedef argv_scanner base;
+
+ const std::string option_;
+ option_info option_info_;
+ const option_info* options_;
+ std::size_t options_count_;
+
+ struct arg
+ {
+ std::string value;
+ const std::string* file;
+ std::size_t line;
+ };
+
+ std::deque<arg> args_;
+ std::list<std::string> files_;
+
+ // Circular buffer of two arguments.
+ //
+ std::string hold_[2];
+ std::size_t i_;
+
+ bool skip_;
+
+ static int zero_argc_;
+ static std::string empty_string_;
+ };
+
+ template <typename X>
+ struct parser;
+ }
+ }
+ }
+}
+
+#include <string>
+
+namespace odb
+{
+ namespace pgsql
+ {
+ namespace details
+ {
+ class options
+ {
+ public:
+ options ();
+
+ options (int& argc,
+ char** argv,
+ bool erase = false,
+ ::odb::pgsql::details::cli::unknown_mode option = ::odb::pgsql::details::cli::unknown_mode::fail,
+ ::odb::pgsql::details::cli::unknown_mode argument = ::odb::pgsql::details::cli::unknown_mode::stop);
+
+ options (int start,
+ int& argc,
+ char** argv,
+ bool erase = false,
+ ::odb::pgsql::details::cli::unknown_mode option = ::odb::pgsql::details::cli::unknown_mode::fail,
+ ::odb::pgsql::details::cli::unknown_mode argument = ::odb::pgsql::details::cli::unknown_mode::stop);
+
+ options (int& argc,
+ char** argv,
+ int& end,
+ bool erase = false,
+ ::odb::pgsql::details::cli::unknown_mode option = ::odb::pgsql::details::cli::unknown_mode::fail,
+ ::odb::pgsql::details::cli::unknown_mode argument = ::odb::pgsql::details::cli::unknown_mode::stop);
+
+ options (int start,
+ int& argc,
+ char** argv,
+ int& end,
+ bool erase = false,
+ ::odb::pgsql::details::cli::unknown_mode option = ::odb::pgsql::details::cli::unknown_mode::fail,
+ ::odb::pgsql::details::cli::unknown_mode argument = ::odb::pgsql::details::cli::unknown_mode::stop);
+
+ options (::odb::pgsql::details::cli::scanner&,
+ ::odb::pgsql::details::cli::unknown_mode option = ::odb::pgsql::details::cli::unknown_mode::fail,
+ ::odb::pgsql::details::cli::unknown_mode argument = ::odb::pgsql::details::cli::unknown_mode::stop);
+
+ // Option accessors.
+ //
+ const std::string&
+ user () const;
+
+ bool
+ user_specified () const;
+
+ const std::string&
+ password () const;
+
+ bool
+ password_specified () const;
+
+ const std::string&
+ database () const;
+
+ bool
+ database_specified () const;
+
+ const std::string&
+ host () const;
+
+ bool
+ host_specified () const;
+
+ const std::string&
+ port () const;
+
+ bool
+ port_specified () const;
+
+ const std::string&
+ options_file () const;
+
+ bool
+ options_file_specified () const;
+
+ // Print usage information.
+ //
+ static ::odb::pgsql::details::cli::usage_para
+ print_usage (::std::ostream&,
+ ::odb::pgsql::details::cli::usage_para = ::odb::pgsql::details::cli::usage_para::none);
+
+ // Implementation details.
+ //
+ protected:
+ bool
+ _parse (const char*, ::odb::pgsql::details::cli::scanner&);
+
+ private:
+ bool
+ _parse (::odb::pgsql::details::cli::scanner&,
+ ::odb::pgsql::details::cli::unknown_mode option,
+ ::odb::pgsql::details::cli::unknown_mode argument);
+
+ public:
+ std::string user_;
+ bool user_specified_;
+ std::string password_;
+ bool password_specified_;
+ std::string database_;
+ bool database_specified_;
+ std::string host_;
+ bool host_specified_;
+ std::string port_;
+ bool port_specified_;
+ std::string options_file_;
+ bool options_file_specified_;
+ };
+ }
+ }
+}
+
+#include <odb/pgsql/details/options.ixx>
+
+// Begin epilogue.
+//
+//
+// End epilogue.
+
+#endif // LIBODB_PGSQL_DETAILS_OPTIONS_HXX
diff --git a/odb/pgsql/details/pregenerated/odb/pgsql/details/options.ixx b/odb/pgsql/details/pregenerated/odb/pgsql/details/options.ixx
new file mode 100644
index 0000000..340789e
--- /dev/null
+++ b/odb/pgsql/details/pregenerated/odb/pgsql/details/options.ixx
@@ -0,0 +1,372 @@
+// -*- C++ -*-
+//
+// This file was generated by CLI, a command line interface
+// compiler for C++.
+//
+
+// Begin prologue.
+//
+//
+// End prologue.
+
+#include <cassert>
+
+namespace odb
+{
+ namespace pgsql
+ {
+ namespace details
+ {
+ namespace cli
+ {
+ // usage_para
+ //
+ inline usage_para::
+ usage_para (value v)
+ : v_ (v)
+ {
+ }
+
+ // unknown_mode
+ //
+ inline unknown_mode::
+ unknown_mode (value v)
+ : v_ (v)
+ {
+ }
+
+ // exception
+ //
+ inline ::std::ostream&
+ operator<< (::std::ostream& os, const exception& e)
+ {
+ e.print (os);
+ return os;
+ }
+
+ // unknown_option
+ //
+ inline unknown_option::
+ unknown_option (const std::string& option)
+ : option_ (option)
+ {
+ }
+
+ inline const std::string& unknown_option::
+ option () const
+ {
+ return option_;
+ }
+
+ // unknown_argument
+ //
+ inline unknown_argument::
+ unknown_argument (const std::string& argument)
+ : argument_ (argument)
+ {
+ }
+
+ inline const std::string& unknown_argument::
+ argument () const
+ {
+ return argument_;
+ }
+
+ // missing_value
+ //
+ inline missing_value::
+ missing_value (const std::string& option)
+ : option_ (option)
+ {
+ }
+
+ inline const std::string& missing_value::
+ option () const
+ {
+ return option_;
+ }
+
+ // invalid_value
+ //
+ inline invalid_value::
+ invalid_value (const std::string& option,
+ const std::string& value,
+ const std::string& message)
+ : option_ (option),
+ value_ (value),
+ message_ (message)
+ {
+ }
+
+ inline const std::string& invalid_value::
+ option () const
+ {
+ return option_;
+ }
+
+ inline const std::string& invalid_value::
+ value () const
+ {
+ return value_;
+ }
+
+ inline const std::string& invalid_value::
+ message () const
+ {
+ return message_;
+ }
+
+ // file_io_failure
+ //
+ inline file_io_failure::
+ file_io_failure (const std::string& file)
+ : file_ (file)
+ {
+ }
+
+ inline const std::string& file_io_failure::
+ file () const
+ {
+ return file_;
+ }
+
+ // unmatched_quote
+ //
+ inline unmatched_quote::
+ unmatched_quote (const std::string& argument)
+ : argument_ (argument)
+ {
+ }
+
+ inline const std::string& unmatched_quote::
+ argument () const
+ {
+ return argument_;
+ }
+
+ // argv_scanner
+ //
+ inline argv_scanner::
+ argv_scanner (int& argc,
+ char** argv,
+ bool erase,
+ std::size_t sp)
+ : start_position_ (sp + 1),
+ i_ (1),
+ argc_ (argc),
+ argv_ (argv),
+ erase_ (erase)
+ {
+ }
+
+ inline argv_scanner::
+ argv_scanner (int start,
+ int& argc,
+ char** argv,
+ bool erase,
+ std::size_t sp)
+ : start_position_ (sp + static_cast<std::size_t> (start)),
+ i_ (start),
+ argc_ (argc),
+ argv_ (argv),
+ erase_ (erase)
+ {
+ }
+
+ inline int argv_scanner::
+ end () const
+ {
+ return i_;
+ }
+
+ // argv_file_scanner
+ //
+ inline argv_file_scanner::
+ argv_file_scanner (int& argc,
+ char** argv,
+ const std::string& option,
+ bool erase,
+ std::size_t sp)
+ : argv_scanner (argc, argv, erase, sp),
+ option_ (option),
+ options_ (&option_info_),
+ options_count_ (1),
+ i_ (1),
+ skip_ (false)
+ {
+ option_info_.option = option_.c_str ();
+ option_info_.search_func = 0;
+ }
+
+ inline argv_file_scanner::
+ argv_file_scanner (int start,
+ int& argc,
+ char** argv,
+ const std::string& option,
+ bool erase,
+ std::size_t sp)
+ : argv_scanner (start, argc, argv, erase, sp),
+ option_ (option),
+ options_ (&option_info_),
+ options_count_ (1),
+ i_ (1),
+ skip_ (false)
+ {
+ option_info_.option = option_.c_str ();
+ option_info_.search_func = 0;
+ }
+
+ inline argv_file_scanner::
+ argv_file_scanner (const std::string& file,
+ const std::string& option,
+ std::size_t sp)
+ : argv_scanner (0, zero_argc_, 0, sp),
+ option_ (option),
+ options_ (&option_info_),
+ options_count_ (1),
+ i_ (1),
+ skip_ (false)
+ {
+ option_info_.option = option_.c_str ();
+ option_info_.search_func = 0;
+
+ load (file);
+ }
+
+ inline argv_file_scanner::
+ argv_file_scanner (int& argc,
+ char** argv,
+ const option_info* options,
+ std::size_t options_count,
+ bool erase,
+ std::size_t sp)
+ : argv_scanner (argc, argv, erase, sp),
+ options_ (options),
+ options_count_ (options_count),
+ i_ (1),
+ skip_ (false)
+ {
+ }
+
+ inline argv_file_scanner::
+ argv_file_scanner (int start,
+ int& argc,
+ char** argv,
+ const option_info* options,
+ std::size_t options_count,
+ bool erase,
+ std::size_t sp)
+ : argv_scanner (start, argc, argv, erase, sp),
+ options_ (options),
+ options_count_ (options_count),
+ i_ (1),
+ skip_ (false)
+ {
+ }
+
+ inline argv_file_scanner::
+ argv_file_scanner (const std::string& file,
+ const option_info* options,
+ std::size_t options_count,
+ std::size_t sp)
+ : argv_scanner (0, zero_argc_, 0, sp),
+ options_ (options),
+ options_count_ (options_count),
+ i_ (1),
+ skip_ (false)
+ {
+ load (file);
+ }
+ }
+ }
+ }
+}
+
+namespace odb
+{
+ namespace pgsql
+ {
+ namespace details
+ {
+ // options
+ //
+
+ inline const std::string& options::
+ user () const
+ {
+ return this->user_;
+ }
+
+ inline bool options::
+ user_specified () const
+ {
+ return this->user_specified_;
+ }
+
+ inline const std::string& options::
+ password () const
+ {
+ return this->password_;
+ }
+
+ inline bool options::
+ password_specified () const
+ {
+ return this->password_specified_;
+ }
+
+ inline const std::string& options::
+ database () const
+ {
+ return this->database_;
+ }
+
+ inline bool options::
+ database_specified () const
+ {
+ return this->database_specified_;
+ }
+
+ inline const std::string& options::
+ host () const
+ {
+ return this->host_;
+ }
+
+ inline bool options::
+ host_specified () const
+ {
+ return this->host_specified_;
+ }
+
+ inline const std::string& options::
+ port () const
+ {
+ return this->port_;
+ }
+
+ inline bool options::
+ port_specified () const
+ {
+ return this->port_specified_;
+ }
+
+ inline const std::string& options::
+ options_file () const
+ {
+ return this->options_file_;
+ }
+
+ inline bool options::
+ options_file_specified () const
+ {
+ return this->options_file_specified_;
+ }
+ }
+ }
+}
+
+// Begin epilogue.
+//
+//
+// End epilogue.
diff --git a/odb/pgsql/error.cxx b/odb/pgsql/error.cxx
index 3dfb365..ba8451e 100644
--- a/odb/pgsql/error.cxx
+++ b/odb/pgsql/error.cxx
@@ -1,5 +1,4 @@
// file : odb/pgsql/error.cxx
-// copyright : Copyright (c) 2005-2019 Code Synthesis Tools CC
// license : GNU GPL v2; see accompanying LICENSE file
#include <string>
@@ -16,11 +15,12 @@ namespace odb
namespace pgsql
{
void
- translate_error (connection& c, PGresult* r)
+ translate_error (connection& c, PGresult* r,
+ size_t pos, multiple_exceptions* mex)
{
if (!r)
{
- if (CONNECTION_BAD == PQstatus (c.handle ()))
+ if (PQstatus (c.handle ()) == CONNECTION_BAD)
{
c.mark_failed ();
throw connection_lost ();
@@ -29,50 +29,58 @@ namespace odb
throw bad_alloc ();
}
- string msg;
- {
- // Can be NULL in case of PGRES_BAD_RESPONSE.
- //
- const char* m (PQresultErrorMessage (r));
- msg = (m != 0 ? m : "bad server response");
-
- // Get rid of a trailing newline if there is one.
- //
- string::size_type n (msg.size ());
- if (n != 0 && msg[n - 1] == '\n')
- msg.resize (n - 1);
- }
-
+ // Note that we expect the caller to handle PGRES_PIPELINE_ABORTED since
+ // it's not really an error but rather an indication that no attempt was
+ // made to execute this statement.
+ //
+ string ss;
switch (PQresultStatus (r))
{
case PGRES_BAD_RESPONSE:
{
- throw database_exception (msg);
+ throw database_exception ("bad server response");
}
case PGRES_FATAL_ERROR:
{
- string ss;
- {
- const char* s (PQresultErrorField (r, PG_DIAG_SQLSTATE));
- ss = (s != 0 ? s : "?????");
- }
+ const char* s (PQresultErrorField (r, PG_DIAG_SQLSTATE));
+ ss = (s != 0 ? s : "?????");
// Deadlock detected.
//
if (ss == "40001" || ss == "40P01")
throw deadlock ();
- else if (CONNECTION_BAD == PQstatus (c.handle ()))
+ else if (PQstatus (c.handle ()) == CONNECTION_BAD)
{
c.mark_failed ();
throw connection_lost ();
}
- else
- throw database_exception (ss, msg);
+ break;
}
default:
assert (false);
break;
}
+
+ string msg;
+ {
+ // Can be NULL in case of PGRES_BAD_RESPONSE.
+ //
+ const char* m (PQresultErrorMessage (r));
+ msg = (m != 0 ? m : "bad server response");
+
+ // Get rid of the trailing newline if there is one.
+ //
+ string::size_type n (msg.size ());
+ if (n != 0 && msg[n - 1] == '\n')
+ msg.resize (n - 1);
+ }
+
+ if (mex == 0)
+ throw database_exception (ss, msg);
+ else
+ // In PosgreSQL all errors are fatal.
+ //
+ mex->insert (pos, database_exception (ss, msg), true);
}
}
}
diff --git a/odb/pgsql/error.hxx b/odb/pgsql/error.hxx
index 18e79aa..8d2793d 100644
--- a/odb/pgsql/error.hxx
+++ b/odb/pgsql/error.hxx
@@ -1,5 +1,4 @@
// file : odb/pgsql/error.hxx
-// copyright : Copyright (c) 2005-2019 Code Synthesis Tools CC
// license : GNU GPL v2; see accompanying LICENSE file
#ifndef ODB_PGSQL_ERROR_HXX
@@ -10,23 +9,25 @@
#include <libpq-fe.h>
#include <odb/pgsql/version.hxx>
-#include <odb/pgsql/forward.hxx> // connection
+#include <odb/pgsql/forward.hxx> // connection, multiple_exceptions
#include <odb/pgsql/details/export.hxx>
namespace odb
{
namespace pgsql
{
- // Translate an error condition involving a PGresult*. If r is null, it is
- // assumed that the error was caused due to a bad connection or a memory
- // allocation error.
+ // Translate an error condition involving PGresult* and throw (or return,
+ // in case multiple_exceptions is not NULL) an appropriate exception. If
+ // result is NULL, it is assumed that the error was caused due to a bad
+ // connection or a memory allocation error.
//
LIBODB_PGSQL_EXPORT void
- translate_error (connection& c, PGresult* r);
+ translate_error (connection& c, PGresult* r,
+ std::size_t pos = 0, multiple_exceptions* = 0);
- // Return true if the PGresult is in an error state. If both s and r are
- // non-null, the pointed to value will be populated with the result status.
- // Otherwise, s is ignored.
+ // Return true if PGresult is not NULL and is not in an error state. If
+ // both s and r are non-NULL, the pointed to value will be populated with
+ // the result status. Otherwise, s is ignored.
//
LIBODB_PGSQL_EXPORT bool
is_good_result (PGresult* r, ExecStatusType* s = 0);
diff --git a/odb/pgsql/error.ixx b/odb/pgsql/error.ixx
index f087aeb..6a010aa 100644
--- a/odb/pgsql/error.ixx
+++ b/odb/pgsql/error.ixx
@@ -1,13 +1,12 @@
// file : odb/pgsql/error.ixx
-// copyright : Copyright (c) 2009-2019 Code Synthesis Tools CC
// license : GNU GPL v2; see accompanying LICENSE file
namespace odb
{
namespace pgsql
{
- bool
- inline is_good_result (PGresult* r, ExecStatusType* s)
+ inline bool
+ is_good_result (PGresult* r, ExecStatusType* s)
{
if (r != 0)
{
@@ -17,9 +16,13 @@ namespace odb
*s = status;
return
- status != PGRES_BAD_RESPONSE &&
- status != PGRES_NONFATAL_ERROR &&
- status != PGRES_FATAL_ERROR;
+ status != PGRES_BAD_RESPONSE
+ && status != PGRES_NONFATAL_ERROR
+ && status != PGRES_FATAL_ERROR
+#ifdef LIBPQ_HAS_PIPELINING
+ && status != PGRES_PIPELINE_ABORTED
+#endif
+ ;
}
return false;
diff --git a/odb/pgsql/exceptions.cxx b/odb/pgsql/exceptions.cxx
index fd8bb87..28e7fc4 100644
--- a/odb/pgsql/exceptions.cxx
+++ b/odb/pgsql/exceptions.cxx
@@ -1,5 +1,4 @@
// file : odb/pgsql/exceptions.cxx
-// copyright : Copyright (c) 2005-2019 Code Synthesis Tools CC
// license : GNU GPL v2; see accompanying LICENSE file
#include <sstream>
@@ -27,7 +26,10 @@ namespace odb
const string& message)
: sqlstate_ (sqlstate), message_ (message)
{
- what_ = sqlstate_ + ": " + message_;
+ if (!sqlstate_.empty ())
+ what_ = sqlstate_ + ": " + message_;
+ else
+ what_ = message_;
}
database_exception::
diff --git a/odb/pgsql/exceptions.hxx b/odb/pgsql/exceptions.hxx
index ad4fee7..8417c1a 100644
--- a/odb/pgsql/exceptions.hxx
+++ b/odb/pgsql/exceptions.hxx
@@ -1,5 +1,4 @@
// file : odb/pgsql/exceptions.hxx
-// copyright : Copyright (c) 2005-2019 Code Synthesis Tools CC
// license : GNU GPL v2; see accompanying LICENSE file
#ifndef ODB_PGSQL_EXCEPTIONS_HXX
diff --git a/odb/pgsql/forward.hxx b/odb/pgsql/forward.hxx
index 8386a56..1186b28 100644
--- a/odb/pgsql/forward.hxx
+++ b/odb/pgsql/forward.hxx
@@ -1,5 +1,4 @@
// file : odb/pgsql/forward.hxx
-// copyright : Copyright (c) 2009-2019 Code Synthesis Tools CC
// license : GNU GPL v2; see accompanying LICENSE file
#ifndef ODB_PGSQL_FORWARD_HXX
diff --git a/odb/pgsql/makefile b/odb/pgsql/makefile
index 1e09400..acd23f6 100644
--- a/odb/pgsql/makefile
+++ b/odb/pgsql/makefile
@@ -1,5 +1,4 @@
# file : odb/pgsql/makefile
-# copyright : Copyright (c) 2009-2019 Code Synthesis Tools CC
# license : GNU GPL v2; see accompanying LICENSE file
include $(dir $(lastword $(MAKEFILE_LIST)))../../build/bootstrap.make
@@ -110,7 +109,7 @@ libodb-pgsql-vc10.vcxproj libodb-pgsql-vc10.vcxproj.filters \
libodb-pgsql-vc11.vcxproj libodb-pgsql-vc11.vcxproj.filters \
libodb-pgsql-vc12.vcxproj libodb-pgsql-vc12.vcxproj.filters
$(dist): export interface_version = $(shell sed -e \
-'s/^\([0-9]*\.[0-9]*\).*/\1/' $(src_root)/version)
+'s/^\([0-9]*\.[0-9]*\).*/\1/' $(src_root)/version.txt)
$(dist): $(gen)
$(call dist-data,$(sources_dist) $(headers_dist) $(data_dist))
diff --git a/odb/pgsql/no-id-object-result.hxx b/odb/pgsql/no-id-object-result.hxx
index 7a47d11..734d4a7 100644
--- a/odb/pgsql/no-id-object-result.hxx
+++ b/odb/pgsql/no-id-object-result.hxx
@@ -1,5 +1,4 @@
// file : odb/pgsql/no-id-object-result.hxx
-// copyright : Copyright (c) 2009-2019 Code Synthesis Tools CC
// license : GNU GPL v2; see accompanying LICENSE file
#ifndef ODB_PGSQL_NO_ID_OBJECT_RESULT_HXX
diff --git a/odb/pgsql/no-id-object-result.txx b/odb/pgsql/no-id-object-result.txx
index e10036a..0bae952 100644
--- a/odb/pgsql/no-id-object-result.txx
+++ b/odb/pgsql/no-id-object-result.txx
@@ -1,5 +1,4 @@
// file : odb/pgsql/no-id-object-result.txx
-// copyright : Copyright (c) 2009-2019 Code Synthesis Tools CC
// license : GNU GPL v2; see accompanying LICENSE file
#include <odb/callback.hxx>
diff --git a/odb/pgsql/no-id-object-statements.hxx b/odb/pgsql/no-id-object-statements.hxx
index 82e0fe2..baa1b2a 100644
--- a/odb/pgsql/no-id-object-statements.hxx
+++ b/odb/pgsql/no-id-object-statements.hxx
@@ -1,5 +1,4 @@
// file : odb/pgsql/no-id-object-statements.hxx
-// copyright : Copyright (c) 2005-2019 Code Synthesis Tools CC
// license : GNU GPL v2; see accompanying LICENSE file
#ifndef ODB_PGSQL_NO_ID_OBJECT_STATEMENTS_HXX
@@ -49,7 +48,10 @@ namespace odb
// Object image.
//
image_type&
- image () {return image_;}
+ image (std::size_t i = 0)
+ {
+ return image_[i];
+ }
// Insert binding.
//
@@ -113,7 +115,8 @@ namespace odb
no_id_object_statements& operator= (const no_id_object_statements&);
private:
- image_type image_;
+ image_type image_[object_traits::batch];
+ unsigned long long status_[object_traits::batch];
// Select binding.
//
diff --git a/odb/pgsql/no-id-object-statements.txx b/odb/pgsql/no-id-object-statements.txx
index 83ef2de..0c340ab 100644
--- a/odb/pgsql/no-id-object-statements.txx
+++ b/odb/pgsql/no-id-object-statements.txx
@@ -1,5 +1,4 @@
// file : odb/pgsql/no-id-object-statements.txx
-// copyright : Copyright (c) 2005-2019 Code Synthesis Tools CC
// license : GNU GPL v2; see accompanying LICENSE file
#include <cstring> // std::memset
@@ -25,13 +24,17 @@ namespace odb
// select
select_image_binding_ (select_image_bind_, select_column_count),
// insert
- insert_image_binding_ (insert_image_bind_, insert_column_count),
+ insert_image_binding_ (insert_image_bind_,
+ insert_column_count,
+ object_traits::batch,
+ sizeof (image_type),
+ status_),
insert_image_native_binding_ (insert_image_values_,
insert_image_lengths_,
insert_image_formats_,
insert_column_count)
{
- image_.version = 0;
+ image_[0].version = 0; // Only version in the first element used.
select_image_version_ = 0;
insert_image_version_ = 0;
diff --git a/odb/pgsql/pgsql-fwd.hxx b/odb/pgsql/pgsql-fwd.hxx
index 317d0c1..e60bc37 100644
--- a/odb/pgsql/pgsql-fwd.hxx
+++ b/odb/pgsql/pgsql-fwd.hxx
@@ -1,5 +1,4 @@
// file : odb/pgsql/pgsql-fwd.hxx
-// copyright : Copyright (c) 2005-2019 Code Synthesis Tools CC
// license : GNU GPL v2; see accompanying LICENSE file
#ifndef ODB_PGSQL_PGSQL_FWD_HXX
diff --git a/odb/pgsql/pgsql-oid.hxx b/odb/pgsql/pgsql-oid.hxx
index ca3ae0c..e2ef1af 100644
--- a/odb/pgsql/pgsql-oid.hxx
+++ b/odb/pgsql/pgsql-oid.hxx
@@ -1,5 +1,4 @@
// file : odb/pgsql/pgsql-oid.hxx
-// copyright : Copyright (c) 2005-2019 Code Synthesis Tools CC
// license : GNU GPL v2; see accompanying LICENSE file
// Generated file of OIDs extracted from the PostgreSQL 8.4.8 source file
diff --git a/odb/pgsql/pgsql-types.hxx b/odb/pgsql/pgsql-types.hxx
index a397efe..117a41e 100644
--- a/odb/pgsql/pgsql-types.hxx
+++ b/odb/pgsql/pgsql-types.hxx
@@ -1,5 +1,4 @@
// file : odb/pgsql/pgsql-types.hxx
-// copyright : Copyright (c) 2005-2019 Code Synthesis Tools CC
// license : GNU GPL v2; see accompanying LICENSE file
#ifndef ODB_PGSQL_PGSQL_TYPES_HXX
@@ -15,8 +14,13 @@ namespace odb
{
namespace pgsql
{
- // The libpq result binding. This data structures is
- // modelled after MYSQL_BIND from MySQL.
+ // The libpq result binding. This data structures is roughly modeled
+ // after MYSQL_BIND from MySQL.
+ //
+ // Types that may need to grow are bound as pointers to pointers to char
+ // array (normally in details::buffer) in order to allow simple offsetting
+ // in bulk operation support. Note that if we were to do the same for
+ // capacity, we could get rid of the buffer growth tracking altogether.
//
struct bind
{
@@ -28,14 +32,14 @@ namespace odb
bigint, // Buffer is long long; size, capacity, truncated are unused.
real, // Buffer is float; size, capacity, truncated are unused.
double_, // Buffer is double; size, capacity, truncated are unused.
- numeric, // Buffer is a char array.
+ numeric, // Buffer is a pointer to pointer to char array.
date, // Buffer is int; size, capacity, truncated are unused.
time, // Buffer is long long; size, capacity, truncated are unused.
timestamp,// Buffer is long long; size, capacity, truncated are unused.
- text, // Buffer is a char array.
- bytea, // Buffer is a char array.
- bit, // Buffer is a char array.
- varbit, // Buffer is a char array.
+ text, // Buffer is a pointer to pointer to char array.
+ bytea, // Buffer is a pointer to pointer to char array.
+ bit, // Buffer is a pointer to char array.
+ varbit, // Buffer is a pointer to pointer to char array.
uuid // Buffer is a 16-byte char array; size capacity, truncated
// are unused. Note: big-endian, in RFC 4122/4.1.2 order.
};
diff --git a/odb/pgsql/polymorphic-object-result.hxx b/odb/pgsql/polymorphic-object-result.hxx
index c0a49e7..a1cd108 100644
--- a/odb/pgsql/polymorphic-object-result.hxx
+++ b/odb/pgsql/polymorphic-object-result.hxx
@@ -1,5 +1,4 @@
// file : odb/pgsql/polymorphic-object-result.hxx
-// copyright : Copyright (c) 2009-2019 Code Synthesis Tools CC
// license : GNU GPL v2; see accompanying LICENSE file
#ifndef ODB_PGSQL_POLYMORPHIC_OBJECT_RESULT_HXX
diff --git a/odb/pgsql/polymorphic-object-result.txx b/odb/pgsql/polymorphic-object-result.txx
index c556a16..bad2091 100644
--- a/odb/pgsql/polymorphic-object-result.txx
+++ b/odb/pgsql/polymorphic-object-result.txx
@@ -1,5 +1,4 @@
// file : odb/pgsql/polymorphic-object-result.txx
-// copyright : Copyright (c) 2009-2019 Code Synthesis Tools CC
// license : GNU GPL v2; see accompanying LICENSE file
#include <cassert>
diff --git a/odb/pgsql/polymorphic-object-statements.hxx b/odb/pgsql/polymorphic-object-statements.hxx
index 44839b6..717410a 100644
--- a/odb/pgsql/polymorphic-object-statements.hxx
+++ b/odb/pgsql/polymorphic-object-statements.hxx
@@ -1,5 +1,4 @@
// file : odb/pgsql/polymorphic-object-statements.hxx
-// copyright : Copyright (c) 2005-2019 Code Synthesis Tools CC
// license : GNU GPL v2; see accompanying LICENSE file
#ifndef ODB_PGSQL_POLYMORPHIC_OBJECT_STATEMENTS_HXX
diff --git a/odb/pgsql/polymorphic-object-statements.txx b/odb/pgsql/polymorphic-object-statements.txx
index ae1cc63..8472fca 100644
--- a/odb/pgsql/polymorphic-object-statements.txx
+++ b/odb/pgsql/polymorphic-object-statements.txx
@@ -1,5 +1,4 @@
// file : odb/pgsql/polymorphic-object-statements.txx
-// copyright : Copyright (c) 2005-2019 Code Synthesis Tools CC
// license : GNU GPL v2; see accompanying LICENSE file
#include <cstring> // std::memset
@@ -130,7 +129,7 @@ namespace odb
root_type& robj,
const schema_version_migration* svm)
{
- connection_type& conn (transaction::current ().connection ());
+ connection_type& conn (transaction::current ().connection (db));
polymorphic_derived_object_statements& sts (
conn.statement_cache ().find_object<object_type> ());
root_statements_type& rsts (sts.root_statements ());
diff --git a/odb/pgsql/prepared-query.cxx b/odb/pgsql/prepared-query.cxx
index 016652b..a6d783c 100644
--- a/odb/pgsql/prepared-query.cxx
+++ b/odb/pgsql/prepared-query.cxx
@@ -1,5 +1,4 @@
// file : odb/pgsql/prepared-query.cxx
-// copyright : Copyright (c) 2005-2019 Code Synthesis Tools CC
// license : GNU GPL v2; see accompanying LICENSE file
#include <odb/pgsql/prepared-query.hxx>
diff --git a/odb/pgsql/prepared-query.hxx b/odb/pgsql/prepared-query.hxx
index b103d39..3622226 100644
--- a/odb/pgsql/prepared-query.hxx
+++ b/odb/pgsql/prepared-query.hxx
@@ -1,5 +1,4 @@
// file : odb/pgsql/prepared-query.hxx
-// copyright : Copyright (c) 2005-2019 Code Synthesis Tools CC
// license : GNU GPL v2; see accompanying LICENSE file
#ifndef ODB_PGSQL_PREPARED_QUERY_HXX
diff --git a/odb/pgsql/query-const-expr.cxx b/odb/pgsql/query-const-expr.cxx
index 3aa5101..c910620 100644
--- a/odb/pgsql/query-const-expr.cxx
+++ b/odb/pgsql/query-const-expr.cxx
@@ -1,5 +1,4 @@
// file : odb/pgsql/query-const-expr.cxx
-// copyright : Copyright (c) 2009-2019 Code Synthesis Tools CC
// license : GNU GPL v2; see accompanying LICENSE file
#include <odb/pgsql/query.hxx>
diff --git a/odb/pgsql/query-dynamic.cxx b/odb/pgsql/query-dynamic.cxx
index 2ced689..ebd62de 100644
--- a/odb/pgsql/query-dynamic.cxx
+++ b/odb/pgsql/query-dynamic.cxx
@@ -1,5 +1,4 @@
// file : odb/pgsql/query-dynamic.cxx
-// copyright : Copyright (c) 2005-2019 Code Synthesis Tools CC
// license : GNU GPL v2; see accompanying LICENSE file
#include <cstddef> // std::size_t
diff --git a/odb/pgsql/query-dynamic.hxx b/odb/pgsql/query-dynamic.hxx
index 71f8206..df87519 100644
--- a/odb/pgsql/query-dynamic.hxx
+++ b/odb/pgsql/query-dynamic.hxx
@@ -1,5 +1,4 @@
// file : odb/pgsql/query-dynamic.hxx
-// copyright : Copyright (c) 2005-2019 Code Synthesis Tools CC
// license : GNU GPL v2; see accompanying LICENSE file
#ifndef ODB_PGSQL_QUERY_DYNAMIC_HXX
diff --git a/odb/pgsql/query-dynamic.ixx b/odb/pgsql/query-dynamic.ixx
index 7b2de77..016d213 100644
--- a/odb/pgsql/query-dynamic.ixx
+++ b/odb/pgsql/query-dynamic.ixx
@@ -1,5 +1,4 @@
// file : odb/pgsql/query-dynamic.ixx
-// copyright : Copyright (c) 2005-2019 Code Synthesis Tools CC
// license : GNU GPL v2; see accompanying LICENSE file
namespace odb
diff --git a/odb/pgsql/query-dynamic.txx b/odb/pgsql/query-dynamic.txx
index 90da968..7cfaf63 100644
--- a/odb/pgsql/query-dynamic.txx
+++ b/odb/pgsql/query-dynamic.txx
@@ -1,5 +1,4 @@
// file : odb/pgsql/query-dynamic.txx
-// copyright : Copyright (c) 2005-2019 Code Synthesis Tools CC
// license : GNU GPL v2; see accompanying LICENSE file
namespace odb
diff --git a/odb/pgsql/query.cxx b/odb/pgsql/query.cxx
index c1b9aee..b096c97 100644
--- a/odb/pgsql/query.cxx
+++ b/odb/pgsql/query.cxx
@@ -1,5 +1,4 @@
// file : odb/pgsql/query.cxx
-// copyright : Copyright (c) 2009-2019 Code Synthesis Tools CC
// license : GNU GPL v2; see accompanying LICENSE file
#include <cstddef> // std::size_t
diff --git a/odb/pgsql/query.hxx b/odb/pgsql/query.hxx
index d880111..42182d6 100644
--- a/odb/pgsql/query.hxx
+++ b/odb/pgsql/query.hxx
@@ -1,5 +1,4 @@
// file : odb/pgsql/query.hxx
-// copyright : Copyright (c) 2009-2019 Code Synthesis Tools CC
// license : GNU GPL v2; see accompanying LICENSE file
#ifndef ODB_PGSQL_QUERY_HXX
@@ -149,13 +148,14 @@ namespace odb
kind_bool
};
- clause_part (kind_type k): kind (k) {}
- clause_part (kind_type k, const std::string& p): kind (k), part (p) {}
+ clause_part (kind_type k): kind (k), bool_part (false) {}
+ clause_part (kind_type k, const std::string& p)
+ : kind (k), part (p), bool_part (false) {}
clause_part (bool p): kind (kind_bool), bool_part (p) {}
kind_type kind;
std::string part; // If kind is param, then part is conversion expr.
- bool bool_part = false;
+ bool bool_part;
};
query_base ()
@@ -1671,7 +1671,7 @@ namespace odb
bind (bind_type* b)
{
b->type = bind::numeric;
- b->buffer = buffer_.data ();
+ b->buffer = buffer_.data_ptr ();
b->capacity = buffer_.capacity ();
b->size = &size_;
}
@@ -1836,7 +1836,7 @@ namespace odb
bind (bind_type* b)
{
b->type = bind::text;
- b->buffer = buffer_.data ();
+ b->buffer = buffer_.data_ptr ();
b->capacity = buffer_.capacity ();
b->size = &size_;
}
@@ -1881,7 +1881,7 @@ namespace odb
bind (bind_type* b)
{
b->type = bind::bytea;
- b->buffer = buffer_.data ();
+ b->buffer = buffer_.data_ptr ();
b->capacity = buffer_.capacity ();
b->size = &size_;
}
@@ -1926,7 +1926,7 @@ namespace odb
bind (bind_type* b)
{
b->type = bind::bit;
- b->buffer = buffer_.data ();
+ b->buffer = buffer_.data_ptr ();
b->capacity = buffer_.capacity ();
b->size = &size_;
}
@@ -1970,7 +1970,7 @@ namespace odb
bind (bind_type* b)
{
b->type = bind::varbit;
- b->buffer = buffer_.data ();
+ b->buffer = buffer_.data_ptr ();
b->capacity = buffer_.capacity ();
b->size = &size_;
}
diff --git a/odb/pgsql/query.ixx b/odb/pgsql/query.ixx
index c8bf121..826b4ab 100644
--- a/odb/pgsql/query.ixx
+++ b/odb/pgsql/query.ixx
@@ -1,5 +1,4 @@
// file : odb/pgsql/query.ixx
-// copyright : Copyright (c) 2009-2019 Code Synthesis Tools CC
// license : GNU GPL v2; see accompanying LICENSE file
namespace odb
diff --git a/odb/pgsql/query.txx b/odb/pgsql/query.txx
index ad2ffe4..44dae30 100644
--- a/odb/pgsql/query.txx
+++ b/odb/pgsql/query.txx
@@ -1,5 +1,4 @@
// file : odb/pgsql/query.txx
-// copyright : Copyright (c) 2009-2019 Code Synthesis Tools CC
// license : GNU GPL v2; see accompanying LICENSE file
namespace odb
diff --git a/odb/pgsql/section-statements.hxx b/odb/pgsql/section-statements.hxx
index 74dd35f..e40b282 100644
--- a/odb/pgsql/section-statements.hxx
+++ b/odb/pgsql/section-statements.hxx
@@ -1,5 +1,4 @@
// file : odb/pgsql/section-statements.hxx
-// copyright : Copyright (c) 2005-2019 Code Synthesis Tools CC
// license : GNU GPL v2; see accompanying LICENSE file
#ifndef ODB_PGSQL_SECTION_STATEMENTS_HXX
diff --git a/odb/pgsql/section-statements.txx b/odb/pgsql/section-statements.txx
index 5a081de..55f4093 100644
--- a/odb/pgsql/section-statements.txx
+++ b/odb/pgsql/section-statements.txx
@@ -1,5 +1,4 @@
// file : odb/pgsql/section-statements.txx
-// copyright : Copyright (c) 2005-2019 Code Synthesis Tools CC
// license : GNU GPL v2; see accompanying LICENSE file
#include <cstring> // std::memset
diff --git a/odb/pgsql/simple-object-result.hxx b/odb/pgsql/simple-object-result.hxx
index 591c968..7472cbe 100644
--- a/odb/pgsql/simple-object-result.hxx
+++ b/odb/pgsql/simple-object-result.hxx
@@ -1,5 +1,4 @@
// file : odb/pgsql/simple-object-result.hxx
-// copyright : Copyright (c) 2009-2019 Code Synthesis Tools CC
// license : GNU GPL v2; see accompanying LICENSE file
#ifndef ODB_PGSQL_SIMPLE_OBJECT_RESULT_HXX
diff --git a/odb/pgsql/simple-object-result.txx b/odb/pgsql/simple-object-result.txx
index 949bfc5..c14d64b 100644
--- a/odb/pgsql/simple-object-result.txx
+++ b/odb/pgsql/simple-object-result.txx
@@ -1,5 +1,4 @@
// file : odb/pgsql/simple-object-result.txx
-// copyright : Copyright (c) 2009-2019 Code Synthesis Tools CC
// license : GNU GPL v2; see accompanying LICENSE file
#include <cassert>
diff --git a/odb/pgsql/simple-object-statements.cxx b/odb/pgsql/simple-object-statements.cxx
index b7c926d..432f990 100644
--- a/odb/pgsql/simple-object-statements.cxx
+++ b/odb/pgsql/simple-object-statements.cxx
@@ -1,5 +1,4 @@
// file : odb/pgsql/simple-object-statements.cxx
-// copyright : Copyright (c) 2005-2019 Code Synthesis Tools CC
// license : GNU GPL v2; see accompanying LICENSE file
#include <odb/pgsql/simple-object-statements.hxx>
diff --git a/odb/pgsql/simple-object-statements.hxx b/odb/pgsql/simple-object-statements.hxx
index fc845d4..086ef5f 100644
--- a/odb/pgsql/simple-object-statements.hxx
+++ b/odb/pgsql/simple-object-statements.hxx
@@ -1,5 +1,4 @@
// file : odb/pgsql/simple-object-statements.hxx
-// copyright : Copyright (c) 2005-2019 Code Synthesis Tools CC
// license : GNU GPL v2; see accompanying LICENSE file
#ifndef ODB_PGSQL_SIMPLE_OBJECT_STATEMENTS_HXX
@@ -168,7 +167,8 @@ namespace odb
typedef T object_type;
typedef object_traits_impl<object_type, id_pgsql> object_traits;
- optimistic_data (bind*, char** nv, int* nl, int* nf);
+ optimistic_data (bind*, char** nv, int* nl, int* nf,
+ std::size_t skip, unsigned long long* status);
binding*
id_image_binding () {return &id_image_binding_;}
@@ -191,7 +191,8 @@ namespace odb
template <typename T>
struct optimistic_data<T, false>
{
- optimistic_data (bind*, char**, int*, int*) {}
+ optimistic_data (bind*, char**, int*, int*,
+ std::size_t, unsigned long long*) {}
binding*
id_image_binding () {return 0;}
@@ -302,7 +303,7 @@ namespace odb
// Object image.
//
image_type&
- image () {return image_;}
+ image (std::size_t i = 0) {return images_[i].obj;}
// Insert binding.
//
@@ -349,7 +350,7 @@ namespace odb
// Object id image and binding.
//
id_image_type&
- id_image () {return id_image_;}
+ id_image (std::size_t i = 0) {return images_[i].id;}
std::size_t
id_image_version () const {return id_image_version_;}
@@ -472,8 +473,8 @@ namespace odb
{
return extra_statement_cache_.get (
conn_,
- image_,
- id_image_,
+ images_[0].obj,
+ images_[0].id,
id_image_binding_,
od_.id_image_binding (),
id_image_native_binding_,
@@ -528,7 +529,18 @@ namespace odb
image_type,
id_image_type> extra_statement_cache_;
- image_type image_;
+ // The UPDATE statement uses both the object and id image. Keep them
+ // next to each other so that the same skip distance can be used in
+ // batch binding.
+ //
+ struct images
+ {
+ image_type obj;
+ id_image_type id;
+ };
+
+ images images_[object_traits::batch];
+ unsigned long long status_[object_traits::batch];
// Select binding.
//
@@ -575,7 +587,6 @@ namespace odb
// Id image binding (only used as a parameter). Uses the suffix in
// the update bind.
//
- id_image_type id_image_;
std::size_t id_image_version_;
binding id_image_binding_;
native_binding id_image_native_binding_;
diff --git a/odb/pgsql/simple-object-statements.ixx b/odb/pgsql/simple-object-statements.ixx
index 5a5fe89..fbb2775 100644
--- a/odb/pgsql/simple-object-statements.ixx
+++ b/odb/pgsql/simple-object-statements.ixx
@@ -1,5 +1,4 @@
// file : odb/pgsql/simple-object-statements.ixx
-// copyright : Copyright (c) 2005-2019 Code Synthesis Tools CC
// license : GNU GPL v2; see accompanying LICENSE file
namespace odb
diff --git a/odb/pgsql/simple-object-statements.txx b/odb/pgsql/simple-object-statements.txx
index 42a14b0..bb47b43 100644
--- a/odb/pgsql/simple-object-statements.txx
+++ b/odb/pgsql/simple-object-statements.txx
@@ -1,5 +1,4 @@
// file : odb/pgsql/simple-object-statements.txx
-// copyright : Copyright (c) 2005-2019 Code Synthesis Tools CC
// license : GNU GPL v2; see accompanying LICENSE file
#include <cstring> // std::memset
@@ -20,11 +19,15 @@ namespace odb
template <typename T>
optimistic_data<T, true>::
- optimistic_data (bind* b, char** nv, int* nl, int* nf)
+ optimistic_data (bind* b, char** nv, int* nl, int* nf,
+ std::size_t skip, unsigned long long* status)
: id_image_binding_ (
b,
object_traits::id_column_count +
- object_traits::managed_optimistic_column_count),
+ object_traits::managed_optimistic_column_count,
+ object_traits::batch,
+ skip,
+ status),
id_image_native_binding_ (
nv, nl, nf,
object_traits::id_column_count +
@@ -49,7 +52,11 @@ namespace odb
// select
select_image_binding_ (select_image_bind_, select_column_count),
// insert
- insert_image_binding_ (insert_image_bind_, insert_column_count),
+ insert_image_binding_ (insert_image_bind_,
+ insert_column_count,
+ object_traits::batch,
+ sizeof (images),
+ status_),
insert_image_native_binding_ (insert_image_values_,
insert_image_lengths_,
insert_image_formats_,
@@ -57,7 +64,10 @@ namespace odb
// update
update_image_binding_ (update_image_bind_,
update_column_count + id_column_count +
- managed_optimistic_column_count),
+ managed_optimistic_column_count,
+ object_traits::batch,
+ sizeof (images),
+ status_),
update_image_native_binding_ (update_image_values_,
update_image_lengths_,
update_image_formats_,
@@ -65,7 +75,10 @@ namespace odb
managed_optimistic_column_count),
// id
id_image_binding_ (update_image_bind_ + update_column_count,
- id_column_count),
+ id_column_count,
+ object_traits::batch,
+ sizeof (images),
+ status_),
id_image_native_binding_ (
update_image_values_ + update_column_count,
update_image_lengths_ + update_column_count,
@@ -75,15 +88,19 @@ namespace odb
od_ (update_image_bind_ + update_column_count,
update_image_values_ + update_column_count,
update_image_lengths_ + update_column_count,
- update_image_formats_ + update_column_count)
+ update_image_formats_ + update_column_count,
+ sizeof (images),
+ status_)
{
- image_.version = 0;
+ // Only versions in the first element used.
+ //
+ images_[0].obj.version = 0;
+ images_[0].id.version = 0;
+
select_image_version_ = 0;
insert_image_version_ = 0;
update_image_version_ = 0;
update_id_image_version_ = 0;
-
- id_image_.version = 0;
id_image_version_ = 0;
std::memset (insert_image_bind_, 0, sizeof (insert_image_bind_));
diff --git a/odb/pgsql/statement-cache.hxx b/odb/pgsql/statement-cache.hxx
index c22734b..9417949 100644
--- a/odb/pgsql/statement-cache.hxx
+++ b/odb/pgsql/statement-cache.hxx
@@ -1,5 +1,4 @@
// file : odb/pgsql/statement-cache.hxx
-// copyright : Copyright (c) 2005-2019 Code Synthesis Tools CC
// license : GNU GPL v2; see accompanying LICENSE file
#ifndef ODB_PGSQL_STATEMENT_CACHE_HXX
diff --git a/odb/pgsql/statement-cache.txx b/odb/pgsql/statement-cache.txx
index f46d784..488ba2c 100644
--- a/odb/pgsql/statement-cache.txx
+++ b/odb/pgsql/statement-cache.txx
@@ -1,5 +1,4 @@
// file : odb/pgsql/statement-cache.txx
-// copyright : Copyright (c) 2005-2019 Code Synthesis Tools CC
// license : GNU GPL v2; see accompanying LICENSE file
#include <odb/pgsql/database.hxx>
diff --git a/odb/pgsql/statement.cxx b/odb/pgsql/statement.cxx
index 377dc60..8574c37 100644
--- a/odb/pgsql/statement.cxx
+++ b/odb/pgsql/statement.cxx
@@ -1,17 +1,32 @@
// file : odb/pgsql/statement.cxx
-// copyright : Copyright (c) 2005-2019 Code Synthesis Tools CC
// license : GNU GPL v2; see accompanying LICENSE file
-#include <cstdlib> // std::atol
-#include <cassert>
-#include <sstream> // istringstream
+#include <odb/details/config.hxx> // ODB_CXX11
#include <libpq-fe.h>
+#ifdef LIBPQ_HAS_PIPELINING
+# ifndef _WIN32
+# include <errno.h>
+# include <sys/select.h>
+# endif
+#endif
+
+#include <cstring> // strcmp
+#include <utility> // pair
+#include <cassert>
+
+#ifdef ODB_CXX11
+# include <cstdlib> // strtoull
+#else
+# include <sstream> // istringstream
+#endif
+
#include <odb/tracer.hxx>
#include <odb/pgsql/pgsql-oid.hxx>
#include <odb/pgsql/statement.hxx>
+#include <odb/pgsql/exceptions.hxx>
#include <odb/pgsql/connection.hxx>
#include <odb/pgsql/transaction.hxx>
#include <odb/pgsql/auto-handle.hxx>
@@ -37,11 +52,12 @@ namespace odb
count = static_cast<unsigned long long> (s[0] - '0');
else
{
- // @@ Using stringstream conversion for now. See if we can optimize
- // this (atoll possibly, even though it is not standard).
- //
+#ifdef ODB_CXX11
+ count = strtoull (s, 0, 10);
+#else
istringstream ss (s);
ss >> count;
+#endif
}
return count;
@@ -257,30 +273,39 @@ namespace odb
return text_;
}
+ template <typename T>
+ static inline T*
+ offset (T* base, size_t count, size_t size)
+ {
+ return reinterpret_cast<T*> (
+ reinterpret_cast<char*> (base) + count * size);
+ }
+
void statement::
- bind_param (native_binding& n, const binding& b)
+ bind_param (native_binding& ns, const binding& bs, size_t pos)
{
- assert (n.count == b.count);
+ assert (ns.count == bs.count);
- for (size_t i (0); i < n.count; ++i)
+ for (size_t i (0); i < ns.count; ++i)
{
- const bind& current_bind (b.bind[i]);
+ const bind& b (bs.bind[i]);
- n.formats[i] = 1;
+ ns.formats[i] = 1;
- if (current_bind.buffer == 0 || // Skip NULL entries.
- (current_bind.is_null != 0 && *current_bind.is_null))
+ bool* n (b.is_null != 0 ? offset (b.is_null, pos, bs.skip) : 0);
+
+ if ((n != 0 && *n) || b.buffer == 0) // Handle NULL entries.
{
- n.values[i] = 0;
- n.lengths[i] = 0;
+ ns.values[i] = 0;
+ ns.lengths[i] = 0;
continue;
}
- n.values[i] = static_cast<char*> (current_bind.buffer);
+ ns.values[i] = static_cast<char*> (offset (b.buffer, pos, bs.skip));
size_t l (0);
- switch (current_bind.type)
+ switch (b.type)
{
case bind::boolean_:
{
@@ -326,10 +351,18 @@ namespace odb
case bind::numeric:
case bind::text:
case bind::bytea:
- case bind::bit:
case bind::varbit:
{
- l = *current_bind.size;
+ // In this case b.buffer is a pointer to pointer to buffer so we
+ // need to chase one level.
+ //
+ ns.values[i] = static_cast<char*> (
+ *reinterpret_cast<void**> (ns.values[i]));
+ }
+ // Fall through.
+ case bind::bit:
+ {
+ l = *offset (b.size, pos, bs.skip);
break;
}
case bind::uuid:
@@ -341,54 +374,61 @@ namespace odb
}
}
- n.lengths[i] = static_cast<int> (l);
+ ns.lengths[i] = static_cast<int> (l);
}
}
bool statement::
- bind_result (bind* p,
- size_t count,
+ bind_result (const binding& bs,
PGresult* result,
size_t row,
- bool truncated)
+ bool truncated,
+ size_t pos)
{
bool r (true);
int col_count (PQnfields (result));
int col (0);
- for (size_t i (0); i != count && col != col_count; ++i)
+ for (size_t i (0); i != bs.count && col != col_count; ++i)
{
- const bind& b (p[i]);
+ const bind& b (bs.bind[i]);
if (b.buffer == 0) // Skip NULL entries.
continue;
int c (col++);
- if (truncated && (b.truncated == 0 || !*b.truncated))
- continue;
+ {
+ bool* t (b.truncated != 0 ? offset (b.truncated, pos, bs.skip) : 0);
- if (b.truncated != 0)
- *b.truncated = false;
+ if (truncated && (t == 0 || !*t))
+ continue;
+
+ if (t != 0)
+ *t = false;
+ }
// Check for NULL unless we are reloading a truncated result.
//
if (!truncated)
{
- *b.is_null = PQgetisnull (result, static_cast<int> (row), c) == 1;
+ bool* n (offset (b.is_null, pos, bs.skip));
+
+ *n = PQgetisnull (result, static_cast<int> (row), c) == 1;
- if (*b.is_null)
+ if (*n)
continue;
}
+ void* buf (offset (b.buffer, pos, bs.skip));
+
const char* v (PQgetvalue (result, static_cast<int> (row), c));
switch (b.type)
{
case bind::boolean_:
{
- *static_cast<bool*> (b.buffer) =
- *reinterpret_cast<const bool*> (v);
+ *static_cast<bool*> (buf) = *reinterpret_cast<const bool*> (v);
break;
}
case bind::smallint:
@@ -431,19 +471,19 @@ namespace odb
{
case bind::smallint:
{
- *static_cast<short*> (b.buffer) =
+ *static_cast<short*> (buf) =
endian_traits::hton (static_cast<short> (i));
break;
}
case bind::integer:
{
- *static_cast<int*> (b.buffer) =
+ *static_cast<int*> (buf) =
endian_traits::hton (static_cast<int> (i));
break;
}
case bind::bigint:
{
- *static_cast<long long*> (b.buffer) = endian_traits::hton (i);
+ *static_cast<long long*> (buf) = endian_traits::hton (i);
break;
}
default:
@@ -454,25 +494,23 @@ namespace odb
}
case bind::real:
{
- *static_cast<float*> (b.buffer) =
- *reinterpret_cast<const float*> (v);
+ *static_cast<float*> (buf) = *reinterpret_cast<const float*> (v);
break;
}
case bind::double_:
{
- *static_cast<double*> (b.buffer) =
- *reinterpret_cast<const double*> (v);
+ *static_cast<double*> (buf) = *reinterpret_cast<const double*> (v);
break;
}
case bind::date:
{
- *static_cast<int*> (b.buffer) = *reinterpret_cast<const int*> (v);
+ *static_cast<int*> (buf) = *reinterpret_cast<const int*> (v);
break;
}
case bind::time:
case bind::timestamp:
{
- *static_cast<long long*> (b.buffer) =
+ *static_cast<long long*> (buf) =
*reinterpret_cast<const long long*> (v);
break;
}
@@ -482,24 +520,37 @@ namespace odb
case bind::bit:
case bind::varbit:
{
+ // Currently this is neither supported (due to capacity) nor used
+ // in batches.
+ //
+#ifdef LIBPGSQL_EXTRA_CHECKS
+ assert (pos == 0);
+#endif
+
*b.size = static_cast<size_t> (
PQgetlength (result, static_cast<int> (row), c));
- if (b.capacity < *b.size)
- {
- if (b.truncated)
- *b.truncated = true;
+ if (b.capacity < *b.size)
+ {
+ if (b.truncated)
+ *b.truncated = true;
- r = false;
- continue;
- }
+ r = false;
+ continue;
+ }
+
+ // In these cases b.buffer is a pointer to pointer to buffer so we
+ // need to chase one level.
+ //
+ if (b.type != bind::bit)
+ buf = *static_cast<void**> (buf);
- memcpy (b.buffer, v, *b.size);
- break;
+ memcpy (buf, v, *b.size);
+ break;
}
case bind::uuid:
{
- memcpy (b.buffer, v, 16);
+ memcpy (buf, v, 16);
break;
}
}
@@ -515,6 +566,388 @@ namespace odb
return r;
}
+#if defined(LIBPQ_HAS_PIPELINING) && !defined(_WIN32)
+
+ // Note that this function always marks the connection as failed.
+ //
+ static void
+ translate_connection_error (connection& conn)
+ {
+ const char* m (PQerrorMessage (conn.handle ()));
+
+ if (PQstatus (conn.handle ()) == CONNECTION_BAD)
+ {
+ conn.mark_failed ();
+ throw connection_lost ();
+ }
+ else
+ {
+ conn.mark_failed ();
+ throw database_exception (m != 0 ? m : "bad connection state");
+ }
+ }
+
+ // A RAII object for PGconn's non-blocking pipeline mode.
+ //
+ struct pipeline
+ {
+ connection& conn;
+ int sock;
+
+ explicit
+ pipeline (connection& c)
+ : conn (c)
+ {
+ PGconn* ch (conn.handle ());
+
+ if ((sock = PQsocket (ch)) == -1 ||
+ PQsetnonblocking (ch, 1) == -1 ||
+ PQenterPipelineMode (ch) == 0)
+ {
+ translate_connection_error (conn);
+ }
+ }
+
+ void
+ close (bool throw_ = true)
+ {
+ if (!conn.failed ())
+ {
+ PGconn* ch (conn.handle ());
+
+ if (PQexitPipelineMode (ch) == 0 ||
+ PQsetnonblocking (ch, 0) == -1)
+ {
+ if (throw_)
+ translate_connection_error (conn);
+ else
+ conn.mark_failed ();
+ }
+ }
+ }
+
+ ~pipeline ()
+ {
+ close (false);
+ }
+
+ pair<bool /* read */, bool /* write */>
+ wait (bool write, bool throw_ = true)
+ {
+ fd_set wds;
+ fd_set rds;
+
+ for (;;)
+ {
+ if (write)
+ {
+ FD_ZERO (&wds);
+ FD_SET (sock, &wds);
+ }
+
+ FD_ZERO (&rds);
+ FD_SET (sock, &rds);
+
+ if (select (sock + 1, &rds, write ? &wds : 0, 0, 0) != -1)
+ break;
+
+ if (errno != EINTR)
+ {
+ if (throw_)
+ translate_connection_error (conn);
+ else
+ {
+ conn.mark_failed ();
+ return pair<bool, bool> (false, false);
+ }
+ }
+ }
+
+ return pair<bool, bool> (FD_ISSET (sock, &rds),
+ write && FD_ISSET (sock, &wds));
+ }
+ };
+
+ // A RAII object for recovering from an error in a pipeline.
+ //
+ // Specifically, it reads and discards results until reaching
+ // PGRES_PIPELINE_SYNC.
+ //
+ struct pipeline_recovery
+ {
+ pipeline_recovery (pipeline& pl, bool wdone, bool sync)
+ : pl_ (&pl), wdone_ (wdone), sync_ (sync)
+ {
+ }
+
+ ~pipeline_recovery ()
+ {
+ if (pl_ != 0 && !pl_->conn.failed ())
+ {
+ PGconn* ch (pl_->conn.handle ());
+
+ // This code runs as part of stack unwinding caused by an exception
+ // so if we encounter an error, we "upgrade" the existing exception
+ // by marking the connection as failed.
+ //
+ // The rest is essentially a special version of execute() below.
+ //
+ // Note that on the first iteration we may still have results from
+ // the previous call to PQconsumeInput() (and these results may
+ // be the entire outstanding sequence, in which case calling wait()
+ // will block indefinitely).
+ //
+ for (bool first (true);; first = false)
+ {
+ if (sync_)
+ {
+ assert (!wdone_);
+
+ if (PQpipelineSync (ch) == 0)
+ break;
+
+ sync_ = false;
+ }
+
+ pair<bool, bool> r (false, false);
+
+ if (!first)
+ {
+ r = pl_->wait (!wdone_);
+ if (!r.first && !r.second)
+ break;
+ }
+
+ if (r.first /* read */ || first)
+ {
+ if (r.first && PQconsumeInput (ch) == 0)
+ break;
+
+ while (PQisBusy (ch) == 0)
+ {
+ auto_handle<PGresult> res (PQgetResult (ch));
+
+ // We should only get NULLs as well as PGRES_PIPELINE_ABORTED
+ // finished with PGRES_PIPELINE_SYNC.
+ //
+ if (res != 0)
+ {
+ ExecStatusType stat (PQresultStatus (res));
+
+ if (stat == PGRES_PIPELINE_SYNC)
+ return;
+
+ assert (stat == PGRES_PIPELINE_ABORTED);
+ }
+ }
+ }
+
+ if (r.second /* write */)
+ {
+ int r (PQflush (ch));
+ if (r == -1)
+ break;
+
+ if (r == 0)
+ wdone_ = true;
+ }
+ }
+
+ pl_->conn.mark_failed ();
+ }
+ }
+
+ void
+ cancel ()
+ {
+ pl_ = 0;
+ }
+
+ private:
+ pipeline* pl_;
+ bool wdone_;
+ bool sync_;
+ };
+
+ size_t statement::
+ execute (const binding& param,
+ native_binding& native_param,
+ size_t n,
+ multiple_exceptions& mex,
+ bool (*process) (size_t, PGresult*, bool, void*),
+ void* data)
+ {
+ size_t i (0); // Parameter set being attempted.
+ mex.current (i);
+
+ PGconn* ch (conn_.handle ());
+
+ pipeline pl (conn_);
+
+ // True if we've written and read everything, respectively.
+ //
+ bool wdone (false), rdone (false);
+
+ for (size_t wn (0), rn (0); !rdone; )
+ {
+ // Note that there is a special version of this code above in
+ // ~pipeline_recovery().
+ //
+ pair<bool, bool> r (pl.wait (!wdone));
+
+ // Note that once we start the pipeline, any call that may throw
+ // without marking the connection as failed should be guarded by
+ // pipeline_recovery.
+
+ // Try to minimize the chance of blocking the server by first
+ // processing the result and then sending more queries.
+ //
+ if (r.first /* read */)
+ {
+ if (PQconsumeInput (ch) == 0)
+ translate_connection_error (conn_);
+
+ // Note that PQisBusy() will return 0 (and subsequent PQgetResult()
+ // -- NULL) if we have consumed all the results for the queries that
+ // we have sent so far. Thus the (wn > rn) condition. Note that for
+ // this to work correctly we have to count the PQpipelineSync() call
+ // below as one of the queries (since it has a separate result).
+ //
+ while (wn > rn && PQisBusy (ch) == 0)
+ {
+ auto_handle<PGresult> res (PQgetResult (ch));
+
+ ExecStatusType stat (PGRES_FATAL_ERROR);
+ bool gr (is_good_result (res, &stat));
+
+ if (stat == PGRES_PIPELINE_SYNC)
+ {
+ assert (wdone && rn == n);
+ rdone = true;
+ break;
+ }
+
+ assert (rn != n);
+ ++rn;
+
+ if (stat != PGRES_PIPELINE_ABORTED)
+ {
+ // translate_error() may throw an exception (e.g., deadlock)
+ // without marking the connection as failed.
+ //
+ {
+ pipeline_recovery plr (pl, wdone, wn < n);
+
+ if (!process (i, res, gr, data))
+ translate_error (conn_, res, i, &mex);
+
+ plr.cancel ();
+ }
+
+ mex.attempted (++i);
+ mex.current (i);
+ }
+ else
+ {
+ // Should we treat PGRES_PIPELINE_ABORTED entries as attempted
+ // or not? While we did issue PQsendQueryPrepared() for them,
+ // the server tells us that it did not attemp to execute them.
+ // So it feels like they should not be treated as attempted.
+ //
+ // Note that for this to fit into out multiple_exceptions model,
+ // such an incomplete batch should be fatal (otherwise we could
+ // end up with unattempted "holes"). This is currently the case
+ // for errors handled by translate_error() but not necessarily
+ // the case for those handled by the process function (e.g.,
+ // duplicate id handled by process_insert_result() below). So in
+ // a somewhat hackish way we assume the error (e.g., duplicate
+ // id) will always be translated to an exception and pre-mark
+ // multiple_exceptions as fatal.
+ //
+ mex.fatal (true);
+ }
+
+ // We get a NULL result after each query result.
+ //
+ {
+ PGresult* end (PQgetResult (ch));
+ assert (end == 0);
+ }
+ }
+ }
+
+ if (r.second /* write */)
+ {
+ // Send queries until we get blocked (write-biased). This feels like
+ // a better overall strategy to keep the server busy compared to
+ // sending one query at a time and then re-checking if there is
+ // anything to read because the results of INSERT/UPDATE/DELETE are
+ // presumably small and quite a few of them can get buffered before
+ // the server gets blocked.
+ //
+ for (;;)
+ {
+ if (wn < n)
+ {
+ bind_param (native_param, param, wn);
+
+ if (PQsendQueryPrepared (ch,
+ name_,
+ static_cast<int> (native_param.count),
+ native_param.values,
+ native_param.lengths,
+ native_param.formats,
+ 1) == 0)
+ translate_connection_error (conn_);
+
+ if (++wn == n)
+ {
+ if (PQpipelineSync (ch) == 0)
+ translate_connection_error (conn_);
+
+ // Count as one of the queries since it has a separate result.
+ //
+ ++wn;
+ }
+ }
+
+ // PQflush() result:
+ //
+ // 0 -- success (queue is now empty)
+ // 1 -- blocked
+ // -1 -- error
+ //
+ int r (PQflush (ch));
+ if (r == -1)
+ translate_connection_error (conn_);
+
+ if (r == 0)
+ {
+ if (wn < n)
+ {
+ // If we continue here, then we are write-biased. And if we
+ // break, then we are read-biased.
+ //
+#ifdef LIBPGSQL_READ_BIASED
+ break;
+#else
+ continue;
+#endif
+ }
+
+ wdone = true;
+ }
+
+ break; // Blocked or done.
+ }
+ }
+ }
+
+ pl.close ();
+ return i;
+ }
+#endif
+
//
// select_statement
//
@@ -690,10 +1123,7 @@ namespace odb
return no_data;
assert (current_row_ > 0);
- return bind_result (result_.bind,
- result_.count,
- handle_,
- current_row_ - 1)
+ return bind_result (result_, handle_, current_row_ - 1)
? success
: truncated;
}
@@ -704,11 +1134,7 @@ namespace odb
assert (current_row_ > 0);
assert (current_row_ <= row_count_);
- if (!bind_result (result_.bind,
- result_.count,
- handle_,
- current_row_ - 1,
- true))
+ if (!bind_result (result_, handle_, current_row_ - 1, true))
assert (false);
}
@@ -739,6 +1165,8 @@ namespace odb
native_param_ (native_param),
returning_ (returning)
{
+ if (returning_ != 0)
+ assert (returning_->count == 1);
}
insert_statement::
@@ -760,6 +1188,8 @@ namespace odb
native_param_ (native_param),
returning_ (returning)
{
+ if (returning_ != 0)
+ assert (returning_->count == 1);
}
bool insert_statement::
@@ -793,9 +1223,9 @@ namespace odb
//
if (returning_ == 0 && stat == PGRES_FATAL_ERROR)
{
- string s (PQresultErrorField (h, PG_DIAG_SQLSTATE));
+ const char* ss (PQresultErrorField (h, PG_DIAG_SQLSTATE));
- if (s == "23505")
+ if (ss != 0 && strcmp (ss, "23505") == 0)
return false;
}
@@ -803,11 +1233,76 @@ namespace odb
}
if (returning_ != 0)
- bind_result (returning_->bind, 1, h, 0, false);
+ bind_result (*returning_, h, 0);
+
+ return true;
+ }
+
+#if defined(LIBPQ_HAS_PIPELINING) && !defined(_WIN32)
+
+ struct insert_data
+ {
+ binding& param;
+ binding* returning;
+ };
+
+ static bool
+ process_insert_result (size_t i, PGresult* r, bool gr, void* data)
+ {
+ insert_data& d (*static_cast<insert_data*> (data));
+
+ unsigned long long& s (d.param.status[i]);
+ s = 1;
+
+ if (gr)
+ {
+ // Note that the result can never be truncated.
+ //
+ if (d.returning != 0)
+ statement::bind_result (*d.returning, r, 0, false, i);
+ }
+ else
+ {
+ // An auto-assigned object id should never cause a duplicate
+ // primary key.
+ //
+ if (d.returning == 0 &&
+ r != 0 && PQresultStatus (r) == PGRES_FATAL_ERROR)
+ {
+ // Note that statement::execute() assumes that this will eventually
+ // be translated to an entry in multiple_exceptions.
+ //
+ const char* ss (PQresultErrorField (r, PG_DIAG_SQLSTATE));
+
+ if (ss != 0 && strcmp (ss, "23505") == 0)
+ s = 0;
+ }
+
+ if (s == 1)
+ return false;
+ }
return true;
}
+ size_t insert_statement::
+ execute (size_t n, multiple_exceptions& mex)
+ {
+ {
+ odb::tracer* t;
+ if ((t = conn_.transaction_tracer ()) ||
+ (t = conn_.tracer ()) ||
+ (t = conn_.database ().tracer ()))
+ t->execute (conn_, *this);
+ }
+
+ insert_data d {param_, returning_};
+
+ return statement::execute (
+ param_, native_param_, n, mex, &process_insert_result, &d);
+ }
+#endif
+
//
// update_statement
//
@@ -882,6 +1377,43 @@ namespace odb
return affected_row_count (h);
}
+#if defined(LIBPQ_HAS_PIPELINING) && !defined(_WIN32)
+
+ static bool
+ process_update_result (size_t i, PGresult* r, bool gr, void* data)
+ {
+ binding& param (*static_cast<binding*> (data));
+
+ unsigned long long& s (param.status[i]);
+
+ if (gr)
+ {
+ s = affected_row_count (r);
+ return true;
+ }
+ else
+ {
+ s = update_statement::result_unknown;
+ return false;
+ }
+ }
+
+ size_t update_statement::
+ execute (size_t n, multiple_exceptions& mex)
+ {
+ {
+ odb::tracer* t;
+ if ((t = conn_.transaction_tracer ()) ||
+ (t = conn_.tracer ()) ||
+ (t = conn_.database ().tracer ()))
+ t->execute (conn_, *this);
+ }
+
+ return statement::execute (
+ param_, native_param_, n, mex, &process_update_result, &param_);
+ }
+#endif
+
//
// delete_statement
//
@@ -970,5 +1502,44 @@ namespace odb
return affected_row_count (h);
}
+
+#if defined(LIBPQ_HAS_PIPELINING) && !defined(_WIN32)
+
+ static bool
+ process_delete_result (size_t i, PGresult* r, bool gr, void* data)
+ {
+ binding& param (*static_cast<binding*> (data));
+
+ unsigned long long& s (param.status[i]);
+
+ if (gr)
+ {
+ s = affected_row_count (r);
+ return true;
+ }
+ else
+ {
+ s = delete_statement::result_unknown;
+ return false;
+ }
+ }
+
+ size_t delete_statement::
+ execute (size_t n, multiple_exceptions& mex)
+ {
+ assert (param_ != 0);
+
+ {
+ odb::tracer* t;
+ if ((t = conn_.transaction_tracer ()) ||
+ (t = conn_.tracer ()) ||
+ (t = conn_.database ().tracer ()))
+ t->execute (conn_, *this);
+ }
+
+ return statement::execute (
+ *param_, native_param_, n, mex, &process_delete_result, param_);
+ }
+#endif
}
}
diff --git a/odb/pgsql/statement.hxx b/odb/pgsql/statement.hxx
index e5c084d..139d2d6 100644
--- a/odb/pgsql/statement.hxx
+++ b/odb/pgsql/statement.hxx
@@ -1,5 +1,4 @@
// file : odb/pgsql/statement.hxx
-// copyright : Copyright (c) 2005-2019 Code Synthesis Tools CC
// license : GNU GPL v2; see accompanying LICENSE file
#ifndef ODB_PGSQL_STATEMENT_HXX
@@ -64,22 +63,24 @@ namespace odb
void
deallocate ();
- // Adapt an ODB binding to a native PostgreSQL parameter binding.
+ // Adapt an ODB binding to a native PostgreSQL parameter binding. If pos
+ // is not 0, then bind the parameter set at this position in a batch.
//
static void
- bind_param (native_binding&, const binding&);
+ bind_param (native_binding&, const binding&, std::size_t pos = 0);
// Populate an ODB binding given a PostgreSQL result. If the truncated
// argument is true, then only truncated columns are extracted. Return
// true if all the data was extracted successfully and false if one or
- // more columns were truncated.
+ // more columns were truncated. If pos is not 0, then populate the
+ // parameter set at this position in a batch.
//
static bool
- bind_result (bind*,
- std::size_t count,
+ bind_result (const binding&,
PGresult*,
std::size_t row,
- bool truncated = false);
+ bool truncated = false,
+ std::size_t pos = 0);
protected:
// We keep two versions to take advantage of std::string COW.
@@ -103,6 +104,16 @@ namespace odb
const Oid* types,
std::size_t types_count);
+ // Bulk execute implementation.
+ //
+ std::size_t
+ execute (const binding& param,
+ native_binding& native_param,
+ std::size_t n,
+ multiple_exceptions&,
+ bool (*process) (size_t i, PGresult*, bool good, void* data),
+ void* data);
+
private:
void
init (statement_kind,
@@ -297,6 +308,20 @@ namespace odb
bool
execute ();
+ // Return the number of parameter sets (out of n) that were attempted.
+ //
+ std::size_t
+ execute (std::size_t n, multiple_exceptions&);
+
+ // Return true if successful and false if this row is a duplicate.
+ // All other errors are reported via exceptions.
+ //
+ bool
+ result (std::size_t i)
+ {
+ return param_.status[i] != 0;
+ }
+
private:
insert_statement (const insert_statement&);
insert_statement& operator= (const insert_statement&);
@@ -335,6 +360,22 @@ namespace odb
unsigned long long
execute ();
+ // Return the number of parameter sets (out of n) that were attempted.
+ //
+ std::size_t
+ execute (std::size_t n, multiple_exceptions&);
+
+ // Return the number of rows affected (updated) by the parameter
+ // set. All errors are reported by throwing exceptions.
+ //
+ static const unsigned long long result_unknown = ~0ULL;
+
+ unsigned long long
+ result (std::size_t i)
+ {
+ return param_.status[i];
+ }
+
private:
update_statement (const update_statement&);
update_statement& operator= (const update_statement&);
@@ -377,6 +418,22 @@ namespace odb
unsigned long long
execute ();
+ // Return the number of parameter sets (out of n) that were attempted.
+ //
+ std::size_t
+ execute (std::size_t n, multiple_exceptions&);
+
+ // Return the number of rows affected (deleted) by the parameter
+ // set. All errors are reported by throwing exceptions.
+ //
+ static const unsigned long long result_unknown = ~0ULL;
+
+ unsigned long long
+ result (std::size_t i)
+ {
+ return param_->status[i];
+ }
+
private:
delete_statement (const delete_statement&);
delete_statement& operator= (const delete_statement&);
diff --git a/odb/pgsql/statements-base.cxx b/odb/pgsql/statements-base.cxx
index 2145c02..0e72555 100644
--- a/odb/pgsql/statements-base.cxx
+++ b/odb/pgsql/statements-base.cxx
@@ -1,5 +1,4 @@
// file : odb/pgsql/statements-base.cxx
-// copyright : Copyright (c) 2005-2019 Code Synthesis Tools CC
// license : GNU GPL v2; see accompanying LICENSE file
#include <odb/pgsql/statements-base.hxx>
diff --git a/odb/pgsql/statements-base.hxx b/odb/pgsql/statements-base.hxx
index 3d900cb..8b45bdc 100644
--- a/odb/pgsql/statements-base.hxx
+++ b/odb/pgsql/statements-base.hxx
@@ -1,5 +1,4 @@
// file : odb/pgsql/statements-base.hxx
-// copyright : Copyright (c) 2005-2019 Code Synthesis Tools CC
// license : GNU GPL v2; see accompanying LICENSE file
#ifndef ODB_PGSQL_STATEMENTS_BASE_HXX
diff --git a/odb/pgsql/tracer.cxx b/odb/pgsql/tracer.cxx
index e7f0fbc..48e0cf8 100644
--- a/odb/pgsql/tracer.cxx
+++ b/odb/pgsql/tracer.cxx
@@ -1,5 +1,4 @@
// file : odb/pgsql/tracer.cxx
-// copyright : Copyright (c) 2009-2019 Code Synthesis Tools CC
// license : GNU GPL v2; see accompanying LICENSE file
#include <odb/pgsql/tracer.hxx>
diff --git a/odb/pgsql/tracer.hxx b/odb/pgsql/tracer.hxx
index 80fc242..89cda1c 100644
--- a/odb/pgsql/tracer.hxx
+++ b/odb/pgsql/tracer.hxx
@@ -1,5 +1,4 @@
// file : odb/pgsql/tracer.hxx
-// copyright : Copyright (c) 2009-2019 Code Synthesis Tools CC
// license : GNU GPL v2; see accompanying LICENSE file
#ifndef ODB_PGSQL_TRACER_HXX
diff --git a/odb/pgsql/traits-calls.hxx b/odb/pgsql/traits-calls.hxx
index 78ea087..419c7b2 100644
--- a/odb/pgsql/traits-calls.hxx
+++ b/odb/pgsql/traits-calls.hxx
@@ -1,5 +1,4 @@
// file : odb/pgsql/traits-calls.hxx
-// copyright : Copyright (c) 2009-2019 Code Synthesis Tools CC
// license : GNU GPL v2; see accompanying LICENSE file
#ifndef ODB_PGSQL_TRAITS_CALLS_HXX
diff --git a/odb/pgsql/traits.cxx b/odb/pgsql/traits.cxx
index b729fd6..11a3a67 100644
--- a/odb/pgsql/traits.cxx
+++ b/odb/pgsql/traits.cxx
@@ -1,5 +1,4 @@
// file : odb/pgsql/traits.cxx
-// copyright : Copyright (c) 2005-2019 Code Synthesis Tools CC
// license : GNU GPL v2; see accompanying LICENSE file
#include <odb/pgsql/traits.hxx>
diff --git a/odb/pgsql/traits.hxx b/odb/pgsql/traits.hxx
index 8bc5347..3d87033 100644
--- a/odb/pgsql/traits.hxx
+++ b/odb/pgsql/traits.hxx
@@ -1,5 +1,4 @@
// file : odb/pgsql/traits.hxx
-// copyright : Copyright (c) 2005-2019 Code Synthesis Tools CC
// license : GNU GPL v2; see accompanying LICENSE file
#ifndef ODB_PGSQL_TRAITS_HXX
diff --git a/odb/pgsql/transaction-impl.cxx b/odb/pgsql/transaction-impl.cxx
index d9ae2a6..012fe18 100644
--- a/odb/pgsql/transaction-impl.cxx
+++ b/odb/pgsql/transaction-impl.cxx
@@ -1,5 +1,4 @@
// file : odb/pgsql/transaction-impl.cxx
-// copyright : Copyright (c) 2009-2019 Code Synthesis Tools CC
// license : GNU GPL v2; see accompanying LICENSE file
#include <cassert>
diff --git a/odb/pgsql/transaction-impl.hxx b/odb/pgsql/transaction-impl.hxx
index 90af9d0..5c93b0e 100644
--- a/odb/pgsql/transaction-impl.hxx
+++ b/odb/pgsql/transaction-impl.hxx
@@ -1,5 +1,4 @@
// file : odb/pgsql/transaction-impl.hxx
-// copyright : Copyright (c) 2009-2019 Code Synthesis Tools CC
// license : GNU GPL v2; see accompanying LICENSE file
#ifndef ODB_PGSQL_TRANSACTION_IMPL_HXX
@@ -39,17 +38,12 @@ namespace odb
virtual void
rollback ();
- connection_type&
- connection ();
-
private:
connection_ptr connection_;
};
}
}
-#include <odb/pgsql/transaction-impl.ixx>
-
#include <odb/post.hxx>
#endif // ODB_PGSQL_TRANSACTION_IMPL_HXX
diff --git a/odb/pgsql/transaction-impl.ixx b/odb/pgsql/transaction-impl.ixx
deleted file mode 100644
index 67c7e57..0000000
--- a/odb/pgsql/transaction-impl.ixx
+++ /dev/null
@@ -1,15 +0,0 @@
-// file : odb/pgsql/transaction-impl.ixx
-// copyright : Copyright (c) 2009-2019 Code Synthesis Tools CC
-// license : GNU GPL v2; see accompanying LICENSE file
-
-namespace odb
-{
- namespace pgsql
- {
- inline transaction_impl::connection_type& transaction_impl::
- connection ()
- {
- return *connection_;
- }
- }
-}
diff --git a/odb/pgsql/transaction.cxx b/odb/pgsql/transaction.cxx
index c9410b2..3b32d80 100644
--- a/odb/pgsql/transaction.cxx
+++ b/odb/pgsql/transaction.cxx
@@ -1,5 +1,4 @@
// file : odb/pgsql/transaction.cxx
-// copyright : Copyright (c) 2009-2019 Code Synthesis Tools CC
// license : GNU GPL v2; see accompanying LICENSE file
#include <cassert>
diff --git a/odb/pgsql/transaction.hxx b/odb/pgsql/transaction.hxx
index d6f87ca..e83c754 100644
--- a/odb/pgsql/transaction.hxx
+++ b/odb/pgsql/transaction.hxx
@@ -1,5 +1,4 @@
// file : odb/pgsql/transaction.hxx
-// copyright : Copyright (c) 2009-2019 Code Synthesis Tools CC
// license : GNU GPL v2; see accompanying LICENSE file
#ifndef ODB_PGSQL_TRANSACTION_HXX
@@ -42,6 +41,9 @@ namespace odb
connection_type&
connection ();
+ connection_type&
+ connection (odb::database&);
+
// Return current transaction or throw if there is no transaction
// in effect.
//
diff --git a/odb/pgsql/transaction.ixx b/odb/pgsql/transaction.ixx
index 40313bc..31aa603 100644
--- a/odb/pgsql/transaction.ixx
+++ b/odb/pgsql/transaction.ixx
@@ -1,5 +1,4 @@
// file : odb/pgsql/transaction.ixx
-// copyright : Copyright (c) 2009-2019 Code Synthesis Tools CC
// license : GNU GPL v2; see accompanying LICENSE file
#include <odb/pgsql/database.hxx>
@@ -40,7 +39,13 @@ namespace odb
inline transaction::connection_type& transaction::
connection ()
{
- return implementation ().connection ();
+ return static_cast<connection_type&> (odb::transaction::connection ());
+ }
+
+ inline transaction::connection_type& transaction::
+ connection (odb::database& db)
+ {
+ return static_cast<connection_type&> (odb::transaction::connection (db));
}
inline void transaction::
diff --git a/odb/pgsql/version-build2-stub.hxx b/odb/pgsql/version-build2-stub.hxx
index bb9edc8..a99b093 100644
--- a/odb/pgsql/version-build2-stub.hxx
+++ b/odb/pgsql/version-build2-stub.hxx
@@ -1,5 +1,4 @@
// file : odb/pgsql/version-build2-stub.hxx
-// copyright : Copyright (c) 2005-2019 Code Synthesis Tools CC
// license : GNU GPL v2; see accompanying LICENSE file
#include <odb/pgsql/version.hxx>
diff --git a/odb/pgsql/version-build2.hxx.in b/odb/pgsql/version-build2.hxx.in
index d33d1d5..ed4396b 100644
--- a/odb/pgsql/version-build2.hxx.in
+++ b/odb/pgsql/version-build2.hxx.in
@@ -1,5 +1,4 @@
// file : odb/pgsql/version-build2.hxx.in
-// copyright : Copyright (c) 2005-2019 Code Synthesis Tools CC
// license : GNU GPL v2; see accompanying LICENSE file
#ifndef LIBODB_PGSQL_VERSION // Note: using the version macro itself.
diff --git a/odb/pgsql/version.hxx b/odb/pgsql/version.hxx
index 78b9f79..e050de4 100644
--- a/odb/pgsql/version.hxx
+++ b/odb/pgsql/version.hxx
@@ -1,5 +1,4 @@
// file : odb/pgsql/version.hxx
-// copyright : Copyright (c) 2005-2019 Code Synthesis Tools CC
// license : GNU GPL v2; see accompanying LICENSE file
#ifdef LIBODB_PGSQL_BUILD2
@@ -33,15 +32,15 @@
// Check that we have compatible ODB version.
//
-#if ODB_VERSION != 20466
+#if ODB_VERSION != 20476
# error incompatible odb interface version detected
#endif
// libodb-pgsql version: odb interface version plus the bugfix
// version.
//
-#define LIBODB_PGSQL_VERSION 2049966
-#define LIBODB_PGSQL_VERSION_STR "2.5.0-b.16"
+#define LIBODB_PGSQL_VERSION 2049976
+#define LIBODB_PGSQL_VERSION_STR "2.5.0-b.26"
#include <odb/post.hxx>
diff --git a/odb/pgsql/view-result.hxx b/odb/pgsql/view-result.hxx
index 819b8fb..f9acace 100644
--- a/odb/pgsql/view-result.hxx
+++ b/odb/pgsql/view-result.hxx
@@ -1,5 +1,4 @@
// file : odb/pgsql/view-result.hxx
-// copyright : Copyright (c) 2009-2019 Code Synthesis Tools CC
// license : GNU GPL v2; see accompanying LICENSE file
#ifndef ODB_PGSQL_VIEW_RESULT_HXX
diff --git a/odb/pgsql/view-result.txx b/odb/pgsql/view-result.txx
index eaf8969..980811a 100644
--- a/odb/pgsql/view-result.txx
+++ b/odb/pgsql/view-result.txx
@@ -1,5 +1,4 @@
// file : odb/pgsql/view-result.txx
-// copyright : Copyright (c) 2009-2019 Code Synthesis Tools CC
// license : GNU GPL v2; see accompanying LICENSE file
#include <odb/callback.hxx>
diff --git a/odb/pgsql/view-statements.hxx b/odb/pgsql/view-statements.hxx
index a512181..970e610 100644
--- a/odb/pgsql/view-statements.hxx
+++ b/odb/pgsql/view-statements.hxx
@@ -1,5 +1,4 @@
// file : odb/pgsql/view-statements.hxx
-// copyright : Copyright (c) 2005-2019 Code Synthesis Tools CC
// license : GNU GPL v2; see accompanying LICENSE file
#ifndef ODB_PGSQL_VIEW_STATEMENTS_HXX
diff --git a/odb/pgsql/view-statements.txx b/odb/pgsql/view-statements.txx
index c8b1db7..afa2a49 100644
--- a/odb/pgsql/view-statements.txx
+++ b/odb/pgsql/view-statements.txx
@@ -1,5 +1,4 @@
// file : odb/pgsql/view-statements.txx
-// copyright : Copyright (c) 2005-2019 Code Synthesis Tools CC
// license : GNU GPL v2; see accompanying LICENSE file
#include <cstddef> // std::size_t
diff --git a/repositories.manifest b/repositories.manifest
index b4bccc3..4451c88 100644
--- a/repositories.manifest
+++ b/repositories.manifest
@@ -3,8 +3,12 @@ summary: PostgreSQL ODB runtime library repository
:
role: prerequisite
-location: https://git.build2.org/packaging/postgresql/libpq.git##HEAD
+location: https://git.build2.org/packaging/postgresql/postgresql.git##HEAD
:
role: prerequisite
location: ../libodb.git##HEAD
+
+:
+role: prerequisite
+location: https://git.codesynthesis.com/cli/cli.git##HEAD
diff --git a/tests/basics/buildfile b/tests/basics/buildfile
index b47b13f..fccb243 100644
--- a/tests/basics/buildfile
+++ b/tests/basics/buildfile
@@ -1,5 +1,4 @@
# file : tests/basics/buildfile
-# copyright : Copyright (c) 2009-2019 Code Synthesis Tools CC
# license : GNU GPL v2; see accompanying LICENSE file
import libs = libodb-pgsql%lib{odb-pgsql}
diff --git a/tests/basics/driver.cxx b/tests/basics/driver.cxx
index 287a52e..efd1985 100644
--- a/tests/basics/driver.cxx
+++ b/tests/basics/driver.cxx
@@ -1,5 +1,4 @@
// file : tests/basics/driver.cxx
-// copyright : Copyright (c) 2009-2019 Code Synthesis Tools CC
// license : GNU GPL v2; see accompanying LICENSE file
// Basic test to make sure the library is usable. Functionality testing
diff --git a/tests/build/bootstrap.build b/tests/build/bootstrap.build
index c5c067b..6ee38db 100644
--- a/tests/build/bootstrap.build
+++ b/tests/build/bootstrap.build
@@ -1,5 +1,4 @@
# file : tests/build/bootstrap.build
-# copyright : Copyright (c) 2009-2019 Code Synthesis Tools CC
# license : GNU GPL v2; see accompanying LICENSE file
project = # Unnamed subproject.
diff --git a/tests/build/root.build b/tests/build/root.build
index da6ff40..6c5a90b 100644
--- a/tests/build/root.build
+++ b/tests/build/root.build
@@ -1,5 +1,4 @@
# file : tests/build/root.build
-# copyright : Copyright (c) 2009-2019 Code Synthesis Tools CC
# license : GNU GPL v2; see accompanying LICENSE file
cxx.std = latest
diff --git a/tests/buildfile b/tests/buildfile
index 3614001..57588a4 100644
--- a/tests/buildfile
+++ b/tests/buildfile
@@ -1,5 +1,4 @@
# file : tests/buildfile
-# copyright : Copyright (c) 2009-2019 Code Synthesis Tools CC
# license : GNU GPL v2; see accompanying LICENSE file
./: {*/ -build/}
diff --git a/version b/version
deleted file mode 100644
index dfe1a80..0000000
--- a/version
+++ /dev/null
@@ -1 +0,0 @@
-2.5.0-b.16
diff --git a/version.txt b/version.txt
new file mode 100644
index 0000000..6bc2f39
--- /dev/null
+++ b/version.txt
@@ -0,0 +1 @@
+2.5.0-b.26