diff --git a/include/sqlpp11/detail/float_safe_ostringstream.h b/include/sqlpp11/detail/float_safe_ostringstream.h new file mode 100644 index 00000000..05a0ea1f --- /dev/null +++ b/include/sqlpp11/detail/float_safe_ostringstream.h @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2023, 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_COLUMN_TUPLE_FLOAT_SAFE_OSTRINGSTREAM_H +#define SQLPP11_COLUMN_TUPLE_FLOAT_SAFE_OSTRINGSTREAM_H + +#include +#include +#include +#include + +#include + +namespace sqlpp +{ + namespace detail + { + template + struct float_safe_ostringstream_implementation + { + template + void operator()(std::ostringstream& os, U&& x) const + { + os << std::forward(x); + } + }; + + template + struct float_safe_ostringstream_implementation::value>> + { + template + void operator()(std::ostringstream& os, U&& x) const + { + auto const old_precision{os.precision(std::numeric_limits::max_digits10)}; + os << std::forward(x); + os.precision(old_precision); + } + }; + + struct float_safe_ostringstream : std::ostringstream + { + template + friend float_safe_ostringstream& operator<<(float_safe_ostringstream& os, T&& x) + { + float_safe_ostringstream_implementation::type>{}(os, x); + return os; + } + }; + } // namespace detail +} // namespace sqlpp + +#endif diff --git a/include/sqlpp11/mysql/connection.h b/include/sqlpp11/mysql/connection.h index 21280178..ada50374 100644 --- a/include/sqlpp11/mysql/connection.h +++ b/include/sqlpp11/mysql/connection.h @@ -28,6 +28,7 @@ #define SQLPP_MYSQL_CONNECTION_H #include +#include #include #include #include @@ -247,7 +248,7 @@ namespace sqlpp } const connection& _db; - std::stringstream _os; + sqlpp::detail::float_safe_ostringstream _os; }; std::integral_constant get_quote_left(const serializer_t&); diff --git a/include/sqlpp11/postgresql/connection.h b/include/sqlpp11/postgresql/connection.h index 93c7bd57..c73eb381 100644 --- a/include/sqlpp11/postgresql/connection.h +++ b/include/sqlpp11/postgresql/connection.h @@ -33,6 +33,7 @@ #include #include +#include #include #include #include @@ -125,7 +126,7 @@ namespace sqlpp } const connection& _db; - std::ostringstream _os; + sqlpp::detail::float_safe_ostringstream _os; size_t _count{1}; }; diff --git a/include/sqlpp11/postgresql/prepared_statement.h b/include/sqlpp11/postgresql/prepared_statement.h index 87a94cd5..e8bc4c70 100644 --- a/include/sqlpp11/postgresql/prepared_statement.h +++ b/include/sqlpp11/postgresql/prepared_statement.h @@ -32,7 +32,7 @@ #include #include #include - +#include #include namespace sqlpp @@ -127,9 +127,8 @@ namespace sqlpp _handle->nullValues[index] = is_null; if (!is_null) { - std::ostringstream out; - out.precision(std::numeric_limits::digits10); - out << std::fixed << *value; + sqlpp::detail::float_safe_ostringstream out; + out << *value; _handle->paramValues[index] = out.str(); } } diff --git a/include/sqlpp11/sqlite3/connection.h b/include/sqlpp11/sqlite3/connection.h index 79b3ae63..164b676b 100644 --- a/include/sqlpp11/sqlite3/connection.h +++ b/include/sqlpp11/sqlite3/connection.h @@ -33,6 +33,7 @@ #include #endif #include +#include #include #include #include @@ -184,7 +185,7 @@ namespace sqlpp } const connection& _db; - std::stringstream _os; + sqlpp::detail::float_safe_ostringstream _os; size_t _count; }; diff --git a/include/sqlpp11/value.h b/include/sqlpp11/value.h index d40bd868..66d66718 100644 --- a/include/sqlpp11/value.h +++ b/include/sqlpp11/value.h @@ -27,7 +27,9 @@ #ifndef SQLPP11_VALUE_H #define SQLPP11_VALUE_H +#include #include +#include namespace sqlpp { diff --git a/tests/core/serialize/CMakeLists.txt b/tests/core/serialize/CMakeLists.txt index 0b98e9ce..e3c6da92 100644 --- a/tests/core/serialize/CMakeLists.txt +++ b/tests/core/serialize/CMakeLists.txt @@ -31,6 +31,7 @@ set(test_files CustomQuery.cpp DynamicWhere.cpp Exists.cpp + Float.cpp ForUpdate.cpp From.cpp In.cpp diff --git a/tests/core/serialize/Float.cpp b/tests/core/serialize/Float.cpp new file mode 100644 index 00000000..26384042 --- /dev/null +++ b/tests/core/serialize/Float.cpp @@ -0,0 +1,83 @@ +/* + * Copyright (c) 2023, 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 "compare.h" + +namespace +{ + template + void float_safe_ostringstream_serializes_value_as(int line, T value, std::string expected) + { + sqlpp::detail::float_safe_ostringstream os; + os << value; + assert_equal(line, os.str(), expected); + } + + template + void float_safe_ostringstream_serializes_in_deserializable_format(int line, T value) + { + sqlpp::detail::float_safe_ostringstream os; + os << value; + std::istringstream is{os.str()}; + T deserialized; + is >> deserialized; + assert_equal(line, deserialized, value); + } + + template + std::string string_for_10_0000086() + { + switch (std::numeric_limits::max_digits10) + { + case 9: + return "10.0000086"; + case 17: + return "10.000008599999999"; + case 21: + return "10.0000086000000000001"; + default: + throw std::logic_error("Unknown floating point digit count"); + } + } +} // namespace + +int Float(int, char*[]) +{ + float_safe_ostringstream_serializes_value_as(__LINE__, 10.0000086f, string_for_10_0000086()); + float_safe_ostringstream_serializes_value_as(__LINE__, 10.0000086, string_for_10_0000086()); + float_safe_ostringstream_serializes_value_as(__LINE__, 10.0000086l, string_for_10_0000086()); + + float_safe_ostringstream_serializes_in_deserializable_format(__LINE__, 10.0000086f); + float_safe_ostringstream_serializes_in_deserializable_format(__LINE__, 10.0000086); + float_safe_ostringstream_serializes_in_deserializable_format(__LINE__, 10.0000086l); + + compare(__LINE__, sqlpp::value(10.0000114), "10.0000114"); + + return 0; +} diff --git a/tests/core/serialize/In.cpp b/tests/core/serialize/In.cpp index 89fc09c7..0af7402e 100644 --- a/tests/core/serialize/In.cpp +++ b/tests/core/serialize/In.cpp @@ -49,8 +49,8 @@ int In(int, char* []) compare(__LINE__, foo.omega.in(17, bar.alpha, sqlpp::value(19)), "tab_foo.omega IN(17,tab_bar.alpha,19)"); // Lists - compare(__LINE__, foo.omega.in(sqlpp::value_list(std::vector{1.7f, 2.5f, 17.f, 0.f})), - "tab_foo.omega IN(1.7,2.5,17,0)"); + compare(__LINE__, foo.omega.in(sqlpp::value_list(std::vector{1.75f, 2.5f, 17.f, 0.f})), + "tab_foo.omega IN(1.75,2.5,17,0)"); // Sub select compare(__LINE__, foo.omega.in(select(bar.alpha).from(bar).unconditionally()), diff --git a/tests/core/serialize/compare.h b/tests/core/serialize/compare.h index 9709a44c..3dec0039 100644 --- a/tests/core/serialize/compare.h +++ b/tests/core/serialize/compare.h @@ -31,6 +31,17 @@ namespace { + template + void assert_equal(int lineNo, const Result& result, const Expected& expected) + { + if (result != expected) + { + std::cerr << __FILE__ << " " << lineNo << '\n' << "Expected: -->|" << expected << "|<--\n" + << "Received: -->|" << result << "|<--\n"; + throw std::runtime_error("unexpected result"); + } + } + template void compare(int lineNo, const Expression& expr, const std::string& expected) { @@ -38,12 +49,7 @@ namespace const auto result = serialize(expr, printer).str(); - if (result != expected) - { - std::cerr << __FILE__ << " " << lineNo << '\n' << "Expected: -->|" << expected << "|<--\n" - << "Received: -->|" << result << "|<--\n"; - throw std::runtime_error("unexpected serialization result"); - } + assert_equal(lineNo, result, expected); } } diff --git a/tests/core/usage/MockDb.h b/tests/core/usage/MockDb.h index a344514d..96947365 100644 --- a/tests/core/usage/MockDb.h +++ b/tests/core/usage/MockDb.h @@ -28,6 +28,7 @@ #include #include +#include #include #include #include @@ -49,7 +50,7 @@ struct MockDb : public sqlpp::connection struct _serializer_context_t { - std::ostringstream _os; + ::sqlpp::detail::float_safe_ostringstream _os; _serializer_context_t() = default; _serializer_context_t(const _serializer_context_t& rhs) @@ -68,7 +69,7 @@ struct MockDb : public sqlpp::connection } template - std::ostream& operator<<(T t) + ::sqlpp::detail::float_safe_ostringstream& operator<<(T t) { return _os << t; } diff --git a/tests/mysql/CMakeLists.txt b/tests/mysql/CMakeLists.txt index e848fb58..b31e76d1 100644 --- a/tests/mysql/CMakeLists.txt +++ b/tests/mysql/CMakeLists.txt @@ -22,4 +22,5 @@ # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS # SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +add_subdirectory(serialize) add_subdirectory(usage) \ No newline at end of file diff --git a/tests/mysql/serialize/CMakeLists.txt b/tests/mysql/serialize/CMakeLists.txt new file mode 100644 index 00000000..422a27fa --- /dev/null +++ b/tests/mysql/serialize/CMakeLists.txt @@ -0,0 +1,51 @@ +# Copyright (c) 2023, 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. + +find_package(Threads REQUIRED) + +set(test_files + Float.cpp +) + +create_test_sourcelist(test_sources test_main.cpp ${test_files}) +add_executable(sqlpp11_mysql_serialize_tests ${test_sources}) +target_link_libraries(sqlpp11_mysql_serialize_tests PRIVATE sqlpp11::mysql sqlpp11_testing sqlpp11_mysql_testing) +target_link_libraries(sqlpp11_mysql_serialize_tests PRIVATE Threads::Threads) +if(NOT MSVC) + target_compile_options(sqlpp11_mysql_serialize_tests PRIVATE -Wall -Wextra -pedantic) +endif() + +# conditionally bump to a higher C++ standard to test compatibility +if (SQLPP11_TESTS_CXX_STD) + set_property(TARGET sqlpp11_mysql_serialize_tests PROPERTY CXX_STANDARD ${SQLPP11_TESTS_CXX_STD}) + set_property(TARGET sqlpp11_mysql_serialize_tests PROPERTY CXX_STANDARD_REQUIRED yes) + set_property(TARGET sqlpp11_mysql_serialize_tests PROPERTY CXX_EXTENSIONS no) +endif() + +foreach(test_file IN LISTS test_files) + get_filename_component(test ${test_file} NAME_WLE) + add_test(NAME sqlpp11.mysql.serialize.${test} + COMMAND sqlpp11_mysql_serialize_tests ${test} + ) +endforeach() diff --git a/tests/mysql/serialize/Float.cpp b/tests/mysql/serialize/Float.cpp new file mode 100644 index 00000000..d19ce39c --- /dev/null +++ b/tests/mysql/serialize/Float.cpp @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2023, 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 "compare.h" + +int Float(int, char*[]) +{ + compare(__LINE__, sqlpp::value(10.0000114), "10.0000114"); + + return 0; +} diff --git a/tests/mysql/serialize/compare.h b/tests/mysql/serialize/compare.h new file mode 100644 index 00000000..9bf6b059 --- /dev/null +++ b/tests/mysql/serialize/compare.h @@ -0,0 +1,72 @@ +/* + * 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 SQLPP_TESTS_MYSQL_COMPARE_H +#define SQLPP_TESTS_MYSQL_COMPARE_H + +#include +#include + +namespace +{ + template + void assert_equal(int lineNo, const Result& result, const Expected& expected) + { + if (result != expected) + { + std::cerr << __FILE__ << " " << lineNo << '\n' + << "Expected: -->|" << expected << "|<--\n" + << "Received: -->|" << result << "|<--\n"; + throw std::runtime_error("unexpected result"); + } + } + + template + void compare(int lineNo, const Expression& expr, const std::string& expected) + { + auto config{std::make_shared()}; + config->user = "root"; + config->database = "sqlpp_mysql"; + config->debug = true; + try + { + sqlpp::mysql::connection db(config); + } + catch (const sqlpp::exception& e) + { + std::cerr << e.what() << std::endl; + throw std::logic_error("For testing, you'll need to create a database sqlpp_mysql for user root (no password)"); + } + + sqlpp::mysql::connection connection{config}; + sqlpp::mysql::serializer_t printer{connection}; + + const auto result = serialize(expr, printer).str(); + + assert_equal(lineNo, result, expected); + } +} // namespace + +#endif diff --git a/tests/postgresql/CMakeLists.txt b/tests/postgresql/CMakeLists.txt index a76f4fc0..b5bed210 100644 --- a/tests/postgresql/CMakeLists.txt +++ b/tests/postgresql/CMakeLists.txt @@ -23,4 +23,5 @@ # SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. add_subdirectory(constraints) +add_subdirectory(serialize) add_subdirectory(usage) \ No newline at end of file diff --git a/tests/postgresql/serialize/CMakeLists.txt b/tests/postgresql/serialize/CMakeLists.txt new file mode 100644 index 00000000..190e8c86 --- /dev/null +++ b/tests/postgresql/serialize/CMakeLists.txt @@ -0,0 +1,48 @@ +# Copyright (c) 2023, 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. + +set(test_files + Float.cpp +) + +create_test_sourcelist(test_sources test_main.cpp ${test_files}) +add_executable(sqlpp11_postgresql_serialize_tests ${test_sources}) +target_link_libraries(sqlpp11_postgresql_serialize_tests PRIVATE sqlpp11::postgresql sqlpp11_testing sqlpp11_postgresql_testing) +if(NOT MSVC) + target_compile_options(sqlpp11_postgresql_serialize_tests PRIVATE -Wall -Wextra -pedantic) +endif() + +# conditionally bump to a higher C++ standard to test compatibility +if (SQLPP11_TESTS_CXX_STD) + set_property(TARGET sqlpp11_postgresql_serialize_tests PROPERTY CXX_STANDARD ${SQLPP11_TESTS_CXX_STD}) + set_property(TARGET sqlpp11_postgresql_serialize_tests PROPERTY CXX_STANDARD_REQUIRED yes) + set_property(TARGET sqlpp11_postgresql_serialize_tests PROPERTY CXX_EXTENSIONS no) +endif() + +foreach(test_file IN LISTS test_files) + get_filename_component(test ${test_file} NAME_WLE) + add_test(NAME sqlpp11.postgresql.serialize.${test} + COMMAND sqlpp11_postgresql_serialize_tests ${test} + ) +endforeach() diff --git a/tests/postgresql/serialize/Float.cpp b/tests/postgresql/serialize/Float.cpp new file mode 100644 index 00000000..d19ce39c --- /dev/null +++ b/tests/postgresql/serialize/Float.cpp @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2023, 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 "compare.h" + +int Float(int, char*[]) +{ + compare(__LINE__, sqlpp::value(10.0000114), "10.0000114"); + + return 0; +} diff --git a/tests/postgresql/serialize/compare.h b/tests/postgresql/serialize/compare.h new file mode 100644 index 00000000..951b7598 --- /dev/null +++ b/tests/postgresql/serialize/compare.h @@ -0,0 +1,59 @@ +/* + * 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 SQLPP_TESTS_POSTGRESQL_COMPARE_H +#define SQLPP_TESTS_POSTGRESQL_COMPARE_H + +#include + +#include + +namespace +{ + template + void assert_equal(int lineNo, const Result& result, const Expected& expected) + { + if (result != expected) + { + std::cerr << __FILE__ << " " << lineNo << '\n' + << "Expected: -->|" << expected << "|<--\n" + << "Received: -->|" << result << "|<--\n"; + throw std::runtime_error("unexpected result"); + } + } + + template + void compare(int lineNo, const Expression& expr, const std::string& expected) + { + sqlpp::postgresql::connection connection; + sqlpp::postgresql::context_t printer{connection}; + + const auto result = serialize(expr, printer).str(); + + assert_equal(lineNo, result, expected); + } +} // namespace + +#endif diff --git a/tests/sqlite3/CMakeLists.txt b/tests/sqlite3/CMakeLists.txt index e848fb58..b31e76d1 100644 --- a/tests/sqlite3/CMakeLists.txt +++ b/tests/sqlite3/CMakeLists.txt @@ -22,4 +22,5 @@ # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS # SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +add_subdirectory(serialize) add_subdirectory(usage) \ No newline at end of file diff --git a/tests/sqlite3/serialize/CMakeLists.txt b/tests/sqlite3/serialize/CMakeLists.txt new file mode 100644 index 00000000..c0ff4fc1 --- /dev/null +++ b/tests/sqlite3/serialize/CMakeLists.txt @@ -0,0 +1,54 @@ +# Copyright (c) 2023, 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. + +set(test_files + Float.cpp +) + +create_test_sourcelist(test_sources test_main.cpp ${test_files}) + +add_executable(sqlpp11_sqlite3_serialize_tests ${test_sources}) +target_link_libraries(sqlpp11_sqlite3_serialize_tests PRIVATE sqlpp11_testing sqlpp11_sqlite3_testing) +if (BUILD_SQLCIPHER_CONNECTOR) + target_link_libraries(sqlpp11_sqlite3_serialize_tests PRIVATE sqlpp11::sqlcipher) + if (SQLPP_DYNAMIC_LOADING) + target_include_directories(sqlpp11_sqlite3_serialize_tests PRIVATE ${SQLCIPHER_INCLUDE_DIRS}) + endif() +else() + target_link_libraries(sqlpp11_sqlite3_serialize_tests PRIVATE sqlpp11::sqlite3) +endif() + +# conditionally bump to a higher C++ standard to test compatibility +if (SQLPP11_TESTS_CXX_STD) + set_property(TARGET sqlpp11_sqlite3_serialize_tests PROPERTY CXX_STANDARD ${SQLPP11_TESTS_CXX_STD}) + set_property(TARGET sqlpp11_sqlite3_serialize_tests PROPERTY CXX_STANDARD_REQUIRED ON) + set_property(TARGET sqlpp11_sqlite3_serialize_tests PROPERTY CXX_EXTENSIONS OFF) +endif() + +foreach(test_file IN LISTS test_files) + get_filename_component(test ${test_file} NAME_WLE) + add_test(NAME sqlpp11.sqlite3.serialize.${test} + COMMAND sqlpp11_sqlite3_serialize_tests ${test} + ) +endforeach() diff --git a/tests/sqlite3/serialize/Float.cpp b/tests/sqlite3/serialize/Float.cpp new file mode 100644 index 00000000..d19ce39c --- /dev/null +++ b/tests/sqlite3/serialize/Float.cpp @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2023, 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 "compare.h" + +int Float(int, char*[]) +{ + compare(__LINE__, sqlpp::value(10.0000114), "10.0000114"); + + return 0; +} diff --git a/tests/sqlite3/serialize/compare.h b/tests/sqlite3/serialize/compare.h new file mode 100644 index 00000000..e821c124 --- /dev/null +++ b/tests/sqlite3/serialize/compare.h @@ -0,0 +1,63 @@ +/* + * 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 SQLPP_TESTS_SQLITE3_COMPARE_H +#define SQLPP_TESTS_SQLITE3_COMPARE_H + +#include + +#include + +namespace +{ + template + void assert_equal(int lineNo, const Result& result, const Expected& expected) + { + if (result != expected) + { + std::cerr << __FILE__ << " " << lineNo << '\n' + << "Expected: -->|" << expected << "|<--\n" + << "Received: -->|" << result << "|<--\n"; + throw std::runtime_error("unexpected result"); + } + } + + template + void compare(int lineNo, const Expression& expr, const std::string& expected) + { + sqlpp::sqlite3::connection_config config; + config.path_to_database = ":memory:"; + config.flags = SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE; + config.debug = true; + sqlpp::sqlite3::connection connection{config}; + sqlpp::sqlite3::serializer_t printer{connection}; + + const auto result = serialize(expr, printer).str(); + + assert_equal(lineNo, result, expected); + } +} // namespace + +#endif