0
0
mirror of https://github.com/rbock/sqlpp11.git synced 2024-11-16 04:47:18 +08:00

(Only) allow comparison with ANY and introduce BETWEEN

This commit is contained in:
Roland Bock 2024-07-17 07:43:19 +02:00
parent 937dd31a13
commit 25200ba4cb
13 changed files with 284 additions and 115 deletions

View File

@ -26,11 +26,17 @@
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/ */
#include <type_traits>
#include <sqlpp11/char_sequence.h> #include <sqlpp11/char_sequence.h>
namespace sqlpp
{
struct name_tag
{
};
}
#define SQLPP_ALIAS_PROVIDER(name) \ #define SQLPP_ALIAS_PROVIDER(name) \
struct name##_t \ struct name##_t : public sqlpp::name_tag \
{ \ { \
struct _alias_t \ struct _alias_t \
{ \ { \
@ -54,7 +60,7 @@
constexpr name##_t name = {}; constexpr name##_t name = {};
#define SQLPP_QUOTED_ALIAS_PROVIDER(name) \ #define SQLPP_QUOTED_ALIAS_PROVIDER(name) \
struct name##_t \ struct name##_t : public sqlpp::name_tag \
{ \ { \
struct _alias_t \ struct _alias_t \
{ \ { \
@ -79,20 +85,6 @@
namespace sqlpp namespace sqlpp
{ {
template <typename T, typename Enable = void>
struct is_alias_provider_t
{
static constexpr bool value = false;
};
template <typename T>
struct is_alias_provider_t<
T,
typename std::enable_if<std::is_class<typename T::_alias_t::template _member_t<int>>::value, void>::type>
{
static constexpr bool value = true;
};
namespace alias namespace alias
{ {
SQLPP_ALIAS_PROVIDER(a) SQLPP_ALIAS_PROVIDER(a)

View File

@ -71,6 +71,7 @@ namespace sqlpp
return _table{}; return _table{};
} }
#warning: Let's do if_(condition, expression) -> if_t<Expression>, which can be used exclusively in SELECT, AND, OR, JOIN
sqlpp::compat::optional<column_t> if_(bool condition) const sqlpp::compat::optional<column_t> if_(bool condition) const
{ {
return condition ? sqlpp::compat::make_optional(*this) : sqlpp::compat::nullopt; return condition ? sqlpp::compat::make_optional(*this) : sqlpp::compat::nullopt;

View File

@ -34,8 +34,6 @@
#include <sqlpp11/case.h> #include <sqlpp11/case.h>
#include <sqlpp11/lower.h> #include <sqlpp11/lower.h>
#include <sqlpp11/upper.h> #include <sqlpp11/upper.h>
#include <sqlpp11/any.h>
#include <sqlpp11/some.h>
#include <sqlpp11/value_type.h> #include <sqlpp11/value_type.h>
#include <sqlpp11/verbatim.h> // Csaba Csoma suggests: unsafe_sql instead of verbatim #include <sqlpp11/verbatim.h> // Csaba Csoma suggests: unsafe_sql instead of verbatim
#include <sqlpp11/parameterized_verbatim.h> #include <sqlpp11/parameterized_verbatim.h>

View File

@ -36,8 +36,10 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <sqlpp11/operator/logical_expression.h> #include <sqlpp11/operator/logical_expression.h>
// comparison // comparison
#include <sqlpp11/operator/any.h>
#include <sqlpp11/operator/comparison_expression.h> #include <sqlpp11/operator/comparison_expression.h>
#include <sqlpp11/operator/in_expression.h> #include <sqlpp11/operator/in_expression.h>
#include <sqlpp11/operator/between_expression.h>
// arithmetic // arithmetic
#include <sqlpp11/operator/arithmetic_expression.h> #include <sqlpp11/operator/arithmetic_expression.h>

View File

@ -51,11 +51,23 @@ namespace sqlpp
Select _select; Select _select;
}; };
template<typename Select> // No value_type_of defined for any_t, because it is to be used with basic comparison operators, only.
struct value_type_of<any_t<Select>> : value_type_of<Select>
template <typename T>
struct remove_any
{ {
using type = T;
}; };
template <typename Select>
struct remove_any<any_t<Select>>
{
using type = Select;
};
template <typename T>
using remove_any_t = typename remove_any<T>::type;
template <typename Context, typename Select> template <typename Context, typename Select>
Context& serialize(const any_t<Select>& t, Context& context) Context& serialize(const any_t<Select>& t, Context& context)
{ {
@ -64,9 +76,8 @@ namespace sqlpp
return context; return context;
} }
#warning: Need tests
template <typename Select> template <typename Select>
using check_any_args = std::enable_if_t<is_statement_t<Select>::value and has_value_type<Select>::value>; using check_any_args = std::enable_if_t<has_value_type<Select>::value>;
template <typename ...Policies, typename = check_any_args<statement_t<Policies...>>> template <typename ...Policies, typename = check_any_args<statement_t<Policies...>>>
auto any(statement_t<Policies...> t) -> any_t<statement_t<Policies...>> auto any(statement_t<Policies...> t) -> any_t<statement_t<Policies...>>

View File

@ -0,0 +1,143 @@
#pragma once
/*
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:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. 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/type_traits.h>
#include <sqlpp11/logic.h>
namespace sqlpp
{
template<typename L, typename R1, typename R2>
struct between_expression
{
L l;
R1 r1;
R2 r2;
};
template <typename L, typename R1, typename R2>
using check_between_args =
std::enable_if_t<values_are_comparable<L, R1>::value and values_are_comparable<L, R2>::value>;
template <typename L, typename R1, typename R2>
struct value_type_of<between_expression<L, R1, R2>>
: public std::conditional<sqlpp::is_optional<value_type_of_t<L>>::value or
sqlpp::is_optional<value_type_of_t<R1>>::value or
sqlpp::is_optional<value_type_of_t<R2>>::value,
sqlpp::compat::optional<boolean>,
boolean>
{
};
/*
template <typename L, typename... Args>
struct nodes_of<between_t<L, Args...>>
{
using type = type_vector<L, Args...>;
};
template <typename L, typename... Args>
constexpr auto in(L l, Args... args)
-> std::enable_if_t<((sizeof...(Args) > 0) and ... and values_are_compatible_v<L, Args>), between_t<L, Args...>>
{
return between_t<L, Args...>{l, std::tuple{args...}};
}
template <typename L, typename... Args>
constexpr auto requires_braces_v<between_t<L, Args...>> = true;
template <typename Context, typename L, typename... Args>
[[nodiscard]] auto to_sql_string(Context& context, const between_t<L, Args...>& t)
{
if constexpr (sizeof...(Args) == 1)
{
return to_sql_string(context, embrace(t.l)) + " IN(" + to_sql_string(context, std::get<0>(t.args)) + ")";
}
else
{
return to_sql_string(context, embrace(t.l)) + " IN(" + tuple_to_sql_string(context, ", ", t.args) + ")";
}
}
*/
#warning: Need tests for between expressions
template <typename L, typename R1, typename R2, typename = check_between_args<L, R1, R2>>
constexpr auto between(L l, R1 r1, R2 r2) -> between_expression<L, R1, R2>
{
return {std::move(l), std::move(r1), std::move(r2)};
}
#if 0 // original serialize implementation
template <typename Context, typename Operand, typename Arg, typename... Args>
Context& serialize(const between_t<Operand, Arg, Args...>& t, Context& context)
{
serialize(t._operand, context);
context << " IN(";
if (sizeof...(Args) == 0)
{
serialize(std::get<0>(t._args), context);
}
else
{
interpret_tuple(t._args, ',', context);
}
context << ')';
return context;
}
template <typename Context, typename Operand>
Context& serialize(const between_t<Operand>&, Context& context)
{
serialize(boolean_operand{false}, context);
return context;
}
template <typename Container>
struct value_list_t;
template <typename Context, typename Operand, typename Container>
Context& serialize(const between_t<Operand, value_list_t<Container>>& t, Context& context)
{
const auto& value_list = std::get<0>(t._args);
if (value_list._container.empty())
{
serialize(boolean_operand{false}, context);
}
else
{
serialize(t._operand, context);
context << " IN(";
serialize(value_list, context);
context << ')';
}
return context;
}
#endif
} // namespace sqlpp

View File

@ -28,6 +28,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <utility> #include <utility>
#include <sqlpp11/operator/any.h>
#include <sqlpp11/type_traits.h> #include <sqlpp11/type_traits.h>
namespace sqlpp namespace sqlpp
@ -44,7 +45,7 @@ namespace sqlpp
template <typename L, typename Operator, typename R> template <typename L, typename Operator, typename R>
struct value_type_of<comparison_expression<L, Operator, R>> struct value_type_of<comparison_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, : std::conditional<sqlpp::is_optional<value_type_of_t<L>>::value or sqlpp::is_optional<value_type_of_t<remove_any_t<R>>>::value,
sqlpp::compat::optional<boolean>, sqlpp::compat::optional<boolean>,
boolean> boolean>
{ {
@ -113,7 +114,9 @@ namespace sqlpp
static constexpr auto symbol = " < "; static constexpr auto symbol = " < ";
}; };
template <typename L, typename R, typename = check_comparison_args<L, R>> // We are using remove_any_t in the basic comparison operators to allow comparison with ANY-expressions.
// Note: any_t does not have a specialization for value_type_of to disallow it from being used in other contexts.
template <typename L, typename R, typename = check_comparison_args<L, remove_any_t<R>>>
constexpr auto operator<(L l, R r) -> comparison_expression<L, less, R> constexpr auto operator<(L l, R r) -> comparison_expression<L, less, R>
{ {
return {std::move(l), std::move(r)}; return {std::move(l), std::move(r)};
@ -124,7 +127,7 @@ namespace sqlpp
static constexpr auto symbol = " <= "; static constexpr auto symbol = " <= ";
}; };
template <typename L, typename R, typename = check_comparison_args<L, R>> template <typename L, typename R, typename = check_comparison_args<L, remove_any_t<R>>>
constexpr auto operator<=(L l, R r) -> comparison_expression<L, less_equal, R> constexpr auto operator<=(L l, R r) -> comparison_expression<L, less_equal, R>
{ {
return {std::move(l), std::move(r)}; return {std::move(l), std::move(r)};
@ -135,7 +138,7 @@ namespace sqlpp
static constexpr auto symbol = " = "; static constexpr auto symbol = " = ";
}; };
template <typename L, typename R, typename = check_comparison_args<L, R>> template <typename L, typename R, typename = check_comparison_args<L, remove_any_t<R>>>
constexpr auto operator==(L l, R r) -> comparison_expression<L, equal_to, R> constexpr auto operator==(L l, R r) -> comparison_expression<L, equal_to, R>
{ {
return {l, r}; return {l, r};
@ -146,7 +149,7 @@ namespace sqlpp
static constexpr auto symbol = " != "; static constexpr auto symbol = " != ";
}; };
template <typename L, typename R, typename = check_comparison_args<L, R>> template <typename L, typename R, typename = check_comparison_args<L, remove_any_t<R>>>
constexpr auto operator!=(L l, R r) -> comparison_expression<L, not_equal_to, R> constexpr auto operator!=(L l, R r) -> comparison_expression<L, not_equal_to, R>
{ {
return {std::move(l), std::move(r)}; return {std::move(l), std::move(r)};
@ -157,7 +160,7 @@ namespace sqlpp
static constexpr auto symbol = " >= "; static constexpr auto symbol = " >= ";
}; };
template <typename L, typename R, typename = check_comparison_args<L, R>> template <typename L, typename R, typename = check_comparison_args<L, remove_any_t<R>>>
constexpr auto operator>=(L l, R r) -> comparison_expression<L, greater_equal, R> constexpr auto operator>=(L l, R r) -> comparison_expression<L, greater_equal, R>
{ {
return {std::move(l), std::move(r)}; return {std::move(l), std::move(r)};
@ -168,7 +171,7 @@ namespace sqlpp
static constexpr auto symbol = " > "; static constexpr auto symbol = " > ";
}; };
template <typename L, typename R, typename = check_comparison_args<L, R>> template <typename L, typename R, typename = check_comparison_args<L, remove_any_t<R>>>
constexpr auto operator>(L l, R r) -> comparison_expression<L, greater, R> constexpr auto operator>(L l, R r) -> comparison_expression<L, greater, R>
{ {
return {std::move(l), std::move(r)}; return {std::move(l), std::move(r)};

View File

@ -73,7 +73,7 @@ namespace sqlpp
-> parameter_t<ValueType, AliasProvider> -> parameter_t<ValueType, AliasProvider>
{ {
static_assert(is_value_type_t<ValueType>::value, "first argument is not a value type"); static_assert(is_value_type_t<ValueType>::value, "first argument is not a value type");
static_assert(is_alias_provider_t<AliasProvider>::value, "second argument is not an alias provider"); static_assert(has_name<AliasProvider>::value, "second argument does not have a name");
return {}; return {};
} }
} // namespace sqlpp } // namespace sqlpp

View File

@ -1,76 +0,0 @@
#pragma once
/*
* Copyright (c) 2013-2015, 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/statement_fwd.h>
#include <sqlpp11/detail/type_set.h>
#include <sqlpp11/char_sequence.h>
namespace sqlpp
{
template <typename Select>
struct some_t
{
using _traits = make_traits<value_type_of_t<Select>, tag::is_multi_expression>;
using _nodes = detail::type_vector<Select>;
some_t(Select select) : _select(select)
{
}
some_t(const some_t&) = default;
some_t(some_t&&) = default;
some_t& operator=(const some_t&) = default;
some_t& operator=(some_t&&) = default;
~some_t() = default;
Select _select;
};
template<typename Select>
struct value_type_of<some_t<Select>> : value_type_of<Select>
{
};
template <typename Context, typename Select>
Context& serialize(const some_t<Select>& t, Context& context)
{
context << "SOME";
serialize_operand(t._select, context);
return context;
}
#warning : Need tests
template <typename Select>
using check_some_args = std::enable_if_t<has_value_type<Select>::value>;
template <typename ... Policies, typename = check_some_args<statement_t<Policies...>>>
auto some(statement_t<Policies...> t) -> some_t<statement_t<Policies...>>
{
return {std::move(t)};
}
} // namespace sqlpp

View File

@ -420,7 +420,6 @@ namespace sqlpp
SQLPP_VALUE_TRAIT_GENERATOR(is_sql_null) SQLPP_VALUE_TRAIT_GENERATOR(is_sql_null)
SQLPP_VALUE_TRAIT_GENERATOR(is_value_type) SQLPP_VALUE_TRAIT_GENERATOR(is_value_type)
SQLPP_VALUE_TRAIT_GENERATOR(is_wrapped_value)
SQLPP_VALUE_TRAIT_GENERATOR(is_selectable) SQLPP_VALUE_TRAIT_GENERATOR(is_selectable)
SQLPP_VALUE_TRAIT_GENERATOR(is_expression) SQLPP_VALUE_TRAIT_GENERATOR(is_expression)
SQLPP_VALUE_TRAIT_GENERATOR(is_multi_expression) SQLPP_VALUE_TRAIT_GENERATOR(is_multi_expression)
@ -481,9 +480,6 @@ namespace sqlpp
using is_database = using is_database =
typename std::conditional<std::is_same<Database, void>::value, std::false_type, std::true_type>::type; typename std::conditional<std::is_same<Database, void>::value, std::false_type, std::true_type>::type;
template <typename T>
using cpp_value_type_of_t = typename value_type_of_t<T>::_cpp_value_type;
namespace detail namespace detail
{ {
template <typename T, typename HasNodes = void> template <typename T, typename HasNodes = void>
@ -666,14 +662,15 @@ namespace sqlpp
template <typename T> template <typename T>
using parameters_of = typename detail::parameters_of_impl<T>::type; using parameters_of = typename detail::parameters_of_impl<T>::type;
template <typename T>
using alias_of = typename T::_alias_t;
template <typename T> template <typename T>
using name_of = typename T::_alias_t::_name_t; using name_of = typename T::_alias_t::_name_t;
// Used by SQLPP_ALIAS_PROVIDER.
struct name_tag;
// Override this for other classes like columns or tables.
template<typename T> template<typename T>
struct has_name : public std::false_type {}; struct has_name : public std::integral_constant<bool, std::is_base_of<name_tag, T>::value> {};
template <typename ValueType, typename... Tags> template <typename ValueType, typename... Tags>
struct make_traits struct make_traits

View File

@ -26,6 +26,7 @@
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/ */
#include <sqlpp11/operator/as_expression.h>
#include <sqlpp11/expression_operators.h> #include <sqlpp11/expression_operators.h>
#include <sqlpp11/type_traits.h> #include <sqlpp11/type_traits.h>

View File

@ -34,6 +34,7 @@ function(test_compile name)
endif() endif()
endfunction() endfunction()
test_compile(any)
test_compile(aggregate_functions) test_compile(aggregate_functions)
test_compile(comparison_expression) test_compile(comparison_expression)
test_compile(in_expression) test_compile(in_expression)

96
tests/core/types/any.cpp Normal file
View File

@ -0,0 +1,96 @@
/*
* 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 <sqlpp11/sqlpp11.h>
SQLPP_ALIAS_PROVIDER(r_not_null);
SQLPP_ALIAS_PROVIDER(r_maybe_null);
template <typename Value>
void test_any(Value v)
{
using ValueType = sqlpp::value_type_of_t<Value>;
using OptValueType = sqlpp::value_type_of_t<sqlpp::compat::optional<Value>>;
// 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);
// ANY expression are not to be in most expressions and therefore have no value defined.
static_assert(std::is_same<sqlpp::value_type_of_t<decltype(any(select(v_not_null)))>, sqlpp::no_value_t>::value, "");
static_assert(std::is_same<sqlpp::value_type_of_t<decltype(any(select(v_maybe_null)))>, sqlpp::no_value_t>::value,
"");
// ANY expression can be used in basic comparison expressions, which use remove_any_t to look inside.
static_assert(
std::is_same<sqlpp::value_type_of_t<sqlpp::remove_any_t<decltype(any(select(v_not_null)))>>, ValueType>::value,
"");
static_assert(std::is_same<sqlpp::value_type_of_t<sqlpp::remove_any_t<decltype(any(select(v_maybe_null)))>>,
OptValueType>::value,
"");
}
int main()
{
// boolean
test_any(bool{true});
// integral
test_any(int8_t{7});
test_any(int16_t{7});
test_any(int32_t{7});
test_any(int64_t{7});
// unsigned integral
test_any(uint8_t{7});
test_any(uint16_t{7});
test_any(uint32_t{7});
test_any(uint64_t{7});
// floating point
test_any(float{7.7});
test_any(double{7.7});
// text
test_any('7');
test_any("seven");
test_any(std::string("seven"));
test_any(sqlpp::compat::string_view("seven"));
// blob
test_any(std::vector<uint8_t>{});
// date
test_any(::sqlpp::chrono::day_point{});
// timestamp
test_any(::sqlpp::chrono::microsecond_point{});
using minute_point = std::chrono::time_point<std::chrono::system_clock, std::chrono::minutes>;
test_any(minute_point{});
// time_of_day
test_any(std::chrono::microseconds{});
}