Lightweight 0.20260303.0
Loading...
Searching...
No Matches
SqlTime.hpp
1// SPDX-License-Identifier: Apache-2.0
2
3#pragma once
4
5#include "../SqlColumnTypeDefinitions.hpp"
6#include "Core.hpp"
7
8#include <chrono>
9#include <format>
10
11// clang-format off
12#if !defined(SQL_SS_TIME2)
13// This is a Microsoft-specific extension to ODBC.
14// It is supported by at lesat the following drivers:
15// - SQL Server 2008 and later
16// - MariaDB and MySQL ODBC drivers
17
18#define SQL_SS_TIME2 (-154)
19
20struct SQL_SS_TIME2_STRUCT
21{
22 SQLUSMALLINT hour;
23 SQLUSMALLINT minute;
24 SQLUSMALLINT second;
25 SQLUINTEGER fraction;
26};
27
28static_assert(
29 sizeof(SQL_SS_TIME2_STRUCT) == 12,
30 "SQL_SS_TIME2_STRUCT size must be padded 12 bytes, as per ODBC extension spec."
31);
32
33#endif
34// clang-format on
35
36namespace Lightweight
37{
38
39/// Stores the time (of the day) to efficiently write to or read from a database.
40///
41/// @ingroup DataTypes
42struct SqlTime
43{
44 /// The native C++ type for time representation.
45 using native_type = std::chrono::hh_mm_ss<std::chrono::microseconds>;
46
47#if defined(SQL_SS_TIME2)
48 /// The SQL type used for ODBC binding.
49 using sql_type = SQL_SS_TIME2_STRUCT;
50#else
51 /// The SQL type used for ODBC binding.
52 using sql_type = SQL_TIME_STRUCT;
53#endif
54
55 /// The underlying SQL value for ODBC binding.
57
58 /// Default constructor.
59 constexpr SqlTime() noexcept = default;
60 /// Move constructor.
61 constexpr SqlTime(SqlTime&&) noexcept = default;
62 /// Move assignment operator.
63 constexpr SqlTime& operator=(SqlTime&&) noexcept = default;
64 /// Copy constructor.
65 constexpr SqlTime(SqlTime const&) noexcept = default;
66 /// Copy assignment operator.
67 constexpr SqlTime& operator=(SqlTime const&) noexcept = default;
68 constexpr ~SqlTime() noexcept = default;
69
70 /// Returns the native time value.
71 [[nodiscard]] LIGHTWEIGHT_FORCE_INLINE constexpr native_type value() const noexcept
72 {
74 }
75
76 /// Equality comparison operator.
77 LIGHTWEIGHT_FORCE_INLINE constexpr bool operator==(SqlTime const& other) const noexcept
78 {
79 return value().to_duration().count() == other.value().to_duration().count();
80 }
81
82 /// Inequality comparison operator.
83 LIGHTWEIGHT_FORCE_INLINE constexpr bool operator!=(SqlTime const& other) const noexcept
84 {
85 return !(*this == other);
86 }
87
88 /// Constructs a SqlTime from a native time value.
89 LIGHTWEIGHT_FORCE_INLINE constexpr SqlTime(native_type value) noexcept:
91 {
92 }
93
94 /// Constructs a SqlTime from hours, minutes, seconds, and optional microseconds.
95 LIGHTWEIGHT_FORCE_INLINE constexpr SqlTime(std::chrono::hours hour,
96 std::chrono::minutes minute,
97 std::chrono::seconds second,
98 std::chrono::microseconds micros = {}) noexcept:
99 SqlTime(native_type { hour + minute + second + micros })
100 {
101 }
102
103 /// Converts a native time value to the SQL representation.
104 static LIGHTWEIGHT_FORCE_INLINE constexpr sql_type ConvertToSqlValue(native_type value) noexcept
105 {
106 return sql_type {
107 .hour = (SQLUSMALLINT) value.hours().count(),
108 .minute = (SQLUSMALLINT) value.minutes().count(),
109 .second = (SQLUSMALLINT) value.seconds().count(),
110#if defined(SQL_SS_TIME2)
111 .fraction = (SQLUINTEGER) value.subseconds().count(),
112#endif
113 };
114 }
115
116 /// Converts a SQL time value to the native representation.
117 static LIGHTWEIGHT_FORCE_INLINE constexpr native_type ConvertToNative(sql_type const& value) noexcept
118 {
119 // clang-format off
120 return native_type { std::chrono::hours { (int) value.hour }
121 + std::chrono::minutes { (unsigned) value.minute }
122 + std::chrono::seconds { (unsigned) value.second }
123#if defined(SQL_SS_TIME2)
124 + std::chrono::microseconds { value.fraction }
125#endif
126
127 };
128 // clang-format on
129 }
130};
131
132template <>
133struct SqlDataBinder<SqlTime>
134{
135 static constexpr auto ColumnType = SqlColumnTypeDefinitions::Time {};
136
137 static LIGHTWEIGHT_FORCE_INLINE SQLRETURN InputParameter(SQLHSTMT stmt,
138 SQLUSMALLINT column,
139 SqlTime const& value,
140 SqlDataBinderCallback& /*cb*/) noexcept
141 {
142 return SQLBindParameter(
143 stmt, column, SQL_PARAM_INPUT, SQL_C_TYPE_TIME, SQL_TYPE_TIME, 0, 0, (SQLPOINTER) &value.sqlValue, 0, nullptr);
144 }
145
146 static LIGHTWEIGHT_FORCE_INLINE SQLRETURN OutputColumn(
147 SQLHSTMT stmt, SQLUSMALLINT column, SqlTime* result, SQLLEN* indicator, SqlDataBinderCallback& /*cb*/) noexcept
148 {
149 return SQLBindCol(stmt, column, SQL_C_TYPE_TIME, &result->sqlValue, sizeof(result->sqlValue), indicator);
150 }
151
152 static LIGHTWEIGHT_FORCE_INLINE SQLRETURN GetColumn(
153 SQLHSTMT stmt, SQLUSMALLINT column, SqlTime* result, SQLLEN* indicator, SqlDataBinderCallback const& /*cb*/) noexcept
154 {
155 return SQLGetData(stmt, column, SQL_C_TYPE_TIME, &result->sqlValue, sizeof(result->sqlValue), indicator);
156 }
157
158 static LIGHTWEIGHT_FORCE_INLINE std::string Inspect(SqlTime const& value) noexcept
159 {
160 return std::format("{:02}:{:02}:{:02}.{:06}",
161 value.sqlValue.hour,
162 value.sqlValue.minute,
163 value.sqlValue.second,
164 value.sqlValue.fraction);
165 }
166};
167
168} // namespace Lightweight
169
170template <>
171struct std::formatter<Lightweight::SqlTime>: std::formatter<std::string>
172{
173 auto format(Lightweight::SqlTime const& value, std::format_context& ctx) const -> std::format_context::iterator
174 {
175 return std::formatter<std::string>::format(std::format("{:02}:{:02}:{:02}.{:06}",
176 value.sqlValue.hour,
177 value.sqlValue.minute,
178 value.sqlValue.second,
179 value.sqlValue.fraction),
180 ctx);
181 }
182};
static LIGHTWEIGHT_FORCE_INLINE constexpr sql_type ConvertToSqlValue(native_type value) noexcept
Converts a native time value to the SQL representation.
Definition SqlTime.hpp:104
constexpr SqlTime() noexcept=default
Default constructor.
std::chrono::hh_mm_ss< std::chrono::microseconds > native_type
The native C++ type for time representation.
Definition SqlTime.hpp:45
SQL_SS_TIME2_STRUCT sql_type
The SQL type used for ODBC binding.
Definition SqlTime.hpp:49
LIGHTWEIGHT_FORCE_INLINE constexpr bool operator!=(SqlTime const &other) const noexcept
Inequality comparison operator.
Definition SqlTime.hpp:83
LIGHTWEIGHT_FORCE_INLINE constexpr bool operator==(SqlTime const &other) const noexcept
Equality comparison operator.
Definition SqlTime.hpp:77
sql_type sqlValue
The underlying SQL value for ODBC binding.
Definition SqlTime.hpp:56
LIGHTWEIGHT_FORCE_INLINE constexpr SqlTime(native_type value) noexcept
Constructs a SqlTime from a native time value.
Definition SqlTime.hpp:89
LIGHTWEIGHT_FORCE_INLINE constexpr native_type value() const noexcept
Returns the native time value.
Definition SqlTime.hpp:71
static LIGHTWEIGHT_FORCE_INLINE constexpr native_type ConvertToNative(sql_type const &value) noexcept
Converts a SQL time value to the native representation.
Definition SqlTime.hpp:117
LIGHTWEIGHT_FORCE_INLINE constexpr SqlTime(std::chrono::hours hour, std::chrono::minutes minute, std::chrono::seconds second, std::chrono::microseconds micros={}) noexcept
Constructs a SqlTime from hours, minutes, seconds, and optional microseconds.
Definition SqlTime.hpp:95