mirror of
https://github.com/rbock/sqlpp11.git
synced 2024-11-16 12:51:13 +08:00
Add support for dynamic union in CTEs
This commit is contained in:
parent
6128b78f28
commit
7cdcf0f172
@ -68,6 +68,15 @@ namespace sqlpp
|
|||||||
return to_sql_string(context, t._lhs) + " UNION " + to_sql_string(context, Flag{}) + to_sql_string(context, t._rhs);
|
return to_sql_string(context, t._lhs) + " UNION " + to_sql_string(context, Flag{}) + to_sql_string(context, t._rhs);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <typename Context, typename Flag, typename Lhs, typename Rhs>
|
||||||
|
auto to_sql_string(Context& context, const cte_union_t<Flag, Lhs, dynamic_t<Rhs>>& t) -> std::string
|
||||||
|
{
|
||||||
|
if (t._rhs._condition){
|
||||||
|
return to_sql_string(context, t._lhs) + " UNION " + to_sql_string(context, Flag{}) + to_sql_string(context, t._rhs._expr);
|
||||||
|
}
|
||||||
|
return to_sql_string(context, t._lhs);
|
||||||
|
}
|
||||||
|
|
||||||
template <typename NameTagProvider, typename Statement, typename... FieldSpecs>
|
template <typename NameTagProvider, typename Statement, typename... FieldSpecs>
|
||||||
struct cte_t;
|
struct cte_t;
|
||||||
|
|
||||||
@ -116,14 +125,14 @@ namespace sqlpp
|
|||||||
using union_cte_impl_t = typename union_cte_impl<Check, Union>::type;
|
using union_cte_impl_t = typename union_cte_impl<Check, Union>::type;
|
||||||
|
|
||||||
SQLPP_PORTABLE_STATIC_ASSERT(assert_cte_union_args_are_statements_t, "argument for union() must be a statement");
|
SQLPP_PORTABLE_STATIC_ASSERT(assert_cte_union_args_are_statements_t, "argument for union() must be a statement");
|
||||||
template <typename... T>
|
template <typename T>
|
||||||
struct check_cte_union
|
struct check_cte_union
|
||||||
{
|
{
|
||||||
using type = static_combined_check_t<
|
using type = static_combined_check_t<
|
||||||
static_check_t<logic::all<is_statement_t<T>::value...>::value, assert_cte_union_args_are_statements_t>>;
|
static_check_t<is_statement_t<T>::value, assert_cte_union_args_are_statements_t>>;
|
||||||
};
|
};
|
||||||
template <typename... T>
|
template <typename T>
|
||||||
using check_cte_union_t = typename check_cte_union<T...>::type;
|
using check_cte_union_t = typename check_cte_union<remove_dynamic_t<T>>::type;
|
||||||
|
|
||||||
// cte_member is a helper to add column data members to `cte_t`.
|
// cte_member is a helper to add column data members to `cte_t`.
|
||||||
template <typename NameTagProvider, typename FieldSpec>
|
template <typename NameTagProvider, typename FieldSpec>
|
||||||
@ -194,14 +203,15 @@ namespace sqlpp
|
|||||||
-> union_cte_impl_t<check_cte_union_t<Rhs>,
|
-> union_cte_impl_t<check_cte_union_t<Rhs>,
|
||||||
cte_t<NameTagProvider, cte_union_t<distinct_t, Statement, Rhs>, FieldSpecs...>>
|
cte_t<NameTagProvider, cte_union_t<distinct_t, Statement, Rhs>, FieldSpecs...>>
|
||||||
{
|
{
|
||||||
static_assert(is_statement_t<Rhs>::value, "argument of union call has to be a statement");
|
using _rhs = remove_dynamic_t<Rhs>;
|
||||||
static_assert(has_policy_t<Rhs, is_select_t>::value, "argument of union call has to be a select");
|
static_assert(is_statement_t<_rhs>::value, "argument of union call has to be a statement");
|
||||||
static_assert(has_result_row<Rhs>::value, "argument of a clause/union.has to be a (complete) select statement");
|
static_assert(has_policy_t<_rhs, is_select_t>::value, "argument of union call has to be a select");
|
||||||
|
static_assert(has_result_row<_rhs>::value, "argument of a clause/union.has to be a (complete) select statement");
|
||||||
|
|
||||||
static_assert(std::is_same<_result_row_t, get_result_row_t<Rhs>>::value,
|
static_assert(std::is_same<_result_row_t, get_result_row_t<_rhs>>::value,
|
||||||
"both select statements in a clause/union.have to have the same result columns (type and name)");
|
"both select statements in a clause/union.have to have the same result columns (type and name)");
|
||||||
|
|
||||||
return _union_impl<void, distinct_t>(check_cte_union_t<Rhs>{}, rhs);
|
return _union_impl<distinct_t>(check_cte_union_t<Rhs>{}, rhs);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename Rhs>
|
template <typename Rhs>
|
||||||
@ -209,11 +219,12 @@ namespace sqlpp
|
|||||||
-> union_cte_impl_t<check_cte_union_t<Rhs>,
|
-> union_cte_impl_t<check_cte_union_t<Rhs>,
|
||||||
cte_t<NameTagProvider, cte_union_t<all_t, Statement, Rhs>, FieldSpecs...>>
|
cte_t<NameTagProvider, cte_union_t<all_t, Statement, Rhs>, FieldSpecs...>>
|
||||||
{
|
{
|
||||||
static_assert(is_statement_t<Rhs>::value, "argument of union call has to be a statement");
|
using _rhs = remove_dynamic_t<Rhs>;
|
||||||
static_assert(has_policy_t<Rhs, is_select_t>::value, "argument of union call has to be a select");
|
static_assert(is_statement_t<_rhs>::value, "argument of union call has to be a statement");
|
||||||
static_assert(has_result_row<Rhs>::value, "argument of a clause/union.has to be a (complete) select statement");
|
static_assert(has_policy_t<_rhs, is_select_t>::value, "argument of union call has to be a select");
|
||||||
|
static_assert(has_result_row<_rhs>::value, "argument of a clause/union.has to be a (complete) select statement");
|
||||||
|
|
||||||
static_assert(std::is_same<_result_row_t, get_result_row_t<Rhs>>::value,
|
static_assert(std::is_same<_result_row_t, get_result_row_t<_rhs>>::value,
|
||||||
"both select statements in a clause/union.have to have the same result columns (type and name)");
|
"both select statements in a clause/union.have to have the same result columns (type and name)");
|
||||||
|
|
||||||
return _union_impl<all_t>(check_cte_union_t<Rhs>{}, rhs);
|
return _union_impl<all_t>(check_cte_union_t<Rhs>{}, rhs);
|
||||||
@ -272,6 +283,18 @@ namespace sqlpp
|
|||||||
using type = Statement;
|
using type = Statement;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template <typename NameTagProvider, typename Statement, typename... ColumnSpecs>
|
||||||
|
struct provided_tables_of<cte_t<NameTagProvider, Statement, ColumnSpecs...>>
|
||||||
|
{
|
||||||
|
using type = sqlpp::detail::type_vector<cte_ref_t<NameTagProvider>>;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename NameTagProvider, typename Statement, typename... ColumnSpecs>
|
||||||
|
struct provided_static_tables_of<cte_t<NameTagProvider, Statement, ColumnSpecs...>> : public provided_tables_of<cte_t<NameTagProvider, Statement, ColumnSpecs...>>
|
||||||
|
{
|
||||||
|
};
|
||||||
|
|
||||||
|
#warning: Should enough if with_t provides ctes?
|
||||||
template <typename NameTagProvider, typename Statement, typename... ColumnSpecs>
|
template <typename NameTagProvider, typename Statement, typename... ColumnSpecs>
|
||||||
struct provided_ctes_of<cte_t<NameTagProvider, Statement, ColumnSpecs...>>
|
struct provided_ctes_of<cte_t<NameTagProvider, Statement, ColumnSpecs...>>
|
||||||
{
|
{
|
||||||
|
@ -63,7 +63,7 @@ int main(int, char* [])
|
|||||||
SQLPP_COMPARE(all_of(a), "a.id");
|
SQLPP_COMPARE(all_of(a), "a.id");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Recursive union CTE: X AS SELECT ... UNION ALL SELECT ... FROM X ...
|
// Recursive CTE: X AS SELECT ... UNION ALL SELECT ... FROM X ...
|
||||||
{
|
{
|
||||||
const auto x_base = cte(sqlpp::alias::x).as(select(sqlpp::value(0).as(sqlpp::alias::a)));
|
const auto x_base = cte(sqlpp::alias::x).as(select(sqlpp::value(0).as(sqlpp::alias::a)));
|
||||||
const auto x = x_base.union_all(select((x_base.a + 1).as(sqlpp::alias::a)).from(x_base).where(x_base.a < 10));
|
const auto x = x_base.union_all(select((x_base.a + 1).as(sqlpp::alias::a)).from(x_base).where(x_base.a < 10));
|
||||||
@ -91,5 +91,27 @@ int main(int, char* [])
|
|||||||
SQLPP_COMPARE(all_of(z), "z.id, z.a");
|
SQLPP_COMPARE(all_of(z), "z.id, z.a");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Dynamically recursive CTE: X AS SELECT ... UNION ALL SELECT ... FROM X ...
|
||||||
|
{
|
||||||
|
const auto x_base = cte(sqlpp::alias::x).as(select(sqlpp::value(0).as(sqlpp::alias::a)));
|
||||||
|
auto x = x_base.union_all(dynamic(true, select((x_base.a + 1).as(sqlpp::alias::a)).from(x_base).where(x_base.a < 10)));
|
||||||
|
|
||||||
|
SQLPP_COMPARE(x, "x AS (SELECT 0 AS a UNION ALL SELECT (x.a + 1) AS a FROM x WHERE x.a < 10)");
|
||||||
|
|
||||||
|
x = x_base.union_all(dynamic(false, select((x_base.a + 1).as(sqlpp::alias::a)).from(x_base).where(x_base.a < 10)));
|
||||||
|
SQLPP_COMPARE(x, "x AS (SELECT 0 AS a)");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Dynamically recursive CTE: X AS SELECT ... UNION DISTINCT SELECT ... FROM X ...
|
||||||
|
{
|
||||||
|
const auto x_base = cte(sqlpp::alias::x).as(select(sqlpp::value(0).as(sqlpp::alias::a)));
|
||||||
|
auto x = x_base.union_distinct(dynamic(true, select((x_base.a + 1).as(sqlpp::alias::a)).from(x_base).where(x_base.a < 10)));
|
||||||
|
|
||||||
|
SQLPP_COMPARE(x, "x AS (SELECT 0 AS a UNION DISTINCT SELECT (x.a + 1) AS a FROM x WHERE x.a < 10)");
|
||||||
|
|
||||||
|
x = x_base.union_distinct(dynamic(false, select((x_base.a + 1).as(sqlpp::alias::a)).from(x_base).where(x_base.a < 10)));
|
||||||
|
SQLPP_COMPARE(x, "x AS (SELECT 0 AS a)");
|
||||||
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user