Lightweight 0.20261031.0
Loading...
Searching...
No Matches
SqlVariant.hpp
1// SPDX-License-Identifier: Apache-2.0
2
3#pragma once
4
5#include "../DataBinder/UnicodeConverter.hpp"
6#include "../SqlLogger.hpp"
7#include "Core.hpp"
8#include "Primitives.hpp"
9#include "SqlBinary.hpp"
10#include "SqlDate.hpp"
11#include "SqlDateTime.hpp"
12#include "SqlDynamicBinary.hpp"
13#include "SqlDynamicNumeric.hpp"
14#include "SqlFixedString.hpp"
15#include "SqlGuid.hpp"
16#include "SqlNullValue.hpp"
17#include "SqlText.hpp"
18#include "SqlTime.hpp"
19#include "StdString.hpp"
20#include "StdStringView.hpp"
21
22#include <format>
23#include <print>
24#include <variant>
25
26namespace Lightweight
27{
28
29namespace detail
30{
31 template <class... Ts>
32 struct overloaded: Ts... // NOLINT(readability-identifier-naming)
33 {
34 using Ts::operator()...;
35 };
36
37 template <class... Ts>
38 overloaded(Ts...) -> overloaded<Ts...>;
39
40} // namespace detail
41
42/// @brief Represents a value that can be any of the supported SQL data types.
43///
44/// Use this class with care. Always prefer native types when possible, in order to avoid any unnecessary overhead.
45///
46/// @ingroup DataTypes
48{
49 /// @brief The inner type of the variant.
50 ///
51 /// This type is a variant of all the supported SQL data types.
52 using InnerType = std::variant<SqlNullType,
53 SqlGuid,
54 bool,
55 int8_t,
56 short,
57 unsigned short,
58 int,
59 unsigned int,
60 long long,
61 unsigned long long,
62 float,
63 double,
64 std::string,
65 std::string_view,
66 std::u16string,
67 std::u16string_view,
68 SqlText,
71 SqlDate,
72 SqlTime,
74
75 /// The variant value.
77
78 /// @brief Default construct a new SqlVariant.
79 SqlVariant() = default;
80 /// @brief Copy construct a new SqlVariant from another.
81 SqlVariant(SqlVariant const&) = default;
82 /// @brief Move construct a new SqlVariant from another.
83 SqlVariant(SqlVariant&&) noexcept = default;
84 /// @brief Copy assign a new SqlVariant from another.
85 SqlVariant& operator=(SqlVariant const&) = default;
86 /// @brief Move assign a new SqlVariant from another.
87 SqlVariant& operator=(SqlVariant&&) noexcept = default;
88 /// @brief Destructor for SqlVariant.
89 ~SqlVariant() = default;
90
91 /// @brief Copy constructor of a SqlVariant from one of the supported types.
92 LIGHTWEIGHT_FORCE_INLINE SqlVariant(InnerType const& other):
93 value(other)
94 {
95 }
96
97 /// @brief Move constructor of a SqlVariant from one of the supported types.
98 LIGHTWEIGHT_FORCE_INLINE SqlVariant(InnerType&& other) noexcept:
99 value(std::move(other))
100 {
101 }
102
103 /// @brief Construct a new SqlVariant from a SqlFixedString.
104 template <std::size_t N, typename T = char, SqlFixedStringMode Mode>
105 constexpr LIGHTWEIGHT_FORCE_INLINE SqlVariant(SqlFixedString<N, T, Mode> const& other):
106 value { std::string { other.data(), other.size() } }
107 {
108 }
109
110 /// @brief Construct a new SqlVariant from a SqlDynamicBinary, holding a copy of its bytes as
111 /// @ref SqlBinary. This is what lets a binary column be compared in a query builder's WHERE
112 /// clause, which binds its values as SqlVariant.
113 template <std::size_t N>
114 LIGHTWEIGHT_FORCE_INLINE SqlVariant(SqlDynamicBinary<N> const& other):
115 value { SqlBinary(other.data(), other.data() + other.size()) }
116 {
117 }
118
119 /// @brief Copy constructor of a SqlVariant from a char array.
120 template <std::size_t TextSize>
121 constexpr LIGHTWEIGHT_FORCE_INLINE SqlVariant(char const (&text)[TextSize]):
122 value { std::string_view { text, TextSize - 1 } }
123 {
124 }
125
126 /// @brief Copy constructor of a SqlVariant from a char16_t array.
127 template <std::size_t TextSize>
128 constexpr LIGHTWEIGHT_FORCE_INLINE SqlVariant(char16_t const (&text)[TextSize]):
129 value { std::u16string_view { text, TextSize - 1 } }
130 {
131 }
132
133 /// @brief Copy constructor of a SqlVariant from an optional of one of the supported types.
134 template <typename T>
135 LIGHTWEIGHT_FORCE_INLINE SqlVariant(std::optional<T> const& other):
136 value { other ? InnerType { *other } : InnerType { SqlNullValue } }
137 {
138 }
139
140 /// @brief Assignment operator of a SqlVariant from one of the supported types.
141 LIGHTWEIGHT_FORCE_INLINE SqlVariant& operator=(InnerType const& other)
142 {
143 value = other;
144 return *this;
145 }
146
147 /// @brief Assignment operator of a SqlVariant from one of the supported types.
148 LIGHTWEIGHT_FORCE_INLINE SqlVariant& operator=(InnerType&& other) noexcept
149 {
150 value = std::move(other);
151 return *this;
152 }
153
154 /// @brief Construct from an string-like object that implements an SqlViewHelper<>.
155 template <detail::HasSqlViewHelper StringViewLike>
156 LIGHTWEIGHT_FORCE_INLINE explicit SqlVariant(StringViewLike const* newValue):
157 value { detail::SqlViewHelper<std::remove_cv_t<decltype(*newValue)>>::View(*newValue) }
158 {
159 }
160
161 /// @brief Assign from an string-like object that implements an SqlViewHelper<>.
162 template <detail::HasSqlViewHelper StringViewLike>
163 LIGHTWEIGHT_FORCE_INLINE SqlVariant& operator=(StringViewLike const* newValue) noexcept
164 {
165 value = std::string_view(newValue->GetString(), newValue->GetLength());
166 return *this;
167 }
168
169 /// @brief Check if the value is NULL.
170 [[nodiscard]] LIGHTWEIGHT_FORCE_INLINE bool IsNull() const noexcept
171 {
172 return std::holds_alternative<SqlNullType>(value);
173 }
174
175 /// @brief Check if the value is of the specified type.
176 template <typename T>
177 [[nodiscard]] LIGHTWEIGHT_FORCE_INLINE bool Is() const noexcept
178 {
179 return std::holds_alternative<T>(value);
180 }
181
182 /// @brief Retrieve the value as the specified type.
183 ///
184 /// @note A DECIMAL/NUMERIC column fills the @ref SqlDynamicNumeric alternative and a binary
185 /// column fills @ref SqlBinary. Asking for a floating-point or `std::string` @p T converts
186 /// from those and therefore yields a value rather than a reference. Use
187 /// @ref TryGetNumeric when the exact decimal matters.
188 /// @throws std::bad_variant_access The variant holds neither @p T nor one of the alternatives
189 /// converted above. Use the `TryGet*` accessors to probe instead.
190 template <typename T>
191 [[nodiscard]] LIGHTWEIGHT_FORCE_INLINE decltype(auto) Get()
192 {
193 if constexpr (IsSpecializationOf<std::optional, T>)
194 {
195 if (IsNull())
196 return T { std::nullopt };
197 else
198 return T { std::get<typename T::value_type>(value) };
199 }
200 else if constexpr (std::is_floating_point_v<T>)
201 {
202 if (auto const* numeric = std::get_if<SqlDynamicNumeric>(&value))
203 return static_cast<T>(numeric->ToDouble());
204 return static_cast<T>(std::get<T>(value));
205 }
206 else if constexpr (std::is_same_v<T, std::string>)
207 {
208 if (auto const* binary = std::get_if<SqlBinary>(&value))
209 return std::string(reinterpret_cast<char const*>(binary->data()), binary->size());
210 if (auto const* numeric = std::get_if<SqlDynamicNumeric>(&value))
211 return numeric->ToString();
212 return std::string(std::get<std::string>(value));
213 }
214 else
215 return std::get<T>(value);
216 }
217
218 /// @brief Retrieve the value as the specified type, or return the default value if the value is NULL.
219 ///
220 /// @note A DECIMAL/NUMERIC column fills the @ref SqlDynamicNumeric alternative and a binary column
221 /// fills @ref SqlBinary. Both are converted here when a floating-point or string @p T is
222 /// asked for, so callers written against the arithmetic/string alternatives keep working.
223 /// Reach for @ref TryGetNumeric when the exact decimal matters.
224 template <typename T>
225 [[nodiscard]] LIGHTWEIGHT_FORCE_INLINE T ValueOr(T&& defaultValue) const noexcept
226 {
227 if constexpr (std::is_integral_v<T>)
228 return TryGetIntegral<T>().value_or(std::forward<T>(defaultValue));
229
230 if (IsNull())
231 return std::forward<T>(defaultValue);
232
233 if constexpr (std::is_floating_point_v<T>)
234 {
235 if (auto const* numeric = std::get_if<SqlDynamicNumeric>(&value))
236 return static_cast<T>(numeric->ToDouble());
237 }
238 else if constexpr (std::is_same_v<std::remove_cvref_t<T>, std::string>)
239 {
240 if (auto const* binary = std::get_if<SqlBinary>(&value))
241 return T(reinterpret_cast<char const*>(binary->data()), binary->size());
242 if (auto const* numeric = std::get_if<SqlDynamicNumeric>(&value))
243 return T(numeric->ToString());
244 }
245
246 // Asking for an alternative the variant does not hold would throw through this noexcept
247 // function and abort. Returning the caller's default keeps the contract the signature
248 // advertises: a value, or the fallback.
249 if (auto const* held = std::get_if<std::remove_cvref_t<T>>(&value))
250 return *held;
251
252 return std::forward<T>(defaultValue);
253 }
254
255 // clang-format off
256 /// @brief Retrieve the bool from the variant or std::nullopt
257 [[nodiscard]] LIGHTWEIGHT_FORCE_INLINE std::optional<bool> TryGetBool() const noexcept { return TryGetIntegral<bool>(); }
258 /// @brief Retrieve the int8_t from the variant or std::nullopt
259 [[nodiscard]] LIGHTWEIGHT_FORCE_INLINE std::optional<int8_t> TryGetInt8() const noexcept { return TryGetIntegral<int8_t>(); }
260 /// @brief Retrieve the unsigned short from the variant or std::nullopt
261 [[nodiscard]] LIGHTWEIGHT_FORCE_INLINE std::optional<short> TryGetShort() const noexcept { return TryGetIntegral<short>(); }
262 /// @brief Retrieve the unsigned short from the variant or std::nullopt
263 [[nodiscard]] LIGHTWEIGHT_FORCE_INLINE std::optional<unsigned short> TryGetUShort() const noexcept { return TryGetIntegral<unsigned short>(); }
264 /// @brief Retrieve the int from the variant or std::nullopt
265 [[nodiscard]] LIGHTWEIGHT_FORCE_INLINE std::optional<int> TryGetInt() const noexcept { return TryGetIntegral<int>(); }
266 /// @brief Retrieve the unsigned int from the variant or std::nullopt
267 [[nodiscard]] LIGHTWEIGHT_FORCE_INLINE std::optional<unsigned int> TryGetUInt() const noexcept { return TryGetIntegral<unsigned int>(); }
268 /// @brief Retrieve the long long from the variant or std::nullopt
269 [[nodiscard]] LIGHTWEIGHT_FORCE_INLINE std::optional<long long> TryGetLongLong() const noexcept { return TryGetIntegral<long long>(); }
270 /// @brief Retrieve the unsigned long long from the variant or std::nullopt
271 [[nodiscard]] LIGHTWEIGHT_FORCE_INLINE std::optional<unsigned long long> TryGetULongLong() const noexcept { return TryGetIntegral<unsigned long long>(); }
272 // clang-format on
273
274 private:
275 /// @brief template that is used to get integral types.
276 ///
277 /// Returns `std::nullopt` both when the variant is NULL and when it holds a non-integral
278 /// alternative — the function is `noexcept`, so it must not propagate `bad_variant_access`.
279 template <typename ResultType>
280 [[nodiscard]] std::optional<ResultType> TryGetIntegral() const noexcept
281 {
282 if (IsNull())
283 return std::nullopt;
284
285 // clang-format off
286 return std::visit(detail::overloaded {
287 []<typename T>(T v) -> std::optional<ResultType> requires(std::is_integral_v<T>) { return static_cast<ResultType>(v); },
288 // A DECIMAL(p, 0) column carries no fractional part, so it still reads as an integer —
289 // which is how this accessor behaved before such columns gained their own alternative.
290 [](SqlDynamicNumeric const& v) -> std::optional<ResultType> {
291 if (v.scale != 0)
292 return std::nullopt;
293 return static_cast<ResultType>(v.unscaledValue);
294 },
295 [](auto) -> std::optional<ResultType> { return std::nullopt; } // NOLINT(performance-unnecessary-value-param)
296 }, value);
297 // clang-format on
298 }
299
300 public:
301 /// @brief Retrieves a string view from the variant, or `std::nullopt` if the variant is NULL
302 /// or holds a non-string alternative. The function is `noexcept`, so it must not propagate
303 /// `bad_variant_access`.
304 [[nodiscard]] std::optional<std::string_view> TryGetStringView() const noexcept
305 {
306 if (IsNull())
307 return std::nullopt;
308
309 using Result = std::optional<std::string_view>;
310 // clang-format off
311 return std::visit(detail::overloaded {
312 [](std::string_view v) -> Result { return v; },
313 [](std::string const& v) -> Result { return std::string_view(v.data(), v.size()); },
314 [](SqlText const& v) -> Result { return std::string_view(v.value.data(), v.value.size()); },
315 // A binary column used to land on std::string and so was reachable here; keep it so.
316 // The view is over the variant's own storage, exactly as for the string alternatives.
317 [](SqlBinary const& v) -> Result { return std::string_view(reinterpret_cast<char const*>(v.data()), v.size()); },
318 [](auto const&) -> Result { return std::nullopt; }
319 }, value);
320 // clang-format on
321 }
322
323 /// @brief Retrieves a UTF-16 string view from the variant, or `std::nullopt` if the variant
324 /// is NULL or holds a non-string alternative. The function is `noexcept`, so it must not
325 /// propagate `bad_variant_access`.
326 [[nodiscard]] std::optional<std::u16string_view> TryGetUtf16StringView() const noexcept
327 {
328 if (IsNull())
329 return std::nullopt;
330
331 using Result = std::optional<std::u16string_view>;
332 // clang-format off
333 return std::visit(detail::overloaded {
334 [](std::u16string_view v) -> Result { return v; },
335 [](std::u16string const& v) -> Result { return std::u16string_view(v.data(), v.size()); },
336 [](auto const&) -> Result { return std::nullopt; }
337 }, value);
338 // clang-format on
339 }
340
341 /// @brief function to get SqlDate from SqlVariant or std::nullopt
342 [[nodiscard]] LIGHTWEIGHT_FORCE_INLINE std::optional<SqlDate> TryGetDate() const
343 {
344 if (IsNull())
345 return std::nullopt;
346
347 if (auto const* date = std::get_if<SqlDate>(&value))
348 return *date;
349
350 if (auto const* datetime = std::get_if<SqlDateTime>(&value))
351 {
352 return SqlDate { std::chrono::year(datetime->sqlValue.year),
353 std::chrono::month(datetime->sqlValue.month),
354 std::chrono::day(datetime->sqlValue.day) };
355 }
356
357 throw std::bad_variant_access();
358 }
359
360 /// @brief Equality comparison operator.
361 [[nodiscard]] bool operator==(SqlVariant const& other) const noexcept
362 {
363 return ToString() == other.ToString();
364 }
365
366 /// @brief Inequality comparison operator.
367 [[nodiscard]] bool operator!=(SqlVariant const& other) const noexcept
368 {
369 return !(*this == other);
370 }
371
372 /// @brief function to get SqlTime from SqlVariant or std::nullopt
373 [[nodiscard]] LIGHTWEIGHT_FORCE_INLINE std::optional<SqlTime> TryGetTime() const
374 {
375 if (IsNull())
376 return std::nullopt;
377
378 if (auto const* time = std::get_if<SqlTime>(&value))
379 return *time;
380
381 if (auto const* datetime = std::get_if<SqlDateTime>(&value))
382 {
383 return SqlTime { std::chrono::hours(datetime->sqlValue.hour),
384 std::chrono::minutes(datetime->sqlValue.minute),
385 std::chrono::seconds(datetime->sqlValue.second),
386 std::chrono::microseconds(datetime->sqlValue.fraction) };
387 }
388
389 throw std::bad_variant_access();
390 }
391
392 /// @brief function to get SqlDateTime from SqlVariant or std::nullopt
393 [[nodiscard]] LIGHTWEIGHT_FORCE_INLINE std::optional<SqlDateTime> TryGetDateTime() const
394 {
395 if (IsNull())
396 return std::nullopt;
397
398 if (auto const* dateTime = std::get_if<SqlDateTime>(&value))
399 return *dateTime;
400
401 throw std::bad_variant_access();
402 }
403
404 /// @brief Retrieve the GUID from the variant or std::nullopt if the value is NULL.
405 [[nodiscard]] LIGHTWEIGHT_FORCE_INLINE std::optional<SqlGuid> TryGetGuid() const
406 {
407 if (IsNull())
408 return std::nullopt;
409
410 if (auto const* guid = std::get_if<SqlGuid>(&value))
411 return *guid;
412
413 throw std::bad_variant_access();
414 }
415
416 /// @brief Retrieve the exact fixed-point decimal from the variant, or std::nullopt if NULL.
417 ///
418 /// DECIMAL and NUMERIC columns land on this alternative, keeping every digit the column declares.
419 /// Use @ref SqlDynamicNumeric::ToDouble only where an approximation is acceptable.
420 ///
421 /// @throws std::bad_variant_access The value is neither NULL nor a fixed-point decimal.
422 [[nodiscard]] LIGHTWEIGHT_FORCE_INLINE std::optional<SqlDynamicNumeric> TryGetNumeric() const
423 {
424 if (IsNull())
425 return std::nullopt;
426
427 if (auto const* numeric = std::get_if<SqlDynamicNumeric>(&value))
428 return *numeric;
429
430 throw std::bad_variant_access();
431 }
432
433 /// @brief Retrieve the binary payload from the variant, or std::nullopt if the value is NULL.
434 ///
435 /// BINARY, VARBINARY and LONGVARBINARY columns land on this alternative, which keeps the bytes
436 /// distinguishable from text so they bind back as `SQL_C_BINARY`.
437 ///
438 /// @throws std::bad_variant_access The value is neither NULL nor binary.
439 [[nodiscard]] LIGHTWEIGHT_FORCE_INLINE std::optional<SqlBinary> TryGetBinary() const
440 {
441 if (IsNull())
442 return std::nullopt;
443
444 if (auto const* binary = std::get_if<SqlBinary>(&value))
445 return *binary;
446
447 throw std::bad_variant_access();
448 }
449
450 /// @brief Create string representation of the variant. Can be used for debug purposes
451 [[nodiscard]] LIGHTWEIGHT_API std::string ToString() const;
452};
453
454/// @brief Represents a row of data from the database using SqlVariant as the column data type.
455using SqlVariantRow = std::vector<SqlVariant>;
456
457template <>
458struct LIGHTWEIGHT_API SqlDataBinder<SqlVariant>
459{
460 static SQLRETURN InputParameter(SQLHSTMT stmt,
461 SQLUSMALLINT column,
462 SqlVariant const& variantValue,
463 SqlDataBinderCallback& cb) noexcept;
464
465 static SQLRETURN GetColumn(
466 SQLHSTMT stmt, SQLUSMALLINT column, SqlVariant* result, SQLLEN* indicator, SqlDataBinderCallback const& cb) noexcept;
467
468 static LIGHTWEIGHT_FORCE_INLINE std::string Inspect(SqlVariant const& value) noexcept
469 {
470 return value.ToString();
471 }
472};
473
474} // namespace Lightweight
475
476template <>
477struct std::formatter<Lightweight::SqlVariant>: formatter<string>
478{
479 auto format(Lightweight::SqlVariant const& value, format_context& ctx) const -> format_context::iterator
480 {
481 return std::formatter<string>::format(value.ToString(), ctx);
482 }
483};
Represents a binary data type.
Definition SqlBinary.hpp:24
constexpr auto SqlNullValue
A fixed-point decimal whose precision and scale are known only at run time.
Represents a value that can be any of the supported SQL data types.
LIGHTWEIGHT_FORCE_INLINE SqlVariant(InnerType &&other) noexcept
Move constructor of a SqlVariant from one of the supported types.
LIGHTWEIGHT_API std::string ToString() const
Create string representation of the variant. Can be used for debug purposes.
LIGHTWEIGHT_FORCE_INLINE std::optional< unsigned long long > TryGetULongLong() const noexcept
Retrieve the unsigned long long from the variant or std::nullopt.
LIGHTWEIGHT_FORCE_INLINE SqlVariant(SqlDynamicBinary< N > const &other)
Construct a new SqlVariant from a SqlDynamicBinary, holding a copy of its bytes as SqlBinary....
LIGHTWEIGHT_FORCE_INLINE SqlVariant(std::optional< T > const &other)
Copy constructor of a SqlVariant from an optional of one of the supported types.
LIGHTWEIGHT_FORCE_INLINE std::optional< SqlDynamicNumeric > TryGetNumeric() const
Retrieve the exact fixed-point decimal from the variant, or std::nullopt if NULL.
LIGHTWEIGHT_FORCE_INLINE std::optional< SqlDateTime > TryGetDateTime() const
function to get SqlDateTime from SqlVariant or std::nullopt
constexpr LIGHTWEIGHT_FORCE_INLINE SqlVariant(SqlFixedString< N, T, Mode > const &other)
Construct a new SqlVariant from a SqlFixedString.
LIGHTWEIGHT_FORCE_INLINE bool Is() const noexcept
Check if the value is of the specified type.
LIGHTWEIGHT_FORCE_INLINE T ValueOr(T &&defaultValue) const noexcept
Retrieve the value as the specified type, or return the default value if the value is NULL.
SqlVariant(SqlVariant const &)=default
Copy construct a new SqlVariant from another.
constexpr LIGHTWEIGHT_FORCE_INLINE SqlVariant(char16_t const (&text)[TextSize])
Copy constructor of a SqlVariant from a char16_t array.
LIGHTWEIGHT_FORCE_INLINE std::optional< SqlGuid > TryGetGuid() const
Retrieve the GUID from the variant or std::nullopt if the value is NULL.
LIGHTWEIGHT_FORCE_INLINE decltype(auto) Get()
Retrieve the value as the specified type.
std::optional< std::string_view > TryGetStringView() const noexcept
Retrieves a string view from the variant, or std::nullopt if the variant is NULL or holds a non-strin...
std::variant< SqlNullType, SqlGuid, bool, int8_t, short, unsigned short, int, unsigned int, long long, unsigned long long, float, double, std::string, std::string_view, std::u16string, std::u16string_view, SqlText, SqlBinary, SqlDynamicNumeric, SqlDate, SqlTime, SqlDateTime > InnerType
The inner type of the variant.
bool operator!=(SqlVariant const &other) const noexcept
Inequality comparison operator.
std::optional< std::u16string_view > TryGetUtf16StringView() const noexcept
Retrieves a UTF-16 string view from the variant, or std::nullopt if the variant is NULL or holds a no...
LIGHTWEIGHT_FORCE_INLINE SqlVariant & operator=(InnerType &&other) noexcept
Assignment operator of a SqlVariant from one of the supported types.
InnerType value
The variant value.
SqlVariant()=default
Default construct a new SqlVariant.
LIGHTWEIGHT_FORCE_INLINE std::optional< int > TryGetInt() const noexcept
Retrieve the int from the variant or std::nullopt.
LIGHTWEIGHT_FORCE_INLINE SqlVariant(StringViewLike const *newValue)
Construct from an string-like object that implements an SqlViewHelper<>.
LIGHTWEIGHT_FORCE_INLINE std::optional< SqlBinary > TryGetBinary() const
Retrieve the binary payload from the variant, or std::nullopt if the value is NULL.
LIGHTWEIGHT_FORCE_INLINE bool IsNull() const noexcept
Check if the value is NULL.
LIGHTWEIGHT_FORCE_INLINE std::optional< SqlTime > TryGetTime() const
function to get SqlTime from SqlVariant or std::nullopt
constexpr LIGHTWEIGHT_FORCE_INLINE SqlVariant(char const (&text)[TextSize])
Copy constructor of a SqlVariant from a char array.
LIGHTWEIGHT_FORCE_INLINE SqlVariant & operator=(StringViewLike const *newValue) noexcept
Assign from an string-like object that implements an SqlViewHelper<>.
bool operator==(SqlVariant const &other) const noexcept
Equality comparison operator.
LIGHTWEIGHT_FORCE_INLINE std::optional< SqlDate > TryGetDate() const
function to get SqlDate from SqlVariant or std::nullopt
LIGHTWEIGHT_FORCE_INLINE std::optional< short > TryGetShort() const noexcept
Retrieve the unsigned short from the variant or std::nullopt.
LIGHTWEIGHT_FORCE_INLINE std::optional< unsigned short > TryGetUShort() const noexcept
Retrieve the unsigned short from the variant or std::nullopt.
LIGHTWEIGHT_FORCE_INLINE std::optional< bool > TryGetBool() const noexcept
Retrieve the bool from the variant or std::nullopt.
LIGHTWEIGHT_FORCE_INLINE std::optional< int8_t > TryGetInt8() const noexcept
Retrieve the int8_t from the variant or std::nullopt.
SqlVariant(SqlVariant &&) noexcept=default
Move construct a new SqlVariant from another.
LIGHTWEIGHT_FORCE_INLINE std::optional< long long > TryGetLongLong() const noexcept
Retrieve the long long from the variant or std::nullopt.
LIGHTWEIGHT_FORCE_INLINE SqlVariant & operator=(InnerType const &other)
Assignment operator of a SqlVariant from one of the supported types.
LIGHTWEIGHT_FORCE_INLINE std::optional< unsigned int > TryGetUInt() const noexcept
Retrieve the unsigned int from the variant or std::nullopt.