From 8caea01d0aa7c4410cd7fde39ba27243b09ca15f Mon Sep 17 00:00:00 2001 From: Roland Bock Date: Sat, 24 Aug 2024 20:00:16 +0200 Subject: [PATCH] Reorganized join and added a first set of serialize tests --- docs/DifferencesToVersion-1.0.md | 4 + include/sqlpp11/core/basic/enable_join.h | 7 +- include/sqlpp11/core/basic/join.h | 196 +++++++++++++------- include/sqlpp11/core/basic/join_fwd.h | 94 ++++++++++ include/sqlpp11/core/basic/join_types.h | 70 ------- include/sqlpp11/core/basic/on.h | 80 -------- include/sqlpp11/core/basic/pre_join.h | 213 ---------------------- include/sqlpp11/core/to_sql_string.h | 2 +- tests/core/serialize/CMakeLists.txt | 1 + tests/core/serialize/basic/CMakeLists.txt | 33 ++++ tests/core/serialize/basic/join.cpp | 70 +++++++ tests/core/types/basic/CMakeLists.txt | 2 +- tests/core/types/basic/join.cpp | 1 + 13 files changed, 341 insertions(+), 432 deletions(-) create mode 100644 include/sqlpp11/core/basic/join_fwd.h delete mode 100644 include/sqlpp11/core/basic/join_types.h delete mode 100644 include/sqlpp11/core/basic/on.h delete mode 100644 include/sqlpp11/core/basic/pre_join.h create mode 100644 tests/core/serialize/basic/CMakeLists.txt create mode 100644 tests/core/serialize/basic/join.cpp diff --git a/docs/DifferencesToVersion-1.0.md b/docs/DifferencesToVersion-1.0.md index 968d5d2b..cb4a0fbf 100644 --- a/docs/DifferencesToVersion-1.0.md +++ b/docs/DifferencesToVersion-1.0.md @@ -37,6 +37,10 @@ They must not be mixed in a select. If group_by is specified in the select, then all columns have to be aggregate expressions. +# Join +unconditional joins are cross joins. The "unconditional" function is dropped. +Added join tables (other than the left-most) can be dynamic. + # Dynamic queries We don't always have a completely fixed structure for our queries. For instance, there might columns that we only want to select under certain circumstances. In version 1.0, this was handled by dynamic queries. Now we introduce conditional query parts that may or may not be used at runtime: diff --git a/include/sqlpp11/core/basic/enable_join.h b/include/sqlpp11/core/basic/enable_join.h index 17755358..6bbf4410 100644 --- a/include/sqlpp11/core/basic/enable_join.h +++ b/include/sqlpp11/core/basic/enable_join.h @@ -27,7 +27,7 @@ */ #include -#include +#include namespace sqlpp { @@ -64,10 +64,11 @@ namespace sqlpp return ::sqlpp::right_outer_join(this->derived(), t); } +#warning: There is no full_outer_join in mysql? template - auto outer_join(T t) const -> decltype(::sqlpp::outer_join(this->derived(), t)) + auto full_outer_join(T t) const -> decltype(::sqlpp::full_outer_join(this->derived(), t)) { - return ::sqlpp::outer_join(this->derived(), t); + return ::sqlpp::full_outer_join(this->derived(), t); } template diff --git a/include/sqlpp11/core/basic/join.h b/include/sqlpp11/core/basic/join.h index f1f57bf4..e7e7b31b 100644 --- a/include/sqlpp11/core/basic/join.h +++ b/include/sqlpp11/core/basic/join.h @@ -1,7 +1,7 @@ #pragma once /* - * Copyright (c) 2013, Roland Bock + * Copyright (c) 2024, Roland Bock * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, @@ -26,79 +26,147 @@ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#include -#include -#include +#include +#include namespace sqlpp { - template - struct join_t + // Join representation including condition + template + struct join_t : enable_join> { - using _traits = make_traits; - using _nodes = detail::type_vector; - using _can_be_null = std::false_type; - using _provided_tables = provided_tables_of_t; - using _required_tables = detail::make_difference_set_t, _provided_tables>; - - template - auto join(T t) const -> decltype(::sqlpp::join(*this, t)) + join_t(Lhs lhs, Rhs rhs, Condition condition) + : _lhs(std::move(lhs)), _rhs(std::move(rhs)), _condition(std::move(condition)) { - return ::sqlpp::join(*this, t); } - template - auto inner_join(T t) const -> decltype(::sqlpp::inner_join(*this, t)) - { - return ::sqlpp::inner_join(*this, t); - } + join_t(const join_t&) = default; + join_t(join_t&&) = default; + join_t& operator=(const join_t&) = default; + join_t& operator=(join_t&&) = default; + ~join_t() = default; - template - auto left_outer_join(T t) const -> decltype(::sqlpp::left_outer_join(*this, t)) - { - return ::sqlpp::left_outer_join(*this, t); - } - - template - auto right_outer_join(T t) const -> decltype(::sqlpp::right_outer_join(*this, t)) - { - return ::sqlpp::right_outer_join(*this, t); - } - - template - auto outer_join(T t) const -> decltype(::sqlpp::outer_join(*this, t)) - { - return ::sqlpp::outer_join(*this, t); - } - - template - auto cross_join(T t) const -> decltype(::sqlpp::cross_join(*this, t)) - { - return ::sqlpp::cross_join(*this, t); - } - - PreJoin _pre_join; - On _on; + Lhs _lhs; + Rhs _rhs; + Condition _condition; }; - 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{}; - - template - auto to_sql_string(Context& context, const join_t& t) -> std::string + template + struct nodes_of> { - return to_sql_string(context, t._pre_join) + to_sql_string(context, t._on); + using type = sqlpp::detail::type_vector; + }; + + template + struct provided_outer_tables_of> + { + using type = typename std::conditional< + std::is_same::value, + sqlpp::detail::type_set, + typename std::conditional< + std::is_same::value, + sqlpp::detail::type_set, + typename std::conditional::value, + detail::make_joined_set_t, provided_tables_of_t>, + detail::type_set<>>::type>::type>::type; + }; + + template + struct is_table> : public std::true_type + { + }; + + template + auto to_sql_string(Context& context, const join_t& t) -> std::string + { + static_assert(not std::is_same::value, ""); + return to_sql_string(context, t._lhs) + JoinType::_name + to_sql_string(context, t._rhs) + " ON " + + to_sql_string(context, t._condition); } + + template + auto to_sql_string(Context& context, const join_t, Condition>& t) -> std::string + { + static_assert(not std::is_same::value, ""); + if (t._rhs._condition) + { + return to_sql_string(context, t._lhs) + JoinType::_name + to_sql_string(context, t._rhs) + " ON " + + to_sql_string(context, t._condition); + } + return to_sql_string(context, t._lhs); + } + + template + auto to_sql_string(Context& context, const join_t& t) -> std::string + { + return to_sql_string(context, t._lhs) + cross_join_t::_name + to_sql_string(context, t._rhs); + } + + template + auto to_sql_string(Context& context, const join_t, unconditional_t>& t) -> std::string + { + if (t._rhs._condition) + { + return to_sql_string(context, t._lhs) + cross_join_t::_name + to_sql_string(context, t._rhs); + } + return to_sql_string(context, t._lhs); + } + +#warning: Verify that the Expr does not require tables other than Lhs, Rhs + //and detail::make_joined_set_t, provided_tables_of_t>::is_superset_of::value + template + using check_on_args = sqlpp::enable_if_t::value>; + + template + struct pre_join_t + { + template > + auto on(Expr expr) const -> join_t + { + return {_lhs, _rhs, std::move(expr)}; + } + + Lhs _lhs; + Rhs _rhs; + }; + + // Note: See sqlpp11/core/basic/join_fwd.h for forward declarations including check_join_args. + + template */> + auto join(Lhs lhs, Rhs rhs) -> pre_join_t + { +#warning: What is the point of from_table? rename to make_table_ref? + return {from_table(std::move(lhs)), from_table(std::move(rhs))}; + } + + template */> + auto inner_join(Lhs lhs, Rhs rhs) -> pre_join_t + { + return {from_table(std::move(lhs)), from_table(std::move(rhs))}; + } + + template */> + auto left_outer_join(Lhs lhs, Rhs rhs) -> pre_join_t + { + return {from_table(std::move(lhs)), from_table(std::move(rhs))}; + } + + template */> + auto right_outer_join(Lhs lhs, Rhs rhs) -> pre_join_t + { + return {from_table(std::move(lhs)), from_table(std::move(rhs))}; + } + + template */> + auto full_outer_join(Lhs lhs, Rhs rhs) -> pre_join_t + { + return {from_table(std::move(lhs)), from_table(std::move(rhs))}; + } + + template */> + auto cross_join(Lhs lhs, Rhs rhs) -> join_t + { + return {from_table(std::move(lhs)), from_table(std::move(rhs)), {}}; + } + } // namespace sqlpp diff --git a/include/sqlpp11/core/basic/join_fwd.h b/include/sqlpp11/core/basic/join_fwd.h new file mode 100644 index 00000000..180cdf8b --- /dev/null +++ b/include/sqlpp11/core/basic/join_fwd.h @@ -0,0 +1,94 @@ +#pragma once + +/* + * 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 +#include +#include +#include +#include + +namespace sqlpp +{ + // Join types. + struct cross_join_t + { + static constexpr const char* _name = " CROSS JOIN "; + }; + + struct inner_join_t + { + static constexpr const char* _name = " INNER JOIN "; + }; + + struct left_outer_join_t + { + static constexpr const char* _name = " LEFT OUTER JOIN "; + }; + + struct right_outer_join_t + { + static constexpr const char* _name = " RIGHT OUTER JOIN "; + }; + + struct full_outer_join_t + { + static constexpr const char* _name = " FULL OUTER JOIN "; + }; + + template + struct join_t; + + template + struct pre_join_t; + + template + using check_join_args = + sqlpp::enable_if_t::value and is_table>::value and + required_tables_of_t::size::value == 0 and required_tables_of_t::size::value == 0 and + detail::is_disjunct_from>, + detail::make_name_of_set_t>>::value>; + + template > + auto join(Lhs lhs, Rhs rhs) -> pre_join_t; + + template > + auto inner_join(Lhs lhs, Rhs rhs) -> pre_join_t; + + template > + auto left_outer_join(Lhs lhs, Rhs rhs) -> pre_join_t; + + template > + auto right_outer_join(Lhs lhs, Rhs rhs) -> pre_join_t; + + template > + auto full_outer_join(Lhs lhs, Rhs rhs) -> pre_join_t; + + template > + auto cross_join(Lhs lhs, Rhs rhs) -> join_t; + +} // namespace sqlpp diff --git a/include/sqlpp11/core/basic/join_types.h b/include/sqlpp11/core/basic/join_types.h deleted file mode 100644 index 95e7448d..00000000 --- a/include/sqlpp11/core/basic/join_types.h +++ /dev/null @@ -1,70 +0,0 @@ -#pragma once - -/* - * 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. - */ - -#include - -namespace sqlpp -{ - struct inner_join_t - { - template - using _provided_outer_tables = - 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_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_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_t>; - - static constexpr const char* _name = " RIGHT OUTER"; - }; - struct cross_join_t - { - template - using _provided_outer_tables = - detail::make_joined_set_t, provided_outer_tables_of_t>; - - static constexpr const char* _name = " CROSS"; - }; -} // namespace sqlpp diff --git a/include/sqlpp11/core/basic/on.h b/include/sqlpp11/core/basic/on.h deleted file mode 100644 index ed5f7d5c..00000000 --- a/include/sqlpp11/core/basic/on.h +++ /dev/null @@ -1,80 +0,0 @@ -#pragma once - -/* - * 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. - */ - -#include -#include -#include - -namespace sqlpp -{ - SQLPP_PORTABLE_STATIC_ASSERT(assert_on_is_expression_t, "argument is not an expression in on()"); - SQLPP_PORTABLE_STATIC_ASSERT(assert_on_is_boolean_expression_t, "argument is not a boolean expression in on()"); - - template - struct check_on - { - using type = static_combined_check_t::value, assert_on_is_boolean_expression_t>>; - }; - - template - using check_on_t = typename check_on::type; - - template - struct on_t - { - using _traits = make_traits; - using _nodes = detail::type_vector; - - Expression _expression; - }; - - template <> - struct on_t - { - using _traits = make_traits; - 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 - { - return {}; - } - - template - auto to_sql_string(Context& context, const on_t& t) -> std::string - { - return " ON " + to_sql_string(context, t._expression); - } -} // namespace sqlpp diff --git a/include/sqlpp11/core/basic/pre_join.h b/include/sqlpp11/core/basic/pre_join.h deleted file mode 100644 index 3c9b1493..00000000 --- a/include/sqlpp11/core/basic/pre_join.h +++ /dev/null @@ -1,213 +0,0 @@ -#pragma once - -/* - * Copyright (c) 2013, 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 -#include -#include -#include -#include - -namespace sqlpp -{ - SQLPP_PORTABLE_STATIC_ASSERT(assert_pre_join_lhs_table_t, "lhs argument of join() has to be a table or a join"); - SQLPP_PORTABLE_STATIC_ASSERT(assert_pre_join_rhs_table_t, "rhs argument of join() has to be a table"); - SQLPP_PORTABLE_STATIC_ASSERT(assert_pre_join_rhs_no_join_t, "rhs argument of join() must not be a join"); - SQLPP_PORTABLE_STATIC_ASSERT(assert_pre_join_unique_names_t, "joined table names have to be unique"); - - template - struct check_pre_join - { - using type = static_combined_check_t< - 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>, -#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>>; - }; - - template - using check_pre_join_t = typename check_pre_join::type; - - SQLPP_PORTABLE_STATIC_ASSERT(assert_join_consist_of_pre_join_and_on_t, - "join has to consist of a pre_join and a join condition"); - SQLPP_PORTABLE_STATIC_ASSERT(assert_join_no_table_dependencies_t, "joined tables must not depend on other tables"); - SQLPP_PORTABLE_STATIC_ASSERT(assert_join_on_no_foreign_table_dependencies_t, - "on() condition must not depend on other tables"); - - template - struct check_join - { - using type = static_combined_check_t< - 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_t>::value, - assert_join_on_no_foreign_table_dependencies_t>>; - }; - - template - using check_join_t = typename check_join::type; - - template - struct check_join_on - { - using type = static_combined_check_t, check_join_t>>; - }; - - template - using check_join_on_t = typename check_join_on::type; - - template - struct join_t; - - template - struct pre_join_t - { - using _traits = make_traits; - using _nodes = detail::type_vector; - using _can_be_null = std::false_type; - using _provided_outer_tables = typename JoinType::template _provided_outer_tables; - -#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> - { - return {*this, {}}; - } - - template - auto on(Expr expr) const -> typename std::conditional::value, - join_t>, - check_join_on_t>::type - { - using Check = check_join_on_t; - - return on_impl(Check{}, expr); - } - - private: - template - auto on_impl(Check, const Expr&) const -> inconsistent; - - template - auto on_impl(consistent_t /*unused*/, const Expr& expr) const -> join_t> - { - return {*this, {expr}}; - } - - public: - Lhs _lhs; - 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 - { - return to_sql_string(context, t._lhs) + JoinType::_name + " JOIN " + to_sql_string(context, t._rhs); - } - - namespace detail - { - template - auto join_impl(Check, Lhs lhs, Rhs rhs) -> inconsistent; - - template - 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)); - } // namespace detail - - template - auto join(Lhs lhs, Rhs rhs) -> decltype(detail::join_impl(lhs, rhs)) - { - return {from_table(lhs), from_table(rhs)}; - } - - template - auto inner_join(Lhs lhs, Rhs rhs) -> decltype(detail::join_impl(lhs, rhs)) - { - return {from_table(lhs), from_table(rhs)}; - } - - template - auto left_outer_join(Lhs lhs, Rhs rhs) -> decltype(detail::join_impl(lhs, rhs)) - { - return {from_table(lhs), from_table(rhs)}; - } - - template - auto right_outer_join(Lhs lhs, Rhs rhs) -> decltype(detail::join_impl(lhs, rhs)) - { - check_pre_join_t::verify(); - - return {from_table(lhs), from_table(rhs)}; - } - - template - auto outer_join(Lhs lhs, Rhs rhs) -> decltype(detail::join_impl(lhs, rhs)) - { - return {from_table(lhs), from_table(rhs)}; - } - - namespace detail - { - template - auto cross_join_impl(Check, Lhs lhs, Rhs rhs) -> inconsistent; - - template - auto cross_join_impl(consistent_t, Lhs lhs, Rhs rhs) - -> join_t, on_t>; - - template - auto cross_join_impl(Lhs lhs, Rhs rhs) - -> decltype(cross_join_impl(check_pre_join_t, from_table_t>{}, lhs, rhs)); - } // namespace detail - - template - auto cross_join(Lhs lhs, Rhs rhs) -> decltype(detail::cross_join_impl(lhs, rhs)) - { - return {pre_join_t, from_table_t>{from_table(lhs), from_table(rhs)}, {}}; - } -} // namespace sqlpp diff --git a/include/sqlpp11/core/to_sql_string.h b/include/sqlpp11/core/to_sql_string.h index 1e403a18..0fab6144 100644 --- a/include/sqlpp11/core/to_sql_string.h +++ b/include/sqlpp11/core/to_sql_string.h @@ -40,7 +40,7 @@ namespace sqlpp { template - auto to_sql_string(Context& context, ...) -> std::string + auto to_sql_string(Context& , ...) -> std::string { static_assert(wrong_t::value, "Missing specialization"); return {}; diff --git a/tests/core/serialize/CMakeLists.txt b/tests/core/serialize/CMakeLists.txt index aee6be6e..a2543289 100644 --- a/tests/core/serialize/CMakeLists.txt +++ b/tests/core/serialize/CMakeLists.txt @@ -54,6 +54,7 @@ foreach(test_file IN LISTS test_files) endforeach() add_subdirectory(aggregate_function) +add_subdirectory(basic) add_subdirectory(clause) add_subdirectory(operator) add_subdirectory(query) diff --git a/tests/core/serialize/basic/CMakeLists.txt b/tests/core/serialize/basic/CMakeLists.txt new file mode 100644 index 00000000..bd8a0894 --- /dev/null +++ b/tests/core/serialize/basic/CMakeLists.txt @@ -0,0 +1,33 @@ +# 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(create_test name) + set(target sqlpp11_core_serialize_basic_${name}) + add_executable(${target} ${name}.cpp) + target_link_libraries(${target} PRIVATE sqlpp11::sqlpp11 sqlpp11_testing) + add_test(NAME ${target} COMMAND ${target}) +endfunction() + +create_test(join) + diff --git a/tests/core/serialize/basic/join.cpp b/tests/core/serialize/basic/join.cpp new file mode 100644 index 00000000..d4e4c378 --- /dev/null +++ b/tests/core/serialize/basic/join.cpp @@ -0,0 +1,70 @@ +/* + * 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 "../compare.h" +#include + +SQLPP_ALIAS_PROVIDER(v); + +int main(int, char* []) +{ + const auto val = sqlpp::value(17); + const auto expr = sqlpp::value(17) + 4; + + const auto foo = test::TabFoo{}; + const auto bar = test::TabBar{}; + + // Join with two tables + SQLPP_COMPARE(foo.join(bar).on(foo.id == bar.id), "tab_foo INNER JOIN tab_bar ON tab_foo.id = tab_bar.id"); + SQLPP_COMPARE(foo.inner_join(bar).on(foo.id == bar.id), "tab_foo INNER JOIN tab_bar ON tab_foo.id = tab_bar.id"); + SQLPP_COMPARE(foo.left_outer_join(bar).on(foo.id == bar.id), "tab_foo LEFT OUTER JOIN tab_bar ON tab_foo.id = tab_bar.id"); + SQLPP_COMPARE(foo.right_outer_join(bar).on(foo.id == bar.id), "tab_foo RIGHT OUTER JOIN tab_bar ON tab_foo.id = tab_bar.id"); + SQLPP_COMPARE(foo.full_outer_join(bar).on(foo.id == bar.id), "tab_foo FULL OUTER JOIN tab_bar ON tab_foo.id = tab_bar.id"); + + SQLPP_COMPARE(foo.cross_join(bar), "tab_foo CROSS JOIN tab_bar"); + + // Join with dynamic table + SQLPP_COMPARE(foo.join(dynamic(true, bar)).on(foo.id == bar.id), "tab_foo INNER JOIN tab_bar ON tab_foo.id = tab_bar.id"); + SQLPP_COMPARE(foo.inner_join(dynamic(true, bar)).on(foo.id == bar.id), "tab_foo INNER JOIN tab_bar ON tab_foo.id = tab_bar.id"); + SQLPP_COMPARE(foo.left_outer_join(dynamic(true, bar)).on(foo.id == bar.id), "tab_foo LEFT OUTER JOIN tab_bar ON tab_foo.id = tab_bar.id"); + SQLPP_COMPARE(foo.right_outer_join(dynamic(true, bar)).on(foo.id == bar.id), "tab_foo RIGHT OUTER JOIN tab_bar ON tab_foo.id = tab_bar.id"); + SQLPP_COMPARE(foo.full_outer_join(dynamic(true, bar)).on(foo.id == bar.id), "tab_foo FULL OUTER JOIN tab_bar ON tab_foo.id = tab_bar.id"); + + SQLPP_COMPARE(foo.cross_join(dynamic(true, bar)), "tab_foo CROSS JOIN tab_bar"); + + SQLPP_COMPARE(foo.join(dynamic(false, bar)).on(foo.id == bar.id), "tab_foo"); + SQLPP_COMPARE(foo.inner_join(dynamic(false, bar)).on(foo.id == bar.id), "tab_foo"); + SQLPP_COMPARE(foo.left_outer_join(dynamic(false, bar)).on(foo.id == bar.id), "tab_foo"); + SQLPP_COMPARE(foo.right_outer_join(dynamic(false, bar)).on(foo.id == bar.id), "tab_foo"); + SQLPP_COMPARE(foo.full_outer_join(dynamic(false, bar)).on(foo.id == bar.id), "tab_foo"); + + SQLPP_COMPARE(foo.cross_join(dynamic(false, bar)), "tab_foo"); + +#warning: Need to add tests with 3 tables + +#warning: Need to add tests with CTEs + return 0; +} diff --git a/tests/core/types/basic/CMakeLists.txt b/tests/core/types/basic/CMakeLists.txt index 71f0a3c2..20dc2537 100644 --- a/tests/core/types/basic/CMakeLists.txt +++ b/tests/core/types/basic/CMakeLists.txt @@ -23,7 +23,7 @@ # SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. function(test_compile name) - set(target sqlpp11_core_types_clause_${name}) + set(target sqlpp11_core_types_basic_${name}) add_executable(${target} ${name}.cpp) target_link_libraries(${target} PRIVATE sqlpp11::sqlpp11 sqlpp11_testing) endfunction() diff --git a/tests/core/types/basic/join.cpp b/tests/core/types/basic/join.cpp index b1e10f07..970fb306 100644 --- a/tests/core/types/basic/join.cpp +++ b/tests/core/types/basic/join.cpp @@ -69,6 +69,7 @@ void test_group_by() } +#warning: Need to add tests all join types! #warning: Need to add tests with 3 tables #warning: Need to add tests with CTEs