From 151af17bbc200be7fa82000c88ca1cb67c738175 Mon Sep 17 00:00:00 2001 From: Roland Bock Date: Fri, 23 Aug 2024 11:13:48 +0200 Subject: [PATCH] Added type tests for join and fixed a few things to make them compile --- include/sqlpp11/core/basic/column.h | 5 +- include/sqlpp11/core/basic/join.h | 16 ++++- include/sqlpp11/core/basic/join_types.h | 10 +-- include/sqlpp11/core/basic/on.h | 6 ++ include/sqlpp11/core/basic/pre_join.h | 33 ++++++---- include/sqlpp11/core/basic/table.h | 9 ++- include/sqlpp11/core/clause/from.h | 4 +- include/sqlpp11/core/query/dynamic.h | 10 +++ include/sqlpp11/core/query/statement.h | 4 +- include/sqlpp11/core/type_traits.h | 36 ++++++++++- tests/core/types/CMakeLists.txt | 6 +- tests/core/types/basic/CMakeLists.txt | 32 ++++++++++ tests/core/types/basic/join.cpp | 82 +++++++++++++++++++++++++ 13 files changed, 219 insertions(+), 34 deletions(-) create mode 100644 tests/core/types/basic/CMakeLists.txt create mode 100644 tests/core/types/basic/join.cpp diff --git a/include/sqlpp11/core/basic/column.h b/include/sqlpp11/core/basic/column.h index 6f9f2463..4e74fdba 100644 --- a/include/sqlpp11/core/basic/column.h +++ b/include/sqlpp11/core/basic/column.h @@ -104,10 +104,13 @@ namespace sqlpp { }; + template + struct table_t; + template struct required_tables_of> { - using type = detail::type_set; + using type = detail::type_set>; }; template diff --git a/include/sqlpp11/core/basic/join.h b/include/sqlpp11/core/basic/join.h index ca3d9905..f1f57bf4 100644 --- a/include/sqlpp11/core/basic/join.h +++ b/include/sqlpp11/core/basic/join.h @@ -1,7 +1,7 @@ #pragma once /* - * Copyright (c) 2013-2016, Roland Bock + * Copyright (c) 2013, Roland Bock * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, @@ -38,7 +38,7 @@ namespace sqlpp using _traits = make_traits; using _nodes = detail::type_vector; using _can_be_null = std::false_type; - using _provided_tables = provided_tables_of; + using _provided_tables = provided_tables_of_t; using _required_tables = detail::make_difference_set_t, _provided_tables>; template @@ -81,6 +81,18 @@ namespace sqlpp On _on; }; + template + struct nodes_of> + { + using type = sqlpp::detail::type_vector; + }; + + template + struct provided_outer_tables_of> + { + using type = provided_outer_tables_of_t; + }; + template struct is_table> : public std::true_type{}; diff --git a/include/sqlpp11/core/basic/join_types.h b/include/sqlpp11/core/basic/join_types.h index de984092..95e7448d 100644 --- a/include/sqlpp11/core/basic/join_types.h +++ b/include/sqlpp11/core/basic/join_types.h @@ -34,28 +34,28 @@ namespace sqlpp { template using _provided_outer_tables = - detail::make_joined_set_t, provided_outer_tables_of>; + detail::make_joined_set_t, provided_outer_tables_of_t>; static constexpr const char* _name = " INNER"; }; struct outer_join_t { template - using _provided_outer_tables = detail::make_joined_set_t, provided_tables_of>; + using _provided_outer_tables = detail::make_joined_set_t, provided_tables_of_t>; static constexpr const char* _name = " OUTER"; }; struct left_outer_join_t { template - using _provided_outer_tables = detail::make_joined_set_t, provided_tables_of>; + using _provided_outer_tables = detail::make_joined_set_t, provided_tables_of_t>; static constexpr const char* _name = " LEFT OUTER"; }; struct right_outer_join_t { template - using _provided_outer_tables = detail::make_joined_set_t, provided_outer_tables_of>; + using _provided_outer_tables = detail::make_joined_set_t, provided_outer_tables_of_t>; static constexpr const char* _name = " RIGHT OUTER"; }; @@ -63,7 +63,7 @@ namespace sqlpp { template using _provided_outer_tables = - detail::make_joined_set_t, provided_outer_tables_of>; + detail::make_joined_set_t, provided_outer_tables_of_t>; static constexpr const char* _name = " CROSS"; }; diff --git a/include/sqlpp11/core/basic/on.h b/include/sqlpp11/core/basic/on.h index dad05a16..ed5f7d5c 100644 --- a/include/sqlpp11/core/basic/on.h +++ b/include/sqlpp11/core/basic/on.h @@ -60,6 +60,12 @@ namespace sqlpp using _nodes = detail::type_vector<>; }; + template + struct nodes_of> + { + using type = sqlpp::detail::type_vector; + }; + template auto to_sql_string(Context& , const on_t&) -> std::string { diff --git a/include/sqlpp11/core/basic/pre_join.h b/include/sqlpp11/core/basic/pre_join.h index 0a635092..3c9b1493 100644 --- a/include/sqlpp11/core/basic/pre_join.h +++ b/include/sqlpp11/core/basic/pre_join.h @@ -1,7 +1,7 @@ #pragma once /* - * Copyright (c) 2013-2016, Roland Bock + * Copyright (c) 2013, Roland Bock * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, @@ -28,6 +28,7 @@ #include #include +#include #include #include @@ -45,8 +46,9 @@ namespace sqlpp static_check_t::value, assert_pre_join_lhs_table_t>, static_check_t::value, assert_pre_join_rhs_table_t>, static_check_t::value, assert_pre_join_rhs_no_join_t>, - static_check_t>, - detail::make_name_of_set_t>>::value, +#warning: Since rhs is a table, we could also just get a type vector here. + static_check_t>, + detail::make_name_of_set_t>>::value, assert_pre_join_unique_names_t>>; }; @@ -66,7 +68,7 @@ namespace sqlpp static_check_t::value, assert_join_consist_of_pre_join_and_on_t>, static_check_t::value, assert_join_consist_of_pre_join_and_on_t>, static_check_t::size::value == 0, assert_join_no_table_dependencies_t>, - static_check_t, provided_tables_of>::value, + static_check_t, provided_tables_of_t>::value, assert_join_on_no_foreign_table_dependencies_t>>; }; @@ -93,13 +95,7 @@ namespace sqlpp using _can_be_null = std::false_type; using _provided_outer_tables = typename JoinType::template _provided_outer_tables; - static_assert(is_table::value, "lhs argument for join() has to be a table or join"); - static_assert(is_table::value, "rhs argument for join() has to be a table"); - static_assert(not is_join_t::value, "rhs argument for join must not be a join"); - - static_assert(detail::is_disjunct_from, provided_tables_of>::value, - "joined tables must not be identical"); - +#warning: Do we really need this? static_assert(required_tables_of_t::size::value == 0, "joined tables must not depend on other tables"); auto unconditionally() -> join_t> @@ -132,6 +128,19 @@ namespace sqlpp Rhs _rhs; }; + template + struct nodes_of> + { + using type = sqlpp::detail::type_vector; + }; + + template + struct provided_outer_tables_of> + { + using type = typename JoinType::template _provided_outer_tables; + }; + + template auto to_sql_string(Context& context, const pre_join_t& t) -> std::string { @@ -147,7 +156,7 @@ namespace sqlpp auto join_impl(consistent_t, Lhs lhs, Rhs rhs) -> pre_join_t, from_table_t>; template - auto join_impl(Lhs lhs, Rhs rhs) -> decltype(join_impl(check_pre_join_t{}, lhs, rhs)); + auto join_impl(Lhs lhs, Rhs rhs) -> decltype(join_impl(check_pre_join_t>{}, lhs, rhs)); } // namespace detail template diff --git a/include/sqlpp11/core/basic/table.h b/include/sqlpp11/core/basic/table.h index 02f801a3..e4fb1179 100644 --- a/include/sqlpp11/core/basic/table.h +++ b/include/sqlpp11/core/basic/table.h @@ -41,9 +41,6 @@ namespace sqlpp { using _traits = make_traits; - using _nodes = detail::type_vector<>; - using _provided_tables = detail::type_set; - using _required_insert_columns = typename TableSpec::_required_insert_columns; #warning: Need to inherit? //using _column_tuple_t = std::tuple...>; @@ -66,6 +63,12 @@ namespace sqlpp template struct is_table>: public std::true_type {}; + template + struct provided_tables_of> + { + using type = sqlpp::detail::type_set>; + }; + template auto to_sql_string(Context& context, const table_t& /*unused*/) -> std::string { diff --git a/include/sqlpp11/core/clause/from.h b/include/sqlpp11/core/clause/from.h index d4732362..c3e5e0e2 100644 --- a/include/sqlpp11/core/clause/from.h +++ b/include/sqlpp11/core/clause/from.h @@ -85,8 +85,8 @@ namespace sqlpp static_check_t::value, assert_from_not_pre_join_t>, static_check_t::value, assert_from_table_t>, static_check_t::size::value == 0, assert_from_dependency_free_t>, - static_check_t::size::value == - detail::make_name_of_set_t>::size::value, + static_check_t::size::value == + detail::make_name_of_set_t>::size::value, assert_from_no_duplicates_t>>; }; diff --git a/include/sqlpp11/core/query/dynamic.h b/include/sqlpp11/core/query/dynamic.h index e56ad957..d7e34872 100644 --- a/include/sqlpp11/core/query/dynamic.h +++ b/include/sqlpp11/core/query/dynamic.h @@ -27,6 +27,7 @@ */ #include +#include #include #include #include @@ -115,4 +116,13 @@ namespace sqlpp { return {condition, std::move(t)}; } + + template + struct table_t; + + template + auto dynamic(bool condition, table_t t) -> dynamic_t> + { + return {condition, std::move(t)}; + } } // namespace sqlpp diff --git a/include/sqlpp11/core/query/statement.h b/include/sqlpp11/core/query/statement.h index e587308a..64e4fecc 100644 --- a/include/sqlpp11/core/query/statement.h +++ b/include/sqlpp11/core/query/statement.h @@ -78,8 +78,8 @@ namespace sqlpp using _all_required_ctes = detail::make_joined_set_t...>; using _all_provided_ctes = 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_provided_outer_tables = detail::make_joined_set_t...>; + using _all_provided_tables = detail::make_joined_set_t...>; + using _all_provided_outer_tables = detail::make_joined_set_t...>; using _all_provided_aggregates = detail::make_joined_set_t...>; template diff --git a/include/sqlpp11/core/type_traits.h b/include/sqlpp11/core/type_traits.h index a2d2cba3..0dc4e062 100644 --- a/include/sqlpp11/core/type_traits.h +++ b/include/sqlpp11/core/type_traits.h @@ -285,8 +285,6 @@ namespace sqlpp SQLPP_RECURSIVE_TRAIT_SET_GENERATOR(required_ctes) SQLPP_RECURSIVE_TRAIT_SET_GENERATOR(provided_ctes) - SQLPP_RECURSIVE_TRAIT_SET_GENERATOR(provided_tables) - SQLPP_RECURSIVE_TRAIT_SET_GENERATOR(provided_outer_tables) SQLPP_RECURSIVE_TRAIT_SET_GENERATOR(provided_aggregates) template @@ -325,6 +323,40 @@ namespace sqlpp static_assert(required_tables_of_t::size::value == 0, ""); + template + struct provided_tables_of + { + using type = typename provided_tables_of>::type; + }; + + template + struct provided_tables_of> + { + using type = detail::make_joined_set_t::type...>; + }; + + template + using provided_tables_of_t = typename provided_tables_of::type; + + static_assert(provided_tables_of_t::size::value == 0, ""); + + template + struct provided_outer_tables_of + { + using type = typename provided_outer_tables_of>::type; + }; + + template + struct provided_outer_tables_of> + { + using type = detail::make_joined_set_t::type...>; + }; + + template + using provided_outer_tables_of_t = typename provided_outer_tables_of::type; + + static_assert(provided_outer_tables_of_t::size::value == 0, ""); + template struct is_valid_operand { diff --git a/tests/core/types/CMakeLists.txt b/tests/core/types/CMakeLists.txt index 710119f2..1e8392f5 100644 --- a/tests/core/types/CMakeLists.txt +++ b/tests/core/types/CMakeLists.txt @@ -33,8 +33,4 @@ test_compile(result_row) test_compile(select_as) test_compile(value) -add_subdirectory(aggregate_function) -add_subdirectory(operator) -add_subdirectory(clause) -add_subdirectory(detail) -add_subdirectory(type_traits) +add_subdirectory(basic) diff --git a/tests/core/types/basic/CMakeLists.txt b/tests/core/types/basic/CMakeLists.txt new file mode 100644 index 00000000..71f0a3c2 --- /dev/null +++ b/tests/core/types/basic/CMakeLists.txt @@ -0,0 +1,32 @@ +# Copyright (c) 2024, 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. + +function(test_compile name) + set(target sqlpp11_core_types_clause_${name}) + add_executable(${target} ${name}.cpp) + target_link_libraries(${target} PRIVATE sqlpp11::sqlpp11 sqlpp11_testing) +endfunction() + +test_compile(join) + diff --git a/tests/core/types/basic/join.cpp b/tests/core/types/basic/join.cpp new file mode 100644 index 00000000..b1e10f07 --- /dev/null +++ b/tests/core/types/basic/join.cpp @@ -0,0 +1,82 @@ +/* + * Copyright (c) 2024, 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. + */ + +#include "Sample.h" +#include + +void test_group_by() +{ + auto v = sqlpp::value(17); + auto foo = test::TabFoo{}; + auto bar = test::TabBar{}; + + // Pre-join + static_assert(not sqlpp::is_table::value, ""); + + // Join + { + using J = decltype(foo.join(bar).on(foo.id == bar.id)); + static_assert(sqlpp::is_table::value, ""); + static_assert( + std::is_same, sqlpp::detail::type_set>::value, ""); + static_assert( + std::is_same, sqlpp::detail::type_set<>>::value, ""); +#warning: test the provided dynamic tables of? + } + + { + using J = decltype(foo.outer_join(bar).on(foo.id == bar.id)); + static_assert(sqlpp::is_table::value, ""); + static_assert( + std::is_same, sqlpp::detail::type_set>::value, ""); + static_assert( + std::is_same, sqlpp::detail::type_set>::value, ""); +#warning: test the provided dynamic tables of? + } + + // Join with dynamic table + { + using J = decltype(foo.join(dynamic(true, bar)).on(foo.id == bar.id)); + static_assert(sqlpp::is_table::value, ""); + static_assert( + std::is_same, sqlpp::detail::type_set>::value, ""); +#warning: OUTER is the wrong term. In a left-outer join, the *right* table is the one with optional rows. + static_assert( + std::is_same, sqlpp::detail::type_set<>>::value, ""); +#warning: test the provided dynamic tables of? + } + + +#warning: Need to add tests with 3 tables + +#warning: Need to add tests with CTEs +} + +int main() +{ + void test_group_by(); +} + +