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

Added more tests and cleaned up type traits a bit

This commit is contained in:
Roland Bock 2024-07-13 21:04:06 +02:00
parent c2c5f15690
commit 87f4c348e9
11 changed files with 760 additions and 377 deletions

View File

@ -34,32 +34,8 @@
namespace sqlpp namespace sqlpp
{ {
struct count_alias_t
{
struct _alias_t
{
static constexpr const char _literal[] = "count_";
using _name_t = sqlpp::make_char_sequence<sizeof(_literal), _literal>;
template <typename T>
struct _member_t
{
T count;
T& operator()()
{
return count;
}
const T& operator()() const
{
return count;
}
};
};
};
template <typename Flag, typename Expr> template <typename Flag, typename Expr>
struct count_t : public expression_operators<count_t<Flag, Expr>, integral>, struct count_t
public aggregate_function_operators<count_t<Flag, Expr>>,
public alias_operators<count_t<Flag, Expr>>
{ {
using _traits = make_traits<integral, tag::is_expression /*, tag::is_selectable*/>; using _traits = make_traits<integral, tag::is_expression /*, tag::is_selectable*/>;
@ -67,11 +43,6 @@ namespace sqlpp
using _can_be_null = std::false_type; using _can_be_null = std::false_type;
using _is_aggregate_expression = std::true_type; using _is_aggregate_expression = std::true_type;
static_assert(is_noop<Flag>::value or std::is_same<distinct_t, Flag>::value,
"count() used with flag other than 'distinct'");
using _auto_alias_t = count_alias_t;
count_t(const Expr expr) : _expr(expr) count_t(const Expr expr) : _expr(expr)
{ {
} }
@ -85,6 +56,12 @@ namespace sqlpp
Expr _expr; Expr _expr;
}; };
template <typename Flag, typename Expr>
struct value_type_of<count_t<Flag, Expr>>
{
using type = integral;
};
template <typename Context, typename Flag, typename Expr> template <typename Context, typename Flag, typename Expr>
Context& serialize(const count_t<Flag, Expr>& t, Context& context) Context& serialize(const count_t<Flag, Expr>& t, Context& context)
{ {
@ -100,20 +77,19 @@ namespace sqlpp
} }
template <typename T> template <typename T>
auto count(T t) -> count_t<noop, wrap_operand_t<T>> using check_count_arg =
std::enable_if_t<values_are_comparable<T, T>::value and not contains_aggregate_function_t<T>::value>;
template <typename T, typename = check_count_arg<T>>
auto count(T t) -> count_t<noop, T>
{ {
static_assert(not contains_aggregate_function_t<wrap_operand_t<T>>::value, return {std::move(t)};
"count() cannot be used on an aggregate function");
static_assert(is_expression_t<wrap_operand_t<T>>::value, "count() requires an expression as argument");
return {t};
} }
template <typename T> template <typename T, typename = check_count_arg<T>>
auto count(const distinct_t& /*unused*/, T t) -> count_t<distinct_t, wrap_operand_t<T>> auto count(const distinct_t& /*unused*/, T t) -> count_t<distinct_t, T>
{ {
static_assert(not contains_aggregate_function_t<wrap_operand_t<T>>::value, return {std::move(t)};
"count() cannot be used on an aggregate function");
static_assert(is_expression_t<wrap_operand_t<T>>::value, "count() requires an expression as argument");
return {t};
} }
} // namespace sqlpp } // namespace sqlpp

View File

@ -31,40 +31,14 @@
namespace sqlpp namespace sqlpp
{ {
struct min_alias_t
{
struct _alias_t
{
static constexpr const char _literal[] = "min_";
using _name_t = sqlpp::make_char_sequence<sizeof(_literal), _literal>;
template <typename T>
struct _member_t
{
T min;
T& operator()()
{
return min;
}
const T& operator()() const
{
return min;
}
};
};
};
template <typename Flag, typename Expr> template <typename Flag, typename Expr>
struct min_t : public expression_operators<min_t<Flag, Expr>, value_type_of_t<Expr>>, struct min_t
public aggregate_function_operators<min_t<Flag, Expr>>,
public alias_operators<min_t<Flag, Expr>>
{ {
using _traits = make_traits<value_type_of_t<Expr>, tag::is_expression, tag::is_selectable>; using _traits = make_traits<value_type_of_t<Expr>, tag::is_expression, tag::is_selectable>;
using _nodes = detail::type_vector<Expr, aggregate_function>; using _nodes = detail::type_vector<Expr, aggregate_function>;
using _can_be_null = std::true_type; using _can_be_null = std::true_type;
using _is_aggregate_expression = std::true_type; using _is_aggregate_expression = std::true_type;
using _auto_alias_t = min_alias_t;
min_t(Expr expr) : _expr(expr) min_t(Expr expr) : _expr(expr)
{ {
} }
@ -78,6 +52,12 @@ namespace sqlpp
Expr _expr; Expr _expr;
}; };
template <typename Flag, typename Expr>
struct value_type_of<min_t<Flag, Expr>>
{
using type = sqlpp::force_optional_t<value_type_of_t<Expr>>;
};
template <typename Context, typename Flag, typename Expr> template <typename Context, typename Flag, typename Expr>
Context& serialize(const min_t<Flag, Expr>& t, Context& context) Context& serialize(const min_t<Flag, Expr>& t, Context& context)
{ {
@ -93,20 +73,18 @@ namespace sqlpp
} }
template <typename T> template <typename T>
auto min(T t) -> min_t<noop, wrap_operand_t<T>> using check_min_arg =
std::enable_if_t<values_are_comparable<T, T>::value and not contains_aggregate_function_t<T>::value>;
template <typename T, typename = check_min_arg<T>>
auto min(T t) -> min_t<noop, T>
{ {
static_assert(not contains_aggregate_function_t<wrap_operand_t<T>>::value, return {std::move(t)};
"min() cannot be used on an aggregate function");
static_assert(is_expression_t<wrap_operand_t<T>>::value, "min() requires an expression as argument");
return {t};
} }
template <typename T> template <typename T, typename = check_min_arg<T>>
auto min(const distinct_t& /*unused*/, T t) -> min_t<distinct_t, wrap_operand_t<T>> auto min(const distinct_t& /*unused*/, T t) -> min_t<distinct_t, T>
{ {
static_assert(not contains_aggregate_function_t<wrap_operand_t<T>>::value, return {std::move(t)};
"min() cannot be used on an aggregate function");
static_assert(is_expression_t<wrap_operand_t<T>>::value, "min() requires an expression as argument");
return {t};
} }
} // namespace sqlpp } // namespace sqlpp

View File

@ -66,7 +66,7 @@ namespace sqlpp
}; };
template <typename L, typename R> template <typename L, typename R>
using check_arithmetic_args = std::enable_if_t<has_numeric_value<L>::value and has_numeric_value<R>::value>; using check_arithmetic_args = std::enable_if_t<is_numeric<L>::value and is_numeric<R>::value>;
#warning: need to document that this is on purpose (not integral, or unsigned integral, or floating_point) because it is difficult to know for the library to know what the actual result type will be (it is difficult to guess in C++ already, and it is probably different from DB vendor to vendor). #warning: need to document that this is on purpose (not integral, or unsigned integral, or floating_point) because it is difficult to know for the library to know what the actual result type will be (it is difficult to guess in C++ already, and it is probably different from DB vendor to vendor).
template <typename L, typename Operator, typename R> template <typename L, typename Operator, typename R>

View File

@ -127,7 +127,7 @@ namespace sqlpp
template<typename T> template<typename T>
struct value_type_of<sqlpp::compat::optional<T>> struct value_type_of<sqlpp::compat::optional<T>>
{ {
using type = sqlpp::compat::optional<value_type_of_t<remove_optional_t<T>>>; using type = sqlpp::force_optional_t<value_type_of_t<remove_optional_t<T>>>;
}; };
template <typename T> template <typename T>
@ -232,10 +232,23 @@ namespace sqlpp
struct is_unsigned_integral<sqlpp::compat::nullopt_t> : public std::true_type { struct is_unsigned_integral<sqlpp::compat::nullopt_t> : public std::true_type {
}; };
template <typename T>
struct is_floating_point : public std::is_same<remove_optional_t<value_type_of_t<T>>, floating_point>
{
};
template <>
struct is_floating_point<sqlpp::compat::nullopt_t> : public std::true_type {
};
// A generic numeric type which could be (unsigned) integral or floating point. // A generic numeric type which could be (unsigned) integral or floating point.
struct numeric; struct numeric;
template <typename T> template <typename T>
struct is_numeric : public std::integral_constant<bool, is_integral<T>::value or is_unsigned_integral<T>::value or std::is_floating_point<T>::value>{}; struct is_numeric : public std::integral_constant<bool,
is_integral<T>::value or is_unsigned_integral<T>::value or
is_floating_point<T>::value>
{
};
template <> template <>
struct is_numeric<numeric> : public std::true_type{}; struct is_numeric<numeric> : public std::true_type{};
@ -244,125 +257,64 @@ namespace sqlpp
struct is_numeric<sqlpp::compat::nullopt_t> : public std::true_type{}; struct is_numeric<sqlpp::compat::nullopt_t> : public std::true_type{};
template <typename T> template <typename T>
struct has_numeric_value : public std::integral_constant<bool, struct is_text : public std::is_same<remove_optional_t<value_type_of_t<T>>, text>
is_numeric<remove_optional_t<T>>::value or is_numeric<remove_optional_t<value_type_of_t<T>>>::value>{};
struct text;
template <typename T>
struct is_text : public std::false_type {};
template <>
struct is_text<text> : public std::true_type {};
template <>
struct is_text<char> : public std::true_type {};
template <>
struct is_text<const char*> : public std::true_type {};
template <>
struct is_text<std::string> : public std::true_type {};
template <>
struct is_text<sqlpp::compat::string_view> : public std::true_type {};
template <>
struct is_text<sqlpp::compat::nullopt_t> : public std::true_type {};
template <typename T>
struct has_text_value : public std::integral_constant<bool,
is_text<remove_optional_t<T>>::value or
is_text<remove_optional_t<value_type_of_t<T>>>::value>{};
struct blob;
template <typename T>
struct is_blob : public std::false_type {};
template <>
struct is_blob<blob> : public std::true_type {};
template <>
struct is_blob<std::vector<std::uint8_t>> : public std::true_type {};
template <>
struct is_blob<sqlpp::compat::span<std::uint8_t>> : public std::true_type {};
template <>
struct is_blob<sqlpp::compat::nullopt_t> : public std::true_type {};
template <typename T>
struct has_blob_value : public std::integral_constant<bool,
is_blob<remove_optional_t<T>>::value or
is_blob<remove_optional_t<value_type_of_t<T>>>::value>{};
struct day_point;
template <typename T>
struct is_day_point : public std::false_type {};
template <>
struct is_day_point<day_point> : public std::true_type {};
template <>
struct is_day_point<std::chrono::time_point<std::chrono::system_clock, sqlpp::chrono::days>> : public std::true_type {};
template <>
struct is_day_point<sqlpp::compat::nullopt_t> : public std::true_type {};
template <typename T>
struct has_day_point_value : public std::integral_constant<bool,
is_day_point<remove_optional_t<T>>::value or
is_day_point<remove_optional_t<value_type_of_t<T>>>::value>{};
struct time_of_day;
template <typename T>
struct is_time_of_day : public std::false_type {};
template <>
struct is_time_of_day<time_of_day> : public std::true_type {};
template <typename Rep, typename Period>
struct is_time_of_day<std::chrono::duration<Rep, Period>> : public std::true_type {};
template <>
struct is_time_of_day<sqlpp::compat::nullopt_t> : public std::true_type {};
template <typename T>
struct has_time_of_day_value : public std::integral_constant<bool,
is_time_of_day<remove_optional_t<T>>::value or
is_time_of_day<remove_optional_t<value_type_of_t<T>>>::value>{};
struct time_point;
template <typename T>
struct is_time_point : public std::false_type {};
template <>
struct is_time_point<time_point> : public std::true_type {};
template <typename Period>
struct is_time_point<std::chrono::time_point<std::chrono::system_clock, Period>> : public std::true_type {};
template <>
struct is_time_point<sqlpp::compat::nullopt_t> : public std::true_type {};
template <typename T>
struct has_time_point_value : public std::integral_constant<bool,
is_time_point<remove_optional_t<T>>::value or
is_time_point<remove_optional_t<value_type_of_t<T>>>::value>{};
#warning: Need to add float and unsigned traits?
template <typename L, typename R>
struct values_are_comparable
: public std::integral_constant<bool,
(has_blob_value<L>::value and has_blob_value<R>::value) or
(is_boolean<L>::value and is_boolean<R>::value) or
(has_day_point_value<L>::value and has_day_point_value<R>::value) or
(has_numeric_value<L>::value and has_numeric_value<R>::value) or
(has_text_value<L>::value and has_text_value<R>::value) or
(has_time_of_day_value<L>::value and has_time_of_day_value<R>::value) or
(has_time_point_value<L>::value and has_time_point_value<R>::value)>
{ {
}; };
template <>
struct is_text<sqlpp::compat::nullopt_t> : public std::true_type {
};
template <typename T>
struct is_blob : public std::is_same<remove_optional_t<value_type_of_t<T>>, blob>
{
};
template <>
struct is_blob<sqlpp::compat::nullopt_t> : public std::true_type {
};
template <typename T>
struct is_day_point : public std::is_same<remove_optional_t<value_type_of_t<T>>, day_point>
{
};
template <>
struct is_day_point<sqlpp::compat::nullopt_t> : public std::true_type {
};
template <typename T>
struct is_time_point : public std::is_same<remove_optional_t<value_type_of_t<T>>, time_point>
{
};
template <>
struct is_time_point<sqlpp::compat::nullopt_t> : public std::true_type {
};
template <typename T>
struct is_time_of_day : public std::is_same<remove_optional_t<value_type_of_t<T>>, time_of_day>
{
};
template <>
struct is_time_of_day<sqlpp::compat::nullopt_t> : public std::true_type {
};
template <typename L, typename R>
struct values_are_comparable
: public std::integral_constant<bool,
(is_blob<L>::value and is_blob<R>::value) or
(is_boolean<L>::value and is_boolean<R>::value) or
(is_day_point<L>::value and is_day_point<R>::value) or
(is_numeric<L>::value and is_numeric<R>::value) or
(is_text<L>::value and is_text<R>::value) or
(is_time_of_day<L>::value and is_time_of_day<R>::value) or
(is_time_point<L>::value and is_time_point<R>::value)>
{
};
#warning: These something_t data type classifiers should be removed
// data types // data types
struct blob; struct blob;
template <typename T> template <typename T>
@ -400,7 +352,6 @@ namespace sqlpp
using is_time_point_t = std::is_same<value_type_of_t<T>, time_point>; using is_time_point_t = std::is_same<value_type_of_t<T>, time_point>;
// joined data type // joined data type
#warning: These something_t data type classifiers should be removed
template <typename T> template <typename T>
using is_numeric_t = using is_numeric_t =
logic::any_t<is_integral_t<T>::value, is_unsigned_integral_t<T>::value, is_floating_point_t<T>::value>; logic::any_t<is_integral_t<T>::value, is_unsigned_integral_t<T>::value, is_floating_point_t<T>::value>;

View File

@ -34,4 +34,10 @@ function(test_compile name)
endif() endif()
endfunction() endfunction()
test_compile(aggregate_functions)
test_compile(comparison_expression)
test_compile(in_expression)
test_compile(logical_expression)
test_compile(result_row) test_compile(result_row)
test_compile(value)

View File

@ -0,0 +1,100 @@
/*
* Copyright (c) 2016-2016, 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, typename V>
using is_same_type = std::is_same<sqlpp::value_type_of_t<T>, V>;
}
template <typename Value>
void test_aggregate_functions(Value v)
{
auto v_not_null = sqlpp::value(v);
auto v_maybe_null = sqlpp::value(sqlpp::compat::make_optional(v));
using ValueType = sqlpp::value_type_of_t<Value>;
using OptValueType = sqlpp::value_type_of_t<sqlpp::compat::optional<Value>>;
// Aggregate of non-nullable
static_assert(is_same_type<decltype(count(v_not_null)), sqlpp::integral>::value, "");
static_assert(is_same_type<decltype(max(v_not_null)), OptValueType>::value, "");
static_assert(is_same_type<decltype(min(v_not_null)), OptValueType>::value, "");
// Aggregate of nullable
static_assert(is_same_type<decltype(count(v_not_null)), sqlpp::integral>::value, "");
static_assert(is_same_type<decltype(max(v_maybe_null)), OptValueType>::value, "");
static_assert(is_same_type<decltype(min(v_maybe_null)), OptValueType>::value, "");
}
int main()
{
// boolean
test_aggregate_functions(bool{true});
// integral
test_aggregate_functions(int8_t{7});
test_aggregate_functions(int16_t{7});
test_aggregate_functions(int32_t{7});
test_aggregate_functions(int64_t{7});
// unsigned integral
test_aggregate_functions(uint8_t{7});
test_aggregate_functions(uint16_t{7});
test_aggregate_functions(uint32_t{7});
test_aggregate_functions(uint64_t{7});
// floating point
test_aggregate_functions(float{7.7});
test_aggregate_functions(double{7.7});
// text
test_aggregate_functions('7');
test_aggregate_functions("seven");
test_aggregate_functions(std::string("seven"));
test_aggregate_functions(sqlpp::compat::string_view("seven"));
// blob
test_aggregate_functions(std::vector<uint8_t>{});
// date
test_aggregate_functions(::sqlpp::chrono::day_point{});
// timestamp
test_aggregate_functions(::sqlpp::chrono::microsecond_point{});
using minute_point = std::chrono::time_point<std::chrono::system_clock, std::chrono::minutes>;
test_aggregate_functions(minute_point{});
// time_of_day
test_aggregate_functions(std::chrono::microseconds{});
}

View File

@ -0,0 +1,169 @@
/*
* Copyright (c) 2016-2016, 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::compat::optional<sqlpp::boolean>>;
}
template <typename Value>
void test_comparison_expression(Value v)
{
using OptValue = sqlpp::compat::optional<Value>;
auto v_not_null = sqlpp::value(v);
auto v_maybe_null = sqlpp::value(sqlpp::compat::make_optional(v));
#warning : Should also implement like, is_null, is_distinct_from as member functions.
// Compare non-nullable with non-nullable.
static_assert(is_bool<decltype(v_not_null < v_not_null)>::value, "");
static_assert(is_bool<decltype(v_not_null <= v_not_null)>::value, "");
static_assert(is_bool<decltype(v_not_null == v_not_null)>::value, "");
static_assert(is_bool<decltype(v_not_null != v_not_null)>::value, "");
static_assert(is_bool<decltype(v_not_null == v_not_null)>::value, "");
static_assert(is_bool<decltype(v_not_null >= v_not_null)>::value, "");
static_assert(is_bool<decltype(v_not_null > v_not_null)>::value, "");
static_assert(is_bool<decltype(is_distinct_from(v_not_null, v_not_null))>::value, "");
static_assert(is_bool<decltype(is_not_distinct_from(v_not_null, v_not_null))>::value, "");
// Compare non-nullable with nullable.
static_assert(is_maybe_bool<decltype(v_not_null < v_maybe_null)>::value, "");
static_assert(is_maybe_bool<decltype(v_not_null <= v_maybe_null)>::value, "");
static_assert(is_maybe_bool<decltype(v_not_null == v_maybe_null)>::value, "");
static_assert(is_maybe_bool<decltype(v_not_null != v_maybe_null)>::value, "");
static_assert(is_maybe_bool<decltype(v_not_null == v_maybe_null)>::value, "");
static_assert(is_maybe_bool<decltype(v_not_null >= v_maybe_null)>::value, "");
static_assert(is_maybe_bool<decltype(v_not_null > v_maybe_null)>::value, "");
static_assert(is_bool<decltype(is_distinct_from(v_not_null, v_maybe_null))>::value, "");
static_assert(is_bool<decltype(is_not_distinct_from(v_not_null, v_maybe_null))>::value, "");
// Compare nullable with non-nullable.
static_assert(is_maybe_bool<decltype(v_maybe_null < v_not_null)>::value, "");
static_assert(is_maybe_bool<decltype(v_maybe_null <= v_not_null)>::value, "");
static_assert(is_maybe_bool<decltype(v_maybe_null == v_not_null)>::value, "");
static_assert(is_maybe_bool<decltype(v_maybe_null != v_not_null)>::value, "");
static_assert(is_maybe_bool<decltype(v_maybe_null == v_not_null)>::value, "");
static_assert(is_maybe_bool<decltype(v_maybe_null >= v_not_null)>::value, "");
static_assert(is_maybe_bool<decltype(v_maybe_null > v_not_null)>::value, "");
static_assert(is_bool<decltype(is_distinct_from(v_maybe_null, v_not_null))>::value, "");
static_assert(is_bool<decltype(is_not_distinct_from(v_maybe_null, v_not_null))>::value, "");
// Compare nullable with nullable.
static_assert(is_maybe_bool<decltype(v_maybe_null < v_maybe_null)>::value, "");
static_assert(is_maybe_bool<decltype(v_maybe_null <= v_maybe_null)>::value, "");
static_assert(is_maybe_bool<decltype(v_maybe_null == v_maybe_null)>::value, "");
static_assert(is_maybe_bool<decltype(v_maybe_null != v_maybe_null)>::value, "");
static_assert(is_maybe_bool<decltype(v_maybe_null == v_maybe_null)>::value, "");
static_assert(is_maybe_bool<decltype(v_maybe_null >= v_maybe_null)>::value, "");
static_assert(is_maybe_bool<decltype(v_maybe_null > v_maybe_null)>::value, "");
static_assert(is_bool<decltype(is_distinct_from(v_maybe_null, v_maybe_null))>::value, "");
static_assert(is_bool<decltype(is_not_distinct_from(v_maybe_null, v_maybe_null))>::value, "");
// Compare with null.
static_assert(is_bool<decltype(is_null(v_not_null))>::value, "");
static_assert(is_bool<decltype(is_null(v_maybe_null))>::value, "");
static_assert(is_bool<decltype(is_not_null(v_maybe_null))>::value, "");
static_assert(is_bool<decltype(is_not_null(v_not_null))>::value, "");
}
template<typename Value>
void test_like(Value v)
{
auto v_not_null= sqlpp::value(v);
auto v_maybe_null= sqlpp::value(sqlpp::compat::make_optional(v));
// Compare non-nullable with non-nullable.
static_assert(is_bool<decltype(like(v_not_null, v_not_null))>::value, "");
// Compare non-nullable with nullable.
static_assert(is_maybe_bool<decltype(like(v_not_null, v_maybe_null))>::value, "");
// Compare nullable with non-nullable.
static_assert(is_maybe_bool<decltype(like(v_maybe_null, v_not_null))>::value, "");
// Compare nullable with nullable.
static_assert(is_maybe_bool<decltype(like(v_maybe_null, v_maybe_null))>::value, "");
}
int main()
{
// boolean
test_comparison_expression(bool{true});
// integral
test_comparison_expression(int8_t{7});
test_comparison_expression(int16_t{7});
test_comparison_expression(int32_t{7});
test_comparison_expression(int64_t{7});
// unsigned integral
test_comparison_expression(uint8_t{7});
test_comparison_expression(uint16_t{7});
test_comparison_expression(uint32_t{7});
test_comparison_expression(uint64_t{7});
// floating point
test_comparison_expression(float{7.7});
test_comparison_expression(double{7.7});
// text
test_comparison_expression('7');
test_comparison_expression("seven");
test_comparison_expression(std::string("seven"));
test_comparison_expression(sqlpp::compat::string_view("seven"));
// blob
test_comparison_expression(std::vector<uint8_t>{});
// date
test_comparison_expression(::sqlpp::chrono::day_point{});
// timestamp
test_comparison_expression(::sqlpp::chrono::microsecond_point{});
using minute_point = std::chrono::time_point<std::chrono::system_clock, std::chrono::minutes>;
test_comparison_expression(minute_point{});
// time_of_day
test_comparison_expression(std::chrono::microseconds{});
// text
test_like('7');
test_like("seven");
test_like(std::string("seven"));
test_like(sqlpp::compat::string_view("seven"));
}

View File

@ -0,0 +1,136 @@
/*
* Copyright (c) 2016-2016, 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::compat::optional<sqlpp::boolean>>;
}
template <typename Value>
void test_in_expression(Value v)
{
using OptValue = sqlpp::compat::optional<Value>;
auto v_not_null = sqlpp::value(v);
auto v_maybe_null = sqlpp::value(sqlpp::compat::make_optional(v));
#warning : Need to support in with select
// in(v_not_null, select(v_not_null.as(sqlpp::alias::a)));
// Compare non-nullable with non-nullable.
static_assert(is_bool<decltype(in(v_not_null, std::make_tuple(v_not_null, v_not_null)))>::value, "");
static_assert(is_bool<decltype(in(v_not_null, std::vector<Value>{}))>::value, "");
// Compare non-nullable with nullable.
static_assert(is_maybe_bool<decltype(in(v_not_null, std::make_tuple(v_not_null, v_maybe_null)))>::value, "");
static_assert(is_maybe_bool<decltype(in(v_not_null, std::vector<OptValue>{}))>::value, "");
// Compare nullable with non-nullable.
static_assert(is_maybe_bool<decltype(in(v_maybe_null, std::make_tuple(v_not_null, v_not_null)))>::value, "");
static_assert(is_maybe_bool<decltype(in(v_maybe_null, std::vector<Value>{}))>::value, "");
// Compare nullable with nullable.
static_assert(is_maybe_bool<decltype(in(v_maybe_null, std::make_tuple(v_not_null, v_maybe_null)))>::value, "");
static_assert(is_maybe_bool<decltype(in(v_maybe_null, std::vector<OptValue>{}))>::value, "");
}
template<typename Value>
void test_like(Value v)
{
auto v_not_null= sqlpp::value(v);
auto v_maybe_null= sqlpp::value(sqlpp::compat::make_optional(v));
// Compare non-nullable with non-nullable.
static_assert(is_bool<decltype(like(v_not_null, v_not_null))>::value, "");
// Compare non-nullable with nullable.
static_assert(is_maybe_bool<decltype(like(v_not_null, v_maybe_null))>::value, "");
// Compare nullable with non-nullable.
static_assert(is_maybe_bool<decltype(like(v_maybe_null, v_not_null))>::value, "");
// Compare nullable with nullable.
static_assert(is_maybe_bool<decltype(like(v_maybe_null, v_maybe_null))>::value, "");
}
int main()
{
// boolean
test_in_expression(bool{true});
// integral
test_in_expression(int8_t{7});
test_in_expression(int16_t{7});
test_in_expression(int32_t{7});
test_in_expression(int64_t{7});
// unsigned integral
test_in_expression(uint8_t{7});
test_in_expression(uint16_t{7});
test_in_expression(uint32_t{7});
test_in_expression(uint64_t{7});
// floating point
test_in_expression(float{7.7});
test_in_expression(double{7.7});
// text
test_in_expression('7');
test_in_expression("seven");
test_in_expression(std::string("seven"));
test_in_expression(sqlpp::compat::string_view("seven"));
// blob
test_in_expression(std::vector<uint8_t>{});
// date
test_in_expression(::sqlpp::chrono::day_point{});
// timestamp
test_in_expression(::sqlpp::chrono::microsecond_point{});
using minute_point = std::chrono::time_point<std::chrono::system_clock, std::chrono::minutes>;
test_in_expression(minute_point{});
// time_of_day
test_in_expression(std::chrono::microseconds{});
// text
test_like('7');
test_like("seven");
test_like(std::string("seven"));
test_like(sqlpp::compat::string_view("seven"));
}

View File

@ -0,0 +1,73 @@
/*
* Copyright (c) 2016-2016, 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::compat::optional<sqlpp::boolean>>;
}
template<typename Value>
void test_logical_expression(Value v)
{
auto v_not_null= sqlpp::value(v);
auto v_maybe_null= sqlpp::value(sqlpp::compat::make_optional(v));
// Compare non-nullable with non-nullable.
static_assert(is_bool<decltype(v_not_null and v_not_null)>::value, "");
static_assert(is_bool<decltype(v_not_null or v_not_null)>::value, "");
// Compare non-nullable with nullable.
static_assert(is_maybe_bool<decltype(v_maybe_null and v_not_null)>::value, "");
static_assert(is_maybe_bool<decltype(v_maybe_null or v_not_null)>::value, "");
// Compare nullable with non-nullable.
static_assert(is_maybe_bool<decltype(v_not_null and v_maybe_null)>::value, "");
static_assert(is_maybe_bool<decltype(v_not_null or v_maybe_null)>::value, "");
// Compare nullable with nullable.
static_assert(is_maybe_bool<decltype(v_maybe_null and v_maybe_null)>::value, "");
static_assert(is_maybe_bool<decltype(v_maybe_null or v_maybe_null)>::value, "");
// not.
static_assert(is_bool<decltype(not(v_not_null))>::value, "");
static_assert(is_maybe_bool<decltype(not(v_maybe_null))>::value, "");
}
int main()
{
// boolean
test_logical_expression(bool{true});
}

View File

@ -42,193 +42,73 @@ namespace
auto db = MockDb{}; auto db = MockDb{};
} }
SQLPP_ALIAS_PROVIDER(r_not_null);
SQLPP_ALIAS_PROVIDER(r_maybe_null);
SQLPP_ALIAS_PROVIDER(r_opt_not_null);
SQLPP_ALIAS_PROVIDER(r_opt_maybe_null);
template<typename ResultType, typename Value>
void test_result_row(Value v)
{
using OptResultType = sqlpp::compat::optional<ResultType>;
// Selectable values.
auto v_not_null = sqlpp::value(v).as(r_not_null);
const auto v_maybe_null = sqlpp::value(sqlpp::compat::make_optional(v)).as(r_maybe_null);
// Optional selectable values.
const auto v_opt_not_null = sqlpp::value(v).as(r_opt_not_null).if_(true);
const auto v_opt_maybe_null = sqlpp::value(sqlpp::compat::make_optional(v)).as(r_opt_maybe_null).if_(true);
for (const auto& row : db(select(v_not_null, v_maybe_null, v_opt_not_null, v_opt_maybe_null)))
{
static_assert(std::is_same<decltype(row.r_not_null), ResultType>::value, "");
static_assert(std::is_same<decltype(row.r_maybe_null), OptResultType>::value, "");
static_assert(std::is_same<decltype(row.r_opt_not_null), OptResultType>::value, "");
static_assert(std::is_same<decltype(row.r_opt_maybe_null), OptResultType>::value, "");
}
}
int main() int main()
{ {
static_assert(not sqlpp::can_be_null<decltype(bar.id)>::value, ""); // boolean
static_assert(sqlpp::can_be_null<decltype(foo.doubleN)>::value, ""); test_result_row<bool>(bool{true});
static_assert(not sqlpp::can_be_null<decltype(foo.textNnD)>::value, "");
static_assert(not sqlpp::can_be_null<decltype(bar.boolNn)>::value, "");
const auto seven = sqlpp::value(7).as(sqlpp::alias::s);
static_assert(not sqlpp::can_be_null<decltype(seven)>::value, "");
// Select non-optional column or alias of it. // integral
for (const auto& row : db(select(foo.id, foo.id.as(sqlpp::alias::a), foo.textNnD, foo.textNnD.as(sqlpp::alias::b)) test_result_row<int64_t>(int8_t{7});
.from(foo) test_result_row<int64_t>(int16_t{7});
.unconditionally())) test_result_row<int64_t>(int32_t{7});
{ test_result_row<int64_t>(int64_t{7});
static_assert(is_same_type<decltype(row.id), int64_t>(), "");
static_assert(is_same_type<decltype(row.a), int64_t>(), "");
static_assert(is_same_type<decltype(row.textNnD), sqlpp::compat::string_view>(), "");
static_assert(is_same_type<decltype(row.b), sqlpp::compat::string_view>(), "");
}
// Optionally select non-optional column or alias of it. // unsigned integral
for (const auto& row : db(select(foo.id.if_(true), foo.id.as(sqlpp::alias::a).if_(true), foo.textNnD.if_(true), test_result_row<uint64_t>(uint8_t{7});
foo.textNnD.as(sqlpp::alias::b).if_(true)) test_result_row<uint64_t>(uint16_t{7});
.from(foo) test_result_row<uint64_t>(uint32_t{7});
.unconditionally())) test_result_row<uint64_t>(uint64_t{7});
{
static_assert(is_same_type<decltype(row.id), sqlpp::compat::optional<int64_t>>(), "");
static_assert(is_same_type<decltype(row.a), sqlpp::compat::optional<int64_t>>(), "");
static_assert(is_same_type<decltype(row.textNnD), sqlpp::compat::optional<sqlpp::compat::string_view>>(), "");
static_assert(is_same_type<decltype(row.b), sqlpp::compat::optional<sqlpp::compat::string_view>>(), "");
}
// Select optional column or alias of it. // floating point
for (const auto& row : db(select(bar.intN, bar.intN.as(sqlpp::alias::a), bar.textN, bar.textN.as(sqlpp::alias::b)) test_result_row<double>(float{7.7});
.from(bar) test_result_row<double>(double{7.7});
.unconditionally()))
{
static_assert(is_same_type<decltype(row.intN), sqlpp::compat::optional<int64_t>>(), "");
static_assert(is_same_type<decltype(row.a), sqlpp::compat::optional<int64_t>>(), "");
static_assert(is_same_type<decltype(row.textN), sqlpp::compat::optional<sqlpp::compat::string_view>>(), "");
static_assert(is_same_type<decltype(row.b), sqlpp::compat::optional<sqlpp::compat::string_view>>(), "");
}
// Optionally select optional column or alias of it. // text
for (const auto& row : db(select(bar.intN.if_(true), bar.intN.as(sqlpp::alias::a).if_(true), bar.textN.if_(true), test_result_row<sqlpp::compat::string_view>('7');
bar.textN.as(sqlpp::alias::b).if_(true)) test_result_row<sqlpp::compat::string_view>("seven");
.from(bar) test_result_row<sqlpp::compat::string_view>(std::string("seven"));
.unconditionally())) test_result_row<sqlpp::compat::string_view>(sqlpp::compat::string_view("seven"));
{
// optional optional are still represented as one level of optional
static_assert(is_same_type<decltype(row.intN), sqlpp::compat::optional<int64_t>>(), "");
static_assert(is_same_type<decltype(row.a), sqlpp::compat::optional<int64_t>>(), "");
static_assert(is_same_type<decltype(row.textN), sqlpp::compat::optional<sqlpp::compat::string_view>>(), "");
static_assert(is_same_type<decltype(row.b), sqlpp::compat::optional<sqlpp::compat::string_view>>(), "");
}
// Select value and optional value. // blob
for (const auto& row : db(select(sqlpp::value(7).as(sqlpp::alias::a), test_result_row<sqlpp::compat::span<uint8_t>>(std::vector<uint8_t>{});
sqlpp::value(sqlpp::compat::optional<int>(7)).as(sqlpp::alias::b))))
{
static_assert(is_same_type<decltype(row.a), int64_t>(), "");
static_assert(is_same_type<decltype(row.b), sqlpp::compat::optional<int64_t>>(), "");
}
#warning: also test with optional // date
static_assert(sqlpp::is_boolean<bool>::value, ""); test_result_row<::sqlpp::chrono::day_point>(::sqlpp::chrono::day_point{});
static_assert(sqlpp::is_boolean<decltype(bar.boolNn)>::value, "");
static_assert(sqlpp::has_text_value<decltype(bar.textN)>::value, "");
static_assert(sqlpp::has_text_value<std::string>::value, "");
static_assert(sqlpp::has_numeric_value<int>::value, "");
static_assert(sqlpp::has_numeric_value<decltype(bar.intN)>::value, "");
#warning: These should be moved into comparison type requirement tests, etc. // timestamp
// Comparing optional value with non-optional value yields optional boolean. test_result_row<::sqlpp::chrono::microsecond_point>(::sqlpp::chrono::microsecond_point{});
static_assert(std::is_same<sqlpp::value_type_of_t<decltype(bar.textN < "hansi")>, using minute_point = std::chrono::time_point<std::chrono::system_clock, std::chrono::minutes>;
sqlpp::compat::optional<sqlpp::boolean>>::value, test_result_row<::sqlpp::chrono::microsecond_point>(minute_point{});
"");
static_assert(std::is_same<sqlpp::value_type_of_t<decltype(bar.textN <= "hansi")>,
sqlpp::compat::optional<sqlpp::boolean>>::value,
"");
static_assert(std::is_same<sqlpp::value_type_of_t<decltype(bar.textN == "hansi")>,
sqlpp::compat::optional<sqlpp::boolean>>::value,
"");
static_assert(std::is_same<sqlpp::value_type_of_t<decltype(bar.textN != "hansi")>,
sqlpp::compat::optional<sqlpp::boolean>>::value,
"");
static_assert(std::is_same<sqlpp::value_type_of_t<decltype(bar.textN >= "hansi")>,
sqlpp::compat::optional<sqlpp::boolean>>::value,
"");
static_assert(std::is_same<sqlpp::value_type_of_t<decltype(bar.textN < "hansi")>,
sqlpp::compat::optional<sqlpp::boolean>>::value,
"");
// Comparing non-optional value with non-optional value yields non-optional boolean. // time_of_day
static_assert(std::is_same<sqlpp::value_type_of_t<decltype(foo.textNnD < "hansi")>, test_result_row<std::chrono::microseconds>(std::chrono::microseconds{});
sqlpp::boolean>::value,
"");
static_assert(std::is_same<sqlpp::value_type_of_t<decltype(foo.textNnD <= "hansi")>,
sqlpp::boolean>::value,
"");
static_assert(std::is_same<sqlpp::value_type_of_t<decltype(foo.textNnD == "hansi")>,
sqlpp::boolean>::value,
"");
static_assert(std::is_same<sqlpp::value_type_of_t<decltype(foo.textNnD != "hansi")>,
sqlpp::boolean>::value,
"");
static_assert(std::is_same<sqlpp::value_type_of_t<decltype(foo.textNnD >= "hansi")>,
sqlpp::boolean>::value,
"");
static_assert(std::is_same<sqlpp::value_type_of_t<decltype(foo.textNnD < "hansi")>,
sqlpp::boolean>::value,
"");
// The first exceptions are the operators is_null and is_not_null which always yield non-optional boolean
#warning: Still need to implement is_distinct_from as member function
static_assert(std::is_same<sqlpp::value_type_of_t<decltype(is_null(bar.textN))>,
sqlpp::boolean>::value,
"");
static_assert(std::is_same<sqlpp::value_type_of_t<decltype(is_null(foo.textNnD))>,
sqlpp::boolean>::value,
"");
static_assert(std::is_same<sqlpp::value_type_of_t<decltype(is_not_null(bar.textN))>,
sqlpp::boolean>::value,
"");
static_assert(std::is_same<sqlpp::value_type_of_t<decltype(is_not_null(foo.textNnD))>,
sqlpp::boolean>::value,
"");
// The other exceptions are the operators is_distinct_from and is_not_distinct_from which always yield non-optional boolean
#warning: Still need to implement is_distinct_from as member function
static_assert(std::is_same<sqlpp::value_type_of_t<decltype(is_distinct_from(bar.textN, "hansi"))>,
sqlpp::boolean>::value,
"");
static_assert(std::is_same<sqlpp::value_type_of_t<decltype(is_distinct_from(foo.textNnD, "hansi"))>,
sqlpp::boolean>::value,
"");
static_assert(std::is_same<sqlpp::value_type_of_t<decltype(is_not_distinct_from(bar.textN, sqlpp::compat::make_optional("hansi")))>,
sqlpp::boolean>::value,
"");
static_assert(std::is_same<sqlpp::value_type_of_t<decltype(is_not_distinct_from(foo.textNnD, sqlpp::compat::make_optional("hansi")))>,
sqlpp::boolean>::value,
"");
// LIKE expressions can be NULL is one of their operands can be NULL.
static_assert(std::is_same<sqlpp::value_type_of_t<decltype(like(bar.textN, "hansi"))>, sqlpp::compat::optional<sqlpp::boolean>>::value, "");
static_assert(std::is_same<sqlpp::value_type_of_t<decltype(like(foo.textNnD, sqlpp::compat::make_optional("hansi")))>, sqlpp::compat::optional<sqlpp::boolean>>::value, "");
static_assert(std::is_same<sqlpp::value_type_of_t<decltype(like(foo.textNnD, "hansi"))>, sqlpp::boolean>::value, "");
#warning: These should be moved into logical type requirement tests, etc.
// Logically combining optional value with non-optional value yields optional boolean.
static_assert(std::is_same<sqlpp::value_type_of_t<decltype(sqlpp::compat::make_optional(bar.boolNn) and true)>,
sqlpp::compat::optional<sqlpp::boolean>>::value,
"");
static_assert(std::is_same<sqlpp::value_type_of_t<decltype(sqlpp::compat::make_optional(bar.boolNn) or true)>,
sqlpp::compat::optional<sqlpp::boolean>>::value,
"");
static_assert(std::is_same<sqlpp::value_type_of_t<decltype(sqlpp::compat::make_optional(bar.boolNn) and
sqlpp::compat::make_optional(true))>,
sqlpp::compat::optional<sqlpp::boolean>>::value,
"");
static_assert(std::is_same<sqlpp::value_type_of_t<decltype(sqlpp::compat::make_optional(bar.boolNn) or
sqlpp::compat::make_optional(true))>,
sqlpp::compat::optional<sqlpp::boolean>>::value,
"");
static_assert(std::is_same<sqlpp::value_type_of_t<decltype(bar.boolNn and sqlpp::compat::make_optional(true))>,
sqlpp::compat::optional<sqlpp::boolean>>::value,
"");
static_assert(std::is_same<sqlpp::value_type_of_t<decltype(bar.boolNn or sqlpp::compat::make_optional(true))>,
sqlpp::compat::optional<sqlpp::boolean>>::value,
"");
static_assert(std::is_same<sqlpp::value_type_of_t<decltype(not sqlpp::compat::make_optional(bar.boolNn))>,
sqlpp::compat::optional<sqlpp::boolean>>::value,
"");
// Logically combining non-optional value with non-optional value yields non-optional boolean.
static_assert(std::is_same<sqlpp::value_type_of_t<decltype(bar.boolNn and true)>,
sqlpp::boolean>::value,
"");
static_assert(std::is_same<sqlpp::value_type_of_t<decltype(bar.boolNn or true)>,
sqlpp::boolean>::value,
"");
static_assert(std::is_same<sqlpp::value_type_of_t<decltype(not bar.boolNn)>,
sqlpp::boolean>::value,
"");
// Arithmetically combining optional value with non-optional value yields optional boolean. // Arithmetically combining optional value with non-optional value yields optional boolean.
static_assert(std::is_same<sqlpp::value_type_of_t<decltype(sqlpp::value(sqlpp::compat::make_optional(7)) + 8)>, static_assert(std::is_same<sqlpp::value_type_of_t<decltype(sqlpp::value(sqlpp::compat::make_optional(7)) + 8)>,
@ -282,6 +162,7 @@ int main()
sqlpp::compat::optional<sqlpp::boolean>>::value, sqlpp::compat::optional<sqlpp::boolean>>::value,
""); "");
// in expression
static_assert(std::is_same<sqlpp::value_type_of_t<decltype(in(sqlpp::value(7), sqlpp::compat::make_optional(7), 8, 9))>, static_assert(std::is_same<sqlpp::value_type_of_t<decltype(in(sqlpp::value(7), sqlpp::compat::make_optional(7), 8, 9))>,
sqlpp::compat::optional<sqlpp::boolean>>::value, sqlpp::compat::optional<sqlpp::boolean>>::value,
""); "");

113
tests/core/types/value.cpp Normal file
View File

@ -0,0 +1,113 @@
/*
* Copyright (c) 2016-2016, 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{};
}
SQLPP_ALIAS_PROVIDER(r_not_null);
SQLPP_ALIAS_PROVIDER(r_maybe_null);
SQLPP_ALIAS_PROVIDER(r_opt_not_null);
SQLPP_ALIAS_PROVIDER(r_opt_maybe_null);
template <typename T, typename ValueType>
using is_value_type = std::is_same<sqlpp::value_type_of_t<T>, ValueType>;
template<typename Value>
void test_value(Value v)
{
using ValueType = sqlpp::value_type_of_t<Value>;
using OptValueType = sqlpp::compat::optional<ValueType>;
auto v_not_null= sqlpp::value(v);
auto v_maybe_null= sqlpp::value(sqlpp::compat::make_optional(v));
auto v_not_null_alias = sqlpp::value(v).as(r_not_null);
auto v_maybe_null_alias = sqlpp::value(sqlpp::compat::make_optional(v)).as(r_maybe_null);
auto v_opt_not_null_alias = sqlpp::value(v).as(r_opt_not_null).if_(true);
auto v_opt_maybe_null_alias = sqlpp::value(sqlpp::compat::make_optional(v)).as(r_opt_maybe_null).if_(true);
static_assert(is_value_type<decltype(v_not_null), ValueType>::value, "");
static_assert(is_value_type<decltype(v_maybe_null), OptValueType>::value, "");
static_assert(is_value_type<decltype(v_not_null_alias), ValueType>::value, "");
static_assert(is_value_type<decltype(v_maybe_null_alias), OptValueType>::value, "");
static_assert(is_value_type<decltype(v_opt_not_null_alias), OptValueType>::value, "");
static_assert(is_value_type<decltype(v_opt_maybe_null_alias), OptValueType>::value, "");
static_assert(not sqlpp::can_be_null<decltype(v_not_null)>::value, "");
static_assert(sqlpp::can_be_null<decltype(v_maybe_null)>::value, "");
static_assert(not sqlpp::can_be_null<decltype(v_not_null_alias)>::value, "");
static_assert(sqlpp::can_be_null<decltype(v_maybe_null_alias)>::value, "");
static_assert(sqlpp::can_be_null<decltype(v_opt_not_null_alias)>::value, "");
static_assert(sqlpp::can_be_null<decltype(v_opt_maybe_null_alias)>::value, "");
}
int main()
{
// boolean
test_value(bool{true});
// integral
test_value(int8_t{7});
test_value(int16_t{7});
test_value(int32_t{7});
test_value(int64_t{7});
// unsigned integral
test_value(uint8_t{7});
test_value(uint16_t{7});
test_value(uint32_t{7});
test_value(uint64_t{7});
// floating point
test_value(float{7.7});
test_value(double{7.7});
// text
test_value('7');
test_value("seven");
test_value(std::string("seven"));
test_value(sqlpp::compat::string_view("seven"));
// blob
test_value(std::vector<uint8_t>{});
// date
test_value(::sqlpp::chrono::day_point{});
// timestamp
test_value(::sqlpp::chrono::microsecond_point{});
using minute_point = std::chrono::time_point<std::chrono::system_clock, std::chrono::minutes>;
test_value(minute_point{});
// time_of_day
test_value(std::chrono::microseconds{});
}