8#ifndef BOOST_SQLITE_VTABLE_HPP
9#define BOOST_SQLITE_VTABLE_HPP
11#include <boost/sqlite/detail/config.hpp>
12#include <boost/sqlite/detail/catch.hpp>
13#include <boost/sqlite/function.hpp>
15#include <boost/core/span.hpp>
16#include <boost/core/demangle.hpp>
20BOOST_SQLITE_BEGIN_NAMESPACE
43 template<
typename Func>
46 set_impl(func,
static_cast<callable_traits::args_t<Func>*
>(
nullptr));
49 template<
typename ... Args, std::size_t Extent>
50 void set(
void(* ptr)(context<Args...>, span<value, Extent>))
noexcept
52 *ppArg_ =
reinterpret_cast<void*
>(ptr);
54 +[](sqlite3_context* ctx,
int len, sqlite3_value** args)
56 auto cc =
context<Args...>(ctx);
57 auto aa =
reinterpret_cast<value*
>(args);
58 auto &f = *
reinterpret_cast<void(*)(
context<Args...
>, span<value, Extent>)>(sqlite3_user_data(ctx));
59 detail::execute_context_function(ctx, f, cc, boost::span<value, Extent>{aa,
static_cast<std::size_t
>(len)});
63 template<
typename T,
typename ... Args, std::size_t Extent>
64 void set(T(* ptr)(context<Args...>, span<value, Extent>))
66 *ppArg_ =
reinterpret_cast<void*
>(ptr);
68 +[](sqlite3_context* ctx,
int len, sqlite3_value** args)
noexcept
70 auto cc = context<Args...>(ctx);
71 auto aa =
reinterpret_cast<value*
>(args);
72 auto &f = *
reinterpret_cast<T(*)(context<Args...
>, span<value, Extent>)>(sqlite3_user_data(ctx));
73 detail::execute_context_function(ctx, f, cc, boost::span<value, Extent>{aa,
static_cast<std::size_t
>(len)});
77 template<std::
size_t Extent>
78 void set(
void(* ptr)(span<value, Extent>))
80 *ppArg_ =
reinterpret_cast<void*
>(ptr);
82 +[](sqlite3_context* ctx,
int len, sqlite3_value** args)
noexcept
84 auto aa =
reinterpret_cast<value*
>(args);
85 auto &f = *
reinterpret_cast<void(*)(span<value, Extent>)
>(sqlite3_user_data(ctx));
86 detail::execute_context_function(ctx, f, boost::span<value, Extent>{aa,
static_cast<std::size_t
>(len)});
90 template<
typename T, std::
size_t Extent>
91 void set(T(* ptr)(span<value, Extent>))
93 *ppArg_ =
reinterpret_cast<void*
>(ptr);
95 +[](sqlite3_context* ctx,
int len, sqlite3_value** args)
noexcept
97 auto aa =
reinterpret_cast<value*
>(args);
98 auto &f = *
reinterpret_cast<T(*)(span<value, Extent>)
>(sqlite3_user_data(ctx));
99 detail::execute_context_function(ctx, f, boost::span<value, Extent>{aa,
static_cast<std::size_t
>(len)});
103 explicit function_setter(
void (**pxFunc)(sqlite3_context*,
int,sqlite3_value**),
104 void **ppArg) : pxFunc_(pxFunc), ppArg_(ppArg) {}
107 template<
typename Func,
typename ... Args, std::size_t Extent>
108 void set_impl(Func & func, std::tuple<context<Args...>, span<value, Extent>>)
112 +[](sqlite3_context* ctx,
int len, sqlite3_value** args)
noexcept
114 auto cc = context<Args...>(ctx);
115 auto aa =
reinterpret_cast<value*
>(args);
116 auto &f = *
reinterpret_cast<Func*
>(sqlite3_user_data(ctx));
117 detail::execute_context_function(ctx, f, cc, boost::span<value, Extent>{aa,
static_cast<std::size_t
>(len)});
120 template<
typename Func, std::
size_t Extent>
121 void set_impl(Func & func, std::tuple<span<value, Extent>> * )
125 +[](sqlite3_context* ctx,
int len, sqlite3_value** args)
noexcept
127 auto aa =
reinterpret_cast<value*
>(args);
128 auto &f = *
reinterpret_cast<Func *
>(sqlite3_user_data(ctx));
129 detail::execute_context_function(ctx, f, boost::span<value, Extent>{aa,
static_cast<std::size_t
>(len)});
133 void (**pxFunc_)(sqlite3_context*,int,sqlite3_value**);
137#if SQLITE_VERSION_NUMBER >= 3038000
147 iterator() =
default;
148 explicit iterator(sqlite3_value *
value ) : value_(
value)
150 if (
value ==
nullptr)
152 auto res = sqlite3_vtab_in_first(
value, &out_.
handle());
153 if (res != SQLITE_OK)
155 system::error_code ec;
156 BOOST_SQLITE_ASSIGN_EC(ec, res);
157 detail::throw_error_code(ec, ec.location());
161 iterator & operator++()
163 auto res = sqlite3_vtab_in_next(value_, &out_.handle());
164 if (res != SQLITE_OK)
166 system::error_code ec;
167 BOOST_SQLITE_ASSIGN_EC(ec, res);
168 detail::throw_error_code(ec, ec.location());
173 iterator operator++(
int)
181 const value & operator*()
const
186 const value * operator->()
const
191 bool operator==(
const iterator& other)
const
193 return value_ == other.value_
194 && out_.handle() == other.out_.handle();
197 bool operator!=(
const iterator& other)
const
199 return value_ != other.value_
200 || out_.handle() != other.out_.handle();
205 sqlite3_value * value_{
nullptr};
210 iterator
begin() {
return iterator(out_);}
212 iterator
end() {
return iterator();}
214 explicit in(sqlite3_value * out) : out_(out) {}
217 sqlite3_value * out_{
nullptr};
228 BOOST_ATTRIBUTE_NODISCARD
229 span<const sqlite3_index_info::sqlite3_index_constraint>
constraints()
const
231 return {info_->aConstraint,
static_cast<std::size_t
>(info_->nConstraint)};
235 BOOST_ATTRIBUTE_NODISCARD
236 span<const sqlite3_index_info::sqlite3_index_orderby>
order_by()
const
238 return {info_->aOrderBy,
static_cast<std::size_t
>(info_->nOrderBy)};
241 BOOST_ATTRIBUTE_NODISCARD
242 span<sqlite3_index_info::sqlite3_index_constraint_usage> usage()
244 return {info_->aConstraintUsage,
static_cast<std::size_t
>(info_->nConstraint)};
247 BOOST_ATTRIBUTE_NODISCARD
248 sqlite3_index_info::sqlite3_index_constraint_usage & usage_of(
249 const sqlite3_index_info::sqlite3_index_constraint & info)
251 auto dist = std::distance(constraints().begin(), &info);
252 auto itr = usage().begin() + dist;
253 BOOST_ASSERT(itr < usage().end());
257#if SQLITE_VERSION_NUMBER >= 3022000
262 return sqlite3_vtab_collation(info_,
static_cast<int>(idx));
266 int on_conflict()
const {
return sqlite3_vtab_on_conflict(db_);}
268#if SQLITE_VERSION_NUMBER >= 3038000
270 bool distinct()
const {
return sqlite3_vtab_distinct(info_);}
272 value * rhs_value(std::size_t idx)
const
275 if (sqlite3_vtab_rhs_value(
276 info_,
static_cast<int>(idx),
277 reinterpret_cast<sqlite3_value**
>(v)) == SQLITE_OK)
284 void set_already_ordered() { info_->orderByConsumed = 1; }
285 void set_estimated_cost(
double cost) { info_->estimatedCost = cost; }
286#if SQLITE_VERSION_NUMBER >= 3008200
287 void set_estimated_rows(sqlite3_int64 rows) { info_->estimatedRows = rows; }
289#if SQLITE_VERSION_NUMBER >= 3009000
290 void set_index_scan_flags(
int flags) { info_->idxFlags = flags; }
292#if SQLITE_VERSION_NUMBER >= 3010000
293 std::bitset<64u> columns_used()
295 return std::bitset<64u>(info_->colUsed);
299 void set_index(
int value) { info_->idxNum = value; }
300 void set_index_string(
char * str,
301 bool take_ownership =
true)
304 info_->needToFreeIdxStr = take_ownership ? 1 : 0;
307 sqlite3_index_info * info()
const {
return info_; }
308 sqlite3 * db()
const {
return db_; }
311 explicit index_info(sqlite3 * db, sqlite3_index_info * info) : db_(db), info_(info) {}
313 sqlite3_index_info * info_{
nullptr};
314 friend struct detail::vtab_impl;
320#if SQLITE_VERSION_NUMBER >= 3031000
324 sqlite3_vtab_config(db_, SQLITE_VTAB_INNOCUOUS);
327 void set_directonly() {sqlite3_vtab_config(db_, SQLITE_VTAB_DIRECTONLY);}
332 void set_constraint_support(
bool enabled =
false)
334 sqlite3_vtab_config(db_, SQLITE_VTAB_CONSTRAINT_SUPPORT, enabled ? 1 : 0);
338 explicit module_config(sqlite3 *db) : db_(db) {}
339 friend struct detail::vtab_impl;
343template<
typename Table>
346 using table_type = Table;
351 BOOST_SQLITE_VIRTUAL result<table_type> create(sqlite::connection db,
int argc,
const char *
const argv[]) BOOST_SQLITE_PURE;
356 BOOST_SQLITE_VIRTUAL result<table_type> connect(sqlite::connection db,
int argc,
const char *
const argv[]) BOOST_SQLITE_PURE;
359template<
typename Table>
360struct eponymous_module
362 using table_type = Table;
367 BOOST_SQLITE_VIRTUAL result<table_type> connect(sqlite::connection db,
int argc,
const char *
const argv[]) BOOST_SQLITE_PURE;
369 eponymous_module(
bool eponymous_only =
false) : eponymous_only_(eponymous_only) {}
371 bool eponymous_only()
const {
return eponymous_only_;}
373 bool eponymous_only_{
false};
377template<
typename ColumnType>
381template<
typename Cursor>
382struct table :
protected sqlite3_vtab
384 using cursor_type = Cursor;
386 BOOST_SQLITE_VIRTUAL result<void> config(module_config &) {
return {};}
392 BOOST_SQLITE_VIRTUAL result<
void> destroy() {
return {}; }
400 BOOST_SQLITE_VIRTUAL result<cursor_type>
open() BOOST_SQLITE_PURE;
406 table(sqlite3 * db =
nullptr) : db_(db) {}
408 template<
typename ColumnType>
409 friend struct cursor;
410 friend struct detail::vtab_impl;
412 sqlite3 * db_{
nullptr};
416template<
typename ColumnType =
void>
417struct cursor :
protected sqlite3_vtab_cursor
419 using column_type = ColumnType;
422 BOOST_SQLITE_VIRTUAL result<void>
filter(
423 int index,
const char * index_data,
424 boost::span<sqlite::value> values)
426 return {system::in_place_error, SQLITE_OK};
430 BOOST_SQLITE_VIRTUAL result<void>
next() BOOST_SQLITE_PURE;
433 BOOST_SQLITE_VIRTUAL
bool eof() BOOST_SQLITE_PURE;
437 BOOST_SQLITE_VIRTUAL result<column_type> column(
int idx,
bool no_change) BOOST_SQLITE_PURE;
439 BOOST_SQLITE_VIRTUAL result<sqlite3_int64> row_id() BOOST_SQLITE_PURE;
445 friend struct detail::vtab_impl;
450struct cursor<void> :
protected sqlite3_vtab_cursor
452 using column_type = void;
455 BOOST_SQLITE_VIRTUAL result<void>
filter(
456 int index,
const char * index_data,
457 boost::span<sqlite::value> values)
459 return {system::in_place_error, SQLITE_OK};
463 BOOST_SQLITE_VIRTUAL result<void>
next() BOOST_SQLITE_PURE;
466 BOOST_SQLITE_VIRTUAL
bool eof() BOOST_SQLITE_PURE;
470 BOOST_SQLITE_VIRTUAL
void column(
context<> ctx,
int idx,
bool no_change) BOOST_SQLITE_PURE;
472 BOOST_SQLITE_VIRTUAL result<sqlite3_int64> row_id() BOOST_SQLITE_PURE;
478 friend struct detail::vtab_impl;
485 BOOST_SQLITE_VIRTUAL result<void> delete_(
sqlite::value key) BOOST_SQLITE_PURE;
487 BOOST_SQLITE_VIRTUAL result<sqlite_int64>
insert(
sqlite::value key, span<sqlite::value> values,
int on_conflict) BOOST_SQLITE_PURE;
496 BOOST_SQLITE_VIRTUAL result<void>
begin() BOOST_SQLITE_PURE;
498 BOOST_SQLITE_VIRTUAL result<
void> sync() BOOST_SQLITE_PURE;
500 BOOST_SQLITE_VIRTUAL result<
void> commit() BOOST_SQLITE_PURE;
502 BOOST_SQLITE_VIRTUAL result<
void> rollback() BOOST_SQLITE_PURE;
511 int arg,
const char * name) BOOST_SQLITE_PURE;
518 BOOST_SQLITE_VIRTUAL result<void>
rename(
const char * new_name) BOOST_SQLITE_PURE;
522#if SQLITE_VERSION_NUMBER >= 3007007
527 BOOST_SQLITE_VIRTUAL result<void>
savepoint(
int i) BOOST_SQLITE_PURE;
529 BOOST_SQLITE_VIRTUAL result<void>
release(
int i) BOOST_SQLITE_PURE;
531 BOOST_SQLITE_VIRTUAL result<void>
rollback_to(
int i) BOOST_SQLITE_PURE;
541template<
typename Module>
542const sqlite3_module make_module(
const Module & mod);
569 system::error_code & ec,
570 error_info & ei) ->
typename std::decay<T>::type &
572 using module_type =
typename std::decay<T>::type;
573 static const sqlite3_module mod = detail::make_module(module);
575 std::unique_ptr<module_type> p{
new (
memory_tag{}) module_type(std::forward<T>(module))};
578 int res = sqlite3_create_module_v2(
579 conn.handle(), name.c_str(),
583 static_cast<module_type*>(ptr)->~module_type();
587 if (res != SQLITE_OK)
589 BOOST_SQLITE_ASSIGN_EC(ec, res);
590 ei.set_message(sqlite3_errmsg(conn.handle()));
596auto create_module(connection & conn,
598 T && module) ->
typename std::decay<T>::type &
600 system::error_code ec;
602 T & ref = create_module(conn, name, std::forward<T>(module), ec, ei);
604 detail::throw_error_code(ec, ei);
610BOOST_SQLITE_END_NAMESPACE
612#include <boost/sqlite/detail/vtable.hpp>
auto create_module(connection &conn, cstring_ref name, T &&module, system::error_code &ec, error_info &ei) -> typename std::decay< T >::type &
Register a vtable.
main object for a connection to a database.
A context that can be passed into scalar functions.
Small wrapper for a null-terminated string that can be directly passed to C APIS.
Additional information about error conditions stored in an sqlite-allocate string.
A holder for a sqlite values used for internal APIs.
handle_type handle() const
Returns the handle.
virtual result< void > next()=0
Returns the next row.
virtual result< void > filter(int index, const char *index_data, boost::span< sqlite::value > values)
Apply a filter to the cursor. Required when best_index is implemented.
Cursor needs the following member.
virtual result< void > next()=0
Returns the next row.
virtual result< void > filter(int index, const char *index_data, boost::span< sqlite::value > values)
Apply a filter to the cursor. Required when best_index is implemented.
Helper type to set a function through the xFindFunction callback.
Utility function that can be used in xFilter for the in operator.
iterator end()
Returns a forward iterator to the in sequence for an in constraint pointing to the end.
iterator begin()
Returns a forward iterator to the in sequence for an in constraint pointing to the begin.
bool distinct() const
Returns true if the constraint is.
BOOST_ATTRIBUTE_NODISCARD span< const sqlite3_index_info::sqlite3_index_constraint > constraints() const
Returns constraints of the index.
const char * collation(std::size_t idx) const
Receive the collation for the contrainst of the position.
BOOST_ATTRIBUTE_NODISCARD span< const sqlite3_index_info::sqlite3_index_orderby > order_by() const
Returns ordering of the index.
Group of functions for modifications.
virtual result< sqlite_int64 > update(sqlite::value old_key, sqlite::value new_key, span< sqlite::value > values, int on_conflict)=0
Update the row.
virtual result< sqlite_int64 > insert(sqlite::value key, span< sqlite::value > values, int on_conflict)=0
Insert a new row.
Fucntion to enable function overriding See xFindFunction.
virtual result< void > find_function(function_setter fs, int arg, const char *name)=0
Support for recursive transactions.
virtual result< void > savepoint(int i)=0
Save the current state with to i
virtual result< void > release(int i)=0
Release all saves states down to i
virtual result< void > rollback_to(int i)=0
Roll the transaction back to i.
Make the vtable renamable.
virtual result< void > rename(const char *new_name)=0
Function to rename the table. Optional.
virtual result< cursor_type > open()=0
Start a search on the table. The cursor_type gets used & managed by value, OR a pointer to a class th...
virtual result< void > best_index(index_info &info)
virtual const char * declaration()=0
The Table declaration to be used with sqlite3_declare_vtab.
Group of functions to support transactions.
virtual result< void > begin()=0
Begin a tranasction.