diff --git a/include/sqlpp11/select.h b/include/sqlpp11/select.h index cd68ec59..fb22fe58 100644 --- a/include/sqlpp11/select.h +++ b/include/sqlpp11/select.h @@ -28,7 +28,6 @@ #define SQLPP_SELECT_H #include -#include #include #include @@ -45,74 +44,69 @@ #include #include #include +#include +#include +#include + #include #include -#include - namespace sqlpp { - template< - typename Database, - typename FlagList, - typename ColumnList, - typename From, - typename Where, - typename GroupBy, - typename Having, - typename OrderBy, - typename Limit, - typename Offset - > - struct select_t - : public ColumnList::_value_type::template operators> - { - using _Database = Database; - using _From = From; + namespace detail + { + template< + typename FlagList, + typename ColumnList, + typename From, + typename Where, + typename GroupBy, + typename Having, + typename OrderBy, + typename Limit, + typename Offset + > + struct check_select_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; + }; + } - 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"); - static_assert(vendor::is_noop::value or is_having_t::value, "invalid 'having' arguments"); - static_assert(vendor::is_noop::value or is_order_by_t::value, "invalid 'order by' arguments"); - static_assert(vendor::is_noop::value or is_limit_t::value, "invalid 'limit' arguments"); - static_assert(vendor::is_noop::value or is_offset_t::value, "invalid 'offset' arguments"); + template + struct select_t: public vendor::policy_t..., public vendor::crtp_wrapper_t, Policies>... + { + template + using _policy_update_t = select_t...>; + + using _database_t = Database; + using _parameter_tuple_t = std::tuple; + using _parameter_list_t = typename make_parameter_list_t::type; + + select_t() + {} + + template + select_t(select_t r, Whatever whatever): + vendor::policy_t(r, whatever)... + {} + + template + select_t(Remove r, Whatever whatever): + vendor::policy_t(r, whatever)... + {} + + select_t(const select_t& r) = default; + select_t(select_t&& r) = default; + select_t& operator=(const select_t& r) = default; + select_t& operator=(select_t&& r) = default; + ~select_t() = default; using _is_select = std::true_type; using _requires_braces = std::true_type; - template - using set_flag_list_t = select_t; - template - using set_column_list_t = select_t; - template - using set_from_t = select_t; - template - using set_where_t = select_t; - template - using set_group_by_t = select_t; - template - using set_having_t = select_t; - template - using set_order_by_t = select_t; - template - using set_limit_t = select_t; - template - using set_offset_t = select_t; - + /* using _result_row_t = typename ColumnList::_result_row_t; using _dynamic_names_t = typename ColumnList::_dynamic_names_t; using _parameter_tuple_t = std::tuple; @@ -640,58 +634,21 @@ namespace sqlpp return {{}, get_dynamic_names(), db.prepare_select(*this)}; } - - FlagList _flags; - ColumnList _columns; - From _from; - Where _where; - GroupBy _group_by; - Having _having; - OrderBy _order_by; - Limit _limit; - Offset _offset; +*/ }; namespace vendor { - template - struct interpreter_t> + template + struct interpreter_t> { - using T = select_t; + using T = select_t; static Context& _(const T& t, Context& context) { context << "SELECT "; + /* interpret(t._flags, context); interpret(t._columns, context); interpret(t._from, context); @@ -701,6 +658,7 @@ namespace sqlpp interpret(t._order_by, context); interpret(t._limit, context); interpret(t._offset, context); + */ return context; } @@ -708,6 +666,8 @@ namespace sqlpp } + /* + // construct select flag list namespace detail { @@ -751,6 +711,7 @@ namespace sqlpp {}, {}, {}, {}, {}, {}, {} }; } + */ } #endif diff --git a/include/sqlpp11/select_fwd.h b/include/sqlpp11/select_fwd.h index dc432e57..a9a5c9dd 100644 --- a/include/sqlpp11/select_fwd.h +++ b/include/sqlpp11/select_fwd.h @@ -31,27 +31,7 @@ namespace sqlpp { - namespace vendor - { - struct noop; - } - // select flags - struct all_t; - struct distinct_t; - struct straight_join_t; - - template< - typename Db, - typename Flags = vendor::noop, - typename ExpressionList = vendor::noop, - typename From = vendor::noop, - typename Where = vendor::noop, - typename GroupBy = vendor::noop, - typename Having = vendor::noop, - typename OrderBy = vendor::noop, - typename Limit = vendor::noop, - typename Offset = vendor::noop - > + template struct select_t; } #endif diff --git a/include/sqlpp11/vendor/from.h b/include/sqlpp11/vendor/from.h index 0de1e217..f0a816cd 100644 --- a/include/sqlpp11/vendor/from.h +++ b/include/sqlpp11/vendor/from.h @@ -83,7 +83,6 @@ namespace sqlpp no_from_t& _from = *this; }; - // CRTP Wrappers template struct crtp_wrapper_t> @@ -109,7 +108,6 @@ namespace sqlpp } }; - // Interpreters template struct interpreter_t> @@ -139,8 +137,8 @@ namespace sqlpp return context; } }; - } + } } #endif diff --git a/include/sqlpp11/vendor/group_by.h b/include/sqlpp11/vendor/group_by.h index ca8e2e5e..bdb7b169 100644 --- a/include/sqlpp11/vendor/group_by.h +++ b/include/sqlpp11/vendor/group_by.h @@ -32,57 +32,111 @@ #include #include #include +#include +#include #include namespace sqlpp { namespace vendor { - template + // GROUP BY + template struct group_by_t { using _is_group_by = std::true_type; using _is_dynamic = typename std::conditional::value, std::false_type, std::true_type>::type; - using _parameter_tuple_t = std::tuple; + using _parameter_tuple_t = std::tuple; - // ensure one argument at least - static_assert(_is_dynamic::value or sizeof...(Expr), "at least one expression (e.g. a column) required in group_by()"); + static_assert(_is_dynamic::value or sizeof...(Expressions), "at least one expression (e.g. a column) required in group_by()"); - // check for duplicate expressions - static_assert(not ::sqlpp::detail::has_duplicates::value, "at least one duplicate argument detected in group_by()"); + static_assert(not ::sqlpp::detail::has_duplicates::value, "at least one duplicate argument detected in group_by()"); - // check for invalid expressions - static_assert(::sqlpp::detail::and_t::value, "at least one argument is not an expression in group_by()"); + static_assert(::sqlpp::detail::and_t::value, "at least one argument is not an expression in group_by()"); - template - void add(E expr) + group_by_t(Expressions... expressions): + _expressions(expressions...) + {} + + group_by_t(const group_by_t&) = default; + group_by_t(group_by_t&&) = default; + group_by_t& operator=(const group_by_t&) = default; + group_by_t& operator=(group_by_t&&) = default; + ~group_by_t() = default; + + template + void add_group_by(Expression expression) { - static_assert(is_table_t::value, "from arguments require to be tables or joins"); - _dynamic_expressions.emplace_back(expr); + static_assert(is_table_t::value, "from arguments require to be tables or joins"); + _dynamic_expressions.emplace_back(expression); } + group_by_t& _group_by = *this; _parameter_tuple_t _expressions; vendor::interpretable_list_t _dynamic_expressions; - }; - template - struct interpreter_t> + struct no_group_by_t + { + using _is_group_by = std::true_type; + no_group_by_t& _group_by = *this; + }; + + // CRTP Wrappers + template + struct crtp_wrapper_t> { - using T = group_by_t; + }; + + template + struct crtp_wrapper_t + { + template + auto group_by(Args... args) + -> vendor::update_policies_t> + { + return { static_cast(*this), group_by_t(args...) }; + } + + template + auto dynamic_group_by(Args... args) + -> vendor::update_policies_t, Args...>> + { + static_assert(not std::is_same, void>::value, "dynamic_group_by must not be called in a static statement"); + return { static_cast(*this), group_by_t, Args...>(args...) }; + } + }; + + // Interpreters + template + struct interpreter_t> + { + using T = group_by_t; static Context& _(const T& t, Context& context) { - if (sizeof...(Expr) == 0 and t._dynamic_expressions.empty()) + if (sizeof...(Expressions) == 0 and t._dynamic_expressions.empty()) return context; context << " GROUP BY "; interpret_tuple(t._expressions, ',', context); - if (sizeof...(Expr) and not t._dynamic_expressions.empty()) + if (sizeof...(Expressions) and not t._dynamic_expressions.empty()) context << ','; interpret_list(t._dynamic_expressions, ',', context); return context; } }; + + template + struct interpreter_t + { + using T = no_group_by_t; + + static Context& _(const T& t, Context& context) + { + return context; + } + }; + } } diff --git a/include/sqlpp11/vendor/having.h b/include/sqlpp11/vendor/having.h index e9a474df..116e1e2a 100644 --- a/include/sqlpp11/vendor/having.h +++ b/include/sqlpp11/vendor/having.h @@ -31,52 +31,100 @@ #include #include #include +#include +#include #include namespace sqlpp { namespace vendor { - template + // HAVING + template struct having_t { using _is_having = std::true_type; using _is_dynamic = typename std::conditional::value, std::false_type, std::true_type>::type; - using _parameter_tuple_t = std::tuple; + using _parameter_tuple_t = std::tuple; - static_assert(_is_dynamic::value or sizeof...(Expr), "at least one expression argument required in having()"); - static_assert(::sqlpp::detail::and_t::value, "at least one argument is not an expression in having()"); + static_assert(_is_dynamic::value or sizeof...(Expressions), "at least one expression argument required in having()"); + static_assert(::sqlpp::detail::and_t::value, "at least one argument is not an expression in having()"); using _parameter_list_t = typename make_parameter_list_t<_parameter_tuple_t>::type; - template - void add(E expr) + template + void add(Expression expr) { - static_assert(is_expression_t::value, "invalid expression argument in add_having()"); + static_assert(is_expression_t::value, "invalid expression argument in add_having()"); _dynamic_expressions.emplace_back(expr); } + having_t& _having = *this; _parameter_tuple_t _expressions; vendor::interpretable_list_t _dynamic_expressions; }; - template - struct interpreter_t> + struct no_having_t + { + using _is_having = std::true_type; + no_having_t& _having = *this; + }; + + // CRTP Wrappers + template + struct crtp_wrapper_t> { - using T = having_t; + }; + + template + struct crtp_wrapper_t + { + template + auto having(Args... args) + -> vendor::update_policies_t> + { + return { static_cast(*this), having_t(args...) }; + } + + template + auto dynamic_having(Args... args) + -> vendor::update_policies_t, Args...>> + { + static_assert(not std::is_same, void>::value, "dynamic_having must not be called in a static statement"); + return { static_cast(*this), having_t, Args...>(args...) }; + } + }; + + // Interpreters + template + struct interpreter_t> + { + using T = having_t; static Context& _(const T& t, Context& context) { - if (sizeof...(Expr) == 0 and t._dynamic_expressions.empty()) + if (sizeof...(Expressions) == 0 and t._dynamic_expressions.empty()) return context; context << " HAVING "; interpret_tuple(t._expressions, " AND ", context); - if (sizeof...(Expr) and not t._dynamic_expressions.empty()) + if (sizeof...(Expressions) and not t._dynamic_expressions.empty()) context << " AND "; interpret_list(t._dynamic_expressions, " AND ", context); return context; } }; + + template + struct interpreter_t + { + using T = no_having_t; + + static Context& _(const T& t, Context& context) + { + return context; + } + }; + } } diff --git a/include/sqlpp11/vendor/limit.h b/include/sqlpp11/vendor/limit.h index fdee2700..d3b175a5 100644 --- a/include/sqlpp11/vendor/limit.h +++ b/include/sqlpp11/vendor/limit.h @@ -27,21 +27,106 @@ #ifndef SQLPP_LIMIT_H #define SQLPP_LIMIT_H -#include -#include #include +#include +#include namespace sqlpp { namespace vendor { + // LIMIT template struct limit_t { using _is_limit = std::true_type; static_assert(is_integral_t::value, "limit requires an integral value or integral parameter"); - Limit _limit; + limit_t(size_t value): + _value(value) + {} + + limit_t(const limit_t&) = default; + limit_t(limit_t&&) = default; + limit_t& operator=(const limit_t&) = default; + limit_t& operator=(limit_t&&) = default; + ~limit_t() = default; + + limit_t& _limit = *this; + Limit _value; + }; + + struct dynamic_limit_t + { + using _is_limit = std::true_type; + using _is_dynamic = std::true_type; + + dynamic_limit_t(size_t value): + _value(value) + {} + + dynamic_limit_t(const dynamic_limit_t&) = default; + dynamic_limit_t(dynamic_limit_t&&) = default; + dynamic_limit_t& operator=(const dynamic_limit_t&) = default; + dynamic_limit_t& operator=(dynamic_limit_t&&) = default; + ~dynamic_limit_t() = default; + + void set_limit(std::size_t limit) + { + _value = limit; + } + + dynamic_limit_t& _limit = *this; + std::size_t _value; // FIXME: This should be a serializable! + }; + + struct no_limit_t + { + using _is_limit = std::true_type; + no_limit_t& _limit = *this; + }; + + // CRTP Wrappers + template + struct crtp_wrapper_t> + { + }; + + template + struct crtp_wrapper_t + { + }; + + template + struct crtp_wrapper_t + { + template + auto limit(Arg arg) + -> vendor::update_policies_t> + { + return { static_cast(*this), limit_t(arg) }; + } + + auto dynamic_limit(size_t arg) + -> vendor::update_policies_t + { + static_assert(not std::is_same, void>::value, "dynamic_limit must not be called in a static statement"); + return { static_cast(*this), dynamic_limit_t(arg) }; + } + }; + + // Interpreters + template + struct interpreter_t + { + using T = dynamic_limit_t; + + static Context& _(const T& t, Context& context) + { + if (t._value > 0) + context << " LIMIT " << t._limit; + return context; + } }; template @@ -52,38 +137,23 @@ namespace sqlpp static Context& _(const T& t, Context& context) { context << " LIMIT "; - interpret(t._limit, context); + interpret(t._value, context); return context; } }; - struct dynamic_limit_t - { - using _is_limit = std::true_type; - using _is_dynamic = std::true_type; - - void set(std::size_t limit) - { - _limit = limit; - } - - std::size_t _limit; - }; - template - struct interpreter_t + struct interpreter_t { - using T = dynamic_limit_t; + using T = no_limit_t; static Context& _(const T& t, Context& context) { - if (t._limit > 0) - context << " LIMIT " << t._limit; return context; } }; - } + } } #endif diff --git a/include/sqlpp11/vendor/offset.h b/include/sqlpp11/vendor/offset.h index a7af759a..7f4df82b 100644 --- a/include/sqlpp11/vendor/offset.h +++ b/include/sqlpp11/vendor/offset.h @@ -28,20 +28,94 @@ #define SQLPP_OFFSET_H #include +#include +#include namespace sqlpp { namespace vendor { + // OFFSET template struct offset_t { using _is_offset = std::true_type; static_assert(is_integral_t::value, "offset requires an integral value or integral parameter"); - Offset _offset; + offset_t(size_t value): + _value(value) + {} + + offset_t(const offset_t&) = default; + offset_t(offset_t&&) = default; + offset_t& operator=(const offset_t&) = default; + offset_t& operator=(offset_t&&) = default; + ~offset_t() = default; + + offset_t& _offset = *this; + Offset _value; }; + struct dynamic_offset_t + { + using _is_offset = std::true_type; + using _is_dynamic = std::true_type; + + dynamic_offset_t(size_t value): + _value(value) + {} + + dynamic_offset_t(const dynamic_offset_t&) = default; + dynamic_offset_t(dynamic_offset_t&&) = default; + dynamic_offset_t& operator=(const dynamic_offset_t&) = default; + dynamic_offset_t& operator=(dynamic_offset_t&&) = default; + ~dynamic_offset_t() = default; + + void set_offset(std::size_t offset) + { + _value = offset; + } + + dynamic_offset_t& _offset = *this; + std::size_t _value; // FIXME: This should be a serializable! + }; + + struct no_offset_t + { + using _is_offset = std::true_type; + no_offset_t& _offset = *this; + }; + + // CRTP Wrappers + template + struct crtp_wrapper_t> + { + }; + + template + struct crtp_wrapper_t + { + }; + + template + struct crtp_wrapper_t + { + template + auto offset(Arg arg) + -> vendor::update_policies_t> + { + return { static_cast(*this), offset_t(arg) }; + } + + auto dynamic_offset(size_t arg) + -> vendor::update_policies_t + { + static_assert(not std::is_same, void>::value, "dynamic_offset must not be called in a static statement"); + return { static_cast(*this), dynamic_offset_t(arg) }; + } + }; + + // Interpreters template struct interpreter_t> { @@ -55,19 +129,6 @@ namespace sqlpp } }; - struct dynamic_offset_t - { - using _is_offset = std::true_type; - using _is_dynamic = std::true_type; - - void set(std::size_t offset) - { - _offset = offset; - } - - std::size_t _offset; - }; - template struct interpreter_t { @@ -75,12 +136,22 @@ namespace sqlpp static Context& _(const T& t, Context& context) { - if (t._offset > 0) + if (t._value > 0) context << " OFFSET " << t._offset; return context; } }; + template + struct interpreter_t + { + using T = no_offset_t; + + static Context& _(const T& t, Context& context) + { + return context; + } + }; } } diff --git a/include/sqlpp11/vendor/order_by.h b/include/sqlpp11/vendor/order_by.h index fd58485f..9c6f32ed 100644 --- a/include/sqlpp11/vendor/order_by.h +++ b/include/sqlpp11/vendor/order_by.h @@ -32,55 +32,110 @@ #include #include #include +#include +#include +#include namespace sqlpp { namespace vendor { - template + template struct order_by_t { using _is_order_by = std::true_type; using _is_dynamic = typename std::conditional::value, std::false_type, std::true_type>::type; - using _parameter_tuple_t = std::tuple; + using _parameter_tuple_t = std::tuple; - // check for at least one order expression - static_assert(_is_dynamic::value or sizeof...(Expr), "at least one sort-order expression required in order_by()"); + static_assert(_is_dynamic::value or sizeof...(Expressions), "at least one sort-order expression required in order_by()"); - // check for duplicate order expressions - static_assert(not ::sqlpp::detail::has_duplicates::value, "at least one duplicate argument detected in order_by()"); + static_assert(not ::sqlpp::detail::has_duplicates::value, "at least one duplicate argument detected in order_by()"); - // check for invalid order expressions - static_assert(::sqlpp::detail::and_t::value, "at least one argument is not a sort order expression in order_by()"); + static_assert(::sqlpp::detail::and_t::value, "at least one argument is not a sort order expression in order_by()"); - template - void add(E expr) + order_by_t(Expressions... expressions): + _expressions(expressions...) + {} + + order_by_t(const order_by_t&) = default; + order_by_t(order_by_t&&) = default; + order_by_t& operator=(const order_by_t&) = default; + order_by_t& operator=(order_by_t&&) = default; + ~order_by_t() = default; + + template + void add_order_by(Expression expressions) { - static_assert(is_sort_order_t::value, "order_by arguments require to be sort-order expressions"); - _dynamic_expressions.push_back(expr); + static_assert(is_sort_order_t::value, "order_by arguments require to be sort-order expressions"); + _dynamic_expressions.push_back(expressions); } + order_by_t& _order_by = *this; _parameter_tuple_t _expressions; vendor::interpretable_list_t _dynamic_expressions; }; - template - struct interpreter_t> + struct no_order_by_t + { + using _is_order_by = std::true_type; + no_order_by_t& _order_by = *this; + }; + + // CRTP Wrappers + template + struct crtp_wrapper_t> { - using T = order_by_t; + }; + + template + struct crtp_wrapper_t + { + template + auto order_by(Args... args) + -> vendor::update_policies_t> + { + return { static_cast(*this), order_by_t(args...) }; + } + + template + auto dynamic_order_by(Args... args) + -> vendor::update_policies_t, Args...>> + { + static_assert(not std::is_same, void>::value, "dynamic_order_by must not be called in a static statement"); + return { static_cast(*this), order_by_t, Args...>(args...) }; + } + }; + + // Interpreters + template + struct interpreter_t> + { + using T = order_by_t; static Context& _(const T& t, Context& context) { - if (sizeof...(Expr) == 0 and t._dynamic_expressions.empty()) + if (sizeof...(Expressions) == 0 and t._dynamic_expressions.empty()) return context; context << " ORDER BY "; interpret_tuple(t._expressions, ',', context); - if (sizeof...(Expr) and not t._dynamic_expressions.empty()) + if (sizeof...(Expressions) and not t._dynamic_expressions.empty()) context << ','; interpret_list(t._dynamic_expressions, ',', context); return context; } }; + + template + struct interpreter_t + { + using T = no_order_by_t; + + static Context& _(const T& t, Context& context) + { + return context; + } + }; + } } diff --git a/include/sqlpp11/vendor/select_column_list.h b/include/sqlpp11/vendor/select_column_list.h index ce421e8f..7872ac62 100644 --- a/include/sqlpp11/vendor/select_column_list.h +++ b/include/sqlpp11/vendor/select_column_list.h @@ -37,6 +37,8 @@ #include #include #include +#include +#include #include namespace sqlpp @@ -130,69 +132,103 @@ namespace sqlpp }; - template + // SELECT COLUMNS + template struct select_column_list_t - { - static_assert(::sqlpp::vendor::wrong_t::value, "invalid template argument for select_column_list"); - }; - - template - struct select_column_list_t> { 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 _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"); + static_assert(not ::sqlpp::detail::has_duplicates::value, "at least one duplicate argument detected"); - // check for invalid select expressions template using is_valid_expression_t = std::integral_constant::value or is_multi_column_t::value>; - static_assert(::sqlpp::detail::and_t::value, "at least one argument is not a named expression"); + static_assert(::sqlpp::detail::and_t::value, "at least one argument is not a named expression"); - // check for duplicate select expression names - static_assert(not ::sqlpp::detail::has_duplicates::value, "at least one duplicate name detected"); + static_assert(not ::sqlpp::detail::has_duplicates::value, "at least one duplicate name detected"); - // provide type information for sub-selects that are used as expressions struct _column_type {}; - struct _value_type: ::sqlpp::detail::get_first_argument_if_unique::_value_type + struct _value_type: ::sqlpp::detail::get_first_argument_if_unique::_value_type { - using _is_expression = typename std::conditional::type; - using _is_named_expression = typename std::conditional::type; + using _is_expression = typename std::conditional::type; + using _is_named_expression = typename std::conditional::type; using _is_alias = std::false_type; }; - using _name_t = typename ::sqlpp::detail::get_first_argument_if_unique::_name_t; + using _name_t = typename ::sqlpp::detail::get_first_argument_if_unique::_name_t; using _result_row_t = typename std::conditional<_is_dynamic::value, - dynamic_result_row_t...>, - result_row_t...>>::type; + dynamic_result_row_t...>, + result_row_t...>>::type; using _dynamic_names_t = typename dynamic_select_column_list::_names_t; template - using _pseudo_table_t = select_pseudo_table_t; + using _pseudo_table_t = select_pseudo_table_t; template - using _dynamic_t = select_column_list_t>; + using _dynamic_t = select_column_list_t>; + + select_column_list_t(Columns... columns): + _columns(columns...) + {} + + select_column_list_t(const select_column_list_t&) = default; + select_column_list_t(select_column_list_t&&) = default; + select_column_list_t& operator=(const select_column_list_t&) = default; + select_column_list_t& operator=(select_column_list_t&&) = default; + ~select_column_list_t() = default; template - void add(Expr namedExpr) + void add_column(Expr namedExpr) { static_assert(is_named_expression_t::value, "select() arguments require to be named expressions"); static_assert(_is_dynamic::value, "cannot add columns to a non-dynamic column list"); _dynamic_columns.push_back(namedExpr); } + select_column_list_t& _column_list = *this; _parameter_tuple_t _columns; dynamic_select_column_list _dynamic_columns; }; - template - struct interpreter_t> + struct no_select_column_list_t + { + using _is_select_column_list = std::true_type; + no_select_column_list_t& _column_list = *this; + }; + + // CRTP Wrappers + template + struct crtp_wrapper_t> { - using T = select_column_list_t; + }; + + template + struct crtp_wrapper_t + { + template + auto columns(Args... args) + -> vendor::update_policies_t> + { + return { static_cast(*this), select_column_list_t(args...) }; + } + + template + auto dynamic_columns(Args... args) + -> vendor::update_policies_t, Args...>> + { + static_assert(not std::is_same, void>::value, "dynamic_columns must not be called in a static statement"); + return { static_cast(*this), select_column_list_t, Args...>(args...) }; + } + }; + + // Interpreters + template + struct interpreter_t> + { + using T = select_column_list_t; static Context& _(const T& t, Context& context) { @@ -206,6 +242,17 @@ namespace sqlpp return context; } }; + + template + struct interpreter_t + { + using T = no_select_column_list_t; + + static Context& _(const T& t, Context& context) + { + return context; + } + }; } } diff --git a/include/sqlpp11/vendor/select_flag_list.h b/include/sqlpp11/vendor/select_flag_list.h index a167e4fc..48860aa7 100644 --- a/include/sqlpp11/vendor/select_flag_list.h +++ b/include/sqlpp11/vendor/select_flag_list.h @@ -27,58 +27,95 @@ #ifndef SQLPP_VENDOR_SELECT_FLAG_LIST_H #define SQLPP_VENDOR_SELECT_FLAG_LIST_H +#include #include #include #include #include #include -#include +#include +#include namespace sqlpp { namespace vendor { - template + // SELECT FLAGS + template struct select_flag_list_t - { - static_assert(::sqlpp::vendor::wrong_t::value, "invalid argument for select_flag_list"); - }; - - // select_flag_list_t - template - struct select_flag_list_t> { using _is_select_flag_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 _parameter_tuple_t = std::tuple; using size = std::tuple_size<_parameter_tuple_t>; - // check for duplicate order expressions - static_assert(not ::sqlpp::detail::has_duplicates::value, "at least one duplicate argument detected in select flag list"); + static_assert(not ::sqlpp::detail::has_duplicates::value, "at least one duplicate argument detected in select flag list"); - // check for invalid order expressions - static_assert(::sqlpp::detail::and_t::value, "at least one argument is not a select flag in select flag list"); + static_assert(::sqlpp::detail::and_t::value, "at least one argument is not a select flag in select flag list"); - template - void add(E expr) + select_flag_list_t(Flags... flags): + _flags(flags...) + {} + + select_flag_list_t(const select_flag_list_t&) = default; + select_flag_list_t(select_flag_list_t&&) = default; + select_flag_list_t& operator=(const select_flag_list_t&) = default; + select_flag_list_t& operator=(select_flag_list_t&&) = default; + ~select_flag_list_t() = default; + + template + void add_flag(Flag flag) { - static_assert(is_select_flag_t::value, "flag arguments require to be select flags"); - _dynamic_flags.emplace_back(expr); + static_assert(is_select_flag_t::value, "flag arguments require to be select flags"); + _dynamic_flags.emplace_back(flag); } + select_flag_list_t& _flag_list = *this; _parameter_tuple_t _flags; vendor::interpretable_list_t _dynamic_flags; }; - template - struct interpreter_t>> + struct no_select_flag_list_t + { + using _is_select_flag_list = std::true_type; + no_select_flag_list_t& _flag_list = *this; + }; + + // CRTP Wrappers + template + struct crtp_wrapper_t> { - using T = select_flag_list_t>; + }; + + template + struct crtp_wrapper_t + { + template + auto flags(Args... args) + -> vendor::update_policies_t> + { + return { static_cast(*this), select_flag_list_t(args...) }; + } + + template + auto dynamic_flags(Args... args) + -> vendor::update_policies_t, Args...>> + { + static_assert(not std::is_same, void>::value, "dynamic_flags must not be called in a static statement"); + return { static_cast(*this), select_flag_list_t, Args...>(args...) }; + } + }; + + // Interpreters + template + struct interpreter_t> + { + using T = select_flag_list_t; static Context& _(const T& t, Context& context) { interpret_tuple(t._flags, ' ', context); - if (sizeof...(Flag)) + if (sizeof...(Flags)) context << ' '; interpret_list(t._dynamic_flags, ',', context); if (not t._dynamic_flags.empty()) @@ -86,6 +123,17 @@ namespace sqlpp return context; } }; + + template + struct interpreter_t + { + using T = no_select_flag_list_t; + + static Context& _(const T& t, Context& context) + { + return context; + } + }; } } diff --git a/include/sqlpp11/vendor/where.h b/include/sqlpp11/vendor/where.h index bba16b33..b1805212 100644 --- a/include/sqlpp11/vendor/where.h +++ b/include/sqlpp11/vendor/where.h @@ -27,14 +27,14 @@ #ifndef SQLPP_WHERE_H #define SQLPP_WHERE_H -#include -#include -#include #include -#include +#include +#include #include #include -#include +#include +#include +#include namespace sqlpp { @@ -76,8 +76,18 @@ namespace sqlpp vendor::interpretable_list_t _dynamic_expressions; }; + template<> + struct where_t + { + using _is_where = std::true_type; + using _is_dynamic = std::false_type; + + std::tuple _condition; + }; + struct no_where_t { + using _is_where = std::true_type; no_where_t& _where = *this; }; @@ -125,16 +135,6 @@ namespace sqlpp } }; - template<> - struct where_t - { - using _is_where = std::true_type; - using _is_dynamic = std::false_type; - using _parameter_tuple_t = std::tuple<>; - - std::tuple _condition; - }; - template struct interpreter_t> {