From d062c1a0d8066f6528d03aae3e13ce6970e38989 Mon Sep 17 00:00:00 2001 From: rbock Date: Thu, 15 May 2014 08:00:03 +0200 Subject: [PATCH 01/16] Started to rewrite traits and recursive traits traits are shorter and easier to identify by using tags in a variadic template recursive traits can be automatically derived, which makes it much easier to add new traits to be handed through the expression tree. --- include/sqlpp11/alias.h | 11 ++----- include/sqlpp11/any.h | 9 ++---- include/sqlpp11/avg.h | 10 ++---- include/sqlpp11/boolean.h | 7 +---- include/sqlpp11/column.h | 23 +++++++------- include/sqlpp11/count.h | 10 ++---- include/sqlpp11/default_value.h | 5 ++- include/sqlpp11/exists.h | 10 ++---- include/sqlpp11/floating_point.h | 8 +---- include/sqlpp11/functions.h | 12 ++++--- include/sqlpp11/integral.h | 7 ----- include/sqlpp11/join.h | 9 +++--- include/sqlpp11/max.h | 10 ++---- include/sqlpp11/min.h | 10 ++---- include/sqlpp11/multi_column.h | 9 ++++-- include/sqlpp11/no_value.h | 5 --- include/sqlpp11/null.h | 5 ++- include/sqlpp11/on.h | 4 ++- include/sqlpp11/parameter.h | 10 ++---- include/sqlpp11/result_row.h | 4 +-- include/sqlpp11/select_flags.h | 21 ++++--------- include/sqlpp11/some.h | 8 ++--- include/sqlpp11/sort_order.h | 3 +- include/sqlpp11/sum.h | 8 ++--- include/sqlpp11/table.h | 11 +++++-- include/sqlpp11/table_alias.h | 13 ++++---- include/sqlpp11/text.h | 5 --- include/sqlpp11/tvin.h | 11 ++++--- include/sqlpp11/vendor/assignment.h | 35 ++++++++++++++------- include/sqlpp11/vendor/concat.h | 3 +- include/sqlpp11/vendor/expression.h | 15 ++++++--- include/sqlpp11/vendor/extra_tables.h | 6 ++-- include/sqlpp11/vendor/from.h | 7 +++-- include/sqlpp11/vendor/group_by.h | 6 ++-- include/sqlpp11/vendor/having.h | 6 ++-- include/sqlpp11/vendor/in.h | 3 +- include/sqlpp11/vendor/insert_value.h | 6 ++-- include/sqlpp11/vendor/insert_value_list.h | 16 +++++----- include/sqlpp11/vendor/is_null.h | 3 +- include/sqlpp11/vendor/like.h | 3 +- include/sqlpp11/vendor/limit.h | 9 ++++-- include/sqlpp11/vendor/offset.h | 9 ++++-- include/sqlpp11/vendor/order_by.h | 6 ++-- include/sqlpp11/vendor/select_column_list.h | 6 ++-- include/sqlpp11/vendor/select_flag_list.h | 6 ++-- include/sqlpp11/vendor/single_table.h | 7 +++-- include/sqlpp11/vendor/update_list.h | 3 +- include/sqlpp11/vendor/using.h | 6 ++-- include/sqlpp11/vendor/where.h | 9 ++++-- include/sqlpp11/vendor/wrap_operand.h | 12 ++++--- include/sqlpp11/verbatim_table.h | 2 -- 51 files changed, 218 insertions(+), 224 deletions(-) diff --git a/include/sqlpp11/alias.h b/include/sqlpp11/alias.h index 39f3bb52..da2b5f9a 100644 --- a/include/sqlpp11/alias.h +++ b/include/sqlpp11/alias.h @@ -33,18 +33,13 @@ namespace sqlpp template struct expression_alias_t { + using _traits = make_traits_t, tag::named_expression>; + using _recursive_traits = make_recursive_traits_t; + static_assert(is_expression_t::value, "invalid argument for an expression alias"); static_assert(not is_alias_t::value, "cannot create an alias of an alias"); - struct _value_type: Expression::_value_type - { - using _is_expression = std::false_type; - using _is_named_expression = std::true_type; - using _is_alias = std::true_type; - }; - using _name_t = typename AliasProvider::_name_t; - using _table_set = typename Expression::_table_set; Expression _expression; }; diff --git a/include/sqlpp11/any.h b/include/sqlpp11/any.h index 1f8a55b5..fa7eb456 100644 --- a/include/sqlpp11/any.h +++ b/include/sqlpp11/any.h @@ -37,11 +37,8 @@ namespace sqlpp template struct any_t { - struct _value_type: public Select::_value_type::_base_value_type - { - using _is_expression = std::false_type; - using _is_multi_expression = std::true_type; // must not be named or used with +,-,*,/, etc - }; + using _traits = make_traits_t, tag::multi_expression>; + using _recursive_traits = make_recursive_traits_t; + static_assert(is_noop::value or std::is_same::value, "avg() used with flag other than 'distinct'"); static_assert(is_numeric_t::value, "avg() requires a value expression as argument"); - struct _value_type: public floating_point - { - using _is_named_expression = std::true_type; - }; - - using _table_set = typename Expr::_table_set; - struct _name_t { static constexpr const char* _get_name() { return "AVG"; } diff --git a/include/sqlpp11/boolean.h b/include/sqlpp11/boolean.h index 66e80853..ee8a3dc4 100644 --- a/include/sqlpp11/boolean.h +++ b/include/sqlpp11/boolean.h @@ -42,16 +42,11 @@ namespace sqlpp // boolean value type struct boolean { - using _value_type = boolean; - using _base_value_type = boolean; - using _is_boolean = std::true_type; - using _is_value = std::true_type; - using _is_expression = std::true_type; using _cpp_value_type = bool; struct _parameter_t { - using _value_type = boolean; + using _value_type = boolean; // FIXME _parameter_t(): _value(false), diff --git a/include/sqlpp11/column.h b/include/sqlpp11/column.h index 8292f376..8c227a30 100644 --- a/include/sqlpp11/column.h +++ b/include/sqlpp11/column.h @@ -45,21 +45,20 @@ namespace sqlpp struct column_t: public ColumnSpec::_value_type::template expression_operators>, public ColumnSpec::_value_type::template column_operators> { - using _is_column = std::true_type; + using _traits = make_traits_t, tag::column, tag::expression, tag::named_expression>; + struct _recursive_traits + { + using _provided_tables = detail::type_set<>; + using _required_tables = detail::type_set<_table>; + }; + using _spec_t = ColumnSpec; using _table = Table; - using _table_set = detail::type_set<_table>; - using _column_type = typename ColumnSpec::_column_type; - struct _value_type: ColumnSpec::_value_type - { - using _is_expression = std::true_type; - using _is_named_expression = std::true_type; - using _is_alias = std::false_type; - }; - template - using _is_valid_operand = typename _value_type::template _is_valid_operand; + using _column_type = typename _spec_t::_column_type; + using _name_t = typename _spec_t::_name_t; - using _name_t = typename ColumnSpec::_name_t; + template + using _is_valid_operand = typename value_type_of::template _is_valid_operand; column_t() = default; column_t(const column_t&) = default; diff --git a/include/sqlpp11/count.h b/include/sqlpp11/count.h index dc54437f..8cdd61df 100644 --- a/include/sqlpp11/count.h +++ b/include/sqlpp11/count.h @@ -37,16 +37,12 @@ namespace sqlpp template struct count_t: public sqlpp::detail::integral::template expression_operators> { + using _traits = make_traits_t, tag::expression, tag::named_expression>; + using _recursive_traits = make_recursive_traits_t; + static_assert(is_select_t; verbatim_t(std::string verbatim): _verbatim(verbatim) {} verbatim_t(const verbatim_t&) = default; @@ -102,9 +103,10 @@ namespace sqlpp template struct value_list_t // to be used in .in() method { + using _traits = make_traits_t; + using _recursive_traits = make_recursive_traits_t; + static_assert(is_value_t::value, "max() requires a value expression as argument"); - struct _value_type: public Expr::_value_type::_base_value_type - { - using _is_named_expression = std::true_type; - }; - - using _table_set = typename Expr::_table_set; - struct _name_t { static constexpr const char* _get_name() { return "MAX"; } diff --git a/include/sqlpp11/min.h b/include/sqlpp11/min.h index c7d9f9e0..3199ba8d 100644 --- a/include/sqlpp11/min.h +++ b/include/sqlpp11/min.h @@ -36,15 +36,11 @@ namespace sqlpp template struct min_t: public Expr::_value_type::template expression_operators> { + using _traits = make_traits_t, tag::expression, tag::named_expression>; + using _recursive_traits = make_recursive_traits_t; struct _name_t { @@ -54,7 +51,6 @@ namespace sqlpp const T& operator()() const { return some; } }; }; - using _table_set = typename Select::_table_set; some_t(Select select): _select(select) diff --git a/include/sqlpp11/sort_order.h b/include/sqlpp11/sort_order.h index d0616449..8f70b3c8 100644 --- a/include/sqlpp11/sort_order.h +++ b/include/sqlpp11/sort_order.h @@ -41,7 +41,8 @@ namespace sqlpp struct sort_order_t { using _is_sort_order = std::true_type; - using _table_set = typename Expression::_table_set; + using _provided_tables = detail::type_set<>; + using _required_tables = typename Expression::_required_tables; Expression _expression; }; diff --git a/include/sqlpp11/sum.h b/include/sqlpp11/sum.h index 745e48c3..b4a92611 100644 --- a/include/sqlpp11/sum.h +++ b/include/sqlpp11/sum.h @@ -36,14 +36,12 @@ namespace sqlpp template struct sum_t: public Expr::_value_type::template expression_operators> { + using _traits = make_traits_t, tag::expression, tag::named_expression>; + using _recursive_traits = make_recursive_traits_t; + using _traits = make_traits, ::sqlpp::tag::multi_expression>; + using _recursive_traits = make_recursive_traits; + using _traits = make_traits; + using _recursive_traits = make_recursive_traits; static_assert(is_noop::value or std::is_same::value, "avg() used with flag other than 'distinct'"); static_assert(is_numeric_t::value, "avg() requires a value expression as argument"); diff --git a/include/sqlpp11/boolean.h b/include/sqlpp11/boolean.h index ee8a3dc4..d5935484 100644 --- a/include/sqlpp11/boolean.h +++ b/include/sqlpp11/boolean.h @@ -42,6 +42,7 @@ namespace sqlpp // boolean value type struct boolean { + using _tag = ::sqlpp::tag::boolean; using _cpp_value_type = bool; struct _parameter_t diff --git a/include/sqlpp11/column.h b/include/sqlpp11/column.h index 8c227a30..8795a08b 100644 --- a/include/sqlpp11/column.h +++ b/include/sqlpp11/column.h @@ -45,11 +45,11 @@ namespace sqlpp struct column_t: public ColumnSpec::_value_type::template expression_operators>, public ColumnSpec::_value_type::template column_operators> { - using _traits = make_traits_t, tag::column, tag::expression, tag::named_expression>; + using _traits = make_traits; struct _recursive_traits { using _provided_tables = detail::type_set<>; - using _required_tables = detail::type_set<_table>; + using _required_tables = detail::type_set; }; using _spec_t = ColumnSpec; @@ -58,7 +58,7 @@ namespace sqlpp using _name_t = typename _spec_t::_name_t; template - using _is_valid_operand = typename value_type_of::template _is_valid_operand; + using _is_valid_operand = typename ColumnSpec::_value_type::template _is_valid_operand; column_t() = default; column_t(const column_t&) = default; diff --git a/include/sqlpp11/count.h b/include/sqlpp11/count.h index 8cdd61df..eec747be 100644 --- a/include/sqlpp11/count.h +++ b/include/sqlpp11/count.h @@ -37,8 +37,8 @@ namespace sqlpp template struct count_t: public sqlpp::detail::integral::template expression_operators> { - using _traits = make_traits_t, tag::expression, tag::named_expression>; - using _recursive_traits = make_recursive_traits_t; + using _traits = make_traits; + using _recursive_traits = make_recursive_traits::value, "exists() requires a select expression as argument"); diff --git a/include/sqlpp11/floating_point.h b/include/sqlpp11/floating_point.h index 2411305a..48bd70b9 100644 --- a/include/sqlpp11/floating_point.h +++ b/include/sqlpp11/floating_point.h @@ -41,6 +41,7 @@ namespace sqlpp // floating_point value type struct floating_point { + using _tag = ::sqlpp::tag::floating_point; using _cpp_value_type = double; struct _parameter_t diff --git a/include/sqlpp11/functions.h b/include/sqlpp11/functions.h index 86ba048b..c05f46a3 100644 --- a/include/sqlpp11/functions.h +++ b/include/sqlpp11/functions.h @@ -50,15 +50,15 @@ namespace sqlpp { using _provided_tables = detail::type_set<>; using _required_tables = ::sqlpp::detail::type_set<>; - static_assert(not is_value_t::value, "value() is to be called with non-sql-type like int, or string"); + static_assert(not is_expression_t::value, "value() is to be called with non-sql-type like int, or string"); return { t }; } template // Csaba Csoma suggests: unsafe_sql instead of verbatim struct verbatim_t: public ValueType::template expression_operators> { - using _traits = make_traits_t; - using _recursive_traits = make_recursive_traits_t; + using _traits = make_traits>; + using _recursive_traits = make_recursive_traits<>; using _container_t = Container; @@ -148,7 +148,7 @@ namespace sqlpp template auto value_list(Container c) -> value_list_t { - static_assert(not is_value_t::value, "value_list() is to be called with a container of non-sql-type like std::vector, or std::list(string)"); + static_assert(not is_expression_t::value, "value_list() is to be called with a container of non-sql-type like std::vector, or std::list(string)"); return { c }; } diff --git a/include/sqlpp11/integral.h b/include/sqlpp11/integral.h index 6e65e4fb..34366d85 100644 --- a/include/sqlpp11/integral.h +++ b/include/sqlpp11/integral.h @@ -42,6 +42,7 @@ namespace sqlpp // integral value type struct integral { + using _tag = ::sqlpp::tag::integral; using _cpp_value_type = int64_t; struct _parameter_t diff --git a/include/sqlpp11/join.h b/include/sqlpp11/join.h index 66b08e05..d4f96abf 100644 --- a/include/sqlpp11/join.h +++ b/include/sqlpp11/join.h @@ -77,8 +77,8 @@ namespace sqlpp template struct join_t { - using _traits = make_traits_t; - using _recursive_traits = make_recursive_traits_t; + using _traits = make_traits; + using _recursive_traits = make_recursive_traits; static_assert(is_table_t::value, "lhs argument for join() has to be a table or join"); static_assert(is_table_t::value, "rhs argument for join() has to be a table"); diff --git a/include/sqlpp11/max.h b/include/sqlpp11/max.h index 683a0db7..faf903fb 100644 --- a/include/sqlpp11/max.h +++ b/include/sqlpp11/max.h @@ -34,12 +34,12 @@ namespace sqlpp namespace vendor { template - struct max_t: public Expr::_value_type::template expression_operators> + struct max_t: public value_type_of::template expression_operators> { - using _traits = make_traits_t, tag::expression, tag::named_expression>; - using _recursive_traits = make_recursive_traits_t; + using _traits = make_traits, ::sqlpp::tag::expression, ::sqlpp::tag::named_expression>; + using _recursive_traits = make_recursive_traits; - static_assert(is_value_t::value, "min() requires a value expression as argument"); + static_assert(is_expression_t::value, "min() requires a value expression as argument"); struct _name_t { @@ -87,7 +87,7 @@ namespace sqlpp template auto min(T t) -> typename vendor::min_t> { - static_assert(is_value_t>::value, "min() requires a value expression as argument"); + static_assert(is_expression_t>::value, "min() requires a value expression as argument"); return { t }; } diff --git a/include/sqlpp11/multi_column.h b/include/sqlpp11/multi_column.h index 52c3340f..d61c2aaf 100644 --- a/include/sqlpp11/multi_column.h +++ b/include/sqlpp11/multi_column.h @@ -41,8 +41,8 @@ namespace sqlpp template struct multi_column_t { - using _traits = make_traits_t; - using _recursive_traits = make_recursive_traits_t; + using _traits = make_traits; + using _recursive_traits = make_recursive_traits; static_assert(detail::all_t::value...>::value, "multi_column parameters need to be named expressions"); @@ -76,8 +76,8 @@ namespace sqlpp template struct multi_column_alias_t { - using _traits = make_traits_t; - using _recursive_traits = make_recursive_traits_t; + using _traits = make_traits; + using _recursive_traits = make_recursive_traits; static_assert(detail::all_t::value...>::value, "multi_column parameters need to be named expressions"); diff --git a/include/sqlpp11/no_value.h b/include/sqlpp11/no_value.h index 4db1b9b1..c5ec11fa 100644 --- a/include/sqlpp11/no_value.h +++ b/include/sqlpp11/no_value.h @@ -33,6 +33,7 @@ namespace sqlpp { struct no_value_t { + using _tag = void; template struct _is_valid_operand { diff --git a/include/sqlpp11/null.h b/include/sqlpp11/null.h index 64c1f706..7119998d 100644 --- a/include/sqlpp11/null.h +++ b/include/sqlpp11/null.h @@ -33,8 +33,8 @@ namespace sqlpp { struct null_t { - using _traits = make_traits_t; - using _recursive_traits = make_recursive_traits_t<>; + using _traits = make_traits; + using _recursive_traits = make_recursive_traits<>; }; namespace vendor diff --git a/include/sqlpp11/on.h b/include/sqlpp11/on.h index 47e6dcb2..caa23bc6 100644 --- a/include/sqlpp11/on.h +++ b/include/sqlpp11/on.h @@ -37,8 +37,8 @@ namespace sqlpp template struct on_t { - using _traits = make_traits_t; - using _recursive_traits = make_recursive_traits_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; diff --git a/include/sqlpp11/parameter.h b/include/sqlpp11/parameter.h index c8df02ae..d13afdbf 100644 --- a/include/sqlpp11/parameter.h +++ b/include/sqlpp11/parameter.h @@ -36,8 +36,8 @@ namespace sqlpp template struct parameter_t: public ValueType::template expression_operators> { - using _traits = make_traits_t; - using _recursive_traits = make_recursive_traits_t<>; + using _traits = make_traits; + using _recursive_traits = make_recursive_traits<>; using _instance_t = typename NameType::_name_t::template _member_t; @@ -78,7 +78,7 @@ namespace sqlpp auto parameter(const ValueType&, const AliasProvider&) -> parameter_t { - static_assert(is_value_t::value, "first argument is not a value type"); + static_assert(is_expression_t::value, "first argument is not a value type"); static_assert(is_alias_provider_t::value, "second argument is not an alias provider"); return {}; } diff --git a/include/sqlpp11/select_flags.h b/include/sqlpp11/select_flags.h index 4439024c..3462f224 100644 --- a/include/sqlpp11/select_flags.h +++ b/include/sqlpp11/select_flags.h @@ -37,8 +37,8 @@ namespace sqlpp // standard select flags struct all_t { - using _traits = make_traits_t; - using _recursive_traits = make_recursive_traits_t<>; + using _traits = make_traits; + using _recursive_traits = make_recursive_traits<>; }; static constexpr all_t all = {}; @@ -57,8 +57,8 @@ namespace sqlpp struct distinct_t { - using _traits = make_traits_t; - using _recursive_traits = make_recursive_traits_t<>; + using _traits = make_traits; + using _recursive_traits = make_recursive_traits<>; }; static constexpr distinct_t distinct = {}; @@ -77,8 +77,8 @@ namespace sqlpp struct straight_join_t { - using _traits = make_traits_t; - using _recursive_traits = make_recursive_traits_t<>; + using _traits = make_traits; + using _recursive_traits = make_recursive_traits<>; }; static constexpr straight_join_t straight_join = {}; diff --git a/include/sqlpp11/some.h b/include/sqlpp11/some.h index 501004b0..5fe64cac 100644 --- a/include/sqlpp11/some.h +++ b/include/sqlpp11/some.h @@ -37,8 +37,8 @@ namespace sqlpp template struct some_t { - using _traits = make_traits_t, tag::multi_expression>; - using _recursive_traits = make_recursive_traits_t; struct _name_t { @@ -87,7 +87,7 @@ namespace sqlpp auto some(T t) -> typename vendor::some_t> { static_assert(is_select_t>::value, "some() requires a single column select expression as argument"); - static_assert(is_value_t>::value, "some() requires a single column select expression as argument"); + static_assert(is_expression_t>::value, "some() requires a single column select expression as argument"); return { t }; } diff --git a/include/sqlpp11/sum.h b/include/sqlpp11/sum.h index b4a92611..d258ca2d 100644 --- a/include/sqlpp11/sum.h +++ b/include/sqlpp11/sum.h @@ -34,10 +34,10 @@ namespace sqlpp namespace vendor { template - struct sum_t: public Expr::_value_type::template expression_operators> + struct sum_t: public value_type_of::template expression_operators> { - using _traits = make_traits_t, tag::expression, tag::named_expression>; - using _recursive_traits = make_recursive_traits_t
; }; - static_assert(Table::_required_tables::size::value == 0, "table aliases must not depend on external tables"); + static_assert(required_tables_of
::size::value == 0, "table aliases must not depend on external tables"); using _name_t = typename AliasProvider::_name_t; using _column_tuple_t = std::tuple...>; diff --git a/include/sqlpp11/text.h b/include/sqlpp11/text.h index e0b4998a..dbb32118 100644 --- a/include/sqlpp11/text.h +++ b/include/sqlpp11/text.h @@ -41,6 +41,7 @@ namespace sqlpp // text value type struct text { + using _tag = ::sqlpp::tag::text; using _cpp_value_type = std::string; struct _parameter_t diff --git a/include/sqlpp11/tvin.h b/include/sqlpp11/tvin.h index f6444bff..a838296e 100644 --- a/include/sqlpp11/tvin.h +++ b/include/sqlpp11/tvin.h @@ -32,14 +32,15 @@ #include #include #include +#include namespace sqlpp { template struct tvin_t { - using _traits = make_traits_t, tag::operand, tag::expression>; - using _recursive_traits = make_recursive_traits_t; + using _traits = make_traits, tag::expression>; + using _recursive_traits = make_recursive_traits; tvin_t(Operand operand): _value(operand) @@ -55,7 +56,7 @@ namespace sqlpp return _value._is_trivial(); } - _operand_t _value; + Operand _value; }; namespace vendor diff --git a/include/sqlpp11/type_traits.h b/include/sqlpp11/type_traits.h index b4d39bf8..795e0407 100644 --- a/include/sqlpp11/type_traits.h +++ b/include/sqlpp11/type_traits.h @@ -28,7 +28,7 @@ #define SQLPP_TYPE_TRAITS_H #include -#include +#include namespace sqlpp { @@ -40,8 +40,12 @@ namespace sqlpp template\ struct is_##name##_impl::value>::type>: std::true_type {};\ }\ + namespace tag\ + {\ + struct name{};\ + };\ template\ - struct is_##name##_t: detail::is_##name##_impl {}; + using is_##name##_t = detail::is_element_of; #define SQLPP_IS_COLUMN_TRAIT_GENERATOR(name) \ namespace detail\ @@ -77,13 +81,20 @@ namespace sqlpp struct connector_##name##_t: detail::connector_##name##_impl {}; SQLPP_IS_VALUE_TRAIT_GENERATOR(boolean); - SQLPP_IS_VALUE_TRAIT_GENERATOR(numeric); SQLPP_IS_VALUE_TRAIT_GENERATOR(integral); SQLPP_IS_VALUE_TRAIT_GENERATOR(floating_point); + template + using is_numeric_t = detail::any_t< + detail::is_element_of::value, + detail::is_element_of::value>; SQLPP_IS_VALUE_TRAIT_GENERATOR(text); - SQLPP_IS_VALUE_TRAIT_GENERATOR(value); SQLPP_IS_VALUE_TRAIT_GENERATOR(expression); SQLPP_IS_VALUE_TRAIT_GENERATOR(named_expression); + namespace tag + { + template + using named_expression_if = typename std::conditional::type; + } SQLPP_IS_VALUE_TRAIT_GENERATOR(multi_expression); SQLPP_IS_VALUE_TRAIT_GENERATOR(alias); SQLPP_IS_VALUE_TRAIT_GENERATOR(select_flag); @@ -94,41 +105,82 @@ namespace sqlpp SQLPP_IS_COLUMN_TRAIT_GENERATOR(can_be_null); SQLPP_IS_COLUMN_TRAIT_GENERATOR(trivial_value_is_null); - SQLPP_TYPE_TRAIT_GENERATOR(is_noop); - SQLPP_TYPE_TRAIT_GENERATOR(is_table); - SQLPP_TYPE_TRAIT_GENERATOR(is_join); - SQLPP_TYPE_TRAIT_GENERATOR(is_pseudo_table); - SQLPP_TYPE_TRAIT_GENERATOR(is_column); - SQLPP_TYPE_TRAIT_GENERATOR(is_select); - SQLPP_TYPE_TRAIT_GENERATOR(is_select_flag_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); - SQLPP_TYPE_TRAIT_GENERATOR(is_where); - SQLPP_TYPE_TRAIT_GENERATOR(is_group_by); - SQLPP_TYPE_TRAIT_GENERATOR(is_having); - SQLPP_TYPE_TRAIT_GENERATOR(is_order_by); - SQLPP_TYPE_TRAIT_GENERATOR(is_limit); - SQLPP_TYPE_TRAIT_GENERATOR(is_offset); - SQLPP_TYPE_TRAIT_GENERATOR(is_using); - SQLPP_TYPE_TRAIT_GENERATOR(is_column_list); - SQLPP_TYPE_TRAIT_GENERATOR(is_multi_column); - SQLPP_TYPE_TRAIT_GENERATOR(is_value_list); - SQLPP_TYPE_TRAIT_GENERATOR(is_assignment); - SQLPP_TYPE_TRAIT_GENERATOR(is_update_list); - SQLPP_TYPE_TRAIT_GENERATOR(is_insert_list); - SQLPP_TYPE_TRAIT_GENERATOR(is_insert_value); - SQLPP_TYPE_TRAIT_GENERATOR(is_insert_value_list); - SQLPP_TYPE_TRAIT_GENERATOR(is_sort_order); + SQLPP_IS_VALUE_TRAIT_GENERATOR(noop); + SQLPP_IS_VALUE_TRAIT_GENERATOR(table); + SQLPP_IS_VALUE_TRAIT_GENERATOR(join); + SQLPP_IS_VALUE_TRAIT_GENERATOR(pseudo_table); + SQLPP_IS_VALUE_TRAIT_GENERATOR(column); + SQLPP_IS_VALUE_TRAIT_GENERATOR(select); + SQLPP_IS_VALUE_TRAIT_GENERATOR(select_flag_list); + SQLPP_IS_VALUE_TRAIT_GENERATOR(select_column_list); + SQLPP_IS_VALUE_TRAIT_GENERATOR(from); + SQLPP_IS_VALUE_TRAIT_GENERATOR(on); + SQLPP_IS_VALUE_TRAIT_GENERATOR(dynamic); + SQLPP_IS_VALUE_TRAIT_GENERATOR(where); + SQLPP_IS_VALUE_TRAIT_GENERATOR(group_by); + SQLPP_IS_VALUE_TRAIT_GENERATOR(having); + SQLPP_IS_VALUE_TRAIT_GENERATOR(order_by); + SQLPP_IS_VALUE_TRAIT_GENERATOR(limit); + SQLPP_IS_VALUE_TRAIT_GENERATOR(offset); + SQLPP_IS_VALUE_TRAIT_GENERATOR(using_); + SQLPP_IS_VALUE_TRAIT_GENERATOR(column_list); + SQLPP_IS_VALUE_TRAIT_GENERATOR(multi_column); + SQLPP_IS_VALUE_TRAIT_GENERATOR(value_list); + SQLPP_IS_VALUE_TRAIT_GENERATOR(assignment); + SQLPP_IS_VALUE_TRAIT_GENERATOR(update_list); + SQLPP_IS_VALUE_TRAIT_GENERATOR(insert_list); + SQLPP_IS_VALUE_TRAIT_GENERATOR(insert_value); + SQLPP_IS_VALUE_TRAIT_GENERATOR(insert_value_list); + SQLPP_IS_VALUE_TRAIT_GENERATOR(sort_order); + SQLPP_IS_VALUE_TRAIT_GENERATOR(parameter); + SQLPP_TYPE_TRAIT_GENERATOR(requires_braces); - SQLPP_TYPE_TRAIT_GENERATOR(is_parameter); SQLPP_CONNECTOR_TRAIT_GENERATOR(null_result_is_trivial_value); SQLPP_CONNECTOR_TRAIT_GENERATOR(assert_result_validity); template class IsTag> using copy_type_trait = typename std::conditional::value, std::true_type, std::false_type>::type; + + template + struct make_traits + { + using _value_type = ValueType; + using _tags = detail::make_type_set_t; + }; + template + struct make_recursive_traits + { + }; + + namespace detail + { + template + struct value_type_of_impl + { + using type = typename T::_traits::_value_type; + }; + + template + struct required_table_of_impl + { + using type = typename T::_recursive_traits::_required_tables; + }; + + template + struct provided_table_of_impl + { + using type = typename T::_recursive_traits::_provided_tables; + }; + } + template + using value_type_of = typename detail::value_type_of_impl::type; + + template + using required_tables_of = typename detail::required_table_of_impl::type; + + template + using provided_tables_of = typename detail::provided_table_of_impl::type; } #endif diff --git a/include/sqlpp11/vendor/assignment.h b/include/sqlpp11/vendor/assignment.h index 321a1b11..8026a3e1 100644 --- a/include/sqlpp11/vendor/assignment.h +++ b/include/sqlpp11/vendor/assignment.h @@ -59,26 +59,21 @@ namespace sqlpp template bool is_trivial(const T& t) { - return is_trivial_t::_(t); + return is_trivial_t>::_(t); } template struct assignment_t { - struct _traits - { - using _is_assignment = std::true_type; - using value_type = no_value; - }; - - using _recursive_traits = make_recursive_traits_t; + using _traits = make_traits; + using _recursive_traits = make_recursive_traits; using _column_t = Lhs; using _value_t = Lhs; static_assert(can_be_null_t<_column_t>::value ? true : not std::is_same<_value_t, null_t>::value, "column must not be null"); - assignment_t(_column_t lhs, value_type rhs): + assignment_t(_column_t lhs, _value_t rhs): _lhs(lhs), _rhs(rhs) {} @@ -101,7 +96,7 @@ namespace sqlpp static Context& _(const T& t, Context& context) { if ((trivial_value_is_null_t::value - and is_trivial_t::_(t._rhs)) + and is_trivial_t>::_(t._rhs)) or (std::is_same::value)) { serialize(simple_column(t._lhs), context); @@ -120,15 +115,9 @@ namespace sqlpp template struct assignment_t> { - struct _traits - { - using _is_assignment = std::true_type; - using value_type = no_value; - }; + using _traits = make_traits; + using _recursive_traits = make_recursive_traits; - using _recursive_traits = make_recursive_traits_t; - - using _is_assignment = std::true_type; using _column_t = Lhs; using _value_t = tvin_t; diff --git a/include/sqlpp11/vendor/concat.h b/include/sqlpp11/vendor/concat.h index 7e1f049f..a5daa2d3 100644 --- a/include/sqlpp11/vendor/concat.h +++ b/include/sqlpp11/vendor/concat.h @@ -35,19 +35,15 @@ namespace sqlpp { namespace vendor { + // FIXME: Remove First, inherit from text_t template - struct concat_t: public First::_value_type::template expression_operators> + struct concat_t: public value_type_of::template expression_operators> { + using _traits = make_traits, ::sqlpp::tag::expression, ::sqlpp::tag::named_expression>; + using _recursive_traits = make_recursive_traits; + static_assert(sizeof...(Args) > 0, "concat requires two arguments at least"); static_assert(sqlpp::detail::all_t::value, is_text_t::value...>::value, "at least one non-text argument detected in concat()"); - using _provided_tables = detail::type_set<>; - using _required_tables = typename ::sqlpp::detail::make_joined_set::type; - - struct _value_type: public First::_value_type::_base_value_type - { - using _is_named_expression = std::true_type; - }; - struct _name_t { static constexpr const char* _get_name() { return "CONCAT"; } diff --git a/include/sqlpp11/vendor/expression.h b/include/sqlpp11/vendor/expression.h index 4cc560d1..b3c6075a 100644 --- a/include/sqlpp11/vendor/expression.h +++ b/include/sqlpp11/vendor/expression.h @@ -42,10 +42,8 @@ namespace sqlpp template struct binary_expression_t: public ::sqlpp::detail::boolean::template expression_operators> { - using _value_type = ::sqlpp::detail::boolean; - using _parameter_tuple_t = std::tuple; - using _provided_tables = detail::type_set<>; - using _required_tables = typename ::sqlpp::detail::make_joined_set::type; + using _traits = make_traits; + using _recursive_traits = make_recursive_traits; binary_expression_t(Lhs lhs, Rhs rhs): _lhs(lhs), @@ -88,10 +86,8 @@ namespace sqlpp template struct binary_expression_t: public ::sqlpp::detail::boolean::template expression_operators> { - using _value_type = ::sqlpp::detail::boolean; - using _parameter_tuple_t = std::tuple; - using _provided_tables = detail::type_set<>; - using _required_tables = typename ::sqlpp::detail::make_joined_set::type; + using _traits = make_traits; + using _recursive_traits = make_recursive_traits; binary_expression_t(Lhs lhs, Rhs rhs): _lhs(lhs), @@ -134,10 +130,8 @@ namespace sqlpp template struct unary_expression_t: public ::sqlpp::detail::boolean::template expression_operators> { - using _value_type = ::sqlpp::detail::boolean; - using _parameter_tuple_t = std::tuple; - using _provided_tables = detail::type_set<>; - using _required_tables = typename Rhs::_required_tables; + using _traits = make_traits; + using _recursive_traits = make_recursive_traits; unary_expression_t(Rhs rhs): _rhs(rhs) @@ -168,16 +162,12 @@ namespace sqlpp }; template - struct binary_expression_t: public O::_value_type::template expression_operators> + struct binary_expression_t: public value_type_of::template expression_operators> { - using _lhs_t = Lhs; - using _rhs_t = Rhs; - using _value_type = typename O::_value_type; - using _parameter_tuple_t = std::tuple<_lhs_t, _rhs_t>; - using _provided_tables = detail::type_set<>; - using _required_tables = typename ::sqlpp::detail::make_joined_set::type; + using _traits = make_traits, sqlpp::tag::expression>; + using _recursive_traits = make_recursive_traits; - binary_expression_t(_lhs_t lhs, _rhs_t rhs): + binary_expression_t(Lhs lhs, Rhs rhs): _lhs(lhs), _rhs(rhs) {} @@ -188,8 +178,8 @@ namespace sqlpp binary_expression_t& operator=(binary_expression_t&&) = default; ~binary_expression_t() = default; - _lhs_t _lhs; - _rhs_t _rhs; + Lhs _lhs; + Rhs _rhs; }; template @@ -211,10 +201,8 @@ namespace sqlpp template struct unary_expression_t: public O::_value_type::template expression_operators> { - using _value_type = typename O::_value_type; - using _parameter_tuple_t = std::tuple; - using _provided_tables = detail::type_set<>; - using _required_tables = typename Rhs::_required_tables; + using _traits = make_traits, sqlpp::tag::expression>; + using _recursive_traits = make_recursive_traits; unary_expression_t(Rhs rhs): _rhs(rhs) diff --git a/include/sqlpp11/vendor/extra_tables.h b/include/sqlpp11/vendor/extra_tables.h index b3574405..04e3b4d8 100644 --- a/include/sqlpp11/vendor/extra_tables.h +++ b/include/sqlpp11/vendor/extra_tables.h @@ -39,18 +39,15 @@ namespace sqlpp template struct extra_tables_t { - using _is_extra_tables = std::true_type; + using _traits = make_traits; + using _recursive_traits = make_recursive_traits; + + // FIXME: extra_tables must not require tables! static_assert(sizeof...(Tables), "at least one table or join argument required in extra_tables()"); - static_assert(not ::sqlpp::detail::has_duplicates::value, "at least one duplicate argument detected in extra_tables()"); - static_assert(::sqlpp::detail::all_t::value...>::value, "at least one argument is not a table or join in extra_tables()"); - using _provided_tables = ::sqlpp::detail::make_joined_set_t; - using _required_tables = ::sqlpp::detail::make_joined_set_t; - - extra_tables_t() {} @@ -68,9 +65,8 @@ namespace sqlpp struct no_extra_tables_t { - using _is_noop = std::true_type; - using _provided_tables = detail::type_set<>; - using _required_tables = ::sqlpp::detail::type_set<>; + using _traits = make_traits; + using _recursive_traits = make_recursive_traits<>; template struct _methods_t diff --git a/include/sqlpp11/vendor/field.h b/include/sqlpp11/vendor/field.h index 7cd6ec62..2e0293bb 100644 --- a/include/sqlpp11/vendor/field.h +++ b/include/sqlpp11/vendor/field.h @@ -52,7 +52,7 @@ namespace sqlpp struct make_field_t_impl { using type = field_t, trivial_value_is_null_t::value>; }; diff --git a/include/sqlpp11/vendor/from.h b/include/sqlpp11/vendor/from.h index 7107868b..7a016cde 100644 --- a/include/sqlpp11/vendor/from.h +++ b/include/sqlpp11/vendor/from.h @@ -41,9 +41,9 @@ namespace sqlpp template struct from_t { - using _is_from = std::true_type; - using _required_tables = ::sqlpp::detail::make_joined_set_t; - using _provided_tables = ::sqlpp::detail::make_joined_set_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...(Tables), "at least one table or join argument required in from()"); @@ -53,7 +53,7 @@ namespace sqlpp static_assert(::sqlpp::detail::all_t::value...>::value, "at least one argument is not a table or join in from()"); - static_assert(_required_tables::size::value == 0, "at least one table depends on another table"); + static_assert(required_tables_of::size::value == 0, "at least one table depends on another table"); from_t(Tables... tables): @@ -97,9 +97,8 @@ namespace sqlpp struct no_from_t { - using _is_noop = std::true_type; - using _provided_tables = detail::type_set<>; - using _required_tables = ::sqlpp::detail::type_set<>; + using _traits = make_traits; + using _recursive_traits = make_recursive_traits<>; template struct _methods_t diff --git a/include/sqlpp11/vendor/group_by.h b/include/sqlpp11/vendor/group_by.h index 12ca32c7..ab023f4a 100644 --- a/include/sqlpp11/vendor/group_by.h +++ b/include/sqlpp11/vendor/group_by.h @@ -43,13 +43,10 @@ namespace sqlpp 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_list_t = typename make_parameter_list_t<_parameter_tuple_t>::type; + using _traits = make_traits; + using _recursive_traits = make_recursive_traits; - using _provided_tables = detail::type_set<>; - using _required_tables = typename ::sqlpp::detail::make_joined_set::type; + 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 group_by()"); @@ -100,15 +97,14 @@ namespace sqlpp }; const group_by_t& _group_by() const { return *this; } - _parameter_tuple_t _expressions; + std::tuple _expressions; vendor::interpretable_list_t _dynamic_expressions; }; struct no_group_by_t { - using _is_noop = std::true_type; - using _provided_tables = detail::type_set<>; - using _required_tables = ::sqlpp::detail::type_set<>; + using _traits = make_traits; + using _recursive_traits = make_recursive_traits<>; template struct _methods_t diff --git a/include/sqlpp11/vendor/having.h b/include/sqlpp11/vendor/having.h index 093166e1..8c4708e6 100644 --- a/include/sqlpp11/vendor/having.h +++ b/include/sqlpp11/vendor/having.h @@ -42,18 +42,14 @@ namespace sqlpp template struct having_t { - using _is_having = std::true_type; + using _traits = make_traits; + using _recursive_traits = make_recursive_traits; + using _is_dynamic = typename std::conditional::value, std::false_type, std::true_type>::type; - using _parameter_tuple_t = std::tuple; 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()"); - using _parameter_list_t = typename make_parameter_list_t<_parameter_tuple_t>::type; - - using _provided_tables = detail::type_set<>; - using _required_tables = typename ::sqlpp::detail::make_joined_set::type; - having_t(Expressions... expressions): _expressions(expressions...) {} @@ -96,15 +92,14 @@ namespace sqlpp void _add_having_impl(Expression expression, const std::false_type&); }; - _parameter_tuple_t _expressions; + std::tuple _expressions; vendor::interpretable_list_t _dynamic_expressions; }; struct no_having_t { - using _is_noop = std::true_type; - using _provided_tables = detail::type_set<>; - using _required_tables = ::sqlpp::detail::type_set<>; + using _traits = make_traits; + using _recursive_traits = make_recursive_traits<>; template struct _methods_t diff --git a/include/sqlpp11/vendor/in.h b/include/sqlpp11/vendor/in.h index 0059c918..54fec7b7 100644 --- a/include/sqlpp11/vendor/in.h +++ b/include/sqlpp11/vendor/in.h @@ -39,14 +39,12 @@ namespace sqlpp template struct in_t: public boolean::template expression_operators> { + using _traits = make_traits; + using _recursive_traits = make_recursive_traits; + static constexpr bool _inverted = not NotInverted; static_assert(sizeof...(Args) > 0, "in() requires at least one argument"); - struct _value_type: public boolean - { - using _is_named_expression = std::true_type; - }; - struct _name_t { static constexpr const char* _get_name() { return _inverted ? "NOT IN" : "IN"; } @@ -56,8 +54,6 @@ namespace sqlpp T in; }; }; - using _provided_tables = detail::type_set<>; - using _required_tables = typename ::sqlpp::detail::make_joined_set::type; in_t(Operand operand, Args... args): _operand(operand), diff --git a/include/sqlpp11/vendor/is_null.h b/include/sqlpp11/vendor/is_null.h index 73b2fdb3..d47d5aa7 100644 --- a/include/sqlpp11/vendor/is_null.h +++ b/include/sqlpp11/vendor/is_null.h @@ -38,9 +38,10 @@ namespace sqlpp template struct is_null_t: public boolean::template expression_operators> { + using _traits = make_traits; + using _recursive_traits = make_recursive_traits; + static constexpr bool _inverted = not NotInverted; - using _provided_tables = detail::type_set<>; - using _required_tables = typename Operand::_required_tables; struct _value_type: public boolean { diff --git a/include/sqlpp11/vendor/like.h b/include/sqlpp11/vendor/like.h index e1b65e07..fd782853 100644 --- a/include/sqlpp11/vendor/like.h +++ b/include/sqlpp11/vendor/like.h @@ -38,16 +38,11 @@ namespace sqlpp template struct like_t: public boolean::template expression_operators> { + using _traits = make_traits; + using _recursive_traits = make_recursive_traits; + static_assert(is_text_t::value, "Operand for like() has to be a text"); static_assert(is_text_t::value, "Pattern for like() has to be a text"); - using _parameter_tuple_t = std::tuple; - using _provided_tables = detail::type_set<>; - using _required_tables = typename ::sqlpp::detail::make_joined_set::type; - - struct _value_type: public boolean - { - using _is_named_expression = std::true_type; - }; struct _name_t { diff --git a/include/sqlpp11/vendor/value_type.h b/include/sqlpp11/vendor/value_type.h index 06738c36..2f9b5188 100644 --- a/include/sqlpp11/vendor/value_type.h +++ b/include/sqlpp11/vendor/value_type.h @@ -35,7 +35,7 @@ namespace sqlpp namespace vendor { template - using value_type_t = typename wrap_operand::type::_value_type; + using value_type_t = value_type_of>; } } #endif diff --git a/include/sqlpp11/vendor/wrap_operand.h b/include/sqlpp11/vendor/wrap_operand.h index 78925d50..9012aa98 100644 --- a/include/sqlpp11/vendor/wrap_operand.h +++ b/include/sqlpp11/vendor/wrap_operand.h @@ -29,7 +29,7 @@ #include #include -#include +#include namespace sqlpp { @@ -45,11 +45,10 @@ namespace sqlpp { struct boolean_operand { - static constexpr bool _is_expression = true; - using _value_type = sqlpp::detail::boolean; + using _traits = make_traits<::sqlpp::detail::boolean, ::sqlpp::tag::expression>; + using _recursive_traits = make_recursive_traits<>; + using _value_t = bool; - using _provided_tables = detail::type_set<>; - using _required_tables = ::sqlpp::detail::type_set<>; boolean_operand(): _t{} @@ -84,11 +83,10 @@ namespace sqlpp struct integral_operand { - static constexpr bool _is_expression = true; - using _value_type = ::sqlpp::detail::integral; + using _traits = make_traits<::sqlpp::detail::integral, ::sqlpp::tag::expression>; + using _recursive_traits = make_recursive_traits<>; + using _value_t = int64_t; - using _provided_tables = detail::type_set<>; - using _required_tables = ::sqlpp::detail::type_set<>; integral_operand(): _t{} @@ -124,11 +122,10 @@ namespace sqlpp struct floating_point_operand { - static constexpr bool _is_expression = true; - using _value_type = ::sqlpp::detail::floating_point; + using _traits = make_traits<::sqlpp::detail::floating_point, ::sqlpp::tag::expression>; + using _recursive_traits = make_recursive_traits<>; + using _value_t = double; - using _provided_tables = detail::type_set<>; - using _required_tables = ::sqlpp::detail::type_set<>; floating_point_operand(): _t{} @@ -163,11 +160,10 @@ namespace sqlpp struct text_operand { - static constexpr bool _is_expression = true; - using _value_type = ::sqlpp::detail::text; + using _traits = make_traits<::sqlpp::detail::text, ::sqlpp::tag::expression>; + using _recursive_traits = make_recursive_traits<>; + using _value_t = std::string; - using _provided_tables = detail::type_set<>; - using _required_tables = ::sqlpp::detail::type_set<>; text_operand(): _t{} diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 350602ec..71771eee 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -6,14 +6,14 @@ macro (build_and_run arg) add_test(${arg} ${arg}) endmacro () -build_and_run(InterpretTest) -build_and_run(InsertTest) -build_and_run(RemoveTest) -build_and_run(UpdateTest) -build_and_run(SelectTest) -build_and_run(SelectTypeTest) +#build_and_run(InterpretTest) +#build_and_run(InsertTest) +#build_and_run(RemoveTest) +#build_and_run(UpdateTest) +#build_and_run(SelectTest) +#build_and_run(SelectTypeTest) build_and_run(FunctionTest) -build_and_run(PreparedTest) +#build_and_run(PreparedTest) find_package(PythonInterp REQUIRED) diff --git a/tests/FunctionTest.cpp b/tests/FunctionTest.cpp index 04aa8f52..6d70f246 100644 --- a/tests/FunctionTest.cpp +++ b/tests/FunctionTest.cpp @@ -26,7 +26,7 @@ #include "Sample.h" #include "MockDb.h" #include -#include +//#include #include #include @@ -171,6 +171,7 @@ int main() // SUB_SELECT_FUNCTIONS // -------------------- +#if 0 // Test exists { using TI = decltype(exists(select(t.alpha).from(t))); @@ -232,6 +233,7 @@ int main() static_assert(not sqlpp::is_floating_point_t::value, "type requirement"); static_assert(sqlpp::is_text_t::value, "type requirement"); } +#endif // NUMERIC FUNCTIONS // ----------------- From 5f4a88c7cee20c4e3960e606a1ea6787b47dc048 Mon Sep 17 00:00:00 2001 From: rbock Date: Fri, 16 May 2014 09:18:08 +0200 Subject: [PATCH 03/16] Function tests compile again --- include/sqlpp11/any.h | 1 + include/sqlpp11/select.h | 31 +++++++++------- include/sqlpp11/type_traits.h | 26 ++++++++------ include/sqlpp11/vendor/assignment.h | 4 +-- include/sqlpp11/vendor/expression.h | 6 ++-- include/sqlpp11/vendor/expression_fwd.h | 34 +++++++++--------- include/sqlpp11/vendor/extra_tables.h | 4 +-- include/sqlpp11/vendor/field.h | 2 +- include/sqlpp11/vendor/from.h | 4 +-- include/sqlpp11/vendor/group_by.h | 6 ++-- include/sqlpp11/vendor/having.h | 4 +-- include/sqlpp11/vendor/limit.h | 18 ++++------ include/sqlpp11/vendor/offset.h | 17 ++++----- include/sqlpp11/vendor/order_by.h | 16 ++++----- include/sqlpp11/vendor/select_column_list.h | 39 +++++++++------------ include/sqlpp11/vendor/select_flag_list.h | 15 ++++---- include/sqlpp11/vendor/where.h | 23 +++++------- tests/FunctionTest.cpp | 7 ++-- 18 files changed, 120 insertions(+), 137 deletions(-) diff --git a/include/sqlpp11/any.h b/include/sqlpp11/any.h index f7d8ec0c..b4897b6a 100644 --- a/include/sqlpp11/any.h +++ b/include/sqlpp11/any.h @@ -87,6 +87,7 @@ namespace sqlpp { static_assert(is_select_t>::value, "any() requires a select expression as argument"); static_assert(is_expression_t>::value, "any() requires a single column select expression as argument"); + // FIXME: can we accept non-values like NULL here? return { t }; } diff --git a/include/sqlpp11/select.h b/include/sqlpp11/select.h index fd1b3a59..66eafd90 100644 --- a/include/sqlpp11/select.h +++ b/include/sqlpp11/select.h @@ -112,27 +112,27 @@ namespace sqlpp static_assert(is_noop_t::value or sqlpp::is_select_column_list_t::value, "column list of select is neither naught nor a valid column list"); static_assert(is_noop_t::value or sqlpp::is_from_t::value, "from() part of select is neither naught nor a valid from()"); - using _known_tables = detail::make_joined_set_t; + using _known_tables = detail::make_joined_set_t, provided_tables_of<_extra_tables_t>>; // FIXME, use provided_tables_of; template - using _no_unknown_tables = detail::is_subset_of; + using _no_unknown_tables = detail::is_subset_of, _known_tables>; using _required_tables = detail::make_joined_set_t< - typename _flag_list_t::_table_set, - typename _column_list_t::_table_set, - typename _where_t::_table_set, - typename _group_by_t::_table_set, - typename _having_t::_table_set, - typename _order_by_t::_table_set, - typename _limit_t::_table_set, - typename _offset_t::_table_set + required_tables_of<_flag_list_t>, + required_tables_of<_column_list_t>, + required_tables_of<_where_t>, + required_tables_of<_group_by_t>, + required_tables_of<_having_t>, + required_tables_of<_order_by_t>, + required_tables_of<_limit_t>, + required_tables_of<_offset_t> >; // The tables not covered by the from. using _table_set = detail::make_difference_set_t< _required_tables, - typename _from_t::_table_set // Hint: extra_tables_t is not used here because it is just a helper for dynamic .add_*() methods and should not change the structural integrity + provided_tables_of<_from_t> // Hint: extra_tables_t is not used here because it is just a helper for dynamic .add_*() methods and should not change the structural integrity >; // A select can be used as a pseudo table if @@ -145,10 +145,12 @@ namespace sqlpp >::type; using _value_type = typename std::conditional< - is_select_column_list_t<_column_list_t>::value and is_subset_of::value, - typename ColumnList::_value_type, + is_select_column_list_t<_column_list_t>::value and is_subset_of, provided_tables_of<_from_t>>::value, + value_type_of<_column_list_t>, no_value_t // If something is selected that requires a table, then we require a from for this to be a value >::type; + + using _traits = make_traits<_value_type>; }; } @@ -160,6 +162,9 @@ namespace sqlpp public detail::select_policies_t::_value_type::template expression_operators>, public detail::select_policies_t::_methods_t { + using _traits = make_traits>, ::sqlpp::tag::select>; + using _recursive_traits = make_recursive_traits<>; // FIXME + using _policies_t = typename detail::select_policies_t; using _database_t = typename _policies_t::_database_t; using _flag_list_t = typename _policies_t::_flag_list_t; diff --git a/include/sqlpp11/type_traits.h b/include/sqlpp11/type_traits.h index 795e0407..fe2c901d 100644 --- a/include/sqlpp11/type_traits.h +++ b/include/sqlpp11/type_traits.h @@ -114,6 +114,7 @@ namespace sqlpp SQLPP_IS_VALUE_TRAIT_GENERATOR(select_flag_list); SQLPP_IS_VALUE_TRAIT_GENERATOR(select_column_list); SQLPP_IS_VALUE_TRAIT_GENERATOR(from); + SQLPP_IS_VALUE_TRAIT_GENERATOR(extra_tables); SQLPP_IS_VALUE_TRAIT_GENERATOR(on); SQLPP_IS_VALUE_TRAIT_GENERATOR(dynamic); SQLPP_IS_VALUE_TRAIT_GENERATOR(where); @@ -142,17 +143,6 @@ namespace sqlpp template class IsTag> using copy_type_trait = typename std::conditional::value, std::true_type, std::false_type>::type; - template - struct make_traits - { - using _value_type = ValueType; - using _tags = detail::make_type_set_t; - }; - template - struct make_recursive_traits - { - }; - namespace detail { template @@ -181,6 +171,20 @@ namespace sqlpp template using provided_tables_of = typename detail::provided_table_of_impl::type; + + template + struct make_traits + { + using _value_type = ValueType; + using _tags = detail::make_type_set_t; + }; + template + struct make_recursive_traits + { + using _required_tables = detail::make_joined_set_t...>; + using _provided_tables = detail::make_joined_set_t...>; + }; + } #endif diff --git a/include/sqlpp11/vendor/assignment.h b/include/sqlpp11/vendor/assignment.h index 8026a3e1..52ad3c75 100644 --- a/include/sqlpp11/vendor/assignment.h +++ b/include/sqlpp11/vendor/assignment.h @@ -65,7 +65,7 @@ namespace sqlpp template struct assignment_t { - using _traits = make_traits; + using _traits = make_traits; using _recursive_traits = make_recursive_traits; using _column_t = Lhs; @@ -115,7 +115,7 @@ namespace sqlpp template struct assignment_t> { - using _traits = make_traits; + using _traits = make_traits; using _recursive_traits = make_recursive_traits; using _column_t = Lhs; diff --git a/include/sqlpp11/vendor/expression.h b/include/sqlpp11/vendor/expression.h index b3c6075a..03c89cba 100644 --- a/include/sqlpp11/vendor/expression.h +++ b/include/sqlpp11/vendor/expression.h @@ -40,7 +40,7 @@ namespace sqlpp namespace vendor { template - struct binary_expression_t: public ::sqlpp::detail::boolean::template expression_operators> + struct binary_expression_t: public ::sqlpp::detail::boolean::template expression_operators> { using _traits = make_traits; using _recursive_traits = make_recursive_traits; @@ -84,7 +84,7 @@ namespace sqlpp }; template - struct binary_expression_t: public ::sqlpp::detail::boolean::template expression_operators> + struct binary_expression_t: public ::sqlpp::detail::boolean::template expression_operators> { using _traits = make_traits; using _recursive_traits = make_recursive_traits; @@ -128,7 +128,7 @@ namespace sqlpp }; template - struct unary_expression_t: public ::sqlpp::detail::boolean::template expression_operators> + struct unary_expression_t: public ::sqlpp::detail::boolean::template expression_operators> { using _traits = make_traits; using _recursive_traits = make_recursive_traits; diff --git a/include/sqlpp11/vendor/expression_fwd.h b/include/sqlpp11/vendor/expression_fwd.h index 66b446c5..b6529e8b 100644 --- a/include/sqlpp11/vendor/expression_fwd.h +++ b/include/sqlpp11/vendor/expression_fwd.h @@ -31,7 +31,7 @@ namespace sqlpp { namespace vendor { - namespace tag + namespace op { struct less { @@ -139,52 +139,52 @@ namespace sqlpp struct unary_expression_t; template - using less_than_t = binary_expression_t; + using less_than_t = binary_expression_t; template - using less_equal_t = binary_expression_t; + using less_equal_t = binary_expression_t; template - using equal_to_t = binary_expression_t; + using equal_to_t = binary_expression_t; template - using not_equal_to_t = binary_expression_t; + using not_equal_to_t = binary_expression_t; template - using greater_than_t = binary_expression_t; + using greater_than_t = binary_expression_t; template - using greater_equal_t = binary_expression_t; + using greater_equal_t = binary_expression_t; template - using logical_and_t = binary_expression_t; + using logical_and_t = binary_expression_t; template - using logical_or_t = binary_expression_t; + using logical_or_t = binary_expression_t; template - using plus_t = binary_expression_t, Rhs>; + using plus_t = binary_expression_t, Rhs>; template - using minus_t = binary_expression_t, Rhs>; + using minus_t = binary_expression_t, Rhs>; template - using multiplies_t = binary_expression_t, Rhs>; + using multiplies_t = binary_expression_t, Rhs>; template - using divides_t = binary_expression_t; + using divides_t = binary_expression_t; template - using modulus_t = binary_expression_t; + using modulus_t = binary_expression_t; template - using logical_not_t = unary_expression_t; + using logical_not_t = unary_expression_t; template - using unary_plus_t = unary_expression_t, Rhs>; + using unary_plus_t = unary_expression_t, Rhs>; template - using unary_minus_t = unary_expression_t, Rhs>; + using unary_minus_t = unary_expression_t, Rhs>; } } diff --git a/include/sqlpp11/vendor/extra_tables.h b/include/sqlpp11/vendor/extra_tables.h index 04e3b4d8..36fb431a 100644 --- a/include/sqlpp11/vendor/extra_tables.h +++ b/include/sqlpp11/vendor/extra_tables.h @@ -39,7 +39,7 @@ namespace sqlpp template struct extra_tables_t { - using _traits = make_traits; + using _traits = make_traits; using _recursive_traits = make_recursive_traits; // FIXME: extra_tables must not require tables! @@ -65,7 +65,7 @@ namespace sqlpp struct no_extra_tables_t { - using _traits = make_traits; + using _traits = make_traits; using _recursive_traits = make_recursive_traits<>; template diff --git a/include/sqlpp11/vendor/field.h b/include/sqlpp11/vendor/field.h index 2e0293bb..caf93c78 100644 --- a/include/sqlpp11/vendor/field.h +++ b/include/sqlpp11/vendor/field.h @@ -52,7 +52,7 @@ namespace sqlpp struct make_field_t_impl { using type = field_t, + value_type_of, trivial_value_is_null_t::value>; }; diff --git a/include/sqlpp11/vendor/from.h b/include/sqlpp11/vendor/from.h index 7a016cde..3e30ea33 100644 --- a/include/sqlpp11/vendor/from.h +++ b/include/sqlpp11/vendor/from.h @@ -41,7 +41,7 @@ namespace sqlpp template struct from_t { - using _traits = make_traits; + using _traits = make_traits; using _recursive_traits = make_recursive_traits; using _is_dynamic = typename std::conditional::value, std::false_type, std::true_type>::type; @@ -97,7 +97,7 @@ namespace sqlpp struct no_from_t { - using _traits = make_traits; + using _traits = make_traits; using _recursive_traits = make_recursive_traits<>; template diff --git a/include/sqlpp11/vendor/group_by.h b/include/sqlpp11/vendor/group_by.h index ab023f4a..51fb4f11 100644 --- a/include/sqlpp11/vendor/group_by.h +++ b/include/sqlpp11/vendor/group_by.h @@ -43,7 +43,7 @@ namespace sqlpp template struct group_by_t { - using _traits = make_traits; + using _traits = make_traits; using _recursive_traits = make_recursive_traits; using _is_dynamic = typename std::conditional::value, std::false_type, std::true_type>::type; @@ -97,13 +97,13 @@ namespace sqlpp }; const group_by_t& _group_by() const { return *this; } - std::tuple _expressions; + std::tuple _expressions; vendor::interpretable_list_t _dynamic_expressions; }; struct no_group_by_t { - using _traits = make_traits; + using _traits = make_traits; using _recursive_traits = make_recursive_traits<>; template diff --git a/include/sqlpp11/vendor/having.h b/include/sqlpp11/vendor/having.h index 8c4708e6..fa15285f 100644 --- a/include/sqlpp11/vendor/having.h +++ b/include/sqlpp11/vendor/having.h @@ -42,7 +42,7 @@ namespace sqlpp template struct having_t { - using _traits = make_traits; + using _traits = make_traits; using _recursive_traits = make_recursive_traits; using _is_dynamic = typename std::conditional::value, std::false_type, std::true_type>::type; @@ -98,7 +98,7 @@ namespace sqlpp struct no_having_t { - using _traits = make_traits; + using _traits = make_traits; using _recursive_traits = make_recursive_traits<>; template diff --git a/include/sqlpp11/vendor/limit.h b/include/sqlpp11/vendor/limit.h index 15d72af1..62e94916 100644 --- a/include/sqlpp11/vendor/limit.h +++ b/include/sqlpp11/vendor/limit.h @@ -39,11 +39,10 @@ namespace sqlpp template struct limit_t { - using _is_limit = std::true_type; + using _traits = make_traits; + using _recursive_traits = make_recursive_traits; + static_assert(is_integral_t::value, "limit requires an integral value or integral parameter"); - // FIXME: Is this really always empty? - using _provided_tables = detail::type_set<>; - using _required_tables = ::sqlpp::detail::type_set<>; limit_t(Limit value): _value(value) @@ -66,10 +65,8 @@ namespace sqlpp template struct dynamic_limit_t { - using _is_limit = std::true_type; - using _is_dynamic = std::true_type; - using _provided_tables = detail::type_set<>; - using _required_tables = ::sqlpp::detail::type_set<>; + using _traits = make_traits; + using _recursive_traits = make_recursive_traits<>; dynamic_limit_t(): _value(noop()) @@ -108,9 +105,8 @@ namespace sqlpp struct no_limit_t { - using _is_noop = std::true_type; - using _provided_tables = detail::type_set<>; - using _required_tables = ::sqlpp::detail::type_set<>; + using _traits = make_traits; + using _recursive_traits = make_recursive_traits<>; template struct _methods_t diff --git a/include/sqlpp11/vendor/offset.h b/include/sqlpp11/vendor/offset.h index 2a873a50..83cacd95 100644 --- a/include/sqlpp11/vendor/offset.h +++ b/include/sqlpp11/vendor/offset.h @@ -39,9 +39,9 @@ namespace sqlpp template struct offset_t { - using _is_offset = std::true_type; - using _provided_tables = detail::type_set<>; - using _required_tables = ::sqlpp::detail::type_set<>; + using _traits = make_traits; + using _recursive_traits = make_recursive_traits; + static_assert(is_integral_t::value, "offset requires an integral value or integral parameter"); offset_t(Offset value): @@ -65,10 +65,8 @@ namespace sqlpp template struct dynamic_offset_t { - using _is_offset = std::true_type; - using _is_dynamic = std::true_type; - using _provided_tables = detail::type_set<>; - using _required_tables = ::sqlpp::detail::type_set<>; + using _traits = make_traits; + using _recursive_traits = make_recursive_traits<>; dynamic_offset_t(): _value(noop()) @@ -107,9 +105,8 @@ namespace sqlpp struct no_offset_t { - using _is_noop = std::true_type; - using _provided_tables = detail::type_set<>; - using _required_tables = ::sqlpp::detail::type_set<>; + using _traits = make_traits; + using _recursive_traits = make_recursive_traits<>; template struct _methods_t diff --git a/include/sqlpp11/vendor/order_by.h b/include/sqlpp11/vendor/order_by.h index 80d7f891..a6d4a5ad 100644 --- a/include/sqlpp11/vendor/order_by.h +++ b/include/sqlpp11/vendor/order_by.h @@ -42,13 +42,10 @@ namespace sqlpp 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_list_t = typename make_parameter_list_t<_parameter_tuple_t>::type; + using _traits = make_traits; + using _recursive_traits = make_recursive_traits; - using _provided_tables = detail::type_set<>; - using _required_tables = typename ::sqlpp::detail::make_joined_set::type; + 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()"); @@ -98,15 +95,14 @@ namespace sqlpp void _add_order_by_impl(Expression expression, const std::false_type&); }; - _parameter_tuple_t _expressions; + std::tuple _expressions; vendor::interpretable_list_t _dynamic_expressions; }; struct no_order_by_t { - using _is_noop = std::true_type; - using _provided_tables = detail::type_set<>; - using _required_tables = ::sqlpp::detail::type_set<>; + using _traits = make_traits; + using _recursive_traits = make_recursive_traits<>; template struct _methods_t diff --git a/include/sqlpp11/vendor/select_column_list.h b/include/sqlpp11/vendor/select_column_list.h index 955b4df8..1f160d16 100644 --- a/include/sqlpp11/vendor/select_column_list.h +++ b/include/sqlpp11/vendor/select_column_list.h @@ -47,14 +47,14 @@ namespace sqlpp template struct get_first_argument_if_unique { - using _value_type = no_value_t; + using _traits = make_traits; struct _name_t {}; }; template struct get_first_argument_if_unique { - using _value_type = typename T::_value_type; + using _traits = make_traits, tag::select_column_list, tag::expression, tag::named_expression>; using _name_t = typename T::_name_t; }; } @@ -132,13 +132,13 @@ namespace sqlpp 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 size = std::tuple_size<_parameter_tuple_t>; + // get_first_argument_if_unique is kind of ugly + using _traits = typename ::sqlpp::detail::get_first_argument_if_unique::_traits; + using _recursive_traits = make_recursive_traits; - using _provided_tables = detail::type_set<>; - using _required_tables = sqlpp::detail::make_joined_set_t; + using _name_t = typename ::sqlpp::detail::get_first_argument_if_unique::_name_t; + + using _is_dynamic = typename std::conditional::value, std::false_type, std::true_type>::type; static_assert(not ::sqlpp::detail::has_duplicates::value, "at least one duplicate argument detected"); @@ -149,13 +149,7 @@ namespace sqlpp static_assert(not ::sqlpp::detail::has_duplicates::value, "at least one duplicate name detected"); struct _column_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_alias = std::false_type; - }; - using _name_t = typename ::sqlpp::detail::get_first_argument_if_unique::_name_t; + template using _result_row_t = typename std::conditional<_is_dynamic::value, @@ -186,7 +180,7 @@ namespace sqlpp static constexpr size_t static_size() { - return size::value; + return sizeof...(Columns); } template @@ -228,7 +222,7 @@ namespace sqlpp const select_column_list_t& _column_list() const { return *this; } - _parameter_tuple_t _columns; + std::tuple _columns; dynamic_select_column_list _dynamic_columns; }; } @@ -245,13 +239,12 @@ namespace sqlpp { struct no_select_column_list_t { - using _is_noop = std::true_type; - using _provided_tables = detail::type_set<>; - using _required_tables = ::sqlpp::detail::type_set<>; + using _traits = make_traits; + using _recursive_traits = make_recursive_traits<>; + template 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 @@ -293,10 +286,10 @@ namespace sqlpp static Context& _(const T& t, Context& context) { // check for at least one expression - static_assert(T::_is_dynamic::value or T::size::value, "at least one select expression required"); + static_assert(T::_is_dynamic::value or sizeof...(Columns), "at least one select expression required"); interpret_tuple(t._columns, ',', context); - if (T::size::value and not t._dynamic_columns.empty()) + if (sizeof...(Columns) and not t._dynamic_columns.empty()) context << ','; serialize(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 889debce..85303440 100644 --- a/include/sqlpp11/vendor/select_flag_list.h +++ b/include/sqlpp11/vendor/select_flag_list.h @@ -42,12 +42,10 @@ namespace sqlpp template struct select_flag_list_t { - using _is_select_flag_list = std::true_type; + using _traits = make_traits; + using _recursive_traits = make_recursive_traits; + 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>; - using _provided_tables = detail::type_set<>; - using _required_tables = typename ::sqlpp::detail::make_joined_set::type; static_assert(not ::sqlpp::detail::has_duplicates::value, "at least one duplicate argument detected in select flag list"); @@ -96,15 +94,14 @@ namespace sqlpp }; const select_flag_list_t& _flag_list() const { return *this; } - _parameter_tuple_t _flags; + std::tuple _flags; vendor::interpretable_list_t _dynamic_flags; }; struct no_select_flag_list_t { - using _is_noop = std::true_type; - using _provided_tables = detail::type_set<>; - using _required_tables = ::sqlpp::detail::type_set<>; + using _traits = make_traits; + using _recursive_traits = make_recursive_traits<>; template struct _methods_t diff --git a/include/sqlpp11/vendor/where.h b/include/sqlpp11/vendor/where.h index 03d70ec6..01557cdd 100644 --- a/include/sqlpp11/vendor/where.h +++ b/include/sqlpp11/vendor/where.h @@ -42,19 +42,15 @@ namespace sqlpp template struct where_t { - using _is_where = std::true_type; + using _traits = make_traits; + using _recursive_traits = make_recursive_traits; + using _is_dynamic = typename std::conditional::value, std::false_type, std::true_type>::type; - using _parameter_tuple_t = std::tuple; static_assert(_is_dynamic::value or sizeof...(Expressions), "at least one expression argument required in where()"); static_assert(sqlpp::detail::none_t::value...>::value, "at least one argument is an assignment in where()"); static_assert(sqlpp::detail::all_t::value...>::value, "at least one argument is not valid expression in where()"); - using _parameter_list_t = typename make_parameter_list_t<_parameter_tuple_t>::type; - - using _provided_tables = detail::type_set<>; - using _required_tables = typename ::sqlpp::detail::make_joined_set::type; - where_t(Expressions... expressions): _expressions(expressions...) {} @@ -97,17 +93,15 @@ namespace sqlpp void _add_where_impl(Expression expression, const std::false_type&); }; - _parameter_tuple_t _expressions; + std::tuple _expressions; vendor::interpretable_list_t _dynamic_expressions; }; template<> struct where_t { - using _is_where = std::true_type; - using _is_dynamic = std::false_type; - using _provided_tables = detail::type_set<>; - using _required_tables = ::sqlpp::detail::type_set<>; + using _traits = make_traits; + using _recursive_traits = make_recursive_traits<>; where_t(bool condition): _condition(condition) @@ -129,9 +123,8 @@ namespace sqlpp struct no_where_t { - using _is_noop = std::true_type; - using _provided_tables = detail::type_set<>; - using _required_tables = ::sqlpp::detail::type_set<>; + using _traits = make_traits; + using _recursive_traits = make_recursive_traits<>; template struct _methods_t diff --git a/tests/FunctionTest.cpp b/tests/FunctionTest.cpp index 6d70f246..bc02891b 100644 --- a/tests/FunctionTest.cpp +++ b/tests/FunctionTest.cpp @@ -26,7 +26,7 @@ #include "Sample.h" #include "MockDb.h" #include -//#include +#include #include #include @@ -171,7 +171,6 @@ int main() // SUB_SELECT_FUNCTIONS // -------------------- -#if 0 // Test exists { using TI = decltype(exists(select(t.alpha).from(t))); @@ -189,6 +188,9 @@ int main() // Test any { + using S = decltype(select(t.alpha).from(t)); + static_assert(sqlpp::is_numeric_t::value, "type requirement"); + static_assert(sqlpp::is_numeric_t::value, "type requirement"); using TI = decltype(any(select(t.alpha).from(t))); using TT = decltype(any(select(t.beta).from(t))); @@ -233,7 +235,6 @@ int main() static_assert(not sqlpp::is_floating_point_t::value, "type requirement"); static_assert(sqlpp::is_text_t::value, "type requirement"); } -#endif // NUMERIC FUNCTIONS // ----------------- From 6972758931401ebfd1ecacc860fccd04a30da8b6 Mon Sep 17 00:00:00 2001 From: rbock Date: Fri, 16 May 2014 09:33:48 +0200 Subject: [PATCH 04/16] Added extra_tables to recursive_traits --- include/sqlpp11/column.h | 2 ++ include/sqlpp11/parameter.h | 8 +++++++- include/sqlpp11/select.h | 2 +- include/sqlpp11/table.h | 1 + include/sqlpp11/type_traits.h | 10 ++++++++++ include/sqlpp11/vendor/extra_tables.h | 8 ++++++++ 6 files changed, 29 insertions(+), 2 deletions(-) diff --git a/include/sqlpp11/column.h b/include/sqlpp11/column.h index 8795a08b..383f94cc 100644 --- a/include/sqlpp11/column.h +++ b/include/sqlpp11/column.h @@ -48,8 +48,10 @@ namespace sqlpp using _traits = make_traits; struct _recursive_traits { + using _parameters = std::tuple<>; using _provided_tables = detail::type_set<>; using _required_tables = detail::type_set
; + using _extra_tables = detail::type_set<>; }; using _spec_t = ColumnSpec; diff --git a/include/sqlpp11/parameter.h b/include/sqlpp11/parameter.h index d13afdbf..b3769639 100644 --- a/include/sqlpp11/parameter.h +++ b/include/sqlpp11/parameter.h @@ -37,7 +37,13 @@ namespace sqlpp struct parameter_t: public ValueType::template expression_operators> { using _traits = make_traits; - using _recursive_traits = make_recursive_traits<>; + struct _recursive_traits + { + using _parameters = std::tuple; + using _provided_tables = detail::type_set<>; + using _required_tables = detail::type_set<>; + using _extra_tables = detail::type_set<>; + }; using _instance_t = typename NameType::_name_t::template _member_t; diff --git a/include/sqlpp11/select.h b/include/sqlpp11/select.h index 66eafd90..ee36c6bc 100644 --- a/include/sqlpp11/select.h +++ b/include/sqlpp11/select.h @@ -112,7 +112,7 @@ namespace sqlpp static_assert(is_noop_t::value or sqlpp::is_select_column_list_t::value, "column list of select is neither naught nor a valid column list"); static_assert(is_noop_t::value or sqlpp::is_from_t::value, "from() part of select is neither naught nor a valid from()"); - using _known_tables = detail::make_joined_set_t, provided_tables_of<_extra_tables_t>>; // FIXME, use provided_tables_of; + using _known_tables = detail::make_joined_set_t, extra_tables_of<_extra_tables_t>>; template using _no_unknown_tables = detail::is_subset_of, _known_tables>; diff --git a/include/sqlpp11/table.h b/include/sqlpp11/table.h index a77120ea..5f74da41 100644 --- a/include/sqlpp11/table.h +++ b/include/sqlpp11/table.h @@ -49,6 +49,7 @@ namespace sqlpp using _parameters = std::tuple<>; using _required_tables = detail::type_set<>; using _provided_tables = detail::type_set
; + using _extra_tables = detail::type_set<>; }; static_assert(sizeof...(ColumnSpec), "at least one column required per table"); diff --git a/include/sqlpp11/type_traits.h b/include/sqlpp11/type_traits.h index fe2c901d..66243bc2 100644 --- a/include/sqlpp11/type_traits.h +++ b/include/sqlpp11/type_traits.h @@ -162,6 +162,12 @@ namespace sqlpp { using type = typename T::_recursive_traits::_provided_tables; }; + + template + struct extra_table_of_impl + { + using type = typename T::_recursive_traits::_extra_tables; + }; } template using value_type_of = typename detail::value_type_of_impl::type; @@ -172,6 +178,9 @@ namespace sqlpp template using provided_tables_of = typename detail::provided_table_of_impl::type; + template + using extra_tables_of = typename detail::extra_table_of_impl::type; + template struct make_traits { @@ -183,6 +192,7 @@ namespace sqlpp { using _required_tables = detail::make_joined_set_t...>; using _provided_tables = detail::make_joined_set_t...>; + using _extra_tables = detail::make_joined_set_t...>; }; } diff --git a/include/sqlpp11/vendor/extra_tables.h b/include/sqlpp11/vendor/extra_tables.h index 36fb431a..040b5c5f 100644 --- a/include/sqlpp11/vendor/extra_tables.h +++ b/include/sqlpp11/vendor/extra_tables.h @@ -40,6 +40,14 @@ namespace sqlpp struct extra_tables_t { using _traits = make_traits; + struct _recursive_traits + { + using _parameters = std::tuple<>; + using _required_tables = ::sqlpp::detail::type_set<>; + using _provided_tables = ::sqlpp::detail::type_set<>; + using _extra_tables = ::sqlpp::detail::type_set; + }; + using _recursive_traits = make_recursive_traits; // FIXME: extra_tables must not require tables! From f314c6d070aad0324318377c1641b81e6604cb0b Mon Sep 17 00:00:00 2001 From: rbock Date: Fri, 16 May 2014 20:06:20 +0200 Subject: [PATCH 05/16] Added recursive_traits to select --- include/sqlpp11/select.h | 32 +++++++++++++++++++++----------- 1 file changed, 21 insertions(+), 11 deletions(-) diff --git a/include/sqlpp11/select.h b/include/sqlpp11/select.h index ee36c6bc..da752636 100644 --- a/include/sqlpp11/select.h +++ b/include/sqlpp11/select.h @@ -117,7 +117,7 @@ namespace sqlpp template using _no_unknown_tables = detail::is_subset_of, _known_tables>; - using _required_tables = + using _all_required_tables = detail::make_joined_set_t< required_tables_of<_flag_list_t>, required_tables_of<_column_list_t>, @@ -130,8 +130,8 @@ namespace sqlpp >; // The tables not covered by the from. - using _table_set = detail::make_difference_set_t< - _required_tables, + using _required_tables = detail::make_difference_set_t< + _all_required_tables, provided_tables_of<_from_t> // Hint: extra_tables_t is not used here because it is just a helper for dynamic .add_*() methods and should not change the structural integrity >; @@ -139,7 +139,7 @@ namespace sqlpp // - at least one column is selected // - the select is complete (leaks no tables) using _can_be_used_as_table = typename std::conditional< - is_select_column_list_t<_column_list_t>::value and _table_set::size::value == 0, + is_select_column_list_t<_column_list_t>::value and _required_tables::size::value == 0, std::true_type, std::false_type >::type; @@ -150,7 +150,16 @@ namespace sqlpp no_value_t // If something is selected that requires a table, then we require a from for this to be a value >::type; - using _traits = make_traits<_value_type>; + using _traits = make_traits<_value_type>; + + struct _recursive_traits + { + using _parameters = std::tuple<>; // FIXME + using _required_tables = _required_tables; + using _provided_tables = detail::type_set<>; + using _extra_tables = detail::type_set<>; + }; + }; } @@ -162,10 +171,12 @@ namespace sqlpp public detail::select_policies_t::_value_type::template expression_operators>, public detail::select_policies_t::_methods_t { - using _traits = make_traits>, ::sqlpp::tag::select>; - using _recursive_traits = make_recursive_traits<>; // FIXME - using _policies_t = typename detail::select_policies_t; + + using _traits = make_traits, ::sqlpp::tag::select>; + + using _recursive_traits = typename _policies_t::_recursive_traits; + using _database_t = typename _policies_t::_database_t; using _flag_list_t = typename _policies_t::_flag_list_t; using _column_list_t = typename _policies_t::_column_list_t; @@ -182,7 +193,6 @@ namespace sqlpp using _parameter_tuple_t = std::tuple; using _parameter_list_t = typename make_parameter_list_t::type; - using _table_set = typename _policies_t::_table_set; template using _result_row_t = typename _column_list_t::template _result_row_t; @@ -256,7 +266,7 @@ namespace sqlpp template struct is_table_subset_of_from { - static constexpr bool value = ::sqlpp::detail::is_subset_of::value; + static constexpr bool value = ::sqlpp::detail::is_subset_of, provided_tables_of<_from_t>>::value; }; void _check_consistency() const @@ -271,7 +281,7 @@ namespace sqlpp static_assert(is_table_subset_of_from<_order_by_t>::value, "order_by() expression requires additional tables in from()"); static_assert(is_table_subset_of_from<_limit_t>::value, "limit() expression requires additional tables in from()"); static_assert(is_table_subset_of_from<_offset_t>::value, "offset() expression requires additional tables in from()"); - static_assert(not _table_set::size::value, "one sub expression contains tables which are not in the from()"); + static_assert(not required_tables_of<_policies_t>::size::value, "one sub expression contains tables which are not in the from()"); } // Execute From e39444b0f70e613b0008fdc760d773538a50d7f2 Mon Sep 17 00:00:00 2001 From: rbock Date: Mon, 19 May 2014 06:42:45 +0200 Subject: [PATCH 06/16] Added tags missing and return_value missing indicates that a statement part has yet to be added (e.g. columns in a select). return_value indicates that a statement part can be used as a return value. --- include/sqlpp11/detail/type_set.h | 3 +++ include/sqlpp11/select.h | 4 ++-- include/sqlpp11/type_traits.h | 2 ++ include/sqlpp11/vendor/select_column_list.h | 6 +++--- 4 files changed, 10 insertions(+), 5 deletions(-) diff --git a/include/sqlpp11/detail/type_set.h b/include/sqlpp11/detail/type_set.h index 64a2b005..ecc51a23 100644 --- a/include/sqlpp11/detail/type_set.h +++ b/include/sqlpp11/detail/type_set.h @@ -157,6 +157,9 @@ namespace sqlpp using type = typename make_type_set_if::type::template insert_if::type; }; + template class Predicate, typename... T> + using make_type_set_if_t = typename make_type_set_if::type; + template class Predicate, typename... T> struct make_type_set_if_not { diff --git a/include/sqlpp11/select.h b/include/sqlpp11/select.h index da752636..2f5dc271 100644 --- a/include/sqlpp11/select.h +++ b/include/sqlpp11/select.h @@ -145,9 +145,9 @@ namespace sqlpp >::type; using _value_type = typename std::conditional< - is_select_column_list_t<_column_list_t>::value and is_subset_of, provided_tables_of<_from_t>>::value, + detail::make_type_set_if_t::size::value == 0, value_type_of<_column_list_t>, - no_value_t // If something is selected that requires a table, then we require a from for this to be a value + no_value_t // if a required statement part is missing (columns in a select), then the statement cannot be used as a value >::type; using _traits = make_traits<_value_type>; diff --git a/include/sqlpp11/type_traits.h b/include/sqlpp11/type_traits.h index 66243bc2..a1f231c5 100644 --- a/include/sqlpp11/type_traits.h +++ b/include/sqlpp11/type_traits.h @@ -106,6 +106,8 @@ namespace sqlpp SQLPP_IS_COLUMN_TRAIT_GENERATOR(trivial_value_is_null); SQLPP_IS_VALUE_TRAIT_GENERATOR(noop); + SQLPP_IS_VALUE_TRAIT_GENERATOR(missing); + SQLPP_IS_VALUE_TRAIT_GENERATOR(return_value); SQLPP_IS_VALUE_TRAIT_GENERATOR(table); SQLPP_IS_VALUE_TRAIT_GENERATOR(join); SQLPP_IS_VALUE_TRAIT_GENERATOR(pseudo_table); diff --git a/include/sqlpp11/vendor/select_column_list.h b/include/sqlpp11/vendor/select_column_list.h index 1f160d16..ce98c227 100644 --- a/include/sqlpp11/vendor/select_column_list.h +++ b/include/sqlpp11/vendor/select_column_list.h @@ -47,14 +47,14 @@ namespace sqlpp template struct get_first_argument_if_unique { - using _traits = make_traits; + using _traits = make_traits; struct _name_t {}; }; template struct get_first_argument_if_unique { - using _traits = make_traits, tag::select_column_list, tag::expression, tag::named_expression>; + using _traits = make_traits, tag::select_column_list, tag::return_value, tag::expression, tag::named_expression>; using _name_t = typename T::_name_t; }; } @@ -239,7 +239,7 @@ namespace sqlpp { struct no_select_column_list_t { - using _traits = make_traits; + using _traits = make_traits; using _recursive_traits = make_recursive_traits<>; template From bfd13c674372b2639ce87d42f04f526f0e498bf9 Mon Sep 17 00:00:00 2001 From: rbock Date: Mon, 19 May 2014 07:51:24 +0200 Subject: [PATCH 07/16] Determining column_list in a more generic way. By finding the last parameter which is a return value. --- include/sqlpp11/detail/get_last.h | 60 +++++++++++++++++++++++++++++++ include/sqlpp11/select.h | 7 ++-- include/sqlpp11/vendor/noop.h | 3 +- 3 files changed, 67 insertions(+), 3 deletions(-) create mode 100644 include/sqlpp11/detail/get_last.h diff --git a/include/sqlpp11/detail/get_last.h b/include/sqlpp11/detail/get_last.h new file mode 100644 index 00000000..02bacd4b --- /dev/null +++ b/include/sqlpp11/detail/get_last.h @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2013-2014, Roland Bock + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, this + * list of conditions and the following disclaimer in the documentation and/or + * other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef SQLPP_DETAIL_GET_LAST_H +#define SQLPP_DETAIL_GET_LAST_H + +#include + +namespace sqlpp +{ + namespace detail + { + template class Predicate, typename Default, typename... T> + struct get_last_if_impl; + + template class Predicate, typename Default> + struct get_last_if_impl + { + using type = Default; + }; + + template class Predicate, typename Default, typename T, typename... Rest> + struct get_last_if_impl + { + using rest = typename get_last_if_impl::type; + using type = typename std::conditional::value and Predicate::value, + T, + rest>::type; + }; + + template class Predicate, typename Default, typename... T> + using get_last_if = typename get_last_if_impl::type; + } +} + + +#endif diff --git a/include/sqlpp11/select.h b/include/sqlpp11/select.h index 2f5dc271..976d4ef4 100644 --- a/include/sqlpp11/select.h +++ b/include/sqlpp11/select.h @@ -48,6 +48,7 @@ #include #include +#include namespace sqlpp { @@ -135,18 +136,20 @@ namespace sqlpp provided_tables_of<_from_t> // Hint: extra_tables_t is not used here because it is just a helper for dynamic .add_*() methods and should not change the structural integrity >; + using _result_provider = detail::get_last_if; + // A select can be used as a pseudo table if // - at least one column is selected // - the select is complete (leaks no tables) using _can_be_used_as_table = typename std::conditional< - is_select_column_list_t<_column_list_t>::value and _required_tables::size::value == 0, + is_select_column_list_t<_result_provider>::value and _required_tables::size::value == 0, std::true_type, std::false_type >::type; using _value_type = typename std::conditional< detail::make_type_set_if_t::size::value == 0, - value_type_of<_column_list_t>, + value_type_of<_result_provider>, no_value_t // if a required statement part is missing (columns in a select), then the statement cannot be used as a value >::type; diff --git a/include/sqlpp11/vendor/noop.h b/include/sqlpp11/vendor/noop.h index e0c28ef1..1a7bcfe5 100644 --- a/include/sqlpp11/vendor/noop.h +++ b/include/sqlpp11/vendor/noop.h @@ -35,7 +35,8 @@ namespace sqlpp { struct noop { - using is_noop = std::true_type; + using _traits = make_traits; + using _recursive_traits = make_recursive_traits<>; }; template From 569f0ff2ebe42955360f4bfc566a751a89f4c934 Mon Sep 17 00:00:00 2001 From: rbock Date: Mon, 19 May 2014 08:01:14 +0200 Subject: [PATCH 08/16] Wrote down remaining steps for next release --- include/sqlpp11/select.h | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/include/sqlpp11/select.h b/include/sqlpp11/select.h index 976d4ef4..552feafd 100644 --- a/include/sqlpp11/select.h +++ b/include/sqlpp11/select.h @@ -57,6 +57,11 @@ namespace sqlpp > struct select_t; +#warning STEPS: +#warning replace _select_column_t by _result_provider +#warning turn select into a variadic template (and have a empty_select which contains the default settings +#warning do the same with insert, update and remove +#warning deal with different return types in the connector (select could be a single value, update could be a range of rows) namespace detail { template Date: Mon, 19 May 2014 22:54:47 +0200 Subject: [PATCH 09/16] A step towards turning select into a really variadic template --- include/sqlpp11/select.h | 98 ++++++++++++++-------------------------- 1 file changed, 35 insertions(+), 63 deletions(-) diff --git a/include/sqlpp11/select.h b/include/sqlpp11/select.h index 552feafd..40be4bdb 100644 --- a/include/sqlpp11/select.h +++ b/include/sqlpp11/select.h @@ -115,9 +115,6 @@ namespace sqlpp template using _new_statement_t = typename _policies_update_t::type; - static_assert(is_noop_t::value or sqlpp::is_select_column_list_t::value, "column list of select is neither naught nor a valid column list"); - static_assert(is_noop_t::value or sqlpp::is_from_t::value, "from() part of select is neither naught nor a valid from()"); - using _known_tables = detail::make_joined_set_t, extra_tables_of<_extra_tables_t>>; template @@ -141,7 +138,7 @@ namespace sqlpp provided_tables_of<_from_t> // Hint: extra_tables_t is not used here because it is just a helper for dynamic .add_*() methods and should not change the structural integrity >; - using _result_provider = detail::get_last_if; + using _result_provider = detail::get_last_if; // A select can be used as a pseudo table if // - at least one column is selected @@ -171,34 +168,48 @@ namespace sqlpp }; } + namespace detail + { + template + Target pick_arg_impl(Statement statement, Term term, const std::true_type&) + { + return term; + }; + + template + Target pick_arg_impl(Statement statement, Term term, const std::false_type&) + { + return static_cast(statement); + }; + + template + Target pick_arg(Statement statement, Term term) + { + return pick_arg_impl(statement, term, std::is_same()); + }; + } + // SELECT template struct select_t: + public Policies..., public detail::select_policies_t::_value_type::template expression_operators>, public detail::select_policies_t::_methods_t - { + { using _policies_t = typename detail::select_policies_t; using _traits = make_traits, ::sqlpp::tag::select>; using _recursive_traits = typename _policies_t::_recursive_traits; - using _database_t = typename _policies_t::_database_t; - using _flag_list_t = typename _policies_t::_flag_list_t; - using _column_list_t = typename _policies_t::_column_list_t; - using _from_t = typename _policies_t::_from_t; - using _extra_tables_t = typename _policies_t::_extra_tables_t; - using _where_t = typename _policies_t::_where_t; - using _group_by_t = typename _policies_t::_group_by_t; - using _having_t = typename _policies_t::_having_t; - using _order_by_t = typename _policies_t::_order_by_t; - using _limit_t = typename _policies_t::_limit_t; - using _offset_t = typename _policies_t::_offset_t; - + using _database_t = Db; using _is_dynamic = typename std::conditional::value, std::false_type, std::true_type>::type; +#warning replace _column_list_t by a more generic name + using _column_list_t = typename _policies_t::_result_provider; + using _parameter_tuple_t = std::tuple; using _parameter_list_t = typename make_parameter_list_t::type; @@ -216,17 +227,9 @@ namespace sqlpp select_t() {} - template - select_t(Statement s, T t): - _flag_list(detail::arg_selector<_flag_list_t>::_(s._flag_list, t)), - _column_list(detail::arg_selector<_column_list_t>::_(s._column_list, t)), - _from(detail::arg_selector<_from_t>::_(s._from, t)), - _where(detail::arg_selector<_where_t>::_(s._where, t)), - _group_by(detail::arg_selector<_group_by_t>::_(s._group_by, t)), - _having(detail::arg_selector<_having_t>::_(s._having, t)), - _order_by(detail::arg_selector<_order_by_t>::_(s._order_by, t)), - _limit(detail::arg_selector<_limit_t>::_(s._limit, t)), - _offset(detail::arg_selector<_offset_t>::_(s._offset, t)) + template + select_t(Statement statement, Term term): + Policies(detail::pick_arg(statement, term))... {} select_t(const select_t& r) = default; @@ -253,7 +256,7 @@ namespace sqlpp const _dynamic_names_t& get_dynamic_names() const { - return _column_list._dynamic_columns._dynamic_expression_names; + return static_cast(*this)._dynamic_columns._dynamic_expression_names; } static constexpr size_t _get_static_no_of_parameters() @@ -271,24 +274,9 @@ namespace sqlpp return _column_list_t::static_size() + get_dynamic_names().size(); } - template - struct is_table_subset_of_from - { - static constexpr bool value = ::sqlpp::detail::is_subset_of, provided_tables_of<_from_t>>::value; - }; - void _check_consistency() const { - static_assert(is_select_column_list_t<_column_list_t>::value, "no columns selected"); - - static_assert(is_table_subset_of_from<_flag_list_t>::value, "flags require additional tables in from()"); - static_assert(is_table_subset_of_from<_column_list_t>::value, "selected columns require additional tables in from()"); - static_assert(is_table_subset_of_from<_where_t>::value, "where() expression requires additional tables in from()"); - static_assert(is_table_subset_of_from<_group_by_t>::value, "group_by() expression requires additional tables in from()"); - static_assert(is_table_subset_of_from<_having_t>::value, "having() expression requires additional tables in from()"); - static_assert(is_table_subset_of_from<_order_by_t>::value, "order_by() expression requires additional tables in from()"); - static_assert(is_table_subset_of_from<_limit_t>::value, "limit() expression requires additional tables in from()"); - static_assert(is_table_subset_of_from<_offset_t>::value, "offset() expression requires additional tables in from()"); +#warning check for missing terms here, and for missing tables static_assert(not required_tables_of<_policies_t>::size::value, "one sub expression contains tables which are not in the from()"); } @@ -313,15 +301,7 @@ namespace sqlpp return {{}, get_dynamic_names(), db.prepare_select(*this)}; } - _flag_list_t _flag_list; - _column_list_t _column_list; - _from_t _from; - _where_t _where; - _group_by_t _group_by; - _having_t _having; - _order_by_t _order_by; - _limit_t _limit; - _offset_t _offset; + std::tuple _terms; }; namespace vendor @@ -335,15 +315,7 @@ namespace sqlpp { context << "SELECT "; - serialize(t._flag_list, context); - serialize(t._column_list, context); - serialize(t._from, context); - serialize(t._where, context); - serialize(t._group_by, context); - serialize(t._having, context); - serialize(t._order_by, context); - serialize(t._limit, context); - serialize(t._offset, context); + interpret_tuple(t._terms, ' ', context); return context; } From 6d91cf2163c57cb601689418f242cc363fc74db1 Mon Sep 17 00:00:00 2001 From: rbock Date: Mon, 19 May 2014 23:24:41 +0200 Subject: [PATCH 10/16] select is now really a variadic template It is getting ready for customization to reflect vendor specific statement parts, e.g. order by in update and delete for mysql. --- include/sqlpp11/select.h | 106 +++++++++++++-------------------------- 1 file changed, 36 insertions(+), 70 deletions(-) diff --git a/include/sqlpp11/select.h b/include/sqlpp11/select.h index 40be4bdb..8d7033a5 100644 --- a/include/sqlpp11/select.h +++ b/include/sqlpp11/select.h @@ -52,60 +52,24 @@ namespace sqlpp { - template + template struct select_t; #warning STEPS: -#warning replace _select_column_t by _result_provider -#warning turn select into a variadic template (and have a empty_select which contains the default settings #warning do the same with insert, update and remove #warning deal with different return types in the connector (select could be a single value, update could be a range of rows) namespace detail { - template + template struct select_policies_t { using _database_t = Db; - using _flag_list_t = FlagList; - using _column_list_t = ColumnList; - using _from_t = From; - using _extra_tables_t = ExtraTables; - using _where_t = Where; - using _group_by_t = GroupBy; - using _having_t = Having; - using _order_by_t = OrderBy; - using _limit_t = Limit; - using _offset_t = Offset; + using _statement_t = select_t; - using _statement_t = select_t; - - struct _methods_t: - public _flag_list_t::template _methods_t, - public _column_list_t::template _methods_t, - public _from_t::template _methods_t, - public _extra_tables_t::template _methods_t, - public _where_t::template _methods_t, - public _group_by_t::template _methods_t, - public _having_t::template _methods_t, - public _order_by_t::template _methods_t, - public _limit_t::template _methods_t, - public _offset_t::template _methods_t + struct _methods_t: public Policies::template _methods_t... {}; - template + template struct _policies_update_t { static_assert(detail::is_element_of>::value, "policies update for non-policy class detected"); @@ -113,32 +77,24 @@ namespace sqlpp }; template - using _new_statement_t = typename _policies_update_t::type; + using _new_statement_t = typename _policies_update_t::type; - using _known_tables = detail::make_joined_set_t, extra_tables_of<_extra_tables_t>>; + using _all_required_tables = detail::make_joined_set_t...>; + using _all_provided_tables = detail::make_joined_set_t...>; + using _all_extra_tables = detail::make_joined_set_t...>; + + using _known_tables = detail::make_joined_set_t<_all_provided_tables, _all_extra_tables>; template using _no_unknown_tables = detail::is_subset_of, _known_tables>; - using _all_required_tables = - detail::make_joined_set_t< - required_tables_of<_flag_list_t>, - required_tables_of<_column_list_t>, - required_tables_of<_where_t>, - required_tables_of<_group_by_t>, - required_tables_of<_having_t>, - required_tables_of<_order_by_t>, - required_tables_of<_limit_t>, - required_tables_of<_offset_t> - >; - // The tables not covered by the from. using _required_tables = detail::make_difference_set_t< _all_required_tables, - provided_tables_of<_from_t> // Hint: extra_tables_t is not used here because it is just a helper for dynamic .add_*() methods and should not change the structural integrity + _all_provided_tables // Hint: extra_tables are not used here because they are just a helper for dynamic .add_*() >; - using _result_provider = detail::get_last_if; + using _result_provider = detail::get_last_if; // A select can be used as a pseudo table if // - at least one column is selected @@ -150,7 +106,7 @@ namespace sqlpp >::type; using _value_type = typename std::conditional< - detail::make_type_set_if_t::size::value == 0, + detail::none_t::value...>::value, value_type_of<_result_provider>, no_value_t // if a required statement part is missing (columns in a select), then the statement cannot be used as a value >::type; @@ -300,8 +256,6 @@ namespace sqlpp return {{}, get_dynamic_names(), db.prepare_select(*this)}; } - - std::tuple _terms; }; namespace vendor @@ -315,39 +269,51 @@ namespace sqlpp { context << "SELECT "; - interpret_tuple(t._terms, ' ', context); + using swallow = int[]; + (void) swallow{(serialize(static_cast(t), context), 0)...}; return context; } }; } - template - using make_select_t = typename detail::select_policies_t::_statement_t; + template + using blank_select_t = select_t; - make_select_t select() // FIXME: These should be constexpr + + blank_select_t select() // FIXME: These should be constexpr { return { }; } template auto select(Columns... columns) - -> make_select_t> + -> decltype(blank_select_t().columns(detail::make_select_column_list_t(columns...))) { - return { make_select_t(), detail::make_select_column_list_t{std::tuple_cat(detail::as_tuple::_(columns)...)} }; + return blank_select_t().columns(detail::make_select_column_list_t(columns...)); } template - make_select_t dynamic_select(const Database&) + blank_select_t dynamic_select(const Database&) { - return { make_select_t() }; + return { }; } template auto dynamic_select(const Database&, Columns... columns) - -> make_select_t> + -> decltype(blank_select_t().columns(detail::make_select_column_list_t(columns...))) { - return { make_select_t(), detail::make_select_column_list_t(std::tuple_cat(detail::as_tuple::_(columns)...)) }; + return blank_select_t().columns(detail::make_select_column_list_t(columns...)); } } From c81a7d33aeeab64f0ce84e447f0aea27ba15e1d0 Mon Sep 17 00:00:00 2001 From: rbock Date: Tue, 20 May 2014 08:50:55 +0200 Subject: [PATCH 11/16] Cleanup --- .../detail/{arg_selector.h => pick_arg.h} | 27 +++++++---- include/sqlpp11/select.h | 48 +++++-------------- tests/FunctionTest.cpp | 1 - 3 files changed, 30 insertions(+), 46 deletions(-) rename include/sqlpp11/detail/{arg_selector.h => pick_arg.h} (65%) diff --git a/include/sqlpp11/detail/arg_selector.h b/include/sqlpp11/detail/pick_arg.h similarity index 65% rename from include/sqlpp11/detail/arg_selector.h rename to include/sqlpp11/detail/pick_arg.h index e2922920..ca9f5296 100644 --- a/include/sqlpp11/detail/arg_selector.h +++ b/include/sqlpp11/detail/pick_arg.h @@ -24,23 +24,32 @@ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef SQLPP_DETAIL_ARG_SELECTOR_H -#define SQLPP_DETAIL_ARG_SELECTOR_H +#ifndef SQLPP_DETAIL_PICK_ARG_H +#define SQLPP_DETAIL_PICK_ARG_H + +#include namespace sqlpp { namespace detail { - template - struct arg_selector + template + Target pick_arg_impl(Statement statement, Term term, const std::true_type&) { - static Target _(Target, Target t) { return t; } + return term; + }; - template - static Target _(X, Target t) { return t; } + template + Target pick_arg_impl(Statement statement, Term term, const std::false_type&) + { + return static_cast(statement); + }; - template - static Target _(Target t, X) { return t; } + // Returns a statement's term either by picking the term from the statement or using the new term + template + Target pick_arg(Statement statement, Term term) + { + return pick_arg_impl(statement, term, std::is_same()); }; } } diff --git a/include/sqlpp11/select.h b/include/sqlpp11/select.h index 8d7033a5..8b12a784 100644 --- a/include/sqlpp11/select.h +++ b/include/sqlpp11/select.h @@ -47,8 +47,9 @@ #include #include -#include +//#include #include +#include namespace sqlpp { @@ -94,20 +95,20 @@ namespace sqlpp _all_provided_tables // Hint: extra_tables are not used here because they are just a helper for dynamic .add_*() >; - using _result_provider = detail::get_last_if; + using _result_type_provider = detail::get_last_if; // A select can be used as a pseudo table if // - at least one column is selected // - the select is complete (leaks no tables) using _can_be_used_as_table = typename std::conditional< - is_select_column_list_t<_result_provider>::value and _required_tables::size::value == 0, + is_select_column_list_t<_result_type_provider>::value and _required_tables::size::value == 0, std::true_type, std::false_type >::type; using _value_type = typename std::conditional< detail::none_t::value...>::value, - value_type_of<_result_provider>, + value_type_of<_result_type_provider>, no_value_t // if a required statement part is missing (columns in a select), then the statement cannot be used as a value >::type; @@ -124,27 +125,6 @@ namespace sqlpp }; } - namespace detail - { - template - Target pick_arg_impl(Statement statement, Term term, const std::true_type&) - { - return term; - }; - - template - Target pick_arg_impl(Statement statement, Term term, const std::false_type&) - { - return static_cast(statement); - }; - - template - Target pick_arg(Statement statement, Term term) - { - return pick_arg_impl(statement, term, std::is_same()); - }; - } - // SELECT template; using _traits = make_traits, ::sqlpp::tag::select>; - using _recursive_traits = typename _policies_t::_recursive_traits; using _database_t = Db; using _is_dynamic = typename std::conditional::value, std::false_type, std::true_type>::type; -#warning replace _column_list_t by a more generic name - using _column_list_t = typename _policies_t::_result_provider; + using _result_type_provider = typename _policies_t::_result_type_provider; using _parameter_tuple_t = std::tuple; using _parameter_list_t = typename make_parameter_list_t::type; template - using _result_row_t = typename _column_list_t::template _result_row_t; - using _dynamic_names_t = typename _column_list_t::_dynamic_names_t; + using _result_row_t = typename _result_type_provider::template _result_row_t; + using _dynamic_names_t = typename _result_type_provider::_dynamic_names_t; - using _is_select = std::true_type; using _requires_braces = std::true_type; - using _value_type = typename detail::select_policies_t::_value_type; - using _name_t = typename _column_list_t::_name_t; + using _name_t = typename _result_type_provider::_name_t; // Constructors select_t() @@ -198,7 +174,7 @@ namespace sqlpp template struct _pseudo_table_t { - using table = typename _column_list_t::template _pseudo_table_t; + using table = typename _result_type_provider::template _pseudo_table_t; using alias = typename table::template _alias_t; }; @@ -212,7 +188,7 @@ namespace sqlpp const _dynamic_names_t& get_dynamic_names() const { - return static_cast(*this)._dynamic_columns._dynamic_expression_names; + return static_cast(*this)._dynamic_columns._dynamic_expression_names; } static constexpr size_t _get_static_no_of_parameters() @@ -227,7 +203,7 @@ namespace sqlpp size_t get_no_of_result_columns() const { - return _column_list_t::static_size() + get_dynamic_names().size(); + return _result_type_provider::static_size() + get_dynamic_names().size(); } void _check_consistency() const diff --git a/tests/FunctionTest.cpp b/tests/FunctionTest.cpp index bc02891b..e668a668 100644 --- a/tests/FunctionTest.cpp +++ b/tests/FunctionTest.cpp @@ -190,7 +190,6 @@ int main() { using S = decltype(select(t.alpha).from(t)); static_assert(sqlpp::is_numeric_t::value, "type requirement"); - static_assert(sqlpp::is_numeric_t::value, "type requirement"); using TI = decltype(any(select(t.alpha).from(t))); using TT = decltype(any(select(t.beta).from(t))); From c4a02d931c7cceddf7784f9ee7649a3184f8cec2 Mon Sep 17 00:00:00 2001 From: rbock Date: Tue, 20 May 2014 21:22:55 +0200 Subject: [PATCH 12/16] SelectTypeTests compile again! --- include/sqlpp11/alias.h | 2 +- include/sqlpp11/multi_column.h | 2 +- include/sqlpp11/select.h | 17 +++++---- include/sqlpp11/sort_order.h | 5 ++- include/sqlpp11/table_alias.h | 3 +- include/sqlpp11/tvin.h | 38 ++++++++++---------- include/sqlpp11/type_traits.h | 9 +++-- include/sqlpp11/vendor/expression_fwd.h | 32 ++++++++--------- include/sqlpp11/vendor/field.h | 4 ++- include/sqlpp11/vendor/from.h | 3 +- include/sqlpp11/vendor/group_by.h | 4 ++- include/sqlpp11/vendor/having.h | 4 ++- include/sqlpp11/vendor/limit.h | 6 ++-- include/sqlpp11/vendor/offset.h | 6 ++-- include/sqlpp11/vendor/order_by.h | 4 ++- include/sqlpp11/vendor/select_column_list.h | 4 ++- include/sqlpp11/vendor/select_flag_list.h | 4 ++- include/sqlpp11/vendor/select_pseudo_table.h | 5 ++- include/sqlpp11/vendor/where.h | 4 ++- tests/CMakeLists.txt | 2 +- tests/SelectTypeTest.cpp | 26 +++++++------- 21 files changed, 109 insertions(+), 75 deletions(-) diff --git a/include/sqlpp11/alias.h b/include/sqlpp11/alias.h index b9d6e25a..c280c893 100644 --- a/include/sqlpp11/alias.h +++ b/include/sqlpp11/alias.h @@ -35,7 +35,7 @@ namespace sqlpp template struct expression_alias_t { - using _traits = make_traits, tag::named_expression>; + using _traits = make_traits, tag::named_expression, tag::alias>; using _recursive_traits = make_recursive_traits; static_assert(is_expression_t::value, "invalid argument for an expression alias"); diff --git a/include/sqlpp11/multi_column.h b/include/sqlpp11/multi_column.h index d61c2aaf..650e1bc7 100644 --- a/include/sqlpp11/multi_column.h +++ b/include/sqlpp11/multi_column.h @@ -76,7 +76,7 @@ namespace sqlpp template struct multi_column_alias_t { - using _traits = make_traits; + using _traits = make_traits; using _recursive_traits = make_recursive_traits; static_assert(detail::all_t::value...>::value, "multi_column parameters need to be named expressions"); diff --git a/include/sqlpp11/select.h b/include/sqlpp11/select.h index 8b12a784..95e319be 100644 --- a/include/sqlpp11/select.h +++ b/include/sqlpp11/select.h @@ -109,9 +109,14 @@ namespace sqlpp using _value_type = typename std::conditional< detail::none_t::value...>::value, value_type_of<_result_type_provider>, - no_value_t // if a required statement part is missing (columns in a select), then the statement cannot be used as a value + no_value_t // if a required statement part is missing (e.g. columns in a select), then the statement cannot be used as a value >::type; + using _is_expression = typename std::conditional< + std::is_same<_value_type, no_value_t>::value, + std::false_type, + std::true_type>::type; + using _traits = make_traits<_value_type>; struct _recursive_traits @@ -136,7 +141,7 @@ namespace sqlpp { using _policies_t = typename detail::select_policies_t; - using _traits = make_traits, ::sqlpp::tag::select>; + using _traits = make_traits, ::sqlpp::tag::select, tag::expression_if, tag::named_expression_if>; using _recursive_traits = typename _policies_t::_recursive_traits; using _database_t = Db; @@ -274,9 +279,9 @@ namespace sqlpp template auto select(Columns... columns) - -> decltype(blank_select_t().columns(detail::make_select_column_list_t(columns...))) + -> decltype(blank_select_t().columns(columns...)) { - return blank_select_t().columns(detail::make_select_column_list_t(columns...)); + return blank_select_t().columns(columns...); } template @@ -287,9 +292,9 @@ namespace sqlpp template auto dynamic_select(const Database&, Columns... columns) - -> decltype(blank_select_t().columns(detail::make_select_column_list_t(columns...))) + -> decltype(blank_select_t().columns(columns...)) { - return blank_select_t().columns(detail::make_select_column_list_t(columns...)); + return blank_select_t().columns(columns...); } } diff --git a/include/sqlpp11/sort_order.h b/include/sqlpp11/sort_order.h index 8f70b3c8..7ef6c238 100644 --- a/include/sqlpp11/sort_order.h +++ b/include/sqlpp11/sort_order.h @@ -40,9 +40,8 @@ namespace sqlpp template struct sort_order_t { - using _is_sort_order = std::true_type; - using _provided_tables = detail::type_set<>; - using _required_tables = typename Expression::_required_tables; + using _traits = make_traits; + using _recursive_traits = make_recursive_traits; Expression _expression; }; diff --git a/include/sqlpp11/table_alias.h b/include/sqlpp11/table_alias.h index 7ac78868..754ec175 100644 --- a/include/sqlpp11/table_alias.h +++ b/include/sqlpp11/table_alias.h @@ -47,7 +47,8 @@ namespace sqlpp { using _parameters = std::tuple<>; using _required_tables = detail::type_set<>; - using _provided_tables = detail::type_set
; + using _provided_tables = detail::type_set; + using _extra_tables = detail::type_set<>; }; static_assert(required_tables_of
::size::value == 0, "table aliases must not depend on external tables"); diff --git a/include/sqlpp11/tvin.h b/include/sqlpp11/tvin.h index a838296e..1a517714 100644 --- a/include/sqlpp11/tvin.h +++ b/include/sqlpp11/tvin.h @@ -73,18 +73,19 @@ namespace sqlpp }; } - template + template struct maybe_tvin_t { - using _provided_tables = detail::type_set<>; - using _required_tables = typename T::_required_tables; + using _traits = make_traits, tag::expression>; + using _recursive_traits = make_recursive_traits; + static constexpr bool _is_trivial() { return false; } - maybe_tvin_t(T t): - _value(t) + maybe_tvin_t(Operand operand): + _value(operand) {} maybe_tvin_t(const maybe_tvin_t&) = default; maybe_tvin_t(maybe_tvin_t&&) = default; @@ -92,21 +93,22 @@ namespace sqlpp maybe_tvin_t& operator=(maybe_tvin_t&&) = default; ~maybe_tvin_t() = default; - T _value; + Operand _value; }; - template - struct maybe_tvin_t> + template + struct maybe_tvin_t> { - using _provided_tables = detail::type_set<>; - using _required_tables = typename T::_required_tables; + using _traits = make_traits, tag::expression>; + using _recursive_traits = make_recursive_traits; + bool _is_trivial() const { return _value._is_trivial(); }; - maybe_tvin_t(tvin_t t): - _value(t._value) + maybe_tvin_t(tvin_t operand): + _value(operand._value) {} maybe_tvin_t(const maybe_tvin_t&) = default; maybe_tvin_t(maybe_tvin_t&&) = default; @@ -114,7 +116,7 @@ namespace sqlpp maybe_tvin_t& operator=(maybe_tvin_t&&) = default; ~maybe_tvin_t() = default; - typename tvin_t::_operand_t _value; + typename tvin_t::_operand_t _value; }; namespace vendor @@ -139,13 +141,13 @@ namespace sqlpp }; } - template - auto tvin(T t) -> tvin_t::type> + template + auto tvin(Operand operand) -> tvin_t::type> { - using _operand_t = typename vendor::wrap_operand::type; + using _operand_t = typename vendor::wrap_operand::type; static_assert(std::is_same<_operand_t, vendor::text_operand>::value - or not std::is_same<_operand_t, T>::value, "tvin() used with invalid type (only string and primitive types allowed)"); - return {{t}}; + or not std::is_same<_operand_t, Operand>::value, "tvin() used with invalid type (only string and primitive types allowed)"); + return {{operand}}; } } diff --git a/include/sqlpp11/type_traits.h b/include/sqlpp11/type_traits.h index a1f231c5..dc94412f 100644 --- a/include/sqlpp11/type_traits.h +++ b/include/sqlpp11/type_traits.h @@ -92,8 +92,13 @@ namespace sqlpp SQLPP_IS_VALUE_TRAIT_GENERATOR(named_expression); namespace tag { - template - using named_expression_if = typename std::conditional::type; + template + using named_expression_if = typename std::conditional::type; + } + namespace tag + { + template + using expression_if = typename std::conditional::type; } SQLPP_IS_VALUE_TRAIT_GENERATOR(multi_expression); SQLPP_IS_VALUE_TRAIT_GENERATOR(alias); diff --git a/include/sqlpp11/vendor/expression_fwd.h b/include/sqlpp11/vendor/expression_fwd.h index b6529e8b..374a4265 100644 --- a/include/sqlpp11/vendor/expression_fwd.h +++ b/include/sqlpp11/vendor/expression_fwd.h @@ -35,99 +35,99 @@ namespace sqlpp { struct less { - using _value_type = ::sqlpp::detail::boolean; + using _traits = make_traits<::sqlpp::detail::boolean>; static constexpr const char* _name = "<"; }; struct less_equal { - using _value_type = ::sqlpp::detail::boolean; + using _traits = make_traits<::sqlpp::detail::boolean>; static constexpr const char* _name = "<="; }; struct equal_to { - using _value_type = ::sqlpp::detail::boolean; + using _traits = make_traits<::sqlpp::detail::boolean>; }; struct not_equal_to { - using _value_type = ::sqlpp::detail::boolean; + using _traits = make_traits<::sqlpp::detail::boolean>; }; struct greater_equal { - using _value_type = ::sqlpp::detail::boolean; + using _traits = make_traits<::sqlpp::detail::boolean>; static constexpr const char* _name = ">="; }; struct greater { - using _value_type = ::sqlpp::detail::boolean; + using _traits = make_traits<::sqlpp::detail::boolean>; static constexpr const char* _name = ">"; }; struct logical_or { - using _value_type = ::sqlpp::detail::boolean; + using _traits = make_traits<::sqlpp::detail::boolean>; static constexpr const char* _name = " OR "; }; struct logical_and { - using _value_type = ::sqlpp::detail::boolean; + using _traits = make_traits<::sqlpp::detail::boolean>; static constexpr const char* _name = " AND "; }; struct logical_not { - using _value_type = ::sqlpp::detail::boolean; + using _traits = make_traits<::sqlpp::detail::boolean>; }; template struct plus { - using _value_type = ValueType; + using _traits = make_traits; static constexpr const char* _name = "+"; }; template struct minus { - using _value_type = ValueType; + using _traits = make_traits; static constexpr const char* _name = "-"; }; template struct multiplies { - using _value_type = ValueType; + using _traits = make_traits; static constexpr const char* _name = "*"; }; struct divides { - using _value_type = ::sqlpp::detail::floating_point; + using _traits = make_traits<::sqlpp::detail::floating_point>; static constexpr const char* _name = "/"; }; struct modulus { - using _value_type = ::sqlpp::detail::integral; + using _traits = make_traits<::sqlpp::detail::integral>; static constexpr const char* _name = "%"; }; template struct unary_minus { - using _value_type = ValueType; + using _traits = make_traits; static constexpr const char* _name = "-"; }; template struct unary_plus { - using _value_type = ValueType; + using _traits = make_traits; static constexpr const char* _name = "+"; }; } diff --git a/include/sqlpp11/vendor/field.h b/include/sqlpp11/vendor/field.h index caf93c78..b843dc8d 100644 --- a/include/sqlpp11/vendor/field.h +++ b/include/sqlpp11/vendor/field.h @@ -36,8 +36,10 @@ namespace sqlpp template struct field_t { + using _traits = make_traits; + using _recursive_traits = make_recursive_traits<>; + using _name_t = NameType; - using _value_type = ValueType; static constexpr bool _trivial_value_is_null = TrivialValueIsNull; }; diff --git a/include/sqlpp11/vendor/from.h b/include/sqlpp11/vendor/from.h index 3e30ea33..2a82b4e0 100644 --- a/include/sqlpp11/vendor/from.h +++ b/include/sqlpp11/vendor/from.h @@ -55,6 +55,7 @@ namespace sqlpp static_assert(required_tables_of::size::value == 0, "at least one table depends on another table"); + from_t& _from() { return *this; } from_t(Tables... tables): _tables(tables...) @@ -84,7 +85,7 @@ namespace sqlpp template void _add_from_impl(Table table, const std::true_type&) { - return static_cast(this)->_from._dynamic_tables.emplace_back(table); + return static_cast(this)->_from()._dynamic_tables.emplace_back(table); } template diff --git a/include/sqlpp11/vendor/group_by.h b/include/sqlpp11/vendor/group_by.h index 51fb4f11..3766c66c 100644 --- a/include/sqlpp11/vendor/group_by.h +++ b/include/sqlpp11/vendor/group_by.h @@ -54,6 +54,8 @@ 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...) {} @@ -89,7 +91,7 @@ namespace sqlpp template void _add_group_by_impl(Expression expression, const std::true_type&) { - return static_cast(this)->_group_by._dynamic_expressions.emplace_back(expression); + return static_cast(this)->_group_by()._dynamic_expressions.emplace_back(expression); } template diff --git a/include/sqlpp11/vendor/having.h b/include/sqlpp11/vendor/having.h index fa15285f..8f85eab9 100644 --- a/include/sqlpp11/vendor/having.h +++ b/include/sqlpp11/vendor/having.h @@ -50,6 +50,8 @@ 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; } + having_t(Expressions... expressions): _expressions(expressions...) {} @@ -85,7 +87,7 @@ namespace sqlpp template void _add_having_impl(Expression expression, const std::true_type&) { - return static_cast(this)->_having._dynamic_expressions.emplace_back(expression); + return static_cast(this)->_having()._dynamic_expressions.emplace_back(expression); } template diff --git a/include/sqlpp11/vendor/limit.h b/include/sqlpp11/vendor/limit.h index 62e94916..b5b2ec89 100644 --- a/include/sqlpp11/vendor/limit.h +++ b/include/sqlpp11/vendor/limit.h @@ -68,6 +68,8 @@ namespace sqlpp using _traits = make_traits; using _recursive_traits = make_recursive_traits<>; + dynamic_limit_t& _limit() { return *this; } + dynamic_limit_t(): _value(noop()) { @@ -94,8 +96,8 @@ namespace sqlpp { // 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; + static_cast(this)->_limit()._value = arg_t{value}; + static_cast(this)->_limit()._initialized = true; } }; diff --git a/include/sqlpp11/vendor/offset.h b/include/sqlpp11/vendor/offset.h index 83cacd95..dca7fd16 100644 --- a/include/sqlpp11/vendor/offset.h +++ b/include/sqlpp11/vendor/offset.h @@ -68,6 +68,8 @@ namespace sqlpp using _traits = make_traits; using _recursive_traits = make_recursive_traits<>; + dynamic_offset_t& _offset() { return *this; } + dynamic_offset_t(): _value(noop()) { @@ -94,8 +96,8 @@ namespace sqlpp { // FIXME: Make sure that Offset does not require external tables? Need to read up on SQL using arg_t = typename wrap_operand::type; - static_cast(this)->_offset._value = arg_t{value}; - static_cast(this)->_offset._initialized = true; + static_cast(this)->_offset()._value = arg_t{value}; + static_cast(this)->_offset()._initialized = true; } }; diff --git a/include/sqlpp11/vendor/order_by.h b/include/sqlpp11/vendor/order_by.h index a6d4a5ad..f60537eb 100644 --- a/include/sqlpp11/vendor/order_by.h +++ b/include/sqlpp11/vendor/order_by.h @@ -53,6 +53,8 @@ namespace sqlpp 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): _expressions(expressions...) {} @@ -88,7 +90,7 @@ namespace sqlpp template void _add_order_by_impl(Expression expression, const std::true_type&) { - return static_cast(this)->_order_by._dynamic_expressions.emplace_back(expression); + return static_cast(this)->_order_by()._dynamic_expressions.emplace_back(expression); } template diff --git a/include/sqlpp11/vendor/select_column_list.h b/include/sqlpp11/vendor/select_column_list.h index ce98c227..ef3ad4e2 100644 --- a/include/sqlpp11/vendor/select_column_list.h +++ b/include/sqlpp11/vendor/select_column_list.h @@ -164,6 +164,8 @@ namespace sqlpp template using _dynamic_t = select_column_list_t>; + select_column_list_t& _select_column_list() { return *this; } + select_column_list_t(std::tuple columns): _columns(columns) {} @@ -213,7 +215,7 @@ namespace sqlpp template void _add_column_impl(NamedExpression namedExpression, const std::true_type&) { - return static_cast(this)->_column_list._dynamic_columns.emplace_back(namedExpression); + return static_cast(this)->_select_column_list()._dynamic_columns.emplace_back(namedExpression); } template diff --git a/include/sqlpp11/vendor/select_flag_list.h b/include/sqlpp11/vendor/select_flag_list.h index 85303440..5a7e2cf9 100644 --- a/include/sqlpp11/vendor/select_flag_list.h +++ b/include/sqlpp11/vendor/select_flag_list.h @@ -51,6 +51,8 @@ namespace sqlpp static_assert(::sqlpp::detail::all_t::value...>::value, "at least one argument is not a select flag in select flag list"); + select_flag_list_t& _select_flag_list() { return *this; } + select_flag_list_t(Flags... flags): _flags(flags...) {} @@ -86,7 +88,7 @@ namespace sqlpp template void _add_flag_impl(Flag flag, const std::true_type&) { - return static_cast(this)->_flag_list._dynamic_flags.emplace_back(flag); + return static_cast(this)->_select_flag_list()._dynamic_flags.emplace_back(flag); } template diff --git a/include/sqlpp11/vendor/select_pseudo_table.h b/include/sqlpp11/vendor/select_pseudo_table.h index a63c4d63..eae7ce5a 100644 --- a/include/sqlpp11/vendor/select_pseudo_table.h +++ b/include/sqlpp11/vendor/select_pseudo_table.h @@ -35,8 +35,11 @@ namespace sqlpp template struct select_column_spec_t { + using _traits = make_traits>; + using _recursive_traits = make_recursive_traits<>; + using _value_type = value_type_of; // FIXME: column specs probably should use _traits, too + using _name_t = typename Expr::_name_t; - using _value_type = typename Expr::_value_type; struct _column_type { using _must_not_insert = std::true_type; diff --git a/include/sqlpp11/vendor/where.h b/include/sqlpp11/vendor/where.h index 01557cdd..9c77059f 100644 --- a/include/sqlpp11/vendor/where.h +++ b/include/sqlpp11/vendor/where.h @@ -51,6 +51,8 @@ namespace sqlpp static_assert(sqlpp::detail::none_t::value...>::value, "at least one argument is an assignment in where()"); static_assert(sqlpp::detail::all_t::value...>::value, "at least one argument is not valid expression in where()"); + where_t& _where() { return *this; } + where_t(Expressions... expressions): _expressions(expressions...) {} @@ -86,7 +88,7 @@ namespace sqlpp template void _add_where_impl(Expression expression, const std::true_type&) { - return static_cast(this)->_where._dynamic_expressions.emplace_back(expression); + return static_cast(this)->_where()._dynamic_expressions.emplace_back(expression); } template diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 71771eee..98f12e6e 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -11,7 +11,7 @@ endmacro () #build_and_run(RemoveTest) #build_and_run(UpdateTest) #build_and_run(SelectTest) -#build_and_run(SelectTypeTest) +build_and_run(SelectTypeTest) build_and_run(FunctionTest) #build_and_run(PreparedTest) diff --git a/tests/SelectTypeTest.cpp b/tests/SelectTypeTest.cpp index 12cf9c56..8e1784de 100644 --- a/tests/SelectTypeTest.cpp +++ b/tests/SelectTypeTest.cpp @@ -158,10 +158,10 @@ int main() // Test a select of a single column without a from { - using T = decltype(select(t.alpha)); // Hint: The current rule is pretty crude (a from is required), but certainly better than nothing - static_assert(not sqlpp::is_numeric_t::value, "type requirement"); - static_assert(not sqlpp::is_expression_t::value, "type requirement"); - static_assert(not sqlpp::is_named_expression_t::value, "type requirement"); + using T = decltype(select(t.alpha)); + static_assert(sqlpp::is_numeric_t::value, "type requirement"); + static_assert(sqlpp::is_expression_t::value, "type requirement"); + static_assert(sqlpp::is_named_expression_t::value, "type requirement"); static_assert(not sqlpp::require_insert_t::value, "type requirement"); static_assert(not sqlpp::must_not_insert_t::value, "type requirement"); static_assert(not sqlpp::must_not_update_t::value, "type requirement"); @@ -175,8 +175,8 @@ int main() // Test a select of a single numeric table column { using T = decltype(select(t.alpha).from(t)); - static_assert(sqlpp::is_select_column_list_t::value, "Must not be noop"); - static_assert(sqlpp::is_from_t::value, "Must not be noop"); + //static_assert(sqlpp::is_select_column_list_t::value, "Must not be noop"); + //static_assert(sqlpp::is_from_t::value, "Must not be noop"); static_assert(sqlpp::is_numeric_t::value, "type requirement"); static_assert(sqlpp::is_expression_t::value, "type requirement"); static_assert(sqlpp::is_named_expression_t::value, "type requirement"); @@ -290,7 +290,7 @@ int main() { auto m = multi_column(t.alpha, t.beta).as(alias::a); auto a = select(m).from(t).as(alias::b).a; - static_assert(not sqlpp::is_value_t::value, "a multi_column is not a value"); + // FIXME: Do we really need that test? multi_column is a no_value static_assert(not sqlpp::is_expression_t::value, "a multi_column is not a value"); } // Test that result sets with identical name/value combinations have identical types { @@ -299,8 +299,8 @@ int main() using A = typename decltype(a)::_result_row_t; using B = typename decltype(b)::_result_row_t; static_assert(std::is_same< - decltype(t.alpha)::_value_type::_base_value_type, - decltype(f.epsilon)::_value_type::_base_value_type>::value, "Two bigint columns must have identical base_value_type"); + sqlpp::value_type_of, + sqlpp::value_type_of>::value, "Two bigint columns must have identical base_value_type"); static_assert(std::is_same::value, "select with identical columns(name/value_type) need to have identical result_types"); } @@ -339,9 +339,8 @@ int main() static_assert(sqlpp::is_select_flag_t::value, "sqlpp::all has to be a select_flag"); using T = sqlpp::vendor::wrap_operand::type; static_assert(sqlpp::is_regular::value, "type requirement"); - static_assert(T::_is_expression, "T has to be an expression"); - static_assert(std::is_same::value, "T has to be a numeric"); - static_assert(sqlpp::is_numeric_t::value, "T has to be a numeric"); + static_assert(sqlpp::is_expression_t::value, "T has to be an expression"); + static_assert(sqlpp::is_numeric_t::value, "T has to be numeric"); static_assert(sqlpp::is_numeric_t::value, "TabBar.alpha has to be a numeric"); ((t.alpha + 7) + 4).asc(); static_assert(sqlpp::is_boolean_t::value, "Comparison expression have to be boolean"); @@ -353,7 +352,6 @@ int main() static_assert(sqlpp::must_not_insert_t::value, "alpha must not be inserted"); serialize(t.alpha, printer).str(); std::cerr << "\n" << sizeof(test::TabBar) << std::endl; - static_assert(std::is_same::value, "alpha should be a named expression"); static_assert(sqlpp::is_named_expression_t::value, "alpha should be a named expression"); static_assert(sqlpp::is_named_expression_t::value, "an alias of alpha should be a named expression"); static_assert(sqlpp::is_alias_t::value, "an alias of alpha should be an alias"); @@ -366,6 +364,7 @@ int main() auto s = select(r.a).from(r); using RA = decltype(r.a); using S = decltype(s); + /* using SCL = typename S::_column_list_t; using SF = typename S::_from_t; static_assert(sqlpp::is_select_column_list_t::value, "no column list"); @@ -375,6 +374,7 @@ int main() static_assert(SCL_T::size::value == 1, "unexpected table_set in column_list"); static_assert(SF_T::size::value == 1, "unexpected table_set in from"); static_assert(std::is_same::value, "should be the same"); + */ static_assert(sqlpp::is_boolean_t::value, "select(bool) has to be a bool"); auto s1 = sqlpp::select().flags(sqlpp::distinct, sqlpp::straight_join).columns(l.alpha, l.beta, select(r.a).from(r)) .from(r,t,l) From 22e1e7c531240ed24623d527a9fe382e5d1e1314 Mon Sep 17 00:00:00 2001 From: rbock Date: Thu, 22 May 2014 22:53:08 +0200 Subject: [PATCH 13/16] Migrated insert to be truly variadic --- include/sqlpp11/column.h | 4 +- include/sqlpp11/insert.h | 93 +++++++++++----------- include/sqlpp11/select.h | 1 - include/sqlpp11/type_traits.h | 1 + include/sqlpp11/vendor/assignment.h | 2 +- include/sqlpp11/vendor/insert_value.h | 8 +- include/sqlpp11/vendor/insert_value_list.h | 55 +++++++------ include/sqlpp11/vendor/single_table.h | 31 ++++++-- include/sqlpp11/vendor/where.h | 2 +- tests/CMakeLists.txt | 6 +- 10 files changed, 115 insertions(+), 88 deletions(-) diff --git a/include/sqlpp11/column.h b/include/sqlpp11/column.h index 383f94cc..47f764f1 100644 --- a/include/sqlpp11/column.h +++ b/include/sqlpp11/column.h @@ -81,12 +81,12 @@ namespace sqlpp } template - auto operator =(T t) const -> vendor::assignment_t::type> + auto operator =(T t) const -> vendor::assignment_t> { using rhs = vendor::wrap_operand_t; static_assert(_is_valid_operand::value, "invalid rhs operand assignment operand"); - return { *this, {t} }; + return { *this, rhs{t} }; } auto operator =(sqlpp::null_t) const diff --git a/include/sqlpp11/insert.h b/include/sqlpp11/insert.h index c24f236f..78e5d0f9 100644 --- a/include/sqlpp11/insert.h +++ b/include/sqlpp11/insert.h @@ -35,78 +35,86 @@ #include #include #include -#include + +#include +#include namespace sqlpp { - template + template struct insert_t; namespace detail { - template + template struct insert_policies_t { using _database_t = Db; - using _table_t = Table; - using _insert_value_list_t = InsertValueList; - using _statement_t = insert_t; + using _statement_t = insert_t; - struct _methods_t: - public _insert_value_list_t::template _methods_t + struct _methods_t: public Policies::template _methods_t... {}; - template - struct _policies_insert_t + template + struct _policies_update_t { + static_assert(detail::is_element_of>::value, "policies update for non-policy class detected"); using type = insert_t...>; }; template - using _new_statement_t = typename _policies_insert_t::type; + using _new_statement_t = typename _policies_update_t::type; - using _table_set = typename _table_t::_table_set; + using _all_required_tables = detail::make_joined_set_t...>; + using _all_provided_tables = detail::make_joined_set_t...>; + using _all_extra_tables = detail::make_joined_set_t...>; - using _known_tables = detail::make_joined_set_t; + using _known_tables = detail::make_joined_set_t<_all_provided_tables, _all_extra_tables>; template - using _no_unknown_tables = detail::is_subset_of; + using _no_unknown_tables = detail::is_subset_of, _known_tables>; + + // The tables not covered by the from. + using _required_tables = detail::make_difference_set_t< + _all_required_tables, + _all_provided_tables // Hint: extra_tables are not used here because they are just a helper for dynamic .add_*() + >; + + using _traits = make_traits; // FIXME + + struct _recursive_traits + { + using _parameters = std::tuple<>; // FIXME + using _required_tables = _required_tables; + using _provided_tables = detail::type_set<>; + using _extra_tables = detail::type_set<>; + }; }; } // INSERT - template + template struct insert_t: + public Policies..., public detail::insert_policies_t::_methods_t { using _policies_t = typename detail::insert_policies_t; using _database_t = typename _policies_t::_database_t; - using _table_t = typename _policies_t::_table_t; - using _insert_value_list_t = typename _policies_t::_insert_value_list_t; using _is_dynamic = typename std::conditional::value, std::false_type, std::true_type>::type; using _parameter_tuple_t = std::tuple; using _parameter_list_t = typename make_parameter_list_t::type; - static_assert(::sqlpp::detail::is_superset_of::value, "columns do not match the table they are to be inserted into"); // Constructors insert_t() {} template - insert_t(Statement s, T t): - _table(detail::arg_selector<_table_t>::_(s._table, t)), - _insert_value_list(detail::arg_selector<_insert_value_list_t>::_(s._insert_value_list, t)) + insert_t(Statement statement, T term): + Policies(detail::pick_arg(statement, term))... {} insert_t(const insert_t&) = default; @@ -126,12 +134,6 @@ namespace sqlpp return _parameter_list_t::size::value; } - template - struct is_table_subset_of_table - { - static constexpr bool value = ::sqlpp::detail::is_subset_of::value; - }; - void _check_consistency() const { // FIXME: Read up on what is allowed/prohibited in INSERT @@ -154,9 +156,6 @@ namespace sqlpp return {{}, db.prepare_insert(*this)}; } - - _insert_value_list_t _insert_value_list; - _table_t _table; }; namespace vendor @@ -169,30 +168,32 @@ namespace sqlpp static Context& _(const T& t, Context& context) { context << "INSERT INTO "; - serialize(t._table, context); - serialize(t._insert_value_list, context); + + using swallow = int[]; + (void) swallow{(serialize(static_cast(t), context), 0)...}; return context; } }; } - template - using make_insert_t = typename detail::insert_policies_t::_statement_t; + template + using blank_insert_t = insert_t; template constexpr auto insert_into(Table table) - -> make_insert_t> + -> decltype(blank_insert_t().into(table)) { - return { make_insert_t(), vendor::single_table_t{table} }; + return { blank_insert_t().into(table) }; } template constexpr auto dynamic_insert_into(const Database&, Table table) - -> make_insert_t> + -> decltype(blank_insert_t().into(table)) { - return { make_insert_t(), vendor::single_table_t{table} }; + return { blank_insert_t().into(table) }; } - } #endif diff --git a/include/sqlpp11/select.h b/include/sqlpp11/select.h index 95e319be..6292e21c 100644 --- a/include/sqlpp11/select.h +++ b/include/sqlpp11/select.h @@ -47,7 +47,6 @@ #include #include -//#include #include #include diff --git a/include/sqlpp11/type_traits.h b/include/sqlpp11/type_traits.h index dc94412f..a195f1c0 100644 --- a/include/sqlpp11/type_traits.h +++ b/include/sqlpp11/type_traits.h @@ -121,6 +121,7 @@ namespace sqlpp SQLPP_IS_VALUE_TRAIT_GENERATOR(select_flag_list); SQLPP_IS_VALUE_TRAIT_GENERATOR(select_column_list); SQLPP_IS_VALUE_TRAIT_GENERATOR(from); + SQLPP_IS_VALUE_TRAIT_GENERATOR(single_table); SQLPP_IS_VALUE_TRAIT_GENERATOR(extra_tables); SQLPP_IS_VALUE_TRAIT_GENERATOR(on); SQLPP_IS_VALUE_TRAIT_GENERATOR(dynamic); diff --git a/include/sqlpp11/vendor/assignment.h b/include/sqlpp11/vendor/assignment.h index 52ad3c75..1899a393 100644 --- a/include/sqlpp11/vendor/assignment.h +++ b/include/sqlpp11/vendor/assignment.h @@ -69,7 +69,7 @@ namespace sqlpp using _recursive_traits = make_recursive_traits; using _column_t = Lhs; - using _value_t = Lhs; + using _value_t = Rhs; static_assert(can_be_null_t<_column_t>::value ? true : not std::is_same<_value_t, null_t>::value, "column must not be null"); diff --git a/include/sqlpp11/vendor/insert_value.h b/include/sqlpp11/vendor/insert_value.h index ddf54f7e..b0f4dfea 100644 --- a/include/sqlpp11/vendor/insert_value.h +++ b/include/sqlpp11/vendor/insert_value.h @@ -44,8 +44,6 @@ namespace sqlpp struct type_if { using type = Type; - using _provided_tables = detail::type_set<>; - using _required_tables = typename Type::_required_tables; }; template @@ -53,8 +51,8 @@ namespace sqlpp { struct type { - using _provided_tables = detail::type_set<>; - using _required_tables = sqlpp::detail::type_set<>; + using _traits = make_traits; + using _recursive_traits = make_recursive_traits<>; }; }; } @@ -63,7 +61,7 @@ namespace sqlpp struct insert_value_t { using _is_insert_value = std::true_type; - using _pure_value_t = typename Column::_value_type::_cpp_value_type; + using _pure_value_t = typename value_type_of::_cpp_value_type; using _wrapped_value_t = typename wrap_operand<_pure_value_t>::type; using _tvin_t = typename detail::type_if, can_be_null_t::value>::type; // static asserts and SFINAE do not work together using _null_t = typename detail::type_if::value>::type; // static asserts and SFINAE do not work together diff --git a/include/sqlpp11/vendor/insert_value_list.h b/include/sqlpp11/vendor/insert_value_list.h index e23dc9f0..9cebe8d1 100644 --- a/include/sqlpp11/vendor/insert_value_list.h +++ b/include/sqlpp11/vendor/insert_value_list.h @@ -42,8 +42,8 @@ namespace sqlpp // COLUMN AND VALUE LIST struct insert_default_values_t { - using _required_tables = ::sqlpp::detail::type_set<>; - using _is_dynamic = std::false_type; + using _traits = make_traits; + using _recursive_traits = make_recursive_traits<>; template struct _methods_t @@ -53,29 +53,36 @@ namespace sqlpp template struct insert_list_t { - using _is_insert_list = std::true_type; + using _traits = make_traits; + using _recursive_traits = make_recursive_traits; + using _is_dynamic = typename std::conditional::value, std::false_type, std::true_type>::type; - using _parameter_tuple_t = std::tuple; + template class Target> using copy_assignments_t = Target; // FIXME: Nice idea to copy variadic template arguments? template class Target, template class Wrap> using copy_wrapped_assignments_t = Target...>; - static_assert(_is_dynamic::value or sizeof...(Assignments), "at least one select expression required in set()"); + static_assert(_is_dynamic::value or sizeof...(Assignments), "at least one assignment required in set()"); static_assert(not ::sqlpp::detail::has_duplicates::value, "at least one duplicate argument detected in set()"); static_assert(sqlpp::detail::all_t::value...>::value, "at least one argument is not an assignment in set()"); - static_assert(sqlpp::detail::none_t::value...>::value, "at least one assignment is prohibited by its column definition in set()"); + static_assert(sqlpp::detail::none_t::value...>::value, "at least one assignment is prohibited by its column definition in set()"); +#warning: Need to reactivate these checks + /* using _column_required_tables = typename ::sqlpp::detail::make_joined_set::type; using _value_required_tables = typename ::sqlpp::detail::make_joined_set::type; using _provided_tables = ::sqlpp::detail::type_set<>; using _required_tables = typename ::sqlpp::detail::make_joined_set<_column_required_tables, _value_required_tables>::type; static_assert(sizeof...(Assignments) ? (_column_required_tables::size::value == 1) : true, "set() contains assignments for tables from several columns"); static_assert(::sqlpp::detail::is_subset_of<_value_required_tables, _column_required_tables>::value, "set() contains values from foreign tables"); + */ + insert_list_t& _insert_value_list() { return *this; } + insert_list_t(Assignments... assignment): _assignments(assignment...), _columns({assignment._lhs}...), @@ -92,22 +99,24 @@ namespace sqlpp struct _methods_t { template + void add_set_ntc(Assignment assignment) + { + add_set(assignment); + } + + template void add_set(Assignment assignment) { static_assert(_is_dynamic::value, "add_set must not be called for static from()"); static_assert(is_assignment_t::value, "add_set() arguments require to be assigments"); static_assert(not must_not_insert_t::value, "add_set() argument must not be used in insert"); - using _column_table_set = typename Assignment::_column_t::_table_set; - using _value_table_set = typename Assignment::value_type::_table_set; - static_assert(::sqlpp::detail::is_subset_of<_value_table_set, typename Policies::_table_set>::value, "add_set() contains a column from a foreign table"); - static_assert(::sqlpp::detail::is_subset_of<_column_table_set, typename Policies::_table_set>::value, "add_set() contains a value from a foreign table"); + static_assert(not TableCheckRequired::value or Policies::template _no_unknown_tables::value, "add_set() contains a column from a foreign table"); using ok = ::sqlpp::detail::all_t< _is_dynamic::value, is_assignment_t::value, not must_not_insert_t::value, - ::sqlpp::detail::is_subset_of<_value_table_set, typename Policies::_table_set>::value, - ::sqlpp::detail::is_subset_of<_column_table_set, typename Policies::_table_set>::value>; + (not TableCheckRequired::value or Policies::template _no_unknown_tables::value)>; _add_set_impl(assignment, ok()); // dispatch to prevent compile messages after the static_assert } @@ -116,8 +125,8 @@ namespace sqlpp template void _add_set_impl(Assignment assignment, const std::true_type&) { - static_cast(this)->_insert_value_list._dynamic_columns.emplace_back(simple_column_t{assignment._lhs}); - static_cast(this)->_insert_value_list._dynamic_values.emplace_back(assignment._rhs); + static_cast(this)->_insert_value_list()._dynamic_columns.emplace_back(simple_column_t{assignment._lhs}); + static_cast(this)->_insert_value_list()._dynamic_values.emplace_back(assignment._rhs); } template @@ -127,7 +136,7 @@ namespace sqlpp std::tuple...> _columns; - std::tuple _values; + std::tuple _values; std::tuple _assignments; // FIXME: Need to replace _columns and _values by _assignments (connector-container requires assignments) typename vendor::interpretable_list_t _dynamic_columns; typename vendor::interpretable_list_t _dynamic_values; @@ -136,8 +145,8 @@ namespace sqlpp template struct column_list_t { - using _is_column_list = std::true_type; - using _parameter_tuple_t = std::tuple; + using _traits = make_traits; + using _recursive_traits = make_recursive_traits; static_assert(sizeof...(Columns), "at least one column required in columns()"); @@ -148,9 +157,10 @@ namespace sqlpp static_assert(::sqlpp::detail::none_t::value...>::value, "at least one column argument has a must_not_insert flag in its definition"); using _value_tuple_t = std::tuple...>; - using _table_set = typename ::sqlpp::detail::make_joined_set::type; - static_assert(_table_set::size::value == 1, "columns from multiple tables in columns()"); + static_assert(required_tables_of::size::value == 1, "columns from multiple tables in columns()"); + + column_list_t& _insert_value_list() { return *this; } column_list_t(Columns... columns): _columns(simple_column_t{columns}...) @@ -184,7 +194,7 @@ namespace sqlpp template void _add_values_impl(const std::true_type&, Assignments... assignments) { - return static_cast(this)->_insert_value_list._insert_values.emplace_back(vendor::insert_value_t{assignments}...); + return static_cast(this)->_insert_value_list()._insert_values.emplace_back(vendor::insert_value_t{assignments}...); } template @@ -203,9 +213,8 @@ namespace sqlpp struct no_insert_value_list_t { - using _is_noop = std::true_type; - using _provided_tables = ::sqlpp::detail::type_set<>; - using _required_tables = ::sqlpp::detail::type_set<>; + using _traits = make_traits; + using _recursive_traits = make_recursive_traits<>; template struct _methods_t diff --git a/include/sqlpp11/vendor/single_table.h b/include/sqlpp11/vendor/single_table.h index 583c6562..ddf55c72 100644 --- a/include/sqlpp11/vendor/single_table.h +++ b/include/sqlpp11/vendor/single_table.h @@ -38,12 +38,11 @@ namespace sqlpp template struct single_table_t { - using _is_single_table = std::true_type; - using _required_tables = typename Table::_required_tables; - using _provided_tables = typename Table::_provided_tables; + using _traits = make_traits; + using _recursive_traits = make_recursive_traits
; static_assert(is_table_t
::value, "argument has to be a table"); - static_assert(_required_tables::size::value == 0, "table depends on another table"); + static_assert(required_tables_of
::size::value == 0, "table depends on another table"); single_table_t(Table table): _table(table) @@ -55,13 +54,33 @@ namespace sqlpp single_table_t& operator=(single_table_t&&) = default; ~single_table_t() = default; + template + struct _methods_t + { + }; + Table _table; }; struct no_single_table_t { - using _provided_tables = detail::type_set<>; - using _required_tables = ::sqlpp::detail::type_set<>; + using _traits = make_traits; + using _recursive_traits = make_recursive_traits<>; + + template + struct _methods_t + { + using _database_t = typename Policies::_database_t; + template + using _new_statement_t = typename Policies::template _new_statement_t; + + template + auto into(Args... args) + -> _new_statement_t> + { + return { *static_cast(this), single_table_t{args...} }; + } + }; }; // Interpreters diff --git a/include/sqlpp11/vendor/where.h b/include/sqlpp11/vendor/where.h index 9c77059f..eef81374 100644 --- a/include/sqlpp11/vendor/where.h +++ b/include/sqlpp11/vendor/where.h @@ -77,7 +77,7 @@ namespace sqlpp { static_assert(_is_dynamic::value, "add_where can only be called for dynamic_where"); static_assert(is_expression_t::value, "invalid expression argument in add_where()"); - static_assert(TableCheckRequired::value or Policies::template _no_unknown_tables::value, "expression uses tables unknown to this statement in add_where()"); + static_assert(not TableCheckRequired::value or Policies::template _no_unknown_tables::value, "expression uses tables unknown to this statement in add_where()"); using ok = ::sqlpp::detail::all_t<_is_dynamic::value, is_expression_t::value>; diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 98f12e6e..9de5e4e2 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -7,12 +7,12 @@ macro (build_and_run arg) endmacro () #build_and_run(InterpretTest) -#build_and_run(InsertTest) +build_and_run(InsertTest) #build_and_run(RemoveTest) #build_and_run(UpdateTest) #build_and_run(SelectTest) -build_and_run(SelectTypeTest) -build_and_run(FunctionTest) +#build_and_run(SelectTypeTest) +#build_and_run(FunctionTest) #build_and_run(PreparedTest) find_package(PythonInterp REQUIRED) From 2a215905fd24ab22a094a72387bfdc3fd4d0e8ec Mon Sep 17 00:00:00 2001 From: rbock Date: Fri, 23 May 2014 20:36:13 +0200 Subject: [PATCH 14/16] Migrated remove to being variadic --- include/sqlpp11/basic_expression_operators.h | 7 +- include/sqlpp11/insert.h | 21 +++- include/sqlpp11/remove.h | 124 ++++++++++--------- include/sqlpp11/vendor/expression_fwd.h | 7 ++ include/sqlpp11/vendor/noop.h | 2 + include/sqlpp11/vendor/single_table.h | 8 ++ include/sqlpp11/vendor/using.h | 17 ++- tests/CMakeLists.txt | 4 +- 8 files changed, 111 insertions(+), 79 deletions(-) diff --git a/include/sqlpp11/basic_expression_operators.h b/include/sqlpp11/basic_expression_operators.h index 9e97a044..e306542d 100644 --- a/include/sqlpp11/basic_expression_operators.h +++ b/include/sqlpp11/basic_expression_operators.h @@ -32,16 +32,11 @@ #include #include #include +#include #include namespace sqlpp { - - namespace detail - { - struct boolean; - } - // basic operators template class IsCorrectValueType> struct basic_expression_operators diff --git a/include/sqlpp11/insert.h b/include/sqlpp11/insert.h index 78e5d0f9..b1141ae8 100644 --- a/include/sqlpp11/insert.h +++ b/include/sqlpp11/insert.h @@ -104,16 +104,14 @@ namespace sqlpp using _is_dynamic = typename std::conditional::value, std::false_type, std::true_type>::type; - using _parameter_tuple_t = std::tuple; using _parameter_list_t = typename make_parameter_list_t::type; - // Constructors - insert_t() + constexpr insert_t() {} - template - insert_t(Statement statement, T term): + template + insert_t(Statement statement, Term term): Policies(detail::pick_arg(statement, term))... {} @@ -181,6 +179,12 @@ namespace sqlpp vendor::no_single_table_t, vendor::no_insert_value_list_t>; + constexpr auto insert() + -> blank_insert_t + { + return { blank_insert_t() }; + } + template constexpr auto insert_into(Table table) -> decltype(blank_insert_t().into(table)) @@ -188,6 +192,13 @@ namespace sqlpp return { blank_insert_t().into(table) }; } + template + constexpr auto dynamic_insert(const Database&) + -> decltype(blank_insert_t()) + { + return { blank_insert_t() }; + } + template constexpr auto dynamic_insert_into(const Database&, Table table) -> decltype(blank_insert_t().into(table)) diff --git a/include/sqlpp11/remove.h b/include/sqlpp11/remove.h index ed12718f..77349668 100644 --- a/include/sqlpp11/remove.h +++ b/include/sqlpp11/remove.h @@ -31,88 +31,90 @@ #include #include #include +#warning: need to use another table provider, since delete can be used with several tables #include #include #include #include #include -#include + +#include +#include namespace sqlpp { - template + template struct remove_t; namespace detail { - template + template struct remove_policies_t { using _database_t = Db; - using _table_t = Table; - using _using_t = Using; - using _extra_tables_t = ExtraTables; - using _where_t = Where; - using _statement_t = remove_t; + using _statement_t = remove_t; - struct _methods_t: - public _using_t::template _methods_t, - public _extra_tables_t::template _methods_t, - public _where_t::template _methods_t + struct _methods_t: public Policies::template _methods_t... {}; - template + template struct _policies_update_t { + static_assert(detail::is_element_of>::value, "policies update for non-policy class detected"); using type = remove_t...>; }; template - using _new_statement_t = typename _policies_update_t::type; + using _new_statement_t = typename _policies_update_t::type; - using _known_tables = detail::make_joined_set_t; + using _all_required_tables = detail::make_joined_set_t...>; + using _all_provided_tables = detail::make_joined_set_t...>; + using _all_extra_tables = detail::make_joined_set_t...>; + + using _known_tables = detail::make_joined_set_t<_all_provided_tables, _all_extra_tables>; template - using _no_unknown_tables = detail::is_subset_of; + using _no_unknown_tables = detail::is_subset_of, _known_tables>; + + // The tables not covered by the from. + using _required_tables = detail::make_difference_set_t< + _all_required_tables, + _all_provided_tables // Hint: extra_tables are not used here because they are just a helper for dynamic .add_*() + >; + + using _traits = make_traits; // FIXME + + struct _recursive_traits + { + using _parameters = std::tuple<>; // FIXME + using _required_tables = _required_tables; + using _provided_tables = detail::type_set<>; + using _extra_tables = detail::type_set<>; + }; }; } // REMOVE - template + template struct remove_t: + public Policies..., public detail::remove_policies_t::_methods_t { using _policies_t = typename detail::remove_policies_t; using _database_t = typename _policies_t::_database_t; - using _table_t = typename _policies_t::_table_t; - using _using_t = typename _policies_t::_using_t; - using _extra_tables_t = typename _policies_t::_extra_tables_t; - using _where_t = typename _policies_t::_where_t; using _is_dynamic = typename std::conditional::value, std::false_type, std::true_type>::type; - using _parameter_tuple_t = std::tuple; using _parameter_list_t = typename make_parameter_list_t::type; // Constructors - remove_t() + constexpr remove_t() {} - template - remove_t(Statement s, T t): - _table(detail::arg_selector<_table_t>::_(s._table, t)), - _using(detail::arg_selector<_using_t>::_(s._using, t)), - _where(detail::arg_selector<_where_t>::_(s._where, t)) + template + remove_t(Statement statement, Term term): + Policies(detail::pick_arg(statement, term))... {} remove_t(const remove_t&) = default; @@ -132,18 +134,15 @@ namespace sqlpp return _parameter_list_t::size::value; } - template - struct is_table_subset_of_table - { - static constexpr bool value = ::sqlpp::detail::is_subset_of::value; - }; - void _check_consistency() const { +#warning reactivate checks +#if 0 static_assert(is_where_t<_where_t>::value, "cannot run update without having a where condition, use .where(true) to update all rows"); // FIXME: Read more details about what is allowed and what not in SQL DELETE static_assert(is_table_subset_of_table<_where_t>::value, "where requires additional tables"); +#endif } template @@ -163,10 +162,6 @@ namespace sqlpp return {{}, db.prepare_remove(*this)}; } - - _table_t _table; - _using_t _using; - _where_t _where; }; namespace vendor @@ -179,31 +174,46 @@ namespace sqlpp static Context& _(const T& t, Context& context) { context << "DELETE FROM "; - serialize(t._table, context); - serialize(t._using, context); - serialize(t._where, context); + using swallow = int[]; + (void) swallow{(serialize(static_cast(t), context), 0)...}; return context; } }; } - template - using make_remove_t = typename detail::remove_policies_t::_statement_t; + template + using blank_remove_t = remove_t; + + constexpr auto remove() + -> blank_remove_t + { + return { blank_remove_t() }; + } template constexpr auto remove_from(Table table) - -> make_remove_t> + -> decltype(blank_remove_t().from(table)) { - return { make_remove_t(), vendor::single_table_t{table} }; + return { blank_remove_t().from(table) }; + } + + template + constexpr auto dynamic_remove(const Database&) + -> decltype(blank_remove_t()) + { + return { blank_remove_t() }; } template constexpr auto dynamic_remove_from(const Database&, Table table) - -> make_remove_t> + -> decltype(blank_remove_t().from(table)) { - return { make_remove_t(), vendor::single_table_t{table} }; + return { blank_remove_t().from(table) }; } - } #endif diff --git a/include/sqlpp11/vendor/expression_fwd.h b/include/sqlpp11/vendor/expression_fwd.h index 374a4265..796596e5 100644 --- a/include/sqlpp11/vendor/expression_fwd.h +++ b/include/sqlpp11/vendor/expression_fwd.h @@ -29,6 +29,13 @@ namespace sqlpp { + namespace detail + { + struct boolean; + struct integral; + struct floating_point; + } + namespace vendor { namespace op diff --git a/include/sqlpp11/vendor/noop.h b/include/sqlpp11/vendor/noop.h index 1a7bcfe5..05df9dd9 100644 --- a/include/sqlpp11/vendor/noop.h +++ b/include/sqlpp11/vendor/noop.h @@ -28,6 +28,8 @@ #define SQLPP_NOOP_H #include +#include +#include namespace sqlpp { diff --git a/include/sqlpp11/vendor/single_table.h b/include/sqlpp11/vendor/single_table.h index ddf55c72..57dc7fc0 100644 --- a/include/sqlpp11/vendor/single_table.h +++ b/include/sqlpp11/vendor/single_table.h @@ -80,6 +80,14 @@ namespace sqlpp { return { *static_cast(this), single_table_t{args...} }; } + +#warning: remove can operate on several tables at once, so it should not use single_table anyway + template + auto from(Args... args) + -> _new_statement_t> + { + return { *static_cast(this), single_table_t{args...} }; + } }; }; diff --git a/include/sqlpp11/vendor/using.h b/include/sqlpp11/vendor/using.h index f9094408..7a7d7ccf 100644 --- a/include/sqlpp11/vendor/using.h +++ b/include/sqlpp11/vendor/using.h @@ -41,9 +41,10 @@ namespace sqlpp template struct using_t { - using _is_using = std::true_type; + using _traits = make_traits; + using _recursive_traits = make_recursive_traits; + using _is_dynamic = typename std::conditional::value, std::false_type, std::true_type>::type; - using _parameter_tuple_t = std::tuple; static_assert(_is_dynamic::value or sizeof...(Tables), "at least one table argument required in using()"); @@ -51,8 +52,7 @@ namespace sqlpp static_assert(::sqlpp::detail::all_t::value...>::value, "at least one argument is not an table in using()"); - using _provided_tables = detail::type_set<>; - using _required_tables = ::sqlpp::detail::make_joined_set_t; + using_t& _using() { return *this; } using_t(Tables... tables): _tables(tables...) @@ -82,7 +82,7 @@ namespace sqlpp template void _add_using_impl(Table table, const std::true_type&) { - return static_cast(this)->_using._dynamic_tables.emplace_back(table); + return static_cast(this)->_using()._dynamic_tables.emplace_back(table); } template @@ -90,15 +90,14 @@ namespace sqlpp }; - _parameter_tuple_t _tables; + std::tuple _tables; vendor::interpretable_list_t _dynamic_tables; }; struct no_using_t { - using _is_noop = std::true_type; - using _provided_tables = detail::type_set<>; - using _required_tables = ::sqlpp::detail::type_set<>; + using _traits = make_traits; + using _recursive_traits = make_recursive_traits<>; template struct _methods_t diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 9de5e4e2..d7fcb902 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -7,8 +7,8 @@ macro (build_and_run arg) endmacro () #build_and_run(InterpretTest) -build_and_run(InsertTest) -#build_and_run(RemoveTest) +#build_and_run(InsertTest) +build_and_run(RemoveTest) #build_and_run(UpdateTest) #build_and_run(SelectTest) #build_and_run(SelectTypeTest) From c13d514e95d6af816c0b83c7fad446f7d7b5ecdd Mon Sep 17 00:00:00 2001 From: rbock Date: Fri, 23 May 2014 21:42:27 +0200 Subject: [PATCH 15/16] Adjusted update to be variadic --- include/sqlpp11/update.h | 108 +++++++++++++------------- include/sqlpp11/vendor/assignment.h | 4 +- include/sqlpp11/vendor/single_table.h | 2 + include/sqlpp11/vendor/update_list.h | 18 +++-- tests/CMakeLists.txt | 4 +- 5 files changed, 69 insertions(+), 67 deletions(-) diff --git a/include/sqlpp11/update.h b/include/sqlpp11/update.h index 5865651a..1368d6a4 100644 --- a/include/sqlpp11/update.h +++ b/include/sqlpp11/update.h @@ -35,82 +35,84 @@ #include #include #include -#include + +#include +#include namespace sqlpp { - template + template struct update_t; namespace detail { - template + template struct update_policies_t { using _database_t = Db; - using _table_t = Table; - using _update_list_t = UpdateList; - using _where_t = Where; - using _statement_t = update_t; + using _statement_t = update_t; - struct _methods_t: - public _update_list_t::template _methods_t, - public _where_t::template _methods_t + struct _methods_t: public Policies::template _methods_t... {}; - template + template struct _policies_update_t { + static_assert(detail::is_element_of>::value, "policies update for non-policy class detected"); using type = update_t...>; }; template - using _new_statement_t = typename _policies_update_t::type; + using _new_statement_t = typename _policies_update_t::type; - using _known_tables = detail::make_joined_set_t; + using _all_required_tables = detail::make_joined_set_t...>; + using _all_provided_tables = detail::make_joined_set_t...>; + using _all_extra_tables = detail::make_joined_set_t...>; + + using _known_tables = detail::make_joined_set_t<_all_provided_tables, _all_extra_tables>; template - using _no_unknown_tables = detail::is_subset_of; + using _no_unknown_tables = detail::is_subset_of, _known_tables>; + // The tables not covered by the from. + using _required_tables = detail::make_difference_set_t< + _all_required_tables, + _all_provided_tables // Hint: extra_tables are not used here because they are just a helper for dynamic .add_*() + >; + + using _traits = make_traits; // FIXME + + struct _recursive_traits + { + using _parameters = std::tuple<>; // FIXME + using _required_tables = _required_tables; + using _provided_tables = detail::type_set<>; + using _extra_tables = detail::type_set<>; + }; }; } - template + // UPDATE + template struct update_t: + public Policies..., public detail::update_policies_t::_methods_t { using _policies_t = typename detail::update_policies_t; using _database_t = typename _policies_t::_database_t; - using _table_t = typename _policies_t::_table_t; - using _update_list_t = typename _policies_t::_update_list_t; - using _where_t = typename _policies_t::_where_t; using _is_dynamic = typename std::conditional::value, std::false_type, std::true_type>::type; - using _parameter_tuple_t = std::tuple; using _parameter_list_t = typename make_parameter_list_t::type; - static_assert(::sqlpp::detail::is_superset_of::value, "updated columns do not match the table"); - static_assert(::sqlpp::detail::is_superset_of::value, "where condition does not match updated table"); - // Constructors - update_t() + constexpr update_t() {} - template - update_t(Statement s, T t): - _table(detail::arg_selector<_table_t>::_(s._table, t)), - _update_list(detail::arg_selector<_update_list_t>::_(s._update_list, t)), - _where(detail::arg_selector<_where_t>::_(s._where, t)) + template + update_t(Statement statement, Term term): + Policies(detail::pick_arg(statement, term))... {} update_t(const update_t&) = default; @@ -130,18 +132,15 @@ namespace sqlpp return _parameter_list_t::size::value; } - template - struct is_table_subset_of_table - { - static constexpr bool value = ::sqlpp::detail::is_subset_of::value; - }; - void _check_consistency() const { +#warning reactivate tests + /* static_assert(is_where_t<_where_t>::value, "cannot run update without having a where condition, use .where(true) to update all rows"); static_assert(is_table_subset_of_table<_update_list_t>::value, "updates require additional tables"); static_assert(is_table_subset_of_table<_where_t>::value, "where requires additional tables"); + */ } template @@ -161,10 +160,6 @@ namespace sqlpp return {{}, db.prepare_update(*this)}; } - - _table_t _table; - _update_list_t _update_list; - _where_t _where; }; namespace vendor @@ -177,31 +172,32 @@ namespace sqlpp static Context& _(const T& t, Context& context) { context << "UPDATE "; - serialize(t._table, context); - serialize(t._update_list, context); - serialize(t._where, context); + using swallow = int[]; + (void) swallow{(serialize(static_cast(t), context), 0)...}; return context; } }; } - template - using make_update_t = typename detail::update_policies_t::_statement_t; + template + using blank_update_t = update_t; template constexpr auto update(Table table) - -> make_update_t> + -> decltype(blank_update_t().from(table)) { - return { update_t(), vendor::single_table_t{table} }; + return { blank_update_t().from(table) }; } template constexpr auto dynamic_update(const Database&, Table table) - -> make_update_t> + -> decltype(blank_update_t().from(table)) { - return { update_t(), vendor::single_table_t{table} }; + return { blank_update_t().from(table) }; } - } #endif diff --git a/include/sqlpp11/vendor/assignment.h b/include/sqlpp11/vendor/assignment.h index 1899a393..e74a6da5 100644 --- a/include/sqlpp11/vendor/assignment.h +++ b/include/sqlpp11/vendor/assignment.h @@ -59,7 +59,7 @@ namespace sqlpp template bool is_trivial(const T& t) { - return is_trivial_t>::_(t); + return is_trivial_t::_(t); } template @@ -96,7 +96,7 @@ namespace sqlpp static Context& _(const T& t, Context& context) { if ((trivial_value_is_null_t::value - and is_trivial_t>::_(t._rhs)) + and is_trivial(t._rhs)) or (std::is_same::value)) { serialize(simple_column(t._lhs), context); diff --git a/include/sqlpp11/vendor/single_table.h b/include/sqlpp11/vendor/single_table.h index 57dc7fc0..cb4bbfbf 100644 --- a/include/sqlpp11/vendor/single_table.h +++ b/include/sqlpp11/vendor/single_table.h @@ -28,6 +28,8 @@ #define SQLPP_VENDOR_SINGLE_TABLE_H #include +#include +#include #include namespace sqlpp diff --git a/include/sqlpp11/vendor/update_list.h b/include/sqlpp11/vendor/update_list.h index 2034452a..a4755658 100644 --- a/include/sqlpp11/vendor/update_list.h +++ b/include/sqlpp11/vendor/update_list.h @@ -40,9 +40,9 @@ namespace sqlpp template struct update_list_t { - using _is_update_list = std::true_type; + using _traits = make_traits; + using _recursive_traits = make_recursive_traits; using _is_dynamic = typename std::conditional::value, std::false_type, std::true_type>::type; - using _parameter_tuple_t = std::tuple; static_assert(_is_dynamic::value or sizeof...(Assignments), "at least one assignment expression required in set()"); @@ -52,11 +52,16 @@ namespace sqlpp static_assert(::sqlpp::detail::none_t::value...>::value, "at least one assignment is prohibited by its column definition in set()"); +#warning reactivate tests + /* using _column_table_set = typename ::sqlpp::detail::make_joined_set::type; using _value_table_set = typename ::sqlpp::detail::make_joined_set::type; using _table_set = typename ::sqlpp::detail::make_joined_set<_column_table_set, _value_table_set>::type; static_assert(sizeof...(Assignments) ? (_column_table_set::size::value == 1) : true, "set() contains assignments for tables from several columns"); static_assert(::sqlpp::detail::is_subset_of<_value_table_set, _column_table_set>::value, "set() contains values from foreign tables"); + */ + + update_list_t& _update_list() { return *this; } update_list_t(Assignments... assignments): _assignments(assignments...) @@ -97,7 +102,7 @@ namespace sqlpp template void _add_set_impl(Assignment assignment, const std::true_type&) { - return static_cast(this)->_update_list._dynamic_assignments.emplace_back(assignment); + return static_cast(this)->_update_list()._dynamic_assignments.emplace_back(assignment); } template @@ -105,15 +110,14 @@ namespace sqlpp }; - _parameter_tuple_t _assignments; + std::tuple _assignments; typename vendor::interpretable_list_t _dynamic_assignments; }; struct no_update_list_t { - using _is_noop = std::true_type; - using _provided_tables = detail::type_set<>; - using _required_tables = ::sqlpp::detail::type_set<>; + using _traits = make_traits; + using _recursive_traits = make_recursive_traits<>; template struct _methods_t diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index d7fcb902..280fe484 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -8,8 +8,8 @@ endmacro () #build_and_run(InterpretTest) #build_and_run(InsertTest) -build_and_run(RemoveTest) -#build_and_run(UpdateTest) +#build_and_run(RemoveTest) +build_and_run(UpdateTest) #build_and_run(SelectTest) #build_and_run(SelectTypeTest) #build_and_run(FunctionTest) From d11f529bd8ef9801394dd9dcadc33c24b644d469 Mon Sep 17 00:00:00 2001 From: rbock Date: Mon, 26 May 2014 07:42:59 +0200 Subject: [PATCH 16/16] Minor cleanup. --- include/sqlpp11/remove.h | 1 - include/sqlpp11/select.h | 1 - 2 files changed, 2 deletions(-) diff --git a/include/sqlpp11/remove.h b/include/sqlpp11/remove.h index 77349668..2204212b 100644 --- a/include/sqlpp11/remove.h +++ b/include/sqlpp11/remove.h @@ -52,7 +52,6 @@ namespace sqlpp struct remove_policies_t { using _database_t = Db; - using _statement_t = remove_t; struct _methods_t: public Policies::template _methods_t... diff --git a/include/sqlpp11/select.h b/include/sqlpp11/select.h index 6292e21c..defdb5ac 100644 --- a/include/sqlpp11/select.h +++ b/include/sqlpp11/select.h @@ -56,7 +56,6 @@ namespace sqlpp struct select_t; #warning STEPS: -#warning do the same with insert, update and remove #warning deal with different return types in the connector (select could be a single value, update could be a range of rows) namespace detail {