Merge pull request #613 from thomcc/modern_sqlite

Separate the `modern_sqlite` and `bundled` features.
This commit is contained in:
gwenn 2020-01-14 20:40:39 +01:00 committed by GitHub
commit ea7f0da6ae
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 53 additions and 38 deletions

View File

@ -33,7 +33,7 @@ collation = []
functions = ["libsqlite3-sys/min_sqlite_version_3_7_7"]
# sqlite3_log: 3.6.23 (2010-03-09)
trace = ["libsqlite3-sys/min_sqlite_version_3_6_23"]
bundled = ["libsqlite3-sys/bundled"]
bundled = ["libsqlite3-sys/bundled", "modern_sqlite"]
buildtime_bindgen = ["libsqlite3-sys/buildtime_bindgen"]
limits = []
hooks = []
@ -55,6 +55,7 @@ window = ["functions"]
series = ["vtab"]
# check for invalid query.
extra_check = []
modern_sqlite = ["libsqlite3-sys/bundled_bindings"]
[dependencies]
time = "0.1.0"
@ -93,7 +94,7 @@ name = "deny_single_threaded_sqlite_config"
name = "vtab"
[package.metadata.docs.rs]
features = [ "backup", "blob", "chrono", "collation", "functions", "limits", "load_extension", "serde_json", "trace", "url", "vtab", "window" ]
features = [ "backup", "blob", "chrono", "collation", "functions", "limits", "load_extension", "serde_json", "trace", "url", "vtab", "window", "modern_sqlite" ]
all-features = false
no-default-features = true
default-target = "x86_64-unknown-linux-gnu"

View File

@ -165,6 +165,12 @@ bundled version of SQLite. If you need other specific pregenerated binding
versions, please file an issue. If you want to run `bindgen` at buildtime to
produce your own bindings, use the `buildtime_bindgen` Cargo feature.
If you enable the `modern_sqlite` feature, we'll use the bindings we would have
included with the bundled build. You generally should have `buildtime_bindgen`
enabled if you turn this on, as otherwise you'll need to keep the version of
SQLite you link with in sync with what rusqlite would have bundled, (usually the
most recent release of sqlite). Failing to do this will cause a runtime error.
## Author
John Gallagher, johnkgallagher@gmail.com

View File

@ -13,14 +13,17 @@ categories = ["external-ffi-bindings"]
[features]
default = ["min_sqlite_version_3_6_8"]
bundled = ["cc"]
bundled-windows = ["cc"]
bundled = ["cc", "bundled_bindings"]
bundled-windows = ["cc", "bundled_bindings"]
buildtime_bindgen = ["bindgen", "pkg-config", "vcpkg"]
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.
bundled_bindings = []
# sqlite3_unlock_notify >= 3.6.12
unlock_notify = []
# 3.13.0

View File

@ -166,18 +166,17 @@ mod build_linked {
pub fn main(_out_dir: &str, out_path: &Path) {
let header = find_sqlite();
if cfg!(any(
feature = "bundled_bindings",
feature = "bundled",
all(windows, feature = "bundled-windows")
)) && !cfg!(feature = "buildtime_bindgen")
{
// We can only get here if `bundled` and `sqlcipher` were both
// specified (and `builtime_bindgen` was not). In order to keep
// `rusqlite` relatively clean we hide the fact that `bundled` can
// be ignored in some cases, and just use the bundled bindings, even
// though the library we found might not match their version.
// Ideally we'd perform a version check here, but doing so is rather
// tricky, since we might not have access to executables (and
// moreover, we might be cross compiling).
// Generally means the `bundled_bindings` feature is enabled
// (there's also an edge case where we get here involving
// sqlcipher). In either case most users are better off with turning
// on buildtime_bindgen instead, but this is still supported as we
// have runtime version checks and there are good reasons to not
// want to run bindgen.
std::fs::copy("sqlite3/bindgen_bundled_version.rs", out_path)
.expect("Could not copy bindings to output directory");
} else {

View File

@ -81,11 +81,11 @@ unsafe fn report_error(ctx: *mut sqlite3_context, err: &Error) {
// an explicit feature check for that, and this doesn't really warrant one.
// We'll use the extended code if we're on the bundled version (since it's
// at least 3.17.0) and the normal constraint error code if not.
#[cfg(feature = "bundled")]
#[cfg(feature = "modern_sqlite")]
fn constraint_error_code() -> i32 {
ffi::SQLITE_CONSTRAINT_FUNCTION
}
#[cfg(not(feature = "bundled"))]
#[cfg(not(feature = "modern_sqlite"))]
fn constraint_error_code() -> i32 {
ffi::SQLITE_CONSTRAINT
}

View File

@ -281,7 +281,7 @@ impl InnerConnection {
unsafe { ffi::sqlite3_get_autocommit(self.db()) != 0 }
}
#[cfg(feature = "bundled")] // 3.8.6
#[cfg(feature = "modern_sqlite")] // 3.8.6
pub fn is_busy(&self) -> bool {
let db = self.db();
unsafe {

View File

@ -295,7 +295,7 @@ pub enum DatabaseName<'a> {
feature = "backup",
feature = "blob",
feature = "session",
feature = "bundled"
feature = "modern_sqlite"
))]
impl DatabaseName<'_> {
fn to_cstring(&self) -> Result<CString> {
@ -750,7 +750,7 @@ impl Connection {
}
/// Determine if all associated prepared statements have been reset.
#[cfg(feature = "bundled")]
#[cfg(feature = "modern_sqlite")] // 3.8.6
pub fn is_busy(&self) -> bool {
self.db.borrow().is_busy()
}
@ -847,7 +847,7 @@ impl InterruptHandle {
}
}
#[cfg(feature = "bundled")] // 3.7.10
#[cfg(feature = "modern_sqlite")] // 3.7.10
unsafe fn db_filename(db: *mut ffi::sqlite3) -> Option<PathBuf> {
let db_name = DatabaseName::Main.to_cstring().unwrap();
let db_filename = ffi::sqlite3_db_filename(db, db_name.as_ptr());
@ -857,7 +857,7 @@ unsafe fn db_filename(db: *mut ffi::sqlite3) -> Option<PathBuf> {
CStr::from_ptr(db_filename).to_str().ok().map(PathBuf::from)
}
}
#[cfg(not(feature = "bundled"))]
#[cfg(not(feature = "modern_sqlite"))]
unsafe fn db_filename(_: *mut ffi::sqlite3) -> Option<PathBuf> {
None
}
@ -1302,7 +1302,7 @@ mod test {
}
#[test]
#[cfg(feature = "bundled")]
#[cfg(feature = "modern_sqlite")]
fn test_is_busy() {
let db = checked_memory_handle();
assert!(!db.is_busy());
@ -1331,11 +1331,11 @@ mod test {
fn test_notnull_constraint_error() {
// extended error codes for constraints were added in SQLite 3.7.16; if we're
// running on our bundled version, we know the extended error code exists.
#[cfg(feature = "bundled")]
#[cfg(feature = "modern_sqlite")]
fn check_extended_code(extended_code: c_int) {
assert_eq!(extended_code, ffi::SQLITE_CONSTRAINT_NOTNULL);
}
#[cfg(not(feature = "bundled"))]
#[cfg(not(feature = "modern_sqlite"))]
fn check_extended_code(_extended_code: c_int) {}
let db = checked_memory_handle();

View File

@ -326,7 +326,7 @@ mod test {
}
#[test]
#[cfg(feature = "bundled")]
#[cfg(feature = "modern_sqlite")]
fn pragma_func_query_value() {
use crate::NO_PARAMS;
@ -379,7 +379,7 @@ mod test {
}
#[test]
#[cfg(feature = "bundled")]
#[cfg(feature = "modern_sqlite")]
fn pragma_func() {
let db = Connection::open_in_memory().unwrap();
let mut table_info = db.prepare("SELECT * FROM pragma_table_info(?)").unwrap();

View File

@ -117,13 +117,13 @@ impl RawStatement {
r
}
#[cfg(feature = "bundled")]
#[cfg(feature = "modern_sqlite")] // 3.7.4
pub fn readonly(&self) -> bool {
unsafe { ffi::sqlite3_stmt_readonly(self.0) != 0 }
}
/// `CStr` must be freed
#[cfg(feature = "bundled")]
#[cfg(feature = "modern_sqlite")] // 3.14.0
pub unsafe fn expanded_sql(&self) -> Option<&CStr> {
let ptr = ffi::sqlite3_expanded_sql(self.0);
if ptr.is_null() {

View File

@ -533,13 +533,13 @@ impl Statement<'_> {
self.conn.decode_result(stmt.finalize())
}
#[cfg(not(feature = "bundled"))]
#[cfg(not(feature = "modern_sqlite"))]
#[inline]
fn check_readonly(&self) -> Result<()> {
Ok(())
}
#[cfg(feature = "bundled")]
#[cfg(feature = "modern_sqlite")]
#[inline]
fn check_readonly(&self) -> Result<()> {
/*if !self.stmt.readonly() { does not work for PRAGMA
@ -548,7 +548,7 @@ impl Statement<'_> {
Ok(())
}
#[cfg(all(feature = "bundled", feature = "extra_check"))]
#[cfg(all(feature = "modern_sqlite", feature = "extra_check"))]
#[inline]
fn check_update(&self) -> Result<()> {
if self.column_count() > 0 || self.stmt.readonly() {
@ -557,7 +557,7 @@ impl Statement<'_> {
Ok(())
}
#[cfg(all(not(feature = "bundled"), feature = "extra_check"))]
#[cfg(all(not(feature = "modern_sqlite"), feature = "extra_check"))]
#[inline]
fn check_update(&self) -> Result<()> {
if self.column_count() > 0 {
@ -574,7 +574,7 @@ impl Statement<'_> {
/// Returns a string containing the SQL text of prepared statement with
/// bound parameters expanded.
#[cfg(feature = "bundled")]
#[cfg(feature = "modern_sqlite")]
pub fn expanded_sql(&self) -> Option<String> {
unsafe {
match self.stmt.expanded_sql() {
@ -1019,7 +1019,7 @@ mod test {
}
#[test]
#[cfg(feature = "bundled")]
#[cfg(feature = "modern_sqlite")]
fn test_expanded_sql() {
let db = Connection::open_in_memory().unwrap();
let stmt = db.prepare("SELECT ?").unwrap();

View File

@ -70,6 +70,14 @@ pub struct Module<T: VTab> {
unsafe impl<T: VTab> Send for Module<T> {}
unsafe impl<T: VTab> Sync for Module<T> {}
// Used as a trailing initializer for sqlite3_module -- this way we avoid having
// the build fail if buildtime_bindgen is on, our bindings have
// `sqlite3_module::xShadowName`, but vtab_v3 wasn't specified.
fn zeroed_module() -> ffi::sqlite3_module {
// This is safe, as bindgen-generated structs are allowed to be zeroed.
unsafe { std::mem::MaybeUninit::zeroed().assume_init() }
}
/// Create a read-only virtual table implementation.
///
/// Step 2 of [Creating New Virtual Table Implementations](https://sqlite.org/vtab.html#creating_new_virtual_table_implementations).
@ -100,8 +108,7 @@ pub fn read_only_module<T: CreateVTab>(version: c_int) -> Module<T> {
xSavepoint: None,
xRelease: None,
xRollbackTo: None,
#[cfg(any(feature = "bundled", feature = "vtab_v3"))]
xShadowName: None,
.. zeroed_module()
};
Module {
base: ffi_module,
@ -140,8 +147,7 @@ pub fn eponymous_only_module<T: VTab>(version: c_int) -> Module<T> {
xSavepoint: None,
xRelease: None,
xRollbackTo: None,
#[cfg(any(feature = "bundled", feature = "vtab_v3"))]
xShadowName: None,
.. zeroed_module()
};
Module {
base: ffi_module,
@ -309,8 +315,8 @@ impl IndexInfo {
}
}
/// Estimated number of rows returned
#[cfg(feature = "bundled")] // SQLite >= 3.8.2
/// Estimated number of rows returned.
#[cfg(feature = "modern_sqlite")] // SQLite >= 3.8.2
pub fn set_estimated_rows(&mut self, estimated_rows: i64) {
unsafe {
(*self.0).estimatedRows = estimated_rows;