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

Add more cte tests

This commit is contained in:
Roland Bock 2024-11-03 11:33:47 +01:00
parent fef1c3e426
commit dc53fd5acc
9 changed files with 79 additions and 33 deletions

View File

@ -33,12 +33,12 @@
namespace sqlpp namespace sqlpp
{ {
#warning: It would be sufficient to store the NameTag here, not the whole NameTagProvider
template <typename ValueType, typename NameType> template <typename ValueType, typename NameType>
struct parameter_t : public enable_comparison<parameter_t<ValueType, NameType>> struct parameter_t : public enable_comparison<parameter_t<ValueType, NameType>>
{ {
using _traits = make_traits<ValueType, tag::is_parameter, tag::is_expression>; using _traits = make_traits<ValueType, tag::is_parameter, tag::is_expression>;
using _parameters = detail::type_vector<parameter_t>;
using _is_literal_expression = std::true_type; using _is_literal_expression = std::true_type;
using _instance_t = member_t<NameType, parameter_value_t<ValueType>>; using _instance_t = member_t<NameType, parameter_value_t<ValueType>>;
@ -52,6 +52,12 @@ namespace sqlpp
~parameter_t() = default; ~parameter_t() = default;
}; };
template<typename ValueType, typename NameType>
struct parameters_of<parameter_t<ValueType, NameType>>
{
using type = detail::type_vector<parameter_t<ValueType, NameType>>;
};
template<typename ValueType, typename NameType> template<typename ValueType, typename NameType>
struct value_type_of<parameter_t<ValueType, NameType>> struct value_type_of<parameter_t<ValueType, NameType>>
{ {

View File

@ -40,8 +40,6 @@ namespace sqlpp
template <typename Flag, typename Lhs, typename Rhs> template <typename Flag, typename Lhs, typename Rhs>
struct cte_union_t struct cte_union_t
{ {
using _parameters = detail::type_vector_cat_t<parameters_of<Lhs>, parameters_of<Rhs>>;
cte_union_t(Lhs lhs, Rhs rhs) : _lhs(lhs), _rhs(rhs) cte_union_t(Lhs lhs, Rhs rhs) : _lhs(lhs), _rhs(rhs)
{ {
} }
@ -303,9 +301,6 @@ namespace sqlpp
} }
}; };
template<typename NameTagProvider>
struct is_table<cte_ref_t<NameTagProvider>> : public std::true_type{};
template<typename NameTagProvider> template<typename NameTagProvider>
struct name_tag_of<cte_ref_t<NameTagProvider>> : public name_tag_of<NameTagProvider> struct name_tag_of<cte_ref_t<NameTagProvider>> : public name_tag_of<NameTagProvider>
{}; {};

View File

@ -62,7 +62,7 @@ namespace sqlpp
using _nodes = detail::type_vector<>; using _nodes = detail::type_vector<>;
using _provided_ctes = using _provided_ctes =
detail::make_joined_set_t<required_ctes_of<Expressions>...>; // WITH provides common table expressions detail::make_joined_set_t<required_ctes_of<Expressions>...>; // WITH provides common table expressions
using _parameters = detail::type_vector_cat_t<parameters_of<Expressions>...>; using _parameters = detail::type_vector_cat_t<parameters_of_t<Expressions>...>;
using _data_t = with_data_t<Expressions...>; using _data_t = with_data_t<Expressions...>;
@ -80,6 +80,7 @@ namespace sqlpp
using _consistency_check = consistent_t; using _consistency_check = consistent_t;
}; };
}; };
#warning: Need traits here! And type tests for them
struct no_with_t struct no_with_t
{ {

View File

@ -64,6 +64,7 @@ namespace sqlpp
} }
}; };
#warning: Why would we need this?
template <typename Exp> template <typename Exp>
using make_parameter_list_t = parameter_list_t<parameters_of<Exp>>; using make_parameter_list_t = parameter_list_t<parameters_of_t<Exp>>;
} // namespace sqlpp } // namespace sqlpp

View File

@ -69,7 +69,7 @@ namespace sqlpp
using _nodes = detail::type_vector<Parts...>; using _nodes = detail::type_vector<Parts...>;
using _parameter_check = using _parameter_check =
typename std::conditional<parameters_of<custom_query_t>::empty(), typename std::conditional<parameters_of_t<custom_query_t>::empty(),
consistent_t, consistent_t,
assert_no_parameters_t>::type; assert_no_parameters_t>::type;
using _run_check = detail::get_first_if<is_inconsistent_t, consistent_t, _parameter_check>; using _run_check = detail::get_first_if<is_inconsistent_t, consistent_t, _parameter_check>;

View File

@ -123,7 +123,7 @@ namespace sqlpp
// - the select is complete (leaks no table requirements or cte requirements) // - the select is complete (leaks no table requirements or cte requirements)
static constexpr bool _can_be_used_as_table() static constexpr bool _can_be_used_as_table()
{ {
return has_result_row<_statement_t>::value and _required_tables_of::empty() == 0 and return has_result_row<_statement_t>::value and _required_tables_of::empty() and
_required_ctes_of::empty(); _required_ctes_of::empty();
} }
@ -140,11 +140,11 @@ namespace sqlpp
detail::make_intersect_set_t<required_tables_of_t<_result_type_provider>, detail::make_intersect_set_t<required_tables_of_t<_result_type_provider>,
_all_provided_optional_tables>::size::value != 0>; _all_provided_optional_tables>::size::value != 0>;
*/ */
using _parameters = detail::type_vector_cat_t<parameters_of<Policies>...>; using _parameters = detail::type_vector_cat_t<parameters_of_t<Policies>...>;
// required_tables and _required_ctes are defined above // required_tables and _required_ctes are defined above
using _cte_check = using _cte_check =
typename std::conditional<_required_ctes_of::empty() == 0, consistent_t, assert_no_unknown_ctes_t>::type; typename std::conditional<_required_ctes_of::empty(), consistent_t, assert_no_unknown_ctes_t>::type;
using _table_check = using _table_check =
typename std::conditional<_required_tables_of::empty(), consistent_t, assert_no_unknown_tables_t>::type; typename std::conditional<_required_tables_of::empty(), consistent_t, assert_no_unknown_tables_t>::type;
using _parameter_check = typename std:: using _parameter_check = typename std::

View File

@ -404,26 +404,20 @@ namespace sqlpp
template <typename KnownAggregates, typename T> template <typename KnownAggregates, typename T>
using is_non_aggregate_expression_t = typename detail::is_non_aggregate_expression_impl<KnownAggregates, T>::type; using is_non_aggregate_expression_t = typename detail::is_non_aggregate_expression_impl<KnownAggregates, T>::type;
namespace detail template<typename T>
struct parameters_of
{ {
template <typename T, typename Leaf = void> using type = typename parameters_of<nodes_of_t<T>>::type;
struct parameters_of_impl
{
using type = typename parameters_of_impl<nodes_of_t<T>>::type;
}; };
template<typename... T>
struct parameters_of<detail::type_vector<T...>>
{
using type = detail::type_vector_cat_t<typename parameters_of<T>::type...>;
};
template <typename T> template <typename T>
struct parameters_of_impl<T, typename std::enable_if<std::is_class<typename T::_parameters>::value>::type> using parameters_of_t = typename parameters_of<T>::type;
{
using type = typename T::_parameters;
};
template <typename... Nodes>
struct parameters_of_impl<type_vector<Nodes...>, void>
{
using type = detail::type_vector_cat_t<typename parameters_of_impl<Nodes>::type...>;
};
} // namespace detail
template <typename T>
using parameters_of = typename detail::parameters_of_impl<T>::type;
// Something that can be used as a table // Something that can be used as a table
template <typename T> template <typename T>

View File

@ -31,21 +31,68 @@ void test_cte()
const auto foo = test::TabFoo{}; const auto foo = test::TabFoo{};
const auto bar = test::TabBar{}; const auto bar = test::TabBar{};
#warning: add more tests #warning: add more tests, including parameters and dynamic parts
#warning: Can we union dynamically?
// Simple CTE: X AS SELECT // Simple CTE: X AS SELECT
{ {
auto x = cte(sqlpp::alias::x).as(select(foo.id).from(foo).unconditionally()); auto x = cte(sqlpp::alias::x).as(select(foo.id).from(foo).unconditionally());
auto a = x.as(sqlpp::alias::a); auto a = x.as(sqlpp::alias::a);
using X = decltype(x); using X = decltype(x);
using R = decltype(make_table_ref(x)); using RX = decltype(make_table_ref(x));
using A = decltype(a); using A = decltype(a);
using RA = decltype(make_table_ref(a));
// CTE is used in WITH and in FROM
static_assert(sqlpp::is_cte<X>::value, ""); static_assert(sqlpp::is_cte<X>::value, "");
static_assert(not sqlpp::is_recursive_cte<X>::value, ""); static_assert(not sqlpp::is_recursive_cte<X>::value, "");
static_assert(sqlpp::is_table<X>::value, ""); static_assert(sqlpp::is_table<X>::value, "");
static_assert(sqlpp::required_ctes_of_t<X>::empty(), ""); static_assert(sqlpp::required_ctes_of_t<X>::empty(), "");
static_assert(std::is_same<sqlpp::provided_ctes_of_t<X>, sqlpp::detail::type_vector<R>>::value, ""); static_assert(std::is_same<sqlpp::provided_ctes_of_t<X>, sqlpp::detail::type_vector<RX>>::value, "");
// CTE reference is what is stored in from_t or join_t.
// While it refers to a CTE, it cannot be used as a CTE or table, i.e. with(rx) or from(ra) would not compile.
static_assert(not sqlpp::is_cte<RX>::value, "");
static_assert(not sqlpp::is_table<RX>::value, "");
// CTEs can be aliased (e.g. x AS a). This alias can be used as a table in FROM, but not as a CTE in WITH.
static_assert(not sqlpp::is_cte<A>::value, "");
static_assert(sqlpp::is_table<A>::value, "");
static_assert(std::is_same<A, RA>::value, "");
}
// Simple CTE with parameter
{
auto p = sqlpp::parameter(foo.id);
auto x = cte(sqlpp::alias::x).as(select(foo.id).from(foo).where(foo.id > p));
auto a = x.as(sqlpp::alias::a);
using X = decltype(x);
using RX = decltype(make_table_ref(x));
using A = decltype(a);
using RA = decltype(make_table_ref(a));
using P = decltype(p);
// CTE is used in WITH and in FROM
static_assert(sqlpp::is_cte<X>::value, "");
static_assert(not sqlpp::is_recursive_cte<X>::value, "");
static_assert(sqlpp::is_table<X>::value, "");
static_assert(sqlpp::required_ctes_of_t<X>::empty(), "");
static_assert(std::is_same<sqlpp::provided_ctes_of_t<X>, sqlpp::detail::type_vector<RX>>::value, "");
static_assert(std::is_same<sqlpp::parameters_of_t<X>, sqlpp::detail::type_vector<P>>::value, "");
// CTE reference is what is stored in from_t or join_t.
// While it refers to a CTE, it cannot be used as a CTE or table, i.e. with(rx) or from(ra) would not compile.
static_assert(not sqlpp::is_cte<RX>::value, "");
static_assert(not sqlpp::is_table<RX>::value, "");
static_assert(sqlpp::parameters_of_t<RX>::empty(), "");
// CTEs can be aliased (e.g. x AS a). This alias can be used as a table in FROM, but not as a CTE in WITH.
static_assert(not sqlpp::is_cte<A>::value, "");
static_assert(sqlpp::is_table<A>::value, "");
static_assert(std::is_same<A, RA>::value, "");
static_assert(sqlpp::parameters_of_t<RA>::empty(), "");
} }
// Non-recursive union CTE: X AS SELECT ... UNION ALL SELECT ... // Non-recursive union CTE: X AS SELECT ... UNION ALL SELECT ...

View File

@ -304,6 +304,8 @@ int main()
} }
} }
#warning: Test with CTEs
int main(int, char* []) int main(int, char* [])
{ {
single_table(); single_table();