diff --git a/include/tao/pq/parameter.hpp b/include/tao/pq/parameter.hpp index 9bd9aee..1e47446 100644 --- a/include/tao/pq/parameter.hpp +++ b/include/tao/pq/parameter.hpp @@ -65,6 +65,9 @@ namespace tao::pq int m_lengths[ Max ]; int m_formats[ Max ]; + template< std::size_t > + friend class parameter; + friend class transaction; template< typename T, std::size_t... Is > @@ -132,9 +135,16 @@ namespace tao::pq ~parameter() { +#if defined( __GNUC__ ) && !defined( __clang__ ) +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wmaybe-uninitialized" +#endif for( std::size_t i = 0; i != m_pos; ++i ) { delete m_params[ i ]; } +#if defined( __GNUC__ ) && !defined( __clang__ ) +#pragma GCC diagnostic pop +#endif } explicit parameter( const parameter& p ) @@ -165,6 +175,28 @@ namespace tao::pq } }; + namespace internal + { + template< typename A > + inline constexpr bool contains_parameter_impl = false; + + template< std::size_t Max > + inline constexpr bool contains_parameter_impl< parameter< Max > > = true; + + template< typename... As > + inline constexpr bool contains_parameter = ( contains_parameter_impl< std::decay_t< As > > || ... ); + + template< typename A > + inline constexpr std::size_t parameter_size_impl = parameter_traits< A >::columns; + + template< std::size_t Max > + inline constexpr std::size_t parameter_size_impl< parameter< Max > > = Max; + + template< typename... As > + inline constexpr std::size_t parameter_size = ( parameter_size_impl< std::decay_t< As > > + ... + 0 ); + + } // namespace internal + } // namespace tao::pq #endif diff --git a/include/tao/pq/transaction.hpp b/include/tao/pq/transaction.hpp index 1f736a1..3be0ad4 100644 --- a/include/tao/pq/transaction.hpp +++ b/include/tao/pq/transaction.hpp @@ -100,29 +100,20 @@ namespace tao::pq if constexpr( sizeof...( As ) == 0 ) { send_params( statement, 0, nullptr, nullptr, nullptr, nullptr ); } + else if constexpr( internal::contains_parameter< As... > ) { + if constexpr( sizeof...( As ) == 1 ) { + ( send_params( statement, as.m_size, as.m_types, as.m_values, as.m_lengths, as.m_formats ), ... ); + } + else { + const parameter< internal::parameter_size< As... > > p( std::forward< As >( as )... ); + send_params( statement, p.m_size, p.m_types, p.m_values, p.m_lengths, p.m_formats ); + } + } else { send_traits( statement, parameter_traits< std::decay_t< As > >( std::forward< As >( as ) )... ); } } - template< std::size_t Max > - void send( const internal::zsv statement, const parameter< Max >& as ) - { - send_params( statement, as.m_size, as.m_types, as.m_values, as.m_lengths, as.m_formats ); - } - - template< std::size_t Max > - void send( const internal::zsv statement, parameter< Max >& as ) - { - send( statement, const_cast< const parameter< Max >& >( as ) ); - } - - template< std::size_t Max > - void send( const internal::zsv statement, parameter< Max >&& as ) - { - send( statement, const_cast< const parameter< Max >& >( as ) ); - } - [[nodiscard]] auto get_result( const std::chrono::steady_clock::time_point start = std::chrono::steady_clock::now() ) -> result; template< typename... As > diff --git a/src/test/pq/parameter.cpp b/src/test/pq/parameter.cpp index bd6dd80..9aaf952 100644 --- a/src/test/pq/parameter.cpp +++ b/src/test/pq/parameter.cpp @@ -48,6 +48,13 @@ void run() tr->execute( "insert_user", p2 ); } + { + tao::pq::parameter< 1 > p; + std::string s = "Alice"; + p.bind( std::move( s ) ); + tr->execute( "insert_user", p, 44 ); + } + // commit transaction tr->commit(); }