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:
parent
fef1c3e426
commit
dc53fd5acc
@ -33,12 +33,12 @@
|
||||
|
||||
namespace sqlpp
|
||||
{
|
||||
#warning: It would be sufficient to store the NameTag here, not the whole NameTagProvider
|
||||
template <typename ValueType, typename NameType>
|
||||
struct parameter_t : public enable_comparison<parameter_t<ValueType, NameType>>
|
||||
{
|
||||
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 _instance_t = member_t<NameType, parameter_value_t<ValueType>>;
|
||||
@ -52,6 +52,12 @@ namespace sqlpp
|
||||
~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>
|
||||
struct value_type_of<parameter_t<ValueType, NameType>>
|
||||
{
|
||||
|
@ -40,8 +40,6 @@ namespace sqlpp
|
||||
template <typename Flag, typename Lhs, typename Rhs>
|
||||
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)
|
||||
{
|
||||
}
|
||||
@ -303,9 +301,6 @@ namespace sqlpp
|
||||
}
|
||||
};
|
||||
|
||||
template<typename NameTagProvider>
|
||||
struct is_table<cte_ref_t<NameTagProvider>> : public std::true_type{};
|
||||
|
||||
template<typename NameTagProvider>
|
||||
struct name_tag_of<cte_ref_t<NameTagProvider>> : public name_tag_of<NameTagProvider>
|
||||
{};
|
||||
|
@ -62,7 +62,7 @@ namespace sqlpp
|
||||
using _nodes = detail::type_vector<>;
|
||||
using _provided_ctes =
|
||||
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...>;
|
||||
|
||||
@ -80,6 +80,7 @@ namespace sqlpp
|
||||
using _consistency_check = consistent_t;
|
||||
};
|
||||
};
|
||||
#warning: Need traits here! And type tests for them
|
||||
|
||||
struct no_with_t
|
||||
{
|
||||
|
@ -64,6 +64,7 @@ namespace sqlpp
|
||||
}
|
||||
};
|
||||
|
||||
#warning: Why would we need this?
|
||||
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
|
||||
|
@ -69,7 +69,7 @@ namespace sqlpp
|
||||
using _nodes = detail::type_vector<Parts...>;
|
||||
|
||||
using _parameter_check =
|
||||
typename std::conditional<parameters_of<custom_query_t>::empty(),
|
||||
typename std::conditional<parameters_of_t<custom_query_t>::empty(),
|
||||
consistent_t,
|
||||
assert_no_parameters_t>::type;
|
||||
using _run_check = detail::get_first_if<is_inconsistent_t, consistent_t, _parameter_check>;
|
||||
|
@ -123,7 +123,7 @@ namespace sqlpp
|
||||
// - the select is complete (leaks no table requirements or cte requirements)
|
||||
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();
|
||||
}
|
||||
|
||||
@ -140,11 +140,11 @@ namespace sqlpp
|
||||
detail::make_intersect_set_t<required_tables_of_t<_result_type_provider>,
|
||||
_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
|
||||
|
||||
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 =
|
||||
typename std::conditional<_required_tables_of::empty(), consistent_t, assert_no_unknown_tables_t>::type;
|
||||
using _parameter_check = typename std::
|
||||
|
@ -404,26 +404,20 @@ namespace sqlpp
|
||||
template <typename KnownAggregates, typename T>
|
||||
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>
|
||||
struct parameters_of_impl
|
||||
{
|
||||
using type = typename parameters_of_impl<nodes_of_t<T>>::type;
|
||||
using type = typename parameters_of<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>
|
||||
struct parameters_of_impl<T, typename std::enable_if<std::is_class<typename T::_parameters>::value>::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;
|
||||
using parameters_of_t = typename parameters_of<T>::type;
|
||||
|
||||
// Something that can be used as a table
|
||||
template <typename T>
|
||||
|
@ -31,21 +31,68 @@ void test_cte()
|
||||
const auto foo = test::TabFoo{};
|
||||
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
|
||||
{
|
||||
auto x = cte(sqlpp::alias::x).as(select(foo.id).from(foo).unconditionally());
|
||||
auto a = x.as(sqlpp::alias::a);
|
||||
|
||||
using X = decltype(x);
|
||||
using R = decltype(make_table_ref(x));
|
||||
using RX = decltype(make_table_ref(x));
|
||||
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(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<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 ...
|
||||
|
@ -304,6 +304,8 @@ int main()
|
||||
}
|
||||
}
|
||||
|
||||
#warning: Test with CTEs
|
||||
|
||||
int main(int, char* [])
|
||||
{
|
||||
single_table();
|
||||
|
Loading…
Reference in New Issue
Block a user