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

More cte tests

This commit is contained in:
Roland Bock 2024-11-03 12:21:53 +01:00
parent 25879d1dc0
commit 6128b78f28
2 changed files with 91 additions and 16 deletions

View File

@ -161,6 +161,13 @@ namespace sqlpp
{ {
}; };
template <typename NameTagProvider, typename NewNameTagProvider, typename... ColumnSpecs>
struct required_ctes_of<cte_as_t<NameTagProvider, NewNameTagProvider, ColumnSpecs...>>
{
// An aliased CTE requires the original CTE from the WITH clause.
using type = sqlpp::detail::type_vector<cte_ref_t<NameTagProvider>>;
};
template <typename Context, typename NameTagProvider, typename NewNameTagProvider, typename... ColumnSpecs> template <typename Context, typename NameTagProvider, typename NewNameTagProvider, typename... ColumnSpecs>
auto to_sql_string(Context& context, const cte_as_t<NameTagProvider, NewNameTagProvider, ColumnSpecs...>&) -> std::string auto to_sql_string(Context& context, const cte_as_t<NameTagProvider, NewNameTagProvider, ColumnSpecs...>&) -> std::string
{ {

View File

@ -50,16 +50,23 @@ void test_cte()
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<RX>>::value, ""); static_assert(std::is_same<sqlpp::provided_ctes_of_t<X>, sqlpp::detail::type_vector<RX>>::value, "");
static_assert(sqlpp::parameters_of_t<X>::empty(), "");
// CTE reference is what is stored in from_t or join_t. // 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. // 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_cte<RX>::value, "");
static_assert(not sqlpp::is_table<RX>::value, ""); static_assert(not sqlpp::is_table<RX>::value, "");
static_assert(std::is_same<sqlpp::provided_ctes_of_t<RX>, sqlpp::detail::type_vector<>>::value, "");
static_assert(std::is_same<sqlpp::required_ctes_of_t<RX>, sqlpp::detail::type_vector<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. // 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(not sqlpp::is_cte<A>::value, "");
static_assert(sqlpp::is_table<A>::value, ""); static_assert(sqlpp::is_table<A>::value, "");
static_assert(std::is_same<A, RA>::value, ""); static_assert(std::is_same<A, RA>::value, "");
static_assert(std::is_same<sqlpp::provided_ctes_of_t<RA>, sqlpp::detail::type_vector<>>::value, "");
static_assert(std::is_same<sqlpp::required_ctes_of_t<RA>, sqlpp::detail::type_vector<RX>>::value, "");
static_assert(sqlpp::parameters_of_t<RA>::empty(), "");
} }
// Simple CTE with parameter // Simple CTE with parameter
@ -70,7 +77,6 @@ void test_cte()
using X = decltype(x); using X = decltype(x);
using RX = decltype(make_table_ref(x)); using RX = decltype(make_table_ref(x));
using A = decltype(a);
using RA = decltype(make_table_ref(a)); using RA = decltype(make_table_ref(a));
using P = decltype(p); using P = decltype(p);
@ -82,16 +88,8 @@ void test_cte()
static_assert(std::is_same<sqlpp::provided_ctes_of_t<X>, sqlpp::detail::type_vector<RX>>::value, ""); 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, ""); 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. // Neither CTE reference nor alias carry the parameter.
// While it refers to a CTE, it cannot be used as a CTE or table, i.e. with(rx) or from(rx) 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(), ""); 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(), ""); static_assert(sqlpp::parameters_of_t<RA>::empty(), "");
} }
@ -100,21 +98,91 @@ void test_cte()
auto x = auto x =
cte(sqlpp::alias::x) cte(sqlpp::alias::x)
.as(select(foo.id).from(foo).unconditionally().union_all(select(bar.id).from(bar).unconditionally())); .as(select(foo.id).from(foo).unconditionally().union_all(select(bar.id).from(bar).unconditionally()));
auto a = x.as(sqlpp::alias::a);
using X = decltype(x);
using RX = decltype(make_table_ref(x));
// 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(sqlpp::parameters_of_t<X>::empty(), "");
} }
// Recursive union CTE: X AS SELECT ... UNION ALL SELECT ... FROM X ... // Recursive union CTE: X AS SELECT ... UNION ALL SELECT ... FROM X ...
{ {
auto p = sqlpp::parameter(foo.id);
auto x_base = cte(sqlpp::alias::x).as(select(sqlpp::value(0).as(sqlpp::alias::a))); auto x_base = cte(sqlpp::alias::x).as(select(sqlpp::value(0).as(sqlpp::alias::a)));
auto x = x_base.union_all(select((x_base.a + 1).as(sqlpp::alias::a)).from(x_base).where(x_base.a < 10)); auto x = x_base.union_all(select((x_base.a + 1).as(sqlpp::alias::a)).from(x_base).where(x_base.a < p));
auto y = x.as(sqlpp::alias::y);
using X = decltype(x);
using RX = decltype(make_table_ref(x));
using P = decltype(p);
// CTE is used in WITH and in FROM
static_assert(sqlpp::is_cte<X>::value, "");
static_assert(sqlpp::is_recursive_cte<X>::value, "");
static_assert(sqlpp::is_table<X>::value, "");
static_assert(std::is_same<sqlpp::required_ctes_of_t<X>, sqlpp::detail::type_vector<RX>>::value, "");
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, "");
} }
// A CTE depending on another CTE // A CTE depending on another CTE
{ {
auto x = cte(sqlpp::alias::x).as(select(foo.id).from(foo).unconditionally()); auto pb = sqlpp::parameter(foo.intN);
auto y = cte(sqlpp::alias::y).as(select(x.id, sqlpp::value(7).as(sqlpp::alias::a)).from(x).unconditionally()); auto p = sqlpp::parameter(foo.id);
auto z = y.as(sqlpp::alias::z); auto b = cte(sqlpp::alias::b).as(select(foo.id).from(foo).where(foo.id != pb));
auto x = cte(sqlpp::alias::y).as(select(b.id, sqlpp::value(7).as(sqlpp::alias::a)).from(b).where(b.id > p));
auto a = x.as(sqlpp::alias::a);
using RB = decltype(make_table_ref(b));
using X = decltype(x);
using RX = decltype(make_table_ref(x));
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(std::is_same<sqlpp::required_ctes_of_t<X>, sqlpp::detail::type_vector<RB>>::value, "");
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, "");
// Neither CTE reference nor alias carry the dependency.
static_assert(std::is_same<sqlpp::required_ctes_of_t<RA>, sqlpp::detail::type_vector<RX>>::value, "");
static_assert(std::is_same<sqlpp::required_ctes_of_t<RX>, sqlpp::detail::type_vector<RX>>::value, "");
}
// A recursive CTE depending on another CTE
{
auto pb = sqlpp::parameter(foo.intN);
auto p = sqlpp::parameter(foo.id);
auto b = cte(sqlpp::alias::b).as(select(foo.id.as(sqlpp::alias::a)).from(foo).where(foo.id != pb));
auto x_base = cte(sqlpp::alias::x).as(select(b.a).from(b).unconditionally());
auto x = x_base.union_all(select((x_base.a + 1).as(sqlpp::alias::a)).from(x_base).where(x_base.a < p));
auto a = x.as(sqlpp::alias::a);
using RB = decltype(make_table_ref(b));
using X = decltype(x);
using RX = decltype(make_table_ref(x));
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(sqlpp::is_recursive_cte<X>::value, "");
static_assert(sqlpp::is_table<X>::value, "");
static_assert(std::is_same<sqlpp::required_ctes_of_t<X>, sqlpp::detail::type_vector<RB, RX>>::value, "");
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, "");
// Neither CTE reference nor alias carry the dependency.
static_assert(std::is_same<sqlpp::required_ctes_of_t<RA>, sqlpp::detail::type_vector<RX>>::value, "");
static_assert(std::is_same<sqlpp::required_ctes_of_t<RX>, sqlpp::detail::type_vector<RX>>::value, "");
} }
} }