diff --git a/include/sqlpp11/select.h b/include/sqlpp11/select.h index 2a9561f2..28f31c01 100644 --- a/include/sqlpp11/select.h +++ b/include/sqlpp11/select.h @@ -203,13 +203,13 @@ namespace sqlpp vendor::no_select_flag_list_t, vendor::no_select_column_list_t, vendor::no_from_t, - //vendor::no_extra_tables_t, - vendor::no_where_t/*, + vendor::no_extra_tables_t, + vendor::no_where_t, vendor::no_group_by_t, vendor::no_having_t, vendor::no_order_by_t, vendor::no_limit_t, - vendor::no_offset_t*/>; + vendor::no_offset_t>; blank_select_t select() // FIXME: These should be constexpr diff --git a/include/sqlpp11/vendor/extra_tables.h b/include/sqlpp11/vendor/extra_tables.h index 94f68328..5496518c 100644 --- a/include/sqlpp11/vendor/extra_tables.h +++ b/include/sqlpp11/vendor/extra_tables.h @@ -84,9 +84,17 @@ namespace sqlpp template struct _member_t { + using _data_t = extra_tables_data_t; + _impl_t extra_tables; _impl_t& operator()() { return extra_tables; } const _impl_t& operator()() const { return extra_tables; } + + template + static auto _get_member(T t) -> decltype(t.extra_tables) + { + return t.extra_tables; + } }; // Additional methods for the statement @@ -103,9 +111,7 @@ namespace sqlpp using _recursive_traits = make_recursive_traits<>; // Data - struct _data_t - { - }; + using _data_t = no_data_t; // Member implementation with data and methods template @@ -118,9 +124,17 @@ namespace sqlpp template struct _member_t { - _impl_t no_extra_tables_t; - _impl_t& operator()() { return no_extra_tables_t; } - const _impl_t& operator()() const { return no_extra_tables_t; } + using _data_t = no_data_t; + + _impl_t no_extra_tables; + _impl_t& operator()() { return no_extra_tables; } + const _impl_t& operator()() const { return no_extra_tables; } + + template + static auto _get_member(T t) -> decltype(t.no_extra_tables) + { + return t.no_extra_tables; + } }; template @@ -150,17 +164,6 @@ namespace sqlpp } }; - template - struct serializer_t - { - using T = typename no_extra_tables_t::_data_t; - - static Context& _(const T& t, Context& context) - { - return context; - } - }; - } } diff --git a/include/sqlpp11/vendor/group_by.h b/include/sqlpp11/vendor/group_by.h index 3766c66c..caadc8db 100644 --- a/include/sqlpp11/vendor/group_by.h +++ b/include/sqlpp11/vendor/group_by.h @@ -39,6 +39,24 @@ namespace sqlpp { namespace vendor { + // GROUP BY DATA + template + struct group_by_data_t + { + group_by_data_t(Expressions... expressions): + _expressions(expressions...) + {} + + group_by_data_t(const group_by_data_t&) = default; + group_by_data_t(group_by_data_t&&) = default; + group_by_data_t& operator=(const group_by_data_t&) = default; + group_by_data_t& operator=(group_by_data_t&&) = default; + ~group_by_data_t() = default; + + std::tuple _expressions; + vendor::interpretable_list_t _dynamic_expressions; + }; + // GROUP BY template struct group_by_t @@ -54,60 +72,100 @@ namespace sqlpp static_assert(::sqlpp::detail::all_t::value...>::value, "at least one argument is not an expression in group_by()"); - group_by_t& _group_by() { return *this; } - - 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; + // Data + using _data_t = select_flag_list_data_t; + // Member implementation with data and methods template - struct _methods_t + struct _impl_t { template - void add_group_by_ntc(Expression expression) + void add_ntc(Expression expression) { - add_group_by(expression); + add(expression); } template - void add_group_by(Expression expression) + void add(Expression expression) { - static_assert(_is_dynamic::value, "add_group_by must not be called for static group_by"); - static_assert(is_expression_t::value, "invalid expression argument in add_group_by()"); - static_assert(TableCheckRequired::value or Policies::template _no_unknown_tables::value, "expression uses tables unknown to this statement in add_group_by()"); + static_assert(_is_dynamic::value, "add() must not be called for static group_by"); + static_assert(is_expression_t::value, "invalid expression argument in group_by::add()"); + static_assert(TableCheckRequired::value or Policies::template _no_unknown_tables::value, "expression uses tables unknown to this statement in group_by::add()"); using ok = ::sqlpp::detail::all_t<_is_dynamic::value, is_expression_t::value>; - _add_group_by_impl(expression, ok()); // dispatch to prevent compile messages after the static_assert + _add_impl(expression, ok()); // dispatch to prevent compile messages after the static_assert } private: template - void _add_group_by_impl(Expression expression, const std::true_type&) + void _add_impl(Expression expression, const std::true_type&) { - return static_cast(this)->_group_by()._dynamic_expressions.emplace_back(expression); + return _data._dynamic_expressions.emplace_back(expression); } template - void _add_group_by_impl(Expression expression, const std::false_type&); + void _add_impl(Expression expression, const std::false_type&); + public: + _data_t _data; }; - const group_by_t& _group_by() const { return *this; } - std::tuple _expressions; - vendor::interpretable_list_t _dynamic_expressions; + // Member template for adding the named member to a statement + template + struct _member_t + { + using _data_t = group_by_data_t; + + _impl_t group_by; + _impl_t& operator()() { return group_by; } + const _impl_t& operator()() const { return group_by; } + + template + static auto _get_member(T t) -> decltype(t.group_by) + { + return t.group_by; + } + }; + + template + struct _methods_t + { + }; }; + // NO GROUP BY YET struct no_group_by_t { using _traits = make_traits; using _recursive_traits = make_recursive_traits<>; + // Data + using _data_t = no_data_t; + + // Member implementation with data and methods + template + struct _impl_t + { + _data_t _data; + }; + + // Member template for adding the named member to a statement + template + struct _member_t + { + using _data_t = no_data_t; + + _impl_t no_group_by; + _impl_t& operator()() { return no_group_by; } + const _impl_t& operator()() const { return no_group_by; } + + template + static auto _get_member(T t) -> decltype(t.no_group_by) + { + return t.no_group_by; + } + }; + template struct _methods_t { @@ -119,7 +177,7 @@ namespace sqlpp auto group_by(Args... args) -> _new_statement_t> { - return { *static_cast(this), group_by_t{args...} }; + return { *static_cast(this), group_by_data_t{args...} }; } template @@ -127,16 +185,16 @@ namespace sqlpp -> _new_statement_t> { static_assert(not std::is_same<_database_t, void>::value, "dynamic_group_by must not be called in a static statement"); - return { *static_cast(this), vendor::group_by_t<_database_t, Args...>{args...} }; + return { *static_cast(this), group_by_data_t<_database_t, Args...>{args...} }; } }; }; // Interpreters template - struct serializer_t> + struct serializer_t> { - using T = group_by_t; + using T = group_by_data_t; static Context& _(const T& t, Context& context) { @@ -150,18 +208,6 @@ namespace sqlpp return context; } }; - - template - struct serializer_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 8f85eab9..0abdcb72 100644 --- a/include/sqlpp11/vendor/having.h +++ b/include/sqlpp11/vendor/having.h @@ -38,6 +38,24 @@ namespace sqlpp { namespace vendor { + // HAVING DATA + template + struct having_data_t + { + having_data_t(Expressions... expressions): + _expressions(expressions...) + {} + + having_data_t(const having_data_t&) = default; + having_data_t(having_data_t&&) = default; + having_data_t& operator=(const having_data_t&) = default; + having_data_t& operator=(having_data_t&&) = default; + ~having_data_t() = default; + + std::tuple _expressions; + vendor::interpretable_list_t _dynamic_expressions; + }; + // HAVING template struct having_t @@ -50,59 +68,102 @@ namespace sqlpp static_assert(_is_dynamic::value or sizeof...(Expressions), "at least one expression argument required in having()"); static_assert(::sqlpp::detail::all_t::value...>::value, "at least one argument is not an expression in having()"); - having_t& _having() { return *this; } + // Data + using _data_t = having_data_t; - having_t(Expressions... expressions): - _expressions(expressions...) - {} - - having_t(const having_t&) = default; - having_t(having_t&&) = default; - having_t& operator=(const having_t&) = default; - having_t& operator=(having_t&&) = default; - ~having_t() = default; - - template - struct _methods_t + // Member implementation with data and methods + template + struct _impl_t { template - void add_having_ntc(Expression expression) + void add_ntc(Expression expression) { - add_having(expression); + add(expression); } template - void add_having(Expression expression) + void add(Expression expression) { - static_assert(_is_dynamic::value, "add_having must not be called for static having"); - static_assert(is_expression_t::value, "invalid expression argument in add_having()"); - static_assert(TableCheckRequired::value or Policies::template _no_unknown_tables::value, "expression uses tables unknown to this statement in add_having()"); + static_assert(_is_dynamic::value, "having::add() can only be called for dynamic_having"); + static_assert(is_expression_t::value, "invalid expression argument in having::add()"); + static_assert(not TableCheckRequired::value or Policies::template _no_unknown_tables::value, "expression uses tables unknown to this statement in having::add()"); using ok = ::sqlpp::detail::all_t<_is_dynamic::value, is_expression_t::value>; - _add_having_impl(expression, ok()); // dispatch to prevent compile messages after the static_assert + _add_impl(expression, ok()); // dispatch to prevent compile messages after the static_assert } private: template - void _add_having_impl(Expression expression, const std::true_type&) + void _add_impl(Expression expression, const std::true_type&) { - return static_cast(this)->_having()._dynamic_expressions.emplace_back(expression); + return _data._dynamic_expressions.emplace_back(expression); } template - void _add_having_impl(Expression expression, const std::false_type&); + void _add_impl(Expression expression, const std::false_type&); + + public: + _data_t _data; }; - std::tuple _expressions; - vendor::interpretable_list_t _dynamic_expressions; + // Member template for adding the named member to a statement + template + struct _member_t + { + using _data_t = having_data_t; + + _impl_t having; + _impl_t& operator()() { return having; } + const _impl_t& operator()() const { return having; } + + template + static auto _get_member(T t) -> decltype(t.having) + { + return t.having; + } + }; + + // Additional methods for the statement + template + struct _methods_t + { + }; }; + // NO HAVING YET struct no_having_t { using _traits = make_traits; using _recursive_traits = make_recursive_traits<>; + // Data + using _data_t = no_data_t; + + // Member implementation with data and methods + template + struct _impl_t + { + _data_t _data; + }; + + // Member template for adding the named member to a statement + template + struct _member_t + { + using _data_t = no_data_t; + + _impl_t no_having; + _impl_t& operator()() { return no_having; } + const _impl_t& operator()() const { return no_having; } + + template + static auto _get_member(T t) -> decltype(t.no_having) + { + return t.no_having; + } + }; + template struct _methods_t { @@ -114,7 +175,7 @@ namespace sqlpp auto having(Args... args) -> _new_statement_t> { - return { *static_cast(this), having_t{args...} }; + return { *static_cast(this), having_data_t{args...} }; } template @@ -122,16 +183,16 @@ namespace sqlpp -> _new_statement_t> { static_assert(not std::is_same<_database_t, void>::value, "dynamic_having must not be called in a static statement"); - return { *static_cast(this), vendor::having_t<_database_t, Args...>{args...} }; + return { *static_cast(this), having_data_t<_database_t, Args...>{args...} }; } }; }; // Interpreters template - struct serializer_t> + struct serializer_t> { - using T = having_t; + using T = having_data_t; static Context& _(const T& t, Context& context) { @@ -145,18 +206,6 @@ namespace sqlpp return context; } }; - - template - struct serializer_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 b5b2ec89..62310324 100644 --- a/include/sqlpp11/vendor/limit.h +++ b/include/sqlpp11/vendor/limit.h @@ -35,6 +35,23 @@ namespace sqlpp { namespace vendor { + // LIMIT DATA + template + struct limit_data_t + { + limit_data_t(Limit value): + _value(value) + {} + + limit_data_t(const limit_data_t&) = default; + limit_data_t(limit_data_t&&) = default; + limit_data_t& operator=(const limit_data_t&) = default; + limit_data_t& operator=(limit_data_t&&) = default; + ~limit_data_t() = default; + + Limit _value; + }; + // LIMIT template struct limit_t @@ -44,65 +61,109 @@ namespace sqlpp static_assert(is_integral_t::value, "limit requires an integral value or integral parameter"); - limit_t(Limit value): - _value(value) - {} + // Data + using _data_t = limit_data_t; - 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; + // Member implementation with data and methods + template + struct _impl_t + { + _data_t _data; + }; + + // Member template for adding the named member to a statement + template + struct _member_t + { + _impl_t limit; + _impl_t& operator()() { return limit; } + const _impl_t& operator()() const { return limit; } + + template + static auto _get_member(T t) -> decltype(t.limit) + { + return t.limit; + } + }; template struct _methods_t { }; - - Limit _value; }; + // DYNAMIC LIMIT DATA + template + struct dynamic_limit_data_t + { + dynamic_limit_data_t(): + _value(noop()) + { + } + + template + dynamic_limit_data_t(Limit value): + _initialized(true), + _value(typename wrap_operand::type(value)) + { + } + + dynamic_limit_data_t(const dynamic_limit_data_t&) = default; + dynamic_limit_data_t(dynamic_limit_data_t&&) = default; + dynamic_limit_data_t& operator=(const dynamic_limit_data_t&) = default; + dynamic_limit_data_t& operator=(dynamic_limit_data_t&&) = default; + ~dynamic_limit_data_t() = default; + + bool _initialized = false; + interpretable_t _value; + }; + + // DYNAMIC LIMIT template struct dynamic_limit_t { using _traits = make_traits; using _recursive_traits = make_recursive_traits<>; - dynamic_limit_t& _limit() { return *this; } + // Data + using _data_t = limit_data_t; - dynamic_limit_t(): - _value(noop()) - { - } - - template - dynamic_limit_t(Limit value): - _initialized(true), - _value(typename wrap_operand::type(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; - - template - struct _methods_t + // Member implementation with data and methods + template + struct _impl_t { template - void set_limit(Limit value) + void set(Limit value) { // FIXME: Make sure that Limit does not require external tables? Need to read up on SQL using arg_t = typename wrap_operand::type; - static_cast(this)->_limit()._value = arg_t{value}; - static_cast(this)->_limit()._initialized = true; + _data._value = arg_t{value}; + _data._initialized = true; + } + public: + _data_t _data; + }; + + // Member template for adding the named member to a statement + template + struct _member_t + { + _impl_t limit; + _impl_t& operator()() { return limit; } + const _impl_t& operator()() const { return limit; } + + template + static auto _get_member(T t) -> decltype(t.limit) + { + return t.limit; } }; - bool _initialized = false; - interpretable_t _value; + // Additional methods for the statement + template + struct _methods_t + { + }; }; struct no_limit_t @@ -110,6 +171,33 @@ namespace sqlpp using _traits = make_traits; using _recursive_traits = make_recursive_traits<>; + // Data + using _data_t = no_data_t; + + // Member implementation with data and methods + template + struct _impl_t + { + _data_t _data; + }; + + // Member template for adding the named member to a statement + template + struct _member_t + { + using _data_t = no_data_t; + + _impl_t no_limit; + _impl_t& operator()() { return no_limit; } + const _impl_t& operator()() const { return no_limit; } + + template + static auto _get_member(T t) -> decltype(t.no_limit) + { + return t.no_limit; + } + }; + template struct _methods_t { @@ -121,23 +209,23 @@ namespace sqlpp auto limit(Arg arg) -> _new_statement_t::type>> { - return { *static_cast(this), limit_t::type>{{arg}} }; + return { *static_cast(this), limit_data_t::type>{{arg}} }; } auto dynamic_limit() -> _new_statement_t> { static_assert(not std::is_same<_database_t, void>::value, "dynamic_limit must not be called in a static statement"); - return { *static_cast(this), dynamic_limit_t<_database_t>{} }; + return { *static_cast(this), dynamic_limit_data_t<_database_t>{} }; } }; }; // Interpreters template - struct serializer_t> + struct serializer_t> { - using T = dynamic_limit_t; + using T = dynamic_limit_data_t; static Context& _(const T& t, Context& context) { @@ -162,18 +250,6 @@ namespace sqlpp return context; } }; - - template - struct serializer_t - { - using T = no_limit_t; - - static Context& _(const T& t, Context& context) - { - return context; - } - }; - } } diff --git a/include/sqlpp11/vendor/offset.h b/include/sqlpp11/vendor/offset.h index dca7fd16..fd42d846 100644 --- a/include/sqlpp11/vendor/offset.h +++ b/include/sqlpp11/vendor/offset.h @@ -35,6 +35,23 @@ namespace sqlpp { namespace vendor { + // OFFSET DATA + template + struct offset_data_t + { + offset_data_t(Offset value): + _value(value) + {} + + offset_data_t(const offset_data_t&) = default; + offset_data_t(offset_data_t&&) = default; + offset_data_t& operator=(const offset_data_t&) = default; + offset_data_t& operator=(offset_data_t&&) = default; + ~offset_data_t() = default; + + Offset _value; + }; + // OFFSET template struct offset_t @@ -44,49 +61,103 @@ namespace sqlpp static_assert(is_integral_t::value, "offset requires an integral value or integral parameter"); - offset_t(Offset value): - _value(value) - {} + // Data + using _data_t = offset_data_t; - 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; + // Member implementation with data and methods + template + struct _impl_t + { + _data_t _data; + }; + + // Member template for adding the named member to a statement + template + struct _member_t + { + _impl_t offset; + _impl_t& operator()() { return offset; } + const _impl_t& operator()() const { return offset; } + + template + static auto _get_member(T t) -> decltype(t.offset) + { + return t.offset; + } + }; template struct _methods_t { }; - - Offset _value; }; + // DYNAMIC OFFSET DATA + template + struct dynamic_offset_data_t + { + dynamic_offset_data_t(): + _value(noop()) + { + } + + template + dynamic_offset_data_t(Offset value): + _initialized(true), + _value(typename wrap_operand::type(value)) + { + } + + dynamic_offset_data_t(const dynamic_offset_data_t&) = default; + dynamic_offset_data_t(dynamic_offset_data_t&&) = default; + dynamic_offset_data_t& operator=(const dynamic_offset_data_t&) = default; + dynamic_offset_data_t& operator=(dynamic_offset_data_t&&) = default; + ~dynamic_offset_data_t() = default; + + bool _initialized = false; + interpretable_t _value; + }; + + // DYNAMIC OFFSET template struct dynamic_offset_t { using _traits = make_traits; using _recursive_traits = make_recursive_traits<>; - dynamic_offset_t& _offset() { return *this; } + // Data + using _data_t = offset_data_t; - dynamic_offset_t(): - _value(noop()) - { - } + // Member implementation with data and methods + template + struct _impl_t + { + template + void set(Offset value) + { + // FIXME: Make sure that Offset does not require external tables? Need to read up on SQL + using arg_t = typename wrap_operand::type; + _data._value = arg_t{value}; + _data._initialized = true; + } + public: + _data_t _data; + }; - template - dynamic_offset_t(Offset value): - _initialized(true), - _value(typename wrap_operand::type(value)) - { - } + // Member template for adding the named member to a statement + template + struct _member_t + { + _impl_t offset; + _impl_t& operator()() { return offset; } + const _impl_t& operator()() const { return offset; } - 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; + template + static auto _get_member(T t) -> decltype(t.offset) + { + return t.offset; + } + }; template struct _methods_t @@ -110,6 +181,33 @@ namespace sqlpp using _traits = make_traits; using _recursive_traits = make_recursive_traits<>; + // Data + using _data_t = no_data_t; + + // Member implementation with data and methods + template + struct _impl_t + { + _data_t _data; + }; + + // Member template for adding the named member to a statement + template + struct _member_t + { + using _data_t = no_data_t; + + _impl_t no_offset; + _impl_t& operator()() { return no_offset; } + const _impl_t& operator()() const { return no_offset; } + + template + static auto _get_member(T t) -> decltype(t.no_offset) + { + return t.no_offset; + } + }; + template struct _methods_t { @@ -121,14 +219,14 @@ namespace sqlpp auto offset(Arg arg) -> _new_statement_t::type>> { - return { *static_cast(this), offset_t::type>{{arg}} }; + return { *static_cast(this), offset_data_t::type>{{arg}} }; } auto dynamic_offset() -> _new_statement_t> { static_assert(not std::is_same<_database_t, void>::value, "dynamic_offset must not be called in a static statement"); - return { *static_cast(this), dynamic_offset_t<_database_t>{} }; + return { *static_cast(this), dynamic_offset_data_t<_database_t>{} }; } }; }; @@ -162,17 +260,6 @@ namespace sqlpp return context; } }; - - template - struct serializer_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 f60537eb..cd9e89d6 100644 --- a/include/sqlpp11/vendor/order_by.h +++ b/include/sqlpp11/vendor/order_by.h @@ -39,73 +39,133 @@ namespace sqlpp { namespace vendor { - template - struct order_by_t + // ORDER BY DATA + template + struct order_by_data_t { - using _traits = make_traits; - using _recursive_traits = make_recursive_traits; - - using _is_dynamic = typename std::conditional::value, std::false_type, std::true_type>::type; - - static_assert(_is_dynamic::value or sizeof...(Expressions), "at least one sort-order expression required in order_by()"); - - static_assert(not ::sqlpp::detail::has_duplicates::value, "at least one duplicate argument detected in order_by()"); - - static_assert(::sqlpp::detail::all_t::value...>::value, "at least one argument is not a sort order expression in order_by()"); - - order_by_t& _order_by() { return *this; } - - order_by_t(Expressions... expressions): + order_by_data_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 - struct _methods_t - { - template - void add_order_by_ntc(Expression expression) - { - add_order_by(expression); - } - - template - void add_order_by(Expression expression) - { - static_assert(_is_dynamic::value, "add_order_by must not be called for static order_by"); - static_assert(is_sort_order_t::value, "invalid expression argument in add_order_by()"); - static_assert(TableCheckRequired::value or Policies::template _no_unknown_tables::value, "expression uses tables unknown to this statement in add_order_by()"); - - using ok = ::sqlpp::detail::all_t<_is_dynamic::value, is_sort_order_t::value>; - - _add_order_by_impl(expression, ok()); // dispatch to prevent compile messages after the static_assert - } - - private: - template - void _add_order_by_impl(Expression expression, const std::true_type&) - { - return static_cast(this)->_order_by()._dynamic_expressions.emplace_back(expression); - } - - template - void _add_order_by_impl(Expression expression, const std::false_type&); - }; + order_by_data_t(const order_by_data_t&) = default; + order_by_data_t(order_by_data_t&&) = default; + order_by_data_t& operator=(const order_by_data_t&) = default; + order_by_data_t& operator=(order_by_data_t&&) = default; + ~order_by_data_t() = default; std::tuple _expressions; vendor::interpretable_list_t _dynamic_expressions; }; + // ORDER BY + template + struct order_by_t + { + using _traits = make_traits; + using _recursive_traits = make_recursive_traits; + + using _is_dynamic = typename std::conditional::value, std::false_type, std::true_type>::type; + + static_assert(_is_dynamic::value or sizeof...(Expressions), "at least one expression (e.g. a column) required in order_by()"); + + static_assert(not ::sqlpp::detail::has_duplicates::value, "at least one duplicate argument detected in order_by()"); + + static_assert(::sqlpp::detail::all_t::value...>::value, "at least one argument is not an expression in order_by()"); + + // Data + using _data_t = select_flag_list_data_t; + + // Member implementation with data and methods + template + struct _impl_t + { + template + void add_ntc(Expression expression) + { + add(expression); + } + + template + void add(Expression expression) + { + static_assert(_is_dynamic::value, "add() must not be called for static order_by"); + static_assert(is_expression_t::value, "invalid expression argument in order_by::add()"); + static_assert(TableCheckRequired::value or Policies::template _no_unknown_tables::value, "expression uses tables unknown to this statement in order_by::add()"); + + using ok = ::sqlpp::detail::all_t<_is_dynamic::value, is_expression_t::value>; + + _add_impl(expression, ok()); // dispatch to prevent compile messages after the static_assert + } + + private: + template + void _add_impl(Expression expression, const std::true_type&) + { + return _data._dynamic_expressions.emplace_back(expression); + } + + template + void _add_impl(Expression expression, const std::false_type&); + public: + _data_t _data; + }; + + // Member template for adding the named member to a statement + template + struct _member_t + { + using _data_t = order_by_data_t; + + _impl_t order_by; + _impl_t& operator()() { return order_by; } + const _impl_t& operator()() const { return order_by; } + + template + static auto _get_member(T t) -> decltype(t.order_by) + { + return t.order_by; + } + }; + + template + struct _methods_t + { + }; + }; + + // NO ORDER BY YET struct no_order_by_t { using _traits = make_traits; using _recursive_traits = make_recursive_traits<>; + // Data + using _data_t = no_data_t; + + // Member implementation with data and methods + template + struct _impl_t + { + _data_t _data; + }; + + // Member template for adding the named member to a statement + template + struct _member_t + { + using _data_t = no_data_t; + + _impl_t no_order_by; + _impl_t& operator()() { return no_order_by; } + const _impl_t& operator()() const { return no_order_by; } + + template + static auto _get_member(T t) -> decltype(t.no_order_by) + { + return t.no_order_by; + } + }; + template struct _methods_t { @@ -117,7 +177,7 @@ namespace sqlpp auto order_by(Args... args) -> _new_statement_t> { - return { *static_cast(this), order_by_t{args...} }; + return { *static_cast(this), order_by_data_t{args...} }; } template @@ -125,16 +185,16 @@ namespace sqlpp -> _new_statement_t> { static_assert(not std::is_same<_database_t, void>::value, "dynamic_order_by must not be called in a static statement"); - return { *static_cast(this), vendor::order_by_t<_database_t, Args...>{args...} }; + return { *static_cast(this), order_by_data_t<_database_t, Args...>{args...} }; } }; }; // Interpreters template - struct serializer_t> + struct serializer_t> { - using T = order_by_t; + using T = order_by_data_t; static Context& _(const T& t, Context& context) { @@ -148,18 +208,6 @@ namespace sqlpp return context; } }; - - template - struct serializer_t - { - using T = no_order_by_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 111d24ee..735e29e8 100644 --- a/include/sqlpp11/vendor/select_flag_list.h +++ b/include/sqlpp11/vendor/select_flag_list.h @@ -38,7 +38,7 @@ namespace sqlpp { namespace vendor { - // SELECTED COLUMNS DATA + // SELECTED FLAGS DATA template struct select_flag_list_data_t { diff --git a/include/sqlpp11/vendor/where.h b/include/sqlpp11/vendor/where.h index 4c164b34..b865a38e 100644 --- a/include/sqlpp11/vendor/where.h +++ b/include/sqlpp11/vendor/where.h @@ -38,6 +38,7 @@ namespace sqlpp { namespace vendor { + // WHERE DATA template struct where_data_t {