summaryrefslogtreecommitdiff
path: root/doc/reference
diff options
context:
space:
mode:
Diffstat (limited to 'doc/reference')
-rw-r--r--doc/reference/allocator.adoc31
-rw-r--r--doc/reference/backup.adoc43
-rw-r--r--doc/reference/blob.adoc141
-rw-r--r--doc/reference/collation.adoc45
-rw-r--r--doc/reference/connection.adoc100
-rw-r--r--doc/reference/cstring_ref.adoc16
-rw-r--r--doc/reference/error.adoc91
-rw-r--r--doc/reference/extension.adoc36
-rw-r--r--doc/reference/field.adoc42
-rw-r--r--doc/reference/function.adoc263
-rw-r--r--doc/reference/hooks.adoc105
-rw-r--r--doc/reference/json.adoc28
-rw-r--r--doc/reference/memory.adoc29
-rw-r--r--doc/reference/meta_data.adoc36
-rw-r--r--doc/reference/mutex.adoc16
-rw-r--r--doc/reference/result.adoc40
-rw-r--r--doc/reference/resultset.adoc72
-rw-r--r--doc/reference/row.adoc56
-rw-r--r--doc/reference/statement.adoc165
-rw-r--r--doc/reference/static_resultset.adoc98
-rw-r--r--doc/reference/string.adoc18
-rw-r--r--doc/reference/transaction.adoc104
-rw-r--r--doc/reference/value.adoc85
-rw-r--r--doc/reference/vtable.adoc275
24 files changed, 1935 insertions, 0 deletions
diff --git a/doc/reference/allocator.adoc b/doc/reference/allocator.adoc
new file mode 100644
index 0000000..ab9a4e9
--- /dev/null
+++ b/doc/reference/allocator.adoc
@@ -0,0 +1,31 @@
+== `sqlite/allocator.hpp`
+[#allocator]
+
+The sqlite allocator wraps sqlite's malloc & free functions in a similar way that std::allocator wraps `new`/`delete`.
+
+This can be used for sqlite-related code (e.g. vtables or custom functions) that should use memory from the sqlite3 pool.
+
+[source,cpp,subs=+quotes]
+----
+template<typename T>
+struct allocator
+{
+ constexpr allocator() noexcept {}
+ constexpr allocator( const allocator& other ) noexcept {}
+ template< class U >
+ constexpr allocator( const allocator<U>& other ) noexcept {}
+
+ constexpr static std::size_t alignment = __implementation_defined__;
+
+
+ static_assert(alignof(T) <= alignment, "T alignment can't be fulfilled by sqlite");
+
+ [[nodiscard]] T* allocate( std::size_t n ); // <1>
+ void deallocate( T* p, std::size_t); // <2>
+};
+----
+<1> Invokes `sqlite3_malloc64` and throws `std::bad_alloc` if it fails.
+<2> Invokes `sqlite3_free`
+
+NOTE: Sqlite provides extensive https://www.sqlite.org/malloc.html[customizability for its dynamic memory allocation].
+
diff --git a/doc/reference/backup.adoc b/doc/reference/backup.adoc
new file mode 100644
index 0000000..bc74619
--- /dev/null
+++ b/doc/reference/backup.adoc
@@ -0,0 +1,43 @@
+== `sqlite/backup.hpp`
+[#backup]
+
+Backup is a small wrapper function to create a backup of one database into another.
+This can be useful to write an in memory database to disk et vice versa.
+
+[source,cpp]
+----
+void
+backup(connection & source,
+ connection & target,
+ cstring_ref source_name = "main",
+ cstring_ref target_name = "main");
+
+void
+backup(connection & source,
+ connection & target,
+ cstring_ref source_name,
+ cstring_ref target_name,
+ system::error_code & ec,
+ error_info & ei);
+----
+
+
+source:: The source database to backup
+
+target:: The target of the backup
+
+source_name:: The source database to read the backup from. Default is 'main'.
+target_name:: The target database to write the backup to. Default is 'main'.
+
+
+.Example
+[source,cpp]
+----
+sqlite::connection conn{sqlite::in_memory};
+{
+ sqlite::connection read{"./read_only_db.db", SQLITE_READONLY};
+ // read peristed data into memory.
+ backup(read, target);
+}
+----
+
diff --git a/doc/reference/blob.adoc b/doc/reference/blob.adoc
new file mode 100644
index 0000000..8f73105
--- /dev/null
+++ b/doc/reference/blob.adoc
@@ -0,0 +1,141 @@
+== `sqlite/blob.hpp`
+
+=== `blob_view`
+
+A `blob_view` is a view type referring to https://www.sqlite.org/datatype3.html[Binary Large OBject],
+i.e. a non-owning type.
+
+.Definition
+[source,cpp]
+----
+//A view to a binary large object
+struct blob_view
+{
+ // The data in the blob
+ const void * data() const;
+ // The size of the data in the blob, in bytes
+ std::size_t size() const
+ // Construct a blob from existing data
+ blob_view(const void * data, std::size_t size);
+
+ // Construct an empty blob
+ blob_view() = default;
+ // Construct a blob from some other blob-like structure (data() is a pointer & size() returns size_t)
+ template<typename T>
+ explicit blob_view(const T & value);
+
+ // Create a blob from the
+ blob_view(const struct blob & b);
+};
+----
+
+The `blob_view` can be used to access binary data from the database without copying.
+
+=== `zero_blob`
+
+The `zero_blob` is a special type that denotes blobs full of zeros without requiring any allocations.
+It can be used as a result from a <<function>> or as a parameter for a <<statement>>.
+
+.Definition
+[source,cpp]
+----
+enum class zero_blob : sqlite3_uint64 {};
+----
+
+.Example
+[source,cpp]
+----
+extern sqlite::connection conn;
+conn.prepare("INSERT INTO example(bdata) VALUES(?)")
+ .execute(sqlite::zero_blob(1024)); // <1>
+----
+<1> Insert a blob of zeros with the size 1024
+
+=== `blob`
+
+The `blob` object owns a binary large object.
+
+[source,cpp]
+----
+// @brief An object that owns a binary large object. @ingroup reference
+struct blob
+{
+ // The data in the blob
+ void * data() const;
+ // The size of the data int he blob, in bytes
+ std::size_t size() const;
+
+ // Create a blob from a blob_view
+ explicit blob(blob_view bv);
+ // Create an empty blob with size `n`.
+ explicit blob(std::size_t n);
+
+ // Construct an empty blob
+ constexpr blob() = default;
+ // Release & take ownership of the blob.
+ void * release() &&
+};
+----
+
+
+=== `blob_handle`
+
+A `blob_handle` is readable & writable handle to a `blob` in the database.
+It allows incremental reading/writing of the raw data.
+
+[source,cpp]
+----
+// Open a blob
+blob_handle open_blob(connection & conn,
+ cstring_ref db,
+ cstring_ref table,
+ cstring_ref column,
+ sqlite3_int64 row,
+ bool read_only,
+ system::error_code &ec,
+ error_info &ei);
+blob_handle open_blob(connection & conn,
+ cstring_ref db,
+ cstring_ref table,
+ cstring_ref column,
+ sqlite3_int64 row,
+ bool read_only = false);
+
+// An object that holds a binary large object. Can be obtained by using @ref blob_handle. @ingroup reference
+struct blob_handle
+{
+ // Default constructor
+ blob_handle() = default;
+
+ // Construct from a handle. This takesowner ship of the `sqlite3_blob` handle.
+ explicit blob_handle(sqlite3_blob * blob);
+
+ // Reopen the blob on another row (i.e. the same column of the same table)
+ void reopen(sqlite3_int64 row_id);
+ void reopen(sqlite3_int64 row_id, system::error_code & ec);
+
+ // Read data from the blob
+ void read_at(void *data, int len, int offset);
+ void read_at(void *data, int len, int offset, system::error_code &ec);
+
+ // Write data to the blob
+ void write_at(const void *data, int len, int offset);
+ void write_at(const void *data, int len, int offset, system::error_code &ec);
+
+ // The size of the blob
+ std::size_t size() const;
+
+ // The handle of the blob
+ using handle_type = sqlite3_blob*;
+ // Returns the handle of the blob
+ handle_type handle();
+ // Release the owned handle.
+ handle_type release() &&;
+};
+----
+
+
+
+
+
+
diff --git a/doc/reference/collation.adoc b/doc/reference/collation.adoc
new file mode 100644
index 0000000..6578f59
--- /dev/null
+++ b/doc/reference/collation.adoc
@@ -0,0 +1,45 @@
+== `sqlite/collation.hpp`
+[#collation]
+
+A https://www.sqlite.org/datatype3.html#collation[collation] is a comparison operator between two string-like values,
+that allows ordering with a custom algorithm.
+
+.Definition
+[source,cpp]
+----
+
+// Create a collation
+template<typename Func>
+void create_collation(connection & conn, cstring_ref name, Func && func);
+template<typename Func>
+void create_collation(connection & conn, cstring_ref name, Func && func, system::error_code &ec);
+
+// Delete an existing collation.
+void delete_collation(connection & conn, cstring_ref name, system::error_code & ec);
+void delete_collation(connection & conn, cstring_ref name);
+----
+
+ conn:: A connection to the database in which to install the collation.
+ name:: The name of the collation.
+ func:: The function
+
+The function must be callable with two `string_view` and return an int, indicating the comparison results.
+
+.Example
+[source,cpp]
+----
+// a case insensitive string omparison, e.g. from boost.urls
+int ci_compare(string_view s0, string_view s1) noexcept;
+
+extern sqlite::connection conn;
+
+// Register the collation
+sqlite::create_collation(conn, "iequal", &ci_compare);
+
+// use the collation to get by name, case insensitively
+conn.query("select first_name, last_name from people where first_name = 'Klemens' collate iequal;");
+
+// order by names case insensitively
+conn.query("select * from people order by last_name collate iequal asc;");
+----
+
diff --git a/doc/reference/connection.adoc b/doc/reference/connection.adoc
new file mode 100644
index 0000000..6d62c10
--- /dev/null
+++ b/doc/reference/connection.adoc
@@ -0,0 +1,100 @@
+== `sqlite/connection.hpp`
+[#connection]
+
+The `connection` object is the main object to access a database.
+
+.Definition
+[source,cpp]
+----
+// Utility constant for in-memory databases
+constexpr static cstring_ref in_memory = ":memory:";
+
+struct connection
+{
+ // The handle of the connection
+ using handle_type = sqlite3*;
+ // Returns the handle
+ handle_type handle() const;
+ // Release the owned handle.
+ handle_type release() &&;
+
+ //Default constructor
+ connection() = default;
+ // Construct the connection from a handle.
+ explicit connection(handle_type handle, bool take_ownership = true); // <1>
+ // Move constructor.
+ connection(connection && ) = default;
+ // Move assign operator.
+ connection& operator=(connection && ) = default;
+
+ // Construct a connection and connect it to `filename`. `flags` is set by `SQLITE_OPEN_*` flags.
+ connection(cstring_ref filename,
+ int flags = SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE); // <2>
+ template<typename Path>
+ explicit connection(const Path & pth);
+
+
+ // Connect the database to `filename`. `flags` is set by `SQLITE_OPEN_*` flags.
+ void connect(cstring_ref filename, int flags = SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE); // <2>
+ void connect(cstring_ref filename, int flags, system::error_code & ec);
+
+ template<typename Path>
+ void connect(const Path & pth, int flags = SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE);
+ template<typename Path>
+ void connect(const Path & pth, int flags, system::error_code & ec);
+
+ // Close the database connection.
+ void close();
+ void close(system::error_code & ec, error_info & ei);
+
+ // Check if the database holds a valid handle.
+ bool valid() const;
+
+ // Perform a query without parameters. Can only execute a single statement.
+ resultset query(
+ core::string_view q,
+ system::error_code & ec,
+ error_info & ei);
+ resultset query(core::string_view q);
+
+ template<typename T, bool Strict = false>
+ static_resultset<T, Strict> query(core::string_view q, system::error_code & ec, error_info & ei);
+ template<typename T, bool Strict = false>
+ static_resultset<T, Strict> query(core::string_view q);
+
+ // Perform a query without parametert, It execute a multiple statement.
+ void execute(cstring_ref q, system::error_code & ec, error_info & ei);
+ void execute(cstring_ref q);
+
+
+ // Preparse a a statement.
+ statement prepare(
+ core::string_view q,
+ system::error_code & ec,
+ error_info & ei);
+ statement prepare(core::string_view q);
+
+
+ // Check if the database has the table
+ bool has_table(
+ cstring_ref table,
+ cstring_ref db_name = "main") const;
+
+ // Check if the database has the table
+ bool has_column(
+ cstring_ref table,
+ cstring_ref column,
+ cstring_ref db_name = "main") const;
+};
+
+----
+<1> The `take_ownership` is usually only false when used from <<extension_modules, extension modules>>.
+<2> See https://www.sqlite.org/c3ref/c_open_autoproxy.html[the sqlite documentation for the available flags].
+
+.Example
+[source,cpp]
+----
+sqlite::connection conn;
+conn.connect("./my-database.db");
+conn.prepare("insert into log (text) values ($1)").execute(std::make_tuple("booting up"));
+---- \ No newline at end of file
diff --git a/doc/reference/cstring_ref.adoc b/doc/reference/cstring_ref.adoc
new file mode 100644
index 0000000..402663d
--- /dev/null
+++ b/doc/reference/cstring_ref.adoc
@@ -0,0 +1,16 @@
+== `sqlite/cstring_ref.hpp`
+
+[#string_view]
+
+The `sqlite::string_view` class is a https://en.cppreference.com/w/cpp/string/basic_string_view[std::string_view]
+compatible class.
+
+[#cstring_ref]
+
+The `cstring_ref` class is a view type similar to a `string_view`, but with a guarantee that it is null-terminated.
+
+It can be constructed from a raw `const char *` or any class that has a `c_str()` function returning a `const char *`.
+
+Otherwise it is similar to a `string_view`, except that `substr(std::size_t())` will return a `cstring_ref`,
+whereas a `substr(std::size_t(), std::size_t())` returns a `string_view`.
+
diff --git a/doc/reference/error.adoc b/doc/reference/error.adoc
new file mode 100644
index 0000000..424c7dd
--- /dev/null
+++ b/doc/reference/error.adoc
@@ -0,0 +1,91 @@
+== `sqlite/error.hpp`
+
+=== `sqlite_category`
+
+The sqlite_category is a `boost::system::error_category` to be used with sqlite errors.
+
+=== `error_info`
+
+The `error_info` class hold additional information about error conditions stored in an sqlite-allocate string.
+
+Contains an error message describing what happened. Not all error conditions are able to generate this extended information - those that
+can't will have an empty error message.
+
+The `error_info` allocates memory from the sqlite pool and holds it.
+
+[source,cpp]
+----
+struct error_info
+{
+ // Default constructor.
+ error_info() = default;
+
+ // Initialization constructor. Copies the message into a newly create buffer.
+ error_info(core::string_view msg) noexcept;
+ // set the message by copy
+ void set_message(core::string_view msg);
+
+ // Reset the buffer. If `c` is not null, its ownership is transferred into the error_info object.
+ void reset(char * c = nullptr);
+
+ // Format a message into a newly allocated buffer.
+ cstring_ref format(cstring_ref fmt, ...);
+ // Format a message into the existing buffer.
+ cstring_ref snformat(cstring_ref fmt, ...);
+ /// reserve data in the buffer i.e. allocate
+ void reserve(std::size_t sz);
+
+ // Get the allocated memory
+ std::size_t capacity() const;
+
+ // Gets the error message.
+ cstring_ref message() const noexcept;
+
+ // Release the underlying memory. It must be freed using `sqlite_free` later.
+ char * release();
+ // Restores the message to its initial state. Does not release memory.
+ void clear() noexcept;
+
+};
+----
+
+=== `error`
+
+The `error` class holds `error_info` and a `code` and can be used with https://www.boost.org/doc/libs/master/libs/system/doc/html/system.html#ref_boostsystemresult_hpp[`boost::system::result`].
+
+[source,cpp]
+----
+/**
+ * \brief An error containing both a code & optional message.
+ * \ingroup reference
+ * \details Contains an error .
+ */
+struct error
+{
+ // The code of the error.
+ int code;
+ // The additional information of the error
+ error_info info;
+
+ // Create an error with code & message
+ error(int code, error_info info) ;
+ error(int code, core::string_view info);
+ error(system::error_code code, error_info info) // <1>
+ // Create an error with only a code.
+ explicit error(int code);
+
+ error(system::error_code code);
+ // Create an empty error;
+ error() = default;
+ error(error && ) noexcept = default;
+};
+
+// For compatability with system::result;
+void throw_exception_from_error( error const & e, boost::source_location const & loc );
+
+template<typename T = void>
+using result = system::result<T, error>;
+----
+<1> If code.category() is not `sqlite_category`, the code will be set to `SQLITE_FAIL`.
+
+
diff --git a/doc/reference/extension.adoc b/doc/reference/extension.adoc
new file mode 100644
index 0000000..7ee2500
--- /dev/null
+++ b/doc/reference/extension.adoc
@@ -0,0 +1,36 @@
+== `sqlite/extension.hpp`
+
+=== `BOOST_SQLITE_EXTENSION`
+
+ This macro can be used to create an sqlite extension.
+
+.Definition
+[source,cpp]
+----
+#define BOOST_SQLITE_EXTENSION(Name, Conn)
+----
+
+Name:: The name of the module.
+Conn:: The parameter name of the connection.
+
+
+NOTE: When defining BOOST_SQLITE_COMPILE_EXTENSION (was is done in extension.hpp)
+sqlite will use an inline namespace to avoid symbol clashes.
+
+You must link against `Boost::sqlite_ext` and not `Boost::sqlite` and should not mix both in the same binary.
+
+.Example
+[source,cpp]
+----
+BOOST_SQLITE_EXTENSION(extension, conn)
+{
+ create_scalar_function(
+ conn, "assert",
+ [](boost::sqlite::context<>, boost::span<boost::sqlite::value, 1u> sp)
+ {
+ if (sp.front().get_int() == 0)
+ throw std::logic_error("assertion failed");
+ });
+}
+----
+
diff --git a/doc/reference/field.adoc b/doc/reference/field.adoc
new file mode 100644
index 0000000..572719d
--- /dev/null
+++ b/doc/reference/field.adoc
@@ -0,0 +1,42 @@
+== `sqlite/field.hpp`
+
+A `field` is a type representing a <<value>> in a database. or as a result from a query.
+
+.Definition
+[source,cpp]
+----
+
+struct field
+{
+ typedef sqlite_int64 int64;
+
+ // The type of the value
+ value_type type() const;
+ // Is the held value null
+ bool is_null() const;
+ // Is the held value is not null
+ explicit operator bool () const;
+ // Returns the value as an `int64`.
+ int64 get_int() const;
+ // Returns the value as an `double`.
+ double get_double() const;
+ // Returns the value as text, i.e. a string_view. Note that this value may be invalidated
+ cstring_ref get_text() const;
+ // Returns the value as blob, i.e. raw memory. Note that this value may be invalidated
+ blob_view get_blob() const;
+ // Returns the field as a value.
+ value get_value() const;
+ // Returns the name of the column.
+ cstring_ref column_name() const;
+ // Returns the name of the table.
+ cstring_ref table_name() const;
+ // Returns the name of the original data source.
+ cstring_ref column_origin_name() const;
+}
+----
+
+NOTE: The view types can be invalidated when the database changes or the next row is read by the query.
+
+WARNING: The `field` type does not own the statement/query it was produced by. It is a merely a view into the `resultset`.
+Reading the next row will change the values returned.
+
diff --git a/doc/reference/function.adoc b/doc/reference/function.adoc
new file mode 100644
index 0000000..311aebc
--- /dev/null
+++ b/doc/reference/function.adoc
@@ -0,0 +1,263 @@
+== `sqlite/function.hpp`
+
+=== `function_flags`
+
+[source, cpp]
+----
+enum function_flags
+{
+ deterministic = SQLITE_DETERMINISTIC,
+ directonly = SQLITE_DIRECTONLY,
+ subtype = SQLITE_SUBTYPE,
+ innocuous = SQLITE_INNOCUOUS,
+ result_subtype = SQLITE_RESULT_SUBTYPE,
+ selforder1 = SQLITE_SELFORDER1,
+ selforder1 = SQLITE_SELFORDER1
+};
+----
+
+These function flags can be used in accordance to the
+https://www.sqlite.org/c3ref/c_deterministic.html[sqlite documentation].
+
+=== `context`
+
+A context is an object share values between invocations of a scalar function.
+
+.Definition
+[source,cpp]
+----
+
+template<typename ... Args>
+struct context
+{
+ template<std::size_t N>
+ using element = mp11::mp_take_c<mp11::mp_list<Args...>, N>;
+
+ // Set the value in the context at position `Idx`
+ template<std::size_t Idx>
+ void set(element<Idx> value);
+
+ // Returns the value in the context at position `Idx`. Throws if the value isn't set.
+ template<std::size_t Idx>
+ auto get() -> element<Idx> &;
+
+ // Returns the value in the context at position `Idx`. Returns nullptr .value isn't set.
+ template<std::size_t Idx>
+ auto get_if() -> element<Idx> *;
+
+ explicit context(sqlite3_context * ctx) noexcept;
+
+ // Set the result through the context, instead of returning it.
+ template<typename T>
+ auto set_result(T && val);
+
+ // Set the an error through the context, instead of throwing it.
+ void set_error(cstring_ref message, int code = SQLITE_ERROR);
+
+ // Returns the connection of the context.
+ connection get_connection() const;
+};
+----
+
+
+.Example
+[source,cpp]
+----
+extern sqlite::connection conn;
+
+sqlite::create_scalar_function(
+conn, "my_sum",
+[](sqlite::context<std::size_t> ctx,
+ boost::span<sqlite::value, 1u> args) -> std::size_t
+{
+ auto value = args[0].get_int();
+ auto p = ctx.get_if<0>();
+ if (p != nullptr) // increment the counter
+ return (*p) += value;
+ else // set the initial value
+ ctx.set<0>(value);
+ return value;
+});
+----
+
+
+=== `create_scalar_function`
+
+
+Creates a https://www.sqlite.org/appfunc.html[scalar function].
+
+.Definition
+[source,cpp]
+----
+
+template<typename Func>
+auto create_scalar_function(
+ connection & conn,
+ cstring_ref name,
+ Func && func,
+ function_flags flags = {});
+
+template<typename Func>
+auto create_scalar_function(
+ connection & conn,
+ cstring_ref name,
+ Func && func,
+ function_flags flags,
+ system::error_code & ec,
+ error_info & ei);
+----
+
+conn:: The connection to add the function to.
+name:: The name of the function
+func:: The function to be added
+
+`func` must take `context<Args...>` as the first and a `span<value, N>` as the second value.
+If `N` is not `dynamic_extent` it will be used to deduce the number of arguments for the function.
+
+
+.Example
+[source,cpp]
+----
+extern sqlite::connection conn;
+
+sqlite::create_function(
+ conn, "to_upper",
+ [](sqlite::context<> ctx,
+ boost::span<sqlite::value, 1u> args) -> std::string
+ {
+ std::string res;
+ auto txt = val[0].get_text();
+ res.resize(txt.size());
+ std::transform(txt.begin(), txt.end(), res.begin(),
+ [](char c){return std::toupper(c);});
+ return value;
+ });
+----
+
+
+=== `create_aggregate_function`
+
+An aggregrate function will create a new `Func` for a new `aggregate` from the args tuple and call `step` for every step.
+When the aggregation is done `final` is called and the result is returned to sqlite.
+
+[source,cpp]
+----
+template<typename Func, typename Args = std::tuple<>>
+void create_aggregate_function(
+connection & conn,
+cstring_ref name,
+Args && args= {},
+function_flags flags = {});
+
+template<typename Func, typename Args = std::tuple<>>
+void create_aggregate_function(
+connection & conn,
+cstring_ref name,
+Args && args,
+function_flags flags,
+system::error_code & ec,
+error_info & ei);
+----
+
+
+conn:: The connection to add the function to.
+name:: The name of the function
+
+args:: The argument tuple to construct `Func` from.
+Func:: The function to be added. It needs to be an object with two functions:
+[source,cpp]
+----
+void step(boost::span<sqlite::value, N> args);
+T final();
+----
+
+.Example
+[source,cpp]
+----
+ extern sqlite::connection conn;
+
+struct aggregate_func
+{
+ aggregate_func(std::size_t init) : counter(init) {}
+ std::int64_t counter;
+ void step(, boost::span<sqlite::value, 1u> val)
+ {
+ counter += val[0].get_text().size();
+ }
+
+ std::int64_t final()
+ {
+ return counter;
+ }
+};
+
+sqlite::create_function<aggregate_func>(conn, "char_counter", std::make_tuple(42));
+----
+
+
+=== `create_window_function`
+
+NOTE: This is only available starting with sqlite 3.25.0.
+
+An window function will create a new `Func` for a new `aggregate` and call `step` for every step.
+When an element is removed from the window `inverse` is called.
+When the aggregation is done `final` is called and the result is returned to sqlite.
+
+[source,cpp]
+----
+template<typename Func, typename Args = std::tuple<>>
+void create_window_function(
+ connection & conn,
+ cstring_ref name,
+ Args && args = {},
+ function_flags flags = {});
+
+template<typename Func, typename Args = std::tuple<>>
+void create_window_function(
+ connection & conn,
+ cstring_ref name,
+ Args && args,
+ function_flags flags,
+ system::error_code & ec);
+----
+
+
+conn:: The connection to add the function to.
+name:: The name of the function
+args:: The arguments to construct Func from.
+Func:: The function to be added. It needs to be an object with three functions:
+[source,cpp]
+----
+void step(boost::span<sqlite::value, N> args);
+void inverse(boost::span<sqlite::value, N> args);
+T final();
+----
+
+
+.Example
+[source,cpp]
+----
+extern sqlite::connection conn;
+
+struct window_func
+{
+ std::int64_t counter;
+ void step(boost::span<sqlite::value, 1u> val)
+ {
+ counter += val[0].get_text().size();
+ }
+ void inverse(boost::span<sqlite::value, 1u> val)
+ {
+ counter -= val[0].get_text().size();
+ }
+
+ std::int64_t final()
+ {
+ return counter;
+ }
+};
+
+sqlite::create_function(conn, "win_char_counter", aggregate_func{});
+----
+
+
diff --git a/doc/reference/hooks.adoc b/doc/reference/hooks.adoc
new file mode 100644
index 0000000..c74d712
--- /dev/null
+++ b/doc/reference/hooks.adoc
@@ -0,0 +1,105 @@
+== `sqlite/hooks.hpp`
+
+WARNING: This API might be subject change, if a better solution for ownership is found.
+
+=== `commit_hook` & `rollback_commit`
+
+The https://www.sqlite.org/c3ref/commit_hook.html[commit hook]
+gets called before a commit gets performed.
+Likewise the rollback hook gets invoked before a rollback.
+If `func` returns true, the commit goes, otherwise it gets rolled back.
+
+NOTE: If the function is not a free function pointer, this function will *NOT* take ownership.
+
+NOTE: If `func` is a `nullptr` the hook gets reset.
+
+
+[source,cpp]
+----
+template<typename Func>
+bool commit_hook(connection & conn, Func && func);
+
+template<typename Func>
+bool rollback_hook(connection & conn, Func && func);
+----
+
+return:: `true` if a hook has been replaced.
+conn:: The database connection to install the hook in
+func:: The hook function. It must be callable without any parameter, return a `bool` and be `noexcept`.
+
+
+=== `update_hook`
+
+The https://www.sqlite.org/c3ref/update_hook.html[update hook]
+The update hook gets called when an update was performed.
+
+
+NOTE: If the function is not a free function pointer, this function will *NOT* take ownership.
+
+NOTE: If `func` is a `nullptr` the hook gets reset.
+
+
+[source,cpp]
+----
+template<typename Func>
+bool update_hook(connection & conn, Func && func);
+----
+
+return:: `true` if a hook has been replaced.
+conn:: The database connection to install the hook in
+func:: The signature of the function is `void(int op, core::string_view db, core::string_view table, sqlite3_int64 id)`.
+`op` is either `SQLITE_INSERT`, `SQLITE_DELETE` and `SQLITE_UPDATE`. The function must be noexcept.
+
+=== `preupdate_hook`
+
+NOTE: The https://www.sqlite.org/c3ref/preupdate_blobwrite.html[preupdate hook] requires
+sqlite to be required with `SQLITE_ENABLE_PREUPDATE_HOOK` true.
+
+This hook gets called before an update.
+
+[source,cpp]
+----
+struct preupdate_context
+{
+ // Returns the old value, i.e. the value before the update.
+ system::result<value> old(int column) const;
+ // The count of colums to be updated
+ int count() const;
+ // The nesting depth of the update.
+ int depth() const;
+ // The new value to be written to column
+ system::result<value> new_(int column) const;
+
+ // Query the status of blob access, e.g. when using blob_handle <1>
+ int blob_write() const;
+
+ explicit preupdate_context(sqlite3 * db) noexcept;
+};
+
+
+template<typename Func>
+bool preupdate_hook(connection & conn, Func && func);
+----
+<1> See https://www.sqlite.org/c3ref/preupdate_blobwrite.html[sqlite/preupdate_blobwrite]
+
+
+
+return:: `true` if a hook has been replaced.
+conn:: The database connection to install the hook in
+func:: The signature of the function is below:
+[source,cpp]
+----
+ void preupdate_hook(sqlite::preupdate_context ctx,
+ int op,
+ const char * db_name,
+ const char * table_name,
+ sqlite3_int64 current_key,
+ sqlite3_int64 new_key);
+----
+
+
+
+
+
+
+
diff --git a/doc/reference/json.adoc b/doc/reference/json.adoc
new file mode 100644
index 0000000..1c15f52
--- /dev/null
+++ b/doc/reference/json.adoc
@@ -0,0 +1,28 @@
+== `sqlite/json.hpp`
+
+The json header provides integration with boost/json.
+
+[source,cpp]
+----
+
+// The subtype value used by the sqlite json extension. See the [sqlite reference](https://www.sqlite.org/json1.html)
+constexpr int json_subtype = static_cast<int>('J');
+
+// Allow json to be used as a result from functions or vtables
+void tag_invoke(const struct set_result_tag &, sqlite3_context * ctx, const json::value & value);
+
+// Check if the value or field is a json.
+bool is_json(const value & v);
+bool is_json(const field & f);
+
+//Convert the value or field to a json.
+json::value as_json(const value & v, json::storage_ptr ptr = {});
+json::value as_json(const field & f, json::storage_ptr ptr = {});
+
+// Allow conversions to boost::json::value
+void tag_invoke( const json::value_from_tag &, json::value& val, const value & f);
+void tag_invoke( const json::value_from_tag &, json::value& val, const field & f);
+void tag_invoke( const json::value_from_tag &, json::value& val, resultset && rs);
+----
+
+
diff --git a/doc/reference/memory.adoc b/doc/reference/memory.adoc
new file mode 100644
index 0000000..7bf62ef
--- /dev/null
+++ b/doc/reference/memory.adoc
@@ -0,0 +1,29 @@
+== `sqlite/memory.hpp`
+
+The memory header provides C++-y access to the memory facilities of sqlite.
+
+[source,cpp,subs=+quotes]
+----
+// A tag to allow `operator new`
+struct memory_tag {};
+
+// new operators <1>
+void *operator new ( std::size_t size, boost::sqlite::memory_tag) noexcept;
+void *operator new[]( std::size_t size, boost::sqlite::memory_tag) noexcept;
+void operator delete ( void* ptr, boost::sqlite::memory_tag) noexcept;
+
+// A unique ptr that uses sqlite3_malloc / sqlite3_free
+template<typename T>
+using unique_ptr = std::unique_ptr<T, __implementation_detail__>;
+template<typename T, typename ... Args>
+unique_ptr<T> make_unique(Args && ... args);
+
+// Get the size of the allocated memory.
+template<typename T>
+std::size_t msize(const unique_ptr<T> & ptr);
+
+
+---
+<1> `new (sqlite::memory_tag{}) T()` uses sqlite3_malloc
+
+
diff --git a/doc/reference/meta_data.adoc b/doc/reference/meta_data.adoc
new file mode 100644
index 0000000..6375108
--- /dev/null
+++ b/doc/reference/meta_data.adoc
@@ -0,0 +1,36 @@
+== `sqlite/meta_data.hpp`
+
+The meta_data header provides some meta_data for columns.
+
+[source,cpp,subs=+quotes]
+----
+// The metadata of a column
+struct column_meta_data
+{
+ // Data type fo the column
+ cstring_ref data_type;
+ // Name of default collation sequence
+ cstring_ref collation;
+ // true if column has a NOT NULL constraint
+ bool not_null;
+ // true if column is part of the PRIMARY KEY
+ bool primary_key;
+ // true if column is AUTOINCREMENT
+ bool auto_increment;
+};
+
+// get the meta-data of one colum
+
+column_meta_data table_column_meta_data(connection & conn,
+ cstring_ref db_name, cstring_ref table_name, cstring_ref column_name,
+ system::error_code & ec, error_info &ei);
+column_meta_data table_column_meta_data(connection & conn,
+ cstring_ref table_name, cstring_ref column_name,
+ system::error_code & ec, error_info &ei);
+
+column_meta_data table_column_meta_data(connection & conn,
+ cstring_ref db_name, cstring_ref table_name, cstring_ref column_name);
+column_meta_data table_column_meta_data(connection & conn,
+ cstring_ref table_name, cstring_ref column_name);
+---
+
diff --git a/doc/reference/mutex.adoc b/doc/reference/mutex.adoc
new file mode 100644
index 0000000..d0493d6
--- /dev/null
+++ b/doc/reference/mutex.adoc
@@ -0,0 +1,16 @@
+== `sqlite/mutex.hpp`
+
+The mutex header provides to std::mutex compatible classes using the sqlite mutex implementation.
+
+This will allow C++ code to use mutex code matching the configuration of sqlite.
+This may include the mutex being a noop.
+
+[source,cpp,subs=+quotes]
+----
+// similar to std::mutex
+struct mutex;
+// similar to std::recursive_mutexx
+struct recursive_mutex;
+----
+
+
diff --git a/doc/reference/result.adoc b/doc/reference/result.adoc
new file mode 100644
index 0000000..0471b95
--- /dev/null
+++ b/doc/reference/result.adoc
@@ -0,0 +1,40 @@
+== `sqlite/result.hpp`
+
+The result header is used by functions and vtables to turn resulting values into
+sqlite values. The `tag_invoke` interface is public and meant to extended.
+
+That is, implementing `tag_invoke(sqlite::set_result_tag, sqlite3_context, T);`
+will enable `T` to be used as a result by sqlite.
+
+[source,cpp]
+----
+// The tag
+struct set_result_tag {};
+
+// built-in result type
+inline void tag_invoke(set_result_tag, sqlite3_context * ctx, blob b);
+inline void tag_invoke(set_result_tag, sqlite3_context * ctx, zero_blob zb);
+inline void tag_invoke(set_result_tag, sqlite3_context * ctx, double dbl) { sqlite3_result_double(ctx, dbl); }
+inline void tag_invoke(set_result_tag, sqlite3_context * ctx, sqlite3_int64 value);inline void tag_invoke(set_result_tag, sqlite3_context * ctx, std::int64_t value);
+inline void tag_invoke(set_result_tag, sqlite3_context * ctx, std::nullptr_t);
+inline void tag_invoke(set_result_tag, sqlite3_context * ctx, string_view str);
+template<typename String>
+inline auto tag_invoke(set_result_tag, sqlite3_context * ctx, String && str);
+inline void tag_invoke(set_result_tag, sqlite3_context * , variant2::monostate);
+inline void tag_invoke(set_result_tag, sqlite3_context * ctx, const value & val);
+template<typename ... Args>
+inline void tag_invoke(set_result_tag, sqlite3_context * ctx, const variant2::variant<Args...> & var);
+
+template<typename T>
+inline void tag_invoke(set_result_tag, sqlite3_context * ctx, std::unique_ptr<T> ptr);
+template<typename T>
+inline void tag_invoke(set_result_tag, sqlite3_context * ctx, std::unique_ptr<T, void(*)(T*)> ptr);
+template<typename T, typename Deleter>
+inline auto tag_invoke(set_result_tag, sqlite3_context * ctx, std::unique_ptr<T> ptr);
+inline void tag_invoke(set_result_tag, sqlite3_context * ctx, error err);
+template<typename T>
+inline void tag_invoke(set_result_tag tag, sqlite3_context * ctx, result<T> res);
+inline void tag_invoke(set_result_tag tag, sqlite3_context * ctx, result<void> res):
+----
+
+
diff --git a/doc/reference/resultset.adoc b/doc/reference/resultset.adoc
new file mode 100644
index 0000000..fb793a5
--- /dev/null
+++ b/doc/reference/resultset.adoc
@@ -0,0 +1,72 @@
+== `sqlite/resultset.hpp`
+
+A resultset represents the results of a query.
+
+[source,cpp]
+----
+// Representation of a result from a query.
+
+struct resultset
+{
+ // Returns the current row. The row is a pure view type.
+ row current() const &;
+ // Checks if the last row has been reached.
+ bool done() const;
+
+ // Read the next row. Returns false if there's nothing more to read.
+ // Calling this will change the data of any `row` previously obtained from `current.
+ bool read_next(system::error_code & ec, error_info & ei);
+ bool read_next();
+
+ // The number of colums in the resultset
+ std::size_t column_count() const;
+ // Returns the name of the column idx.
+ string_view column_name(std::size_t idx) const;
+ // Returns the name of the source table for column idx.
+ string_view table_name(std::size_t idx) const;
+ // Returns the origin name of the column for column idx.
+ string_view column_origin_name(std::size_t idx) const;
+
+ // The input iterator can be used to read every row in a for-loop
+ struct iterator
+ {
+ using value_type = value;
+ using difference_type = int;
+ using reference = value&;
+ using iterator_category = std::forward_iterator_tag;
+
+ iterator() {}
+
+ bool operator!=(iterator rhs) const;
+ row &operator*();
+ row *operator->();
+
+ iterator operator++();
+ iterator operator++(int);
+ };
+
+ // Return an input iterator to the currently unread row
+ iterator begin();
+ // Sentinel iterator.
+ iterator end();
+};
+----
+
+
+
+
+.Example
+[source,cpp]
+----
+extern sqlite::connection conn;
+
+sqlite::resultset rs = conn.query("select * from users;");
+
+do
+{
+ handle_row(r.current());
+}
+while (rs.read_next()); // read it line by line
+----
+
+
diff --git a/doc/reference/row.adoc b/doc/reference/row.adoc
new file mode 100644
index 0000000..d3af982
--- /dev/null
+++ b/doc/reference/row.adoc
@@ -0,0 +1,56 @@
+== `sqlite/row.hpp`
+
+This type represents one row of data from a query. Is a random-access range.
+
+WARNING: This type is a pure view type, and will be invalidated when the next row is read.
+
+
+
+[source,cpp]
+----
+
+struct row
+{
+ // The size of the row, i.e. number of colums
+ std::size_t size() const;
+
+ // Returns the field at `idx`, @throws std::out_of_range
+ field at(std::size_t idx) const;
+ // Returns the field at `idx`.
+ field operator[](std::size_t idx) const;
+
+ // Random access iterator used to iterate over the columns.
+ struct const_iterator
+ {
+ using difference_type = int;
+ using reference = field&;
+ using iterator_category = std::random_access_iterator_tag;
+
+ const_iterator & operator++();
+ const_iterator operator++(int);
+ const_iterator & operator--();
+ const_iterator operator--(int);
+
+ field operator[](int i) const;
+
+ const_iterator operator+(int i) const;
+ const_iterator operator-(int i) const;
+ const_iterator & operator+=(int i);
+ const_iterator & operator-=(int i);
+ const field & operator*() const;
+ const field * operator->() const;
+
+ bool operator==(const const_iterator& other) const;
+ bool operator!=(const const_iterator& other) const;
+ bool operator<(const const_iterator& other) const;
+ bool operator>(const const_iterator& other) const;
+
+ const_iterator() = default;
+ };
+ // Returns the begin of the column-range.
+ const_iterator begin() const;
+
+ // Returns the end of the column-range.
+ const_iterator end() const
+};
+----
diff --git a/doc/reference/statement.adoc b/doc/reference/statement.adoc
new file mode 100644
index 0000000..6ce89e4
--- /dev/null
+++ b/doc/reference/statement.adoc
@@ -0,0 +1,165 @@
+== `sqlite/statement.hpp`
+
+=== `param_ref`
+
+A reference to a value to temporary bind for an execute statement. Most values are captures by reference.
+
+[source,cpp]
+----
+struct param_ref
+{
+ // Default construct a parameter, gives `null`.
+ param_ref() = default;
+ // Bind null
+ param_ref(variant2::monostate);
+ // Bind null
+ param_ref(std::nullptr_t);
+ // Bind an integer.
+ template<typename I>
+ param_ref(I value);
+ // Bind a blob.
+ param_ref(blob_view blob);
+ // Bind a string.
+ param_ref(string_view text);
+
+ template<typename StringLike>
+ param_ref(StringLike && text);
+ template<typename BlobLike>
+ param_ref(BlobLike && text);
+
+ // Bind a floating point value.
+ param_ref(double value) : impl_(value) { }
+ // Bind a zero_blob value, i.e. a blob that initialized by zero.
+ param_ref(zero_blob zb) : impl_(zb) { }
+
+ // Bind pointer value to the parameter. @see https://www.sqlite.org/bindptr.html
+ // Requires sqlite 3.20
+ // Deleter must a function pointer or trivially constructible.
+ template<typename T, typename Deleter>
+ param_ref(std::unique_ptr<T, Deleter> ptr);
+
+
+
+ // Apply the param_ref to a statement.
+ int apply(sqlite3_stmt * stmt, int c) const;
+
+ // Construct param_ref from a variant
+ template<typename T>
+ param_ref(T && t);
+
+----
+
+
+=== `statement`
+
+A statement used for a prepared-statement.
+
+
+
+[source,cpp]
+----
+struct statement
+{
+ // execute the prepared statement once. This transfers ownership to the resultset
+ template <typename ArgRange = std::initializer_list<param_ref>>
+ resultset execute(ArgRange && params, system::error_code& ec, error_info& info) &&; // <1>
+ template <typename ArgRange = std::initializer_list<param_ref>
+ resultset execute(ArgRange && params) &&; // <1>
+ resultset execute(
+ std::initializer_list<std::pair<string_view, param_ref>> params,
+ system::error_code& ec,
+ error_info& info) &&; // <2>
+
+ resultset execute(std::initializer_list<std::pair<string_view, param_ref>> params) &&;
+ template<typename T, bool Strict = false, typename ArgRange = std::initializer_list<param_ref>>
+ static_resultset<T, Strict> execute(
+ ArgRange && params,
+ system::error_code & ec,
+ error_info & ei) &&; // <1>
+
+ template<typename T, bool Strict = false, typename ArgRange = std::initializer_list<param_ref>>
+ static_resultset<T, Strict> execute(ArgRange && params) &&; // <1>
+
+ template<typename T, bool Strict = false>
+ static_resultset<T, Strict> execute(
+ std::initializer_list<std::pair<string_view, param_ref>> params,
+ system::error_code & ec,
+ error_info & ei) &&; // <2>
+ template<typename T, bool Strict = false>
+ static_resultset<T, Strict> execute(std::initializer_list<std::pair<string_view, param_ref>> params) &&; // <2>
+
+
+ template <typename ArgRange = std::initializer_list<param_ref>>
+ resultset execute(
+ ArgRange && params,
+ system::error_code& ec,
+ error_info& info) &; // <1>
+
+
+ template <typename ArgRange = std::initializer_list<param_ref>>
+ resultset execute(ArgRange && params) &; // <1>
+
+
+ resultset execute(
+ std::initializer_list<std::pair<string_view, param_ref>> params,
+ system::error_code& ec,
+ error_info& info) &; // <2>
+
+ resultset execute(std::initializer_list<std::pair<string_view, param_ref>> params) &; // <2>
+
+ template<typename T, bool Strict = false, typename ArgRange = std::initializer_list<param_ref>>
+ static_resultset<T, Strict> execute(
+ ArgRange && params,
+ system::error_code & ec,
+ error_info & ei) &; // <1>
+
+ template<typename T, bool Strict = false, typename ArgRange = std::initializer_list<param_ref>>
+ static_resultset<T, Strict> execute(ArgRange && params) &; // <1>
+
+ template<typename T, bool Strict = false>
+ static_resultset<T, Strict> execute(
+ std::initializer_list<std::pair<string_view, param_ref>> params,
+ system::error_code & ec,
+ error_info & ei) &; // <2>
+ template<typename T, bool Strict = false>
+ static_resultset<T, Strict> execute(std::initializer_list<std::pair<string_view, param_ref>> params) &; // <2>
+
+
+
+ // Returns the sql used to construct the prepared statement.
+ stringe_view sql();
+
+ // Returns the expanded sql used to construct the prepared statement. Requires sqlite 3.14
+ stringe_view expanded_sql();
+
+ // Returns the expanded sql used to construct the prepared statement. requiers sqlite to be compiles with SQLITE_ENABLE_NORMALIZE.
+ stringe_view normalized_sql();
+
+ // Returns the declared type of the column
+ string_view declared_type(int id) const;
+};
+----
+<1> Executes a query with positional arguments
+<2> Executes a query with named arguments (from a map-like object)
+
+
+
+
+
+WARNING: The `&&` overloads transfer ownership to the resultset, while the `&` keep them in the statement.
+That is, this is UB:
+[source,cpp]
+----
+resultset get_users(sqlite::connection & conn)
+{
+ auto s = conn.prepare("SELECT * from users where name = ?");
+ return s.execute({"allen"}); // UB, because result set points into s
+}
+
+resultset get_users(sqlite::connection & conn)
+{
+ // correct, because resultset takes ownershipo
+ return conn.prepare("SELECT * from users where name = ?").execute({"allen"});
+}
+----
+
diff --git a/doc/reference/static_resultset.adoc b/doc/reference/static_resultset.adoc
new file mode 100644
index 0000000..0e15e25
--- /dev/null
+++ b/doc/reference/static_resultset.adoc
@@ -0,0 +1,98 @@
+== `sqlite/static_resultset.hpp`
+
+A `static_resultset` represents the results of a query matched to a C++ type
+
+[source,cpp]
+----
+// Representation of a result from a query.
+
+struct resultset
+{
+
+template<typename T, bool Strict >
+struct static_resultset
+{
+ // Returns the current row.
+ T current() const &;
+
+ // Returns the current row.
+ T current(system::error_code & ec, error_info & ei) const &;
+ // Checks if the last row has been reached.
+ bool done() const {return result_.done();}
+
+ // Read the next row. Returns false if there's nothing more to read.
+ bool read_next(system::error_code & ec, error_info & ei);
+ bool read_next();
+
+
+ // The number of columes in the resultset
+ std::size_t column_count() const;
+ // Returns the name of the column idx.
+ string_view column_name(std::size_t idx) const;
+
+ // Returns the name of the source table for column idx.
+ string_view table_name(std::size_t idx) const;
+ // Returns the origin name of the column for column idx.
+ string_view column_origin_name(std::size_t idx) const;
+
+ static_resultset() = default;
+ static_resultset(resultset && result)
+
+ static_resultset(static_resultset<T, false> && rhs);
+
+ /// The input iterator can be used to read every row in a for-loop
+ struct iterator
+ {
+ using value_type = T;
+ using difference_type = int;
+ using reference = T&;
+ using iterator_category = std::forward_iterator_tag;
+
+ iterator();
+ explicit iterator(resultset::iterator itr);
+ bool operator!=(iterator rhs) const;
+
+ value_type &operator*();
+ value_type *operator->();
+
+ iterator& operator++();
+ iterator operator++(int);
+ };
+
+ /// Return an input iterator to the currently unread row
+ iterator begin();
+ /// Sentinel iterator.
+ iterator end();
+
+ // Convert the static_result to a strict version
+ static_resultset<T, true> strict() &&
+ {
+ return {std::move(result_)};
+ }
+};
+----
+
+
+T:: The static type of the query. This must be a tuple or pfr compatible (for C++20) or described.
+Strict:: Disables implicit conversions.
+
+
+.Example
+[source,cpp]
+----
+extern sqlite::connection conn;
+struct user { std::string first_name; std::string last_name; };
+BOOST_DESCRIBE_STRUCT(user, (), (first_name, last_name));
+
+sqlite::resultset rs = conn.query("select first_name, last_name from users;");
+
+do
+{
+user usr = r.current();
+handle_row(u);
+}
+while (rs.read_next()) // read it line by line
+
+----
+
+
diff --git a/doc/reference/string.adoc b/doc/reference/string.adoc
new file mode 100644
index 0000000..21660f9
--- /dev/null
+++ b/doc/reference/string.adoc
@@ -0,0 +1,18 @@
+== `sqlite/string.hpp`
+
+This string header exposes some sqlite utility functions in a C++y way.
+
+
+[source,cpp]
+----
+bool like(cstring_ref lhs, cstring_ref rhs, char escape = '\0'); // <1>
+bool glob(cstring_ref lhs, cstring_ref rhs); // <2>
+int icmp(cstring_ref lhs, cstring_ref rhs); // <3>
+int icmp(string_view lhs, string_view rhs, std::size_t n); // <4>
+----
+<1> uses https://www.sqlite.org/c3ref/strlike.html[strlike]
+<2> uses https://www.sqlite.org/c3ref/strglob.html[strglob]
+<3> used https://www.sqlite.org/c3ref/stricmp.html[stricmp]
+<4> used https://www.sqlite.org/c3ref/stricmp.html[strnicmp]
+
+
diff --git a/doc/reference/transaction.adoc b/doc/reference/transaction.adoc
new file mode 100644
index 0000000..b6bc449
--- /dev/null
+++ b/doc/reference/transaction.adoc
@@ -0,0 +1,104 @@
+== `sqlite/transaction.hpp`
+
+=== `transaction`
+
+A simple transaction guard implementing RAAI for transactions
+
+.Definition
+[source,cpp]
+----
+struct transaction
+{
+ // The mode of the transaction
+ enum behaviour {deferred, immediate, exclusive};
+ // A tag to use, to adopt an already initiated transaction.
+ constexpr static struct adopt_transaction_t {} adopt_transaction{};
+
+ // Create transaction guard on an existing transaction
+ transaction(connection & conn, adopt_transaction_t);
+
+
+ // Create transaction guard and initiate a transaction
+ transaction(connection & conn);
+
+ // Create transaction guard and initiate a transaction with the defined behaviour
+ transaction(connection & conn, behaviour b) ;
+
+ // see https://www.sqlite.org/lang_transaction.html re noexcept
+ // rollback the transaction if not committed.
+ ~transaction() noexcept(SQLITE_VERSION_NUMBER >= 3007011);
+
+
+ // Commit the transaction.
+ void commit();
+ void commit(system::error_code & ec, error_info & ei);
+ // Rollback the transaction explicitly.
+ void rollback();
+ void rollback(system::error_code & ec, error_info & ei);
+
+};
+----
+
+
+
+.Example
+[source,cpp]
+----
+sqlite::connection conn;
+conn.connect("./my-database.db");
+
+sqlite::transaction t{conn};
+conn.prepare("insert into log (text) values ($1)").execute(std::make_tuple("booting up"));
+t.commit();
+----
+
+=== `savepoint`
+
+A simple transaction guard implementing RAAI for savepoints. Savepoints can be used recursively.
+
+.Definition
+[source,cpp]
+----
+
+struct savepoint
+{
+ // A tag to use, to adopt an already initiated transaction.
+ constexpr static transaction::adopt_transaction_t adopt_transaction{};
+
+ // Create savepoint guard on an existing savepoint
+ savepoint(connection & conn, std::string name, transaction::adopt_transaction_t);
+
+ // Create transaction guard and initiate it
+ savepoint(connection & conn, std::string name);
+
+ // rollback to the savepoint if not committed.
+ ~savepoint() noexcept(SQLITE_VERSION_NUMBER >= 3007011);
+
+ // Commit/Release the transaction.
+ void commit();
+ void commit(system::error_code & ec, error_info & ei);
+
+ void release();
+ void release(system::error_code & ec, error_info & ei);
+
+ // Rollback the transaction explicitly.
+ void rollback();
+ void rollback(system::error_code & ec, error_info & ei);
+ // The name of the savepoint.
+
+ const std::string & name() const;
+};
+----
+
+
+.Example
+[source,cpp]
+----
+sqlite::connection conn;
+conn.connect("./my-database.db");
+
+sqlite::savepoint t{conn, "my-savepoint};
+conn.prepare("insert into log (text) values ($1)").execute(std::make_tuple("booting up"));
+t.commit();
+----
+
diff --git a/doc/reference/value.adoc b/doc/reference/value.adoc
new file mode 100644
index 0000000..f5cb3de
--- /dev/null
+++ b/doc/reference/value.adoc
@@ -0,0 +1,85 @@
+== `sqlite/value.hpp`
+
+=== `value_type`
+
+The https://www.sqlite.org/datatype3.html)[type of a value].
+
+[source,cpp]
+----
+enum class value_type
+{
+ // An integral value
+ integer = SQLITE_INTEGER,
+ // A floating piont value
+ floating = SQLITE_FLOAT,
+ // A textual value
+ text = SQLITE_TEXT,
+ // A binary value
+ blob = SQLITE_BLOB,
+ // No value
+ null = SQLITE_NULL,
+};
+
+// Get the name as a string
+const char * value_type_name(value_type vt);
+----
+
+=== `value`
+
+A holder for a sqlite values used for internal APIs.
+
+[source,cpp]
+----
+
+struct value
+{
+ // The value for integers in the database
+ typedef sqlite3_int64 int64 ;
+
+ // The type of the value
+ value_type type() const;
+ // The subtype of the value.
+ int subtype() const;
+
+ // Is the held value null
+ bool is_null() const;
+ // Is the held value is not null
+ explicit operator bool () const;
+ // Returns the value as an `integer`.
+ int64 get_int() const;
+ // Returns the value as an `double`.
+ double get_double() const;
+ // Returns the value as text, i.e. a string_view. Note that this value may be invalidated`.
+ cstring_ref get_text() const;
+ // Returns the value as blob, i.e. raw memory. Note that this value may be invalidated`.
+ blob_view get_blob() const;
+
+ // Best numeric datatype of the value
+ value_type numeric_type() const;
+
+ // True if the column is unchanged in an UPDATE against a virtual table.
+ // requires sqlite 3.32
+ bool nochange() const;
+ // True if value originated from a bound parameter
+ // requires sqlite 3.31
+ bool from_bind() const;
+
+
+ // Construct value from a handle.
+ explicit value(sqlite3_value * value_) noexcept : value_(value_) {}
+
+ // The handle of the value.
+ using handle_type = sqlite3_value *;
+ // Returns the handle.
+ handle_type handle() const;
+ handle_type & handle();
+
+ // Get a value that was passed through the pointer interface.
+ // A value can be set as a pointer by binding/returning a unique_ptr.
+ // Rquires sqlite 3.20
+ template<typename T>
+ T * get_pointer();
+
+};
+----
+
diff --git a/doc/reference/vtable.adoc b/doc/reference/vtable.adoc
new file mode 100644
index 0000000..5063ffc
--- /dev/null
+++ b/doc/reference/vtable.adoc
@@ -0,0 +1,275 @@
+== `sqlite/vtable.hpp`
+
+Please read the <<vtables, virtual tables section>> for a more detailed explanation.
+
+[source,cpp]
+----
+namespace vtab
+{
+
+
+// Helper type to set a function through the xFindFunction callback
+struct function_setter
+{
+ /** Set the function
+ *
+ * The function can either take a single argument, a `span<sqlite::value, N>`
+ * for scalar functions,
+ * or a `context<Args...>` as first, and the span as second for aggegrate functions.
+ *
+ */
+ template<typename Func>
+ void set(Func & func);
+ template<typename ... Args, std::size_t Extent>
+ void set(void(* ptr)(context<Args...>, span<value, Extent>)) noexcept;
+ template<typename T, typename ... Args, std::size_t Extent>
+ void set(T(* ptr)(context<Args...>, span<value, Extent>));
+
+ template<std::size_t Extent>
+ void set(void(* ptr)(span<value, Extent>));
+ template<typename T, std::size_t Extent>
+ void set(T(* ptr)(span<value, Extent>));
+};
+
+
+// requires Sqlite 3.38
+// Utility function that can be used in `xFilter` for the `in` operator. <1>
+
+struct in
+{
+ struct iterator
+ {
+ iterator() = default;
+
+ iterator & operator++();
+ iterator operator++(int);
+
+ const value & operator*() const;
+
+ const value * operator->() const;
+
+ bool operator==(const iterator& other) const;
+ bool operator!=(const iterator& other) const;
+ };
+
+ // Returns a forward iterator to the `in` sequence for an `in` constraint pointing to the begin.
+ iterator begin();
+ // Returns a forward iterator to the `in` sequence for an `in` constraint pointing to the end.
+ iterator end();
+explicit in(sqlite::value out);
+};
+
+
+
+// index info used by the find_index function <2>
+struct index_info
+{
+ // Returns constraints of the index.
+ span<const sqlite3_index_info::sqlite3_index_constraint> constraints() const;
+
+ // Returns ordering of the index.
+ span<const sqlite3_index_info::sqlite3_index_orderby> order_by() const;
+
+ span<sqlite3_index_info::sqlite3_index_constraint_usage> usage();
+
+
+ sqlite3_index_info::sqlite3_index_constraint_usage & usage_of(
+ const sqlite3_index_info::sqlite3_index_constraint & info);
+
+ // Receive the collation for the contrainst of the position. requires 3.22
+ const char * collation(std::size_t idx) const;
+
+ int on_conflict() const;
+
+ // Returns true if the constraint is distinct. requires sqlite 3.38
+ bool distinct() const;
+
+ // Requires sqlite 3.38
+ value * rhs_value(std::size_t idx) const;
+
+ void set_already_ordered();
+ void set_estimated_cost(double cost);
+ // requires sqlite 3.8.2
+ void set_estimated_rows(sqlite3_int64 rows);
+ // requires sqlite 3.9
+ void set_index_scan_flags(int flags);
+ // requires sqlite 3.10
+ std::bitset<64u> columns_used();
+
+ void set_index(int value);
+ void set_index_string(char * str, bool take_ownership = true);
+
+ sqlite3_index_info * info() const;
+ sqlite3 * db() const;
+};
+
+
+struct module_config
+{
+ // Can be used to set SQLITE_VTAB_INNOCUOUS. Requires sqlite 3.31
+ void set_innocuous();
+ // Can be used to set SQLITE_VTAB_DIRECTONLY. Requires sqlite 3.31
+ void set_directonly() {sqlite3_vtab_config(db_, SQLITE_VTAB_DIRECTONLY);}
+
+
+ // Can be used to set SQLITE_VTAB_CONSTRAINT_SUPPORT
+ void set_constraint_support(bool enabled = false);
+};
+
+template<typename Table>
+struct module
+{
+ using table_type = Table;
+
+ // Creates the instance
+ // The instance_type gets used & managed by value, OR a pointer to a class that inherits sqlite3_vtab.
+ // instance_type must have a member `declaration` that returns a `const char *` for the declaration.
+ virtual result<table_type> create(sqlite::connection db, int argc, const char * const argv[]) = 0;
+
+ // Create a table
+ // The table_type gets used & managed by value, OR a pointer to a class that inherits sqlite3_vtab.
+ // table_type must have a member `declaration` that returns a `const char *` for the declaration.
+ virtual result<table_type> connect(sqlite::connection db, int argc, const char * const argv[]) = 0;
+};
+
+template<typename Table>
+struct eponymous_module
+{
+ using table_type = Table;
+
+ // Creates the instance
+ // The instance_type gets used & managed by value, OR a pointer to a class that inherits sqlite3_vtab.
+ // instance_type must have a member `declaration` that returns a `const char *` for the declaration.
+ virtual result<table_type> connect(sqlite::connection db, int argc, const char * const argv[]) = 0;
+
+ eponymous_module(bool eponymous_only = false);
+
+ bool eponymous_only() const;'
+ protected:
+ bool eponymous_only_{false};
+
+};
+
+
+// The basis for vtable
+template<typename Cursor>
+struct table : protected sqlite3_vtab
+{
+ using cursor_type = Cursor;
+
+ virtual result<void> config(module_config &);
+
+ // The Table declaration to be used with sqlite3_declare_vtab
+ virtual const char *declaration() = 0;
+
+ // Destroy the storage = this function needs to be present for non eponymous tables
+ virtual result<void> destroy();
+
+ // Tell sqlite how to communicate with the table.
+ // Optional, this library will fill in a default function that leaves comparisons to sqlite.
+ virtual result<void> best_index(index_info & /*info*/);
+
+ // Start a search on the table.
+ // The cursor_type gets used & managed by value, OR a pointer to a class that inherits sqlite3_vtab_cursor.
+ virtual result<cursor_type> open() = 0;
+
+ // Get the connection of the vtable
+ sqlite::connection connection() const;
+
+ table(const sqlite::connection & conn);
+};
+
+
+// Cursor needs the following member.
+template<typename ColumnType = void>
+struct cursor : protected sqlite3_vtab_cursor
+{
+ using column_type = ColumnType;
+
+ // Apply a filter to the cursor. Required when best_index is implemented.
+ virtual result<void> filter(
+ int /*index*/, const char * /*index_data*/,
+ boost::span<sqlite::value> /*values*/)
+ {
+ return {system::in_place_error, SQLITE_OK};
+ }
+
+ // Returns the next row.
+ virtual result<void> next() = 0;
+
+ // Check if the cursor is and the end
+ virtual bool eof() = 0;
+
+ // Returns the result of a value. It will use the set_result functionality to create a an sqlite function. <3>
+ virtual result<column_type> column(int idx, bool no_change) = 0;
+ // Returns the id of the current row
+ virtual result<sqlite3_int64> row_id() = 0;
+
+ // Get the table the cursor is pointing to.
+ vtab::table<cursor> & table();
+ const vtab::table<cursor> & table() const;
+};
+
+
+// Group of functions for modifications. The table must inherit this to be modifiable.
+struct modifiable
+{
+ virtual result<void> delete_(sqlite::value key) = 0;
+ // Insert a new row
+ virtual result<sqlite_int64> insert(sqlite::value key, span<sqlite::value> values, int on_conflict) = 0;
+ // Update the row
+ virtual result<sqlite_int64> update(sqlite::value old_key, sqlite::value new_key, span<sqlite::value> values, int on_conflict) = 0;
+};
+
+// Group of functions to support transactions. The table must inherit this to support transactions.
+struct transaction
+{
+ // Begin a tranasction
+ virtual result<void> begin() = 0;
+ // synchronize the state
+ virtual result<void> sync() = 0;
+ // commit the transaction
+ virtual result<void> commit() = 0;
+ // rollback the transaction
+ virtual result<void> rollback() = 0;
+};
+
+// Base class to enable function overriding See `xFindFunction`.
+struct overload_functions
+{
+ virtual result<void> find_function(
+ function_setter fs,
+ int arg, const char * name) = 0; // <4>
+};
+
+// Support for recursive transactions. Requires sqlite 3.7.7
+struct recursive_transaction
+{
+ // Save the current state with to `i`
+ virtual result<void> savepoint(int i) = 0;
+ // Release all saves states down to `i`
+ virtual result<void> release(int i) = 0;
+ // Roll the transaction back to `i`.
+ virtual result<void> rollback_to(int i) = 0;
+};
+
+/** Register a vtable <5>
+ Returns a reference to the module as stored in the database. It's lifetime is managed by the database.
+*/
+template<typename T>
+auto create_module(connection & conn,
+ cstring_ref name,
+ T && module,
+ system::error_code & ec,
+ error_info & ei) -> typename std::decay<T>::type &;
+template<typename T>
+auto create_module(connection & conn,
+ const char * name,
+ T && module) -> typename std::decay<T>::type &;
+----
+<1> See https://www.sqlite.org/capi3ref.html#sqlite3_vtab_in_first[vtab_in_first]
+<2> See https://www.sqlite.org/vtab.html#xbestindex[best_index]
+<3> See https://www.sqlite.org/c3ref/vtab_nochange.html[vtab_no_change]
+<4> See https://www.sqlite.org/vtab.html#xfindfunction[find_function]
+<5> See https://www.sqlite.org/vtab.html[vtab]
+