Skip to content

Commit

Permalink
Make stream_to accept optional<string_view>. (#597)
Browse files Browse the repository at this point in the history
Fixes #596.

It'd be nice to support each of `optional`, `shared_ptr`, `unique_ptr`,
and potentially other smart pointer types for each of these string
types.  But doing that without C++20's "concepts" is going to be a
little hairy.

Also switching CircleCI tests to use clang, just because the `debian/unstable` image keeps failing with a warning in gcc's own headers.  Can't reproduce that on my own machine, so I hope it's just a transient that's already fixed in Debian.
  • Loading branch information
jtv authored Sep 2, 2022
1 parent 645ea77 commit d35ce16
Show file tree
Hide file tree
Showing 4 changed files with 82 additions and 8 deletions.
12 changes: 6 additions & 6 deletions .circleci/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,7 @@ version: 2
jobs:
build:
docker:
- image: debian:testing
# - image: postgres:latest
- image: debian:unstable
environment:
- PGHOST: "/tmp"
steps:
Expand All @@ -14,10 +13,10 @@ jobs:
command: apt update
- run:
name: Install
command: apt install -y lsb-release python3 cmake postgresql libpq-dev postgresql-server-dev-all build-essential autoconf dh-autoreconf autoconf-archive automake cppcheck
command: apt install -y lsb-release python3 cmake postgresql libpq-dev postgresql-server-dev-all build-essential autoconf dh-autoreconf autoconf-archive automake cppcheck clang
- run:
name: Identify
command: lsb_release -a && c++ --version
command: lsb_release -a && c++ --version && clang++ --version
- run:
name: Prepare postgres
command: |
Expand All @@ -35,7 +34,7 @@ jobs:
command: createdb root
- run:
name: Autogen
command: NOCONFIGURE=1 ./autogen.sh
command: ./autogen.sh
- run:
name: Configure
command: |
Expand All @@ -44,7 +43,8 @@ jobs:
--enable-maintainer-mode \
--enable-audit \
--enable-shared --disable-static \
CXXFLAGS=-O3
CXXFLAGS='-O3 -std=c++17' \
CXX=clang++
- store_artifacts:
path: config.log
- run:
Expand Down
2 changes: 1 addition & 1 deletion config/Makefile.in
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,7 @@ am__can_run_installinfo = \
esac
am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP)
am__DIST_COMMON = $(srcdir)/Makefile.in compile config.guess \
config.sub install-sh ltmain.sh missing mkinstalldirs
config.sub depcomp install-sh ltmain.sh missing mkinstalldirs
DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
ACLOCAL = @ACLOCAL@
AMTAR = @AMTAR@
Expand Down
26 changes: 25 additions & 1 deletion include/pqxx/stream_to.hxx
Original file line number Diff line number Diff line change
Expand Up @@ -349,7 +349,6 @@ private:
// Shrink to fit. Keep the tab though.
m_buffer.resize(static_cast<std::size_t>(end - data));
}
// TODO: Also support std::optional<std::string_view> etc. (#596)
else if constexpr (
std::is_same_v<Field, std::string> or
std::is_same_v<Field, std::string_view> or
Expand All @@ -359,6 +358,31 @@ private:
m_field_buf.resize(budget);
escape_field_to_buffer(f);
}
else if constexpr (
std::is_same_v<Field, std::optional<std::string>> or
std::is_same_v<Field, std::optional<std::string_view>> or
std::is_same_v<Field, std::optional<zview>>)
{
// Optional string. It's not null (we checked for that above), so...
// Treat like a string.
m_field_buf.resize(budget);
escape_field_to_buffer(f.value());
}
// TODO: Support deleter template argument on unique_ptr.
else if constexpr (
std::is_same_v<Field, std::unique_ptr<std::string>> or
std::is_same_v<Field, std::unique_ptr<std::string_view>> or
std::is_same_v<Field, std::unique_ptr<zview>> or
std::is_same_v<Field, std::shared_ptr<std::string>> or
std::is_same_v<Field, std::shared_ptr<std::string_view>> or
std::is_same_v<Field, std::shared_ptr<zview>>)
{
// TODO: Can we generalise this elegantly without Concepts?
// Effectively also an optional string. It's not null (we checked
// for that above).
m_field_buf.resize(budget);
escape_field_to_buffer(*f);
}
else
{
// This field needs to be converted to a string, and after that,
Expand Down
50 changes: 50 additions & 0 deletions test/unit/test_stream_to.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -436,10 +436,60 @@ void test_stream_to_quotes_arguments()
}


void test_stream_to_optionals()
{
pqxx::connection conn;
pqxx::work tx{conn};

tx.exec0("CREATE TEMP TABLE pqxx_strings(key integer, value varchar)");

auto stream{pqxx::stream_to::table(tx, {"pqxx_strings"}, {"key", "value"})};
stream.write_values(1, std::optional<std::string>{});
stream.write_values(2, std::optional<std::string_view>{});
stream.write_values(3, std::optional<pqxx::zview>{});
stream.write_values(4, std::optional<std::string>{"Opt str."});
stream.write_values(5, std::optional<std::string_view>{"Opt sv."});
stream.write_values(6, std::optional<pqxx::zview>{"Opt zv."});

stream.write_values(7, std::shared_ptr<std::string>{});
stream.write_values(8, std::shared_ptr<std::string_view>{});
stream.write_values(9, std::shared_ptr<pqxx::zview>{});
stream.write_values(10, std::make_shared<std::string>("Shared str."));
stream.write_values(11, std::make_shared<std::string_view>("Shared sv."));
stream.write_values(12, std::make_shared<pqxx::zview>("Shared zv."));

stream.write_values(13, std::unique_ptr<std::string>{});
stream.write_values(14, std::unique_ptr<std::string_view>{});
stream.write_values(15, std::unique_ptr<pqxx::zview>{});
stream.write_values(16, std::make_unique<std::string>("Uq str."));
stream.write_values(17, std::make_unique<std::string_view>("Uq sv."));
stream.write_values(18, std::make_unique<pqxx::zview>("Uq zv."));
stream.complete();

std::string nulls;
for (auto [key] : tx.query<int>(
"SELECT key FROM pqxx_strings WHERE value IS NULL ORDER BY key"))
nulls += pqxx::to_string(key) + '.';
PQXX_CHECK_EQUAL(
nulls, "1.2.3.7.8.9.13.14.15.", "Unexpected list of nulls.");

std::string values;
for (auto [value] :
tx.query<std::string>("SELECT value FROM pqxx_strings WHERE value IS "
"NOT NULL ORDER BY key"))
values += value;
PQXX_CHECK_EQUAL(
values,
"Opt str.Opt sv.Opt zv.Shared str.Shared sv.Shared zv.Uq str.Uq sv.Uq zv.",
"Unexpected list of values.");
}


PQXX_REGISTER_TEST(test_stream_to);
PQXX_REGISTER_TEST(test_container_stream_to);
PQXX_REGISTER_TEST(test_stream_to_does_nonnull_optional);
PQXX_REGISTER_TEST(test_stream_to_factory_with_static_columns);
PQXX_REGISTER_TEST(test_stream_to_factory_with_dynamic_columns);
PQXX_REGISTER_TEST(test_stream_to_quotes_arguments);
PQXX_REGISTER_TEST(test_stream_to_optionals);
} // namespace

0 comments on commit d35ce16

Please sign in to comment.