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