New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Support for sqlite vtables as loadable extensions #631
Changes from 45 commits
92fa703
5c97c48
4caff14
b21aed2
0bf1e74
955521f
26c9193
e1fffce
d4b710a
2b3fd57
168821a
2c6b6ac
68bea40
325bfb6
2b170f0
3494e67
7dd7204
1e19268
0b042d0
9be9358
5e20e5d
e4b669c
df9a1b1
14ef2d1
347c9ff
112b061
5181cca
ffbf6b5
0f6ad74
1e211b3
39ac443
be120ef
121fdba
d52a920
db04c93
f3b58e1
643c0f6
a252561
bceef65
03cb901
84bae86
ad842a3
f1ae27c
66de561
cf658af
cb9e702
bbbc76a
61ee112
a20039b
9b93d38
3770778
944ad5e
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
[package] | ||
name = "dummy-extension" | ||
version = "0.0.1" | ||
authors = ["John Gallagher <jgallagher@bignerdranch.com>"] | ||
edition = "2018" | ||
repository = "https://github.com/jgallagher/rusqlite" | ||
description = "Dummy extension" | ||
license = "MIT" | ||
keywords = ["sqlite", "extension"] | ||
|
||
[lib] | ||
crate-type = ["cdylib"] | ||
|
||
[dependencies] | ||
lazy_static = "1.0" | ||
|
||
[dependencies.rusqlite] | ||
path = ".." | ||
default-features = false | ||
features = ["loadable_extension", "vtab"] | ||
version = "0.21.0" |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,105 @@ | ||
use std::os::raw::{c_char, c_int}; | ||
|
||
use rusqlite::ffi; | ||
use rusqlite::vtab::{ | ||
eponymous_only_module, sqlite3_vtab, sqlite3_vtab_cursor, Context, IndexInfo, Module, VTab, | ||
VTabConnection, VTabCursor, Values, | ||
}; | ||
use rusqlite::{to_sqlite_error, Connection, Result}; | ||
|
||
#[allow(clippy::not_unsafe_ptr_arg_deref)] | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This probably should be There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. discussion moved to https://github.com/rusqlite/rusqlite/pull/910/files#r765317101 |
||
#[no_mangle] | ||
pub extern "C" fn sqlite3_extension_init( | ||
db: *mut ffi::sqlite3, | ||
pz_err_msg: *mut *mut c_char, | ||
p_api: *mut ffi::sqlite3_api_routines, | ||
) -> c_int { | ||
// SQLITE_EXTENSION_INIT2 equivalent | ||
unsafe { | ||
ffi::sqlite3_api = p_api; | ||
} | ||
let res = dummy_init(db); | ||
if let Err(err) = res { | ||
return unsafe { to_sqlite_error(&err, pz_err_msg) }; | ||
} | ||
|
||
ffi::SQLITE_OK | ||
} | ||
|
||
lazy_static::lazy_static! { | ||
static ref DUMMY_MODULE: Module<DummyTab> = eponymous_only_module::<DummyTab>(1); | ||
} | ||
#[repr(C)] | ||
struct DummyTab { | ||
/// Base class. Must be first | ||
base: sqlite3_vtab, | ||
} | ||
|
||
impl VTab for DummyTab { | ||
type Aux = (); | ||
type Cursor = DummyTabCursor; | ||
|
||
fn connect( | ||
_: &mut VTabConnection, | ||
_aux: Option<&()>, | ||
_args: &[&[u8]], | ||
) -> Result<(String, DummyTab)> { | ||
let vtab = DummyTab { | ||
base: sqlite3_vtab::default(), | ||
}; | ||
Ok(("CREATE TABLE x(value)".to_owned(), vtab)) | ||
} | ||
|
||
fn best_index(&self, info: &mut IndexInfo) -> Result<()> { | ||
info.set_estimated_cost(1.); | ||
Ok(()) | ||
} | ||
|
||
fn open(&self) -> Result<DummyTabCursor> { | ||
Ok(DummyTabCursor::default()) | ||
} | ||
} | ||
|
||
#[derive(Default)] | ||
#[repr(C)] | ||
struct DummyTabCursor { | ||
/// Base class. Must be first | ||
base: sqlite3_vtab_cursor, | ||
/// The rowid | ||
row_id: i64, | ||
} | ||
|
||
impl VTabCursor for DummyTabCursor { | ||
fn filter( | ||
&mut self, | ||
_idx_num: c_int, | ||
_idx_str: Option<&str>, | ||
_args: &Values<'_>, | ||
) -> Result<()> { | ||
self.row_id = 1; | ||
Ok(()) | ||
} | ||
|
||
fn next(&mut self) -> Result<()> { | ||
self.row_id += 1; | ||
Ok(()) | ||
} | ||
|
||
fn eof(&self) -> bool { | ||
self.row_id > 1 | ||
} | ||
|
||
fn column(&self, ctx: &mut Context, _: c_int) -> Result<()> { | ||
ctx.set_result(&self.row_id) | ||
} | ||
|
||
fn rowid(&self) -> Result<i64> { | ||
Ok(self.row_id) | ||
} | ||
} | ||
|
||
fn dummy_init(db: *mut ffi::sqlite3) -> Result<()> { | ||
let conn = unsafe { Connection::from_handle(db)? }; | ||
|
||
conn.create_module::<DummyTab>("dummy", &DUMMY_MODULE, None) | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
Pre-built sqlite bindings | ||
========================= | ||
|
||
This directory contains pre built (by rust-bindgen) bindings for various sqlite versions. | ||
|
||
The general recipe for doing this is: | ||
1. Download sqlite amalgamation sources for the desired version (see links below) | ||
2. Expand the zip archive into a temporary directory | ||
3. Set environment variables `SQLITE3_LIB_DIR` and `SQLITE3_INCLUDE_DIR` to the location of the resulting source directory | ||
4. Build libsqlite3-sys with the feature `buildtime_bindgen` (e.g. `cargo build --features "buildtime_bindgen" -p libsqlite3-sys`) | ||
5. Copy `bindgen.rs` from within the `target` directory at the top level of the rusqlite workspace to an appropriate file in this directory (it will be found under `target/debug/build/libsqlite3-sys-*/out/bindgen.rs`) | ||
|
||
Repeat the above process for each desired version, and also re-run each build using `--features "buildtime_bindgen,loadable_extension"` to generate the `-ext.h` versions to support sqlite3 loadable extensions. | ||
|
||
sqlite3 amalgamation source links | ||
--------------------------------- | ||
The location of the amalgamation sources used to build these are: | ||
- [3.7.16](https://sqlite.org/2013/sqlite-amalgamation-3071600.zip) | ||
- [3.6.8](https://sqlite.org/sqlite-amalgamation-3_6_8.zip) | ||
|
||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We should consider just making this
Copyright (c) 2014-2020 Rusqlite contributors
or something. Since you haven't been requesting contributors assign copyright (which would be a bit of a pain) they retain it by default, so this would be more accurate anyway.