0
0
mirror of https://github.com/rbock/sqlpp11.git synced 2024-11-16 12:51:13 +08:00

Add more tests

This commit is contained in:
Roland Bock 2024-07-30 21:39:59 +02:00
parent 68a3265fdc
commit 98a4ff9cb2
6 changed files with 392 additions and 14 deletions

View File

@ -52,10 +52,11 @@ namespace sqlpp
template <typename L, typename Operator, typename R> template <typename L, typename Operator, typename R>
struct value_type_of<bit_expression<L, Operator, R>> struct value_type_of<bit_expression<L, Operator, R>>
: std::conditional<sqlpp::is_optional<value_type_of_t<L>>::value or sqlpp::is_optional<value_type_of_t<R>>::value,
force_optional_t<value_type_of_t<L>>,
value_type_of_t<L>>
{ {
using type = typename std::conditional<sqlpp::is_optional<value_type_of_t<L>>::value or
sqlpp::is_optional<value_type_of_t<R>>::value,
::sqlpp::optional<integral>,
integral>::type;
}; };
template <typename L, typename Operator, typename R> template <typename L, typename Operator, typename R>
@ -65,7 +66,10 @@ namespace sqlpp
}; };
template <typename L, typename R> template <typename L, typename R>
using check_bit_expression_args = ::sqlpp::enable_if_t<is_integral<L>::value and (is_integral<R>::value or is_unsigned_integral<R>::value)>; using check_bit_expression_args = ::sqlpp::enable_if_t<is_integral<L>::value and is_integral<R>::value>;
template <typename L, typename R>
using check_bit_shift_expression_args = ::sqlpp::enable_if_t<is_integral<L>::value and (is_integral<R>::value or is_unsigned_integral<R>::value)>;
#if 0 #if 0
template <typename L, typename Operator, typename R> template <typename L, typename Operator, typename R>
@ -150,7 +154,7 @@ namespace sqlpp
static constexpr auto symbol = " << "; static constexpr auto symbol = " << ";
}; };
template <typename L, typename R, typename = check_bit_expression_args<L, R>> template <typename L, typename R, typename = check_bit_shift_expression_args<L, R>>
constexpr auto operator<<(L l, R r) -> bit_expression<L, bit_shift_left, R> constexpr auto operator<<(L l, R r) -> bit_expression<L, bit_shift_left, R>
{ {
return {std::move(l), std::move(r)}; return {std::move(l), std::move(r)};
@ -161,7 +165,7 @@ namespace sqlpp
static constexpr auto symbol = " >> "; static constexpr auto symbol = " >> ";
}; };
template <typename L, typename R, typename = check_bit_expression_args<L, R>> template <typename L, typename R, typename = check_bit_shift_expression_args<L, R>>
constexpr auto operator>>(L l, R r) -> bit_expression<L, bit_shift_right, R> constexpr auto operator>>(L l, R r) -> bit_expression<L, bit_shift_right, R>
{ {
return {std::move(l), std::move(r)}; return {std::move(l), std::move(r)};

View File

@ -56,7 +56,6 @@ namespace sqlpp
struct case_t : public enable_as<case_t<When, Then, Else>>, public enable_comparison<case_t<When, Then, Else>> struct case_t : public enable_as<case_t<When, Then, Else>>, public enable_comparison<case_t<When, Then, Else>>
{ {
using _traits = make_traits<value_type_of_t<Then>, tag::is_expression>; using _traits = make_traits<value_type_of_t<Then>, tag::is_expression>;
using _nodes = detail::type_vector<When, Then, Else>;
case_t(When when, Then then, Else else_) : _when(when), _then(then), _else(else_) case_t(When when, Then then, Else else_) : _when(when), _then(then), _else(else_)
{ {
@ -74,13 +73,18 @@ namespace sqlpp
}; };
template <typename When, typename Then, typename Else> template <typename When, typename Then, typename Else>
struct value_type_of<case_t<When, Then, Else>> struct nodes_of<case_t<When, Then, Else>>
{ {
using type = using type = ::sqlpp::detail::type_vector<When, Then, Else>;
typename std::conditional<can_be_null<When>::value or can_be_null<Then>::value or can_be_null<Else>::value, };
force_optional_t<value_type_of_t<Then>>,
value_type_of_t<Then>>::type; template <typename When, typename Then, typename Else>
}; struct value_type_of<case_t<When, Then, Else>>
: public std::conditional<can_be_null<When>::value or can_be_null<Then>::value or can_be_null<Else>::value,
force_optional_t<value_type_of_t<Then>>,
value_type_of_t<Then>>
{
};
template <typename When, typename Then> template <typename When, typename Then>
class case_then_t class case_then_t

View File

@ -38,6 +38,9 @@ test_compile(any)
test_compile(arithmetic_expression) test_compile(arithmetic_expression)
test_compile(as_expression) test_compile(as_expression)
test_compile(assign_expression) test_compile(assign_expression)
test_compile(between_expression)
test_compile(bit_expression)
test_compile(case_expression)
test_compile(comparison_expression) test_compile(comparison_expression)
test_compile(in_expression) test_compile(in_expression)
test_compile(logical_expression) test_compile(logical_expression)

View File

@ -0,0 +1,112 @@
/*
* Copyright (c) 2024, Roland Bock
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
* OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "MockDb.h"
#include "Sample.h"
#include <sqlpp11/sqlpp11.h>
namespace
{
auto db = MockDb{};
template <typename T>
using is_bool = std::is_same<sqlpp::value_type_of_t<T>, sqlpp::boolean>;
template <typename T>
using is_maybe_bool = std::is_same<sqlpp::value_type_of_t<T>, ::sqlpp::optional<sqlpp::boolean>>;
}
template <typename Value>
void test_between_expression(Value v)
{
auto v_not_null = sqlpp::value(v);
auto v_maybe_null = sqlpp::value(::sqlpp::make_optional(v));
// Variations of nullable and non-nullable values
static_assert(is_bool<decltype(between(v_not_null, v_not_null, v_not_null))>::value, "");
static_assert(is_maybe_bool<decltype(between(v_not_null, v_not_null, v_maybe_null))>::value, "");
static_assert(is_maybe_bool<decltype(between(v_not_null, v_maybe_null, v_not_null))>::value, "");
static_assert(is_maybe_bool<decltype(between(v_not_null, v_maybe_null, v_maybe_null))>::value, "");
static_assert(is_maybe_bool<decltype(between(v_maybe_null, v_not_null, v_not_null))>::value, "");
static_assert(is_maybe_bool<decltype(between(v_maybe_null, v_not_null, v_maybe_null))>::value, "");
static_assert(is_maybe_bool<decltype(between(v_maybe_null, v_maybe_null, v_not_null))>::value, "");
static_assert(is_maybe_bool<decltype(between(v_maybe_null, v_maybe_null, v_maybe_null))>::value, "");
// Between expressions have the `as` member function.
static_assert(sqlpp::has_enabled_as<decltype(between(v_not_null, v_not_null, v_not_null))>::value, "");
// Between expressions do not enable comparison member functions.
static_assert(not sqlpp::has_enabled_comparison<decltype(between(v_not_null, v_not_null, v_not_null))>::value, "");
// Between expressions have their arguments as nodes.
using L = typename std::decay<decltype(v_not_null)>::type;
using M = Value;
using R = typename std::decay<decltype(v_maybe_null)>::type;
static_assert(std::is_same<sqlpp::nodes_of_t<decltype(between(v_not_null, v, v_maybe_null))>, sqlpp::detail::type_vector<L, M, R>>::value, "");
}
int main()
{
// boolean
test_between_expression(bool{true});
// integral
test_between_expression(int8_t{7});
test_between_expression(int16_t{7});
test_between_expression(int32_t{7});
test_between_expression(int64_t{7});
// unsigned integral
test_between_expression(uint8_t{7});
test_between_expression(uint16_t{7});
test_between_expression(uint32_t{7});
test_between_expression(uint64_t{7});
// floating point
test_between_expression(float{7.7});
test_between_expression(double{7.7});
// text
test_between_expression('7');
test_between_expression("seven");
test_between_expression(std::string("seven"));
test_between_expression(::sqlpp::string_view("seven"));
// blob
test_between_expression(std::vector<uint8_t>{});
// date
test_between_expression(::sqlpp::chrono::day_point{});
// timestamp
test_between_expression(::sqlpp::chrono::microsecond_point{});
using minute_point = std::chrono::time_point<std::chrono::system_clock, std::chrono::minutes>;
test_between_expression(minute_point{});
// time_of_day
test_between_expression(std::chrono::microseconds{});
}

View File

@ -0,0 +1,144 @@
/*
* Copyright (c) 2024, Roland Bock
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
* OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "MockDb.h"
#include "Sample.h"
#include <sqlpp11/sqlpp11.h>
namespace
{
auto db = MockDb{};
template <typename T>
using is_integral = std::is_same<sqlpp::value_type_of_t<T>, sqlpp::integral>;
template <typename T>
using is_maybe_integral = std::is_same<sqlpp::value_type_of_t<T>, ::sqlpp::optional<sqlpp::integral>>;
}
template <typename Value>
void test_bit_expression(Value v)
{
auto v_not_null = sqlpp::value(v);
auto v_maybe_null = sqlpp::value(::sqlpp::make_optional(v));
// Compare non-nullable with non-nullable.
static_assert(is_integral<decltype(v_not_null << v_not_null)>::value, "");
static_assert(is_integral<decltype(v_not_null >> v_not_null)>::value, "");
static_assert(is_integral<decltype(v_not_null | v_not_null)>::value, "");
static_assert(is_integral<decltype(v_not_null & v_not_null)>::value, "");
static_assert(is_integral<decltype(v_not_null ^ v_not_null)>::value, "");
// Compare non-nullable with nullable.
static_assert(is_maybe_integral<decltype(v_not_null << v_maybe_null)>::value, "");
static_assert(is_maybe_integral<decltype(v_not_null >> v_maybe_null)>::value, "");
static_assert(is_maybe_integral<decltype(v_not_null | v_maybe_null)>::value, "");
static_assert(is_maybe_integral<decltype(v_not_null & v_maybe_null)>::value, "");
static_assert(is_maybe_integral<decltype(v_not_null ^ v_maybe_null)>::value, "");
// Compare nullable with non-nullable.
static_assert(is_maybe_integral<decltype(v_maybe_null << v_not_null)>::value, "");
static_assert(is_maybe_integral<decltype(v_maybe_null >> v_not_null)>::value, "");
static_assert(is_maybe_integral<decltype(v_maybe_null | v_not_null)>::value, "");
static_assert(is_maybe_integral<decltype(v_maybe_null & v_not_null)>::value, "");
static_assert(is_maybe_integral<decltype(v_maybe_null ^ v_not_null)>::value, "");
// Compare nullable with nullable.
static_assert(is_maybe_integral<decltype(v_maybe_null << v_maybe_null)>::value, "");
static_assert(is_maybe_integral<decltype(v_maybe_null >> v_maybe_null)>::value, "");
static_assert(is_maybe_integral<decltype(v_maybe_null | v_maybe_null)>::value, "");
static_assert(is_maybe_integral<decltype(v_maybe_null & v_maybe_null)>::value, "");
static_assert(is_maybe_integral<decltype(v_maybe_null ^ v_maybe_null)>::value, "");
// Compare with null.
static_assert(is_integral<decltype(~v_not_null)>::value, "");
static_assert(is_maybe_integral<decltype(~v_maybe_null)>::value, "");
// Comparison expressions have the `as` member function.
static_assert(sqlpp::has_enabled_as<decltype(v_not_null << v_maybe_null)>::value, "");
static_assert(sqlpp::has_enabled_as<decltype(~v_not_null)>::value, "");
// Comparison expressions do not enable comparison member functions.
static_assert(not sqlpp::has_enabled_comparison<decltype(v_not_null << v_maybe_null)>::value, "");
// Comparison expressions have their arguments as nodes.
using L = typename std::decay<decltype(v_not_null)>::type;
using R = typename std::decay<decltype(v_maybe_null)>::type;
static_assert(std::is_same<sqlpp::nodes_of_t<decltype(v_not_null << v_maybe_null)>, sqlpp::detail::type_vector<L, R>>::value, "");
static_assert(std::is_same<sqlpp::nodes_of_t<decltype(~v_not_null)>, sqlpp::detail::type_vector<sqlpp::noop, L>>::value, "");
}
template <typename Left, typename Right>
void test_bit_shift_expression(Left l, Right r)
{
auto l_not_null = sqlpp::value(l);
auto l_maybe_null = sqlpp::value(::sqlpp::make_optional(l));
auto r_not_null = sqlpp::value(r);
auto r_maybe_null = sqlpp::value(::sqlpp::make_optional(r));
// Compare non-nullable with non-nullable.
static_assert(is_integral<decltype(l_not_null << r_not_null)>::value, "");
static_assert(is_integral<decltype(l_not_null >> r_not_null)>::value, "");
// Compare non-nullable with nullable.
static_assert(is_maybe_integral<decltype(l_not_null << r_maybe_null)>::value, "");
static_assert(is_maybe_integral<decltype(l_not_null >> r_maybe_null)>::value, "");
// Compare nullable with non-nullable.
static_assert(is_maybe_integral<decltype(l_maybe_null << r_not_null)>::value, "");
static_assert(is_maybe_integral<decltype(l_maybe_null >> r_not_null)>::value, "");
// Compare nullable with nullable.
static_assert(is_maybe_integral<decltype(l_maybe_null << r_maybe_null)>::value, "");
static_assert(is_maybe_integral<decltype(l_maybe_null >> r_maybe_null)>::value, "");
// Comparison expressions have the `as` member function.
static_assert(sqlpp::has_enabled_as<decltype(l_not_null << r_maybe_null)>::value, "");
// Comparison expressions do not enable comparison member functions.
static_assert(not sqlpp::has_enabled_comparison<decltype(l_not_null << r_maybe_null)>::value, "");
// Comparison expressions have their arguments as nodes.
using L = typename std::decay<decltype(l_not_null)>::type;
using R = typename std::decay<decltype(r_maybe_null)>::type;
static_assert(std::is_same<sqlpp::nodes_of_t<decltype(l_not_null << r_maybe_null)>, sqlpp::detail::type_vector<L, R>>::value, "");
}
int main()
{
// bit expression require integral operands
test_bit_expression(int8_t{7});
test_bit_expression(int16_t{7});
test_bit_expression(int32_t{7});
test_bit_expression(int64_t{7});
// bit shift operations can have unsigned rhs operands
test_bit_shift_expression(int8_t{7}, uint8_t{7});
test_bit_shift_expression(int8_t{7}, uint16_t{7});
test_bit_shift_expression(int8_t{7}, uint32_t{7});
test_bit_shift_expression(int8_t{7}, uint64_t{7});
}

View File

@ -0,0 +1,111 @@
/*
* Copyright (c) 2024, Roland Bock
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
* OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <sqlpp11/sqlpp11.h>
template<typename T, typename Value>
using is_same_type = std::is_same<sqlpp::value_type_of_t<T>, sqlpp::value_type_of_t<Value>>;
template <typename Value>
void test_case_expression(Value v)
{
auto c_not_null = sqlpp::value(true);
auto c_maybe_null = sqlpp::value(::sqlpp::make_optional(false));
auto v_not_null = sqlpp::value(v);
auto v_maybe_null = sqlpp::value(::sqlpp::make_optional(v));
using ValueType = sqlpp::value_type_of_t<decltype(v_not_null)>;
using OptValueType = sqlpp::value_type_of_t<decltype(v_maybe_null)>;
// Variations of nullable and non-nullable values
static_assert(is_same_type<decltype(case_when(c_not_null).then(v_not_null).else_(v_not_null)), ValueType>::value, "");
static_assert(is_same_type<decltype(case_when(c_not_null).then(v_not_null).else_(v_maybe_null)), OptValueType>::value, "");
static_assert(is_same_type<decltype(case_when(c_not_null).then(v_maybe_null).else_(v_not_null)), OptValueType>::value, "");
static_assert(is_same_type<decltype(case_when(c_not_null).then(v_maybe_null).else_(v_maybe_null)), OptValueType>::value, "");
static_assert(is_same_type<decltype(case_when(c_maybe_null).then(v_not_null).else_(v_not_null)), OptValueType>::value, "");
static_assert(is_same_type<decltype(case_when(c_maybe_null).then(v_not_null).else_(v_maybe_null)), OptValueType>::value, "");
static_assert(is_same_type<decltype(case_when(c_maybe_null).then(v_maybe_null).else_(v_not_null)), OptValueType>::value, "");
static_assert(is_same_type<decltype(case_when(c_maybe_null).then(v_maybe_null).else_(v_maybe_null)), OptValueType>::value, "");
// Incomplete case expressions have no value.
static_assert(not sqlpp::has_value_type<decltype(case_when(c_not_null))>::value, "");
static_assert(not sqlpp::has_value_type<decltype(case_when(c_not_null).then(v_not_null))>::value, "");
// Case expressions have the `as` member function.
static_assert(sqlpp::has_enabled_as<decltype(case_when(c_not_null).then(v_not_null).else_(v_not_null))>::value, "");
// Case expressions enable comparison member functions.
static_assert(sqlpp::has_enabled_comparison<decltype(case_when(c_not_null).then(v_not_null).else_(v_not_null))>::value, "");
// Between expressions have their arguments as nodes.
using L = typename std::decay<decltype(c_not_null)>::type;
using M = typename std::decay<decltype(v_not_null)>::type;
using R = typename std::decay<decltype(v_maybe_null)>::type;
static_assert(std::is_same<sqlpp::nodes_of_t<decltype(case_when(c_not_null).then(v_not_null).else_(v_maybe_null))>, sqlpp::detail::type_vector<L, M, R>>::value, "");
}
int main()
{
// boolean
test_case_expression(bool{true});
// integral
test_case_expression(int8_t{7});
test_case_expression(int16_t{7});
test_case_expression(int32_t{7});
test_case_expression(int64_t{7});
// unsigned integral
test_case_expression(uint8_t{7});
test_case_expression(uint16_t{7});
test_case_expression(uint32_t{7});
test_case_expression(uint64_t{7});
// floating point
test_case_expression(float{7.7});
test_case_expression(double{7.7});
// text
test_case_expression('7');
test_case_expression("seven");
test_case_expression(std::string("seven"));
test_case_expression(::sqlpp::string_view("seven"));
// blob
test_case_expression(std::vector<uint8_t>{});
// date
test_case_expression(::sqlpp::chrono::day_point{});
// timestamp
test_case_expression(::sqlpp::chrono::microsecond_point{});
using minute_point = std::chrono::time_point<std::chrono::system_clock, std::chrono::minutes>;
test_case_expression(minute_point{});
// time_of_day
test_case_expression(std::chrono::microseconds{});
}