From ee7cda0a5d52f1e46b9abcc1cf6dca15aac3d1b8 Mon Sep 17 00:00:00 2001 From: rbock Date: Mon, 20 Jan 2014 21:26:16 +0100 Subject: [PATCH] Started to change the way dynamic columns and flags are specified --- include/sqlpp11/count.h | 1 + include/sqlpp11/select.h | 262 ++++++++++-------- include/sqlpp11/type_traits.h | 2 +- ...expression_list.h => select_column_list.h} | 53 ++-- include/sqlpp11/vendor/select_flag_list.h | 12 +- tests/InterpretTest.cpp | 2 +- 6 files changed, 185 insertions(+), 147 deletions(-) rename include/sqlpp11/vendor/{select_expression_list.h => select_column_list.h} (79%) diff --git a/include/sqlpp11/count.h b/include/sqlpp11/count.h index f973e533..98c24cba 100644 --- a/include/sqlpp11/count.h +++ b/include/sqlpp11/count.h @@ -91,6 +91,7 @@ namespace sqlpp }; } +#warning: Add optional distinct flag to aggregate functions template auto count(T&& t) -> typename vendor::count_t::type> { diff --git a/include/sqlpp11/select.h b/include/sqlpp11/select.h index 720018e5..51a4bdab 100644 --- a/include/sqlpp11/select.h +++ b/include/sqlpp11/select.h @@ -34,7 +34,7 @@ #include #include -#include +#include #include #include #include @@ -55,8 +55,8 @@ namespace sqlpp { template< typename Database, - typename Flags, - typename ExpressionList, + typename FlagList, + typename ColumnList, typename From, typename Where, typename GroupBy, @@ -66,10 +66,10 @@ namespace sqlpp typename Offset > struct select_t - : public ExpressionList::_value_type::template operators::value or is_select_flag_list_t::value, "invalid list of select flags"); - static_assert(vendor::is_noop or is_select_expression_list_t::value, "invalid list of select expressions"); + static_assert(is_select_flag_list_t::value, "invalid list of select flags"); + static_assert(is_select_column_list_t::value, "invalid list of select expressions"); static_assert(vendor::is_noop::value or is_from_t::value, "invalid 'from' argument"); static_assert(vendor::is_noop::value or is_where_t::value, "invalid 'where' argument"); static_assert(vendor::is_noop::value or is_group_by_t::value, "invalid 'group by' arguments"); @@ -94,73 +94,44 @@ namespace sqlpp using _is_select = std::true_type; using _requires_braces = std::true_type; - template - using set_expression_list_t = select_t; + template + using set_flag_list_t = select_t; + template + using set_column_list_t = select_t; template - using set_from_t = select_t; + using set_from_t = select_t; template - using set_where_t = select_t; + using set_where_t = select_t; template - using set_group_by_t = select_t; + using set_group_by_t = select_t; template - using set_having_t = select_t; + using set_having_t = select_t; template - using set_order_by_t = select_t; + using set_order_by_t = select_t; template - using set_limit_t = select_t; + using set_limit_t = select_t; template - using set_offset_t = select_t; + using set_offset_t = select_t; - using _result_row_t = typename ExpressionList::_result_row_t; - using _dynamic_names_t = typename ExpressionList::_dynamic_names_t; - using _parameter_tuple_t = std::tuple; + 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 ExpressionList::_value_type>::type; + typename ColumnList::_value_type>::type; - using _name_t = typename ExpressionList::_name_t; + using _name_t = typename ColumnList::_name_t; // The standard constructors, assigment operators and destructor - select_t(Flags&& flags, ExpressionList&& expression_list): - _flags(std::move(flags)), - _expression_list(std::move(expression_list)) - { - static_assert(std::is_same>::value, - "basic constructor only available for select_t (default template parameters)"); - } - - select_t(const select_t& rhs) = default; - select_t(select_t&& rhs) = default; - select_t& operator=(const select_t& rhs) = default; - select_t& operator=(select_t&& rhs) = default; - ~select_t() = default; - - // Other constructors - - select_t(Flags&& flags, ExpressionList&& expression_list, From&& from, - Where&& where, GroupBy&& group_by, Having&& having, - OrderBy&& order_by, Limit&& limit, Offset&& offset): - _flags(std::move(flags)), - _expression_list(std::move(expression_list)), - _from(std::move(from)), - _where(std::move(where)), - _group_by(std::move(group_by)), - _having(std::move(having)), - _order_by(std::move(order_by)), - _limit(std::move(limit)), - _offset(std::move(offset)) - { - } - - select_t(const Flags& flags, const ExpressionList& expression_list, const From& from, - const Where& where, const GroupBy& group_by, const Having& having, - const OrderBy& order_by, const Limit& limit, const Offset& offset): - _flags(flags), - _expression_list(expression_list), + constexpr select_t(FlagList flag_list, ColumnList column_list, From from, + Where where, GroupBy group_by, Having having, + OrderBy order_by, Limit limit, Offset offset): + _flags(flag_list), + _column_list(column_list), _from(from), _where(where), _group_by(group_by), @@ -171,22 +142,79 @@ namespace sqlpp { } -Idea: - lets add methods flags(...) and dynamic_flags(...) - add method columns(...) and make dynamic_columns(...) take arguments - offer empty select() and dynamic_select(db) to call *flags() and *columns() later - continue to offer select(...) and dynamic_select(db, ...) for convenience + select_t(const select_t& rhs) = default; + select_t(select_t&& rhs) = default; + select_t& operator=(const select_t& rhs) = default; + select_t& operator=(select_t&& rhs) = default; + ~select_t() = default; - also: have ONE constructor, taking values - - auto dynamic_columns() - -> set_expression_list_t> + // select functions + template + auto flags(Flag&&... flag) + -> set_flag_list_t::type...>> { - static_assert(not std::is_same::value, "cannot call dynamic_from() in a non-dynamic select"); - static_assert(vendor::is_noop::value, "cannot call dynamic_columns() after from()"); + static_assert(vendor::is_noop::value, "cannot call flags() after specifying them the first time"); + static_assert(vendor::is_noop::value, "cannot call dynamic_flags() after specifying columns"); + return { + {flag...}, + _column_list, + _from, + _where, + _group_by, + _having, + _order_by, + _limit, + _offset + }; + } + + template + auto dynamic_flags(Flag&&... flag) + -> set_flag_list_t::type...>> + { + static_assert(not std::is_same::value, "cannot call dynamic_flags() in a non-dynamic select"); + static_assert(vendor::is_noop::value, "cannot call dynamic_flags() after specifying them the first time"); + static_assert(vendor::is_noop::value, "cannot call dynamic_flags() after specifying columns"); + return { + {flag...}, + _column_list, + _from, + _where, + _group_by, + _having, + _order_by, + _limit, + _offset + }; + } + + template + auto columns(Column&&... column) + -> set_column_list_t::type...>> + { + static_assert(not ColumnList::size::value, "cannot call columns() after specifying them the first time"); return { _flags, - {_expression_list._expressions}, + {std::tuple::type...>{std::forward(column)...}}, + _from, + _where, + _group_by, + _having, + _order_by, + _limit, + _offset + }; + } + + template + auto dynamic_columns(Column&&... column) + -> set_column_list_t::type...>>> + { + static_assert(not std::is_same::value, "cannot call dynamic_columns() in a non-dynamic select"); + static_assert(not ColumnList::size::value, "cannot call dynamic_columns() after specifying them the first time"); + return { + _flags, + {std::tuple::type...>{std::forward(column)...}}, _from, _where, _group_by, @@ -200,23 +228,22 @@ Idea: template select_t& add_column(NamedExpr&& namedExpr) { - static_assert(is_dynamic_t::value, "cannot call add_column() in a non-dynamic column list"); + static_assert(is_dynamic_t::value, "cannot call add_column() in a non-dynamic column list"); - _expression_list.add(std::forward(namedExpr)); + _column_list.add(std::forward(namedExpr)); return *this; } - // sqlpp functions template auto from(Table&&... table) -> set_from_t::type...>> { - static_assert(not vendor::is_noop::value, "cannot call from() without having selected anything"); + static_assert(not vendor::is_noop::value, "cannot call from() without having selected anything"); static_assert(vendor::is_noop::value, "cannot call from() twice for a single select"); return { _flags, - _expression_list, + _column_list, {std::tuple::type...>{std::forward(table)...}}, _where, _group_by, @@ -232,11 +259,11 @@ Idea: -> set_from_t::type...>> { static_assert(not std::is_same::value, "cannot call dynamic_from() in a non-dynamic select"); - static_assert(not vendor::is_noop::value, "cannot call from() without having selected anything"); + static_assert(not vendor::is_noop::value, "cannot call from() without having selected anything"); static_assert(vendor::is_noop::value, "cannot call from() twice for a single select"); return { _flags, - _expression_list, + _column_list, {std::tuple::type...>{std::forward
(table)...}}, _where, _group_by, @@ -250,7 +277,7 @@ Idea: template select_t& add_from(Table&& table) { - static_assert(not vendor::is_noop::value, "cannot call add_from() without having selected anything"); + static_assert(not vendor::is_noop::value, "cannot call add_from() without having selected anything"); static_assert(is_dynamic_t::value, "cannot call add_from() in a non-dynamic from"); _from.add(std::forward
(table)); @@ -266,7 +293,7 @@ Idea: static_assert(vendor::is_noop::value, "cannot call where() or dynamic_where() twice for a single select"); return { _flags, - _expression_list, + _column_list, _from, {std::tuple::type...>{std::forward(expr)...}}, _group_by, @@ -285,7 +312,7 @@ Idea: static_assert(vendor::is_noop::value, "cannot call where() or dynamic_where() twice for a single select"); return { _flags, - _expression_list, + _column_list, _from, {std::tuple::type...>{std::forward(expr)...}}, _group_by, @@ -314,7 +341,7 @@ Idea: static_assert(vendor::is_noop::value, "cannot call group_by() twice for a single select"); return { _flags, - _expression_list, + _column_list, _from, _where, {std::tuple::type...>{std::forward(column)...}}, @@ -333,7 +360,7 @@ Idea: static_assert(vendor::is_noop::value, "cannot call group_by() twice for a single select"); return { _flags, - _expression_list, + _column_list, _from, _where, {std::tuple::type...>{std::forward(column)...}}, @@ -362,7 +389,7 @@ Idea: static_assert(vendor::is_noop::value, "cannot call having() twice for a single select"); return { _flags, - _expression_list, + _column_list, _from, _where, _group_by, @@ -381,7 +408,7 @@ Idea: static_assert(vendor::is_noop::value, "cannot call having() twice for a single select"); return { _flags, - _expression_list, + _column_list, _from, _where, _group_by, @@ -410,7 +437,7 @@ Idea: static_assert(vendor::is_noop::value, "cannot call order_by() twice for a single select"); return { _flags, - _expression_list, + _column_list, _from, _where, _group_by, @@ -429,7 +456,7 @@ Idea: static_assert(vendor::is_noop::value, "cannot call order_by() twice for a single select"); return { _flags, - _expression_list, + _column_list, _from, _where, _group_by, @@ -458,7 +485,7 @@ Idea: static_assert(vendor::is_noop::value, "cannot call limit() twice for a single select"); return { _flags, - _expression_list, + _column_list, _from, _where, _group_by, @@ -476,7 +503,7 @@ Idea: static_assert(vendor::is_noop::value, "cannot call limit() twice for a single select"); return { _flags, - _expression_list, + _column_list, _from, _where, _group_by, @@ -504,7 +531,7 @@ Idea: static_assert(vendor::is_noop::value, "cannot call offset() twice for a single select"); return { _flags, - _expression_list, + _column_list, _from, _where, _group_by, @@ -522,7 +549,7 @@ Idea: static_assert(vendor::is_noop::value, "cannot call offset() twice for a single select"); return { _flags, - _expression_list, + _column_list, _from, _where, _group_by, @@ -545,7 +572,7 @@ Idea: template struct _pseudo_table_t { - using table = typename ExpressionList::template _pseudo_table_t; + using table = typename ColumnList::template _pseudo_table_t; using alias = typename table::template _alias_t; }; @@ -556,9 +583,9 @@ Idea: *this).as(aliasProvider); } - const typename ExpressionList::_dynamic_names_t& get_dynamic_names() const + const typename ColumnList::_dynamic_names_t& get_dynamic_names() const { - return _expression_list._dynamic_expressions._dynamic_expression_names; + return _column_list._dynamic_expressions._dynamic_expression_names; } static constexpr size_t _get_static_no_of_parameters() @@ -581,7 +608,7 @@ Idea: auto run(Db& db) const -> result_t { - static_assert(not vendor::is_noop::value, "cannot run select without having selected anything"); + 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(_get_static_no_of_parameters() == 0, "cannot run select directly with parameters, use prepare instead"); // FIXME: Check for missing aliases (if references are used) @@ -595,7 +622,7 @@ Idea: auto prepare(Db& db) const -> prepared_select_t::type, select_t> { - static_assert(not vendor::is_noop::value, "cannot run select without having selected anything"); + 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. @@ -603,8 +630,8 @@ Idea: return {{}, get_dynamic_names(), db.prepare_select(*this)}; } - Flags _flags; - ExpressionList _expression_list; + FlagList _flags; + ColumnList _column_list; From _from; Where _where; GroupBy _group_by; @@ -618,8 +645,8 @@ Idea: { template struct interpreter_t> { using T = select_t + template using make_select_flag_list_t = - vendor::select_flag_list_t()...))>; + vendor::select_flag_list_t()...))>; } // construct select expression list namespace detail { - template - using make_select_expression_list_t = - vendor::select_expression_list_t()...))>; + template + using make_select_column_list_t = + vendor::select_column_list_t()...))>; } + auto select() + -> select_t>, vendor::select_column_list_t>> + { + return { {}, vendor::select_column_list_t>{}, {}, {}, {}, {}, {}, {}, {} }; + } + template auto select(NamedExpr&&... namedExpr) - -> select_t, detail::make_select_expression_list_t> + -> select_t, detail::make_select_column_list_t> { return { { detail::make_flag_tuple(std::forward(namedExpr)...) }, - { detail::make_expression_tuple(std::forward(namedExpr)...) } + { detail::make_expression_tuple(std::forward(namedExpr)...) }, + {}, {}, {}, {}, {}, {}, {} }; } + template auto dynamic_select(const Db& db, NamedExpr&&... namedExpr) - -> select_t::type, detail::make_select_flag_list_t, detail::make_select_expression_list_t> + -> select_t::type, detail::make_select_flag_list_t::type, NamedExpr...>, detail::make_select_column_list_t::type, NamedExpr...>> { return { { detail::make_flag_tuple(std::forward(namedExpr)...) }, - { detail::make_expression_tuple(std::forward(namedExpr)...) } + { detail::make_expression_tuple(std::forward(namedExpr)...) }, + {}, {}, {}, {}, {}, {}, {} }; } diff --git a/include/sqlpp11/type_traits.h b/include/sqlpp11/type_traits.h index 3cba4240..f2b3c36e 100644 --- a/include/sqlpp11/type_traits.h +++ b/include/sqlpp11/type_traits.h @@ -97,7 +97,7 @@ namespace sqlpp SQLPP_TYPE_TRAIT_GENERATOR(is_pseudo_table); SQLPP_TYPE_TRAIT_GENERATOR(is_select); SQLPP_TYPE_TRAIT_GENERATOR(is_select_flag_list); - SQLPP_TYPE_TRAIT_GENERATOR(is_select_expression_list); + SQLPP_TYPE_TRAIT_GENERATOR(is_select_column_list); SQLPP_TYPE_TRAIT_GENERATOR(is_from); SQLPP_TYPE_TRAIT_GENERATOR(is_on); SQLPP_TYPE_TRAIT_GENERATOR(is_dynamic); diff --git a/include/sqlpp11/vendor/select_expression_list.h b/include/sqlpp11/vendor/select_column_list.h similarity index 79% rename from include/sqlpp11/vendor/select_expression_list.h rename to include/sqlpp11/vendor/select_column_list.h index ab9d06f6..e71f961f 100644 --- a/include/sqlpp11/vendor/select_expression_list.h +++ b/include/sqlpp11/vendor/select_column_list.h @@ -24,8 +24,8 @@ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef SQLPP_SELECT_EXPRESSION_LIST_H -#define SQLPP_SELECT_EXPRESSION_LIST_H +#ifndef SQLPP_SELECT_COLUMN_LIST_H +#define SQLPP_SELECT_COLUMN_LIST_H #include #include @@ -61,27 +61,27 @@ namespace sqlpp namespace vendor { template - struct dynamic_select_expression_list + struct dynamic_select_column_list { using _names_t = std::vector; - std::vector> _dynamic_expressions; + std::vector> _dynamic_columns; _names_t _dynamic_expression_names; template void push_back(Expr&& expr) { _dynamic_expression_names.push_back(std::decay::type::_name_t::_get_name()); - _dynamic_expressions.emplace_back(std::forward(expr)); + _dynamic_columns.emplace_back(std::forward(expr)); } bool empty() const { - return _dynamic_expressions.empty(); + return _dynamic_columns.empty(); } }; template<> - struct dynamic_select_expression_list + struct dynamic_select_column_list { struct _names_t {}; _names_t _dynamic_expression_names; @@ -96,13 +96,13 @@ namespace sqlpp }; template - struct interpreter_t> + struct interpreter_t> { - using T = dynamic_select_expression_list; + using T = dynamic_select_column_list; static Context& _(const T& t, Context& context) { - for (const auto column : t._dynamic_expressions) + for (const auto column : t._dynamic_columns) { interpret(column, context); } @@ -111,9 +111,9 @@ namespace sqlpp }; template - struct interpreter_t> + struct interpreter_t> { - using T = dynamic_select_expression_list; + using T = dynamic_select_column_list; static Context& _(const T& t, Context& context) { @@ -123,17 +123,18 @@ namespace sqlpp template - struct select_expression_list_t + struct select_column_list_t { - static_assert(::sqlpp::detail::wrong::value, "invalid template argument for select_expression_list"); + static_assert(::sqlpp::detail::wrong::value, "invalid template argument for select_column_list"); }; template - struct select_expression_list_t> + struct select_column_list_t> { - using _is_select_expression_list = std::true_type; + using _is_select_column_list = std::true_type; using _is_dynamic = typename std::conditional::value, std::false_type, std::true_type>::type; using _parameter_tuple_t = std::tuple; + using size = std::tuple_size<_parameter_tuple_t>; // check for duplicate select expressions static_assert(not ::sqlpp::detail::has_duplicates::value, "at least one duplicate argument detected"); @@ -161,40 +162,40 @@ namespace sqlpp dynamic_result_row_t...>, result_row_t...>>::type; - using _dynamic_names_t = typename dynamic_select_expression_list::_names_t; + using _dynamic_names_t = typename dynamic_select_column_list::_names_t; template using _pseudo_table_t = select_pseudo_table_t; template - using _dynamic_t = select_expression_list_t>; + using _dynamic_t = select_column_list_t>; template void add(Expr&& namedExpr) { static_assert(is_named_expression_t::type>::value, "select() arguments require to be named expressions"); static_assert(_is_dynamic::value, "cannot add columns to a non-dynamic column list"); - _dynamic_expressions.push_back(std::forward(namedExpr)); + _dynamic_columns.push_back(std::forward(namedExpr)); } - _parameter_tuple_t _expressions; - dynamic_select_expression_list _dynamic_expressions; + _parameter_tuple_t _columns; + dynamic_select_column_list _dynamic_columns; }; template - struct interpreter_t> + struct interpreter_t> { - using T = select_expression_list_t; + using T = select_column_list_t; static Context& _(const T& t, Context& context) { // check for at least one expression static_assert(T::_is_dynamic::value or sizeof...(NamedExpr), "at least one select expression required"); - interpret_tuple(t._expressions, ',', context); - if (sizeof...(NamedExpr) and not t._dynamic_expressions.empty()) + interpret_tuple(t._columns, ',', context); + if (sizeof...(NamedExpr) and not t._dynamic_columns.empty()) context << ','; - interpret(t._dynamic_expressions, context); + interpret(t._dynamic_columns, context); return context; } }; diff --git a/include/sqlpp11/vendor/select_flag_list.h b/include/sqlpp11/vendor/select_flag_list.h index 62630b88..bf281a22 100644 --- a/include/sqlpp11/vendor/select_flag_list.h +++ b/include/sqlpp11/vendor/select_flag_list.h @@ -104,15 +104,15 @@ namespace sqlpp namespace vendor { - template + template struct select_flag_list_t { static_assert(detail::wrong::value, "invalid argument for select_flag_list"); }; // select_flag_list_t - template - struct select_flag_list_t> + template + struct select_flag_list_t> { // check for duplicate order expressions static_assert(not detail::has_duplicates::value, "at least one duplicate argument detected in select flag list"); @@ -126,10 +126,10 @@ namespace sqlpp std::tuple _flags; }; - template - struct interpreter_t>> + template + struct interpreter_t>> { - using T = select_flag_list_t>; + using T = select_flag_list_t>; static Context& _(const T& t, Context& context) { diff --git a/tests/InterpretTest.cpp b/tests/InterpretTest.cpp index da620dba..74904e21 100644 --- a/tests/InterpretTest.cpp +++ b/tests/InterpretTest.cpp @@ -110,7 +110,7 @@ int main() interpret(multi_column(t.alpha, t.alpha, (t.beta + "cake").as(t.gamma)), printer).flush(); // dynamic select - interpret(dynamic_select(db, t.alpha).dynamic_columns().add_column(t.beta), printer).flush(); + interpret(dynamic_select(db).dynamic_columns(t.alpha).add_column(t.beta), printer).flush(); return 0; }