0
0
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:
rbock 2015-01-15 19:43:56 +01:00
parent 92e670118a
commit 61b0bd9ff8
5 changed files with 79 additions and 54 deletions

View File

@ -286,6 +286,7 @@ namespace sqlpp
template<typename AliasProvider>
_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(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);

View File

@ -107,6 +107,9 @@ namespace sqlpp
template<typename Expression>
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.
using _required_tables = detail::make_difference_set_t<
_all_required_tables,
@ -130,7 +133,7 @@ namespace sqlpp
// - the select is complete (leaks no tables)
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_ctes::size::value == 0
? true
@ -183,15 +186,14 @@ namespace sqlpp
{
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,
typename _policies_t::_parameter_check,
typename Policies::template _base_t<_policies_t>::_consistency_check...,
typename _policies_t::_table_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>;
_consistency_check>;
using _prepare_check = _consistency_check;
using _result_type_provider = typename _policies_t::_result_type_provider;
template<typename Composite>

View File

@ -339,6 +339,57 @@ namespace sqlpp
template<typename Context, typename T>
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

View File

@ -37,42 +37,6 @@
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;
@ -119,7 +83,7 @@ namespace sqlpp
template<typename Database, typename Flag, typename Lhs, typename Rhs>
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 _alias_t = struct{};
@ -145,9 +109,9 @@ namespace sqlpp
_impl_t<Policies>& operator()() { return union_; }
const _impl_t<Policies>& operator()() const { return union_; }
using _selected_columns_t = decltype(union_._data._lhs.selected_columns);
_selected_columns_t& get_selected_columns() { return union_._data._lhs.selected_columns;}
const _selected_columns_t& get_selected_columns() const { return 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.get_selected_columns(); }
const _selected_columns_t& get_selected_columns() const { return union_._data._lhs.get_selected_columns(); }
template<typename T>
static auto _get_member(T t) -> decltype(t.union_)
@ -155,7 +119,9 @@ namespace sqlpp
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>
@ -208,8 +174,8 @@ namespace sqlpp
auto union_distinct(Rhs rhs) const
-> _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(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<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)");

View File

@ -37,12 +37,17 @@ int main()
test::TabBar t;
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).union_all(select(f.epsilon.as(t.alpha)).from(f)));
db(select(t.alpha).from(t).where(true)
.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;
}