ThinSQLite++
A thin, safe and convenient modern C++ wrapper for the SQLite API.
Loading...
Searching...
No Matches
statement_iface.hpp
1/*
2 Copyright 2019 Eugene Gershnik
3
4 Use of this source code is governed by a BSD-style
5 license that can be found in the LICENSE file or at
6 https://github.com/gershnik/thinsqlitepp/blob/master/LICENSE
7*/
8
9#ifndef HEADER_SQLITEPP_STATEMENT_IFACE_INCLUDED
10#define HEADER_SQLITEPP_STATEMENT_IFACE_INCLUDED
11
12#include "handle.hpp"
13#include "string_param.hpp"
14#include "span.hpp"
15#include "meta.hpp"
16#include "memory_iface.hpp"
17
18#include <utility>
19#include <string>
20#include <string_view>
21
22#if __has_include(<sys/uio.h>)
23 #include <sys/uio.h>
24#endif
25
26#ifndef SQLITEPP_BUILDING_MODULE
27 // forward declare it so at least the delaration is there
28 // whether <sys/uio.h> is present and whether it declares it
29 struct iovec;
30#endif
31
32namespace thinsqlitepp
33{
34 SQLITEPP_EXPORTED class database;
35 SQLITEPP_EXPORTED class value;
36
41
47 SQLITEPP_EXPORTED
50 void *iov_base;
52 size_t iov_len;
53 };
54
55 template<class T=struct ::iovec, size_t = sizeof(T)>
56 constexpr struct ::iovec * detect_iovec(T *) { return{}; }
57 constexpr auto detect_iovec(...) { return (iovec_fallback *)nullptr; }
58
69#if !DOXYGEN
70 SQLITEPP_EXPORTED
71 using iovec = std::remove_reference_t<decltype(*detect_iovec((::iovec *)nullptr))>;
72#else
73 using iovec = <conditionally declared>;
74#endif
75
85 SQLITEPP_EXPORTED
86 class statement final : public handle<sqlite3_stmt, statement>
87 {
88 public:
100 #if SQLITE_VERSION_NUMBER >= SQLITEPP_SQLITE_VERSION(3, 20, 0)
101 , unsigned int flags = 0
102 #endif
103 );
104
118 #if SQLITE_VERSION_NUMBER >= SQLITEPP_SQLITE_VERSION(3, 20, 0)
119 , unsigned int flags = 0
120 #endif
121 );
122
123#if __cpp_char8_t >= 201811
130 #if SQLITE_VERSION_NUMBER >= SQLITEPP_SQLITE_VERSION(3, 20, 0)
131 , unsigned int flags = 0
132 #endif
133 )
134 {
135 return create(db, (const char *)sql.c_str()
136 #if SQLITE_VERSION_NUMBER >= SQLITEPP_SQLITE_VERSION(3, 20, 0)
137 , flags
138 #endif
139 );
140 }
141
148 #if SQLITE_VERSION_NUMBER >= SQLITEPP_SQLITE_VERSION(3, 20, 0)
149 , unsigned int flags = 0
150 #endif
151 )
152 {
153 return create(db, *reinterpret_cast<std::string_view *>(&sql)
154 #if SQLITE_VERSION_NUMBER >= SQLITEPP_SQLITE_VERSION(3, 20, 0)
155 , flags
156 #endif
157 );
158 }
159#endif
160
162 ~statement() noexcept
163 { sqlite3_finalize(c_ptr()); }
164
170 class database & database() const noexcept
171 { return *(class database *)sqlite3_db_handle(c_ptr()); }
172
183 bool step();
184
190 void reset() noexcept
191 { sqlite3_reset(c_ptr()); }
192
198 bool busy() const noexcept
199 { return sqlite3_stmt_busy(c_ptr()); }
200
204 enum class explain_type : int
205 {
209 };
210
211
212#if SQLITE_VERSION_NUMBER >= SQLITEPP_SQLITE_VERSION(3, 31, 1)
220 explain_type isexplain() const noexcept
222#endif
223
229 bool readonly() const noexcept
230 { return sqlite3_stmt_readonly(c_ptr()); }
231
239
245 void bind(int idx, std::nullptr_t)
246 { check_error(sqlite3_bind_null(c_ptr(), idx)); }
247
252 void bind(int idx, int val)
253 { check_error(sqlite3_bind_int(c_ptr(), idx, val)); }
254
259 void bind(int idx, int64_t val)
260 { check_error(sqlite3_bind_int64(c_ptr(), idx, val)); }
261
266 void bind(int idx, double val)
267 { check_error(sqlite3_bind_double(c_ptr(), idx, val)); }
268
269
279 void bind(int idx, const std::string_view & val);
280
290 void bind_reference(int idx, const std::string_view & val);
291
304 void bind_reference(int idx, const std::string_view & val, void (*unref)(const char *) noexcept);
305
306 #if __cpp_char8_t >= 201811
312 void bind(int idx, const std::u8string_view & val);
313
319 void bind_reference(int idx, const std::u8string_view & val);
320
326 void bind_reference(int idx, const std::u8string_view & val, void (*unref)(const char8_t *) noexcept);
327 #endif
328
338 void bind(int idx, const blob_view & val);
339
349 void bind_reference(int idx, const blob_view & val);
350
363 void bind_reference(int idx, const blob_view & val, void (*unref)(const std::byte *) noexcept);
364
370 void bind(int idx, const zero_blob & val)
371 { check_error(sqlite3_bind_zeroblob(c_ptr(), idx, int(val.size()))); }
372
374
381 template<class T, class D>
382 SQLITEPP_ENABLE_IF((std::is_convertible_v<D, void(*)(T *) noexcept>),
383 void) bind(int idx, T * ptr, const char * type, D destroy)
384 { check_error(sqlite3_bind_pointer(this->c_ptr(), idx, ptr, type, (void(*)(void*))(void(*)(T *) noexcept)destroy)); }
385
396 template<class T>
397 void bind(int idx, std::unique_ptr<T> ptr)
398 { this->bind(idx, ptr.release(), typeid(T).name(), [](T * p) noexcept { delete p; }); }
399
405 void bind(int idx, const value & val);
406
408
416
417#if SQLITE_VERSION_NUMBER >= SQLITEPP_SQLITE_VERSION(3, 52, 0)
418
419 private:
420 template<class T>
421 static constexpr bool supported_carray_type =
426 #if __cpp_char8_t >= 201811
428 #endif
430
431
432 template<class T>
433 static constexpr int carray_type()
434 {
435 if constexpr (std::is_same_v<std::remove_const_t<T>, int>)
436 return SQLITE_CARRAY_INT32;
437 else if constexpr (std::is_same_v<std::remove_const_t<T>, int64_t>)
438 return SQLITE_CARRAY_INT64;
439 else if constexpr (std::is_same_v<std::remove_const_t<T>, double>)
440 return SQLITE_CARRAY_DOUBLE;
441 else if constexpr (std::is_same_v<std::remove_const_t<T>, char *>)
442 return SQLITE_CARRAY_TEXT;
443 #if __cpp_char8_t >= 201811
444 else if constexpr (std::is_same_v<std::remove_const_t<T>, char8_t *>)
445 return SQLITE_CARRAY_TEXT;
446 #endif
447 else if constexpr (std::is_same_v<std::remove_const_t<T>, iovec>)
448 return SQLITE_CARRAY_BLOB;
449 else
450 static_assert(dependent_false<T>, "unsupported carray type");
451 }
452
453 public:
454
472 template<class T>
473 SQLITEPP_ENABLE_IF(supported_carray_type<T>,
474 void) carray_bind(int idx, span<T> array)
475 { this->carray_bind(idx, array, (void (*)(void *) noexcept)SQLITE_TRANSIENT, nullptr); }
476
494 template<class T>
495 SQLITEPP_ENABLE_IF(supported_carray_type<T>,
496 void) carray_bind_reference(int idx, span<T> array)
497 { this->carray_bind(idx, array, (void (*)(void *) noexcept)SQLITE_STATIC, nullptr); }
498
516 template<class T>
517 SQLITEPP_ENABLE_IF(supported_carray_type<T>,
518 void) carray_bind(int idx, span<T> array, void (*destroy)(void *) noexcept, void * destroy_arg = nullptr)
519 {
520 check_error(sqlite3_carray_bind_v2(this->c_ptr(), idx, (void*)array.data(), int(array.size()),
521 carray_type<T>(), (void(*)(void *))destroy, destroy_arg));
522 }
523
524 #endif
525
527
532
538 void clear_bindings() noexcept
540
546 int bind_parameter_count() const noexcept
548
554 int bind_parameter_index(const string_param & name) const noexcept
555 { return sqlite3_bind_parameter_index(c_ptr(), name.c_str()); }
556
562 const char * bind_parameter_name(int idx) const noexcept
563 { return sqlite3_bind_parameter_name(c_ptr(), idx); }
564
566
567
579 int column_count() const noexcept
580 { return sqlite3_column_count(c_ptr()); }
581
593 int data_count() const noexcept
594 { return sqlite3_data_count(c_ptr()); }
595
596 private:
597 template<class T>
598 static constexpr bool supported_column_type =
603 #if __cpp_char8_t >= 201811
605 #endif
607
608 public:
609
614
630 template<class T>
631 SQLITEPP_ENABLE_IF(supported_column_type<T>,
632 T) column_value(int idx) const noexcept;
633
639 const value & raw_column_value(int idx) const noexcept
640 { return *(const value *)sqlite3_column_value(c_ptr(), idx); }
641
649 int column_type(int idx) const noexcept
650 { return sqlite3_column_type(c_ptr(), idx); }
651
662 const char * column_name(int idx) const noexcept
663 { return sqlite3_column_name(c_ptr(), idx); }
664
670 const char * column_database_name(int idx) const noexcept
671 { return sqlite3_column_database_name(c_ptr(), idx); }
672
678 const char * column_table_name(int idx) const noexcept
679 { return sqlite3_column_table_name(c_ptr(), idx); }
680
686 const char * column_origin_name(int idx) const noexcept
687 { return sqlite3_column_origin_name(c_ptr(), idx); }
688
694 const char * column_declared_type(int idx) const noexcept
695 { return sqlite3_column_decltype(c_ptr(), idx); }
696
698
704 const char * sql() const noexcept
705 { return sqlite3_sql(c_ptr()); }
706
707#if SQLITE_VERSION_NUMBER >= SQLITEPP_SQLITE_VERSION(3, 14, 0)
716#endif
717
718 private:
719 void check_error(int res) const;
720 };
721
723
724 template<>
725 inline int statement::column_value<int>(int idx) const noexcept
726 { return sqlite3_column_int(c_ptr(), idx); }
727
728 template<>
729 inline int64_t statement::column_value<int64_t>(int idx) const noexcept
730 { return sqlite3_column_int64(c_ptr(), idx); }
731
732 template<>
733 inline double statement::column_value<double>(int idx) const noexcept
734 { return sqlite3_column_double(c_ptr(), idx); }
735
737
739
744
745
752 SQLITEPP_EXPORTED
754 {
755 public:
758 _db(&db),
759 _sql(sql)
760 {}
761
768 private:
769 const database * _db;
770 std::string_view _sql;
771 };
772
778 SQLITEPP_EXPORTED
779 enum class auto_reset_flags: unsigned
780 {
781 none = 0,
782 reset = 1,
784 all = 3
785 };
786 SQLITEPP_EXPORTED constexpr auto_reset_flags operator|(auto_reset_flags lhs, auto_reset_flags rhs)
787 { return auto_reset_flags(unsigned(lhs) | unsigned(rhs)); }
788 SQLITEPP_EXPORTED constexpr auto_reset_flags operator&(auto_reset_flags lhs, auto_reset_flags rhs)
789 { return auto_reset_flags(unsigned(lhs) & unsigned(rhs)); }
790 SQLITEPP_EXPORTED constexpr auto_reset_flags operator^(auto_reset_flags lhs, auto_reset_flags rhs)
791 { return auto_reset_flags(unsigned(lhs) ^ unsigned(rhs)); }
792 SQLITEPP_EXPORTED constexpr auto_reset_flags operator~(auto_reset_flags arg)
793 { return auto_reset_flags(~unsigned(arg)); }
794
804 SQLITEPP_EXPORTED
805 template<auto_reset_flags Flags>
807 {
808 public:
811 _st(nullptr)
812 {}
813
820 _st(st.get())
821 {}
822
824 auto_reset(statement * st) noexcept:
825 _st(st)
826 {}
827
828 auto_reset(const auto_reset &) = delete;
829 auto_reset & operator=(const auto_reset &) = delete;
830 auto_reset(auto_reset && src) noexcept:
831 _st(src._st)
832 {
833 src._st = nullptr;
834 }
835 auto_reset & operator=(auto_reset && src) noexcept
836 {
837 destroy();
838 _st = src._st;
839 src._st = nullptr;
840 return *this;
841 }
842
844 ~auto_reset() noexcept
845 { destroy(); }
846
848 statement * operator->() const noexcept
849 { return _st; }
850
851 private:
852 void destroy() noexcept
853 {
854 if (_st)
855 {
856 if constexpr ((Flags & auto_reset_flags::reset) != auto_reset_flags::none)
857 _st->reset();
859 _st->clear_bindings();
860 }
861 }
862 private:
863 statement * _st;
864 };
865
867
868}
869
870#endif
871
sqlite3_bind_null
sqlite3_bind_parameter_count
sqlite3_bind_parameter_index
sqlite3_bind_parameter_name
#define SQLITE_VERSION_NUMBER
#define SQLITE_TRANSIENT
sqlite3_carray_bind_v2
RAII wrapper that resets statement on destruction.
Definition statement_iface.hpp:807
auto_reset()
Constructs an empty instance with no statement.
Definition statement_iface.hpp:810
auto_reset(const std::unique_ptr< statement > &st) noexcept
Constructs an instance referring to a given statement.
Definition statement_iface.hpp:819
~auto_reset() noexcept
Resets the statement if present.
Definition statement_iface.hpp:844
auto_reset(statement *st) noexcept
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition statement_iface.hpp:824
statement * operator->() const noexcept
Access the stored statement.
Definition statement_iface.hpp:848
Database Connection.
Definition database_iface.hpp:109
sqlite3_stmt * c_ptr() const noexcept
Definition handle.hpp:45
std::unique_ptr< statement > next()
Return the next statement if any.
statement_parser(const database &db, std::string_view sql)
Create a parser for the given database and SQL text.
Definition statement_iface.hpp:757
Prepared Statement Object.
Definition statement_iface.hpp:87
explain_type isexplain() const noexcept
Query the EXPLAIN Setting for the statement.
Definition statement_iface.hpp:220
bool step()
Evaluate the statement.
class database & database() const noexcept
Returns the database to which this statement belongs.
Definition statement_iface.hpp:170
bool readonly() const noexcept
Determine if the statement writes to the database.
Definition statement_iface.hpp:229
void reset() noexcept
Reset the statement.
Definition statement_iface.hpp:190
void bind(int idx, const value &val)
Bind a dynamically typed value to a parameter of the statement.
void bind(int idx, const std::u8string_view &val)
Bind a string value to a parameter of the statement.
void bind(int idx, std::nullptr_t)
Bind a NULL value to a parameter of the statement.
Definition statement_iface.hpp:245
bool busy() const noexcept
Determine if the statement has been reset.
Definition statement_iface.hpp:198
const value & raw_column_value(int idx) const noexcept
Get result values from a query as a raw value object.
Definition statement_iface.hpp:639
void bind_reference(int idx, const std::u8string_view &val)
Bind a string reference to a parameter of the statement.
void bind(int idx, std::unique_ptr< T > ptr)
Bind a custom pointer to a parameter of the statement.
Definition statement_iface.hpp:397
void carray_bind(int idx, span< T > array, void(*destroy)(void *) noexcept, void *destroy_arg=nullptr)
Bind a reference to an array for the CARRAY table-valued function in the statement.
Definition statement_iface.hpp:518
void bind_reference(int idx, const std::string_view &val, void(*unref)(const char *) noexcept)
Bind a string reference to a parameter of the statement.
const char * sql() const noexcept
Returns a pointer to a copy of the SQL text used to create the statement.
Definition statement_iface.hpp:704
void bind(int idx, int val)
Bind an int value to a parameter of the statement.
Definition statement_iface.hpp:252
int column_type(int idx) const noexcept
Default datatype of the result column.
Definition statement_iface.hpp:649
allocated_string expanded_sql() const
Returns SQL text of the statement with bound parameters expanded.
void bind_reference(int idx, const blob_view &val, void(*unref)(const std::byte *) noexcept)
Bind a blob reference to a parameter of the statement.
void bind(int idx, const zero_blob &val)
Bind a blob of zeroes to a parameter of the statement.
Definition statement_iface.hpp:370
void carray_bind(int idx, span< T > array)
Bind the content of an array for the CARRAY table-valued function in the statement.
Definition statement_iface.hpp:474
int column_count() const noexcept
Number of columns in a result set.
Definition statement_iface.hpp:579
void bind(int idx, int64_t val)
Bind an int64_t value to a parameter of the statement.
Definition statement_iface.hpp:259
static std::unique_ptr< statement > create(const database &db, std::string_view &sql, unsigned int flags=0)
Compile an SQL statement.
const char * column_table_name(int idx) const noexcept
Table that is the origin of a result column.
Definition statement_iface.hpp:678
const char * bind_parameter_name(int idx) const noexcept
Returns the name of a parameter with a given index.
Definition statement_iface.hpp:562
void bind_reference(int idx, const std::u8string_view &val, void(*unref)(const char8_t *) noexcept)
Bind a string reference to a parameter of the statement.
const char * column_origin_name(int idx) const noexcept
Table column that is the origin of a result column.
Definition statement_iface.hpp:686
static std::unique_ptr< statement > create(const database &db, const string_param &sql, unsigned int flags=0)
Compile an SQL statement.
void bind(int idx, T *ptr, const char *type, D destroy)
Definition statement_iface.hpp:383
const char * column_database_name(int idx) const noexcept
Database that is the origin of a result column.
Definition statement_iface.hpp:670
~statement() noexcept
Equivalent to sqlite3_finalize.
Definition statement_iface.hpp:162
void bind(int idx, double val)
Bind a double value to a parameter of the statement.
Definition statement_iface.hpp:266
static std::unique_ptr< statement > create(const database &db, std::u8string_view &sql, unsigned int flags=0)
Compile an SQL statement.
Definition statement_iface.hpp:147
explain_type
Return type for isexplain().
Definition statement_iface.hpp:205
@ explain_query_plan
The statement is an EXPLAIN QUERY PLAN.
Definition statement_iface.hpp:208
@ explain
The statement is an EXPLAIN statement.
Definition statement_iface.hpp:207
@ not_explain
The statement is an ordinary statement.
Definition statement_iface.hpp:206
const char * column_name(int idx) const noexcept
Name of the result column.
Definition statement_iface.hpp:662
T column_value(int idx) const noexcept
Get result value from a query.
void bind(int idx, const blob_view &val)
Bind a blob value to a parameter of the statement.
void bind_reference(int idx, const std::string_view &val)
Bind a string reference to a parameter of the statement.
void bind_reference(int idx, const blob_view &val)
Bind a blob reference to a parameter of the statement.
int bind_parameter_count() const noexcept
Returns the number of SQL parameters.
Definition statement_iface.hpp:546
void clear_bindings() noexcept
Reset all bindings on the statement.
Definition statement_iface.hpp:538
void carray_bind_reference(int idx, span< T > array)
Bind a reference to an array for the CARRAY table-valued function in the statement.
Definition statement_iface.hpp:496
int bind_parameter_index(const string_param &name) const noexcept
Returns the index of a parameter with a given name.
Definition statement_iface.hpp:554
const char * column_declared_type(int idx) const noexcept
Declared datatype of a result column.
Definition statement_iface.hpp:694
void bind(int idx, const std::string_view &val)
Bind a string value to a parameter of the statement.
static std::unique_ptr< statement > create(const database &db, const u8string_param &sql, unsigned int flags=0)
Compile an SQL statement.
Definition statement_iface.hpp:129
int data_count() const noexcept
Number of columns in a result set.
Definition statement_iface.hpp:593
Dynamically Typed Value Object.
Definition value_iface.hpp:36
An efficient blob of zeroes of a given size.
Definition span.hpp:257
sqlite3_clear_bindings
sqlite3_column_value
sqlite3_column_count
sqlite3_column_database_name
sqlite3_column_decltype
sqlite3_column_name
sqlite3_data_count
T data(T... args)
sqlite3_db_handle
sqlite3_sql
sqlite3_finalize
void * iov_base
Base address of a memory region for input or output.
Definition statement_iface.hpp:50
size_t iov_len
The size of the memory pointed to by iov_base.
Definition statement_iface.hpp:52
< conditionally declared > iovec
A portable version of struct iovec that SQLite uses for carray() functionality.
Definition statement_iface.hpp:73
A fallback version of struct iovec for platforms that lack it.
Definition statement_iface.hpp:48
std::span< T > span
Alias or reimplementation of std::span.
Definition span.hpp:36
span< const std::byte > blob_view
A blob_view is a span of bytes.
Definition span.hpp:239
basic_string_param< char > string_param
Convenience typedef.
Definition string_param.hpp:58
std::unique_ptr< char, sqlite_deleter< char > > allocated_string
A string allocated by SQLite.
Definition memory_iface.hpp:50
basic_string_param< char8_t > u8string_param
Convenience typedef. Only available if you compiler/library supports char8_t.
Definition string_param.hpp:63
auto_reset_flags
Bitwise mask of resets to perform for thinsqlitepp::auto_reset.
Definition statement_iface.hpp:780
@ none
Reset nothing.
Definition statement_iface.hpp:781
@ reset
Reset the statement (does not affect the bindings).
Definition statement_iface.hpp:782
@ all
Reset everything.
Definition statement_iface.hpp:784
@ clear_bindings
Reset the bindings.
Definition statement_iface.hpp:783
T is_convertible_v
T is_same_v
ThinSQLite++ namespace.
Definition backup_iface.hpp:17
T release(T... args)
sqlite3_reset
T size(T... args)
sqlite3_stmt_busy
sqlite3_stmt_isexplain
sqlite3_stmt_readonly