diff --git a/include/sqlpp11/mysql/bind_result.h b/include/sqlpp11/mysql/bind_result.h index a8a34012..ad859fcf 100644 --- a/include/sqlpp11/mysql/bind_result.h +++ b/include/sqlpp11/mysql/bind_result.h @@ -280,6 +280,29 @@ namespace sqlpp param.error = &meta_data.bound_error; } + void _bind_time_of_day_result(size_t index, ::std::chrono::microseconds* value, bool* is_null) + { + if (_handle->debug) + std::cerr << "MySQL debug: binding time of day result " << static_cast(value) << " at index: " << index + << std::endl; + + detail::result_meta_data_t& meta_data{_handle->result_param_meta_data[index]}; + meta_data.index = index; + meta_data.len = nullptr; + meta_data.is_null = is_null; + meta_data.text_buffer = nullptr; + meta_data.bound_text_buffer.resize(sizeof(MYSQL_TIME)); + + MYSQL_BIND& param{_handle->result_params[index]}; + param.buffer_type = MYSQL_TYPE_TIME; + param.buffer = meta_data.bound_text_buffer.data(); + param.buffer_length = meta_data.bound_text_buffer.size(); + param.length = &meta_data.bound_len; + param.is_null = &meta_data.bound_is_null; + param.is_unsigned = false; + param.error = &meta_data.bound_error; + } + void _post_bind_boolean_result(size_t /* index */, signed char* /* value */, bool* /* is_null */) { } @@ -315,7 +338,7 @@ namespace sqlpp void _post_bind_date_time_result(size_t index, ::sqlpp::chrono::microsecond_point* value, bool* is_null) { if (_handle->debug) - std::cerr << "MySQL debug: binding date time result " << static_cast(value) << " at index: " << index + std::cerr << "MySQL debug: post binding date time result " << static_cast(value) << " at index: " << index << std::endl; if (not *is_null) @@ -331,6 +354,21 @@ namespace sqlpp } } + void _post_bind_time_of_day_result(size_t index, ::std::chrono::microseconds* value, bool* is_null) + { + if (_handle->debug) + std::cerr << "MySQL debug: post binding date time result " << static_cast(value) << " at index: " << index + << std::endl; + + if (not *is_null) + { + const auto& dt = + *reinterpret_cast(_handle->result_param_meta_data[index].bound_text_buffer.data()); + *value = std::chrono::hours(dt.hour) + std::chrono::minutes(dt.minute) + std::chrono::seconds(dt.second) + + std::chrono::microseconds(dt.second_part); + } + } + private: void bind_impl() { diff --git a/include/sqlpp11/mysql/char_result.h b/include/sqlpp11/mysql/char_result.h index 1afbf6b6..a3cfc6f9 100644 --- a/include/sqlpp11/mysql/char_result.h +++ b/include/sqlpp11/mysql/char_result.h @@ -187,6 +187,29 @@ namespace sqlpp } } + void _bind_time_of_day_result(size_t index, ::std::chrono::microseconds* value, bool* is_null) + { + if (_handle->debug) + std::cerr << "MySQL debug: parsing time of day result at index: " << index << std::endl; + + *value = {}; + *is_null = (_char_result_row.data == nullptr or _char_result_row.data[index] == nullptr); + if (*is_null) + { + return; + } + + const auto time_string = _char_result_row.data[index]; + if (_handle->debug) + std::cerr << "MySQL debug: time of day string: " << time_string << std::endl; + + if (::sqlpp::detail::parse_time_of_day(*value, time_string) == false) + { + if (_handle->debug) + std::cerr << "MySQL debug: invalid time result: " << time_string << std::endl; + } + } + private: bool next_impl() { diff --git a/tests/mysql/usage/DateTime.cpp b/tests/mysql/usage/DateTime.cpp index 6d4763cd..3d5d820e 100644 --- a/tests/mysql/usage/DateTime.cpp +++ b/tests/mysql/usage/DateTime.cpp @@ -36,10 +36,6 @@ const auto library_raii = sqlpp::mysql::scoped_library_initializer_t{}; namespace { - const auto now = ::sqlpp::chrono::floor<::std::chrono::milliseconds>(std::chrono::system_clock::now()); - const auto today = ::sqlpp::chrono::floor<::sqlpp::chrono::days>(now); - const auto yesterday = today - ::sqlpp::chrono::days{1}; - template auto require_equal(int line, const L& l, const R& r) -> void { @@ -75,14 +71,20 @@ int DateTime(int, char*[]) sql::global_library_init(); try { + const auto now = ::sqlpp::chrono::floor<::std::chrono::milliseconds>(std::chrono::system_clock::now()); + const auto today = ::sqlpp::chrono::floor<::sqlpp::chrono::days>(now); + const auto yesterday = today - ::sqlpp::chrono::days{1}; + const auto current = now - today; + auto db = sql::make_test_connection(); db.execute(R"(SET time_zone = '+00:00')"); // To force MySQL's CURRENT_TIMESTAMP into the right timezone db.execute(R"(DROP TABLE IF EXISTS tab_date_time)"); db.execute(R"(CREATE TABLE tab_date_time ( - col_day_point date, - col_time_point datetime(3), - col_date_time_point datetime DEFAULT CURRENT_TIMESTAMP - ))"); + col_day_point date, + col_time_point datetime(3), + col_date_time_point datetime DEFAULT CURRENT_TIMESTAMP, + col_time_of_day time + ))"); const auto tab = TabDateTime{}; db(insert_into(tab).default_values()); @@ -92,22 +94,28 @@ int DateTime(int, char*[]) require_equal(__LINE__, row.colDayPoint.value(), ::sqlpp::chrono::day_point{}); require_equal(__LINE__, row.colTimePoint.is_null(), true); require_equal(__LINE__, row.colTimePoint.value(), ::sqlpp::chrono::microsecond_point{}); - require_close(__LINE__, row.colDateTimePoint.value(), sqlpp::chrono::floor(std::chrono::system_clock::now())); + require_close(__LINE__, row.colDateTimePoint.value(), now); + require_equal(__LINE__, row.colTimeOfDay.is_null(), true); + require_equal(__LINE__, row.colTimeOfDay.value(), ::std::chrono::microseconds{}); } - auto statement = db.prepare(select(tab.colDateTimePoint).from(tab).unconditionally()); - for (const auto& row : db(statement)) - { - require_equal(__LINE__, row.colDateTimePoint.is_null(), false); - require_close(__LINE__, row.colDateTimePoint.value(), sqlpp::chrono::floor(std::chrono::system_clock::now())); - } - - db(update(tab).set(tab.colDayPoint = today, tab.colTimePoint = now).unconditionally()); + db(update(tab).set(tab.colDayPoint = today, tab.colTimePoint = now, tab.colTimeOfDay = current).unconditionally()); for (const auto& row : db(select(all_of(tab)).from(tab).unconditionally())) { require_equal(__LINE__, row.colDayPoint.value(), today); require_equal(__LINE__, row.colTimePoint.value(), now); + require_close(__LINE__, row.colTimeOfDay.value(), current); + } + + auto statement = db.prepare(select(all_of(tab)).from(tab).unconditionally()); + for (const auto& row : db(statement)) + { + require_equal(__LINE__, row.colDateTimePoint.is_null(), false); + require_close(__LINE__, row.colDateTimePoint.value(), now); + require_equal(__LINE__, row.colDayPoint.value(), today); + require_equal(__LINE__, row.colTimePoint.value(), now); + require_close(__LINE__, row.colTimeOfDay.value(), current); } db(update(tab).set(tab.colDayPoint = yesterday, tab.colTimePoint = today).unconditionally()); diff --git a/tests/mysql/usage/TabSample.h b/tests/mysql/usage/TabSample.h index f846d94f..f8787d76 100644 --- a/tests/mysql/usage/TabSample.h +++ b/tests/mysql/usage/TabSample.h @@ -219,25 +219,55 @@ namespace TabDateTime_ }; using _traits = sqlpp::make_traits; }; - struct ColDateTimePoint - { - struct _alias_t - { - static constexpr const char _literal[] = "col_date_time_point"; - using _name_t = sqlpp::make_char_sequence; - template - struct _member_t - { - T colDateTimePoint; - T& operator()() { return colDateTimePoint; } - const T& operator()() const { return colDateTimePoint; } - }; - }; - using _traits = sqlpp::make_traits; - }; + + struct ColDateTimePoint + { + struct _alias_t + { + static constexpr const char _literal[] = "col_date_time_point"; + using _name_t = sqlpp::make_char_sequence; + template + struct _member_t + { + T colDateTimePoint; + T& operator()() + { + return colDateTimePoint; + } + const T& operator()() const + { + return colDateTimePoint; + } + }; + }; + using _traits = sqlpp::make_traits; + }; + + struct ColTimeOfDay + { + struct _alias_t + { + static constexpr const char _literal[] = "col_time_of_day"; + using _name_t = sqlpp::make_char_sequence; + template + struct _member_t + { + T colTimeOfDay; + T& operator()() + { + return colTimeOfDay; + } + const T& operator()() const + { + return colTimeOfDay; + } + }; + }; + using _traits = sqlpp::make_traits; + }; } -struct TabDateTime : sqlpp::table_t +struct TabDateTime : sqlpp::table_t { struct _alias_t {