diff --git a/docs/DifferencesToVersion-1.0.md b/docs/DifferencesToVersion-1.0.md index f43f2686..d3ea9a64 100644 --- a/docs/DifferencesToVersion-1.0.md +++ b/docs/DifferencesToVersion-1.0.md @@ -38,4 +38,27 @@ SQLPP_ALIAS_PROVIDER(max_price); } ``` +# 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: + +## Select optional columns +select(tab.id, dynamic(condition, tab.bigData)).from(tab).where(tab.id == 17); + +If `condition == true` then `bigData` will be selected, otherwise `NULL` will be selected. + +## Join optional table +select(tabA.id).from(tabA.cross_join(dynamic(condition, tabB))).where(tab.id == 17); + +If `condition == true` then the cross join will be part of the query, otherwise not. Obviously, that means that you need to make sure that query parts that rely on `tabB` in this example also depend on the same condition. + +## Optional AND operand +select(tab.id).from(tab).where(tab.id == 17 and dynamic(condition, tab.desert != "cheesecake")); + +If `condition == true`, then the dynamic part will evaluate to `tab.desert != "cheesecake")`. Otherwise it will be treated as `true` (and the AND expression will be collapsed). + +## Optional OR operand +select(tab.id).from(tab).where(tab.id == 17 or dynamic(condition, tab.desert != "cheesecake")); + +If `condition == true`, then the dynamic part will evaluate to `tab.desert != "cheesecake")`. Otherwise it will be treated as `false` (and the OR expression will be collapsed). + diff --git a/include/sqlpp11/auto_alias.h b/include/sqlpp11/auto_alias.h deleted file mode 100644 index 1d03b389..00000000 --- a/include/sqlpp11/auto_alias.h +++ /dev/null @@ -1,62 +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 -{ - template - struct has_auto_alias_t - { - static constexpr bool value = false; - }; - - template - struct has_auto_alias_t::value>::type> - { - static constexpr bool value = true; - }; - - namespace detail - { - template - struct auto_alias_impl - { - using type = T; - }; - - template - struct auto_alias_impl::value>::type> - { - using type = as_expression; - }; - } // namespace detail - - template - using auto_alias_t = typename detail::auto_alias_impl::type; -} // namespace sqlpp diff --git a/include/sqlpp11/column.h b/include/sqlpp11/column.h index 63fdab93..6babe59e 100644 --- a/include/sqlpp11/column.h +++ b/include/sqlpp11/column.h @@ -71,12 +71,6 @@ namespace sqlpp return _table{}; } -#warning: Let's do if_(condition, expression) -> if_t, which can be used exclusively in SELECT, AND, OR, JOIN - sqlpp::compat::optional if_(bool condition) const - { - return condition ? sqlpp::compat::make_optional(*this) : sqlpp::compat::nullopt; - } - template auto operator=(T value) const -> assign_expression { diff --git a/include/sqlpp11/detail/column_tuple_merge.h b/include/sqlpp11/detail/column_tuple_merge.h deleted file mode 100644 index e5fab06d..00000000 --- a/include/sqlpp11/detail/column_tuple_merge.h +++ /dev/null @@ -1,55 +0,0 @@ -#pragma once - -/* - * Copyright (c) 2021-2021, 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 - -namespace sqlpp -{ - namespace detail - { - template - std::tuple> as_column_tuple(T t) - { - return std::tuple>(auto_alias_t{t}); - } - - template - std::tuple...> as_column_tuple(std::tuple t) - { - return t; - } - - template - auto column_tuple_merge(Columns... columns) -> decltype(std::tuple_cat(as_column_tuple(columns)...)) - { - return std::tuple_cat(as_column_tuple(columns)...); - } - } -} // namespace sqlpp diff --git a/include/sqlpp11/dynamic.h b/include/sqlpp11/dynamic.h new file mode 100644 index 00000000..b17ee800 --- /dev/null +++ b/include/sqlpp11/dynamic.h @@ -0,0 +1,109 @@ +#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 + +namespace sqlpp +{ + template + struct dynamic_t + { + using _traits = make_traits, tag::is_multi_expression>; + using _nodes = detail::type_vector; + + dynamic_t(bool condition, Expr expr) : _condition(condition), _expr(expr) + { + } + + dynamic_t(const dynamic_t&) = default; + dynamic_t(dynamic_t&&) = default; + dynamic_t& operator=(const dynamic_t&) = default; + dynamic_t& operator=(dynamic_t&&) = default; + ~dynamic_t() = default; + + bool _condition; + Expr _expr; + }; + + // No value_type_of defined for dynamic_t, because it is to be used in very specific contexts in which _expr may be + // used depending on the value of _condition. + + template + struct remove_dynamic + { + using type = T; + }; + + template + struct remove_dynamic> + { + using type = Expr; + }; + + template + using remove_dynamic_t = typename remove_dynamic::type; + + template + struct dynamic_to_optional + { + using type = T; + }; + + template + struct dynamic_to_optional> + { + using type = force_optional_t; + }; + + template + using dynamic_to_optional_t = typename dynamic_to_optional::type; + + template + Context& serialize(const dynamic_t