diff --git a/include/tao/pq/parameter_traits_array.hpp b/include/tao/pq/parameter_traits_array.hpp index d82982b..85656ce 100644 --- a/include/tao/pq/parameter_traits_array.hpp +++ b/include/tao/pq/parameter_traits_array.hpp @@ -49,41 +49,26 @@ namespace tao::pq namespace internal { template< typename T > - void to_array( std::string& data, const T& v ); - - template< typename T, std::size_t... Is > - void to_array_indexed( std::string& data, const T& v, std::index_sequence< Is... > /*unused*/ ) + requires( !pq::is_array_parameter< T > ) && ( parameter_traits< T >::columns == 1 ) + void to_array( std::string& data, const T& v ) { - data += '{'; - ( ( v.template element< Is >( data ), data += ',' ), ... ); - *data.rbegin() = '}'; + parameter_traits< T >( v ).template element< 0 >( data ); } template< typename T > + requires pq::is_array_parameter< T > void to_array( std::string& data, const T& v ) { - if constexpr( pq::is_array_parameter< T > ) { - data += '{'; - if( v.empty() ) { - data += '}'; - } - else { - for( const auto& e : v ) { - internal::to_array( data, e ); - data += ','; - } - *data.rbegin() = '}'; - } + data += '{'; + if( v.empty() ) { + data += '}'; } else { - const auto t = parameter_traits< T >( v ); - if constexpr( t.columns == 1 ) { - t.template element< 0 >( data ); - } - else { - static_assert( t.columns > 1 ); - internal::to_array_indexed( data, t, std::make_index_sequence< t.columns >() ); + for( const auto& e : v ) { + internal::to_array( data, e ); + data += ','; } + *data.rbegin() = '}'; } } diff --git a/include/tao/pq/result_traits_array.hpp b/include/tao/pq/result_traits_array.hpp index d3b8110..c98c8b5 100644 --- a/include/tao/pq/result_traits_array.hpp +++ b/include/tao/pq/result_traits_array.hpp @@ -13,7 +13,6 @@ #include #include -#include #include namespace tao::pq @@ -70,27 +69,19 @@ namespace tao::pq } template< typename T > - requires( !pq::is_array_result< T > ) && ( result_traits_size< T > >= 2 ) + requires pq::is_array_result< T > [[nodiscard]] auto parse( const char*& value ) -> T { if( *value++ != '{' ) { throw std::invalid_argument( "expected '{'" ); } - throw std::runtime_error( "NOT YET IMPLEMENTED" ); - } - template< typename T > - requires pq::is_array_result< T > - [[nodiscard]] auto parse( const char*& value ) -> T - { T container; - if( *value++ != '{' ) { - throw std::invalid_argument( "expected '{'" ); - } if( *value == '}' ) { ++value; return container; } + while( true ) { using value_type = typename T::value_type; if constexpr( requires { container.push_back( parse< value_type >( value ) ); } ) { diff --git a/src/test/pq/array.cpp b/src/test/pq/array.cpp index e7a311c..261302a 100644 --- a/src/test/pq/array.cpp +++ b/src/test/pq/array.cpp @@ -78,45 +78,6 @@ namespace TEST_ASSERT( r == v ); } - { - connection->execute( "DROP TABLE IF EXISTS tao_array_test" ); - connection->execute( "CREATE TABLE tao_array_test ( a TEXT[][] NOT NULL )" ); - - using type = std::vector< std::pair< std::string, std::string > >; - const type v = { { "1", "F\"O\\O" }, { "4", " XYZ " } }; - connection->execute( "INSERT INTO tao_array_test VALUES ( $1 )", v ); - - // TODO: Add result_traits... - // const auto r = connection->execute( "SELECT * FROM tao_array_test" ).as< type >(); - // TEST_ASSERT( r == v ); - } - - { - connection->execute( "DROP TABLE IF EXISTS tao_array_test" ); - connection->execute( "CREATE TABLE tao_array_test ( a TEXT[][] NOT NULL )" ); - - using type = std::vector< std::tuple< int, std::string, std::optional< std::string > > >; - const type v = { { 1, "F\"O\\O", std::nullopt }, { 4, " XYZ ", "BAR" } }; - connection->execute( "INSERT INTO tao_array_test VALUES ( $1 )", v ); - - // TODO: Add result_traits... - // const auto r = connection->execute( "SELECT * FROM tao_array_test" ).as< type >(); - // TEST_ASSERT( r == v ); - } - - { - connection->execute( "DROP TABLE IF EXISTS tao_array_test" ); - connection->execute( "CREATE TABLE tao_array_test ( a TEXT[] NOT NULL )" ); - - // note: a tuple with only one element is *not* treated as an array - using type = std::vector< std::tuple< std::string > >; - const type v = { { "F\"O\\O" }, { " XYZ " } }; - connection->execute( "INSERT INTO tao_array_test VALUES ( $1 )", v ); - - const auto r = connection->execute( "SELECT * FROM tao_array_test" ).as< type >(); - TEST_ASSERT( r == v ); - } - { connection->execute( "DROP TABLE IF EXISTS tao_array_test" ); connection->execute( "CREATE TABLE tao_array_test ( a BYTEA[][] NOT NULL )" );