Lightweight 0.20251202.0
Loading...
Searching...
No Matches
SqlBinary.hpp
1// SPDX-License-Identifier: Apache-2.0
2
3#pragma once
4
5#include "../SqlColumnTypeDefinitions.hpp"
6#include "BasicStringBinder.hpp"
7#include "Core.hpp"
8
9#include <cassert>
10#include <cstdint>
11#include <utility>
12#include <vector>
13
14namespace Lightweight
15{
16
17/// @brief Represents a binary data type.
18///
19/// This class is a thin wrapper around std::vector<uint8_t> to represent binary data types efficiently.
20///
21/// @ingroup DataTypes
22class SqlBinary final: public std::vector<uint8_t>
23{
24 public:
25 using std::vector<uint8_t>::vector;
26
27 constexpr auto operator<=>(SqlBinary const&) const noexcept = default;
28
29 private:
30 friend struct SqlDataBinder<SqlBinary>;
31
32 mutable SQLLEN _indicator = 0;
33};
34
35template <>
36struct SqlDataBinder<SqlBinary>
37{
38 static constexpr auto ColumnType = SqlColumnTypeDefinitions::Binary { 255 };
39
40 static LIGHTWEIGHT_FORCE_INLINE SQLRETURN InputParameter(SQLHSTMT stmt,
41 SQLUSMALLINT column,
42 SqlBinary const& value,
43 SqlDataBinderCallback& /*cb*/) noexcept
44 {
45 value._indicator = static_cast<SQLLEN>(value.size());
46 return SQLBindParameter(stmt,
47 column,
48 SQL_PARAM_INPUT,
49 SQL_C_BINARY,
50 SQL_LONGVARBINARY,
51 value.size(),
52 0,
53 (SQLPOINTER) value.data(),
54 0,
55 &value._indicator);
56 }
57
58 static LIGHTWEIGHT_FORCE_INLINE SQLRETURN OutputColumn(
59 SQLHSTMT stmt, SQLUSMALLINT column, SqlBinary* result, SQLLEN* indicator, SqlDataBinderCallback& cb) noexcept
60 {
61 if (result->empty())
62 result->resize(255);
63
64 cb.PlanPostProcessOutputColumn([stmt, column, result, indicator]() {
65 if (*indicator == SQL_NULL_DATA)
66 // The data is NULL.
67 result->clear();
68 else if (*indicator == SQL_NO_TOTAL)
69 // We have a truncation and the server does not know how much data is left.
70 result->resize(result->size() - 1);
71 else if (std::cmp_less_equal(*indicator, static_cast<SQLLEN>(result->size())))
72 result->resize(static_cast<size_t>(*indicator));
73 else
74 {
75 // We have a truncation and the server knows how much data is left.
76 // Extend the buffer and fetch the rest via SQLGetData.
77
78 auto const totalCharsRequired = *indicator;
79 result->resize(static_cast<size_t>(totalCharsRequired) + 1);
80 auto const sqlResult =
81 SQLGetData(stmt, column, SQL_C_BINARY, (SQLPOINTER) result->data(), totalCharsRequired + 1, indicator);
82 (void) sqlResult;
83 assert(SQL_SUCCEEDED(sqlResult));
84 assert(*indicator == totalCharsRequired);
85 result->resize(static_cast<size_t>(totalCharsRequired));
86 }
87 });
88
89 return SQLBindCol(stmt, column, SQL_C_BINARY, (SQLPOINTER) result->data(), 255, indicator);
90 }
91
92 static LIGHTWEIGHT_FORCE_INLINE SQLRETURN GetColumn(SQLHSTMT stmt,
93 SQLUSMALLINT column,
94 SqlBinary* result,
95 SQLLEN* indicator,
96 SqlDataBinderCallback const& /*cb*/) noexcept
97 {
98 if (result->empty())
99 result->resize(255);
100
101 return detail::GetRawColumnArrayData<SQL_C_BINARY>(stmt, column, result, indicator);
102 }
103
104 static LIGHTWEIGHT_FORCE_INLINE std::string Inspect(SqlBinary const& value)
105 {
106 return std::format("SqlBinary(size={})", value.size());
107 }
108};
109
110} // namespace Lightweight
Represents a binary data type.
Definition SqlBinary.hpp:23