Zserio C++17 runtime library  0.5.0
Built for Zserio 2.17.0
SqliteUtil.h
Go to the documentation of this file.
1 #ifndef ZSERIO_SQLITE_UTIL_H_INC
2 #define ZSERIO_SQLITE_UTIL_H_INC
3 
4 #include "zserio/Bitmasks.h"
5 #include "zserio/Enums.h"
6 #include "zserio/Optional.h"
7 #include "zserio/SerializeUtil.h"
8 #include "zserio/Span.h"
9 #include "zserio/Traits.h"
10 
11 #include "sqlite3.h"
12 
13 namespace zserio
14 {
15 namespace detail
16 {
17 
21 template <typename T>
22 struct SqlRow;
23 
24 template <typename T, typename = void>
25 struct ColumnTraits;
26 
27 template <typename T>
28 struct ColumnTraits<T, std::enable_if_t<is_complete_v<View<T>>>>
29 {
30  static constexpr std::string_view TYPE_NAME = "BLOB";
31  static constexpr int TYPE = SQLITE_BLOB;
32 };
33 
34 template <typename T>
35 struct ColumnTraits<T, std::enable_if_t<std::is_enum_v<T> || is_bitmask_v<T>>>
36 {
37  static constexpr std::string_view TYPE_NAME = "INTEGER";
38  static constexpr int TYPE = SQLITE_INTEGER;
39 };
40 
41 template <typename T>
42 struct ColumnTraits<T, std::enable_if_t<is_numeric_wrapper_v<T> && std::is_integral_v<typename T::ValueType>>>
43 {
44  static constexpr std::string_view TYPE_NAME = "INTEGER";
45  static constexpr int TYPE = SQLITE_INTEGER;
46 };
47 
48 template <typename T>
49 struct ColumnTraits<T,
50  std::enable_if_t<is_numeric_wrapper_v<T> && std::is_floating_point_v<typename T::ValueType>>>
51 {
52  static constexpr std::string_view TYPE_NAME = "REAL";
53  static constexpr int TYPE = SQLITE_FLOAT;
54 };
55 
56 template <typename ALLOC>
57 struct ColumnTraits<BasicString<ALLOC>>
58 {
59  static constexpr std::string_view TYPE_NAME = "TEXT";
60  static constexpr int TYPE = SQLITE_TEXT;
61 };
62 
63 template <typename ALLOC, typename T, typename... ARGS>
64 std::enable_if_t<is_complete_v<View<T>>> readColumn(
65  BasicOptional<ALLOC, T>& column, sqlite3_stmt& stmt, int index, const ARGS&... args)
66 {
67  // blob
68  const void* blobDataPtr = sqlite3_column_blob(&stmt, index);
69  const int blobDataLength = sqlite3_column_bytes(&stmt, index);
70  Span<const uint8_t> blobData(static_cast<const uint8_t*>(blobDataPtr), static_cast<size_t>(blobDataLength));
71  column.emplace();
72  deserializeFromBytes(blobData, *column, args...);
73 }
74 
75 template <typename ALLOC, typename T>
76 std::enable_if_t<std::is_enum_v<T>> readColumn(BasicOptional<ALLOC, T>& column, sqlite3_stmt& stmt, int index)
77 {
78  const int64_t intValue = sqlite3_column_int64(&stmt, index);
79  column = valueToEnum<T>(static_cast<std::underlying_type_t<T>>(intValue));
80 }
81 
82 template <typename ALLOC, typename T>
83 std::enable_if_t<is_bitmask_v<T>> readColumn(BasicOptional<ALLOC, T>& column, sqlite3_stmt& stmt, int index)
84 {
85  const int64_t intValue = sqlite3_column_int64(&stmt, index);
86  column = T(static_cast<typename T::ZserioType::ValueType>(intValue));
87 }
88 
89 template <typename ALLOC>
90 void readColumn(BasicOptional<ALLOC, Bool>& column, sqlite3_stmt& stmt, int index)
91 {
92  const int64_t intValue = sqlite3_column_int64(&stmt, index);
93  column = intValue != 0;
94 }
95 
96 template <typename ALLOC, BitSize BIT_SIZE, bool IS_SIGNED>
97 void readColumn(
98  BasicOptional<ALLOC, FixedIntWrapper<BIT_SIZE, IS_SIGNED>>& column, sqlite3_stmt& stmt, int index)
99 {
100  const int64_t intValue = sqlite3_column_int64(&stmt, index);
101  column = static_cast<typename FixedIntWrapper<BIT_SIZE, IS_SIGNED>::ValueType>(intValue);
102 }
103 
104 template <typename ALLOC, typename T>
105 void readColumn(BasicOptional<ALLOC, DynIntWrapper<T>>& column, sqlite3_stmt& stmt, int index)
106 {
107  const int64_t intValue = sqlite3_column_int64(&stmt, index);
108  column = static_cast<T>(intValue);
109 }
110 
111 template <typename ALLOC, typename VALUE_TYPE, VarIntType VAR_TYPE>
112 void readColumn(
113  BasicOptional<ALLOC, VarIntWrapper<VALUE_TYPE, VAR_TYPE>>& column, sqlite3_stmt& stmt, int index)
114 {
115  const int64_t intValue = sqlite3_column_int64(&stmt, index);
116  column = static_cast<VALUE_TYPE>(intValue);
117 }
118 
119 template <typename ALLOC, typename VALUE_TYPE, FloatType FLOAT_TYPE>
120 void readColumn(
121  BasicOptional<ALLOC, FloatWrapper<VALUE_TYPE, FLOAT_TYPE>>& column, sqlite3_stmt& stmt, int index)
122 {
123  const double doubleValue = sqlite3_column_double(&stmt, index);
124  column = static_cast<VALUE_TYPE>(doubleValue);
125 }
126 
127 template <typename ALLOC>
128 void readColumn(
129  BasicOptional<ALLOC, BasicString<RebindAlloc<ALLOC, char>>>& column, sqlite3_stmt& stmt, int index)
130 {
131  const unsigned char* textValue = sqlite3_column_text(&stmt, index);
132  column.emplace(reinterpret_cast<const char*>(textValue));
133 }
134 
135 template <typename T>
136 BitSize prepareColumn(const View<T>& view)
137 {
138  validate(view);
139  return initializeOffsets(view, 0);
140 }
141 
142 template <typename T>
143 BitSize prepareColumn(const T&)
144 {
145  return 0;
146 }
147 
148 template <typename ALLOC, typename T>
149 int bindColumn(sqlite3_stmt& stmt, int index, const View<T>& view, BitSize bitSize, const ALLOC& allocator)
150 {
151  BasicBitBuffer<ALLOC> bitBuffer(bitSize, allocator);
152  BitStreamWriter writer(bitBuffer);
153  write(writer, view);
154  return sqlite3_bind_blob(
155  &stmt, index, bitBuffer.getBuffer(), static_cast<int>(bitBuffer.getByteSize()), SQLITE_TRANSIENT);
156 }
157 
158 template <typename ALLOC, typename T>
159 std::enable_if_t<std::is_enum_v<T>, int> bindColumn(
160  sqlite3_stmt& stmt, int index, T value, BitSize, const ALLOC&)
161 {
162  return sqlite3_bind_int64(&stmt, index, static_cast<int64_t>(value));
163 }
164 
165 template <typename ALLOC, typename T>
166 std::enable_if_t<is_bitmask_v<T>, int> bindColumn(sqlite3_stmt& stmt, int index, T value, BitSize, const ALLOC&)
167 {
168  return sqlite3_bind_int64(&stmt, index, static_cast<int64_t>(value.getValue()));
169 }
170 
171 template <typename ALLOC>
172 int bindColumn(sqlite3_stmt& stmt, int index, Bool value, BitSize, const ALLOC&)
173 {
174  return sqlite3_bind_int64(&stmt, index, static_cast<int64_t>(value));
175 }
176 
177 template <typename ALLOC, BitSize BIT_SIZE, bool IS_SIGNED>
178 int bindColumn(sqlite3_stmt& stmt, int index, FixedIntWrapper<BIT_SIZE, IS_SIGNED> value, BitSize, const ALLOC&)
179 {
180  return sqlite3_bind_int64(&stmt, index, static_cast<int64_t>(value));
181 }
182 
183 template <typename ALLOC, typename T>
184 int bindColumn(sqlite3_stmt& stmt, DynIntWrapper<T> value, BitSize, int index, const ALLOC&)
185 {
186  return sqlite3_bind_int64(&stmt, index, static_cast<int64_t>(value));
187 }
188 
189 template <typename ALLOC, typename VALUE_TYPE, VarIntType VAR_TYPE>
190 int bindColumn(sqlite3_stmt& stmt, int index, VarIntWrapper<VALUE_TYPE, VAR_TYPE> value, BitSize, const ALLOC&)
191 {
192  return sqlite3_bind_int64(&stmt, index, static_cast<int64_t>(value));
193 }
194 
195 template <typename ALLOC, typename VALUE_TYPE, FloatType FLOAT_TYPE>
196 int bindColumn(sqlite3_stmt& stmt, int index, FloatWrapper<VALUE_TYPE, FLOAT_TYPE> value, BitSize, const ALLOC&)
197 {
198  return sqlite3_bind_double(&stmt, index, static_cast<double>(value));
199 }
200 
201 template <typename ALLOC>
202 int bindColumn(sqlite3_stmt& stmt, int index, std::string_view value, BitSize, const ALLOC&)
203 {
204  return sqlite3_bind_text(&stmt, index, value.data(), static_cast<int>(value.size()), SQLITE_TRANSIENT);
205 }
206 
207 } // namespace detail
208 } // namespace zserio
209 
210 #endif // ZSERIO_SQLITE_UTIL_H_INC
Definition: BitBuffer.h:602
View< T > deserializeFromBytes(Span< const uint8_t > buffer, T &data, ARGS &&... arguments)
detail::BoolWrapper Bool
Definition: Types.h:732
unsigned int BitSize
Definition: BitSize.h:8
std::basic_string< char, std::char_traits< char >, ALLOC > BasicString
Definition: String.h:17