From a51b6da3bdb90f031741dc82ea1a3f69b07501c5 Mon Sep 17 00:00:00 2001 From: MacDue <11597044+MacDue@users.noreply.github.com> Date: Sat, 15 Feb 2020 06:54:22 +0000 Subject: [PATCH] Minimal over() implementation for aggregate functions (#316) * Minimal over() implementation for aggregate functions * auto_alias support for over() * add missing typename * Test .over() serialization * Add missing return to test * Fix testing over auto alias Co-authored-by: Ben Maxwell <42680490+MaciumDue@users.noreply.github.com> --- .../sqlpp11/aggregate_function_operators.h | 42 +++++++++++ include/sqlpp11/aggregate_functions/avg.h | 3 +- include/sqlpp11/aggregate_functions/count.h | 5 +- include/sqlpp11/aggregate_functions/max.h | 6 +- include/sqlpp11/aggregate_functions/min.h | 6 +- include/sqlpp11/aggregate_functions/sum.h | 3 +- include/sqlpp11/over.h | 73 +++++++++++++++++++ test_serializer/CMakeLists.txt | 15 ++-- test_serializer/Over.cpp | 50 +++++++++++++ 9 files changed, 189 insertions(+), 14 deletions(-) create mode 100644 include/sqlpp11/aggregate_function_operators.h create mode 100644 include/sqlpp11/over.h create mode 100644 test_serializer/Over.cpp diff --git a/include/sqlpp11/aggregate_function_operators.h b/include/sqlpp11/aggregate_function_operators.h new file mode 100644 index 00000000..6e92ad4c --- /dev/null +++ b/include/sqlpp11/aggregate_function_operators.h @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2013-2020, Roland Bock, MacDue + * 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_AGGREGATE_FUNCTION_OPERATORS_H +#define SQLPP11_AGGREGATE_FUNCTION_OPERATORS_H + +namespace sqlpp +{ + template + struct aggregate_function_operators + { + over_t over() const + { + return {*static_cast(this)}; + } + }; +} // namespace sqlpp + +#endif + diff --git a/include/sqlpp11/aggregate_functions/avg.h b/include/sqlpp11/aggregate_functions/avg.h index a9df9e62..f34ac297 100644 --- a/include/sqlpp11/aggregate_functions/avg.h +++ b/include/sqlpp11/aggregate_functions/avg.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013-2016, Roland Bock + * Copyright (c) 2013-2020, Roland Bock, MacDue * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, @@ -56,6 +56,7 @@ namespace sqlpp template struct avg_t : public expression_operators, floating_point>, + public aggregate_function_operators>, public alias_operators> { using _traits = make_traits; diff --git a/include/sqlpp11/aggregate_functions/count.h b/include/sqlpp11/aggregate_functions/count.h index 79d96e52..91f7a830 100644 --- a/include/sqlpp11/aggregate_functions/count.h +++ b/include/sqlpp11/aggregate_functions/count.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013-2015, Roland Bock + * Copyright (c) 2013-2020, Roland Bock, MacDue * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, @@ -27,8 +27,10 @@ #ifndef SQLPP11_AGGREGATE_FUNCTIONS_COUNT_H #define SQLPP11_AGGREGATE_FUNCTIONS_COUNT_H +#include #include #include +#include #include namespace sqlpp @@ -57,6 +59,7 @@ namespace sqlpp template struct count_t : public expression_operators, integral>, + public aggregate_function_operators>, public alias_operators> { using _traits = make_traits; diff --git a/include/sqlpp11/aggregate_functions/max.h b/include/sqlpp11/aggregate_functions/max.h index 16faaa47..1c601809 100644 --- a/include/sqlpp11/aggregate_functions/max.h +++ b/include/sqlpp11/aggregate_functions/max.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013-2015, Roland Bock + * Copyright (c) 2013-2020, Roland Bock, MacDue * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, @@ -55,7 +55,9 @@ namespace sqlpp }; template - struct max_t : public expression_operators, value_type_of>, public alias_operators> + struct max_t : public expression_operators, value_type_of>, + public aggregate_function_operators>, + public alias_operators> { using _traits = make_traits, tag::is_expression, tag::is_selectable>; using _nodes = detail::type_vector; diff --git a/include/sqlpp11/aggregate_functions/min.h b/include/sqlpp11/aggregate_functions/min.h index 37604e03..54b663c8 100644 --- a/include/sqlpp11/aggregate_functions/min.h +++ b/include/sqlpp11/aggregate_functions/min.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013-2015, Roland Bock + * Copyright (c) 2013-2020, Roland Bock, MacDue * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, @@ -55,7 +55,9 @@ namespace sqlpp }; template - struct min_t : public expression_operators, value_type_of>, public alias_operators> + struct min_t : public expression_operators, value_type_of>, + public aggregate_function_operators>, + public alias_operators> { using _traits = make_traits, tag::is_expression, tag::is_selectable>; using _nodes = detail::type_vector; diff --git a/include/sqlpp11/aggregate_functions/sum.h b/include/sqlpp11/aggregate_functions/sum.h index 67428472..33396c28 100644 --- a/include/sqlpp11/aggregate_functions/sum.h +++ b/include/sqlpp11/aggregate_functions/sum.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013-2015, Roland Bock + * Copyright (c) 2013-2020, Roland Bock, MacDue * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, @@ -56,6 +56,7 @@ namespace sqlpp template struct sum_t : public expression_operators, value_type_of>, + public aggregate_function_operators>, public alias_operators> { using _traits = make_traits, tag::is_expression, tag::is_selectable>; diff --git a/include/sqlpp11/over.h b/include/sqlpp11/over.h new file mode 100644 index 00000000..6a598e1e --- /dev/null +++ b/include/sqlpp11/over.h @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2013-2020, Roland Bock, MacDue + * 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_OVER_H +#define SQLPP11_OVER_H + +#include +#include + +namespace sqlpp +{ + template + struct over_t : public expression_operators, integral>, + public alias_operators> + { + using _traits = make_traits; + using _nodes = detail::type_vector; + + using _auto_alias_t = typename AggregateExpr::_auto_alias_t; + + over_t(AggregateExpr aggregate_expression) + : _aggregate_expression(aggregate_expression) + { + } + + over_t(const over_t&) = default; + over_t(over_t&&) = default; + over_t& operator=(const over_t&) = default; + over_t& operator=(over_t&&) = default; + ~over_t() = default; + + AggregateExpr _aggregate_expression; + }; + + template + struct serializer_t> + { + using _serialize_check = serialize_check_of; + using T = over_t; + + static Context& _(const T& t, Context& context) + { + serialize_operand(t._aggregate_expression, context); + context << " OVER()"; + return context; + } + }; +} // namespace sqlpp + +#endif diff --git a/test_serializer/CMakeLists.txt b/test_serializer/CMakeLists.txt index 0db89df9..b17c83ef 100644 --- a/test_serializer/CMakeLists.txt +++ b/test_serializer/CMakeLists.txt @@ -27,12 +27,13 @@ set(test_serializer_names Blob CustomQuery DynamicWhere - ForUpdate - From - In - Insert - TableAlias - Where + ForUpdate + From + In + Insert + Over + TableAlias + Where ) create_test_sourcelist(test_serializer_sources test_serializer_main.cpp ${test_serializer_names}) @@ -45,7 +46,7 @@ if (SQLPP11_TESTS_CXX_STD) set_property(TARGET sqlpp11_test_serializer PROPERTY CXX_STANDARD_REQUIRED yes) set_property(TARGET sqlpp11_test_serializer PROPERTY CXX_EXTENSIONS no) endif() - + foreach(test_serializer IN LISTS test_serializer_names) add_test(NAME sqlpp11.test_serializer.${test_serializer} COMMAND sqlpp11_test_serializer ${test_serializer} diff --git a/test_serializer/Over.cpp b/test_serializer/Over.cpp new file mode 100644 index 00000000..c1afb69e --- /dev/null +++ b/test_serializer/Over.cpp @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2016-2020, Roland Bock, MacDue + * 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(dueutil) + +int Over(int, char* []) { + auto const foo = test::TabFoo{}; + + // no/auto alias (wrapped in select so alias is applied) + compare(__LINE__, select(avg(foo.omega).over()), "SELECT AVG(tab_foo.omega) OVER() AS avg_"); + compare(__LINE__, select(count(foo.omega).over()), "SELECT COUNT(tab_foo.omega) OVER() AS count_"); + compare(__LINE__, select(max(foo.omega).over()), "SELECT MAX(tab_foo.omega) OVER() AS max_"); + compare(__LINE__, select(min(foo.omega).over()), "SELECT MIN(tab_foo.omega) OVER() AS min_"); + compare(__LINE__, select(sum(foo.omega).over()), "SELECT SUM(tab_foo.omega) OVER() AS sum_"); + + // alias + compare(__LINE__, avg(foo.omega).over().as(dueutil), "AVG(tab_foo.omega) OVER() AS dueutil"); + compare(__LINE__, count(foo.omega).over().as(dueutil), "COUNT(tab_foo.omega) OVER() AS dueutil"); + compare(__LINE__, max(foo.omega).over().as(dueutil), "MAX(tab_foo.omega) OVER() AS dueutil"); + compare(__LINE__, min(foo.omega).over().as(dueutil), "MIN(tab_foo.omega) OVER() AS dueutil"); + compare(__LINE__, sum(foo.omega).over().as(dueutil), "SUM(tab_foo.omega) OVER() AS dueutil"); + + return 0; +}