Skip to content
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

Closed
wants to merge 52 commits into from
Closed
Show file tree
Hide file tree
Changes from 45 commits
Commits
Show all changes
52 commits
Select commit Hold shift + click to select a range
92fa703
add support for sqlite loadable extensions
jrandall Jun 15, 2019
5c97c48
install rustfmt in travis ci
jrandall Jun 15, 2019
4caff14
add rustfmt to appveyor install
jrandall Jun 15, 2019
b21aed2
fix reference to link_lib in vcpkg build
jrandall Jun 16, 2019
0bf1e74
Merge remote-tracking branch 'upstream/master' into pr/loadable-exten…
gwenn Feb 9, 2020
955521f
Remove old bindgens
gwenn Feb 9, 2020
26c9193
Remove some more old bindgens
gwenn Feb 11, 2020
e1fffce
Remove unused `api_routines_stub` feature
gwenn Feb 11, 2020
d4b710a
Remove unused `vtab_v3` feature
gwenn Feb 11, 2020
2b3fd57
Merge remote-tracking branch 'upstream/master' into pr/loadable-exten…
gwenn Feb 11, 2020
168821a
Revert changes on old bindgens
gwenn Feb 11, 2020
2c6b6ac
Ignore PATH change on Windows
gwenn Feb 11, 2020
68bea40
Remove copyright header from build script
gwenn Feb 15, 2020
325bfb6
Generate all three bindgen files
gwenn Feb 15, 2020
2b170f0
Generate new bindgen files for bundled version
gwenn Feb 15, 2020
3494e67
Remove generate-bindgen-bindings script
gwenn Feb 15, 2020
7dd7204
Upgrade syn / quote
gwenn Feb 15, 2020
1e19268
Fix warning after wrong merge
gwenn Feb 15, 2020
0b042d0
Run rustfmt manually only while regenerating bindgen files
gwenn Feb 15, 2020
9be9358
Fix warnings in build script
gwenn Feb 15, 2020
5e20e5d
Remove code specific to SQLITE_DETERMINISTIC
gwenn Feb 15, 2020
e4b669c
Fix build_loadable_extension conditional compilation
gwenn Feb 15, 2020
df9a1b1
Remove non_threadsafe feature
gwenn Feb 15, 2020
14ef2d1
Make loadable_extension compatible with bundled* features
gwenn Feb 16, 2020
347c9ff
Fix clippy warnings
gwenn Feb 16, 2020
112b061
Fix compilation error with loadable_extension feature
gwenn Feb 16, 2020
5181cca
Revert output mutability
gwenn Feb 16, 2020
ffbf6b5
Fix warnings
gwenn Feb 16, 2020
0f6ad74
Check loadable_extension build
gwenn Feb 16, 2020
1e211b3
Merge remote-tracking branch 'upstream/master' into pr/loadable-exten…
gwenn Feb 22, 2020
39ac443
eliminate -ext-embed versions of bindgen-bindings
jrandall Feb 22, 2020
be120ef
Merge pull request #2 from Genomicsplc/pr/loadable-extensions
gwenn Feb 28, 2020
121fdba
Merge remote-tracking branch 'upstream/master' into pr/loadable-exten…
gwenn Mar 1, 2020
d52a920
Fix bindgen_bundled_version-ext.rs
gwenn Mar 8, 2020
db04c93
Add comments
gwenn Mar 8, 2020
f3b58e1
`config_log` cannot be used with `loadable_extension`
gwenn Mar 8, 2020
643c0f6
Introduce `to_sqlite_error`
gwenn Mar 8, 2020
a252561
Add `dummy-extension` module
gwenn Mar 8, 2020
bceef65
Fix dummy-extension module
gwenn Mar 15, 2020
03cb901
Document and export check macro
gwenn Mar 15, 2020
84bae86
Merge remote-tracking branch 'upstream/master' into pr/loadable-exten…
gwenn Mar 15, 2020
ad842a3
Try to fix CI build
gwenn Mar 15, 2020
f1ae27c
Fix dummy-extension
gwenn Mar 15, 2020
66de561
Merge remote-tracking branch 'upstream/master' into pr/loadable-exten…
gwenn Apr 1, 2020
cf658af
Merge remote-tracking branch 'upstream/master' into pr/loadable-exten…
gwenn Apr 5, 2020
cb9e702
Merge remote-tracking branch 'upstream/master' into pr/loadable-exten…
gwenn Jun 13, 2020
bbbc76a
Fix build error
gwenn Jun 13, 2020
61ee112
Fix bindgen ext files.
gwenn Jun 13, 2020
a20039b
Export check macro
gwenn Jun 13, 2020
9b93d38
Fix to_sqlite_error doc
gwenn Jun 13, 2020
3770778
Fix dummy extension
gwenn Jun 13, 2020
944ad5e
Fix sqlite3_api_routines size
gwenn Jun 13, 2020
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
4 changes: 2 additions & 2 deletions .github/workflows/main.yml
Expand Up @@ -33,8 +33,8 @@ jobs:
toolchain: stable
override: true
- run: cargo build --features bundled --workspace --all-targets
- run: cargo test --features bundled --workspace --all-targets
- run: cargo test --features bundled --workspace --doc
- run: cargo test --features bundled --workspace --all-targets --exclude dummy-extension
- run: cargo test --features bundled --workspace --doc --exclude dummy-extension
- name: Static build
if: matrix.platform.os == 'windows-latest'
shell: cmd
Expand Down
1 change: 1 addition & 0 deletions .travis.yml
Expand Up @@ -27,6 +27,7 @@ script:
- cargo build --features bundled
- cargo build --features sqlcipher
- cargo build --features "bundled sqlcipher"
- cargo build --features "loadable_extension backup blob collation functions limits hooks unlock_notify vtab window bundled"
- cargo test
- cargo test --features "backup blob extra_check"
- cargo test --features "collation functions"
Expand Down
17 changes: 9 additions & 8 deletions Cargo.toml
Expand Up @@ -20,30 +20,31 @@ maintenance = { status = "actively-developed" }
name = "rusqlite"

[workspace]
members = ["libsqlite3-sys"]
members = ["libsqlite3-sys", "dummy-extension"]

[features]
load_extension = []
# hot-backup interface: 3.6.11 (2009-02-18)
backup = ["libsqlite3-sys/min_sqlite_version_3_6_23"]
backup = ["libsqlite3-sys/min_sqlite_version_3_7_16"]
# sqlite3_blob_reopen: 3.7.4
blob = ["libsqlite3-sys/min_sqlite_version_3_7_7"]
blob = ["libsqlite3-sys/min_sqlite_version_3_7_16"]
collation = []
# sqlite3_create_function_v2: 3.7.3 (2010-10-08)
functions = ["libsqlite3-sys/min_sqlite_version_3_7_7"]
functions = ["libsqlite3-sys/min_sqlite_version_3_7_16"]
# sqlite3_log: 3.6.23 (2010-03-09)
trace = ["libsqlite3-sys/min_sqlite_version_3_6_23"]
trace = ["libsqlite3-sys/min_sqlite_version_3_7_16"]
bundled = ["libsqlite3-sys/bundled", "modern_sqlite"]
buildtime_bindgen = ["libsqlite3-sys/buildtime_bindgen"]
loadable_extension = ["libsqlite3-sys/loadable_extension"]
loadable_extension_embedded = ["libsqlite3-sys/loadable_extension_embedded"]
limits = []
hooks = []
i128_blob = ["byteorder"]
# when `sqlcipher` is used, `bundled` and `loadable_extension` are ignored
sqlcipher = ["libsqlite3-sys/sqlcipher"]
unlock_notify = ["libsqlite3-sys/unlock_notify"]
# xSavepoint, xRelease and xRollbackTo: 3.7.7 (2011-06-23)
vtab = ["libsqlite3-sys/min_sqlite_version_3_7_7", "lazy_static"]
# xShadowName: 3.26.0
vtab_v3 = ["vtab"]
vtab = ["libsqlite3-sys/min_sqlite_version_3_7_16", "lazy_static"]
csvtab = ["csv", "vtab"]
# pointer passing interfaces: 3.20.0
array = ["vtab"]
Expand Down
1 change: 1 addition & 0 deletions LICENSE
@@ -1,4 +1,5 @@
Copyright (c) 2014 John Gallagher <johnkgallagher@gmail.com>
Copyright (c) 2019 Genomics plc <info@genomicsplc.com>
Copy link
Member

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.


Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
Expand Down
3 changes: 1 addition & 2 deletions README.md
Expand Up @@ -152,8 +152,7 @@ minimum SQLite version that supports your chosen features. If you are using
pregenerated bindings are chosen:

* `min_sqlite_version_3_6_8` - SQLite 3.6.8 bindings (this is the default)
* `min_sqlite_version_3_6_23` - SQLite 3.6.23 bindings
* `min_sqlite_version_3_7_7` - SQLite 3.7.7 bindings
* `min_sqlite_version_3_7_16` - SQLite 3.7.16 bindings

If you use the `bundled` feature, you will get pregenerated bindings for the
bundled version of SQLite. If you need other specific pregenerated binding
Expand Down
21 changes: 21 additions & 0 deletions dummy-extension/Cargo.toml
@@ -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"
105 changes: 105 additions & 0 deletions dummy-extension/src/lib.rs
@@ -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)]
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This probably should be unsafe fn though. It both writes to a static mut without synchronization and dereferences the raw pointers passed in as arguments.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

#[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)
}
8 changes: 6 additions & 2 deletions libsqlite3-sys/Cargo.toml
Expand Up @@ -14,12 +14,14 @@ categories = ["external-ffi-bindings"]
[features]
default = ["min_sqlite_version_3_6_8"]
bundled = ["cc", "bundled_bindings"]
# allows a dependency to use `bundled` only on windows
bundled-windows = ["cc", "bundled_bindings"]
buildtime_bindgen = ["bindgen", "pkg-config", "vcpkg"]
loadable_extension = ["syn", "quote"]
loadable_extension_embedded = ["loadable_extension"]
# when `sqlcipher` is used, `bundled` and `loadable_extension` are ignored
sqlcipher = []
min_sqlite_version_3_6_8 = ["pkg-config", "vcpkg"]
min_sqlite_version_3_6_23 = ["pkg-config", "vcpkg"]
min_sqlite_version_3_7_7 = ["pkg-config", "vcpkg"]
min_sqlite_version_3_7_16 = ["pkg-config", "vcpkg"]
# Bundle only the bindings file. Note that this does nothing if
# `buildtime_bindgen` is enabled.
Expand All @@ -36,6 +38,8 @@ in_gecko = []
bindgen = { version = "0.53", optional = true, default-features = false, features = ["runtime"] }
pkg-config = { version = "0.3", optional = true }
cc = { version = "1.0", optional = true }
syn = { version = "1.0", features = ["extra-traits", "full", "printing"], optional = true }
quote = { version = "1.0", optional = true }

[target.'cfg(target_env = "msvc")'.build-dependencies]
vcpkg = { version = "0.2", optional = true }
21 changes: 21 additions & 0 deletions libsqlite3-sys/bindgen-bindings/README.md
@@ -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)