ThinSQLite++
A thin, safe and convenient modern C++ wrapper for the SQLite API.
Loading...
Searching...
No Matches
database_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_DATABASE_IFACE_INCLUDED
10#define HEADER_SQLITEPP_DATABASE_IFACE_INCLUDED
11
12#include "handle.hpp"
13#include "exception_iface.hpp"
14#include "mutex_iface.hpp"
15#include "blob_iface.hpp"
16#include "snapshot_iface.hpp"
17#include "memory_iface.hpp"
18#include "string_param.hpp"
19#include "span.hpp"
20#include "meta.hpp"
21
22#include <memory>
23#include <functional>
24#include <optional>
25
26#ifdef __GNUC__
27 #pragma GCC diagnostic push
28 #pragma GCC diagnostic ignored "-Wcast-function-type"
29
30 #if defined(__APPLE__) && defined(__clang__)
31 #pragma GCC diagnostic ignored "-Wunguarded-availability-new"
32 #pragma GCC diagnostic ignored "-Wdeprecated-declarations"
33 #endif
34#endif
35
36
37
38namespace thinsqlitepp
39{
40 SQLITEPP_EXPORTED class context;
41 SQLITEPP_EXPORTED class row;
42 SQLITEPP_EXPORTED class value;
43
45
46 struct database_detector
47 {
48 SQLITEPP_CALL_DETECTOR(enable_load_extension, int, sqlite3_enable_load_extension, (T *)nullptr, int{});
49 SQLITEPP_CALL_DETECTOR(load_extension, int, sqlite3_load_extension, (T *)nullptr,
50 (const char *)nullptr,
51 (const char *)nullptr,
52 (char **)nullptr);
53
54 SQLITEPP_METHOD_DETECTOR(void, step, (context *)nullptr, int{}, (value **)nullptr);
55 SQLITEPP_METHOD_DETECTOR(void, last, (context *)nullptr);
56 SQLITEPP_METHOD_DETECTOR(void, inverse, (context *)nullptr, int{}, (value **)nullptr);
57 SQLITEPP_METHOD_DETECTOR(void, current, (context *)nullptr);
58
59 public:
60 template<class T>
62
63 template<class T>
64 static constexpr bool is_aggregate_function = has_noexcept_step<T> && has_noexcept_last<T>;
65
66 template<class T>
67 static constexpr bool is_aggregate_window_function = is_aggregate_function<T> && has_noexcept_inverse<T> && has_noexcept_current<T>;
68
69 template<class R, class T, class... ArgTypes>
70 static constexpr bool is_pointer_to_callback = std::is_null_pointer_v<T> ||
72
73 template<class R, class T, class... ArgTypes>
74 static constexpr bool is_pointer_to_throwing_callback = std::is_null_pointer_v<T> ||
76
77 template<class T>
78 static constexpr bool is_pointer_to_function = std::is_null_pointer_v<T> ||
80 (
81 is_function<std::remove_pointer_t<T>> ||
82 is_aggregate_function<std::remove_pointer_t<T>>
83 )
84 );
85
86 template<class T>
87 static constexpr bool is_pointer_to_window_function = std::is_null_pointer_v<T> ||
88 (std::is_pointer_v<T> && is_aggregate_window_function<std::remove_pointer_t<T>>);
89 };
90
92
97
107 SQLITEPP_EXPORTED
108 class database final : public handle<sqlite3, database>
109 {
110 private:
111 template<int Code, class ...Args>
112 struct config_option
113 {
114 static void apply(database & db, Args && ...args)
115 {
116 int res = sqlite3_db_config(db.c_ptr(), Code, std::forward<Args>(args)...);
117 if (res != SQLITE_OK)
118 throw exception(res, db);
119 }
120 };
121 template<int Code> struct config_mapping;
122
123 template<int Code, class ...Args>
124 struct vtab_config_option
125 {
126 static void apply(database & db, Args && ...args)
127 {
128 int res = sqlite3_vtab_config(db.c_ptr(), Code, std::forward<Args>(args)...);
129 if (res != SQLITE_OK)
130 throw exception(res, db);
131 }
132 };
133 template<int Code> struct vtab_config_mapping;
134
135 public:
141 static std::unique_ptr<database> open(const string_param & db_filename, int flags, const char * vfs = nullptr);
142
144 ~database() noexcept
145 { sqlite3_close_v2(c_ptr()); }
146
147
148 //MARK: -
149
155 void busy_timeout(int ms)
156 { check_error(sqlite3_busy_timeout(c_ptr(), ms)); }
157
158
159 //MARK: -
160
161 #if SQLITE_VERSION_NUMBER >= SQLITEPP_SQLITE_VERSION(3, 50, 0)
162
168 void setlk_timeout(int ms, int flags = 0)
169 { check_error(sqlite3_setlk_timeout(c_ptr(), ms, flags)); }
170
171 #endif
172
173 //MARK: Client data
174
175 #if SQLITE_VERSION_NUMBER >= SQLITEPP_SQLITE_VERSION(3, 44, 0)
176
182 void set_clientdata(const string_param & name, void * ptr, void(*destroy)(void*) = nullptr)
183 { check_error(sqlite3_set_clientdata(c_ptr(), name.c_str(), ptr, destroy)); }
184
193 template<class T>
195 {
196 set_clientdata(name, data.release(), [](void * d) {
197 delete static_cast<T *>(d);
198 });
199 }
200
210 template<class T>
211 T * get_clientdata(const string_param & name) noexcept
212 { return static_cast<T *>(sqlite3_get_clientdata(c_ptr(), name.c_str())); }
213
214 #endif
215
216 //MARK: -
217
223 int64_t changes() const noexcept
224 {
225 #if SQLITE_VERSION_NUMBER >= SQLITEPP_SQLITE_VERSION(3, 36, 1)
226 return sqlite3_changes64(c_ptr());
227 #else
228 return sqlite3_changes(c_ptr());
229 #endif
230 }
231
232 //MARK: -
233
234 #if SQLITE_VERSION_NUMBER >= SQLITEPP_SQLITE_VERSION(3, 51, 1)
240 void set_errmsg(int errcode, const string_param & message)
241 { check_error(sqlite3_set_errmsg(c_ptr(), errcode, message.c_str())); }
242 #endif
243
244 //MARK: - exec
245
250
266
267 #if __cpp_char8_t >= 201811
269 template<class T>
271 { return exec(std::string_view((const char *)sql.data(), sql.size())); }
272 #endif
273
313 template<class T>
314 SQLITEPP_ENABLE_IF((
319 T) exec(std::string_view sql, T callback);
320
321 #if __cpp_char8_t >= 201811
323 template<class T>
324 T exec(std::u8string_view sql, T callback)
325 { return exec(std::string_view((const char *)sql.data(), sql.size()), callback); }
326 #endif
327
329
334
335 //MARK: - busy_handler
336
346 template<class T>
348 void) busy_handler(int (* handler)(type_identity_t<T> data_ptr, int count_invoked) noexcept, T data_ptr)
349 { check_error(sqlite3_busy_handler(this->c_ptr(), (int (*)(void*,int))handler, data_ptr)); }
350
365 template<class T>
366 SQLITEPP_ENABLE_IF((database_detector::is_pointer_to_callback<bool, T, int>),
367 void) busy_handler(T handler_ptr);
368
369
370 //MARK: - collation_needed
371
381 template<class T>
383 void) collation_needed(T data_ptr, void (* handler)(type_identity_t<T> data_ptr, database *, int encoding, const char * name) noexcept)
384 { check_error(sqlite3_collation_needed(this->c_ptr(), data_ptr, (void(*)(void*,sqlite3*,int,const char*))handler)); }
385
402 template<class T>
403 SQLITEPP_ENABLE_IF((database_detector::is_pointer_to_callback<void, T, database *, int, const char *>),
404 void) collation_needed(T handler_ptr);
405
406 //MARK: - commit_hook
407
417 template<class T>
419 void) commit_hook(int (* handler)(type_identity_t<T> data_ptr) noexcept, T data_ptr) noexcept
420 { sqlite3_commit_hook(this->c_ptr(), (int(*)(void*))handler, data_ptr); }
421
435 template<class T>
436 SQLITEPP_ENABLE_IF((database_detector::is_pointer_to_callback<bool, T>),
437 void) commit_hook(T handler_ptr) noexcept;
438
439
440 //MARK: - rollback_hook
441
451 template<class T>
453 void) rollback_hook(void (* handler)(type_identity_t<T> data_ptr) noexcept, T data_ptr) noexcept
454 { sqlite3_rollback_hook(this->c_ptr(), (void(*)(void*))(handler), data_ptr); }
455
469 template<class T>
470 SQLITEPP_ENABLE_IF((database_detector::is_pointer_to_callback<void, T>),
471 void) rollback_hook(T handler_ptr) noexcept;
472
473
474 //MARK: - update_hook
475
485 template<class T>
487 void) update_hook(void (* handler)(type_identity_t<T> data_ptr, int op, const char * db_name, const char * table, sqlite3_int64 rowid) noexcept,
488 T data_ptr) noexcept
489 { sqlite3_update_hook(this->c_ptr(), (void(*)(void*,int,char const *,char const *,sqlite3_int64))(handler), data_ptr); }
490
491
505 template<class T>
506 SQLITEPP_ENABLE_IF((database_detector::is_pointer_to_callback<void, T, int, const char *, const char *, int64_t>),
507 void) update_hook(T handler_ptr) noexcept;
508
509 //MARK: - preupdate_hook
510
511 #if SQLITE_VERSION_NUMBER >= SQLITEPP_SQLITE_VERSION(3, 16, 0) && defined(SQLITE_ENABLE_PREUPDATE_HOOK)
525 template<class T>
527 void) preupdate_hook(void (* handler)(type_identity_t<T> data_ptr,
528 database * db,
529 int op,
530 const char * db_name,
531 const char * table,
532 sqlite3_int64 rowid_old,
533 sqlite3_int64 rowid_new) noexcept,
534 T data_ptr) noexcept
535 {
536 sqlite3_preupdate_hook(this->c_ptr(), (void(*)(void*,sqlite3 *,int,char const *,char const *,sqlite3_int64,sqlite3_int64))(handler),
537 data_ptr);
538 }
539
557 template<class T>
558 SQLITEPP_ENABLE_IF((database_detector::is_pointer_to_callback<void, T, database *, int, const char *, const char *, int64_t, int64_t>),
559 void) preupdate_hook(T handler_ptr) noexcept;
560
561 #endif
562
572 template<class T>
574 void) wal_hook(int (* handler)(type_identity_t<T> data_ptr, database * db, const char * db_name, int num_pages) noexcept,
575 T data_ptr) noexcept
576 { sqlite3_wal_hook(this->c_ptr(), (int(*)(void *,sqlite3*,const char*,int))(handler), data_ptr); }
577
578
592 template<class T>
593 SQLITEPP_ENABLE_IF((database_detector::is_pointer_to_throwing_callback<void, T, database *, const char *, int>),
594 void) wal_hook(T handler_ptr) noexcept;
595
597
598 //MARK: -
599
600 #if defined(SQLITE_ENABLE_PREUPDATE_HOOK)
601 #if SQLITE_VERSION_NUMBER >= SQLITEPP_SQLITE_VERSION(3, 16, 0)
602
606
617 value * preupdate_old(int column_idx);
618
629 value * preupdate_new(int column_idx);
630
641 int preupdate_count() const noexcept
642 { return sqlite3_preupdate_count(c_ptr()); }
643
659 int preupdate_depth() const noexcept
660 { return sqlite3_preupdate_depth(c_ptr()); }
661
662
663 #endif
664 #if SQLITE_VERSION_NUMBER >= SQLITEPP_SQLITE_VERSION(3, 36, 0)
675 int preupdate_blobwrite() const noexcept
677
678
679 #endif
680 #endif
681
682
684
685 //MARK: -
686
690
701 std::pair<int, int> checkpoint(const string_param & db_name, int mode = SQLITE_CHECKPOINT_PASSIVE);
702
708 void autocheckpoint(int num_frames)
709 { check_error(sqlite3_wal_autocheckpoint(c_ptr(), num_frames)); }
710
711 /* @} */
712
713
714
715 //MARK: - create_collation
716
721
736 template<class T>
738 void) create_collation(const string_param & name, int encoding,
739 T collator_ptr,
740 int (*compare)(type_identity_t<T> collator, int lhs_len, const void * lhs_bytes, int rhs_len, const void * rhs_bytes) noexcept,
741 void (*destructor)(type_identity_t<T> collator) noexcept);
742
762 template<class T>
763 SQLITEPP_ENABLE_IF((database_detector::is_pointer_to_callback<int, T, span<const std::byte>, span<const std::byte>>),
764 void) create_collation(const string_param & name, int encoding, T collator_ptr,
765 void (*destructor)(type_identity_t<T> obj) noexcept = nullptr);
766
768
769 //MARK: - create_function
770
775
795 template<class T>
797 void) create_function(const char * name, int arg_count, int flags, T data_ptr,
798 void (*func)(context *, int, value **) noexcept,
799 void (*step)(context *, int, value **) noexcept,
800 void (*last)(context*) noexcept,
801 void (*destructor)(type_identity_t<T> data_ptr) noexcept);
802
803
804
831 template<class T>
832 SQLITEPP_ENABLE_IF(database_detector::is_pointer_to_function<T>,
833 void) create_function(const char * name, int arg_count, int flags,
834 T impl_ptr, void (*destructor)(type_identity_t<T> obj) noexcept = nullptr);
835
836 //MARK: - create_window_function
837
838#if SQLITE_VERSION_NUMBER >= SQLITEPP_SQLITE_VERSION(3, 25, 0)
839
862 template<class T>
864 void) create_window_function(const char * name, int arg_count, int flags, T data_ptr,
865 void (*step)(context *, int, value **) noexcept,
866 void (*last)(context*) noexcept,
867 void (*current)(context*) noexcept,
868 void (*inverse)(context *, int, value **) noexcept,
869 void (*destructor)(type_identity_t<T> data_ptr) noexcept);
870
871
897 template<class T>
898 SQLITEPP_ENABLE_IF(database_detector::is_pointer_to_window_function<T>,
899 void) create_window_function(const char * name, int arg_count, int flags,
900 T impl_ptr, void (*destructor)(type_identity_t<T> obj) noexcept = nullptr);
901#endif
902
904
905 //MARK: -
906#if SQLITE_VERSION_NUMBER >= SQLITEPP_SQLITE_VERSION(3, 10, 0)
915 {
916 if (int res = sqlite3_db_cacheflush(c_ptr()); res != SQLITE_OK)
917 throw exception(res); //sic! sqlite3_db_cacheflush doesn't set DB error
918 }
919#endif
934 template<int Code, class ...Args>
935 auto config(Args && ...args) ->
936 #ifndef DOXYGEN
937 //void but prevents instantiation with wrong types
938 decltype(
939 config_mapping<Code>::type::apply(*this, std::forward<decltype(args)>(args)...)
940 )
941 #else
942 void
943 #endif
944 { config_mapping<Code>::type::apply(*this, std::forward<Args>(args)...); }
945
946
947 //MARK: - create_module
948
953
962 void create_module(const string_param & name, const sqlite3_module * mod)
963 { check_error(sqlite3_create_module_v2(c_ptr(), name.c_str(), mod, nullptr, nullptr)); }
964
976 template<typename T, typename D = void(*)(T *) noexcept>
977 SQLITEPP_ENABLE_IF((std::is_convertible_v<D, void(*)(T *) noexcept>),
978 void) create_module(const string_param & name, const sqlite3_module * mod,
979 T * data, D destructor = nullptr)
980 { check_error(sqlite3_create_module_v2(c_ptr(), name.c_str(), mod, (void*)data, (void (*)(void *))(void(*)(T *) noexcept)destructor)); }
981
982
983 //MARK: -
984
990 void declare_vtab(const string_param & sdl)
991 { check_error(sqlite3_declare_vtab(c_ptr(), sdl.c_str())); }
992
993
1008 template<int Code, class ...Args>
1009 auto vtab_config(Args && ...args) ->
1010 #ifndef DOXYGEN
1011 //void but prevents instantiation with wrong types
1012 decltype(
1013 vtab_config_mapping<Code>::type::apply(*this, std::forward<decltype(args)>(args)...)
1014 )
1015 #else
1016 void
1017 #endif
1018 { vtab_config_mapping<Code>::type::apply(*this, std::forward<Args>(args)...); }
1019
1029 int vtab_on_conflict() const noexcept
1030 { return sqlite3_vtab_on_conflict(c_ptr()); }
1031
1032 //MARK: - drop_modules
1033#if SQLITE_VERSION_NUMBER >= SQLITEPP_SQLITE_VERSION(3, 30, 0)
1042 { check_error(sqlite3_drop_modules(c_ptr(), nullptr)); }
1043
1051 void drop_modules_except(const char * const * keep)
1052 { check_error(sqlite3_drop_modules(c_ptr(), (const char **)keep)); }
1053
1054
1062 template<size_t N>
1063 SQLITEPP_ENABLE_IF(N > 0,
1064 void) drop_modules_except(const char * const (&keep)[N])
1065 {
1066 if (keep[N-1] != nullptr) throw exception(SQLITE_MISUSE);
1067 check_error(sqlite3_drop_modules(this->c_ptr(), (const char **)keep));
1068 }
1069
1080 template<class ...Args>
1082 void) drop_modules_except(Args && ...args)
1083 {
1084 const char * buf[] = {string_param(std::forward<Args>(args)).c_str() ..., nullptr};
1085 check_error(sqlite3_drop_modules(this->c_ptr(), buf));
1086 }
1087#endif
1088
1090
1091 //MARK: -
1092
1098 void extended_result_codes(bool onoff)
1099 { check_error(sqlite3_extended_result_codes(c_ptr(), onoff)); }
1100
1101
1107 void file_control(const string_param & db_name, int op, void * data)
1108 { check_error(sqlite3_file_control(c_ptr(), db_name.c_str(), op, data)); }
1109
1115 const char * filename(const string_param & db_name) const noexcept
1116 {
1117 auto ret = sqlite3_db_filename(c_ptr(), db_name.c_str());
1118 return ret ? ret : "";
1119 }
1120
1126 bool get_autocommit() const noexcept
1127 { return sqlite3_get_autocommit(c_ptr()); }
1128
1134 void interrupt() noexcept
1135 { sqlite3_interrupt(c_ptr()); }
1136
1137 #if SQLITE_VERSION_NUMBER >= SQLITEPP_SQLITE_VERSION(3, 41, 0)
1145 bool is_interrupted() noexcept
1146 { return sqlite3_is_interrupted(c_ptr()) != 0; }
1147 #endif
1148
1154 int64_t last_insert_rowid() const noexcept
1155 { return sqlite3_last_insert_rowid(c_ptr()); }
1156
1157#if SQLITE_VERSION_NUMBER >= SQLITEPP_SQLITE_VERSION(3, 18, 0)
1167#endif
1168
1169 //returns -1 on bad limit or other issues
1179 int limit(int id, int new_val) noexcept
1180 { return sqlite3_limit(c_ptr(), id, new_val); }
1181
1182
1183
1187
1194 { check_error(call_sqlite3_enable_load_extension(this->c_ptr(), val)); }
1195
1196
1202 void load_extension(const string_param & file, const string_param & proc = nullptr);
1203
1204 #if SQLITE_VERSION_NUMBER >= SQLITEPP_SQLITE_VERSION(3, 8, 7)
1205
1213 void auto_extension(void(*entry_point)(database *, const char **, const struct sqlite3_api_routines *))
1214 { check_error(sqlite3_auto_extension((void(*)(void))entry_point)); }
1215
1223 void cancel_auto_extension(void(*entry_point)(database *, const char **, const struct sqlite3_api_routines *))
1224 { check_error(sqlite3_cancel_auto_extension((void(*)(void))entry_point)); }
1225
1226
1236
1237 #endif
1238
1240
1246 class mutex * mutex() const noexcept
1247 { return (class mutex *)sqlite3_db_mutex(c_ptr()); }
1248
1249 //MARK: - next_statement
1250
1256 const class statement * next_statement(const class statement * prev) const noexcept
1257 { return (class statement *)sqlite3_next_stmt(c_ptr(), (sqlite3_stmt *)prev); }
1258
1260 class statement * next_statement(const class statement * prev) noexcept
1261 { return (class statement *)sqlite3_next_stmt(c_ptr(), (sqlite3_stmt *)prev); }
1262
1263 //MARK: -
1264
1270 void overload_function(const string_param & name, int arg_count)
1271 { check_error(sqlite3_overload_function(c_ptr(), name.c_str(), arg_count)); }
1272
1273 //MARK: - progress_handler
1274
1289 template<class T>
1290 SQLITEPP_ENABLE_IF(std::is_pointer_v<T> || std::is_null_pointer_v<T>,
1291 void) progress_handler(int step_count, int(*handler)(type_identity_t<T> data_ptr) noexcept, T data_ptr) const noexcept
1292 { sqlite3_progress_handler(this->c_ptr(), step_count, (int(*)(void*))handler, data_ptr); }
1293
1311 template<class T>
1312 SQLITEPP_ENABLE_IF((std::is_null_pointer_v<T> ||
1314 void) progress_handler(int step_count, T handler_ptr) const noexcept;
1315
1316 //MARK: -
1328
1334 void release_memory() const
1335 { check_error(sqlite3_db_release_memory(c_ptr())); }
1336
1337 //MARK: - status
1338
1340 struct status
1341 {
1342 int current;
1343 int high;
1344 };
1345
1346 #if SQLITE_VERSION_NUMBER >= SQLITEPP_SQLITE_VERSION(3, 51, 0)
1347 [[deprecated("use status64")]]
1348 #endif
1354 struct status status(int op, bool reset = false) const;
1355
1356 #if SQLITE_VERSION_NUMBER >= SQLITEPP_SQLITE_VERSION(3, 51, 1)
1357
1360 {
1361 sqlite3_int64 current;
1362 sqlite3_int64 high;
1363 };
1364
1370 struct status64 status64(int op, bool reset = false) const;
1371
1372 #endif
1373
1374 //MARK: - table_column_metadata
1375
1378 {
1379 const char * data_type;
1380 const char * collation_sequence;
1384 };
1385
1392 const string_param & table_name,
1393 const string_param & column_name) const;
1394
1395 //MARK: -
1396
1402 int64_t total_changes() const noexcept
1403 {
1404 #if SQLITE_VERSION_NUMBER >= SQLITEPP_SQLITE_VERSION(3, 36, 1)
1405 return sqlite3_total_changes64(c_ptr());
1406 #else
1407 return sqlite3_total_changes(c_ptr());
1408 #endif
1409 }
1410
1411#if SQLITE_VERSION_NUMBER >= SQLITEPP_SQLITE_VERSION(3, 34, 0)
1412
1420 int txn_state(const string_param & schema) const noexcept
1421 { return sqlite3_txn_state(c_ptr(), schema.c_str()); }
1422#endif
1423
1430 const string_param & table,
1431 const string_param & column,
1432 int64_t rowid,
1433 bool writable);
1434
1435#if SQLITE_VERSION_NUMBER >= SQLITEPP_SQLITE_VERSION(3, 39, 0)
1436
1440
1449
1457 span<std::byte> serialize_reference(const string_param & schema_name) noexcept;
1458
1459
1467 void deserialize(const string_param & schema_name,
1468 std::byte * buf,
1469 size_t size,
1470 size_t buf_size,
1471 unsigned flags = 0)
1472 { check_error(sqlite3_deserialize(c_ptr(), schema_name.c_str(), (unsigned char *)buf, int64_size(size), int64_size(buf_size), flags)); }
1473
1474
1484 void deserialize(const string_param & schema_name,
1485 const std::byte * buf,
1486 size_t size,
1487 size_t buf_size,
1488 unsigned flags = 0)
1489 { deserialize(schema_name, (std::byte *)buf, size, buf_size, flags | SQLITE_DESERIALIZE_READONLY); }
1490
1491
1501 void deserialize(const string_param & schema_name,
1502 allocated_bytes buf,
1503 size_t size,
1504 size_t buf_size,
1505 unsigned flags = 0);
1506
1507
1508
1510#endif
1511
1515
1516#if SQLITE_VERSION_NUMBER >= SQLITEPP_SQLITE_VERSION(3, 10, 0) && (THINSQLITEPP_ENABLE_EXPERIMENTAL || THINSQLITEPP_ENABLE_EXPIREMENTAL)
1528
1539 void open_snapshot(const string_param & schema, const snapshot & snap)
1540 { check_error(sqlite3_snapshot_open(c_ptr(), schema.c_str(), snap.c_ptr())); }
1541
1553 { check_error(sqlite3_snapshot_recover(c_ptr(), db.c_str())); }
1554
1555#endif
1556
1558
1559
1560 #if SQLITE_VERSION_NUMBER >= SQLITEPP_SQLITE_VERSION(3, 39, 0)
1571 const char * db_name(int idx) noexcept
1572 { return sqlite3_db_name(c_ptr(), idx); }
1573
1574 #endif
1575
1576 //MARK: - Private methods
1577
1578 private:
1579 void check_error(int res) const
1580 {
1581 if (res != SQLITE_OK)
1582 throw exception(res, this);
1583 }
1584
1585 template<class T>
1586 static int call_sqlite3_enable_load_extension(T * db, int onoff)
1587 {
1588 if constexpr (database_detector::has_enable_load_extension<T>)
1589 return sqlite3_enable_load_extension(db, onoff);
1590 else
1591 return SQLITE_ERROR;
1592 }
1593
1594 template<class T>
1595 static int call_sqlite3_load_extension(T * db, const char * file, const char * proc, char ** err)
1596 {
1597 if constexpr (database_detector::has_load_extension<T>)
1598 return sqlite3_load_extension(db, file, proc, err);
1599 else
1600 return SQLITE_ERROR;
1601 }
1602 };
1603
1605
1607
1608
1609 SQLITEPP_SUPPRESS_SILLY_VARARG_WARNING_BEGIN
1610
1611 #if SQLITEPP_USE_VARARG_POUND_POUND_TRICK
1612
1613 #define SQLITEPP_DEFINE_DB_OPTION(code, ...) \
1614 template<> struct database::config_mapping<code> { using type = database::config_option<code, ##__VA_ARGS__>; };
1615
1616 //Idiotic GCC in pedantic mode warns on MACRO(arg) for MARCO(x,...) in < C++20 mode
1617 //with no way to disable the warning(!!!).
1618 #define SQLITEPP_DEFINE_VTAB_OPTION_0(code) \
1619 template<> struct database::vtab_config_mapping<code> { using type = database::vtab_config_option<code>; };
1620 #define SQLITEPP_DEFINE_VTAB_OPTION_N(code, ...) \
1621 template<> struct database::vtab_config_mapping<code> { using type = database::vtab_config_option<code, ##__VA_ARGS__>; };
1622
1623 #else
1624
1625 #define SQLITEPP_DEFINE_DB_OPTION(code, ...) \
1626 template<> struct database::config_mapping<code> { using type = database::config_option<code __VA_OPT__(,) __VA_ARGS__>; };
1627
1628 #define SQLITEPP_DEFINE_VTAB_OPTION_N(code, ...) \
1629 template<> struct database::vtab_config_mapping<code> { using type = database::vtab_config_option<code __VA_OPT__(,) __VA_ARGS__>; };
1630
1631 #define SQLITEPP_DEFINE_VTAB_OPTION_0(code) SQLITEPP_DEFINE_VTAB_OPTION_N(code)
1632
1633 #endif
1634
1635
1636 //@ [DB Options]
1637#ifdef SQLITE_DBCONFIG_MAINDBNAME
1638 SQLITEPP_DEFINE_DB_OPTION( SQLITE_DBCONFIG_MAINDBNAME, const char *);
1639#endif
1640 SQLITEPP_DEFINE_DB_OPTION( SQLITE_DBCONFIG_LOOKASIDE, void *, int, int);
1641 SQLITEPP_DEFINE_DB_OPTION( SQLITE_DBCONFIG_ENABLE_FKEY, int, int *);
1642 SQLITEPP_DEFINE_DB_OPTION( SQLITE_DBCONFIG_ENABLE_TRIGGER, int, int *);
1643#ifdef SQLITE_DBCONFIG_ENABLE_FTS3_TOKENIZER
1644 SQLITEPP_DEFINE_DB_OPTION( SQLITE_DBCONFIG_ENABLE_FTS3_TOKENIZER, int, int *);
1645#endif
1646#ifdef SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION
1647 SQLITEPP_DEFINE_DB_OPTION( SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION, int, int *);
1648#endif
1649#ifdef SQLITE_DBCONFIG_NO_CKPT_ON_CLOSE
1650 SQLITEPP_DEFINE_DB_OPTION( SQLITE_DBCONFIG_NO_CKPT_ON_CLOSE, int, int *);
1651#endif
1652#ifdef SQLITE_DBCONFIG_ENABLE_QPSG
1653 SQLITEPP_DEFINE_DB_OPTION( SQLITE_DBCONFIG_ENABLE_QPSG, int, int *);
1654#endif
1655#ifdef SQLITE_DBCONFIG_TRIGGER_EQP
1656 SQLITEPP_DEFINE_DB_OPTION( SQLITE_DBCONFIG_TRIGGER_EQP, int, int *);
1657#endif
1658#ifdef SQLITE_DBCONFIG_RESET_DATABASE
1659 SQLITEPP_DEFINE_DB_OPTION( SQLITE_DBCONFIG_RESET_DATABASE, int, int *);
1660#endif
1661#ifdef SQLITE_DBCONFIG_DEFENSIVE
1662 SQLITEPP_DEFINE_DB_OPTION( SQLITE_DBCONFIG_DEFENSIVE, int, int *);
1663#endif
1664#ifdef SQLITE_DBCONFIG_WRITABLE_SCHEMA
1665 SQLITEPP_DEFINE_DB_OPTION( SQLITE_DBCONFIG_WRITABLE_SCHEMA, int, int *);
1666#endif
1667#ifdef SQLITE_DBCONFIG_LEGACY_ALTER_TABLE
1668 SQLITEPP_DEFINE_DB_OPTION( SQLITE_DBCONFIG_LEGACY_ALTER_TABLE, int, int *);
1669#endif
1670#ifdef SQLITE_DBCONFIG_ENABLE_VIEW
1671 SQLITEPP_DEFINE_DB_OPTION( SQLITE_DBCONFIG_ENABLE_VIEW, int, int *);
1672#endif
1673#ifdef SQLITE_DBCONFIG_LEGACY_FILE_FORMAT
1674 SQLITEPP_DEFINE_DB_OPTION( SQLITE_DBCONFIG_LEGACY_FILE_FORMAT, int, int *);
1675#endif
1676#ifdef SQLITE_DBCONFIG_TRUSTED_SCHEMA
1677 SQLITEPP_DEFINE_DB_OPTION( SQLITE_DBCONFIG_TRUSTED_SCHEMA, int, int *);
1678#endif
1679#ifdef SQLITE_DBCONFIG_STMT_SCANSTATUS
1680 SQLITEPP_DEFINE_DB_OPTION( SQLITE_DBCONFIG_STMT_SCANSTATUS, int, int *);
1681#endif
1682#ifdef SQLITE_DBCONFIG_REVERSE_SCANORDER
1683 SQLITEPP_DEFINE_DB_OPTION( SQLITE_DBCONFIG_REVERSE_SCANORDER, int, int *);
1684#endif
1685#ifdef SQLITE_DBCONFIG_ENABLE_ATTACH_CREATE
1686 SQLITEPP_DEFINE_DB_OPTION( SQLITE_DBCONFIG_ENABLE_ATTACH_CREATE, int, int *);
1687#endif
1688#ifdef SQLITE_DBCONFIG_ENABLE_ATTACH_WRITE
1689 SQLITEPP_DEFINE_DB_OPTION( SQLITE_DBCONFIG_ENABLE_ATTACH_WRITE, int, int *);
1690#endif
1691#ifdef SQLITE_DBCONFIG_ENABLE_COMMENTS
1692 SQLITEPP_DEFINE_DB_OPTION( SQLITE_DBCONFIG_ENABLE_COMMENTS, int, int *);
1693#endif
1694 //@ [DB Options]
1695
1696 //@ [VTab Options]
1697
1698 SQLITEPP_DEFINE_VTAB_OPTION_N(SQLITE_VTAB_CONSTRAINT_SUPPORT, int);
1699#ifdef SQLITE_VTAB_INNOCUOUS
1700 SQLITEPP_DEFINE_VTAB_OPTION_0(SQLITE_VTAB_INNOCUOUS );
1701#endif
1702#ifdef SQLITE_VTAB_DIRECTONLY
1703 SQLITEPP_DEFINE_VTAB_OPTION_0(SQLITE_VTAB_DIRECTONLY );
1704#endif
1705#ifdef SQLITE_VTAB_USES_ALL_SCHEMAS
1706 SQLITEPP_DEFINE_VTAB_OPTION_0(SQLITE_VTAB_USES_ALL_SCHEMAS );
1707#endif
1708
1709 //@ [VTab Options]
1710
1711 #undef SQLITEPP_DEFINE_DB_OPTION
1712 #undef SQLITEPP_DEFINE_VTAB_OPTION_0
1713 #undef SQLITEPP_DEFINE_VTAB_OPTION_N
1714
1715 SQLITEPP_SUPPRESS_SILLY_VARARG_WARNING_END
1716
1718}
1719
1720#ifdef __GNUC__
1721 #pragma GCC diagnostic pop
1722#endif
1723
1724#endif
1725
sqlite3_auto_extension
sqlite3_busy_handler
sqlite3_busy_timeout
sqlite3_cancel_auto_extension
sqlite3_changes64
const T * c_str() const noexcept
Returns the stored pointer.
Definition string_param.hpp:51
SQL Function Context Object.
Definition context_iface.hpp:38
Database Connection.
Definition database_iface.hpp:109
void release_memory() const
Free memory used by the database connection.
Definition database_iface.hpp:1334
bool auto_increment
Whether column is auto-increment.
Definition database_iface.hpp:1383
void interrupt() noexcept
Interrupt a long-running query.
Definition database_iface.hpp:1134
void drop_modules_except(const char *const *keep)
Remove virtual table modules from database connection.
Definition database_iface.hpp:1051
const char * collation_sequence
Collation sequence name.
Definition database_iface.hpp:1380
int vtab_on_conflict() const noexcept
Determine the virtual table conflict policy.
Definition database_iface.hpp:1029
value * preupdate_new(int column_idx)
Returns value of a column of the table row after it is updated.
void busy_timeout(int ms)
Set a busy timeout.
Definition database_iface.hpp:155
void enable_load_extension(bool val)
Enable or disable extension loading.
Definition database_iface.hpp:1193
std::unique_ptr< blob > open_blob(const string_param &dbname, const string_param &table, const string_param &column, int64_t rowid, bool writable)
Open a blob.
void commit_hook(int(*handler)(type_identity_t< T > data_ptr) noexcept, T data_ptr) noexcept
Register a callback to be called on commit.
Definition database_iface.hpp:419
void drop_modules_except(const char *const (&keep)[N])
Remove virtual table modules from database connection.
Definition database_iface.hpp:1064
class mutex * mutex() const noexcept
Retrieve the mutex for the database connection.
Definition database_iface.hpp:1246
void cacheflush()
Flush caches to disk mid-transaction.
Definition database_iface.hpp:914
void create_function(const char *name, int arg_count, int flags, T data_ptr, void(*func)(context *, int, value **) noexcept, void(*step)(context *, int, value **) noexcept, void(*last)(context *) noexcept, void(*destructor)(type_identity_t< T > data_ptr) noexcept)
Create or redefine SQL function.
T exec(std::u8string_view sql, T callback)
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition database_iface.hpp:324
void update_hook(T handler_ptr) noexcept
Register a callback to be called whenever a row is updated, inserted or deleted in a rowid table.
int txn_state(const string_param &schema) const noexcept
Returns the transaction state of a database.
Definition database_iface.hpp:1420
T exec(std::string_view sql, T callback)
Run multiple statements of SQL with a callback.
void drop_modules()
Remove all virtual table modules from database connection.
Definition database_iface.hpp:1041
void deserialize(const string_param &schema_name, std::byte *buf, size_t size, size_t buf_size, unsigned flags=0)
Deserialize a database.
Definition database_iface.hpp:1467
void create_function(const char *name, int arg_count, int flags, T impl_ptr, void(*destructor)(type_identity_t< T > obj) noexcept=nullptr)
Create or redefine SQL function.
void create_collation(const string_param &name, int encoding, T collator_ptr, void(*destructor)(type_identity_t< T > obj) noexcept=nullptr)
Define a new collating sequence.
void drop_modules_except(Args &&...args)
Remove virtual table modules from database connection.
Definition database_iface.hpp:1082
void autocheckpoint(int num_frames)
Configure an auto-checkpoint.
Definition database_iface.hpp:708
void file_control(const string_param &db_name, int op, void *data)
Low-level control of database file.
Definition database_iface.hpp:1107
void open_snapshot(const string_param &schema, const snapshot &snap)
Start a read transaction on an historical snapshot.
Definition database_iface.hpp:1539
void wal_hook(int(*handler)(type_identity_t< T > data_ptr, database *db, const char *db_name, int num_pages) noexcept, T data_ptr) noexcept
Register a callback to be called each time data is committed to a database in wal mode.
Definition database_iface.hpp:574
void declare_vtab(const string_param &sdl)
Declare the schema of a virtual table.
Definition database_iface.hpp:990
column_metadata table_column_metadata(const string_param &db_name, const string_param &table_name, const string_param &column_name) const
Extract metadata about a column of a table.
void create_collation(const string_param &name, int encoding, T collator_ptr, int(*compare)(type_identity_t< T > collator, int lhs_len, const void *lhs_bytes, int rhs_len, const void *rhs_bytes) noexcept, void(*destructor)(type_identity_t< T > collator) noexcept)
Define a new collating sequence.
void busy_handler(T handler_ptr)
Register a callback to handle SQLITE_BUSY errors.
void commit_hook(T handler_ptr) noexcept
Register a callback to be called on commit.
auto config(Args &&...args) -> void
Configure database connection.
Definition database_iface.hpp:935
bool is_interrupted() noexcept
Returns whether or not an interrupt is currently in effect.
Definition database_iface.hpp:1145
void setlk_timeout(int ms, int flags=0)
Set a setlk timeout.
Definition database_iface.hpp:168
std::unique_ptr< snapshot > get_snapshot(const string_param &schema)
Record a database snapshot.
void auto_extension(void(*entry_point)(database *, const char **, const struct sqlite3_api_routines *))
Automatically load statically linked extension.
Definition database_iface.hpp:1213
~database() noexcept
Equivalent to sqlite3_close_v2.
Definition database_iface.hpp:144
std::pair< int, int > checkpoint(const string_param &db_name, int mode=SQLITE_CHECKPOINT_PASSIVE)
Checkpoint a database.
void create_window_function(const char *name, int arg_count, int flags, T impl_ptr, void(*destructor)(type_identity_t< T > obj) noexcept=nullptr)
Create or redefine SQL aggregate window function.
int preupdate_blobwrite() const noexcept
Returns the index of the column being written via sqlite3_blob_write.
Definition database_iface.hpp:675
void cancel_auto_extension(void(*entry_point)(database *, const char **, const struct sqlite3_api_routines *))
Cancel automatic extension Loading.
Definition database_iface.hpp:1223
static std::unique_ptr< database > open(const string_param &db_filename, int flags, const char *vfs=nullptr)
Open a new database connection.
void preupdate_hook(T handler_ptr) noexcept
Register a callback to be called prior to each INSERT, UPDATE, and DELETE operation on a database tab...
void extended_result_codes(bool onoff)
Enable or disable extended result codes.
Definition database_iface.hpp:1098
void set_clientdata(const string_param &name, std::unique_ptr< T > &&data)
Set arbitrary client data to this database connection.
Definition database_iface.hpp:194
const char * filename(const string_param &db_name) const noexcept
Return the filename for the database connection.
Definition database_iface.hpp:1115
void set_errmsg(int errcode, const string_param &message)
Set error code and message.
Definition database_iface.hpp:240
int preupdate_count() const noexcept
Returns the number of columns in the row that is being inserted, updated, or deleted.
Definition database_iface.hpp:641
int limit(int id, int new_val) noexcept
Set or retrieve run-time limits.
Definition database_iface.hpp:1179
class statement * next_statement(const class statement *prev) noexcept
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition database_iface.hpp:1260
void update_hook(void(*handler)(type_identity_t< T > data_ptr, int op, const char *db_name, const char *table, sqlite3_int64 rowid) noexcept, T data_ptr) noexcept
Register a callback to be called whenever a row is updated, inserted or deleted in a rowid table.
Definition database_iface.hpp:487
void create_window_function(const char *name, int arg_count, int flags, T data_ptr, void(*step)(context *, int, value **) noexcept, void(*last)(context *) noexcept, void(*current)(context *) noexcept, void(*inverse)(context *, int, value **) noexcept, void(*destructor)(type_identity_t< T > data_ptr) noexcept)
Create or redefine SQL aggregate window function.
void collation_needed(T data_ptr, void(*handler)(type_identity_t< T > data_ptr, database *, int encoding, const char *name) noexcept)
Register a callback to be called when undefined collation sequence is required.
Definition database_iface.hpp:383
void deserialize(const string_param &schema_name, const std::byte *buf, size_t size, size_t buf_size, unsigned flags=0)
Deserialize a database.
Definition database_iface.hpp:1484
void load_extension(const string_param &file, const string_param &proc=nullptr)
Load an extension.
int64_t last_insert_rowid() const noexcept
Returns last insert rowid.
Definition database_iface.hpp:1154
void set_clientdata(const string_param &name, void *ptr, void(*destroy)(void *)=nullptr)
Set arbitrary client data to this database connection.
Definition database_iface.hpp:182
void progress_handler(int step_count, T handler_ptr) const noexcept
Register a callback to be called on query progress.
int preupdate_depth() const noexcept
Returns the "depth" of an update from the top level SQL.
Definition database_iface.hpp:659
void deserialize(const string_param &schema_name, allocated_bytes buf, size_t size, size_t buf_size, unsigned flags=0)
Deserialize a database.
void preupdate_hook(void(*handler)(type_identity_t< T > data_ptr, database *db, int op, const char *db_name, const char *table, sqlite3_int64 rowid_old, sqlite3_int64 rowid_new) noexcept, T data_ptr) noexcept
Register a callback to be called prior to each INSERT, UPDATE, and DELETE operation on a database tab...
Definition database_iface.hpp:527
std::optional< bool > readonly(const string_param &db_name) const noexcept
Determine if a database is read-only.
const class statement * next_statement(const class statement *prev) const noexcept
Find the next prepared statement.
Definition database_iface.hpp:1256
bool not_null
Whether NOT NULL constraint exists.
Definition database_iface.hpp:1381
void create_module(const string_param &name, const sqlite3_module *mod)
Register a virtual table implementation.
Definition database_iface.hpp:962
value * preupdate_old(int column_idx)
Returns value of a column of the table row before it is updated.
void rollback_hook(T handler_ptr) noexcept
Register a callback to be called on rollback.
void collation_needed(T handler_ptr)
Register a callback to be called when undefined collation sequence is required.
T exec(std::u8string_view sql)
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition database_iface.hpp:270
bool get_autocommit() const noexcept
Return the auto-commit mode.
Definition database_iface.hpp:1126
int64_t total_changes() const noexcept
Returns total number of rows modified.
Definition database_iface.hpp:1402
const char * data_type
Declared data type.
Definition database_iface.hpp:1379
void create_module(const string_param &name, const sqlite3_module *mod, T *data, D destructor=nullptr)
Register a virtual table implementation.
Definition database_iface.hpp:978
void progress_handler(int step_count, int(*handler)(type_identity_t< T > data_ptr) noexcept, T data_ptr) const noexcept
Register a callback to be called on query progress.
Definition database_iface.hpp:1291
void busy_handler(int(*handler)(type_identity_t< T > data_ptr, int count_invoked) noexcept, T data_ptr)
Register a callback to handle SQLITE_BUSY errors.
Definition database_iface.hpp:348
auto vtab_config(Args &&...args) -> void
Configure virtual table.
Definition database_iface.hpp:1009
int64_t changes() const noexcept
Count of the number of rows modified.
Definition database_iface.hpp:223
std::pair< allocated_bytes, size_t > serialize(const string_param &schema_name)
Serialize a database.
void recover_snapshot(const string_param &db)
Recover snapshots from a wal file.
Definition database_iface.hpp:1552
void exec(std::string_view sql)
Run multiple statements of SQL.
void rollback_hook(void(*handler)(type_identity_t< T > data_ptr) noexcept, T data_ptr) noexcept
Register a callback to be called on rollback.
Definition database_iface.hpp:453
span< std::byte > serialize_reference(const string_param &schema_name) noexcept
Serialize a database.
void reset_auto_extension() noexcept
Reset automatic extension loading.
Definition database_iface.hpp:1234
void set_last_insert_rowid(int64_t value) noexcept
Set the last insert rowid value.
Definition database_iface.hpp:1165
bool primary_key
Whether column part of PK.
Definition database_iface.hpp:1382
const char * db_name(int idx) noexcept
Return schema names.
Definition database_iface.hpp:1571
void overload_function(const string_param &name, int arg_count)
Overload a function for a virtual table.
Definition database_iface.hpp:1270
void wal_hook(T handler_ptr) noexcept
Register a callback to be called each time data is committed to a database in wal mode.
T * get_clientdata(const string_param &name) noexcept
Get arbitrary client data of this database connection.
Definition database_iface.hpp:211
Return type for table_column_metadata().
Definition database_iface.hpp:1378
Return type for status().
Definition database_iface.hpp:1341
Return type for status64().
Definition database_iface.hpp:1360
Exception used to report any SQLite errors.
Definition exception_iface.hpp:180
T * c_ptr() const noexcept
Access the real underlying SQLite type.
Definition handle.hpp:45
Row result of a statement.
Definition row_iterator.hpp:145
A database snapshot.
Definition snapshot_iface.hpp:43
Prepared Statement Object.
Definition statement_iface.hpp:87
Dynamically Typed Value Object.
Definition value_iface.hpp:36
sqlite3_close_v2
sqlite3_collation_needed
sqlite3_commit_hook
T conjunction_v
sqlite3_create_module_v2
T data(T... args)
sqlite3_db_cacheflush
sqlite3_db_config
sqlite3_db_filename
sqlite3_db_mutex
sqlite3_db_name
sqlite3_db_release_memory
sqlite3_declare_vtab
sqlite3_deserialize
sqlite3_drop_modules
sqlite3_enable_load_extension
sqlite3_extended_result_codes
sqlite3_file_control
T forward(T... args)
sqlite3_get_autocommit
sqlite3_set_clientdata
std::span< T > span
Alias or reimplementation of std::span.
Definition span.hpp:36
basic_string_param< char > string_param
Convenience typedef.
Definition string_param.hpp:58
std::unique_ptr< std::byte, sqlite_deleter< std::byte > > allocated_bytes
A byte buffer allocated by SQLite.
Definition memory_iface.hpp:58
@ reset
Reset the statement (does not affect the bindings).
Definition statement_iface.hpp:782
sqlite3_interrupt
T is_convertible_v
T is_nothrow_invocable_r_v
T is_null_pointer_v
T is_pointer_v
sqlite3_last_insert_rowid
sqlite3_limit
sqlite3_load_extension
ThinSQLite++ namespace.
Definition backup_iface.hpp:17
sqlite3_next_stmt
sqlite3_overload_function
sqlite3_preupdate_hook
sqlite3_progress_handler
#define SQLITE_ERROR
#define SQLITE_OK
sqlite3_reset_auto_extension
sqlite3_set_errmsg
sqlite3_set_last_insert_rowid
sqlite3_setlk_timeout
T size(T... args)
sqlite3_snapshot_open
sqlite3_snapshot_recover
sqlite3_total_changes64
sqlite3_txn_state
sqlite3_update_hook
sqlite3_vtab_config
sqlite3_vtab_on_conflict
sqlite3_wal_autocheckpoint
sqlite3_wal_hook