0
0
mirror of https://github.com/rbock/sqlpp11.git synced 2024-11-16 04:47:18 +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> 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);

View File

@ -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>

View File

@ -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

View File

@ -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)");

View File

@ -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;
} }