From 34a8f348214cf7b5e76bb69c6616d014f65901c4 Mon Sep 17 00:00:00 2001 From: Roland Bock Date: Fri, 30 Jul 2021 21:05:36 +0200 Subject: [PATCH] Remove multi_column. While a nice feature in theory, this was extremely rarely used and added quite a bit of complexity to the code. --- docs/Select.md | 24 +-- include/sqlpp11/all_of.h | 7 - include/sqlpp11/detail/field_index_sequence.h | 85 ---------- include/sqlpp11/field_spec.h | 29 +--- include/sqlpp11/multi_column.h | 145 ------------------ include/sqlpp11/result_row.h | 72 ++------- include/sqlpp11/select_column_list.h | 5 +- include/sqlpp11/type_traits.h | 1 - tests/Interpret.cpp | 5 - tests/Select.cpp | 15 -- tests/SelectType.cpp | 28 ---- 11 files changed, 15 insertions(+), 401 deletions(-) delete mode 100644 include/sqlpp11/detail/field_index_sequence.h delete mode 100644 include/sqlpp11/multi_column.h diff --git a/docs/Select.md b/docs/Select.md index 2dd82854..ac2e24ba 100644 --- a/docs/Select.md +++ b/docs/Select.md @@ -75,7 +75,7 @@ Using aliases also comes in handy when you join tables and have several columns select(foo.id, bar.id); // compile error ``` -One of the columns needs an alias (or you use multi-columns as shown below). +One of the columns needs an alias. ```C++ SQLPP_ALIAS_PROVIDER(barId); select(foo.id, bar.id.as(barId)); @@ -129,28 +129,6 @@ Statements like `SELECT * from foo` is used pretty often in SQL. sqlpp11 offers ```C++ select(all_of(foo)); ``` -### Multi-Columns -Sometimes, when you join tables `foo`, `bar` and `baz`, you might want to select several columns of the same name. As shown above, you could use aliases to resolve name clashes. Another option is to group columns together in multi-columns. Here is an example: - -``` -SQLPP_ALIAS_PROVIDER_GENERATOR(left); -for(const auto& row : db( - select(foo.id, - multi_column(left, foo.id, foo.name, foo.hasFun), - multi_column(foo, all_of(foo))) - .from(foo))) -{ - std::cerr << "row.left.id: " << row.left.id - << ", row.left.name: " << row.left.name - << ", row.left.hasFun: " << row.left.hasFun << std::endl; - std::cerr << "row.foo.id: " << row.foo.id - << ", row.foo.name: " << row.foo.name - << ", row.foo.hasFun: " << row.foo.hasFun << std::endl; -}; -``` -That might not be the most creative example in the world, but it shows how to use multi-columns. The first argument is an alias provider. In the cases shown above, the alias provider `left` is created using the `SQLPP_ALIAS_PROVIDER` macro. Tables also have a name and can provide an alias. - -In the result rows, the multi-columns are accessed by their name. Their members in turn are accessed by their names. ## From The `from` method expects one argument. The following subsections expand on the types of valid arguments: diff --git a/include/sqlpp11/all_of.h b/include/sqlpp11/all_of.h index 0a23a168..3172ef8d 100644 --- a/include/sqlpp11/all_of.h +++ b/include/sqlpp11/all_of.h @@ -29,7 +29,6 @@ #include #include -#include #include namespace sqlpp @@ -38,12 +37,6 @@ namespace sqlpp struct all_of_t { using _column_tuple_t = typename Table::_column_tuple_t; - - template - detail::copy_tuple_args_t as(const AliasProvider& alias) - { - return multi_column(_column_tuple_t{}).as(alias); - } }; template diff --git a/include/sqlpp11/detail/field_index_sequence.h b/include/sqlpp11/detail/field_index_sequence.h deleted file mode 100644 index 9045e63c..00000000 --- a/include/sqlpp11/detail/field_index_sequence.h +++ /dev/null @@ -1,85 +0,0 @@ -/* - * Copyright (c) 2013-2015, 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 SQLPP11_DETAIL_FIELD_INDEX_SEQUENCE_H -#define SQLPP11_DETAIL_FIELD_INDEX_SEQUENCE_H - -#include -#include - -namespace sqlpp -{ - namespace detail - { - template - struct field_index_sequence - { - static constexpr std::size_t _next_index = NextIndex; - }; - - template - struct make_field_index_sequence_impl - { - static_assert(wrong_t::value, "invalid field index sequence arguments"); - }; - - template - struct make_field_index_sequence_impl, - field_spec_t, - Rest...> - { - using type = typename make_field_index_sequence_impl, - Rest...>::type; - }; - - template - struct make_field_index_sequence_impl, - multi_field_spec_t, - Rest...> - { - using type = typename make_field_index_sequence_impl< - field_index_sequence::value, Ints..., NextIndex>, - Rest...>::type; - }; - - template - struct make_field_index_sequence_impl> - { - using type = field_index_sequence; - }; - - template - using make_field_index_sequence = - typename make_field_index_sequence_impl, Fields...>::type; - } // namespace detail -} // namespace sqlpp - -#endif diff --git a/include/sqlpp11/field_spec.h b/include/sqlpp11/field_spec.h index dbc8ff26..a62beeba 100644 --- a/include/sqlpp11/field_spec.h +++ b/include/sqlpp11/field_spec.h @@ -27,7 +27,7 @@ #ifndef SQLPP11_FIELD_SPEC_H #define SQLPP11_FIELD_SPEC_H -#include +#include namespace sqlpp { @@ -42,18 +42,6 @@ namespace sqlpp using _alias_t = NameType; }; - template - struct multi_field_spec_t - { - static_assert(wrong_t::value, - "multi_field_spec_t needs to be specialized with a tuple"); - }; - - template - struct multi_field_spec_t> - { - }; - template struct is_field_compatible { @@ -76,14 +64,6 @@ namespace sqlpp // NULL if the right hand side allows it }; - template - struct is_field_compatible>, - multi_field_spec_t>, - typename std::enable_if::type> - { - static constexpr auto value = logic::all_t::value...>::value; - }; - namespace detail { template @@ -98,13 +78,6 @@ namespace sqlpp value_type_of, logic::any_t<_can_be_null, _depends_on_outer_table>::value>; }; - - template - struct make_field_spec_impl> - { - using type = - multi_field_spec_t::type...>>; - }; } // namespace detail template diff --git a/include/sqlpp11/multi_column.h b/include/sqlpp11/multi_column.h deleted file mode 100644 index 67886749..00000000 --- a/include/sqlpp11/multi_column.h +++ /dev/null @@ -1,145 +0,0 @@ -/* - * Copyright (c) 2013-2015, 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 SQLPP11_MULTI_COLUMN_H -#define SQLPP11_MULTI_COLUMN_H - -#include -#include - -#include - -namespace sqlpp -{ - struct no_value_t; - - template - struct multi_column_alias_t; - - template - struct multi_column_t - { - using _traits = make_traits; - using _nodes = detail::type_vector; - - static_assert(logic::all_t::value...>::value, - "multi_column parameters need to be named expressions"); - - multi_column_t(std::tuple columns) : _columns(columns) - { - } - - multi_column_t(Columns... columns) : _columns(columns...) - { - } - - multi_column_t(const multi_column_t&) = default; - multi_column_t(multi_column_t&&) = default; - multi_column_t& operator=(const multi_column_t&) = default; - multi_column_t& operator=(multi_column_t&&) = default; - ~multi_column_t() = default; - - template - multi_column_alias_t as(const AliasProvider& /*unused*/) - { - return {*this}; - } - - std::tuple _columns; - }; - - template - struct multi_column_alias_t - { - using _traits = make_traits; - using _nodes = detail::type_vector; - - static_assert(logic::all_t::value...>::value, - "multi_column parameters need to be named expressions"); - - using _alias_t = typename AliasProvider::_alias_t; - - multi_column_alias_t(multi_column_t multi_column) : _columns(multi_column._columns) - { - } - - multi_column_alias_t(std::tuple columns) : _columns(columns) - { - } - - multi_column_alias_t(Columns... columns) : _columns(columns...) - { - } - - multi_column_alias_t(const multi_column_alias_t&) = default; - multi_column_alias_t(multi_column_alias_t&&) = default; - multi_column_alias_t& operator=(const multi_column_alias_t&) = default; - multi_column_alias_t& operator=(multi_column_alias_t&&) = default; - ~multi_column_alias_t() = default; - - std::tuple _columns; - }; - - template - struct serializer_t> - { - using _serialize_check = serialize_check_of; - using T = multi_column_t; - - static void _(const T& /*unused*/, Context& /*unused*/) - { - static_assert(wrong_t::value, "multi_column must be used with an alias"); - } - }; - - template - struct serializer_t> - { - using _serialize_check = serialize_check_of; - using T = multi_column_alias_t; - - static Context& _(const T& t, Context& context) - { - interpret_tuple(t._columns, ',', context); - return context; - } - }; - - namespace detail - { - template - using make_multi_column_t = - copy_tuple_args_t()...))>; - } // namespace detail - - template - auto multi_column(Columns... columns) -> detail::make_multi_column_t - { - return detail::make_multi_column_t(std::tuple_cat(detail::as_column_tuple::_(columns)...)); - } -} // namespace sqlpp - -#endif diff --git a/include/sqlpp11/result_row.h b/include/sqlpp11/result_row.h index a4568f1f..de0eab8a 100644 --- a/include/sqlpp11/result_row.h +++ b/include/sqlpp11/result_row.h @@ -30,7 +30,7 @@ #include #include #include -#include +#include #include #include #include @@ -85,54 +85,8 @@ namespace sqlpp } }; - template - struct result_field>> - : public member_t, FieldSpecs...>> - { - using _multi_field = - member_t, FieldSpecs...>>; - - result_field() = default; - - void _validate() - { - _multi_field::operator()()._validate(); - } - - void _invalidate() - { - _multi_field::operator()()._invalidate(); - } - - template - void _bind(Target& target) - { - _multi_field::operator()()._bind(target); - } - - template - void _post_bind(Target& target) - { - _multi_field::operator()()._post_bind(target); - } - - template - void _apply(Callable& callable) const - { - _multi_field::operator()()._apply(callable); - } - - template - void _apply(const Callable& callable) const - { - _multi_field::operator()()._apply(callable); - } - }; - - template - struct result_row_impl, FieldSpecs...> + template + struct result_row_impl, FieldSpecs...> : public result_field... { result_row_impl() = default; @@ -181,10 +135,9 @@ namespace sqlpp template struct result_row_t - : public detail::result_row_impl, FieldSpecs...> + : public detail::result_row_impl, FieldSpecs...> { - using _field_index_sequence = detail::make_field_index_sequence<0, FieldSpecs...>; - using _impl = detail::result_row_impl; + using _impl = detail::result_row_impl, FieldSpecs...>; bool _is_valid{false}; result_row_t() : _impl() @@ -224,7 +177,7 @@ namespace sqlpp static constexpr size_t static_size() { - return _field_index_sequence::_next_index; + return sizeof...(FieldSpecs); } template @@ -268,10 +221,9 @@ namespace sqlpp template struct dynamic_result_row_t - : public detail::result_row_impl, FieldSpecs...> + : public detail::result_row_impl, FieldSpecs...> { - using _field_index_sequence = detail::make_field_index_sequence<0, FieldSpecs...>; - using _impl = detail::result_row_impl; + using _impl = detail::result_row_impl, FieldSpecs...>; using _field_type = result_field_t>; bool _is_valid{false}; @@ -336,7 +288,7 @@ namespace sqlpp { _impl::_bind(target); - std::size_t index = _field_index_sequence::_next_index; + std::size_t index = sizeof...(FieldSpecs); for (const auto& field_name : _dynamic_field_names) { _dynamic_fields.at(field_name)._bind(target, index); @@ -349,7 +301,7 @@ namespace sqlpp { _impl::_post_bind(target); - std::size_t index = _field_index_sequence::_next_index; + std::size_t index = sizeof...(FieldSpecs); for (const auto& field_name : _dynamic_field_names) { _dynamic_fields.at(field_name)._post_bind(target, index); @@ -362,7 +314,7 @@ namespace sqlpp { _impl::_apply(callable); - std::size_t index = _field_index_sequence::_next_index; + std::size_t index = sizeof...(FieldSpecs); for (const auto& field_name : _dynamic_field_names) { _dynamic_fields.at(field_name)._apply(callable); @@ -375,7 +327,7 @@ namespace sqlpp { _impl::_apply(callable); - std::size_t index = _field_index_sequence::_next_index; + std::size_t index = sizeof...(FieldSpecs); for (const auto& field_name : _dynamic_field_names) { _dynamic_fields.at(field_name)._apply(callable); diff --git a/include/sqlpp11/select_column_list.h b/include/sqlpp11/select_column_list.h index 05c28698..641396d5 100644 --- a/include/sqlpp11/select_column_list.h +++ b/include/sqlpp11/select_column_list.h @@ -251,8 +251,6 @@ namespace sqlpp consistency_check_t<_statement_t>{}; static_assert(_statement_t::_can_be_used_as_table(), "statement cannot be used as table, e.g. due to missing tables"); - static_assert(logic::none_t::value...>::value, - "cannot use multi-columns in sub selects"); return _table_t(_get_statement()).as(aliasProvider); } @@ -306,8 +304,7 @@ namespace sqlpp struct check_selected_columns { using type = static_combined_check_t< - static_check_t::value or is_multi_column_t::value)...>::value, - assert_selected_colums_are_selectable_t>>; + static_check_t::value...>::value, assert_selected_colums_are_selectable_t>>; }; template using check_selected_columns_t = typename check_selected_columns::type; diff --git a/include/sqlpp11/type_traits.h b/include/sqlpp11/type_traits.h index bcf10e10..b71bf347 100644 --- a/include/sqlpp11/type_traits.h +++ b/include/sqlpp11/type_traits.h @@ -206,7 +206,6 @@ namespace sqlpp SQLPP_VALUE_TRAIT_GENERATOR(is_offset) SQLPP_VALUE_TRAIT_GENERATOR(is_using_) SQLPP_VALUE_TRAIT_GENERATOR(is_column_list) - SQLPP_VALUE_TRAIT_GENERATOR(is_multi_column) SQLPP_VALUE_TRAIT_GENERATOR(is_value_list) SQLPP_VALUE_TRAIT_GENERATOR(is_assignment) SQLPP_VALUE_TRAIT_GENERATOR(is_update_list) diff --git a/tests/Interpret.cpp b/tests/Interpret.cpp index 148498e1..c5153947 100644 --- a/tests/Interpret.cpp +++ b/tests/Interpret.cpp @@ -135,11 +135,6 @@ int Interpret(int, char* []) serialize(select(t.alpha).from(inner), printer).str(); } - // multi_column - serialize(multi_column(t.alpha, (t.beta + "cake").as(t.gamma)).as(t.alpha), printer).str(); - serialize(multi_column(all_of(t)).as(t), printer).str(); - serialize(all_of(t).as(t), printer).str(); - // dynamic select { auto s = dynamic_select(db).dynamic_flags().dynamic_columns().from(t); diff --git a/tests/Select.cpp b/tests/Select.cpp index cd11eaa7..79529c4f 100644 --- a/tests/Select.cpp +++ b/tests/Select.cpp @@ -92,21 +92,6 @@ int Select(int, char*[]) std::cout << a << ", " << b << std::endl; } - for (const auto& row : db(select(all_of(t).as(t)).from(t).unconditionally())) - { - int64_t a = row.tabBar.alpha; - const std::string b = row.tabBar.beta; - std::cout << a << ", " << b << std::endl; - } - - for (const auto& row : db(select(all_of(t).as(t), t.gamma).from(t).where(t.alpha > 7))) - { - int64_t a = row.tabBar.alpha; - const std::string b = row.tabBar.beta; - const bool g = row.gamma; - std::cout << a << ", " << b << ", " << g << std::endl; - } - for (const auto& row : db(select(all_of(t), t.gamma.as(t)).from(t).where(t.alpha > 7 and trim(t.beta) == "test").for_update())) { diff --git a/tests/SelectType.cpp b/tests/SelectType.cpp index e98febbb..e8add31d 100644 --- a/tests/SelectType.cpp +++ b/tests/SelectType.cpp @@ -330,34 +330,6 @@ int SelectType(int, char*[]) // static_assert(std::is_same::value, "t has to be expanded by select()"); } - // Test that all_of(tab) is expanded in multi_column - { - auto a = multi_column(all_of(t)).as(alias::a); - auto b = multi_column(t.alpha, t.beta, t.gamma, t.delta).as(alias::a); - static_assert(std::is_same::value, "all_of(t) has to be expanded by multi_column"); - } - - // Test that a multicolumn is not a value - { - auto m = multi_column(t.alpha, t.beta).as(alias::a); - static_assert(not sqlpp::is_expression_t::value, "a multi_column is not a value"); - } - - // Test result field indices - { - using Select = decltype(select(all_of(t), // index 0, 1, 2, 3 (alpha, beta, gamma, delta) - multi_column(all_of(t)).as(alias::left), // index 4 (including 4, 5, 6, 7) - multi_column(all_of(t)).as(alias::right), // index 8 (including 8, 9, 10, 11) - t.alpha.as(alias::a) // index 12 - ) - .from(t) - .unconditionally()); // next index is 13 - using ResultRow = typename Select::_result_methods_t