mirror of
https://github.com/isar/rusqlite.git
synced 2025-11-03 15:28:54 +08:00
Merge branch 'rusqlite:master' into wasm
This commit is contained in:
@@ -1,8 +1,8 @@
|
||||
[package]
|
||||
name = "libsqlite3-sys"
|
||||
version = "0.26.0"
|
||||
version = "0.27.0"
|
||||
authors = ["The rusqlite developers"]
|
||||
edition = "2018"
|
||||
edition = "2021"
|
||||
repository = "https://github.com/rusqlite/rusqlite"
|
||||
description = "Native bindings to the libsqlite3 library"
|
||||
license = "MIT"
|
||||
@@ -23,6 +23,7 @@ min_sqlite_version_3_14_0 = ["pkg-config", "vcpkg"]
|
||||
# Bundle only the bindings file. Note that this does nothing if
|
||||
# `buildtime_bindgen` is enabled.
|
||||
bundled_bindings = []
|
||||
loadable_extension = ["prettyplease", "quote", "syn"]
|
||||
# sqlite3_unlock_notify >= 3.6.12
|
||||
unlock_notify = []
|
||||
# 3.13.0
|
||||
@@ -44,7 +45,13 @@ winsqlite3 = []
|
||||
openssl-sys = { version = "0.9", optional = true }
|
||||
|
||||
[build-dependencies]
|
||||
bindgen = { version = "0.66", optional = true, default-features = false, features = ["runtime"] }
|
||||
bindgen = { version = "0.69", optional = true, default-features = false, features = ["runtime"] }
|
||||
pkg-config = { version = "0.3.19", optional = true }
|
||||
cc = { version = "1.0", optional = true }
|
||||
vcpkg = { version = "0.2", optional = true }
|
||||
# for loadable_extension:
|
||||
prettyplease = {version = "0.2", optional = true }
|
||||
# like bindgen
|
||||
quote = { version = "1", optional = true, default-features = false }
|
||||
# like bindgen
|
||||
syn = { version = "2.0", optional = true, features = ["full", "extra-traits", "visit-mut"] }
|
||||
|
||||
6956
libsqlite3-sys/bindgen-bindings/bindgen_3.14.0_ext.rs
Normal file
6956
libsqlite3-sys/bindgen-bindings/bindgen_3.14.0_ext.rs
Normal file
File diff suppressed because it is too large
Load Diff
@@ -28,8 +28,12 @@ fn is_compiler(compiler_name: &str) -> bool {
|
||||
|
||||
/// Copy bindgen file from `dir` to `out_path`.
|
||||
fn copy_bindings<T: AsRef<Path>>(dir: &str, bindgen_name: &str, out_path: T) {
|
||||
std::fs::copy(format!("{dir}/{bindgen_name}"), out_path)
|
||||
.expect("Could not copy bindings to output directory");
|
||||
let from = if cfg!(feature = "loadable_extension") {
|
||||
format!("{dir}/{bindgen_name}_ext.rs")
|
||||
} else {
|
||||
format!("{dir}/{bindgen_name}.rs")
|
||||
};
|
||||
std::fs::copy(from, out_path).expect("Could not copy bindings to output directory");
|
||||
}
|
||||
|
||||
fn main() {
|
||||
@@ -38,12 +42,14 @@ fn main() {
|
||||
if cfg!(feature = "in_gecko") {
|
||||
// When inside mozilla-central, we are included into the build with
|
||||
// sqlite3.o directly, so we don't want to provide any linker arguments.
|
||||
copy_bindings("sqlite3", "bindgen_bundled_version.rs", out_path);
|
||||
copy_bindings("sqlite3", "bindgen_bundled_version", out_path);
|
||||
return;
|
||||
}
|
||||
|
||||
println!("cargo:rerun-if-env-changed=LIBSQLITE3_SYS_USE_PKG_CONFIG");
|
||||
if env::var_os("LIBSQLITE3_SYS_USE_PKG_CONFIG").map_or(false, |s| s != "0") {
|
||||
if env::var_os("LIBSQLITE3_SYS_USE_PKG_CONFIG").map_or(false, |s| s != "0")
|
||||
|| cfg!(feature = "loadable_extension")
|
||||
{
|
||||
build_linked::main(&out_dir, &out_path);
|
||||
} else if cfg!(all(
|
||||
feature = "sqlcipher",
|
||||
@@ -106,7 +112,7 @@ mod build_bundled {
|
||||
}
|
||||
#[cfg(not(feature = "buildtime_bindgen"))]
|
||||
{
|
||||
super::copy_bindings(lib_name, "bindgen_bundled_version.rs", out_path);
|
||||
super::copy_bindings(lib_name, "bindgen_bundled_version", out_path);
|
||||
}
|
||||
println!("cargo:rerun-if-changed={lib_name}/sqlite3.c");
|
||||
println!("cargo:rerun-if-changed=sqlite3/wasm32-wasi-vfs.c");
|
||||
@@ -233,11 +239,16 @@ mod build_bundled {
|
||||
if !win_target() {
|
||||
cfg.flag("-DHAVE_LOCALTIME_R");
|
||||
}
|
||||
// Target wasm32-wasi can't compile the default VFS
|
||||
if env::var("TARGET").map_or(false, |v| v == "wasm32-wasi") {
|
||||
cfg.flag("-DSQLITE_OS_OTHER")
|
||||
cfg.flag("-USQLITE_THREADSAFE")
|
||||
.flag("-DSQLITE_THREADSAFE=0")
|
||||
// https://github.com/rust-lang/rust/issues/74393
|
||||
.flag("-DLONGDOUBLE_TYPE=double");
|
||||
.flag("-DLONGDOUBLE_TYPE=double")
|
||||
.flag("-D_WASI_EMULATED_MMAN")
|
||||
.flag("-D_WASI_EMULATED_GETPID")
|
||||
.flag("-D_WASI_EMULATED_SIGNAL")
|
||||
.flag("-D_WASI_EMULATED_PROCESS_CLOCKS");
|
||||
|
||||
if cfg!(feature = "wasm32-wasi-vfs") {
|
||||
cfg.file("sqlite3/wasm32-wasi-vfs.c");
|
||||
}
|
||||
@@ -363,16 +374,30 @@ impl From<HeaderLocation> for String {
|
||||
HeaderLocation::FromEnvironment => {
|
||||
let prefix = env_prefix();
|
||||
let mut header = env::var(format!("{prefix}_INCLUDE_DIR")).unwrap_or_else(|_| {
|
||||
panic!(
|
||||
"{}_INCLUDE_DIR must be set if {}_LIB_DIR is set",
|
||||
prefix, prefix
|
||||
)
|
||||
panic!("{prefix}_INCLUDE_DIR must be set if {prefix}_LIB_DIR is set")
|
||||
});
|
||||
header.push_str(if cfg!(feature = "loadable_extension") {
|
||||
"/sqlite3ext.h"
|
||||
} else {
|
||||
"/sqlite3.h"
|
||||
});
|
||||
header.push_str("/sqlite3.h");
|
||||
header
|
||||
}
|
||||
HeaderLocation::Wrapper => "wrapper.h".into(),
|
||||
HeaderLocation::FromPath(path) => format!("{}/sqlite3.h", path),
|
||||
HeaderLocation::Wrapper => if cfg!(feature = "loadable_extension") {
|
||||
"wrapper_ext.h"
|
||||
} else {
|
||||
"wrapper.h"
|
||||
}
|
||||
.into(),
|
||||
HeaderLocation::FromPath(path) => format!(
|
||||
"{}/{}",
|
||||
path,
|
||||
if cfg!(feature = "loadable_extension") {
|
||||
"sqlite3ext.h"
|
||||
} else {
|
||||
"sqlite3.h"
|
||||
}
|
||||
),
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -399,12 +424,13 @@ mod build_linked {
|
||||
// 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.
|
||||
super::copy_bindings(lib_name(), "bindgen_bundled_version.rs", out_path);
|
||||
super::copy_bindings(lib_name(), "bindgen_bundled_version", out_path);
|
||||
} else {
|
||||
bindings::write_to_out_dir(header, out_path);
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(feature = "loadable_extension"))]
|
||||
fn find_link_mode() -> &'static str {
|
||||
// If the user specifies SQLITE3_STATIC (or SQLCIPHER_STATIC), do static
|
||||
// linking, unless it's explicitly set to 0.
|
||||
@@ -428,9 +454,11 @@ mod build_linked {
|
||||
// `links=` value in our Cargo.toml) to get this value. This might be
|
||||
// useful if you need to ensure whatever crypto library sqlcipher relies
|
||||
// on is available, for example.
|
||||
#[cfg(not(feature = "loadable_extension"))]
|
||||
println!("cargo:link-target={link_lib}");
|
||||
|
||||
if win_target() && cfg!(feature = "winsqlite3") {
|
||||
#[cfg(not(feature = "loadable_extension"))]
|
||||
println!("cargo:rustc-link-lib=dylib={link_lib}");
|
||||
return HeaderLocation::Wrapper;
|
||||
}
|
||||
@@ -440,6 +468,7 @@ mod build_linked {
|
||||
// Try to use pkg-config to determine link commands
|
||||
let pkgconfig_path = Path::new(&dir).join("pkgconfig");
|
||||
env::set_var("PKG_CONFIG_PATH", pkgconfig_path);
|
||||
#[cfg(not(feature = "loadable_extension"))]
|
||||
if pkg_config::Config::new().probe(link_lib).is_err() {
|
||||
// Otherwise just emit the bare minimum link commands.
|
||||
println!("cargo:rustc-link-lib={}={link_lib}", find_link_mode());
|
||||
@@ -467,6 +496,7 @@ mod build_linked {
|
||||
// request and hope that the library exists on the system paths. We used to
|
||||
// output /usr/lib explicitly, but that can introduce other linking problems;
|
||||
// see https://github.com/rusqlite/rusqlite/issues/207.
|
||||
#[cfg(not(feature = "loadable_extension"))]
|
||||
println!("cargo:rustc-link-lib={}={link_lib}", find_link_mode());
|
||||
HeaderLocation::Wrapper
|
||||
}
|
||||
@@ -494,7 +524,7 @@ mod bindings {
|
||||
|
||||
use std::path::Path;
|
||||
|
||||
static PREBUILT_BINDGENS: &[&str] = &["bindgen_3.14.0.rs"];
|
||||
static PREBUILT_BINDGENS: &[&str] = &["bindgen_3.14.0"];
|
||||
|
||||
pub fn write_to_out_dir(_header: HeaderLocation, out_path: &Path) {
|
||||
let name = PREBUILT_BINDGENS[PREBUILT_BINDGENS.len() - 1];
|
||||
@@ -546,10 +576,14 @@ mod bindings {
|
||||
.disable_nested_struct_naming()
|
||||
.trust_clang_mangling(false)
|
||||
.header(header.clone())
|
||||
.parse_callbacks(Box::new(SqliteTypeChooser))
|
||||
.blocklist_function("sqlite3_auto_extension")
|
||||
.raw_line(
|
||||
r#"extern "C" {
|
||||
.parse_callbacks(Box::new(SqliteTypeChooser));
|
||||
if cfg!(feature = "loadable_extension") {
|
||||
bindings = bindings.ignore_functions(); // see generate_functions
|
||||
} else {
|
||||
bindings = bindings
|
||||
.blocklist_function("sqlite3_auto_extension")
|
||||
.raw_line(
|
||||
r#"extern "C" {
|
||||
pub fn sqlite3_auto_extension(
|
||||
xEntryPoint: ::std::option::Option<
|
||||
unsafe extern "C" fn(
|
||||
@@ -560,10 +594,10 @@ mod bindings {
|
||||
>,
|
||||
) -> ::std::os::raw::c_int;
|
||||
}"#,
|
||||
)
|
||||
.blocklist_function("sqlite3_cancel_auto_extension")
|
||||
.raw_line(
|
||||
r#"extern "C" {
|
||||
)
|
||||
.blocklist_function("sqlite3_cancel_auto_extension")
|
||||
.raw_line(
|
||||
r#"extern "C" {
|
||||
pub fn sqlite3_cancel_auto_extension(
|
||||
xEntryPoint: ::std::option::Option<
|
||||
unsafe extern "C" fn(
|
||||
@@ -574,7 +608,8 @@ mod bindings {
|
||||
>,
|
||||
) -> ::std::os::raw::c_int;
|
||||
}"#,
|
||||
);
|
||||
);
|
||||
}
|
||||
|
||||
if cfg!(any(feature = "sqlcipher", feature = "bundled-sqlcipher")) {
|
||||
bindings = bindings.clang_arg("-DSQLITE_HAS_CODEC");
|
||||
@@ -645,11 +680,183 @@ mod bindings {
|
||||
.blocklist_item("__.*");
|
||||
}
|
||||
|
||||
bindings
|
||||
let bindings = bindings
|
||||
.layout_tests(false)
|
||||
.generate()
|
||||
.unwrap_or_else(|_| panic!("could not run bindgen on header {}", header))
|
||||
.unwrap_or_else(|_| panic!("could not run bindgen on header {}", header));
|
||||
|
||||
#[cfg(feature = "loadable_extension")]
|
||||
{
|
||||
let mut output = Vec::new();
|
||||
bindings
|
||||
.write(Box::new(&mut output))
|
||||
.expect("could not write output of bindgen");
|
||||
let mut output = String::from_utf8(output).expect("bindgen output was not UTF-8?!");
|
||||
super::loadable_extension::generate_functions(&mut output);
|
||||
std::fs::write(out_path, output.as_bytes())
|
||||
.unwrap_or_else(|_| panic!("Could not write to {:?}", out_path));
|
||||
}
|
||||
#[cfg(not(feature = "loadable_extension"))]
|
||||
bindings
|
||||
.write_to_file(out_path)
|
||||
.unwrap_or_else(|_| panic!("Could not write to {:?}", out_path));
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(all(feature = "buildtime_bindgen", feature = "loadable_extension"))]
|
||||
mod loadable_extension {
|
||||
/// try to generate similar rust code for all `#define sqlite3_xyz
|
||||
/// sqlite3_api->abc` macros` in sqlite3ext.h
|
||||
pub fn generate_functions(output: &mut String) {
|
||||
// (1) parse sqlite3_api_routines fields from bindgen output
|
||||
let ast: syn::File = syn::parse_str(output).expect("could not parse bindgen output");
|
||||
let sqlite3_api_routines: syn::ItemStruct = ast
|
||||
.items
|
||||
.into_iter()
|
||||
.find_map(|i| {
|
||||
if let syn::Item::Struct(s) = i {
|
||||
if s.ident == "sqlite3_api_routines" {
|
||||
Some(s)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
} else {
|
||||
None
|
||||
}
|
||||
})
|
||||
.expect("could not find sqlite3_api_routines");
|
||||
let sqlite3_api_routines_ident = sqlite3_api_routines.ident;
|
||||
let p_api = quote::format_ident!("p_api");
|
||||
let mut stores = Vec::new();
|
||||
let mut malloc = Vec::new();
|
||||
// (2) `#define sqlite3_xyz sqlite3_api->abc` => `pub unsafe fn
|
||||
// sqlite3_xyz(args) -> ty {...}` for each `abc` field:
|
||||
for field in sqlite3_api_routines.fields {
|
||||
let ident = field.ident.expect("unamed field");
|
||||
let span = ident.span();
|
||||
let name = ident.to_string();
|
||||
if name == "vmprintf" || name == "xvsnprintf" || name == "str_vappendf" {
|
||||
continue; // skip va_list
|
||||
} else if name == "aggregate_count"
|
||||
|| name == "expired"
|
||||
|| name == "global_recover"
|
||||
|| name == "thread_cleanup"
|
||||
|| name == "transfer_bindings"
|
||||
{
|
||||
continue; // omit deprecated
|
||||
}
|
||||
let sqlite3_name = match name.as_ref() {
|
||||
"xthreadsafe" => "sqlite3_threadsafe".to_owned(),
|
||||
"interruptx" => "sqlite3_interrupt".to_owned(),
|
||||
_ => {
|
||||
format!("sqlite3_{name}")
|
||||
}
|
||||
};
|
||||
let ptr_name =
|
||||
syn::Ident::new(format!("__{}", sqlite3_name.to_uppercase()).as_ref(), span);
|
||||
let sqlite3_fn_name = syn::Ident::new(&sqlite3_name, span);
|
||||
let method =
|
||||
extract_method(&field.ty).unwrap_or_else(|| panic!("unexpected type for {name}"));
|
||||
let arg_names: syn::punctuated::Punctuated<&syn::Ident, syn::token::Comma> = method
|
||||
.inputs
|
||||
.iter()
|
||||
.map(|i| &i.name.as_ref().unwrap().0)
|
||||
.collect();
|
||||
let args = &method.inputs;
|
||||
// vtab_config/sqlite3_vtab_config: ok
|
||||
let varargs = &method.variadic;
|
||||
if varargs.is_some() && "db_config" != name && "log" != name && "vtab_config" != name {
|
||||
continue; // skip ...
|
||||
}
|
||||
let ty = &method.output;
|
||||
let tokens = if "db_config" == name {
|
||||
quote::quote! {
|
||||
static #ptr_name: ::std::sync::atomic::AtomicPtr<()> = ::std::sync::atomic::AtomicPtr::new(::std::ptr::null_mut());
|
||||
pub unsafe fn #sqlite3_fn_name(#args arg3: ::std::os::raw::c_int, arg4: *mut ::std::os::raw::c_int) #ty {
|
||||
let ptr = #ptr_name.load(::std::sync::atomic::Ordering::Acquire);
|
||||
assert!(!ptr.is_null(), "SQLite API not initialized");
|
||||
let fun: unsafe extern "C" fn(#args #varargs) #ty = ::std::mem::transmute(ptr);
|
||||
(fun)(#arg_names, arg3, arg4)
|
||||
}
|
||||
}
|
||||
} else if "log" == name {
|
||||
quote::quote! {
|
||||
static #ptr_name: ::std::sync::atomic::AtomicPtr<()> = ::std::sync::atomic::AtomicPtr::new(::std::ptr::null_mut());
|
||||
pub unsafe fn #sqlite3_fn_name(#args arg3: *const ::std::os::raw::c_char) #ty {
|
||||
let ptr = #ptr_name.load(::std::sync::atomic::Ordering::Acquire);
|
||||
assert!(!ptr.is_null(), "SQLite API not initialized");
|
||||
let fun: unsafe extern "C" fn(#args #varargs) #ty = ::std::mem::transmute(ptr);
|
||||
(fun)(#arg_names, arg3)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
quote::quote! {
|
||||
static #ptr_name: ::std::sync::atomic::AtomicPtr<()> = ::std::sync::atomic::AtomicPtr::new(::std::ptr::null_mut());
|
||||
pub unsafe fn #sqlite3_fn_name(#args) #ty {
|
||||
let ptr = #ptr_name.load(::std::sync::atomic::Ordering::Acquire);
|
||||
assert!(!ptr.is_null(), "SQLite API not initialized or SQLite feature omitted");
|
||||
let fun: unsafe extern "C" fn(#args #varargs) #ty = ::std::mem::transmute(ptr);
|
||||
(fun)(#arg_names)
|
||||
}
|
||||
}
|
||||
};
|
||||
output.push_str(&prettyplease::unparse(
|
||||
&syn::parse2(tokens).expect("could not parse quote output"),
|
||||
));
|
||||
output.push('\n');
|
||||
if name == "malloc" {
|
||||
&mut malloc
|
||||
} else {
|
||||
&mut stores
|
||||
}
|
||||
.push(quote::quote! {
|
||||
if let Some(fun) = (*#p_api).#ident {
|
||||
#ptr_name.store(
|
||||
fun as usize as *mut (),
|
||||
::std::sync::atomic::Ordering::Release,
|
||||
);
|
||||
}
|
||||
});
|
||||
}
|
||||
// (3) generate rust code similar to SQLITE_EXTENSION_INIT2 macro
|
||||
let tokens = quote::quote! {
|
||||
/// Like SQLITE_EXTENSION_INIT2 macro
|
||||
pub unsafe fn rusqlite_extension_init2(#p_api: *mut #sqlite3_api_routines_ident) -> ::std::result::Result<(),crate::InitError> {
|
||||
#(#malloc)* // sqlite3_malloc needed by to_sqlite_error
|
||||
if let Some(fun) = (*#p_api).libversion_number {
|
||||
let version = fun();
|
||||
if SQLITE_VERSION_NUMBER > version {
|
||||
return Err(crate::InitError::VersionMismatch{compile_time: SQLITE_VERSION_NUMBER, runtime: version});
|
||||
}
|
||||
} else {
|
||||
return Err(crate::InitError::NullFunctionPointer);
|
||||
}
|
||||
#(#stores)*
|
||||
Ok(())
|
||||
}
|
||||
};
|
||||
output.push_str(&prettyplease::unparse(
|
||||
&syn::parse2(tokens).expect("could not parse quote output"),
|
||||
));
|
||||
output.push('\n');
|
||||
}
|
||||
|
||||
fn extract_method(ty: &syn::Type) -> Option<&syn::TypeBareFn> {
|
||||
match ty {
|
||||
syn::Type::Path(tp) => tp.path.segments.last(),
|
||||
_ => None,
|
||||
}
|
||||
.map(|seg| match &seg.arguments {
|
||||
syn::PathArguments::AngleBracketed(args) => args.args.first(),
|
||||
_ => None,
|
||||
})?
|
||||
.map(|arg| match arg {
|
||||
syn::GenericArgument::Type(t) => Some(t),
|
||||
_ => None,
|
||||
})?
|
||||
.map(|ty| match ty {
|
||||
syn::Type::BareFn(r) => Some(r),
|
||||
_ => None,
|
||||
})?
|
||||
}
|
||||
}
|
||||
|
||||
838
libsqlite3-sys/sqlite3/bindgen_bundled_version.rs
vendored
838
libsqlite3-sys/sqlite3/bindgen_bundled_version.rs
vendored
File diff suppressed because it is too large
Load Diff
8430
libsqlite3-sys/sqlite3/bindgen_bundled_version_ext.rs
vendored
Normal file
8430
libsqlite3-sys/sqlite3/bindgen_bundled_version_ext.rs
vendored
Normal file
File diff suppressed because it is too large
Load Diff
12594
libsqlite3-sys/sqlite3/sqlite3.c
vendored
12594
libsqlite3-sys/sqlite3/sqlite3.c
vendored
File diff suppressed because it is too large
Load Diff
291
libsqlite3-sys/sqlite3/sqlite3.h
vendored
291
libsqlite3-sys/sqlite3/sqlite3.h
vendored
@@ -146,9 +146,9 @@ extern "C" {
|
||||
** [sqlite3_libversion_number()], [sqlite3_sourceid()],
|
||||
** [sqlite_version()] and [sqlite_source_id()].
|
||||
*/
|
||||
#define SQLITE_VERSION "3.42.0"
|
||||
#define SQLITE_VERSION_NUMBER 3042000
|
||||
#define SQLITE_SOURCE_ID "2023-05-16 12:36:15 831d0fb2836b71c9bc51067c49fee4b8f18047814f2ff22d817d25195cf350b0"
|
||||
#define SQLITE_VERSION "3.44.0"
|
||||
#define SQLITE_VERSION_NUMBER 3044000
|
||||
#define SQLITE_SOURCE_ID "2023-11-01 11:23:50 17129ba1ff7f0daf37100ee82d507aef7827cf38de1866e2633096ae6ad81301"
|
||||
|
||||
/*
|
||||
** CAPI3REF: Run-Time Library Version Numbers
|
||||
@@ -528,6 +528,7 @@ SQLITE_API int sqlite3_exec(
|
||||
#define SQLITE_IOERR_ROLLBACK_ATOMIC (SQLITE_IOERR | (31<<8))
|
||||
#define SQLITE_IOERR_DATA (SQLITE_IOERR | (32<<8))
|
||||
#define SQLITE_IOERR_CORRUPTFS (SQLITE_IOERR | (33<<8))
|
||||
#define SQLITE_IOERR_IN_PAGE (SQLITE_IOERR | (34<<8))
|
||||
#define SQLITE_LOCKED_SHAREDCACHE (SQLITE_LOCKED | (1<<8))
|
||||
#define SQLITE_LOCKED_VTAB (SQLITE_LOCKED | (2<<8))
|
||||
#define SQLITE_BUSY_RECOVERY (SQLITE_BUSY | (1<<8))
|
||||
@@ -1190,7 +1191,7 @@ struct sqlite3_io_methods {
|
||||
** by clients within the current process, only within other processes.
|
||||
**
|
||||
** <li>[[SQLITE_FCNTL_CKSM_FILE]]
|
||||
** The [SQLITE_FCNTL_CKSM_FILE] opcode is for use interally by the
|
||||
** The [SQLITE_FCNTL_CKSM_FILE] opcode is for use internally by the
|
||||
** [checksum VFS shim] only.
|
||||
**
|
||||
** <li>[[SQLITE_FCNTL_RESET_CACHE]]
|
||||
@@ -2126,7 +2127,7 @@ struct sqlite3_mem_methods {
|
||||
** is stored in each sorted record and the required column values loaded
|
||||
** from the database as records are returned in sorted order. The default
|
||||
** value for this option is to never use this optimization. Specifying a
|
||||
** negative value for this option restores the default behaviour.
|
||||
** negative value for this option restores the default behavior.
|
||||
** This option is only available if SQLite is compiled with the
|
||||
** [SQLITE_ENABLE_SORTER_REFERENCES] compile-time option.
|
||||
**
|
||||
@@ -2301,7 +2302,7 @@ struct sqlite3_mem_methods {
|
||||
** database handle, SQLite checks if this will mean that there are now no
|
||||
** connections at all to the database. If so, it performs a checkpoint
|
||||
** operation before closing the connection. This option may be used to
|
||||
** override this behaviour. The first parameter passed to this operation
|
||||
** override this behavior. The first parameter passed to this operation
|
||||
** is an integer - positive to disable checkpoints-on-close, or zero (the
|
||||
** default) to enable them, and negative to leave the setting unchanged.
|
||||
** The second parameter is a pointer to an integer
|
||||
@@ -2454,7 +2455,7 @@ struct sqlite3_mem_methods {
|
||||
** the [VACUUM] command will fail with an obscure error when attempting to
|
||||
** process a table with generated columns and a descending index. This is
|
||||
** not considered a bug since SQLite versions 3.3.0 and earlier do not support
|
||||
** either generated columns or decending indexes.
|
||||
** either generated columns or descending indexes.
|
||||
** </dd>
|
||||
**
|
||||
** [[SQLITE_DBCONFIG_STMT_SCANSTATUS]]
|
||||
@@ -2735,6 +2736,7 @@ SQLITE_API sqlite3_int64 sqlite3_total_changes64(sqlite3*);
|
||||
**
|
||||
** ^The [sqlite3_is_interrupted(D)] interface can be used to determine whether
|
||||
** or not an interrupt is currently in effect for [database connection] D.
|
||||
** It returns 1 if an interrupt is currently in effect, or 0 otherwise.
|
||||
*/
|
||||
SQLITE_API void sqlite3_interrupt(sqlite3*);
|
||||
SQLITE_API int sqlite3_is_interrupted(sqlite3*);
|
||||
@@ -3388,8 +3390,10 @@ SQLITE_API SQLITE_DEPRECATED void *sqlite3_profile(sqlite3*,
|
||||
** M argument should be the bitwise OR-ed combination of
|
||||
** zero or more [SQLITE_TRACE] constants.
|
||||
**
|
||||
** ^Each call to either sqlite3_trace() or sqlite3_trace_v2() overrides
|
||||
** (cancels) any prior calls to sqlite3_trace() or sqlite3_trace_v2().
|
||||
** ^Each call to either sqlite3_trace(D,X,P) or sqlite3_trace_v2(D,M,X,P)
|
||||
** overrides (cancels) all prior calls to sqlite3_trace(D,X,P) or
|
||||
** sqlite3_trace_v2(D,M,X,P) for the [database connection] D. Each
|
||||
** database connection may have at most one trace callback.
|
||||
**
|
||||
** ^The X callback is invoked whenever any of the events identified by
|
||||
** mask M occur. ^The integer return value from the callback is currently
|
||||
@@ -3758,7 +3762,7 @@ SQLITE_API int sqlite3_open_v2(
|
||||
** as F) must be one of:
|
||||
** <ul>
|
||||
** <li> A database filename pointer created by the SQLite core and
|
||||
** passed into the xOpen() method of a VFS implemention, or
|
||||
** passed into the xOpen() method of a VFS implementation, or
|
||||
** <li> A filename obtained from [sqlite3_db_filename()], or
|
||||
** <li> A new filename constructed using [sqlite3_create_filename()].
|
||||
** </ul>
|
||||
@@ -3871,7 +3875,7 @@ SQLITE_API sqlite3_file *sqlite3_database_file_object(const char*);
|
||||
/*
|
||||
** CAPI3REF: Create and Destroy VFS Filenames
|
||||
**
|
||||
** These interfces are provided for use by [VFS shim] implementations and
|
||||
** These interfaces are provided for use by [VFS shim] implementations and
|
||||
** are not useful outside of that context.
|
||||
**
|
||||
** The sqlite3_create_filename(D,J,W,N,P) allocates memory to hold a version of
|
||||
@@ -3951,6 +3955,7 @@ SQLITE_API void sqlite3_free_filename(sqlite3_filename);
|
||||
**
|
||||
** ^The sqlite3_errmsg() and sqlite3_errmsg16() return English-language
|
||||
** text that describes the error, as either UTF-8 or UTF-16 respectively.
|
||||
** (See how SQLite handles [invalid UTF] for exceptions to this rule.)
|
||||
** ^(Memory to hold the error message string is managed internally.
|
||||
** The application does not need to worry about freeing the result.
|
||||
** However, the error string might be overwritten or deallocated by
|
||||
@@ -4418,6 +4423,41 @@ SQLITE_API int sqlite3_stmt_readonly(sqlite3_stmt *pStmt);
|
||||
*/
|
||||
SQLITE_API int sqlite3_stmt_isexplain(sqlite3_stmt *pStmt);
|
||||
|
||||
/*
|
||||
** CAPI3REF: Change The EXPLAIN Setting For A Prepared Statement
|
||||
** METHOD: sqlite3_stmt
|
||||
**
|
||||
** The sqlite3_stmt_explain(S,E) interface changes the EXPLAIN
|
||||
** setting for [prepared statement] S. If E is zero, then S becomes
|
||||
** a normal prepared statement. If E is 1, then S behaves as if
|
||||
** its SQL text began with "[EXPLAIN]". If E is 2, then S behaves as if
|
||||
** its SQL text began with "[EXPLAIN QUERY PLAN]".
|
||||
**
|
||||
** Calling sqlite3_stmt_explain(S,E) might cause S to be reprepared.
|
||||
** SQLite tries to avoid a reprepare, but a reprepare might be necessary
|
||||
** on the first transition into EXPLAIN or EXPLAIN QUERY PLAN mode.
|
||||
**
|
||||
** Because of the potential need to reprepare, a call to
|
||||
** sqlite3_stmt_explain(S,E) will fail with SQLITE_ERROR if S cannot be
|
||||
** reprepared because it was created using [sqlite3_prepare()] instead of
|
||||
** the newer [sqlite3_prepare_v2()] or [sqlite3_prepare_v3()] interfaces and
|
||||
** hence has no saved SQL text with which to reprepare.
|
||||
**
|
||||
** Changing the explain setting for a prepared statement does not change
|
||||
** the original SQL text for the statement. Hence, if the SQL text originally
|
||||
** began with EXPLAIN or EXPLAIN QUERY PLAN, but sqlite3_stmt_explain(S,0)
|
||||
** is called to convert the statement into an ordinary statement, the EXPLAIN
|
||||
** or EXPLAIN QUERY PLAN keywords will still appear in the sqlite3_sql(S)
|
||||
** output, even though the statement now acts like a normal SQL statement.
|
||||
**
|
||||
** This routine returns SQLITE_OK if the explain mode is successfully
|
||||
** changed, or an error code if the explain mode could not be changed.
|
||||
** The explain mode cannot be changed while a statement is active.
|
||||
** Hence, it is good practice to call [sqlite3_reset(S)]
|
||||
** immediately prior to calling sqlite3_stmt_explain(S,E).
|
||||
*/
|
||||
SQLITE_API int sqlite3_stmt_explain(sqlite3_stmt *pStmt, int eMode);
|
||||
|
||||
/*
|
||||
** CAPI3REF: Determine If A Prepared Statement Has Been Reset
|
||||
** METHOD: sqlite3_stmt
|
||||
@@ -4581,7 +4621,7 @@ typedef struct sqlite3_context sqlite3_context;
|
||||
** with it may be passed. ^It is called to dispose of the BLOB or string even
|
||||
** if the call to the bind API fails, except the destructor is not called if
|
||||
** the third parameter is a NULL pointer or the fourth parameter is negative.
|
||||
** ^ (2) The special constant, [SQLITE_STATIC], may be passsed to indicate that
|
||||
** ^ (2) The special constant, [SQLITE_STATIC], may be passed to indicate that
|
||||
** the application remains responsible for disposing of the object. ^In this
|
||||
** case, the object and the provided pointer to it must remain valid until
|
||||
** either the prepared statement is finalized or the same SQL parameter is
|
||||
@@ -5260,20 +5300,33 @@ SQLITE_API int sqlite3_finalize(sqlite3_stmt *pStmt);
|
||||
** ^The [sqlite3_reset(S)] interface resets the [prepared statement] S
|
||||
** back to the beginning of its program.
|
||||
**
|
||||
** ^If the most recent call to [sqlite3_step(S)] for the
|
||||
** [prepared statement] S returned [SQLITE_ROW] or [SQLITE_DONE],
|
||||
** or if [sqlite3_step(S)] has never before been called on S,
|
||||
** then [sqlite3_reset(S)] returns [SQLITE_OK].
|
||||
** ^The return code from [sqlite3_reset(S)] indicates whether or not
|
||||
** the previous evaluation of prepared statement S completed successfully.
|
||||
** ^If [sqlite3_step(S)] has never before been called on S or if
|
||||
** [sqlite3_step(S)] has not been called since the previous call
|
||||
** to [sqlite3_reset(S)], then [sqlite3_reset(S)] will return
|
||||
** [SQLITE_OK].
|
||||
**
|
||||
** ^If the most recent call to [sqlite3_step(S)] for the
|
||||
** [prepared statement] S indicated an error, then
|
||||
** [sqlite3_reset(S)] returns an appropriate [error code].
|
||||
** ^The [sqlite3_reset(S)] interface might also return an [error code]
|
||||
** if there were no prior errors but the process of resetting
|
||||
** the prepared statement caused a new error. ^For example, if an
|
||||
** [INSERT] statement with a [RETURNING] clause is only stepped one time,
|
||||
** that one call to [sqlite3_step(S)] might return SQLITE_ROW but
|
||||
** the overall statement might still fail and the [sqlite3_reset(S)] call
|
||||
** might return SQLITE_BUSY if locking constraints prevent the
|
||||
** database change from committing. Therefore, it is important that
|
||||
** applications check the return code from [sqlite3_reset(S)] even if
|
||||
** no prior call to [sqlite3_step(S)] indicated a problem.
|
||||
**
|
||||
** ^The [sqlite3_reset(S)] interface does not change the values
|
||||
** of any [sqlite3_bind_blob|bindings] on the [prepared statement] S.
|
||||
*/
|
||||
SQLITE_API int sqlite3_reset(sqlite3_stmt *pStmt);
|
||||
|
||||
|
||||
/*
|
||||
** CAPI3REF: Create Or Redefine SQL Functions
|
||||
** KEYWORDS: {function creation routines}
|
||||
@@ -5484,7 +5537,7 @@ SQLITE_API int sqlite3_create_window_function(
|
||||
** [application-defined SQL function]
|
||||
** that has side-effects or that could potentially leak sensitive information.
|
||||
** This will prevent attacks in which an application is tricked
|
||||
** into using a database file that has had its schema surreptiously
|
||||
** into using a database file that has had its schema surreptitiously
|
||||
** modified to invoke the application-defined function in ways that are
|
||||
** harmful.
|
||||
** <p>
|
||||
@@ -5828,32 +5881,32 @@ SQLITE_API sqlite3 *sqlite3_context_db_handle(sqlite3_context*);
|
||||
** METHOD: sqlite3_context
|
||||
**
|
||||
** These functions may be used by (non-aggregate) SQL functions to
|
||||
** associate metadata with argument values. If the same value is passed to
|
||||
** multiple invocations of the same SQL function during query execution, under
|
||||
** some circumstances the associated metadata may be preserved. An example
|
||||
** of where this might be useful is in a regular-expression matching
|
||||
** function. The compiled version of the regular expression can be stored as
|
||||
** metadata associated with the pattern string.
|
||||
** associate auxiliary data with argument values. If the same argument
|
||||
** value is passed to multiple invocations of the same SQL function during
|
||||
** query execution, under some circumstances the associated auxiliary data
|
||||
** might be preserved. An example of where this might be useful is in a
|
||||
** regular-expression matching function. The compiled version of the regular
|
||||
** expression can be stored as auxiliary data associated with the pattern string.
|
||||
** Then as long as the pattern string remains the same,
|
||||
** the compiled regular expression can be reused on multiple
|
||||
** invocations of the same function.
|
||||
**
|
||||
** ^The sqlite3_get_auxdata(C,N) interface returns a pointer to the metadata
|
||||
** ^The sqlite3_get_auxdata(C,N) interface returns a pointer to the auxiliary data
|
||||
** associated by the sqlite3_set_auxdata(C,N,P,X) function with the Nth argument
|
||||
** value to the application-defined function. ^N is zero for the left-most
|
||||
** function argument. ^If there is no metadata
|
||||
** function argument. ^If there is no auxiliary data
|
||||
** associated with the function argument, the sqlite3_get_auxdata(C,N) interface
|
||||
** returns a NULL pointer.
|
||||
**
|
||||
** ^The sqlite3_set_auxdata(C,N,P,X) interface saves P as metadata for the N-th
|
||||
** argument of the application-defined function. ^Subsequent
|
||||
** ^The sqlite3_set_auxdata(C,N,P,X) interface saves P as auxiliary data for the
|
||||
** N-th argument of the application-defined function. ^Subsequent
|
||||
** calls to sqlite3_get_auxdata(C,N) return P from the most recent
|
||||
** sqlite3_set_auxdata(C,N,P,X) call if the metadata is still valid or
|
||||
** NULL if the metadata has been discarded.
|
||||
** sqlite3_set_auxdata(C,N,P,X) call if the auxiliary data is still valid or
|
||||
** NULL if the auxiliary data has been discarded.
|
||||
** ^After each call to sqlite3_set_auxdata(C,N,P,X) where X is not NULL,
|
||||
** SQLite will invoke the destructor function X with parameter P exactly
|
||||
** once, when the metadata is discarded.
|
||||
** SQLite is free to discard the metadata at any time, including: <ul>
|
||||
** once, when the auxiliary data is discarded.
|
||||
** SQLite is free to discard the auxiliary data at any time, including: <ul>
|
||||
** <li> ^(when the corresponding function parameter changes)^, or
|
||||
** <li> ^(when [sqlite3_reset()] or [sqlite3_finalize()] is called for the
|
||||
** SQL statement)^, or
|
||||
@@ -5869,7 +5922,7 @@ SQLITE_API sqlite3 *sqlite3_context_db_handle(sqlite3_context*);
|
||||
** function implementation should not make any use of P after
|
||||
** sqlite3_set_auxdata() has been called.
|
||||
**
|
||||
** ^(In practice, metadata is preserved between function calls for
|
||||
** ^(In practice, auxiliary data is preserved between function calls for
|
||||
** function parameters that are compile-time constants, including literal
|
||||
** values and [parameters] and expressions composed from the same.)^
|
||||
**
|
||||
@@ -5879,10 +5932,67 @@ SQLITE_API sqlite3 *sqlite3_context_db_handle(sqlite3_context*);
|
||||
**
|
||||
** These routines must be called from the same thread in which
|
||||
** the SQL function is running.
|
||||
**
|
||||
** See also: [sqlite3_get_clientdata()] and [sqlite3_set_clientdata()].
|
||||
*/
|
||||
SQLITE_API void *sqlite3_get_auxdata(sqlite3_context*, int N);
|
||||
SQLITE_API void sqlite3_set_auxdata(sqlite3_context*, int N, void*, void (*)(void*));
|
||||
|
||||
/*
|
||||
** CAPI3REF: Database Connection Client Data
|
||||
** METHOD: sqlite3
|
||||
**
|
||||
** These functions are used to associate one or more named pointers
|
||||
** with a [database connection].
|
||||
** A call to sqlite3_set_clientdata(D,N,P,X) causes the pointer P
|
||||
** to be attached to [database connection] D using name N. Subsequent
|
||||
** calls to sqlite3_get_clientdata(D,N) will return a copy of pointer P
|
||||
** or a NULL pointer if there were no prior calls to
|
||||
** sqlite3_set_clientdata() with the same values of D and N.
|
||||
** Names are compared using strcmp() and are thus case sensitive.
|
||||
**
|
||||
** If P and X are both non-NULL, then the destructor X is invoked with
|
||||
** argument P on the first of the following occurrences:
|
||||
** <ul>
|
||||
** <li> An out-of-memory error occurs during the call to
|
||||
** sqlite3_set_clientdata() which attempts to register pointer P.
|
||||
** <li> A subsequent call to sqlite3_set_clientdata(D,N,P,X) is made
|
||||
** with the same D and N parameters.
|
||||
** <li> The database connection closes. SQLite does not make any guarantees
|
||||
** about the order in which destructors are called, only that all
|
||||
** destructors will be called exactly once at some point during the
|
||||
** database connection closing process.
|
||||
** </ul>
|
||||
**
|
||||
** SQLite does not do anything with client data other than invoke
|
||||
** destructors on the client data at the appropriate time. The intended
|
||||
** use for client data is to provide a mechanism for wrapper libraries
|
||||
** to store additional information about an SQLite database connection.
|
||||
**
|
||||
** There is no limit (other than available memory) on the number of different
|
||||
** client data pointers (with different names) that can be attached to a
|
||||
** single database connection. However, the implementation is optimized
|
||||
** for the case of having only one or two different client data names.
|
||||
** Applications and wrapper libraries are discouraged from using more than
|
||||
** one client data name each.
|
||||
**
|
||||
** There is no way to enumerate the client data pointers
|
||||
** associated with a database connection. The N parameter can be thought
|
||||
** of as a secret key such that only code that knows the secret key is able
|
||||
** to access the associated data.
|
||||
**
|
||||
** Security Warning: These interfaces should not be exposed in scripting
|
||||
** languages or in other circumstances where it might be possible for an
|
||||
** an attacker to invoke them. Any agent that can invoke these interfaces
|
||||
** can probably also take control of the process.
|
||||
**
|
||||
** Database connection client data is only available for SQLite
|
||||
** version 3.44.0 ([dateof:3.44.0]) and later.
|
||||
**
|
||||
** See also: [sqlite3_set_auxdata()] and [sqlite3_get_auxdata()].
|
||||
*/
|
||||
SQLITE_API void *sqlite3_get_clientdata(sqlite3*,const char*);
|
||||
SQLITE_API int sqlite3_set_clientdata(sqlite3*, const char*, void*, void(*)(void*));
|
||||
|
||||
/*
|
||||
** CAPI3REF: Constants Defining Special Destructor Behavior
|
||||
@@ -6515,7 +6625,7 @@ SQLITE_API int sqlite3_db_readonly(sqlite3 *db, const char *zDbName);
|
||||
SQLITE_API int sqlite3_txn_state(sqlite3*,const char *zSchema);
|
||||
|
||||
/*
|
||||
** CAPI3REF: Allowed return values from [sqlite3_txn_state()]
|
||||
** CAPI3REF: Allowed return values from sqlite3_txn_state()
|
||||
** KEYWORDS: {transaction state}
|
||||
**
|
||||
** These constants define the current transaction state of a database file.
|
||||
@@ -6647,7 +6757,7 @@ SQLITE_API void *sqlite3_rollback_hook(sqlite3*, void(*)(void *), void*);
|
||||
** ^Each call to the sqlite3_autovacuum_pages() interface overrides all
|
||||
** previous invocations for that database connection. ^If the callback
|
||||
** argument (C) to sqlite3_autovacuum_pages(D,C,P,X) is a NULL pointer,
|
||||
** then the autovacuum steps callback is cancelled. The return value
|
||||
** then the autovacuum steps callback is canceled. The return value
|
||||
** from sqlite3_autovacuum_pages() is normally SQLITE_OK, but might
|
||||
** be some other error code if something goes wrong. The current
|
||||
** implementation will only return SQLITE_OK or SQLITE_MISUSE, but other
|
||||
@@ -7166,6 +7276,10 @@ struct sqlite3_module {
|
||||
/* The methods above are in versions 1 and 2 of the sqlite_module object.
|
||||
** Those below are for version 3 and greater. */
|
||||
int (*xShadowName)(const char*);
|
||||
/* The methods above are in versions 1 through 3 of the sqlite_module object.
|
||||
** Those below are for version 4 and greater. */
|
||||
int (*xIntegrity)(sqlite3_vtab *pVTab, const char *zSchema,
|
||||
const char *zTabName, int mFlags, char **pzErr);
|
||||
};
|
||||
|
||||
/*
|
||||
@@ -7653,7 +7767,7 @@ SQLITE_API int sqlite3_blob_reopen(sqlite3_blob *, sqlite3_int64);
|
||||
** code is returned and the transaction rolled back.
|
||||
**
|
||||
** Calling this function with an argument that is not a NULL pointer or an
|
||||
** open blob handle results in undefined behaviour. ^Calling this routine
|
||||
** open blob handle results in undefined behavior. ^Calling this routine
|
||||
** with a null pointer (such as would be returned by a failed call to
|
||||
** [sqlite3_blob_open()]) is a harmless no-op. ^Otherwise, if this function
|
||||
** is passed a valid open blob handle, the values returned by the
|
||||
@@ -8133,6 +8247,7 @@ SQLITE_API int sqlite3_test_control(int op, ...);
|
||||
#define SQLITE_TESTCTRL_PRNG_SAVE 5
|
||||
#define SQLITE_TESTCTRL_PRNG_RESTORE 6
|
||||
#define SQLITE_TESTCTRL_PRNG_RESET 7 /* NOT USED */
|
||||
#define SQLITE_TESTCTRL_FK_NO_ACTION 7
|
||||
#define SQLITE_TESTCTRL_BITVEC_TEST 8
|
||||
#define SQLITE_TESTCTRL_FAULT_INSTALL 9
|
||||
#define SQLITE_TESTCTRL_BENIGN_MALLOC_HOOKS 10
|
||||
@@ -8161,7 +8276,8 @@ SQLITE_API int sqlite3_test_control(int op, ...);
|
||||
#define SQLITE_TESTCTRL_TRACEFLAGS 31
|
||||
#define SQLITE_TESTCTRL_TUNE 32
|
||||
#define SQLITE_TESTCTRL_LOGEST 33
|
||||
#define SQLITE_TESTCTRL_LAST 33 /* Largest TESTCTRL */
|
||||
#define SQLITE_TESTCTRL_USELONGDOUBLE 34
|
||||
#define SQLITE_TESTCTRL_LAST 34 /* Largest TESTCTRL */
|
||||
|
||||
/*
|
||||
** CAPI3REF: SQL Keyword Checking
|
||||
@@ -9617,7 +9733,7 @@ SQLITE_API int sqlite3_vtab_config(sqlite3*, int op, ...);
|
||||
** [[SQLITE_VTAB_DIRECTONLY]]<dt>SQLITE_VTAB_DIRECTONLY</dt>
|
||||
** <dd>Calls of the form
|
||||
** [sqlite3_vtab_config](db,SQLITE_VTAB_DIRECTONLY) from within the
|
||||
** the [xConnect] or [xCreate] methods of a [virtual table] implmentation
|
||||
** the [xConnect] or [xCreate] methods of a [virtual table] implementation
|
||||
** prohibits that virtual table from being used from within triggers and
|
||||
** views.
|
||||
** </dd>
|
||||
@@ -9807,7 +9923,7 @@ SQLITE_API int sqlite3_vtab_distinct(sqlite3_index_info*);
|
||||
** communicated to the xBestIndex method as a
|
||||
** [SQLITE_INDEX_CONSTRAINT_EQ] constraint.)^ If xBestIndex wants to use
|
||||
** this constraint, it must set the corresponding
|
||||
** aConstraintUsage[].argvIndex to a postive integer. ^(Then, under
|
||||
** aConstraintUsage[].argvIndex to a positive integer. ^(Then, under
|
||||
** the usual mode of handling IN operators, SQLite generates [bytecode]
|
||||
** that invokes the [xFilter|xFilter() method] once for each value
|
||||
** on the right-hand side of the IN operator.)^ Thus the virtual table
|
||||
@@ -10236,7 +10352,7 @@ SQLITE_API int sqlite3_db_cacheflush(sqlite3*);
|
||||
** When the [sqlite3_blob_write()] API is used to update a blob column,
|
||||
** the pre-update hook is invoked with SQLITE_DELETE. This is because the
|
||||
** in this case the new values are not available. In this case, when a
|
||||
** callback made with op==SQLITE_DELETE is actuall a write using the
|
||||
** callback made with op==SQLITE_DELETE is actually a write using the
|
||||
** sqlite3_blob_write() API, the [sqlite3_preupdate_blobwrite()] returns
|
||||
** the index of the column being written. In other cases, where the
|
||||
** pre-update hook is being invoked for some other reason, including a
|
||||
@@ -10497,6 +10613,13 @@ SQLITE_API SQLITE_EXPERIMENTAL int sqlite3_snapshot_recover(sqlite3 *db, const c
|
||||
** SQLITE_SERIALIZE_NOCOPY bit is set but no contiguous copy
|
||||
** of the database exists.
|
||||
**
|
||||
** After the call, if the SQLITE_SERIALIZE_NOCOPY bit had been set,
|
||||
** the returned buffer content will remain accessible and unchanged
|
||||
** until either the next write operation on the connection or when
|
||||
** the connection is closed, and applications must not modify the
|
||||
** buffer. If the bit had been clear, the returned buffer will not
|
||||
** be accessed by SQLite after the call.
|
||||
**
|
||||
** A call to sqlite3_serialize(D,S,P,F) might return NULL even if the
|
||||
** SQLITE_SERIALIZE_NOCOPY bit is omitted from argument F if a memory
|
||||
** allocation error occurs.
|
||||
@@ -10545,6 +10668,9 @@ SQLITE_API unsigned char *sqlite3_serialize(
|
||||
** SQLite will try to increase the buffer size using sqlite3_realloc64()
|
||||
** if writes on the database cause it to grow larger than M bytes.
|
||||
**
|
||||
** Applications must not modify the buffer P or invalidate it before
|
||||
** the database connection D is closed.
|
||||
**
|
||||
** The sqlite3_deserialize() interface will fail with SQLITE_BUSY if the
|
||||
** database is currently in a read transaction or is involved in a backup
|
||||
** operation.
|
||||
@@ -10553,6 +10679,13 @@ SQLITE_API unsigned char *sqlite3_serialize(
|
||||
** S argument to sqlite3_deserialize(D,S,P,N,M,F) is "temp" then the
|
||||
** function returns SQLITE_ERROR.
|
||||
**
|
||||
** The deserialized database should not be in [WAL mode]. If the database
|
||||
** is in WAL mode, then any attempt to use the database file will result
|
||||
** in an [SQLITE_CANTOPEN] error. The application can set the
|
||||
** [file format version numbers] (bytes 18 and 19) of the input database P
|
||||
** to 0x01 prior to invoking sqlite3_deserialize(D,S,P,N,M,F) to force the
|
||||
** database file into rollback mode and work around this limitation.
|
||||
**
|
||||
** If sqlite3_deserialize(D,S,P,N,M,F) fails for any reason and if the
|
||||
** SQLITE_DESERIALIZE_FREEONCLOSE bit is set in argument F, then
|
||||
** [sqlite3_free()] is invoked on argument P prior to returning.
|
||||
@@ -11625,6 +11758,18 @@ SQLITE_API int sqlite3changeset_concat(
|
||||
);
|
||||
|
||||
|
||||
/*
|
||||
** CAPI3REF: Upgrade the Schema of a Changeset/Patchset
|
||||
*/
|
||||
SQLITE_API int sqlite3changeset_upgrade(
|
||||
sqlite3 *db,
|
||||
const char *zDb,
|
||||
int nIn, const void *pIn, /* Input changeset */
|
||||
int *pnOut, void **ppOut /* OUT: Inverse of input */
|
||||
);
|
||||
|
||||
|
||||
|
||||
/*
|
||||
** CAPI3REF: Changegroup Handle
|
||||
**
|
||||
@@ -11671,6 +11816,38 @@ typedef struct sqlite3_changegroup sqlite3_changegroup;
|
||||
*/
|
||||
SQLITE_API int sqlite3changegroup_new(sqlite3_changegroup **pp);
|
||||
|
||||
/*
|
||||
** CAPI3REF: Add a Schema to a Changegroup
|
||||
** METHOD: sqlite3_changegroup_schema
|
||||
**
|
||||
** This method may be used to optionally enforce the rule that the changesets
|
||||
** added to the changegroup handle must match the schema of database zDb
|
||||
** ("main", "temp", or the name of an attached database). If
|
||||
** sqlite3changegroup_add() is called to add a changeset that is not compatible
|
||||
** with the configured schema, SQLITE_SCHEMA is returned and the changegroup
|
||||
** object is left in an undefined state.
|
||||
**
|
||||
** A changeset schema is considered compatible with the database schema in
|
||||
** the same way as for sqlite3changeset_apply(). Specifically, for each
|
||||
** table in the changeset, there exists a database table with:
|
||||
**
|
||||
** <ul>
|
||||
** <li> The name identified by the changeset, and
|
||||
** <li> at least as many columns as recorded in the changeset, and
|
||||
** <li> the primary key columns in the same position as recorded in
|
||||
** the changeset.
|
||||
** </ul>
|
||||
**
|
||||
** The output of the changegroup object always has the same schema as the
|
||||
** database nominated using this function. In cases where changesets passed
|
||||
** to sqlite3changegroup_add() have fewer columns than the corresponding table
|
||||
** in the database schema, these are filled in using the default column
|
||||
** values from the database schema. This makes it possible to combined
|
||||
** changesets that have different numbers of columns for a single table
|
||||
** within a changegroup, provided that they are otherwise compatible.
|
||||
*/
|
||||
SQLITE_API int sqlite3changegroup_schema(sqlite3_changegroup*, sqlite3*, const char *zDb);
|
||||
|
||||
/*
|
||||
** CAPI3REF: Add A Changeset To A Changegroup
|
||||
** METHOD: sqlite3_changegroup
|
||||
@@ -11739,13 +11916,18 @@ SQLITE_API int sqlite3changegroup_new(sqlite3_changegroup **pp);
|
||||
** If the new changeset contains changes to a table that is already present
|
||||
** in the changegroup, then the number of columns and the position of the
|
||||
** primary key columns for the table must be consistent. If this is not the
|
||||
** case, this function fails with SQLITE_SCHEMA. If the input changeset
|
||||
** appears to be corrupt and the corruption is detected, SQLITE_CORRUPT is
|
||||
** returned. Or, if an out-of-memory condition occurs during processing, this
|
||||
** function returns SQLITE_NOMEM. In all cases, if an error occurs the state
|
||||
** of the final contents of the changegroup is undefined.
|
||||
** case, this function fails with SQLITE_SCHEMA. Except, if the changegroup
|
||||
** object has been configured with a database schema using the
|
||||
** sqlite3changegroup_schema() API, then it is possible to combine changesets
|
||||
** with different numbers of columns for a single table, provided that
|
||||
** they are otherwise compatible.
|
||||
**
|
||||
** If no error occurs, SQLITE_OK is returned.
|
||||
** If the input changeset appears to be corrupt and the corruption is
|
||||
** detected, SQLITE_CORRUPT is returned. Or, if an out-of-memory condition
|
||||
** occurs during processing, this function returns SQLITE_NOMEM.
|
||||
**
|
||||
** In all cases, if an error occurs the state of the final contents of the
|
||||
** changegroup is undefined. If no error occurs, SQLITE_OK is returned.
|
||||
*/
|
||||
SQLITE_API int sqlite3changegroup_add(sqlite3_changegroup*, int nData, void *pData);
|
||||
|
||||
@@ -12010,10 +12192,17 @@ SQLITE_API int sqlite3changeset_apply_v2(
|
||||
** <li>an insert change if all fields of the conflicting row match
|
||||
** the row being inserted.
|
||||
** </ul>
|
||||
**
|
||||
** <dt>SQLITE_CHANGESETAPPLY_FKNOACTION <dd>
|
||||
** If this flag it set, then all foreign key constraints in the target
|
||||
** database behave as if they were declared with "ON UPDATE NO ACTION ON
|
||||
** DELETE NO ACTION", even if they are actually CASCADE, RESTRICT, SET NULL
|
||||
** or SET DEFAULT.
|
||||
*/
|
||||
#define SQLITE_CHANGESETAPPLY_NOSAVEPOINT 0x0001
|
||||
#define SQLITE_CHANGESETAPPLY_INVERT 0x0002
|
||||
#define SQLITE_CHANGESETAPPLY_IGNORENOOP 0x0004
|
||||
#define SQLITE_CHANGESETAPPLY_FKNOACTION 0x0008
|
||||
|
||||
/*
|
||||
** CAPI3REF: Constants Passed To The Conflict Handler
|
||||
@@ -12754,7 +12943,7 @@ struct Fts5PhraseIter {
|
||||
** See xPhraseFirstColumn above.
|
||||
*/
|
||||
struct Fts5ExtensionApi {
|
||||
int iVersion; /* Currently always set to 3 */
|
||||
int iVersion; /* Currently always set to 2 */
|
||||
|
||||
void *(*xUserData)(Fts5Context*);
|
||||
|
||||
@@ -12983,8 +13172,8 @@ struct Fts5ExtensionApi {
|
||||
** as separate queries of the FTS index are required for each synonym.
|
||||
**
|
||||
** When using methods (2) or (3), it is important that the tokenizer only
|
||||
** provide synonyms when tokenizing document text (method (2)) or query
|
||||
** text (method (3)), not both. Doing so will not cause any errors, but is
|
||||
** provide synonyms when tokenizing document text (method (3)) or query
|
||||
** text (method (2)), not both. Doing so will not cause any errors, but is
|
||||
** inefficient.
|
||||
*/
|
||||
typedef struct Fts5Tokenizer Fts5Tokenizer;
|
||||
@@ -13032,7 +13221,7 @@ struct fts5_api {
|
||||
int (*xCreateTokenizer)(
|
||||
fts5_api *pApi,
|
||||
const char *zName,
|
||||
void *pContext,
|
||||
void *pUserData,
|
||||
fts5_tokenizer *pTokenizer,
|
||||
void (*xDestroy)(void*)
|
||||
);
|
||||
@@ -13041,7 +13230,7 @@ struct fts5_api {
|
||||
int (*xFindTokenizer)(
|
||||
fts5_api *pApi,
|
||||
const char *zName,
|
||||
void **ppContext,
|
||||
void **ppUserData,
|
||||
fts5_tokenizer *pTokenizer
|
||||
);
|
||||
|
||||
@@ -13049,7 +13238,7 @@ struct fts5_api {
|
||||
int (*xCreateFunction)(
|
||||
fts5_api *pApi,
|
||||
const char *zName,
|
||||
void *pContext,
|
||||
void *pUserData,
|
||||
fts5_extension_function xFunction,
|
||||
void (*xDestroy)(void*)
|
||||
);
|
||||
|
||||
10
libsqlite3-sys/sqlite3/sqlite3ext.h
vendored
10
libsqlite3-sys/sqlite3/sqlite3ext.h
vendored
@@ -361,6 +361,11 @@ struct sqlite3_api_routines {
|
||||
int (*value_encoding)(sqlite3_value*);
|
||||
/* Version 3.41.0 and later */
|
||||
int (*is_interrupted)(sqlite3*);
|
||||
/* Version 3.43.0 and later */
|
||||
int (*stmt_explain)(sqlite3_stmt*,int);
|
||||
/* Version 3.44.0 and later */
|
||||
void *(*get_clientdata)(sqlite3*,const char*);
|
||||
int (*set_clientdata)(sqlite3*, const char*, void*, void(*)(void*));
|
||||
};
|
||||
|
||||
/*
|
||||
@@ -689,6 +694,11 @@ typedef int (*sqlite3_loadext_entry)(
|
||||
#define sqlite3_value_encoding sqlite3_api->value_encoding
|
||||
/* Version 3.41.0 and later */
|
||||
#define sqlite3_is_interrupted sqlite3_api->is_interrupted
|
||||
/* Version 3.43.0 and later */
|
||||
#define sqlite3_stmt_explain sqlite3_api->stmt_explain
|
||||
/* Version 3.44.0 and later */
|
||||
#define sqlite3_get_clientdata sqlite3_api->get_clientdata
|
||||
#define sqlite3_set_clientdata sqlite3_api->set_clientdata
|
||||
#endif /* !defined(SQLITE_CORE) && !defined(SQLITE_OMIT_LOAD_EXTENSION) */
|
||||
|
||||
#if !defined(SQLITE_CORE) && !defined(SQLITE_OMIT_LOAD_EXTENSION)
|
||||
|
||||
@@ -132,6 +132,8 @@ const SQLITE_IOERR_BEGIN_ATOMIC: c_int = super::SQLITE_IOERR | (29 << 8);
|
||||
const SQLITE_IOERR_COMMIT_ATOMIC: c_int = super::SQLITE_IOERR | (30 << 8);
|
||||
const SQLITE_IOERR_ROLLBACK_ATOMIC: c_int = super::SQLITE_IOERR | (31 << 8);
|
||||
const SQLITE_IOERR_DATA: c_int = super::SQLITE_IOERR | (32 << 8);
|
||||
const SQLITE_IOERR_CORRUPTFS: c_int = super::SQLITE_IOERR | (33 << 8);
|
||||
const SQLITE_IOERR_IN_PAGE: c_int = super::SQLITE_IOERR | (34 << 8);
|
||||
|
||||
const SQLITE_LOCKED_VTAB: c_int = super::SQLITE_LOCKED | (2 << 8);
|
||||
|
||||
@@ -219,6 +221,8 @@ pub fn code_to_str(code: c_int) -> &'static str {
|
||||
SQLITE_IOERR_COMMIT_ATOMIC => "SQLITE_IOERR_COMMIT_ATOMIC",
|
||||
SQLITE_IOERR_ROLLBACK_ATOMIC => "SQLITE_IOERR_ROLLBACK_ATOMIC",
|
||||
SQLITE_IOERR_DATA => "SQLITE_IOERR_DATA",
|
||||
SQLITE_IOERR_CORRUPTFS => "SQLITE_IOERR_CORRUPTFS",
|
||||
SQLITE_IOERR_IN_PAGE => "SQLITE_IOERR_IN_PAGE",
|
||||
|
||||
super::SQLITE_LOCKED_SHAREDCACHE => "Locking conflict due to another connection with a shared cache",
|
||||
SQLITE_LOCKED_VTAB => "SQLITE_LOCKED_VTAB",
|
||||
@@ -269,3 +273,32 @@ pub fn code_to_str(code: c_int) -> &'static str {
|
||||
_ => "Unknown error code",
|
||||
}
|
||||
}
|
||||
|
||||
/// Loadable extension initialization error
|
||||
#[cfg(feature = "loadable_extension")]
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
|
||||
#[non_exhaustive]
|
||||
pub enum InitError {
|
||||
/// Version mismatch between the extension and the SQLite3 library
|
||||
VersionMismatch { compile_time: i32, runtime: i32 },
|
||||
/// Invalid function pointer in one of sqlite3_api_routines fields
|
||||
NullFunctionPointer,
|
||||
}
|
||||
#[cfg(feature = "loadable_extension")]
|
||||
impl ::std::fmt::Display for InitError {
|
||||
fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
|
||||
match *self {
|
||||
InitError::VersionMismatch {
|
||||
compile_time,
|
||||
runtime,
|
||||
} => {
|
||||
write!(f, "SQLite version mismatch: {runtime} < {compile_time}")
|
||||
}
|
||||
InitError::NullFunctionPointer => {
|
||||
write!(f, "Some sqlite3_api_routines fields are null")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#[cfg(feature = "loadable_extension")]
|
||||
impl error::Error for InitError {}
|
||||
|
||||
@@ -3,26 +3,38 @@
|
||||
SCRIPT_DIR=$(cd "$(dirname "$0")" && pwd)
|
||||
echo "$SCRIPT_DIR"
|
||||
cd "$SCRIPT_DIR" || { echo "fatal error" >&2; exit 1; }
|
||||
cargo clean
|
||||
mkdir -p "$SCRIPT_DIR/../target" "$SCRIPT_DIR/sqlite3"
|
||||
cargo clean -p libsqlite3-sys
|
||||
TARGET_DIR="$SCRIPT_DIR/../target"
|
||||
export SQLITE3_LIB_DIR="$SCRIPT_DIR/sqlite3"
|
||||
export SQLITE3_INCLUDE_DIR="$SQLITE3_LIB_DIR"
|
||||
mkdir -p "$TARGET_DIR" "$SQLITE3_LIB_DIR"
|
||||
|
||||
# Download and extract amalgamation
|
||||
SQLITE=sqlite-amalgamation-3420000
|
||||
SQLITE=sqlite-amalgamation-3440000
|
||||
curl -O https://sqlite.org/2023/$SQLITE.zip
|
||||
unzip -p "$SQLITE.zip" "$SQLITE/sqlite3.c" > "$SQLITE3_LIB_DIR/sqlite3.c"
|
||||
unzip -p "$SQLITE.zip" "$SQLITE/sqlite3.h" > "$SQLITE3_LIB_DIR/sqlite3.h"
|
||||
unzip -p "$SQLITE.zip" "$SQLITE/sqlite3ext.h" > "$SQLITE3_LIB_DIR/sqlite3ext.h"
|
||||
rm -f "$SQLITE.zip"
|
||||
|
||||
# Regenerate bindgen file for sqlite3
|
||||
export SQLITE3_INCLUDE_DIR="$SQLITE3_LIB_DIR"
|
||||
# Regenerate bindgen file for sqlite3.h
|
||||
rm -f "$SQLITE3_LIB_DIR/bindgen_bundled_version.rs"
|
||||
cargo update
|
||||
# Just to make sure there is only one bindgen.rs file in target dir
|
||||
find "$SCRIPT_DIR/../target" -type f -name bindgen.rs -exec rm {} \;
|
||||
find "$TARGET_DIR" -type f -name bindgen.rs -exec rm {} \;
|
||||
env LIBSQLITE3_SYS_BUNDLING=1 cargo build --features "buildtime_bindgen session" --no-default-features
|
||||
find "$SCRIPT_DIR/../target" -type f -name bindgen.rs -exec mv {} "$SQLITE3_LIB_DIR/bindgen_bundled_version.rs" \;
|
||||
find "$TARGET_DIR" -type f -name bindgen.rs -exec mv {} "$SQLITE3_LIB_DIR/bindgen_bundled_version.rs" \;
|
||||
|
||||
# Regenerate bindgen file for sqlite3ext.h
|
||||
# some sqlite3_api_routines fields are function pointers with va_list arg but currently stable Rust doesn't support this type.
|
||||
# FIXME how to generate portable bindings without :
|
||||
sed -i.bk -e 's/va_list/void*/' "$SQLITE3_LIB_DIR/sqlite3ext.h"
|
||||
rm -f "$SQLITE3_LIB_DIR/bindgen_bundled_version_ext.rs"
|
||||
find "$TARGET_DIR" -type f -name bindgen.rs -exec rm {} \;
|
||||
env LIBSQLITE3_SYS_BUNDLING=1 cargo build --features "buildtime_bindgen loadable_extension" --no-default-features
|
||||
find "$TARGET_DIR" -type f -name bindgen.rs -exec mv {} "$SQLITE3_LIB_DIR/bindgen_bundled_version_ext.rs" \;
|
||||
git checkout "$SQLITE3_LIB_DIR/sqlite3ext.h"
|
||||
rm -f "$SQLITE3_LIB_DIR/sqlite3ext.h.bk"
|
||||
|
||||
# Sanity checks
|
||||
cd "$SCRIPT_DIR/.." || { echo "fatal error" >&2; exit 1; }
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
SCRIPT_DIR=$(cd "$(dirname "$0")" && pwd)
|
||||
echo "$SCRIPT_DIR"
|
||||
cd "$SCRIPT_DIR" || { echo "fatal error" >&2; exit 1; }
|
||||
cargo clean
|
||||
cargo clean -p libsqlite3-sys
|
||||
mkdir -p "$SCRIPT_DIR/../target" "$SCRIPT_DIR/sqlcipher"
|
||||
export SQLCIPHER_LIB_DIR="$SCRIPT_DIR/sqlcipher"
|
||||
export SQLCIPHER_INCLUDE_DIR="$SQLCIPHER_LIB_DIR"
|
||||
|
||||
2
libsqlite3-sys/wrapper_ext.h
Normal file
2
libsqlite3-sys/wrapper_ext.h
Normal file
@@ -0,0 +1,2 @@
|
||||
#include "sqlite3ext.h"
|
||||
|
||||
Reference in New Issue
Block a user