mirror of
https://github.com/rbock/sqlpp11.git
synced 2024-11-15 20:31:16 +08:00
Can chain unions
And a few more checks
This commit is contained in:
parent
92e670118a
commit
61b0bd9ff8
@ -286,6 +286,7 @@ namespace sqlpp
|
|||||||
template<typename AliasProvider>
|
template<typename AliasProvider>
|
||||||
_alias_t<AliasProvider> as(const AliasProvider& aliasProvider) const
|
_alias_t<AliasProvider> as(const AliasProvider& aliasProvider) const
|
||||||
{
|
{
|
||||||
|
run_check_t<_statement_t>::_();
|
||||||
static_assert(_statement_t::_can_be_used_as_table(), "statement cannot be used as table, e.g. due to missing tables");
|
static_assert(_statement_t::_can_be_used_as_table(), "statement cannot be used as table, e.g. due to missing tables");
|
||||||
static_assert(logic::none_t<is_multi_column_t<Columns>::value...>::value, "cannot use multi-columns in sub selects");
|
static_assert(logic::none_t<is_multi_column_t<Columns>::value...>::value, "cannot use multi-columns in sub selects");
|
||||||
return _table_t<AliasProvider>(_get_statement()).as(aliasProvider);
|
return _table_t<AliasProvider>(_get_statement()).as(aliasProvider);
|
||||||
|
@ -107,6 +107,9 @@ namespace sqlpp
|
|||||||
template<typename Expression>
|
template<typename Expression>
|
||||||
using _no_unknown_tables = detail::is_subset_of<required_tables_of<Expression>, _known_tables>;
|
using _no_unknown_tables = detail::is_subset_of<required_tables_of<Expression>, _known_tables>;
|
||||||
|
|
||||||
|
template<template<typename> class Predicate>
|
||||||
|
using any_t = logic::any_t<Predicate<Policies>::value...>;
|
||||||
|
|
||||||
// The tables not covered by the from.
|
// The tables not covered by the from.
|
||||||
using _required_tables = detail::make_difference_set_t<
|
using _required_tables = detail::make_difference_set_t<
|
||||||
_all_required_tables,
|
_all_required_tables,
|
||||||
@ -130,7 +133,7 @@ namespace sqlpp
|
|||||||
// - the select is complete (leaks no tables)
|
// - the select is complete (leaks no tables)
|
||||||
static constexpr bool _can_be_used_as_table()
|
static constexpr bool _can_be_used_as_table()
|
||||||
{
|
{
|
||||||
return is_select_column_list_t<_result_type_provider>::value
|
return has_result_row_t<_statement_t>::value
|
||||||
and _required_tables::size::value == 0
|
and _required_tables::size::value == 0
|
||||||
and _required_ctes::size::value == 0
|
and _required_ctes::size::value == 0
|
||||||
? true
|
? true
|
||||||
@ -183,15 +186,14 @@ namespace sqlpp
|
|||||||
{
|
{
|
||||||
using _policies_t = typename detail::statement_policies_t<Db, Policies...>;
|
using _policies_t = typename detail::statement_policies_t<Db, Policies...>;
|
||||||
|
|
||||||
|
using _consistency_check = detail::get_first_if<is_inconsistent_t, consistent_t,
|
||||||
|
typename Policies::template _base_t<_policies_t>::_consistency_check...,
|
||||||
|
typename _policies_t::_table_check,
|
||||||
|
typename _policies_t::_cte_check>;
|
||||||
using _run_check = detail::get_first_if<is_inconsistent_t, consistent_t,
|
using _run_check = detail::get_first_if<is_inconsistent_t, consistent_t,
|
||||||
typename _policies_t::_parameter_check,
|
typename _policies_t::_parameter_check,
|
||||||
typename Policies::template _base_t<_policies_t>::_consistency_check...,
|
_consistency_check>;
|
||||||
typename _policies_t::_table_check,
|
using _prepare_check = _consistency_check;
|
||||||
typename _policies_t::_cte_check>;
|
|
||||||
using _prepare_check = detail::get_first_if<is_inconsistent_t, consistent_t,
|
|
||||||
typename Policies::template _base_t<_policies_t>::_consistency_check...,
|
|
||||||
typename _policies_t::_table_check,
|
|
||||||
typename _policies_t::_cte_check>;
|
|
||||||
|
|
||||||
using _result_type_provider = typename _policies_t::_result_type_provider;
|
using _result_type_provider = typename _policies_t::_result_type_provider;
|
||||||
template<typename Composite>
|
template<typename Composite>
|
||||||
|
@ -339,6 +339,57 @@ namespace sqlpp
|
|||||||
template<typename Context, typename T>
|
template<typename Context, typename T>
|
||||||
using serialize_check_t = typename serialize_check<Context, T>::type;
|
using serialize_check_t = typename serialize_check<Context, T>::type;
|
||||||
|
|
||||||
|
template<typename Statement, typename Enable = void>
|
||||||
|
struct has_result_row_impl
|
||||||
|
{
|
||||||
|
using type = std::false_type;
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename Statement>
|
||||||
|
struct has_result_row_impl<Statement,
|
||||||
|
typename std::enable_if<
|
||||||
|
not wrong_t<typename Statement::template _result_methods_t<Statement>::template _result_row_t<void>>::value,
|
||||||
|
void>::type>
|
||||||
|
{
|
||||||
|
using type = std::true_type;
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename Statement>
|
||||||
|
using has_result_row_t = typename has_result_row_impl<Statement>::type;
|
||||||
|
|
||||||
|
template<typename Statement, typename Enable = void>
|
||||||
|
struct get_result_row_impl
|
||||||
|
{
|
||||||
|
using type = void;
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename Statement>
|
||||||
|
struct get_result_row_impl<Statement,
|
||||||
|
typename std::enable_if<
|
||||||
|
not wrong_t<typename Statement::template _result_methods_t<Statement>::template _result_row_t<void>>::value,
|
||||||
|
void>::type>
|
||||||
|
{
|
||||||
|
using type = typename Statement::template _result_methods_t<Statement>::template _result_row_t<void>;
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename Statement>
|
||||||
|
using get_result_row_t = typename get_result_row_impl<Statement>::type;
|
||||||
|
|
||||||
|
template<typename Statement, template<typename> class Predicate, typename Enable=void>
|
||||||
|
struct has_policy_impl
|
||||||
|
{
|
||||||
|
using type = std::false_type;
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename Statement, template<typename> class Predicate>
|
||||||
|
struct has_policy_impl<Statement, Predicate, typename std::enable_if<is_statement_t<Statement>::value>::type>
|
||||||
|
{
|
||||||
|
using type = std::true_type;
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename Statement, template<typename> class Predicate>
|
||||||
|
using has_policy_t = typename has_policy_impl<Statement, Predicate>::type;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -37,42 +37,6 @@
|
|||||||
|
|
||||||
namespace sqlpp
|
namespace sqlpp
|
||||||
{
|
{
|
||||||
template<typename Statement, typename Enable = void>
|
|
||||||
struct has_result_row_impl
|
|
||||||
{
|
|
||||||
using type = std::false_type;
|
|
||||||
};
|
|
||||||
|
|
||||||
template<typename Statement>
|
|
||||||
struct has_result_row_impl<Statement,
|
|
||||||
typename std::enable_if<
|
|
||||||
not wrong_t<typename Statement::template _result_methods_t<Statement>::template _result_row_t<void>>::value,
|
|
||||||
void>::type>
|
|
||||||
{
|
|
||||||
using type = std::true_type;
|
|
||||||
};
|
|
||||||
|
|
||||||
template<typename Statement>
|
|
||||||
using has_result_row_t = typename has_result_row_impl<Statement>::type;
|
|
||||||
|
|
||||||
template<typename Statement, typename Enable = void>
|
|
||||||
struct get_result_row_impl
|
|
||||||
{
|
|
||||||
using type = void;
|
|
||||||
};
|
|
||||||
|
|
||||||
template<typename Statement>
|
|
||||||
struct get_result_row_impl<Statement,
|
|
||||||
typename std::enable_if<
|
|
||||||
not wrong_t<typename Statement::template _result_methods_t<Statement>::template _result_row_t<void>>::value,
|
|
||||||
void>::type>
|
|
||||||
{
|
|
||||||
using type = typename Statement::template _result_methods_t<Statement>::template _result_row_t<void>;
|
|
||||||
};
|
|
||||||
|
|
||||||
template<typename Statement>
|
|
||||||
using get_result_row_t = typename get_result_row_impl<Statement>::type;
|
|
||||||
|
|
||||||
|
|
||||||
struct no_union_t;
|
struct no_union_t;
|
||||||
|
|
||||||
@ -119,7 +83,7 @@ namespace sqlpp
|
|||||||
template<typename Database, typename Flag, typename Lhs, typename Rhs>
|
template<typename Database, typename Flag, typename Lhs, typename Rhs>
|
||||||
struct union_t
|
struct union_t
|
||||||
{
|
{
|
||||||
using _traits = make_traits<no_value_t, tag::is_union, tag::is_select_column_list, tag::is_return_value>;
|
using _traits = make_traits<no_value_t, tag::is_union, tag::is_return_value>;
|
||||||
using _recursive_traits = make_recursive_traits<Lhs, Rhs>;
|
using _recursive_traits = make_recursive_traits<Lhs, Rhs>;
|
||||||
|
|
||||||
using _alias_t = struct{};
|
using _alias_t = struct{};
|
||||||
@ -145,9 +109,9 @@ namespace sqlpp
|
|||||||
_impl_t<Policies>& operator()() { return union_; }
|
_impl_t<Policies>& operator()() { return union_; }
|
||||||
const _impl_t<Policies>& operator()() const { return union_; }
|
const _impl_t<Policies>& operator()() const { return union_; }
|
||||||
|
|
||||||
using _selected_columns_t = decltype(union_._data._lhs.selected_columns);
|
using _selected_columns_t = typename std::decay<decltype(union_._data._lhs.get_selected_columns())>::type;
|
||||||
_selected_columns_t& get_selected_columns() { return union_._data._lhs.selected_columns;}
|
_selected_columns_t& get_selected_columns() { return union_._data._lhs.get_selected_columns(); }
|
||||||
const _selected_columns_t& get_selected_columns() const { return union_._data._lhs.selected_columns; }
|
const _selected_columns_t& get_selected_columns() const { return union_._data._lhs.get_selected_columns(); }
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
static auto _get_member(T t) -> decltype(t.union_)
|
static auto _get_member(T t) -> decltype(t.union_)
|
||||||
@ -155,7 +119,9 @@ namespace sqlpp
|
|||||||
return t.union_;
|
return t.union_;
|
||||||
}
|
}
|
||||||
|
|
||||||
using _consistency_check = consistent_t;
|
using _consistency_check = detail::get_first_if<is_inconsistent_t, consistent_t,
|
||||||
|
typename Lhs::_consistency_check,
|
||||||
|
typename Rhs::_consistency_check>;
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename Statement>
|
template<typename Statement>
|
||||||
@ -208,8 +174,8 @@ namespace sqlpp
|
|||||||
auto union_distinct(Rhs rhs) const
|
auto union_distinct(Rhs rhs) const
|
||||||
-> _new_statement_t<_check<Rhs>, union_t<void, distinct_t, derived_statement_t<Policies>, Rhs>>
|
-> _new_statement_t<_check<Rhs>, union_t<void, distinct_t, derived_statement_t<Policies>, Rhs>>
|
||||||
{
|
{
|
||||||
#warning: make sure that Rhs is a select, not a uninon
|
|
||||||
static_assert(is_statement_t<Rhs>::value, "argument of union call has to be a statement");
|
static_assert(is_statement_t<Rhs>::value, "argument of union call has to be a 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_t<Rhs>::value, "argument of a union has to be a (complete) select statement");
|
static_assert(has_result_row_t<Rhs>::value, "argument of a union has to be a (complete) select statement");
|
||||||
static_assert(has_result_row_t<derived_statement_t<Policies>>::value, "left hand side argument of a union has to be a (complete) select statement");
|
static_assert(has_result_row_t<derived_statement_t<Policies>>::value, "left hand side argument of a union has to be a (complete) select statement");
|
||||||
static_assert(std::is_same<get_result_row_t<derived_statement_t<Policies>>, get_result_row_t<Rhs>>::value, "both select statements in a union have to have the same result columns (type and name)");
|
static_assert(std::is_same<get_result_row_t<derived_statement_t<Policies>>, get_result_row_t<Rhs>>::value, "both select statements in a union have to have the same result columns (type and name)");
|
||||||
|
@ -37,12 +37,17 @@ int main()
|
|||||||
test::TabBar t;
|
test::TabBar t;
|
||||||
test::TabFoo f;
|
test::TabFoo f;
|
||||||
|
|
||||||
db(select(t.alpha).from(t).union_distinct(select(f.epsilon.as(t.alpha)).from(f)));
|
db(select(t.alpha).from(t).where(true)
|
||||||
db(select(t.alpha).from(t).union_all(select(f.epsilon.as(t.alpha)).from(f)));
|
.union_distinct(select(f.epsilon.as(t.alpha)).from(f).where(true)));
|
||||||
|
db(select(t.alpha).from(t).where(true)
|
||||||
|
.union_all(select(f.epsilon.as(t.alpha)).from(f).where(true)));
|
||||||
|
|
||||||
auto u = select(t.alpha).from(t).union_all(select(f.epsilon.as(t.alpha)).from(f)).as(sqlpp::alias::u);
|
auto u = select(t.alpha).from(t).where(true).union_all(select(f.epsilon.as(t.alpha)).from(f).where(true)).as(sqlpp::alias::u);
|
||||||
|
|
||||||
db(select(all_of(u)).from(u).union_all(select(t.delta.as(t.alpha)).from(t)));
|
db(select(all_of(u)).from(u).where(true).union_all(select(t.delta.as(t.alpha)).from(t).where(true)));
|
||||||
|
db(select(u.alpha).from(u).where(true).union_all(select(t.delta.as(t.alpha)).from(t).where(true)));
|
||||||
|
|
||||||
|
db(select(t.alpha).from(t).where(true).union_all(select(t.alpha).from(t).where(true)).union_all(select(t.alpha).from(t).where(true)));
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user