5#include "../DataBinder/UnicodeConverter.hpp"
6#include "../SqlLogger.hpp"
8#include "Primitives.hpp"
9#include "SqlBinary.hpp"
11#include "SqlDateTime.hpp"
12#include "SqlDynamicBinary.hpp"
13#include "SqlDynamicNumeric.hpp"
14#include "SqlFixedString.hpp"
16#include "SqlNullValue.hpp"
19#include "StdString.hpp"
20#include "StdStringView.hpp"
31 template <
class... Ts>
32 struct overloaded: Ts...
34 using Ts::operator()...;
37 template <
class... Ts>
38 overloaded(Ts...) -> overloaded<Ts...>;
99 value(std::move(other))
104 template <std::
size_t N,
typename T =
char, SqlFixedStringMode Mode>
106 value { std::string { other.data(), other.size() } }
113 template <std::
size_t N>
120 template <std::
size_t TextSize>
121 constexpr LIGHTWEIGHT_FORCE_INLINE
SqlVariant(
char const (&text)[TextSize]):
122 value { std::string_view { text, TextSize - 1 } }
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 } }
134 template <
typename T>
135 LIGHTWEIGHT_FORCE_INLINE
SqlVariant(std::optional<T>
const& other):
150 value = std::move(other);
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) }
162 template <detail::HasSqlViewHelper StringViewLike>
165 value = std::string_view(newValue->GetString(), newValue->GetLength());
170 [[nodiscard]] LIGHTWEIGHT_FORCE_INLINE
bool IsNull() const noexcept
172 return std::holds_alternative<SqlNullType>(
value);
176 template <
typename T>
177 [[nodiscard]] LIGHTWEIGHT_FORCE_INLINE
bool Is() const noexcept
179 return std::holds_alternative<T>(
value);
190 template <
typename T>
191 [[nodiscard]] LIGHTWEIGHT_FORCE_INLINE
decltype(
auto)
Get()
193 if constexpr (IsSpecializationOf<std::optional, T>)
196 return T { std::nullopt };
198 return T { std::get<typename T::value_type>(
value) };
200 else if constexpr (std::is_floating_point_v<T>)
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));
206 else if constexpr (std::is_same_v<T, std::string>)
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));
215 return std::get<T>(
value);
224 template <
typename T>
225 [[nodiscard]] LIGHTWEIGHT_FORCE_INLINE T
ValueOr(T&& defaultValue)
const noexcept
227 if constexpr (std::is_integral_v<T>)
228 return TryGetIntegral<T>().value_or(std::forward<T>(defaultValue));
231 return std::forward<T>(defaultValue);
233 if constexpr (std::is_floating_point_v<T>)
235 if (
auto const* numeric = std::get_if<SqlDynamicNumeric>(&
value))
236 return static_cast<T
>(numeric->ToDouble());
238 else if constexpr (std::is_same_v<std::remove_cvref_t<T>, std::string>)
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());
249 if (
auto const* held = std::get_if<std::remove_cvref_t<T>>(&
value))
252 return std::forward<T>(defaultValue);
257 [[nodiscard]] LIGHTWEIGHT_FORCE_INLINE std::optional<bool>
TryGetBool() const noexcept {
return TryGetIntegral<bool>(); }
259 [[nodiscard]] LIGHTWEIGHT_FORCE_INLINE std::optional<int8_t>
TryGetInt8() const noexcept {
return TryGetIntegral<int8_t>(); }
261 [[nodiscard]] LIGHTWEIGHT_FORCE_INLINE std::optional<short>
TryGetShort() const noexcept {
return TryGetIntegral<short>(); }
263 [[nodiscard]] LIGHTWEIGHT_FORCE_INLINE std::optional<unsigned short>
TryGetUShort() const noexcept {
return TryGetIntegral<unsigned short>(); }
265 [[nodiscard]] LIGHTWEIGHT_FORCE_INLINE std::optional<int>
TryGetInt() const noexcept {
return TryGetIntegral<int>(); }
267 [[nodiscard]] LIGHTWEIGHT_FORCE_INLINE std::optional<unsigned int>
TryGetUInt() const noexcept {
return TryGetIntegral<unsigned int>(); }
269 [[nodiscard]] LIGHTWEIGHT_FORCE_INLINE std::optional<long long>
TryGetLongLong() const noexcept {
return TryGetIntegral<long long>(); }
271 [[nodiscard]] LIGHTWEIGHT_FORCE_INLINE std::optional<unsigned long long>
TryGetULongLong() const noexcept {
return TryGetIntegral<unsigned long long>(); }
279 template <
typename ResultType>
280 [[nodiscard]] std::optional<ResultType> TryGetIntegral() const noexcept
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); },
290 [](SqlDynamicNumeric
const& v) -> std::optional<ResultType> {
293 return static_cast<ResultType
>(v.unscaledValue);
295 [](
auto) -> std::optional<ResultType> {
return std::nullopt; }
309 using Result = std::optional<std::string_view>;
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()); },
317 [](
SqlBinary const& v) -> Result {
return std::string_view(
reinterpret_cast<char const*
>(v.data()), v.size()); },
318 [](
auto const&) -> Result {
return std::nullopt; }
331 using Result = std::optional<std::u16string_view>;
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; }
342 [[nodiscard]] LIGHTWEIGHT_FORCE_INLINE std::optional<SqlDate>
TryGetDate()
const
347 if (
auto const* date = std::get_if<SqlDate>(&
value))
350 if (
auto const* datetime = std::get_if<SqlDateTime>(&
value))
352 return SqlDate { std::chrono::year(datetime->sqlValue.year),
353 std::chrono::month(datetime->sqlValue.month),
354 std::chrono::day(datetime->sqlValue.day) };
357 throw std::bad_variant_access();
363 return ToString() == other.ToString();
369 return !(*
this == other);
373 [[nodiscard]] LIGHTWEIGHT_FORCE_INLINE std::optional<SqlTime>
TryGetTime()
const
378 if (
auto const* time = std::get_if<SqlTime>(&
value))
381 if (
auto const* datetime = std::get_if<SqlDateTime>(&
value))
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) };
389 throw std::bad_variant_access();
393 [[nodiscard]] LIGHTWEIGHT_FORCE_INLINE std::optional<SqlDateTime>
TryGetDateTime()
const
398 if (
auto const* dateTime = std::get_if<SqlDateTime>(&
value))
401 throw std::bad_variant_access();
405 [[nodiscard]] LIGHTWEIGHT_FORCE_INLINE std::optional<SqlGuid>
TryGetGuid()
const
410 if (
auto const* guid = std::get_if<SqlGuid>(&
value))
413 throw std::bad_variant_access();
422 [[nodiscard]] LIGHTWEIGHT_FORCE_INLINE std::optional<SqlDynamicNumeric>
TryGetNumeric()
const
427 if (
auto const* numeric = std::get_if<SqlDynamicNumeric>(&
value))
430 throw std::bad_variant_access();
439 [[nodiscard]] LIGHTWEIGHT_FORCE_INLINE std::optional<SqlBinary>
TryGetBinary()
const
444 if (
auto const* binary = std::get_if<SqlBinary>(&
value))
447 throw std::bad_variant_access();
451 [[nodiscard]] LIGHTWEIGHT_API std::string
ToString()
const;
455using SqlVariantRow = std::vector<SqlVariant>;
458struct LIGHTWEIGHT_API SqlDataBinder<
SqlVariant>
460 static SQLRETURN InputParameter(SQLHSTMT stmt,
465 static SQLRETURN GetColumn(
468 static LIGHTWEIGHT_FORCE_INLINE std::string Inspect(
SqlVariant const& value)
noexcept
477struct std::formatter<Lightweight::SqlVariant>: formatter<string>
481 return std::formatter<string>::format(value.ToString(), ctx);
Represents a binary data type.
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.