include/simdb/
Coverage:
low: ≥ 0%
medium: ≥ 75.0%
high: ≥ 90.0%
Lines:
166 / 169
98.2%
Branches:
74 / 165
44.8%
Functions:
51 / 51
100.0%

sqlite/Iterator.hpp
Line Branch Exec Source
1 // <Iterator.hpp> -*- C++ -*-
2
3 #pragma once
4
5 #include "simdb/Assert.hpp"
6 #include "simdb/sqlite/Transaction.hpp"
7 #include "simdb/utils/utf16.hpp"
8
9 #include <memory>
10 #include <optional>
11 #include <sqlite3.h>
12 #include <string.h>
13 #include <string>
14 #include <type_traits>
15 #include <vector>
16
17 namespace simdb {
18
19 namespace detail {
20 template <typename T> struct unrolled_type
21 {
22 using type = T;
23 };
24
25 template <typename T> struct unrolled_type<std::optional<T>>
26 {
27 using type = T;
28 };
29
30 template <typename T> using unrolled_type_t = typename unrolled_type<T>::type;
31
32 template <typename T1, typename T2>
33 struct unrolled_is_same
34 : std::conditional_t<std::is_same_v<unrolled_type_t<T1>, unrolled_type_t<T2>>, std::true_type, std::false_type>
35 {
36 };
37
38 template <typename T1, typename T2> inline constexpr bool unrolled_is_same_v = unrolled_is_same<T1, T2>::value;
39
40 template <typename T> struct is_optional : std::false_type
41 {
42 };
43
44 template <typename T> struct is_optional<std::optional<T>> : std::true_type
45 {
46 };
47
48 template <typename T> inline constexpr bool is_optional_v = is_optional<T>::value;
49
50 197369 inline bool columnIsNull(sqlite3_stmt* stmt, const int idx)
51 {
52 197369 return sqlite3_column_type(stmt, idx) == SQLITE_NULL;
53 }
54
55 107214 inline void requireNonNullColumn(sqlite3_stmt* stmt, const int idx, const std::string& col_name)
56 {
57
14/14
✓ Branch 3 → 4 taken 2 times.
✓ Branch 3 → 24 taken 107212 times.
✓ Branch 6 → 7 taken 2 times.
✓ Branch 7 → 8 taken 2 times.
✓ Branch 9 → 10 taken 2 times.
✓ Branch 13 → 14 taken 2 times.
✓ Branch 14 → 15 taken 2 times.
✓ Branch 15 → 16 taken 2 times.
✓ Branch 16 → 17 taken 2 times.
✓ Branch 17 → 18 taken 2 times.
✓ Branch 18 → 19 taken 2 times.
✓ Branch 19 → 20 taken 2 times.
✓ Branch 20 → 21 taken 2 times.
✓ Branch 22 → 23 taken 2 times.
107218 simdb_assert(!columnIsNull(stmt, idx), "Column '" << col_name << "' is NULL; use std::optional overload");
58 107212 }
59 } // namespace detail
60
61 /*!
62 * \class ResultWriterBase
63 *
64 * \brief Base class for all SELECT objects that are responsible for
65 * writing record values to the user's local variables whenever
66 * a query's result set iterator is advanced.
67 */
68 class ResultWriterBase
69 {
70 public:
71 /// Destroy
72 39188 virtual ~ResultWriterBase() = default;
73
74 /// Read the value for the prepared statement at the given column index
75 /// and copy it to the user's local variable.
76 virtual void writeToUserVar(sqlite3_stmt* stmt, const int idx) const = 0;
77
78 /// Return a new copy of this writer.
79 virtual ResultWriterBase* clone() const = 0;
80
81 /// \brief Return the column name for this writer.
82 ///
83 /// Used when creating the query's prepared statement:
84 /// SELECT ColA,ColB FROM Table WHERE Id=44 AND Name='foo'
85 146433 const std::string& getColName() const { return col_name_; }
86
87 protected:
88 39188 ResultWriterBase(const char* col_name) :
89
1/1
✓ Branch 4 → 5 taken 39188 times.
78376 col_name_(col_name)
90 {
91 39188 }
92
93 private:
94 std::string col_name_;
95 };
96
97 /*!
98 * \class ResultWriterInt32
99 *
100 * \brief Responsible for writing int32 record values to the user's local
101 * variables whenever a query's result set iterator is advanced.
102 */
103 template <typename IntT = int32_t> class ResultWriterInt32 : public ResultWriterBase
104 {
105 static_assert(detail::unrolled_is_same_v<IntT, int32_t>);
106
107 public:
108 /// \brief Construction
109 /// \param col_name Name of the selected column
110 /// \param user_var Pointer to the local variable where result values are
111 /// written to
112 22431 ResultWriterInt32(const char* col_name, IntT* user_var) :
113 ResultWriterBase(col_name),
114 22431 user_var_(user_var)
115 {
116 22431 }
117
118 /// Read the value for the prepared statement at the given column index
119 /// and copy it to the user's local variable.
120 8332 void writeToUserVar(sqlite3_stmt* stmt, const int idx) const override
121 {
122 if constexpr (detail::is_optional_v<IntT>)
123 {
124
2/2
✓ Branch 3 → 4 taken 1 time.
✓ Branch 3 → 6 taken 12 times.
13 if (detail::columnIsNull(stmt, idx))
125 {
126 1 *user_var_ = std::nullopt;
127 1 return;
128 }
129 } else
130 {
131 8319 detail::requireNonNullColumn(stmt, idx, getColName());
132 }
133
134
1/1
✓ Branch 6 → 7 taken 12 times.
8331 *user_var_ = sqlite3_column_int(stmt, idx);
135 8319 }
136
137 /// Return a new copy of this writer.
138
2/6
simdb::ResultWriterInt32<std::optional<int> >::clone() const:
✓ Branch 5 → 6 taken 17 times.
✗ Branch 8 → 9 not taken.
✗ Branch 8 → 10 not taken.
simdb::ResultWriterInt32<int>::clone() const:
✓ Branch 5 → 6 taken 11202 times.
✗ Branch 8 → 9 not taken.
✗ Branch 8 → 10 not taken.
11219 ResultWriterBase* clone() const override { return new ResultWriterInt32<IntT>(getColName().c_str(), user_var_); }
139
140 private:
141 IntT* user_var_;
142 };
143
144 /*!
145 * \class ResultWriterUInt32
146 *
147 * \brief Responsible for writing uint32 record values to the user's local
148 * variables whenever a query's result set iterator is advanced.
149 */
150 template <typename UIntT = uint32_t> class ResultWriterUInt32 : public ResultWriterBase
151 {
152 static_assert(detail::unrolled_is_same_v<UIntT, uint32_t>);
153
154 public:
155 /// \brief Construction
156 /// \param col_name Name of the selected column
157 /// \param user_var Pointer to the local variable where result values are
158 /// written to
159 45 ResultWriterUInt32(const char* col_name, UIntT* user_var) :
160 ResultWriterBase(col_name),
161 45 user_var_(user_var)
162 {
163 45 }
164
165 /// Read the value for the prepared statement at the given column index
166 /// and copy it to the user's local variable.
167 89805 void writeToUserVar(sqlite3_stmt* stmt, const int idx) const override
168 {
169 if constexpr (detail::is_optional_v<UIntT>)
170 {
171
2/2
✓ Branch 3 → 4 taken 3 times.
✓ Branch 3 → 6 taken 1 time.
4 if (detail::columnIsNull(stmt, idx))
172 {
173 3 *user_var_ = std::nullopt;
174 3 return;
175 }
176 } else
177 {
178 89801 detail::requireNonNullColumn(stmt, idx, getColName());
179 }
180
181 89801 sqlite3_int64 tmp = sqlite3_column_int64(stmt, idx);
182
183
6/32
simdb::ResultWriterUInt32<std::optional<unsigned int> >::writeToUserVar(sqlite3_stmt*, int) const:
✓ Branch 7 → 8 taken 1 time.
✗ Branch 7 → 9 not taken.
✗ Branch 8 → 9 not taken.
✓ Branch 8 → 10 taken 1 time.
✗ Branch 11 → 12 not taken.
✓ Branch 11 → 30 taken 1 time.
✗ Branch 14 → 15 not taken.
✗ Branch 15 → 16 not taken.
✗ Branch 17 → 18 not taken.
✗ Branch 21 → 22 not taken.
✗ Branch 22 → 23 not taken.
✗ Branch 23 → 24 not taken.
✗ Branch 24 → 25 not taken.
✗ Branch 25 → 26 not taken.
✗ Branch 26 → 27 not taken.
✗ Branch 28 → 29 not taken.
simdb::ResultWriterUInt32<unsigned int>::writeToUserVar(sqlite3_stmt*, int) const:
✓ Branch 5 → 6 taken 89800 times.
✗ Branch 5 → 7 not taken.
✗ Branch 6 → 7 not taken.
✓ Branch 6 → 8 taken 89800 times.
✗ Branch 9 → 10 not taken.
✓ Branch 9 → 28 taken 89800 times.
✗ Branch 12 → 13 not taken.
✗ Branch 13 → 14 not taken.
✗ Branch 15 → 16 not taken.
✗ Branch 19 → 20 not taken.
✗ Branch 20 → 21 not taken.
✗ Branch 21 → 22 not taken.
✗ Branch 22 → 23 not taken.
✗ Branch 23 → 24 not taken.
✗ Branch 24 → 25 not taken.
✗ Branch 26 → 27 not taken.
89801 simdb_assert(tmp >= 0 && tmp <= UINT32_MAX, "Value out of range for uint32_t");
184
185 89801 *user_var_ = static_cast<uint32_t>(tmp);
186 89800 }
187
188 /// Return a new copy of this writer.
189
2/6
simdb::ResultWriterUInt32<std::optional<unsigned int> >::clone() const:
✓ Branch 5 → 6 taken 4 times.
✗ Branch 8 → 9 not taken.
✗ Branch 8 → 10 not taken.
simdb::ResultWriterUInt32<unsigned int>::clone() const:
✓ Branch 5 → 6 taken 22 times.
✗ Branch 8 → 9 not taken.
✗ Branch 8 → 10 not taken.
26 ResultWriterBase* clone() const override { return new ResultWriterUInt32<UIntT>(getColName().c_str(), user_var_); }
190
191 private:
192 UIntT* user_var_;
193 };
194
195 /*!
196 * \class ResultWriterInt64
197 *
198 * \brief Responsible for writing int64 record values to the user's local
199 * variables whenever a query's result set iterator is advanced.
200 */
201 template <typename IntT = int64_t> class ResultWriterInt64 : public ResultWriterBase
202 {
203 static_assert(detail::unrolled_is_same_v<IntT, int64_t>);
204
205 public:
206 /// \brief Construction
207 /// \param col_name Name of the selected column
208 /// \param user_var Pointer to the local variable where result values are
209 /// written to
210 43 ResultWriterInt64(const char* col_name, IntT* user_var) :
211 ResultWriterBase(col_name),
212 43 user_var_(user_var)
213 {
214 43 }
215
216 /// Read the value for the prepared statement at the given column index
217 /// and copy it to the user's local variable.
218 6058 void writeToUserVar(sqlite3_stmt* stmt, const int idx) const override
219 {
220 if constexpr (detail::is_optional_v<IntT>)
221 {
222
2/2
✓ Branch 3 → 4 taken 3 times.
✓ Branch 3 → 6 taken 1 time.
4 if (detail::columnIsNull(stmt, idx))
223 {
224 3 *user_var_ = std::nullopt;
225 3 return;
226 }
227 } else
228 {
229 6054 detail::requireNonNullColumn(stmt, idx, getColName());
230 }
231
232
1/1
✓ Branch 6 → 7 taken 1 time.
6055 *user_var_ = sqlite3_column_int64(stmt, idx);
233 6054 }
234
235 /// Return a new copy of this writer.
236
2/6
simdb::ResultWriterInt64<std::optional<long> >::clone() const:
✓ Branch 5 → 6 taken 1 time.
✗ Branch 8 → 9 not taken.
✗ Branch 8 → 10 not taken.
simdb::ResultWriterInt64<long>::clone() const:
✓ Branch 5 → 6 taken 24 times.
✗ Branch 8 → 9 not taken.
✗ Branch 8 → 10 not taken.
25 ResultWriterBase* clone() const override { return new ResultWriterInt64<IntT>(getColName().c_str(), user_var_); }
237
238 private:
239 IntT* user_var_;
240 };
241
242 /*!
243 * \class ResultWriterUInt64
244 *
245 * \brief Responsible for writing uint64 record values to the user's local
246 * variables whenever a query's result set iterator is advanced.
247 */
248 template <typename UIntT = uint64_t> class ResultWriterUInt64 : public ResultWriterBase
249 {
250 static_assert(detail::unrolled_is_same_v<UIntT, uint64_t>);
251
252 public:
253 /// \brief Construction
254 /// \param col_name Name of the selected column
255 /// \param user_var Pointer to the local variable where result values are
256 /// written to
257 30 ResultWriterUInt64(const char* col_name, UIntT* user_var) :
258 ResultWriterBase(col_name),
259 30 user_var_(user_var)
260 {
261 30 }
262
263 /// Read the value for the prepared statement at the given column index
264 /// and copy it to the user's local variable.
265 3026 void writeToUserVar(sqlite3_stmt* stmt, const int idx) const override
266 {
267 if constexpr (detail::is_optional_v<UIntT>)
268 {
269
2/2
✓ Branch 3 → 4 taken 2 times.
✓ Branch 3 → 6 taken 2 times.
4 if (detail::columnIsNull(stmt, idx))
270 {
271 2 *user_var_ = std::nullopt;
272 2 return;
273 }
274 } else
275 {
276 3022 detail::requireNonNullColumn(stmt, idx, getColName());
277 }
278
279 3023 const void* blob = sqlite3_column_text16(stmt, idx);
280
6/12
simdb::ResultWriterUInt64<std::optional<unsigned long> >::writeToUserVar(sqlite3_stmt*, int) const:
✓ Branch 8 → 9 taken 2 times.
✗ Branch 8 → 11 not taken.
✓ Branch 9 → 10 taken 2 times.
✗ Branch 9 → 11 not taken.
✓ Branch 12 → 13 taken 2 times.
✗ Branch 12 → 16 not taken.
simdb::ResultWriterUInt64<unsigned long>::writeToUserVar(sqlite3_stmt*, int) const:
✓ Branch 6 → 7 taken 3021 times.
✗ Branch 6 → 9 not taken.
✓ Branch 7 → 8 taken 3021 times.
✗ Branch 7 → 9 not taken.
✓ Branch 10 → 11 taken 3021 times.
✗ Branch 10 → 13 not taken.
3023 if (sqlite3_column_type(stmt, idx) == SQLITE_TEXT && blob != nullptr)
281 {
282 3023 const char16_t* utf16str = static_cast<const char16_t*>(blob);
283
1/1
✓ Branch 13 → 14 taken 2 times.
3023 *user_var_ = utils::utf16_to_uint64(utf16str, 20);
284 } else
285 {
286
0/2
simdb::ResultWriterUInt64<std::optional<unsigned long> >::writeToUserVar(sqlite3_stmt*, int) const:
✗ Branch 18 → 19 not taken.
simdb::ResultWriterUInt64<unsigned long>::writeToUserVar(sqlite3_stmt*, int) const:
✗ Branch 15 → 16 not taken.
✗ throw DBException("Invalid data / data type");
287 }
288 3021 }
289
290 /// Return a new copy of this writer.
291
2/6
simdb::ResultWriterUInt64<std::optional<unsigned long> >::clone() const:
✓ Branch 5 → 6 taken 2 times.
✗ Branch 8 → 9 not taken.
✗ Branch 8 → 10 not taken.
simdb::ResultWriterUInt64<unsigned long>::clone() const:
✓ Branch 5 → 6 taken 13 times.
✗ Branch 8 → 9 not taken.
✗ Branch 8 → 10 not taken.
15 ResultWriterBase* clone() const override { return new ResultWriterUInt64<UIntT>(getColName().c_str(), user_var_); }
292
293 private:
294 UIntT* user_var_;
295 };
296
297 /*!
298 * \class ResultWriterDouble
299 *
300 * \brief Responsible for writing double record values to the user's local
301 * variables whenever a query's result set iterator is advanced.
302 */
303 template <typename DoubleT = double> class ResultWriterDouble : public ResultWriterBase
304 {
305 static_assert(detail::unrolled_is_same_v<DoubleT, double>);
306
307 public:
308 /// \brief Construction
309 /// \param col_name Name of the selected column
310 /// \param user_var Pointer to the local variable where result values are
311 /// written to
312 16 ResultWriterDouble(const char* col_name, DoubleT* user_var) :
313 ResultWriterBase(col_name),
314 16 user_var_(user_var)
315 {
316 16 }
317
318 /// Read the value for the prepared statement at the given column index
319 /// and copy it to the user's local variable.
320 22 void writeToUserVar(sqlite3_stmt* stmt, const int idx) const override
321 {
322 if constexpr (detail::is_optional_v<DoubleT>)
323 {
324
2/2
✓ Branch 3 → 4 taken 3 times.
✓ Branch 3 → 6 taken 1 time.
4 if (detail::columnIsNull(stmt, idx))
325 {
326 3 *user_var_ = std::nullopt;
327 3 return;
328 }
329 } else
330 {
331 18 detail::requireNonNullColumn(stmt, idx, getColName());
332 }
333
334
1/1
✓ Branch 6 → 7 taken 1 time.
19 *user_var_ = sqlite3_column_double(stmt, idx);
335 18 }
336
337 /// Return a new copy of this writer.
338 8 ResultWriterBase* clone() const override
339 {
340
2/6
simdb::ResultWriterDouble<std::optional<double> >::clone() const:
✓ Branch 5 → 6 taken 1 time.
✗ Branch 8 → 9 not taken.
✗ Branch 8 → 10 not taken.
simdb::ResultWriterDouble<double>::clone() const:
✓ Branch 5 → 6 taken 7 times.
✗ Branch 8 → 9 not taken.
✗ Branch 8 → 10 not taken.
8 return new ResultWriterDouble<DoubleT>(getColName().c_str(), user_var_);
341 }
342
343 private:
344 DoubleT* user_var_;
345 };
346
347 /*!
348 * \class ResultWriterString
349 *
350 * \brief Responsible for writing text record values to the user's local
351 * variables whenever a query's result set iterator is advanced.
352 */
353 template <typename StringT = std::string> class ResultWriterString : public ResultWriterBase
354 {
355 static_assert(detail::unrolled_is_same_v<StringT, std::string>);
356
357 public:
358 /// \brief Construction
359 /// \param col_name Name of the selected column
360 /// \param user_var Pointer to the local variable where result values are
361 /// written to
362 235 ResultWriterString(const char* col_name, StringT* user_var) :
363 ResultWriterBase(col_name),
364 235 user_var_(user_var)
365 {
366 235 }
367
368 /// Read the value for the prepared statement at the given column index
369 /// and copy it to the user's local variable.
370 90126 void writeToUserVar(sqlite3_stmt* stmt, const int idx) const override
371 {
372 if constexpr (detail::is_optional_v<StringT>)
373 {
374
2/2
✓ Branch 3 → 4 taken 1 time.
✓ Branch 3 → 6 taken 10 times.
11 if (detail::columnIsNull(stmt, idx))
375 {
376 1 *user_var_ = std::nullopt;
377 1 return;
378 }
379
2/2
✓ Branch 3 → 4 taken 1 time.
✓ Branch 3 → 6 taken 90114 times.
90115 } else if (detail::columnIsNull(stmt, idx))
380 {
381 1 *user_var_ = "";
382 1 return;
383 }
384
385 90124 const char* text = reinterpret_cast<const char*>(sqlite3_column_text(stmt, idx));
386
3/5
simdb::ResultWriterString<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >::writeToUserVar(sqlite3_stmt*, int) const:
✓ Branch 7 → 8 taken 90114 times.
✗ Branch 7 → 9 not taken.
simdb::ResultWriterString<std::optional<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > >::writeToUserVar(sqlite3_stmt*, int) const:
✓ Branch 7 → 8 taken 10 times.
✗ Branch 7 → 9 not taken.
✓ Branch 10 → 11 taken 10 times.
90124 *user_var_ = text ? text : "";
387 }
388
389 /// Return a new copy of this writer.
390 117 ResultWriterBase* clone() const override
391 {
392
2/6
simdb::ResultWriterString<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >::clone() const:
✓ Branch 5 → 6 taken 104 times.
✗ Branch 8 → 9 not taken.
✗ Branch 8 → 10 not taken.
simdb::ResultWriterString<std::optional<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > >::clone() const:
✓ Branch 5 → 6 taken 13 times.
✗ Branch 8 → 9 not taken.
✗ Branch 8 → 10 not taken.
117 return new ResultWriterString<StringT>(getColName().c_str(), user_var_);
393 }
394
395 private:
396 StringT* user_var_;
397 };
398
399 /*!
400 * \class ResultWriterBlob<T>
401 *
402 * \brief Responsible for writing blob record values to the user's local
403 * variables whenever a query's result set iterator is advanced.
404 */
405 template <typename T> class ResultWriterBlob : public ResultWriterBase
406 {
407 public:
408 /// \brief Construction
409 /// \param col_name Name of the selected column
410 /// \param user_var Pointer to the local variable where result values are
411 /// written to
412 16388 ResultWriterBlob(const char* col_name, std::vector<T>* user_var) :
413 ResultWriterBase(col_name),
414 16388 user_var_(user_var)
415 {
416 16388 }
417
418 /// Read the value for the prepared statement at the given column index
419 /// and copy it to the user's local variable.
420 19716 void writeToUserVar(sqlite3_stmt* stmt, const int idx) const override
421 {
422 19716 const void* data = sqlite3_column_blob(stmt, idx);
423 19716 const int bytes = sqlite3_column_bytes(stmt, idx);
424 19716 user_var_->resize(bytes / sizeof(T));
425 19716 memcpy(user_var_->data(), data, bytes);
426 19716 }
427
428 /// Return a new copy of this writer.
429
2/6
simdb::ResultWriterBlob<char>::clone() const:
✓ Branch 5 → 6 taken 8176 times.
✗ Branch 8 → 9 not taken.
✗ Branch 8 → 10 not taken.
simdb::ResultWriterBlob<int>::clone() const:
✓ Branch 5 → 6 taken 22 times.
✗ Branch 8 → 9 not taken.
✗ Branch 8 → 10 not taken.
8198 ResultWriterBase* clone() const override { return new ResultWriterBlob(getColName().c_str(), user_var_); }
430
431 private:
432 std::vector<T>* user_var_;
433 };
434
435 /*!
436 * \class SqlResultIterator
437 *
438 * \brief This class is returned by SqlQuery::getResultSet() and
439 * is used to iterate over a query result set.
440 */
441 class SqlResultIterator
442 {
443 public:
444 /// Construct with a prepared statement and the result writers that read
445 /// column values and write them into the user's local variables.
446 19486 SqlResultIterator(sqlite3_stmt* stmt, std::vector<std::shared_ptr<ResultWriterBase>>&& result_writers) :
447 19486 stmt_(stmt),
448 19486 result_writers_(std::move(result_writers))
449 {
450 19486 }
451
452 /// Finalize the prepared statement on destruction.
453 19486 ~SqlResultIterator()
454 {
455
1/2
✓ Branch 2 → 3 taken 19486 times.
✗ Branch 2 → 4 not taken.
19486 if (stmt_)
456 {
457 19486 sqlite3_finalize(stmt_);
458 }
459 19486 }
460
461 /// Get the next record, populate the user's local variables,
462 /// and return TRUE if the record was found. FALSE is returned
463 /// when the entire result set has been iterated over.
464 124037 bool getNextRecord()
465 {
466
2/2
✓ Branch 2 → 3 taken 124037 times.
✓ Branch 3 → 4 taken 124037 times.
124037 auto rc = SQLiteReturnCode(sqlite3_step(stmt_));
467
2/2
✓ Branch 5 → 6 taken 120942 times.
✓ Branch 5 → 14 taken 3095 times.
124037 if (rc == SQLITE_ROW)
468 {
469
2/2
✓ Branch 12 → 7 taken 217085 times.
✓ Branch 12 → 13 taken 120940 times.
338025 for (size_t idx = 0; idx < result_writers_.size(); ++idx)
470 {
471
1/1
✓ Branch 9 → 10 taken 217083 times.
217085 result_writers_[idx]->writeToUserVar(stmt_, (int)idx);
472 }
473 120940 return true;
474 } else
475 {
476
1/14
✗ Branch 15 → 16 not taken.
✓ Branch 15 → 36 taken 3095 times.
✗ Branch 18 → 19 not taken.
✗ Branch 19 → 20 not taken.
✗ Branch 21 → 22 not taken.
✗ Branch 25 → 26 not taken.
✗ Branch 26 → 27 not taken.
✗ Branch 27 → 28 not taken.
✗ Branch 28 → 29 not taken.
✗ Branch 29 → 30 not taken.
✗ Branch 30 → 31 not taken.
✗ Branch 31 → 32 not taken.
✗ Branch 32 → 33 not taken.
✗ Branch 34 → 35 not taken.
3095 simdb_assert(rc == SQLITE_DONE, sqlite3_errmsg(sqlite3_db_handle(stmt_)));
477 }
478
479 3095 return false;
480 }
481
482 /// Go back to the beginning of the result set if you need
483 /// to iterate over it again.
484
3/16
✓ Branch 2 → 3 taken 2 times.
✓ Branch 3 → 4 taken 2 times.
✗ Branch 5 → 6 not taken.
✓ Branch 5 → 26 taken 2 times.
✗ Branch 8 → 9 not taken.
✗ Branch 9 → 10 not taken.
✗ Branch 11 → 12 not taken.
✗ Branch 15 → 16 not taken.
✗ Branch 16 → 17 not taken.
✗ Branch 17 → 18 not taken.
✗ Branch 18 → 19 not taken.
✗ Branch 19 → 20 not taken.
✗ Branch 20 → 21 not taken.
✗ Branch 21 → 22 not taken.
✗ Branch 22 → 23 not taken.
✗ Branch 24 → 25 not taken.
2 void reset() { simdb_assert(!SQLiteReturnCode(sqlite3_reset(stmt_)), sqlite3_errmsg(sqlite3_db_handle(stmt_))); }
485
486 private:
487 /// Prepared statement
488 sqlite3_stmt* const stmt_;
489
490 /// Writers that read column values and write them into the user's local
491 /// variables
492 std::vector<std::shared_ptr<ResultWriterBase>> result_writers_;
493 };
494
495 } // namespace simdb
496