1 /**
2 * Copyright (c) 2017, Timothy Stack
3 *
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions are met:
8 *
9 * * Redistributions of source code must retain the above copyright notice, this
10 * list of conditions and the following disclaimer.
11 * * Redistributions in binary form must reproduce the above copyright notice,
12 * this list of conditions and the following disclaimer in the documentation
13 * and/or other materials provided with the distribution.
14 * * Neither the name of Timothy Stack nor the names of its contributors
15 * may be used to endorse or promote products derived from this software
16 * without specific prior written permission.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ''AS IS'' AND ANY
19 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
20 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
21 * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
22 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
23 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
24 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
25 * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
27 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 */
29
30 #ifndef vtab_module_hh
31 #define vtab_module_hh
32
33 #include <sqlite3.h>
34
35 #include <string>
36 #include <vector>
37 #include <utility>
38
39 #include "optional.hpp"
40 #include "base/lnav_log.hh"
41 #include "base/string_util.hh"
42 #include "auto_mem.hh"
43 #include "mapbox/variant.hpp"
44 #include "fmt/format.h"
45
46 #include "sqlite-extension-func.hh"
47
48 struct from_sqlite_conversion_error : std::exception {
from_sqlite_conversion_errorfrom_sqlite_conversion_error49 from_sqlite_conversion_error(const char *type, int argi)
50 : e_type(type), e_argi(argi) {
51
52 };
53
54 const char *e_type;
55 int e_argi;
56 };
57
58 struct sqlite_func_error : std::exception {
59 template<typename ...Args>
sqlite_func_errorsqlite_func_error60 explicit sqlite_func_error(
61 fmt::string_view format_str, const Args& ...args) :
62 e_what(fmt::vformat(format_str, fmt::make_format_args(args...))) {
63 }
64
whatsqlite_func_error65 const char *what() const noexcept override {
66 return this->e_what.c_str();
67 }
68
69 const std::string e_what;
70 };
71
72 namespace vtab_types {
73
74 template<typename T>
75 struct nullable {
76 T *n_value{nullptr};
77 };
78
79 template<typename>
80 struct is_nullable : std::false_type {};
81
82 template<typename T>
83 struct is_nullable<nullable<T>> : std::true_type {};
84
85 }
86
87 template<typename T>
88 struct from_sqlite {
89 using U = typename std::remove_reference<T>::type;
90
operator ()from_sqlite91 inline U operator()(int argc, sqlite3_value **val, int argi) {
92 return U();
93 };
94 };
95
96 template<>
97 struct from_sqlite<bool> {
operator ()from_sqlite98 inline bool operator()(int argc, sqlite3_value **val, int argi) {
99 if (sqlite3_value_numeric_type(val[argi]) != SQLITE_INTEGER) {
100 throw from_sqlite_conversion_error("integer", argi);
101 }
102
103 return sqlite3_value_int64(val[argi]);
104 }
105 };
106
107 template<>
108 struct from_sqlite<int64_t> {
operator ()from_sqlite109 inline int64_t operator()(int argc, sqlite3_value **val, int argi) {
110 if (sqlite3_value_numeric_type(val[argi]) != SQLITE_INTEGER) {
111 throw from_sqlite_conversion_error("integer", argi);
112 }
113
114 return sqlite3_value_int64(val[argi]);
115 }
116 };
117
118 template<>
119 struct from_sqlite<sqlite3_value *> {
operator ()from_sqlite120 inline sqlite3_value *operator()(int argc, sqlite3_value **val, int argi) {
121 return val[argi];
122 }
123 };
124
125 template<>
126 struct from_sqlite<int> {
operator ()from_sqlite127 inline int operator()(int argc, sqlite3_value **val, int argi) {
128 if (sqlite3_value_numeric_type(val[argi]) != SQLITE_INTEGER) {
129 throw from_sqlite_conversion_error("integer", argi);
130 }
131
132 return sqlite3_value_int(val[argi]);
133 }
134 };
135
136 template<>
137 struct from_sqlite<const char *> {
operator ()from_sqlite138 inline const char *operator()(int argc, sqlite3_value **val, int argi) {
139 return (const char *) sqlite3_value_text(val[argi]);
140 }
141 };
142
143 template<>
144 struct from_sqlite<string_fragment> {
operator ()from_sqlite145 inline string_fragment operator()(int argc, sqlite3_value **val, int argi) {
146 return string_fragment {
147 (const unsigned char *) sqlite3_value_blob(val[argi]),
148 0,
149 sqlite3_value_bytes(val[argi]),
150 };
151 }
152 };
153
154 template<>
155 struct from_sqlite<std::string> {
operator ()from_sqlite156 inline std::string operator()(int argc, sqlite3_value **val, int argi) {
157 return {
158 (const char *) sqlite3_value_blob(val[argi]),
159 (size_t) sqlite3_value_bytes(val[argi]),
160 };
161 }
162 };
163
164 template<>
165 struct from_sqlite<double> {
operator ()from_sqlite166 inline double operator()(int argc, sqlite3_value **val, int argi) {
167 return sqlite3_value_double(val[argi]);
168 }
169 };
170
171 template<typename T>
172 struct from_sqlite<nonstd::optional<T>> {
operator ()from_sqlite173 inline nonstd::optional<T> operator()(int argc, sqlite3_value **val, int argi) {
174 if (argi >= argc || sqlite3_value_type(val[argi]) == SQLITE_NULL) {
175 return nonstd::nullopt;
176 }
177
178 return nonstd::optional<T>(from_sqlite<T>()(argc, val, argi));
179 }
180 };
181
182 template<typename T>
183 struct from_sqlite<const std::vector<T> &> {
operator ()from_sqlite184 inline std::vector<T> operator()(int argc, sqlite3_value **val, int argi) {
185 std::vector<T> retval;
186
187 for (int lpc = argi; lpc < argc; lpc++) {
188 retval.emplace_back(from_sqlite<T>()(argc, val, lpc));
189 }
190
191 return retval;
192 }
193 };
194
195 template<typename T>
196 struct from_sqlite<vtab_types::nullable<T>> {
operator ()from_sqlite197 inline vtab_types::nullable<T> operator()(int argc, sqlite3_value **val, int argi) {
198 return {from_sqlite<T *>()(argc, val, argi)};
199 }
200 };
201
to_sqlite(sqlite3_context * ctx,const char * str)202 inline void to_sqlite(sqlite3_context *ctx, const char *str)
203 {
204 if (str == nullptr) {
205 sqlite3_result_null(ctx);
206 } else {
207 sqlite3_result_text(ctx, str, -1, SQLITE_STATIC);
208 }
209 }
210
to_sqlite(sqlite3_context * ctx,text_auto_buffer & buf)211 inline void to_sqlite(sqlite3_context *ctx, text_auto_buffer& buf)
212 {
213 auto pair = buf.inner.release();
214 sqlite3_result_text(ctx, pair.first, pair.second, free);
215 }
216
to_sqlite(sqlite3_context * ctx,blob_auto_buffer & buf)217 inline void to_sqlite(sqlite3_context *ctx, blob_auto_buffer& buf)
218 {
219 auto pair = buf.inner.release();
220 sqlite3_result_blob(ctx, pair.first, pair.second, free);
221 }
222
to_sqlite(sqlite3_context * ctx,const std::string & str)223 inline void to_sqlite(sqlite3_context *ctx, const std::string &str)
224 {
225 sqlite3_result_text(ctx, str.c_str(), str.length(), SQLITE_TRANSIENT);
226 }
227
to_sqlite(sqlite3_context * ctx,const string_fragment & sf)228 inline void to_sqlite(sqlite3_context *ctx, const string_fragment &sf)
229 {
230 if (sf.is_valid()) {
231 sqlite3_result_text(ctx,
232 &sf.sf_string[sf.sf_begin], sf.length(),
233 SQLITE_TRANSIENT);
234 } else {
235 sqlite3_result_null(ctx);
236 }
237 }
238
to_sqlite(sqlite3_context * ctx,bool val)239 inline void to_sqlite(sqlite3_context *ctx, bool val)
240 {
241 sqlite3_result_int(ctx, val);
242 }
243
244 template<typename T>
to_sqlite(sqlite3_context * ctx,T val,typename std::enable_if<std::is_integral<T>::value &&!std::is_same<T,bool>::value>::type * dummy=0)245 inline void to_sqlite(sqlite3_context *ctx, T val,
246 typename std::enable_if<std::is_integral<T>::value &&
247 !std::is_same<T, bool>::value>::type* dummy = 0)
248 {
249 sqlite3_result_int64(ctx, val);
250 }
251
to_sqlite(sqlite3_context * ctx,double val)252 inline void to_sqlite(sqlite3_context *ctx, double val)
253 {
254 sqlite3_result_double(ctx, val);
255 }
256
257 #define JSON_SUBTYPE 74 /* Ascii for "J" */
258
259 template<typename T>
to_sqlite(sqlite3_context * ctx,nonstd::optional<T> & val)260 inline void to_sqlite(sqlite3_context *ctx, nonstd::optional<T> &val)
261 {
262 if (val.has_value()) {
263 to_sqlite(ctx, val.value());
264 } else {
265 sqlite3_result_null(ctx);
266 }
267 }
268
269 template<typename T>
to_sqlite(sqlite3_context * ctx,const nonstd::optional<T> & val)270 inline void to_sqlite(sqlite3_context *ctx, const nonstd::optional<T> &val)
271 {
272 if (val.has_value()) {
273 to_sqlite(ctx, val.value());
274 } else {
275 sqlite3_result_null(ctx);
276 }
277 }
278
279 struct ToSqliteVisitor {
ToSqliteVisitorToSqliteVisitor280 ToSqliteVisitor(sqlite3_context *vctx) : tsv_context(vctx) {
281
282 };
283
284 template<typename T>
operator ()ToSqliteVisitor285 void operator()(T&& t) const {
286 to_sqlite(this->tsv_context, t);
287 }
288
289 sqlite3_context *tsv_context;
290 };
291
292 template<typename ... Types>
to_sqlite(sqlite3_context * ctx,mapbox::util::variant<Types...> & val)293 void to_sqlite(sqlite3_context *ctx, mapbox::util::variant<Types...> &val)
294 {
295 ToSqliteVisitor visitor(ctx);
296
297 mapbox::util::apply_visitor(visitor, val);
298 }
299
300 template<typename ... Args>
301 struct optional_counter {
302 constexpr static int value = 0;
303 };
304
305 template<typename T>
306 struct optional_counter<nonstd::optional<T>> {
307 constexpr static int value = 1;
308 };
309
310 template<typename T, typename U>
311 struct optional_counter<nonstd::optional<T>, const std::vector<U> &> {
312 constexpr static int value = 1;
313 };
314
315 template<typename T, typename ... Rest>
316 struct optional_counter<nonstd::optional<T>, Rest...> {
317 constexpr static int value = 1 + sizeof...(Rest);
318 };
319
320 template<typename Arg>
321 struct optional_counter<Arg> {
322 constexpr static int value = 0;
323 };
324
325 template<typename Arg1, typename ... Args>
326 struct optional_counter<Arg1, Args...> : optional_counter<Args...> {
327
328 };
329
330
331 template<typename ... Args>
332 struct variadic_counter {
333 constexpr static int value = 0;
334 };
335
336 template<typename T>
337 struct variadic_counter<const std::vector<T> &> {
338 constexpr static int value = 1;
339 };
340
341 template<typename Arg>
342 struct variadic_counter<Arg> {
343 constexpr static int value = 0;
344 };
345
346 template<typename Arg1, typename ... Args>
347 struct variadic_counter<Arg1, Args...> : variadic_counter<Args...> {
348
349 };
350
351
352 template<typename F, F f> struct sqlite_func_adapter;
353
354 template<typename Return, typename ... Args, Return (*f)(Args...)>
355 struct sqlite_func_adapter<Return (*)(Args...), f> {
356 constexpr static size_t OPT_COUNT = optional_counter<Args...>::value;
357 constexpr static size_t VAR_COUNT = variadic_counter<Args...>::value;
358 constexpr static size_t REQ_COUNT = sizeof...(Args) - OPT_COUNT - VAR_COUNT;
359
360 template<size_t ... Idx>
func2sqlite_func_adapter361 static void func2(sqlite3_context *context,
362 int argc, sqlite3_value **argv,
363 std::index_sequence<Idx...>) {
364 try {
365 Return retval = f(from_sqlite<Args>()(argc, argv, Idx)...);
366
367 to_sqlite(context, retval);
368 } catch (from_sqlite_conversion_error &e) {
369 char buffer[64];
370
371 snprintf(buffer, sizeof(buffer),
372 "Expecting an %s for argument number %d",
373 e.e_type,
374 e.e_argi);
375 sqlite3_result_error(context, buffer, -1);
376 } catch (const std::exception &e) {
377 sqlite3_result_error(context, e.what(), -1);
378 } catch (...) {
379 sqlite3_result_error(context, "Function threw an unexpected exception", -1);
380 }
381 };
382
func1sqlite_func_adapter383 static void func1(sqlite3_context *context,
384 int argc, sqlite3_value **argv) {
385 const static bool IS_NULLABLE[] = {vtab_types::is_nullable<Args>::value ... };
386 const static bool IS_SQLITE3_VALUE[] = {
387 std::is_same<Args, sqlite3_value *>::value ...
388 };
389
390 if ((size_t) argc < REQ_COUNT && VAR_COUNT == 0) {
391 const struct FuncDef *fd = (const FuncDef *) sqlite3_user_data(context);
392 char buffer[128];
393
394 if (OPT_COUNT == 0) {
395 snprintf(buffer, sizeof(buffer),
396 "%s() expects exactly %ld argument%s",
397 fd->fd_help.ht_name,
398 REQ_COUNT,
399 REQ_COUNT == 1 ? "s" : "");
400 } else {
401 snprintf(buffer, sizeof(buffer),
402 "%s() expects between %ld and %ld arguments",
403 fd->fd_help.ht_name,
404 REQ_COUNT,
405 REQ_COUNT + OPT_COUNT);
406 }
407 sqlite3_result_error(context, buffer, -1);
408 return;
409 }
410
411 for (size_t lpc = 0; lpc < REQ_COUNT; lpc++) {
412 if (!IS_NULLABLE[lpc] &&
413 !IS_SQLITE3_VALUE[lpc] &&
414 sqlite3_value_type(argv[lpc]) == SQLITE_NULL) {
415 sqlite3_result_null(context);
416 return;
417 }
418 }
419
420 func2(context, argc, argv, std::make_index_sequence<sizeof...(Args)>{});
421 };
422
buildersqlite_func_adapter423 static FuncDef builder(help_text ht) {
424 require(ht.ht_parameters.size() == sizeof...(Args));
425
426 return {
427 ht.ht_name,
428 (OPT_COUNT > 0 || VAR_COUNT > 0) ? -1 : (int) REQ_COUNT,
429 SQLITE_UTF8 | SQLITE_DETERMINISTIC,
430 0,
431 func1,
432 ht,
433 };
434 };
435 };
436
437 extern std::string vtab_module_schemas;
438 extern std::map<intern_string_t, std::string> vtab_module_ddls;
439
440 class vtab_index_constraints {
441 public:
vtab_index_constraints(const sqlite3_index_info * index_info)442 vtab_index_constraints(const sqlite3_index_info *index_info)
443 : vic_index_info(*index_info) {
444 };
445
446 struct const_iterator {
const_iteratorvtab_index_constraints::const_iterator447 const_iterator(vtab_index_constraints *parent, int index = 0)
448 : i_parent(parent), i_index(index) {
449 while (this->i_index < this->i_parent->vic_index_info.nConstraint &&
450 !this->i_parent->vic_index_info.aConstraint[this->i_index].usable) {
451 this->i_index += 1;
452 }
453 };
454
operator ++vtab_index_constraints::const_iterator455 const_iterator& operator++() {
456 do {
457 this->i_index += 1;
458 } while (
459 this->i_index < this->i_parent->vic_index_info.nConstraint &&
460 !this->i_parent->vic_index_info.aConstraint[this->i_index].usable);
461
462 return *this;
463 };
464
operator *vtab_index_constraints::const_iterator465 const sqlite3_index_info::sqlite3_index_constraint &operator*() const {
466 return this->i_parent->vic_index_info.aConstraint[this->i_index];
467 };
468
operator ->vtab_index_constraints::const_iterator469 const sqlite3_index_info::sqlite3_index_constraint *operator->() const {
470 return &this->i_parent->vic_index_info.aConstraint[this->i_index];
471 };
472
operator !=vtab_index_constraints::const_iterator473 bool operator!=(const const_iterator &rhs) const {
474 return this->i_parent != rhs.i_parent || this->i_index != rhs.i_index;
475 };
476
477 const vtab_index_constraints *i_parent;
478 int i_index;
479 };
480
begin()481 const_iterator begin() {
482 return {this};
483 };
484
end()485 const_iterator end() {
486 return {this, this->vic_index_info.nConstraint};
487 };
488
489 private:
490 const sqlite3_index_info &vic_index_info;
491 };
492
493 class vtab_index_usage {
494 public:
vtab_index_usage(sqlite3_index_info * index_info)495 vtab_index_usage(sqlite3_index_info *index_info)
496 : viu_index_info(*index_info),
497 viu_used_column_count(0),
498 viu_max_column(0) {
499
500 };
501
column_used(const vtab_index_constraints::const_iterator & iter)502 void column_used(const vtab_index_constraints::const_iterator &iter) {
503 this->viu_max_column = std::max(iter->iColumn, this->viu_max_column);
504 this->viu_index_info.idxNum |= (1L << iter.i_index);
505 this->viu_used_column_count += 1;
506 };
507
allocate_args(int expected)508 void allocate_args(int expected) {
509 int n_arg = 0;
510
511 if (this->viu_used_column_count != expected) {
512 this->viu_index_info.estimatedCost = 2147483647;
513 this->viu_index_info.estimatedRows = 2147483647;
514 return;
515 }
516
517 for (int lpc = 0; lpc <= this->viu_max_column; lpc++) {
518 for (int cons_index = 0;
519 cons_index < this->viu_index_info.nConstraint;
520 cons_index++) {
521 if (this->viu_index_info.aConstraint[cons_index].iColumn != lpc) {
522 continue;
523 }
524 if (!(this->viu_index_info.idxNum & (1L << cons_index))) {
525 continue;
526 }
527
528 this->viu_index_info.aConstraintUsage[cons_index].argvIndex = ++n_arg;
529 }
530 }
531 this->viu_index_info.estimatedCost = 1.0;
532 this->viu_index_info.estimatedRows = 1;
533 };
534
535 private:
536 sqlite3_index_info &viu_index_info;
537 int viu_used_column_count;
538 int viu_max_column;
539 };
540
541 struct vtab_module_base {
542 virtual int create(sqlite3 *db) = 0;
543
544 virtual ~vtab_module_base() = default;
545 };
546
547 template<typename T>
548 struct vtab_module : public vtab_module_base {
549 struct vtab {
vtabvtab_module::vtab550 explicit vtab(T& impl) : v_impl(impl) {};
551
operator sqlite3_vtab*vtab_module::vtab552 explicit operator sqlite3_vtab *() {
553 return &this->base;
554 };
555
556 sqlite3_vtab v_base{};
557 T &v_impl;
558 };
559
tvt_createvtab_module560 static int tvt_create(sqlite3 *db,
561 void *pAux,
562 int argc, const char *const *argv,
563 sqlite3_vtab **pp_vt,
564 char **pzErr) {
565 auto* mod = static_cast<vtab_module<T> *>(pAux);
566 auto vt = new vtab(mod->vm_impl);
567
568 *pp_vt = (sqlite3_vtab *) &vt->v_base;
569
570 return sqlite3_declare_vtab(db, T::CREATE_STMT);
571 };
572
573 template<typename ... Args, size_t... Idx>
apply_implvtab_module574 static int apply_impl(T &obj, int (T::*func)(sqlite3_vtab *, sqlite3_int64 &, Args...), sqlite3_vtab *tab, sqlite3_int64 &rowid, sqlite3_value **argv, std::index_sequence<Idx...>)
575 {
576 return (obj.*func)(tab, rowid, from_sqlite<Args>()(sizeof...(Args), argv, Idx)...);
577 }
578
579 template<typename ... Args>
applyvtab_module580 static int apply(T &obj,
581 int (T::*func)(sqlite3_vtab *, sqlite3_int64 &, Args...),
582 sqlite3_vtab *tab,
583 sqlite3_int64 &rowid,
584 int argc,
585 sqlite3_value **argv)
586 {
587 require(sizeof...(Args) == 0 || argc == sizeof...(Args));
588
589 try {
590 return apply_impl(obj,
591 func,
592 tab,
593 rowid,
594 argv,
595 std::make_index_sequence<sizeof...(Args)>{});
596 } catch (from_sqlite_conversion_error &e) {
597 tab->zErrMsg = sqlite3_mprintf(
598 "Expecting an %s for column number %d",
599 e.e_type,
600 e.e_argi);
601 return SQLITE_ERROR;
602 } catch (const std::exception &e) {
603 tab->zErrMsg = sqlite3_mprintf("%s", e.what());
604 return SQLITE_ERROR;
605 } catch (...) {
606 tab->zErrMsg = sqlite3_mprintf("Encountered an unexpected exception");
607 return SQLITE_ERROR;
608 }
609 }
610
tvt_destructorvtab_module611 static int tvt_destructor(sqlite3_vtab *p_svt)
612 {
613 vtab *vt = (vtab *) p_svt;
614
615 delete vt;
616
617 return SQLITE_OK;
618 }
619
tvt_openvtab_module620 static int tvt_open(sqlite3_vtab *p_svt, sqlite3_vtab_cursor **pp_cursor)
621 {
622 p_svt->zErrMsg = nullptr;
623
624 auto *p_cur = new (typename T::cursor)(p_svt);
625
626 if (p_cur == nullptr) {
627 return SQLITE_NOMEM;
628 } else {
629 *pp_cursor = (sqlite3_vtab_cursor *) p_cur;
630 }
631
632 return SQLITE_OK;
633 }
634
tvt_nextvtab_module635 static int tvt_next(sqlite3_vtab_cursor *cur)
636 {
637 auto *p_cur = (typename T::cursor *) cur;
638
639 return p_cur->next();
640 }
641
tvt_eofvtab_module642 static int tvt_eof(sqlite3_vtab_cursor *cur)
643 {
644 auto *p_cur = (typename T::cursor *) cur;
645
646 return p_cur->eof();
647 }
648
tvt_closevtab_module649 static int tvt_close(sqlite3_vtab_cursor *cur)
650 {
651 auto *p_cur = (typename T::cursor *) cur;
652
653 delete p_cur;
654
655 return SQLITE_OK;
656 }
657
658
tvt_rowidvtab_module659 static int tvt_rowid(sqlite3_vtab_cursor *cur, sqlite_int64 *p_rowid) {
660 auto *p_cur = (typename T::cursor *) cur;
661
662 return p_cur->get_rowid(*p_rowid);
663 };
664
tvt_columnvtab_module665 static int tvt_column(sqlite3_vtab_cursor *cur, sqlite3_context *ctx, int col) {
666 auto *mod_vt = (typename vtab_module<T>::vtab *) cur->pVtab;
667 auto *p_cur = (typename T::cursor *) cur;
668
669 return mod_vt->v_impl.get_column(*p_cur, ctx, col);
670 };
671
vt_best_indexvtab_module672 static int vt_best_index(sqlite3_vtab *tab, sqlite3_index_info *p_info) {
673 return SQLITE_OK;
674 };
675
vt_filtervtab_module676 static int vt_filter(sqlite3_vtab_cursor *p_vtc,
677 int idxNum, const char *idxStr,
678 int argc, sqlite3_value **argv) {
679 auto *p_cur = (typename T::cursor *) p_vtc;
680
681 return p_cur->reset();
682 }
683
tvt_updatevtab_module684 static int tvt_update(sqlite3_vtab *tab,
685 int argc,
686 sqlite3_value **argv,
687 sqlite_int64 *rowid) {
688 auto *mod_vt = (typename vtab_module<T>::vtab *) tab;
689
690 if (argc <= 1) {
691 sqlite3_int64 rowid = sqlite3_value_int64(argv[0]);
692
693 return mod_vt->v_impl.delete_row(tab, rowid);
694 }
695
696 if (sqlite3_value_type(argv[0]) == SQLITE_NULL) {
697 sqlite3_int64 *rowid2 = rowid;
698 return vtab_module<T>::apply(mod_vt->v_impl, &T::insert_row, tab, *rowid2, argc - 2, argv + 2);
699 }
700
701 sqlite3_int64 index = sqlite3_value_int64(argv[0]);
702
703 if (index != sqlite3_value_int64(argv[1])) {
704 tab->zErrMsg = sqlite3_mprintf(
705 "The rowids in the lnav_views table cannot be changed");
706 return SQLITE_ERROR;
707 }
708
709 return vtab_module<T>::apply(mod_vt->v_impl, &T::update_row, tab, index, argc - 2, argv + 2);
710 };
711
712 template<typename U>
addUpdatevtab_module713 auto addUpdate(U u) -> decltype(&U::delete_row, void()) {
714 this->vm_module.xUpdate = tvt_update;
715 };
716
717 template<typename U>
addUpdatevtab_module718 void addUpdate(...) {
719 };
720
721 template<typename ...Args>
vtab_modulevtab_module722 vtab_module(Args& ...args) noexcept : vm_impl(args...) {
723 memset(&this->vm_module, 0, sizeof(this->vm_module));
724 this->vm_module.iVersion = 0;
725 this->vm_module.xCreate = tvt_create;
726 this->vm_module.xConnect = tvt_create;
727 this->vm_module.xOpen = tvt_open;
728 this->vm_module.xNext = tvt_next;
729 this->vm_module.xEof = tvt_eof;
730 this->vm_module.xClose = tvt_close;
731 this->vm_module.xDestroy = tvt_destructor;
732 this->vm_module.xRowid = tvt_rowid;
733 this->vm_module.xDisconnect = tvt_destructor;
734 this->vm_module.xBestIndex = vt_best_index;
735 this->vm_module.xFilter = vt_filter;
736 this->vm_module.xColumn = tvt_column;
737 this->addUpdate<T>(this->vm_impl);
738 };
739
740 ~vtab_module() override = default;
741
createvtab_module742 int create(sqlite3 *db, const char *name)
743 {
744 auto impl_name = std::string(name);
745 vtab_module_schemas += T::CREATE_STMT;
746 vtab_module_ddls[intern_string::lookup(name)] = trim(T::CREATE_STMT);
747
748 // XXX Eponymous tables don't seem to work in older sqlite versions
749 impl_name += "_impl";
750 int rc = sqlite3_create_module(
751 db, impl_name.c_str(), &this->vm_module, this);
752 ensure(rc == SQLITE_OK);
753 auto create_stmt = fmt::format("CREATE VIRTUAL TABLE {} USING {}()",
754 name, impl_name);
755 return sqlite3_exec(db, create_stmt.c_str(), nullptr, nullptr, nullptr);
756 };
757
createvtab_module758 int create(sqlite3 *db) override {
759 return this->create(db, T::NAME);
760 }
761
762 sqlite3_module vm_module;
763 T vm_impl;
764 };
765
766 template<typename T>
767 struct tvt_iterator_cursor {
768 struct cursor {
769 sqlite3_vtab_cursor base{};
770
771 typename T::iterator iter;
772
cursortvt_iterator_cursor::cursor773 explicit cursor(sqlite3_vtab *vt)
774 {
775 auto* mod_vt = (typename vtab_module<T>::vtab *) vt;
776
777 this->base.pVtab = vt;
778 this->iter = mod_vt->v_impl.begin();
779 };
780
resettvt_iterator_cursor::cursor781 int reset() {
782 this->iter = get_handler().begin();
783
784 return SQLITE_OK;
785 };
786
nexttvt_iterator_cursor::cursor787 int next()
788 {
789 if (this->iter != get_handler().end()) {
790 ++this->iter;
791 }
792
793 return SQLITE_OK;
794 };
795
eoftvt_iterator_cursor::cursor796 int eof()
797 {
798 return this->iter == get_handler().end();
799 };
800
801 template< bool cond, typename U >
802 using resolvedType = typename std::enable_if< cond, U >::type;
803
804 template< typename U = int >
805 resolvedType< std::is_same<std::random_access_iterator_tag,
806 typename std::iterator_traits<typename T::iterator>::iterator_category>::value, U >
get_rowidtvt_iterator_cursor::cursor807 get_rowid(sqlite_int64 &rowid_out) {
808 rowid_out = std::distance(get_handler().begin(), this->iter);
809
810 return SQLITE_OK;
811 }
812
813 template< typename U = int >
814 resolvedType< !std::is_same<std::random_access_iterator_tag,
815 typename std::iterator_traits<typename T::iterator>::iterator_category>::value, U >
get_rowidtvt_iterator_cursor::cursor816 get_rowid(sqlite_int64 &rowid_out) {
817 rowid_out = get_handler().get_rowid(this->iter);
818
819 return SQLITE_OK;
820 }
821
822 private:
get_handlertvt_iterator_cursor::cursor823 T &get_handler() {
824 auto* mod_vt = (typename vtab_module<T>::vtab *) this->base.pVtab;
825
826 return mod_vt->v_impl;
827 }
828 };
829 };
830
831 template<typename T>
832 struct tvt_no_update : public T {
delete_rowtvt_no_update833 int delete_row(sqlite3_vtab *vt, sqlite3_int64 rowid) {
834 vt->zErrMsg = sqlite3_mprintf(
835 "Rows cannot be deleted from this table");
836 return SQLITE_ERROR;
837 };
838
insert_rowtvt_no_update839 int insert_row(sqlite3_vtab *tab, sqlite3_int64 &rowid_out) {
840 tab->zErrMsg = sqlite3_mprintf(
841 "Rows cannot be inserted into this table");
842 return SQLITE_ERROR;
843 };
844
update_rowtvt_no_update845 int update_row(sqlite3_vtab *tab, sqlite3_int64 &rowid_out) {
846 tab->zErrMsg = sqlite3_mprintf(
847 "Rows cannot be updated in this table");
848 return SQLITE_ERROR;
849 };
850
851 };
852
853 #endif
854