From b82a0295cf7c87cb8b3618b8e9c84ce1957c0266 Mon Sep 17 00:00:00 2001 From: rbock Date: Sat, 8 Feb 2014 16:29:21 +0100 Subject: [PATCH] Fixed all_of use in select --- include/sqlpp11/multi_column.h | 1 + include/sqlpp11/select.h | 114 +++++++++++++------- include/sqlpp11/vendor/select_column_list.h | 15 +++ include/sqlpp11/vendor/where.h | 15 ++- tests/InterpretTest.cpp | 28 ++++- 5 files changed, 126 insertions(+), 47 deletions(-) diff --git a/include/sqlpp11/multi_column.h b/include/sqlpp11/multi_column.h index 199bcfa8..61d1f5f2 100644 --- a/include/sqlpp11/multi_column.h +++ b/include/sqlpp11/multi_column.h @@ -71,6 +71,7 @@ namespace sqlpp namespace detail { +#warning need to handle all_of here. template using make_multi_column_t = multi_column_t>; diff --git a/include/sqlpp11/select.h b/include/sqlpp11/select.h index 07dadf0a..98795f71 100644 --- a/include/sqlpp11/select.h +++ b/include/sqlpp11/select.h @@ -63,13 +63,26 @@ namespace sqlpp typename Limit, typename Offset > - struct check_select_t + struct select_helper_t { - //static_assert(is_where_t::value, "cannot select remove without having a where condition, use .where(true) to remove all rows"); - static constexpr bool value = true; + using _column_list_t = ColumnList; + using _from_t = ColumnList; + template + struct can_run_t + { + //static_assert(is_where_t::value, "cannot select remove without having a where condition, use .where(true) to remove all rows"); + //static_assert(not vendor::is_noop::value, "cannot run select without having selected anything"); + //static_assert(is_from_t::value, "cannot run select without a from()"); + //static_assert(is_where_t::value, "cannot run select without having a where condition, use .where(true) to select all rows"); + // FIXME: Check for missing aliases (if references are used) + // FIXME: Check for missing tables, well, actually, check for missing tables at the where(), order_by(), etc. + + static constexpr bool value = true; + }; }; } + // SELECT template struct select_t: public vendor::policy_t..., public vendor::crtp_wrapper_t, Policies>... { @@ -80,6 +93,17 @@ namespace sqlpp using _parameter_tuple_t = std::tuple; using _parameter_list_t = typename make_parameter_list_t::type; + using _column_list_t = typename detail::select_helper_t::_column_list_t; + using _result_row_t = typename _column_list_t::_result_row_t; + using _dynamic_names_t = typename _column_list_t::_dynamic_names_t; + + using _is_select = std::true_type; + using _requires_braces = std::true_type; + + // FIXME: introduce checks whether this select could really be used as a value + using _value_type = typename _column_list_t::_value_type; + using _name_t = typename _column_list_t::_name_t; + select_t() {} @@ -99,27 +123,11 @@ namespace sqlpp select_t& operator=(select_t&& r) = default; ~select_t() = default; - using _is_select = std::true_type; - using _requires_braces = std::true_type; - - /* - using _result_row_t = typename ColumnList::_result_row_t; - using _dynamic_names_t = typename ColumnList::_dynamic_names_t; - using _parameter_tuple_t = std::tuple; - using _parameter_list_t = typename make_parameter_list_t::type; - // Indicators - using _value_type = typename std::conditional< - vendor::is_noop::value, - no_value_t, // If there is no from, the select is not complete (this logic is a bit simple, but better than nothing) - typename ColumnList::_value_type>::type; - - using _name_t = typename ColumnList::_name_t; - template struct _pseudo_table_t { - using table = typename ColumnList::template _pseudo_table_t; + using table = typename _column_list_t::template _pseudo_table_t; using alias = typename table::template _alias_t; }; @@ -130,9 +138,9 @@ namespace sqlpp *this).as(aliasProvider); } - const typename ColumnList::_dynamic_names_t& get_dynamic_names() const + const _dynamic_names_t& get_dynamic_names() const { - return _columns._dynamic_columns._dynamic_expression_names; + return _column_list_t::_dynamic_columns._dynamic_expression_names; } static constexpr size_t _get_static_no_of_parameters() @@ -155,13 +163,8 @@ namespace sqlpp auto _run(Db& db) const -> result_t { - static_assert(not vendor::is_noop::value, "cannot run select without having selected anything"); - static_assert(is_from_t::value, "cannot run select without a from()"); - static_assert(is_where_t::value, "cannot run select without having a where condition, use .where(true) to select all rows"); + static_assert(detail::select_helper_t::template can_run_t::value, "Cannot execute select statement"); static_assert(_get_static_no_of_parameters() == 0, "cannot run select directly with parameters, use prepare instead"); - // FIXME: Check for missing aliases (if references are used) - // FIXME: Check for missing tables, well, actually, check for missing tables at the where(), order_by(), etc. - return {db.select(*this), get_dynamic_names()}; } @@ -170,14 +173,10 @@ namespace sqlpp auto _prepare(Db& db) const -> prepared_select_t { - static_assert(not vendor::is_noop::value, "cannot run select without having selected anything"); - static_assert(is_from_t::value, "cannot run select without a from()"); - // FIXME: Check for missing aliases (if references are used) - // FIXME: Check for missing tables, well, actually, check for missing tables at the where(), order_by(), etc. + static_assert(detail::select_helper_t::template can_run_t::value, "Cannot prepare select statement"); return {{}, get_dynamic_names(), db.prepare_select(*this)}; } -*/ }; namespace vendor @@ -218,6 +217,39 @@ namespace sqlpp vendor::no_limit_t, vendor::no_offset_t>; + template + struct as_tuple + { + static std::tuple _(T t) { return { t }; }; + }; + + template + struct as_tuple> + { + static std::tuple _(std::tuple t) { return t; } + }; + + template class Target, typename First, typename T> + struct copy_tuple_args_impl + { + static_assert(vendor::wrong_t::value, "copy_tuple_args must be called with a tuple"); + }; + + template class Target, typename First, typename... Args> + struct copy_tuple_args_impl> + { + using type = Target; + }; + + template class Target, typename First, typename T> + using copy_tuple_args_t = typename copy_tuple_args_impl::type; + + template + using make_select_column_list_t = + copy_tuple_args_t::_(std::declval())...))>; + + blank_select_t select() // FIXME: These should be constexpr { return { blank_select_t() }; @@ -225,22 +257,24 @@ namespace sqlpp template auto select(Columns... columns) - -> vendor::update_policies_t, vendor::no_select_column_list_t, vendor::select_column_list_t> + -> vendor::update_policies_t, + vendor::no_select_column_list_t, + make_select_column_list_t> { - return { blank_select_t(), vendor::select_column_list_t(columns...) }; + return { blank_select_t(), make_select_column_list_t(std::tuple_cat(as_tuple::_(columns)...)) }; } template - blank_select_t dynamic_select() + blank_select_t dynamic_select(const Database&) { - return { blank_select_t() }; + return { blank_select_t() }; } template - auto dynamic_select(Columns... columns) - -> vendor::update_policies_t, vendor::no_select_column_list_t, vendor::select_column_list_t> + auto dynamic_select(const Database&, Columns... columns) + -> vendor::update_policies_t, vendor::no_select_column_list_t, make_select_column_list_t> { - return { blank_select_t(), vendor::select_column_list_t(columns...) }; + return { blank_select_t(), make_select_column_list_t(std::tuple_cat(as_tuple::_(columns)...)) }; } } diff --git a/include/sqlpp11/vendor/select_column_list.h b/include/sqlpp11/vendor/select_column_list.h index ea90f17b..30bf75c4 100644 --- a/include/sqlpp11/vendor/select_column_list.h +++ b/include/sqlpp11/vendor/select_column_list.h @@ -170,6 +170,10 @@ namespace sqlpp template using _dynamic_t = select_column_list_t>; + select_column_list_t(std::tuple columns): + _columns(columns) + {} + select_column_list_t(Columns... columns): _columns(columns...) {} @@ -196,6 +200,17 @@ namespace sqlpp struct no_select_column_list_t { using _is_select_column_list = std::true_type; + using _result_row_t = ::sqlpp::result_row_t<>; + using _dynamic_names_t = typename dynamic_select_column_list::_names_t; + using _value_type = no_value_t; + struct _name_t {}; + + template + struct _pseudo_table_t + { + static_assert(wrong_t::value, "Cannot use a select as a table when no columns have been selected yet"); + }; + const no_select_column_list_t& _column_list() const { return *this; } }; diff --git a/include/sqlpp11/vendor/where.h b/include/sqlpp11/vendor/where.h index 89ceeece..78b34db6 100644 --- a/include/sqlpp11/vendor/where.h +++ b/include/sqlpp11/vendor/where.h @@ -82,7 +82,18 @@ namespace sqlpp using _is_where = std::true_type; using _is_dynamic = std::false_type; - std::tuple _condition; + where_t(bool condition): + _condition(condition) + {} + + where_t(const where_t&) = default; + where_t(where_t&&) = default; + where_t& operator=(const where_t&) = default; + where_t& operator=(where_t&&) = default; + ~where_t() = default; + + const where_t& _where() const { return *this; } + bool _condition; }; struct no_where_t @@ -142,7 +153,7 @@ namespace sqlpp static Context& _(const T& t, Context& context) { - if (not std::get<0>(t._condition)) + if (not t._condition) context << " WHERE NULL"; return context; } diff --git a/tests/InterpretTest.cpp b/tests/InterpretTest.cpp index 3646635e..098710cc 100644 --- a/tests/InterpretTest.cpp +++ b/tests/InterpretTest.cpp @@ -131,20 +131,38 @@ int main() interpret(t.inner_join(t.as(t.alpha)).on(t.beta == t.as(t.alpha).beta), printer).flush(); // multi_column + */ interpret(multi_column(t.alpha, t.alpha, (t.beta + "cake").as(t.gamma)), printer).flush(); // dynamic select - interpret(dynamic_select(db).dynamic_flags().dynamic_columns(t.alpha).add_column(t.beta).add_column(t.gamma), printer).flush(); - interpret(dynamic_select(db).dynamic_flags().add_flag(sqlpp::distinct).dynamic_columns().add_column(t.gamma).add_column(t.beta), printer).flush(); - interpret(dynamic_select(db).dynamic_flags(sqlpp::distinct).add_flag(sqlpp::all).dynamic_columns(t.alpha).add_column(t.beta), printer).flush(); + { + auto s = dynamic_select(db).dynamic_flags().dynamic_columns(); + s.add_column(t.beta); + s.add_column(t.gamma); + interpret(s, printer).flush(); + } + { + auto s = dynamic_select(db).dynamic_flags().dynamic_columns(); + s.add_flag(sqlpp::distinct); + s.add_column(t.beta); + s.add_column(t.gamma); + interpret(s, printer).flush(); + } + { + auto s = dynamic_select(db).dynamic_flags(sqlpp::distinct).dynamic_columns(t.alpha); + s.add_flag(sqlpp::all); + s.add_column(t.beta); + s.add_column(t.gamma); + interpret(s, printer).flush(); + } + /* // distinct aggregate interpret(count(sqlpp::distinct, t.alpha % 7), printer).flush(); interpret(avg(sqlpp::distinct, t.alpha - 7), printer).flush(); interpret(sum(sqlpp::distinct, t.alpha + 7), printer).flush(); - +*/ interpret(select(all_of(t)).from(t).where(true), printer).flush(); interpret(select(all_of(t)).from(t).where(false), printer).flush(); -*/ return 0; }