From 73e8f041274a700452c39b4fbd8d51ee3de98cfe Mon Sep 17 00:00:00 2001 From: rbock Date: Wed, 28 Oct 2015 20:52:43 +0100 Subject: [PATCH] Several minor date/time fixes, new tests --- CMakeLists.txt | 7 ++++ include/sqlpp11/date.h | 30 ++++++++++++++- include/sqlpp11/date_time.h | 29 ++++++++++++++ include/sqlpp11/wrap_operand.h | 39 +++++++++++++++++-- tests/CMakeLists.txt | 1 + tests/DateTime.cpp | 68 +++++++++++++++++++++++++++++++++ tests/Sample.h | 70 ++++++++++++++++++++++++++++++++++ 7 files changed, 239 insertions(+), 5 deletions(-) create mode 100644 tests/DateTime.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 0f033171..f606df00 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -29,7 +29,14 @@ enable_testing() add_library(sqlpp11 INTERFACE) +set(DATE_INCLUDE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/../date" CACHE FILEPATH "Path to Howard Hinnant's date library") + +if(NOT EXISTS ${DATE_INCLUDE_DIR}/date.h) + message(SEND_ERROR "Can't find date.h in ${DATE_INCLUDE_DIR}") +endif() + target_include_directories(sqlpp11 INTERFACE + $ $ ) diff --git a/include/sqlpp11/date.h b/include/sqlpp11/date.h index a2b80a64..37eb170c 100644 --- a/include/sqlpp11/date.h +++ b/include/sqlpp11/date.h @@ -27,6 +27,7 @@ #ifndef SQLPP_DATE_H #define SQLPP_DATE_H +#include #include #include #include @@ -138,7 +139,7 @@ namespace sqlpp struct result_field_t : public result_field_methods_t> { static_assert(std::is_same, date>::value, "field type mismatch"); - using _cpp_value_type = typename date::_cpp_value_type; + using _cpp_value_type = typename sqlpp::date::_cpp_value_type; result_field_t() : _is_valid(false), _is_null(true), _value{} { @@ -201,5 +202,32 @@ namespace sqlpp bool _is_null; _cpp_value_type _value; }; + + template + struct serializer_t> + { + using _serialize_check = consistent_t; + using T = result_field_t; + + static Context& _(const T& t, Context& context) + { + if (t.is_null() and not null_is_trivial_value_t::value) + { + context << "NULL"; + } + else + { + const auto ymd = ::date::year_month_day{t.value()}; + context << ymd; + } + return context; + } + }; + + template + inline std::ostream& operator<<(std::ostream& os, const result_field_t& e) + { + return serialize(e, os); + } } #endif diff --git a/include/sqlpp11/date_time.h b/include/sqlpp11/date_time.h index 659cd20c..1805b334 100644 --- a/include/sqlpp11/date_time.h +++ b/include/sqlpp11/date_time.h @@ -202,5 +202,34 @@ namespace sqlpp bool _is_null; _cpp_value_type _value; }; + + template + struct serializer_t> + { + using _serialize_check = consistent_t; + using T = result_field_t; + + static Context& _(const T& t, Context& context) + { + if (t.is_null() and not null_is_trivial_value_t::value) + { + context << "NULL"; + } + else + { + const auto dp = ::date::floor<::date::days>(t); + const auto time = ::date::make_time(t - dp); + const auto ymd = ::date::year_month_day{dp}; + context << ymd << ' ' << time; + } + return context; + } + }; + + template + inline std::ostream& operator<<(std::ostream& os, const result_field_t& e) + { + return serialize(e, os); + } } #endif diff --git a/include/sqlpp11/wrap_operand.h b/include/sqlpp11/wrap_operand.h index aaedd510..013d6667 100644 --- a/include/sqlpp11/wrap_operand.h +++ b/include/sqlpp11/wrap_operand.h @@ -27,6 +27,7 @@ #ifndef SQLPP_DETAIL_WRAP_OPERAND_H #define SQLPP_DETAIL_WRAP_OPERAND_H +#include #include #include #include @@ -71,6 +72,19 @@ namespace sqlpp _value_t _t; }; + template + struct serializer_t + { + using _serialize_check = consistent_t; + using Operand = boolean_operand; + + static Context& _(const Operand& t, Context& context) + { + context << t._t; + return context; + } + }; + template struct date_time_operand : public alias_operators> { @@ -102,15 +116,32 @@ namespace sqlpp _value_t _t; }; - template - struct serializer_t + template + struct serializer_t> { using _serialize_check = consistent_t; - using Operand = boolean_operand; + using Operand = date_time_operand; static Context& _(const Operand& t, Context& context) { - context << t._t; + const auto dp = ::date::floor<::date::days>(t._t); + const auto time = ::date::make_time(t._t - dp); + const auto ymd = ::date::year_month_day{dp}; + context << "TIMESTAMP '" << ymd << ' ' << time << "'"; + return context; + } + }; + + template + struct serializer_t> + { + using _serialize_check = consistent_t; + using Operand = date_time_operand; + + static Context& _(const Operand& t, Context& context) + { + const auto ymd = ::date::year_month_day{t._t}; + context << "DATE '" << ymd << "'"; return context; } }; diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 66ba4a0f..b54773b0 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -32,6 +32,7 @@ endif () set(test_names BooleanExpression CustomQuery + DateTime Interpret Insert Remove diff --git a/tests/DateTime.cpp b/tests/DateTime.cpp new file mode 100644 index 00000000..2537bf32 --- /dev/null +++ b/tests/DateTime.cpp @@ -0,0 +1,68 @@ +/* + * Copyright (c) 2015-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 "Sample.h" +#include "MockDb.h" +#include + +SQLPP_ALIAS_PROVIDER(now) + +int DateTime(int, char**) +{ + MockDb db = {}; + MockDb::_serializer_context_t printer; + test::TabDateTime t; + + for (const auto& row : db(select(sqlpp::value(std::chrono::system_clock::now()).as(now)))) + { + std::cout << row.now; + } + printer.reset(); + std::cerr << serialize(sqlpp::value(std::chrono::system_clock::now()), printer).str() << std::endl; + + db(insert_into(t).set(t.colDate = ::date::floor(std::chrono::system_clock::now()))); + db(insert_into(t).set(t.colDate = std::chrono::system_clock::now())); + db(insert_into(t).set(t.colDateTime = ::date::floor(std::chrono::system_clock::now()))); + db(insert_into(t).set(t.colDateTime = std::chrono::system_clock::now())); + + db(update(t) + .set(t.colDate = ::date::floor(std::chrono::system_clock::now())) + .where(t.colDate < std::chrono::system_clock::now())); + db(update(t).set(t.colDate = std::chrono::system_clock::now()).where(t.colDate < std::chrono::system_clock::now())); + db(update(t) + .set(t.colDateTime = ::date::floor(std::chrono::system_clock::now())) + .where(t.colDate < std::chrono::system_clock::now())); + db(update(t) + .set(t.colDateTime = std::chrono::system_clock::now()) + .where(t.colDate < std::chrono::system_clock::now())); + + db(remove_from(t).where(t.colDate == ::date::floor(std::chrono::system_clock::now()))); + db(remove_from(t).where(t.colDate == std::chrono::system_clock::now())); + db(remove_from(t).where(t.colDateTime == ::date::floor(std::chrono::system_clock::now()))); + db(remove_from(t).where(t.colDateTime == std::chrono::system_clock::now())); + + return 0; +} diff --git a/tests/Sample.h b/tests/Sample.h index 8439557a..44a2d274 100644 --- a/tests/Sample.h +++ b/tests/Sample.h @@ -212,5 +212,75 @@ namespace test }; }; }; + + namespace TabDateTime_ + { + struct ColDate + { + struct _alias_t + { + static constexpr const char _literal[] = "col_date"; + using _name_t = sqlpp::make_char_sequence; + template + struct _member_t + { + T colDate; + T& operator()() + { + return colDate; + } + const T& operator()() const + { + return colDate; + } + }; + }; + using _traits = sqlpp::make_traits; + }; + struct ColDateTime + { + struct _alias_t + { + static constexpr const char _literal[] = "col_date_time"; + using _name_t = sqlpp::make_char_sequence; + template + struct _member_t + { + T colDateTime; + T& operator()() + { + return colDateTime; + } + const T& operator()() const + { + return colDateTime; + } + }; + }; + using _traits = sqlpp::make_traits; + }; + } + + struct TabDateTime : sqlpp::table_t + { + struct _alias_t + { + static constexpr const char _literal[] = "tab_date_time"; + using _name_t = sqlpp::make_char_sequence; + template + struct _member_t + { + T tabDateTime; + T& operator()() + { + return tabDateTime; + } + const T& operator()() const + { + return tabDateTime; + } + }; + }; + }; } #endif