Skip to content

Commit

Permalink
Use concepts for parameter types
Browse files Browse the repository at this point in the history
  • Loading branch information
d-frey committed Nov 23, 2024
1 parent 1a73e29 commit 0272203
Show file tree
Hide file tree
Showing 7 changed files with 58 additions and 59 deletions.
3 changes: 2 additions & 1 deletion include/tao/pq/connection.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
#include <tao/pq/internal/zsv.hpp>
#include <tao/pq/isolation_level.hpp>
#include <tao/pq/notification.hpp>
#include <tao/pq/parameter.hpp>
#include <tao/pq/poll.hpp>
#include <tao/pq/transaction.hpp>
#include <tao/pq/transaction_status.hpp>
Expand Down Expand Up @@ -149,7 +150,7 @@ namespace tao::pq
void prepare( const std::string& name, const std::string& statement );
void deallocate( const std::string_view name );

template< typename... As >
template< parameter_type... As >
auto execute( const internal::zsv statement, As&&... as )
{
return direct()->execute( statement, std::forward< As >( as )... );
Expand Down
3 changes: 2 additions & 1 deletion include/tao/pq/connection_pool.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
#include <tao/pq/internal/poll.hpp>
#include <tao/pq/internal/pool.hpp>
#include <tao/pq/internal/zsv.hpp>
#include <tao/pq/parameter.hpp>
#include <tao/pq/poll.hpp>
#include <tao/pq/result.hpp>

Expand Down Expand Up @@ -69,7 +70,7 @@ namespace tao::pq

[[nodiscard]] auto connection() -> std::shared_ptr< connection >;

template< typename... As >
template< parameter_type... As >
auto execute( const internal::zsv statement, As&&... as )
{
return connection()->direct()->execute( statement, std::forward< As >( as )... );
Expand Down
58 changes: 32 additions & 26 deletions include/tao/pq/parameter.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,34 @@ namespace tao::pq
class transaction;

template< std::size_t Max = 16 >
class parameter;

namespace internal
{
template< typename A >
inline constexpr bool is_parameter = false;

template< std::size_t Max >
inline constexpr bool is_parameter< parameter< Max > > = true;

template< typename... As >
inline constexpr bool contains_parameter = ( is_parameter< std::decay_t< As > > || ... );

template< typename... As >
inline constexpr std::size_t parameter_size = ( parameter_size< std::decay_t< As > > + ... + 0 );

template< typename A >
inline constexpr std::size_t parameter_size< A > = parameter_traits< A >::columns;

template< std::size_t Max >
inline constexpr std::size_t parameter_size< parameter< Max > > = Max;

} // namespace internal

template< typename T >
concept parameter_type = parameter_type_direct< T > || internal::is_parameter< std::decay_t< T > >;

template< std::size_t Max >
class parameter
{
private:
Expand Down Expand Up @@ -80,7 +108,7 @@ namespace tao::pq
( ( m_formats[ m_size + Is ] = t.template format< Is >() ), ... );
}

template< typename A >
template< parameter_type_direct A >
void bind_impl( A&& a )
{
using D = std::decay_t< A&& >;
Expand Down Expand Up @@ -128,7 +156,7 @@ namespace tao::pq
void bind_impl( parameter< N >&& p ) = delete; // NOLINT(modernize-use-equals-delete)

public:
template< typename... As >
template< parameter_type... As >
explicit parameter( As&&... as ) noexcept( noexcept( std::declval< parameter >().bind( std::forward< As >( as )... ) ) )
{
parameter::bind( std::forward< As >( as )... );
Expand Down Expand Up @@ -158,13 +186,13 @@ namespace tao::pq
void operator=( const parameter& ) = delete;
void operator=( parameter&& ) = delete;

template< typename... As >
template< parameter_type... As >
void bind( As&&... as ) noexcept( sizeof...( As ) == 0 )
{
( parameter::bind_impl( std::forward< As >( as ) ), ... );
}

template< typename... As >
template< parameter_type... As >
void reset( As&&... as ) noexcept( noexcept( std::declval< parameter >().bind( std::forward< As >( as )... ) ) )
{
for( std::size_t i = 0; i != m_pos; ++i ) {
Expand All @@ -176,28 +204,6 @@ namespace tao::pq
}
};

namespace internal
{
template< typename A >
inline constexpr bool is_parameter = false;

template< std::size_t Max >
inline constexpr bool is_parameter< parameter< Max > > = true;

template< typename... As >
inline constexpr bool contains_parameter = ( is_parameter< std::decay_t< As > > || ... );

template< typename... As >
inline constexpr std::size_t parameter_size = ( parameter_size< std::decay_t< As > > + ... + 0 );

template< typename A >
inline constexpr std::size_t parameter_size< A > = parameter_traits< A >::columns;

template< std::size_t Max >
inline constexpr std::size_t parameter_size< parameter< Max > > = Max;

} // namespace internal

} // namespace tao::pq

#endif
40 changes: 12 additions & 28 deletions include/tao/pq/parameter_traits.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,12 @@
#include <span>
#include <string>
#include <string_view>
#include <type_traits>
#include <utility>
#include <vector>

#include <tao/pq/binary.hpp>
#include <tao/pq/bind.hpp>
#include <tao/pq/internal/dependent_false.hpp>
#include <tao/pq/internal/parameter_traits_helper.hpp>
#include <tao/pq/internal/resize_uninitialized.hpp>
#include <tao/pq/null.hpp>
Expand Down Expand Up @@ -64,34 +64,18 @@ namespace tao::pq
} // namespace internal

template< typename T >
struct parameter_traits
{
static_assert( internal::dependent_false< T >, "data type T not registered as taopq parameter type" );

explicit parameter_traits( const T& /*unused*/ ) noexcept;

static constexpr std::size_t columns = 1;
static constexpr bool self_contained = true;

template< std::size_t I >
[[nodiscard]] static auto type() noexcept -> oid;

template< std::size_t I >
[[nodiscard]] static auto value() noexcept -> const char*;
struct parameter_traits;

template< std::size_t I >
[[nodiscard]] static auto length() noexcept -> int;

template< std::size_t I >
[[nodiscard]] static auto format() noexcept -> int;

// for arrays
template< std::size_t I >
static void element( std::string& data );

// for table_writer
template< std::size_t I >
static void copy_to( std::string& data );
template< typename T >
concept parameter_type_direct = requires( const parameter_traits< std::decay_t< T > >& t, std::string& s ) {
{ parameter_traits< std::decay_t< T > >::columns } -> std::same_as< const std::size_t& >;
{ parameter_traits< std::decay_t< T > >::self_contained } -> std::same_as< const bool& >;
{ t.template type< 0 >() } -> std::same_as< oid >;
{ t.template value< 0 >() } -> std::same_as< const char* >;
{ t.template length< 0 >() } -> std::same_as< int >;
{ t.template format< 0 >() } -> std::same_as< int >;
// TODO: { t.template element< 0 >( s ) } -> std::same_as< void >;
{ t.template copy_to< 0 >( s ) } -> std::same_as< void >;
};

template<>
Expand Down
3 changes: 2 additions & 1 deletion include/tao/pq/table_writer.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@

#include <tao/pq/internal/gen.hpp>
#include <tao/pq/internal/zsv.hpp>
#include <tao/pq/parameter.hpp>
#include <tao/pq/parameter_traits.hpp>
#include <tao/pq/transaction.hpp>

Expand Down Expand Up @@ -91,7 +92,7 @@ namespace tao::pq

void insert_raw( const std::string_view data );

template< typename... As >
template< parameter_type... As >
void insert( As&&... as )
{
static_assert( sizeof...( As ) >= 1, "calling tao::pq::table_writer::insert() requires at least one argument" );
Expand Down
4 changes: 2 additions & 2 deletions include/tao/pq/transaction.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,7 @@ namespace tao::pq

[[nodiscard]] auto subtransaction() -> std::shared_ptr< transaction >;

template< typename... As >
template< parameter_type... As >
void send( const internal::zsv statement, As&&... as )
{
if constexpr( sizeof...( As ) == 0 ) {
Expand All @@ -148,7 +148,7 @@ namespace tao::pq

[[nodiscard]] auto get_result( const std::chrono::steady_clock::time_point start = std::chrono::steady_clock::now() ) -> result;

template< typename... As >
template< parameter_type... As >
auto execute( const internal::zsv statement, As&&... as )
{
const auto start = std::chrono::steady_clock::now();
Expand Down
6 changes: 6 additions & 0 deletions src/test/pq/connection.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,9 @@ namespace
// identifier, so you can always make sure that they can not be confused.
connection->execute( "drop_table" );

// statements must consume all parameters
TEST_THROWS( connection->execute( "drop_table", 42 ) );

// a statement which is not a query does not return "affected rows"
TEST_THROWS( connection->execute( "drop_table" ).rows_affected() );

Expand Down Expand Up @@ -126,6 +129,9 @@ namespace
// read data
TEST_ASSERT( connection->execute( "SELECT b FROM tao_connection_test WHERE a = 1" )[ 0 ][ 0 ].get() == std::string( "42" ) );

TEST_THROWS( connection->execute( "SELECT $1" ) );
TEST_THROWS( connection->execute( "SELECT $1", "One", "Two" ) );

TEST_THROWS( connection->execute( "SELECT $1", "" ).as< tao::pq::binary >() );
TEST_THROWS( connection->execute( "SELECT $1", "\\" ).as< tao::pq::binary >() );
TEST_THROWS( connection->execute( "SELECT $1", "\\xa" ).as< tao::pq::binary >() );
Expand Down

0 comments on commit 0272203

Please sign in to comment.