ThinSQLite++
A thin, safe and convenient modern C++ wrapper for 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/main/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 "memory_iface.hpp"
16
17#include <utility>
18#include <string>
19#include <string_view>
20
21namespace thinsqlitepp
22{
23 class database;
24 class value;
25
40 class statement final : public handle<sqlite3_stmt, statement>
41 {
42 public:
54 #if SQLITE_VERSION_NUMBER >= SQLITEPP_SQLITE_VERSION(3, 20, 0)
55 , unsigned int flags = 0
56 #endif
57 );
58
72 #if SQLITE_VERSION_NUMBER >= SQLITEPP_SQLITE_VERSION(3, 20, 0)
73 , unsigned int flags = 0
74 #endif
75 );
76
77#if __cpp_char8_t >= 201811
84 #if SQLITE_VERSION_NUMBER >= SQLITEPP_SQLITE_VERSION(3, 20, 0)
85 , unsigned int flags = 0
86 #endif
87 )
88 {
89 return create(db, (const char *)sql.c_str()
90 #if SQLITE_VERSION_NUMBER >= SQLITEPP_SQLITE_VERSION(3, 20, 0)
91 , flags
92 #endif
93 );
94 }
95
102 #if SQLITE_VERSION_NUMBER >= SQLITEPP_SQLITE_VERSION(3, 20, 0)
103 , unsigned int flags = 0
104 #endif
105 )
106 {
107 return create(db, *reinterpret_cast<std::string_view *>(&sql)
108 #if SQLITE_VERSION_NUMBER >= SQLITEPP_SQLITE_VERSION(3, 20, 0)
109 , flags
110 #endif
111 );
112 }
113#endif
114
116 ~statement() noexcept
117 { sqlite3_finalize(c_ptr()); }
118
124 class database & database() const noexcept
125 { return *(class database *)sqlite3_db_handle(c_ptr()); }
126
137 bool step();
138
144 void reset() noexcept
145 { sqlite3_reset(c_ptr()); }
146
152 bool busy() const noexcept
153 { return sqlite3_stmt_busy(c_ptr()); }
154
158 enum class explain_type : int
159 {
160 not_explain = 0,
161 explain = 1,
163 };
164
165
166#if SQLITE_VERSION_NUMBER >= SQLITEPP_SQLITE_VERSION(3, 31, 1)
174 explain_type isexplain() const noexcept
176#endif
177
183 bool readonly() const noexcept
184 { return sqlite3_stmt_readonly(c_ptr()); }
185
199 void bind(int idx, std::nullptr_t)
200 { check_error(sqlite3_bind_null(c_ptr(), idx)); }
206 void bind(int idx, int val)
207 { check_error(sqlite3_bind_int(c_ptr(), idx, val)); }
213 void bind(int idx, int64_t val)
214 { check_error(sqlite3_bind_int64(c_ptr(), idx, val)); }
220 void bind(int idx, double val)
221 { check_error(sqlite3_bind_double(c_ptr(), idx, val)); }
222
223
233 void bind(int idx, const std::string_view & val);
234
244 void bind_reference(int idx, const std::string_view & val);
245
258 void bind_reference(int idx, const std::string_view & val, void (*unref)(const char *));
259
260 #if __cpp_char8_t >= 201811
266 void bind(int idx, const std::u8string_view & val);
267
273 void bind_reference(int idx, const std::u8string_view & val);
274
280 void bind_reference(int idx, const std::u8string_view & val, void (*unref)(const char8_t *));
281 #endif
282
292 void bind(int idx, const blob_view & val);
293
303 void bind_reference(int idx, const blob_view & val);
304
317 void bind_reference(int idx, const blob_view & val, void (*unref)(const std::byte *));
318
324 void bind(int idx, const zero_blob & val)
325 { check_error(sqlite3_bind_zeroblob(c_ptr(), idx, int(val.size()))); }
326
328
335 template<class T>
336 void bind(int idx, T * ptr, const char * type, void(*destroy)(T*))
337 { check_error(sqlite3_bind_pointer(this->c_ptr(), idx, ptr, type, (void(*)(void*))destroy)); }
338
349 template<class T>
350 void bind(int idx, std::unique_ptr<T> ptr)
351 { this->bind(idx, ptr.release(), typeid(T).name(), [](T * p) { delete p; }); }
352
358 void bind(int idx, const value & val);
359
361
372 void clear_bindings() noexcept
374
380 int bind_parameter_count() const noexcept
382
388 int bind_parameter_index(const string_param & name) const noexcept
389 { return sqlite3_bind_parameter_index(c_ptr(), name.c_str()); }
390
396 const char * bind_parameter_name(int idx) const noexcept
397 { return sqlite3_bind_parameter_name(c_ptr(), idx); }
398
400
401
413 int column_count() const noexcept
414 { return sqlite3_column_count(c_ptr()); }
415
427 int data_count() const noexcept
428 { return sqlite3_data_count(c_ptr()); }
429
430 private:
431 template<typename T>
432 static constexpr bool supported_column_type =
437 #if __cpp_char8_t >= 201811
439 #endif
441
442 public:
443
464 template<class T>
465 SQLITEPP_ENABLE_IF(supported_column_type<T>,
466 T) column_value(int idx) const noexcept;
467
473 const value & raw_column_value(int idx) const noexcept
474 { return *(const value *)sqlite3_column_value(c_ptr(), idx); }
475
483 int column_type(int idx) const noexcept
484 { return sqlite3_column_type(c_ptr(), idx); }
485
496 const char * column_name(int idx) const noexcept
497 { return sqlite3_column_name(c_ptr(), idx); }
498
504 const char * column_database_name(int idx) const noexcept
505 { return sqlite3_column_database_name(c_ptr(), idx); }
506
512 const char * column_table_name(int idx) const noexcept
513 { return sqlite3_column_table_name(c_ptr(), idx); }
514
520 const char * column_origin_name(int idx) const noexcept
521 { return sqlite3_column_origin_name(c_ptr(), idx); }
522
528 const char * column_declared_type(int idx) const noexcept
529 { return sqlite3_column_decltype(c_ptr(), idx); }
530
532
538 const char * sql() const noexcept
539 { return sqlite3_sql(c_ptr()); }
540
541#if SQLITE_VERSION_NUMBER >= SQLITEPP_SQLITE_VERSION(3, 14, 0)
550#endif
551
552 private:
553 void check_error(int res) const;
554 };
555
557
558 template<>
559 inline int statement::column_value<int>(int idx) const noexcept
560 { return sqlite3_column_int(c_ptr(), idx); }
561
562 template<>
563 inline int64_t statement::column_value<int64_t>(int idx) const noexcept
564 { return sqlite3_column_int64(c_ptr(), idx); }
565
566 template<>
567 inline double statement::column_value<double>(int idx) const noexcept
568 { return sqlite3_column_double(c_ptr(), idx); }
569
571
587 {
588 public:
591 _db(&db),
592 _sql(sql)
593 {}
594
601 private:
602 const database * _db;
603 std::string_view _sql;
604 };
605
611 enum class auto_reset_flags: unsigned
612 {
613 none = 0,
614 reset = 1,
615 clear_bindings = 2,
616 all = 3
617 };
618 constexpr auto_reset_flags operator|(auto_reset_flags lhs, auto_reset_flags rhs)
619 { return auto_reset_flags(unsigned(lhs) | unsigned(rhs)); }
620 constexpr auto_reset_flags operator&(auto_reset_flags lhs, auto_reset_flags rhs)
621 { return auto_reset_flags(unsigned(lhs) & unsigned(rhs)); }
622 constexpr auto_reset_flags operator^(auto_reset_flags lhs, auto_reset_flags rhs)
623 { return auto_reset_flags(unsigned(lhs) ^ unsigned(rhs)); }
624 constexpr auto_reset_flags operator~(auto_reset_flags arg)
625 { return auto_reset_flags(~unsigned(arg)); }
626
636 template<auto_reset_flags Flags>
638 {
639 public:
642 _st(nullptr)
643 {}
651 _st(st.get())
652 {}
653
655 auto_reset(statement * st) noexcept:
656 _st(st)
657 {}
658
659 auto_reset(const auto_reset &) = delete;
660 auto_reset & operator=(const auto_reset &) = delete;
661 auto_reset(auto_reset && src) noexcept:
662 _st(src._st)
663 {
664 src._st = nullptr;
665 }
666 auto_reset & operator=(auto_reset && src) noexcept
667 {
668 destroy();
669 _st = src._st;
670 src._st = nullptr;
671 return *this;
672 }
673
675 ~auto_reset() noexcept
676 { destroy(); }
677
679 statement * operator->() const noexcept
680 { return _st; }
681
682 private:
683 void destroy() noexcept
684 {
685 if (_st)
686 {
687 if constexpr ((Flags & auto_reset_flags::reset) != auto_reset_flags::none)
688 _st->reset();
690 _st->clear_bindings();
691 }
692 }
693 private:
694 statement * _st;
695 };
696
699}
700
701#endif
702
sqlite3_bind_null
sqlite3_bind_parameter_count
sqlite3_bind_parameter_index
sqlite3_bind_parameter_name
#define SQLITE_VERSION_NUMBER
RAII wrapper that resets statement on destruction.
Definition statement_iface.hpp:638
auto_reset()
Constructs an empty instance with no statement.
Definition statement_iface.hpp:641
auto_reset(const std::unique_ptr< statement > &st) noexcept
Constructs an instance referring to a given statement.
Definition statement_iface.hpp:650
~auto_reset() noexcept
Resets the statement if present.
Definition statement_iface.hpp:675
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:655
statement * operator->() const noexcept
Access the stored statement.
Definition statement_iface.hpp:679
A reference to a null terminated string.
Definition string_param.hpp:37
Database Connection.
Definition database_iface.hpp:108
Base functionality for all fake wrapper classes
Definition handle.hpp:27
sqlite3_stmt * c_ptr() const noexcept
Definition handle.hpp:45
Parses text containing multiple SQL statements.
Definition statement_iface.hpp:587
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:590
Prepared Statement Object.
Definition statement_iface.hpp:41
explain_type isexplain() const noexcept
Query the EXPLAIN Setting for the statement.
Definition statement_iface.hpp:174
bool step()
Evaluate the statement.
void bind_reference(int idx, const std::string_view &val, void(*unref)(const char *))
Bind a string reference to a parameter of the statement.
class database & database() const noexcept
Returns the database to which this statement belongs.
Definition statement_iface.hpp:124
void bind_reference(int idx, const blob_view &val, void(*unref)(const std::byte *))
Bind a blob reference to a parameter of the statement.
bool readonly() const noexcept
Determine if the statement writes to the database.
Definition statement_iface.hpp:183
void reset() noexcept
Reset the statement.
Definition statement_iface.hpp:144
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:199
bool busy() const noexcept
Determine if the statement has been reset.
Definition statement_iface.hpp:152
const value & raw_column_value(int idx) const noexcept
Get result values from a query as a raw value object.
Definition statement_iface.hpp:473
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:350
const char * sql() const noexcept
Returns a pointer to a copy of the SQL text used to create the statement.
Definition statement_iface.hpp:538
void bind(int idx, int val)
Bind an int value to a parameter of the statement.
Definition statement_iface.hpp:206
int column_type(int idx) const noexcept
Default datatype of the result column.
Definition statement_iface.hpp:483
allocated_string expanded_sql() const
Returns SQL text of the statement with bound parameters expanded.
void bind(int idx, T *ptr, const char *type, void(*destroy)(T *))
Definition statement_iface.hpp:336
void bind(int idx, const zero_blob &val)
Bind a blob of zeroes to a parameter of the statement.
Definition statement_iface.hpp:324
int column_count() const noexcept
Number of columns in a result set.
Definition statement_iface.hpp:413
void bind(int idx, int64_t val)
Bind an int64_t value to a parameter of the statement.
Definition statement_iface.hpp:213
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:512
const char * bind_parameter_name(int idx) const noexcept
Returns the name of a parameter with a given index.
Definition statement_iface.hpp:396
const char * column_origin_name(int idx) const noexcept
Table column that is the origin of a result column.
Definition statement_iface.hpp:520
static std::unique_ptr< statement > create(const database &db, const string_param &sql, unsigned int flags=0)
Compile an SQL statement.
void bind_reference(int idx, const std::u8string_view &val, void(*unref)(const char8_t *))
Bind a string reference to a parameter of the statement.
const char * column_database_name(int idx) const noexcept
Database that is the origin of a result column.
Definition statement_iface.hpp:504
~statement() noexcept
Equivalent to sqlite3_finalize.
Definition statement_iface.hpp:116
void bind(int idx, double val)
Bind a double value to a parameter of the statement.
Definition statement_iface.hpp:220
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:101
explain_type
Return type for isexplain()
Definition statement_iface.hpp:159
@ explain_query_plan
The statement is an EXPLAIN QUERY PLAN.
@ explain
The statement is an EXPLAIN statement.
@ not_explain
The statement is an ordinary statement.
const char * column_name(int idx) const noexcept
Name of the result column.
Definition statement_iface.hpp:496
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:380
void clear_bindings() noexcept
Reset all bindings on the statement.
Definition statement_iface.hpp:372
int bind_parameter_index(const string_param &name) const noexcept
Returns the index of a parameter with a given name.
Definition statement_iface.hpp:388
const char * column_declared_type(int idx) const noexcept
Declared datatype of a result column.
Definition statement_iface.hpp:528
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:83
int data_count() const noexcept
Number of columns in a result set.
Definition statement_iface.hpp:427
Dynamically Typed Value Object.
Definition value_iface.hpp:35
An efficient blob of zeroes of a given size.
Definition span.hpp:256
sqlite3_clear_bindings
sqlite3_column_value
sqlite3_column_count
sqlite3_column_database_name
sqlite3_column_decltype
sqlite3_column_name
sqlite3_data_count
sqlite3_db_handle
sqlite3_sql
sqlite3_finalize
auto_reset_flags
Bitwise mask of resets to perform for thinsqlitepp::auto_reset.
Definition statement_iface.hpp:612
@ reset
Reset the statement (does not affect the bindings)
@ clear_bindings
Reset the bindings.
T is_same_v
ThinSQLite++ namespace.
Definition backup_iface.hpp:17
T release(T... args)
sqlite3_reset
sqlite3_stmt_busy
sqlite3_stmt_isexplain
sqlite3_stmt_readonly