Skip to content

Commit

Permalink
jtv#841: Support parsing a field as an SQL array. (jtv#854)
Browse files Browse the repository at this point in the history
It's annoying that there is already a `field::as_array()`, which returns an obsolete `array_parser` with its clunky API.  I'm being aggressive in deprecating that one, so that eventually the _new_ function can assume its name without clashing.
  • Loading branch information
jtv committed Jul 5, 2024
1 parent f9e9f56 commit 840a13a
Show file tree
Hide file tree
Showing 4 changed files with 40 additions and 5 deletions.
1 change: 1 addition & 0 deletions NEWS
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
- Another fix to the readthedocs documentation build. (#845)
- Work around CMake 3.30 renaming one of its functions. (#851)
- Remove obscure deprecated `stream_to` constructor that never worked. (#853)
- Support reading a field as an SQL array using `as_sql_array()`. (#841)
7.9.1
- Fix bad conversion of array of empty strings to string. (#816)
- Move `[[likely]]` feature check back to compile time, to speed up configure.
Expand Down
12 changes: 7 additions & 5 deletions include/pqxx/array.hxx
Original file line number Diff line number Diff line change
Expand Up @@ -200,7 +200,11 @@ private:
"Malformed array: does not end in the right number of '}'."};
}

explicit array(std::string_view data, pqxx::internal::encoding_group enc)
// Allow fields to construct arrays passing the encoding group.
// Couldn't make this work through a call gate, thanks to the templating.
friend class ::pqxx::field;

array(std::string_view data, pqxx::internal::encoding_group enc)
{
using group = pqxx::internal::encoding_group;
switch (enc)
Expand Down Expand Up @@ -502,10 +506,8 @@ private:
};


/// Low-level array parser.
/** @warning This is not a great API. Something nicer is on the way.
*
* Use this to read an array field retrieved from the database.
/// Low-level parser for C++ arrays. @deprecated Use @ref pqxx::array instead.
/** Clunky old API for parsing SQL arrays.
*
* @warning This parser will only work reliably if your client encoding is
* UTF-8, ASCII, or a "safe ASCII superset" (such as the EUC encodings) where
Expand Down
17 changes: 17 additions & 0 deletions include/pqxx/field.hxx
Original file line number Diff line number Diff line change
Expand Up @@ -243,13 +243,30 @@ public:
return as<O<T>>();
}

/// Read SQL array contents as a @ref pqxx::array.
template<typename ELEMENT, auto... ARGS>
array<ELEMENT, ARGS...> as_sql_array() const
{
using array_type = array<ELEMENT, ARGS...>;

// There's no such thing as a null SQL array.
if (is_null())
internal::throw_null_conversion(type_name<array_type>);
else
return array_type{this->view(), this->m_home.m_encoding};
}

/// Parse the field as an SQL array.
/** Call the parser to retrieve values (and structure) from the array.
*
* Make sure the @ref result object stays alive until parsing is finished. If
* you keep the @ref row of `field` object alive, it will keep the @ref
* result object alive as well.
*/
[[deprecated(
"Avoid pqxx::array_parser. "
"Instead, use as_sql_array() to convert to pqxx::array."
)]]
array_parser as_array() const & noexcept
{
return array_parser{c_str(), m_home.m_encoding};
Expand Down
15 changes: 15 additions & 0 deletions test/unit/test_array.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -693,6 +693,20 @@ void test_array_iterates_in_row_major_order()
}


void test_as_sql_array()
{
pqxx::connection conn;
pqxx::row r;
{
pqxx::work tx{conn};
r = tx.exec1("SELECT ARRAY [5, 4, 3, 2]");
// Connection closes, but we should still be able to parse the array.
}
auto const array{r[0].as_sql_array<int>()};
PQXX_CHECK_EQUAL(array[1], 4, "Got wrong value out of array.");
}


PQXX_REGISTER_TEST(test_empty_arrays);
PQXX_REGISTER_TEST(test_array_null_value);
PQXX_REGISTER_TEST(test_array_double_quoted_string);
Expand All @@ -714,4 +728,5 @@ PQXX_REGISTER_TEST(test_array_parses_multidim_arrays);
PQXX_REGISTER_TEST(test_array_at_checks_bounds);
PQXX_REGISTER_TEST(test_array_iterates_in_row_major_order);
PQXX_REGISTER_TEST(test_array_generate_empty_strings);
PQXX_REGISTER_TEST(test_as_sql_array);
} // namespace

0 comments on commit 840a13a

Please sign in to comment.