diff --git a/include/sqlpp11/select_column_list.h b/include/sqlpp11/select_column_list.h index 76a61c76..727e7513 100644 --- a/include/sqlpp11/select_column_list.h +++ b/include/sqlpp11/select_column_list.h @@ -286,6 +286,7 @@ namespace sqlpp template _alias_t 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::value...>::value, "cannot use multi-columns in sub selects"); return _table_t(_get_statement()).as(aliasProvider); diff --git a/include/sqlpp11/statement.h b/include/sqlpp11/statement.h index 02aaca64..3b4f5b56 100644 --- a/include/sqlpp11/statement.h +++ b/include/sqlpp11/statement.h @@ -107,6 +107,9 @@ namespace sqlpp template using _no_unknown_tables = detail::is_subset_of, _known_tables>; + template class Predicate> + using any_t = logic::any_t::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; + using _consistency_check = detail::get_first_if::_consistency_check..., + typename _policies_t::_table_check, + typename _policies_t::_cte_check>; using _run_check = detail::get_first_if::_consistency_check..., - typename _policies_t::_table_check, - typename _policies_t::_cte_check>; - using _prepare_check = detail::get_first_if::_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 diff --git a/include/sqlpp11/type_traits.h b/include/sqlpp11/type_traits.h index 4cf352ec..31f6a68e 100644 --- a/include/sqlpp11/type_traits.h +++ b/include/sqlpp11/type_traits.h @@ -339,6 +339,57 @@ namespace sqlpp template using serialize_check_t = typename serialize_check::type; + template + struct has_result_row_impl + { + using type = std::false_type; + }; + + template + struct has_result_row_impl::template _result_row_t>::value, + void>::type> + { + using type = std::true_type; + }; + + template + using has_result_row_t = typename has_result_row_impl::type; + + template + struct get_result_row_impl + { + using type = void; + }; + + template + struct get_result_row_impl::template _result_row_t>::value, + void>::type> + { + using type = typename Statement::template _result_methods_t::template _result_row_t; + }; + + template + using get_result_row_t = typename get_result_row_impl::type; + + template class Predicate, typename Enable=void> + struct has_policy_impl + { + using type = std::false_type; + }; + + template class Predicate> + struct has_policy_impl::value>::type> + { + using type = std::true_type; + }; + + template class Predicate> + using has_policy_t = typename has_policy_impl::type; + } #endif diff --git a/include/sqlpp11/union.h b/include/sqlpp11/union.h index 56559421..d68ab63b 100644 --- a/include/sqlpp11/union.h +++ b/include/sqlpp11/union.h @@ -37,42 +37,6 @@ namespace sqlpp { - template - struct has_result_row_impl - { - using type = std::false_type; - }; - - template - struct has_result_row_impl::template _result_row_t>::value, - void>::type> - { - using type = std::true_type; - }; - - template - using has_result_row_t = typename has_result_row_impl::type; - - template - struct get_result_row_impl - { - using type = void; - }; - - template - struct get_result_row_impl::template _result_row_t>::value, - void>::type> - { - using type = typename Statement::template _result_methods_t::template _result_row_t; - }; - - template - using get_result_row_t = typename get_result_row_impl::type; - struct no_union_t; @@ -119,7 +83,7 @@ namespace sqlpp template struct union_t { - using _traits = make_traits; + using _traits = make_traits; using _recursive_traits = make_recursive_traits; using _alias_t = struct{}; @@ -145,9 +109,9 @@ namespace sqlpp _impl_t& operator()() { return union_; } const _impl_t& 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::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 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; }; template @@ -208,8 +174,8 @@ namespace sqlpp auto union_distinct(Rhs rhs) const -> _new_statement_t<_check, union_t, Rhs>> { -#warning: make sure that Rhs is a select, not a uninon static_assert(is_statement_t::value, "argument of union call has to be a statement"); + static_assert(has_policy_t::value, "argument of union call has to be a select"); static_assert(has_result_row_t::value, "argument of a union has to be a (complete) select statement"); static_assert(has_result_row_t>::value, "left hand side argument of a union has to be a (complete) select statement"); static_assert(std::is_same>, get_result_row_t>::value, "both select statements in a union have to have the same result columns (type and name)"); diff --git a/tests/UnionTest.cpp b/tests/UnionTest.cpp index b4462ded..ca88841c 100644 --- a/tests/UnionTest.cpp +++ b/tests/UnionTest.cpp @@ -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; }