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