mirror of
https://github.com/isar/rusqlite.git
synced 2025-03-29 00:32:57 +08:00
Merge remote-tracking branch 'origin/master' into owning
This commit is contained in:
commit
70d192d3cd
77
.github/workflows/main.yml
vendored
77
.github/workflows/main.yml
vendored
@ -20,6 +20,10 @@ env:
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.ref }}
|
||||
cancel-in-progress: true
|
||||
|
||||
jobs:
|
||||
test:
|
||||
name: Test ${{ matrix.target }}
|
||||
@ -39,20 +43,20 @@ jobs:
|
||||
runs-on: ${{ matrix.os }}
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v4
|
||||
# This has a matcher for test panics, so we use it even though elsewhere
|
||||
# we use actions-rs/toolchain.
|
||||
- uses: hecrj/setup-rust-action@v1
|
||||
- uses: hecrj/setup-rust-action@v2
|
||||
with:
|
||||
rust-version: stable${{ matrix.host }}
|
||||
targets: ${{ matrix.target }}
|
||||
# The `{ sharedKey: ... }` allows different actions to share the cache.
|
||||
# The `{ shared-key: ... }` allows different actions to share the cache.
|
||||
# We're using a `fullBuild` key mostly as a "this needs to do the
|
||||
# complete" that needs to do the complete build (that is, including
|
||||
# `--features 'bundled-full session buildtime_bindgen'`), which is very
|
||||
# `--features 'bundled-full session buildtime_bindgen preupdate_hook'`), which is very
|
||||
# slow, and has several deps.
|
||||
- uses: Swatinem/rust-cache@v2
|
||||
with: { sharedKey: fullBuild }
|
||||
with: { shared-key: fullBuild }
|
||||
|
||||
- run: cargo build --features bundled --workspace --all-targets --verbose
|
||||
- run: cargo test --features bundled --workspace --all-targets --verbose
|
||||
@ -62,8 +66,8 @@ jobs:
|
||||
if: matrix.os == 'windows-latest'
|
||||
run: echo "C:\msys64\mingw64\bin" | Out-File -FilePath $env:GITHUB_PATH -Encoding utf8 -Append
|
||||
|
||||
- run: cargo test --features 'bundled-full session buildtime_bindgen' --all-targets --workspace --verbose
|
||||
- run: cargo test --features 'bundled-full session buildtime_bindgen' --doc --workspace --verbose
|
||||
- run: cargo test --features 'bundled-full session buildtime_bindgen preupdate_hook' --all-targets --workspace --verbose
|
||||
- run: cargo test --features 'bundled-full session buildtime_bindgen preupdate_hook' --doc --workspace --verbose
|
||||
|
||||
- name: loadable extension
|
||||
run: |
|
||||
@ -93,15 +97,15 @@ jobs:
|
||||
# TODO: find a way to test this on windows :(
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v4
|
||||
# This has a matcher for test panics, so we use it even though elsewhere
|
||||
# we use actions-rs/toolchain.
|
||||
- uses: hecrj/setup-rust-action@v1
|
||||
- uses: hecrj/setup-rust-action@v2
|
||||
with:
|
||||
rust-version: stable${{ matrix.host }}
|
||||
targets: ${{ matrix.target }}
|
||||
- uses: Swatinem/rust-cache@v2
|
||||
with: { sharedKey: fullBuild }
|
||||
with: { shared-key: fullBuild }
|
||||
|
||||
- run: cargo test --features 'bundled-sqlcipher' --workspace --all-targets --verbose
|
||||
- run: cargo test --features 'bundled-sqlcipher' --workspace --doc --verbose
|
||||
@ -119,15 +123,15 @@ jobs:
|
||||
if: matrix.os == 'windows-latest'
|
||||
run: echo "C:\msys64\mingw64\bin" | Out-File -FilePath $env:GITHUB_PATH -Encoding utf8 -Append
|
||||
|
||||
- run: cargo test --features 'bundled-full session buildtime_bindgen' --all-targets --workspace --verbose
|
||||
- run: cargo test --features 'bundled-full session buildtime_bindgen' --doc --workspace --verbose
|
||||
- run: cargo test --features 'bundled-full session buildtime_bindgen preupdate_hook' --all-targets --workspace --verbose
|
||||
- run: cargo test --features 'bundled-full session buildtime_bindgen preupdate_hook' --doc --workspace --verbose
|
||||
|
||||
sqlcipher:
|
||||
name: Test with sqlcipher
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: hecrj/setup-rust-action@v1
|
||||
- uses: actions/checkout@v4
|
||||
- uses: hecrj/setup-rust-action@v2
|
||||
- uses: Swatinem/rust-cache@v2
|
||||
- run: sudo apt-get install sqlcipher libsqlcipher-dev
|
||||
- run: sqlcipher --version
|
||||
@ -139,9 +143,9 @@ jobs:
|
||||
name: Address Sanitizer
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v4
|
||||
# Need nightly rust.
|
||||
- uses: hecrj/setup-rust-action@v1
|
||||
- uses: hecrj/setup-rust-action@v2
|
||||
with:
|
||||
rust-version: nightly
|
||||
components: rust-src
|
||||
@ -156,29 +160,41 @@ jobs:
|
||||
# leak sanitization, but we don't care about backtraces here, so long
|
||||
# as the other tests have them.
|
||||
RUST_BACKTRACE: "0"
|
||||
run: cargo -Z build-std test --features 'bundled-full session buildtime_bindgen with-asan' --target x86_64-unknown-linux-gnu
|
||||
run: cargo -Z build-std test --features 'bundled-full session buildtime_bindgen preupdate_hook with-asan' --target x86_64-unknown-linux-gnu
|
||||
|
||||
direct-minimal-versions:
|
||||
name: Test min versions
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: hecrj/setup-rust-action@v2
|
||||
with:
|
||||
rust-version: nightly
|
||||
- uses: Swatinem/rust-cache@v2
|
||||
- run: cargo update -Z direct-minimal-versions
|
||||
- run: cargo test --workspace --all-targets --features bundled-full
|
||||
|
||||
# Ensure clippy doesn't complain.
|
||||
clippy:
|
||||
name: Clippy
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: hecrj/setup-rust-action@v1
|
||||
- uses: actions/checkout@v4
|
||||
- uses: hecrj/setup-rust-action@v2
|
||||
with:
|
||||
components: clippy
|
||||
- uses: Swatinem/rust-cache@v2
|
||||
- run: cargo clippy --all-targets --workspace --features bundled -- -D warnings
|
||||
# Clippy with all non-conflicting features
|
||||
- run: cargo clippy --all-targets --workspace --features 'bundled-full session buildtime_bindgen' -- -D warnings
|
||||
- run: cargo clippy --all-targets --workspace --features 'bundled-full session buildtime_bindgen preupdate_hook' -- -D warnings
|
||||
|
||||
# Ensure patch is formatted.
|
||||
fmt:
|
||||
name: Format
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: hecrj/setup-rust-action@v1
|
||||
- uses: actions/checkout@v4
|
||||
- uses: hecrj/setup-rust-action@v2
|
||||
with:
|
||||
components: rustfmt
|
||||
- run: cargo fmt --all -- --check
|
||||
@ -188,21 +204,21 @@ jobs:
|
||||
name: Docs
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: hecrj/setup-rust-action@v1
|
||||
- uses: actions/checkout@v4
|
||||
- uses: hecrj/setup-rust-action@v2
|
||||
- uses: Swatinem/rust-cache@v2
|
||||
with: { sharedKey: fullBuild }
|
||||
- run: cargo doc --features 'bundled-full session buildtime_bindgen' --no-deps
|
||||
with: { shared-key: fullBuild }
|
||||
- run: cargo doc --features 'bundled-full session buildtime_bindgen preupdate_hook' --no-deps
|
||||
env: { RUSTDOCFLAGS: -Dwarnings }
|
||||
|
||||
codecov:
|
||||
name: Generate code coverage
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v4
|
||||
- uses: dtolnay/rust-toolchain@stable
|
||||
with:
|
||||
components: 'llvm-tools-preview'
|
||||
components: "llvm-tools-preview"
|
||||
- uses: taiki-e/install-action@main
|
||||
with:
|
||||
tool: grcov
|
||||
@ -210,7 +226,7 @@ jobs:
|
||||
run: |
|
||||
cargo test --verbose
|
||||
cargo test --features="bundled-full" --verbose
|
||||
cargo test --features="bundled-full session buildtime_bindgen" --verbose
|
||||
cargo test --features="bundled-full session buildtime_bindgen preupdate_hook load_extension" --all --all-targets --verbose
|
||||
cargo test --features="bundled-sqlcipher-vendored-openssl" --verbose
|
||||
env:
|
||||
RUSTFLAGS: -Cinstrument-coverage
|
||||
@ -230,7 +246,8 @@ jobs:
|
||||
-t lcov \
|
||||
-o lcov.info
|
||||
- name: Upload to codecov.io
|
||||
uses: codecov/codecov-action@v3
|
||||
uses: codecov/codecov-action@v4
|
||||
with:
|
||||
files: lcov.info
|
||||
fail_ci_if_error: true
|
||||
token: ${{ secrets.CODECOV_TOKEN }}
|
||||
|
48
Cargo.toml
48
Cargo.toml
@ -1,7 +1,7 @@
|
||||
[package]
|
||||
name = "rusqlite"
|
||||
# Note: Update version in README.md when you change this.
|
||||
version = "0.31.0"
|
||||
version = "0.32.1"
|
||||
authors = ["The rusqlite developers"]
|
||||
edition = "2021"
|
||||
description = "Ergonomic wrapper for SQLite"
|
||||
@ -13,12 +13,12 @@ license = "MIT"
|
||||
categories = ["database"]
|
||||
|
||||
exclude = [
|
||||
"/.github/*",
|
||||
"/.gitattributes",
|
||||
"/appveyor.yml",
|
||||
"/Changelog.md",
|
||||
"/clippy.toml",
|
||||
"/codecov.yml",
|
||||
"/.github/*",
|
||||
"/.gitattributes",
|
||||
"/appveyor.yml",
|
||||
"/Changelog.md",
|
||||
"/clippy.toml",
|
||||
"/codecov.yml",
|
||||
]
|
||||
|
||||
[badges]
|
||||
@ -47,11 +47,15 @@ trace = []
|
||||
release_memory = []
|
||||
bundled = ["libsqlite3-sys/bundled", "modern_sqlite"]
|
||||
bundled-sqlcipher = ["libsqlite3-sys/bundled-sqlcipher", "bundled"]
|
||||
bundled-sqlcipher-vendored-openssl = ["libsqlite3-sys/bundled-sqlcipher-vendored-openssl", "bundled-sqlcipher"]
|
||||
bundled-sqlcipher-vendored-openssl = [
|
||||
"libsqlite3-sys/bundled-sqlcipher-vendored-openssl",
|
||||
"bundled-sqlcipher",
|
||||
]
|
||||
buildtime_bindgen = ["libsqlite3-sys/buildtime_bindgen"]
|
||||
limits = []
|
||||
loadable_extension = ["libsqlite3-sys/loadable_extension"]
|
||||
hooks = []
|
||||
preupdate_hook = ["libsqlite3-sys/preupdate_hook", "hooks"]
|
||||
i128_blob = []
|
||||
sqlcipher = ["libsqlite3-sys/sqlcipher"]
|
||||
unlock_notify = ["libsqlite3-sys/unlock_notify"]
|
||||
@ -96,6 +100,7 @@ modern-full = [
|
||||
"functions",
|
||||
"hooks",
|
||||
"i128_blob",
|
||||
"jiff",
|
||||
"limits",
|
||||
"load_extension",
|
||||
"serde_json",
|
||||
@ -112,10 +117,19 @@ modern-full = [
|
||||
bundled-full = ["modern-full", "bundled"]
|
||||
|
||||
[dependencies]
|
||||
time = { version = "0.3.0", features = ["formatting", "macros", "parsing"], optional = true }
|
||||
bitflags = "2.0"
|
||||
jiff = { version = "0.1", optional = true, default-features = false, features = [
|
||||
"std",
|
||||
] }
|
||||
time = { version = "0.3.36", features = [
|
||||
"formatting",
|
||||
"macros",
|
||||
"parsing",
|
||||
], optional = true }
|
||||
bitflags = "2.6.0"
|
||||
hashlink = "0.9"
|
||||
chrono = { version = "0.4", optional = true, default-features = false, features = ["clock"] }
|
||||
chrono = { version = "0.4.38", optional = true, default-features = false, features = [
|
||||
"clock",
|
||||
] }
|
||||
serde_json = { version = "1.0", optional = true }
|
||||
csv = { version = "1.1", optional = true }
|
||||
url = { version = "2.1", optional = true }
|
||||
@ -123,23 +137,25 @@ fallible-iterator = "0.3"
|
||||
fallible-streaming-iterator = "0.1"
|
||||
uuid = { version = "1.0", optional = true }
|
||||
smallvec = "1.6.1"
|
||||
rusqlite-macros = { path = "rusqlite-macros", version = "0.2.0", optional = true }
|
||||
rusqlite-macros = { path = "rusqlite-macros", version = "0.3.0", optional = true }
|
||||
|
||||
[dev-dependencies]
|
||||
doc-comment = "0.3"
|
||||
tempfile = "3.1.0"
|
||||
lazy_static = "1.4"
|
||||
regex = "1.5.5"
|
||||
uuid = { version = "1.0", features = ["v4"] }
|
||||
unicase = "2.6.0"
|
||||
ouroboros = "0.18"
|
||||
# Use `bencher` over criterion because it builds much faster and we don't have
|
||||
# many benchmarks
|
||||
# Use `bencher` over criterion because it builds much faster,
|
||||
# and we don't have many benchmarks
|
||||
bencher = "0.1"
|
||||
|
||||
[dependencies.libsqlite3-sys]
|
||||
path = "libsqlite3-sys"
|
||||
version = "0.28.0"
|
||||
version = "0.30.1"
|
||||
|
||||
[[test]]
|
||||
name = "auto_ext"
|
||||
|
||||
[[test]]
|
||||
name = "config_log"
|
||||
|
@ -27,7 +27,7 @@ In your Cargo.toml:
|
||||
# That said, it's not ideal for all scenarios and in particular, generic
|
||||
# libraries built around `rusqlite` should probably not enable it, which
|
||||
# is why it is not a default feature -- it could become hard to disable.
|
||||
rusqlite = { version = "0.31.0", features = ["bundled"] }
|
||||
rusqlite = { version = "0.32.0", features = ["bundled"] }
|
||||
```
|
||||
|
||||
Simple example usage:
|
||||
@ -123,6 +123,7 @@ features](https://doc.rust-lang.org/cargo/reference/manifest.html#the-features-s
|
||||
- As the name implies this depends on the `bundled-sqlcipher` feature, and automatically turns it on.
|
||||
- If turned on, this uses the [`openssl-sys`](https://crates.io/crates/openssl-sys) crate, with the `vendored` feature enabled in order to build and bundle the OpenSSL crypto library.
|
||||
* `hooks` for [Commit, Rollback](http://sqlite.org/c3ref/commit_hook.html) and [Data Change](http://sqlite.org/c3ref/update_hook.html) notification callbacks.
|
||||
* `preupdate_hook` for [preupdate](https://sqlite.org/c3ref/preupdate_count.html) notification callbacks. (Implies `hooks`.)
|
||||
* `unlock_notify` for [Unlock](https://sqlite.org/unlock_notify.html) notification.
|
||||
* `vtab` for [virtual table](https://sqlite.org/vtab.html) support (allows you to write virtual table implementations in Rust). Currently, only read-only virtual tables are supported.
|
||||
* `series` exposes [`generate_series(...)`](https://www.sqlite.org/series.html) Table-Valued Function. (Implies `vtab`.)
|
||||
@ -147,11 +148,11 @@ You can adjust this behavior in a number of ways:
|
||||
* If you use the `bundled`, `bundled-sqlcipher`, or `bundled-sqlcipher-vendored-openssl` features, `libsqlite3-sys` will use the
|
||||
[cc](https://crates.io/crates/cc) crate to compile SQLite or SQLCipher from source and
|
||||
link against that. This source is embedded in the `libsqlite3-sys` crate and
|
||||
is currently SQLite 3.45.1 (as of `rusqlite` 0.31.0 / `libsqlite3-sys`
|
||||
0.28.0). This is probably the simplest solution to any build problems. You can enable this by adding the following in your `Cargo.toml` file:
|
||||
is currently SQLite 3.46.0 (as of `rusqlite` 0.32.0 / `libsqlite3-sys`
|
||||
0.30.0). This is probably the simplest solution to any build problems. You can enable this by adding the following in your `Cargo.toml` file:
|
||||
```toml
|
||||
[dependencies.rusqlite]
|
||||
version = "0.31.0"
|
||||
version = "0.32.0"
|
||||
features = ["bundled"]
|
||||
```
|
||||
* When using any of the `bundled` features, the build script will honor `SQLITE_MAX_VARIABLE_NUMBER` and `SQLITE_MAX_EXPR_DEPTH` variables. It will also honor a `LIBSQLITE3_FLAGS` variable, which can have a format like `"-USQLITE_ALPHA -DSQLITE_BETA SQLITE_GAMMA ..."`. That would disable the `SQLITE_ALPHA` flag, and set the `SQLITE_BETA` and `SQLITE_GAMMA` flags. (The initial `-D` can be omitted, as on the last one.)
|
||||
|
@ -1,4 +1,4 @@
|
||||
//! Ensure loadable_extension.rs works.
|
||||
//! Ensure `loadable_extension.rs` works.
|
||||
|
||||
use rusqlite::{Connection, Result};
|
||||
use std::env::consts::{DLL_PREFIX, DLL_SUFFIX};
|
||||
@ -9,10 +9,7 @@ fn main() -> Result<()> {
|
||||
unsafe {
|
||||
db.load_extension_enable()?;
|
||||
db.load_extension(
|
||||
format!(
|
||||
"target/debug/examples/{}loadable_extension{}",
|
||||
DLL_PREFIX, DLL_SUFFIX
|
||||
),
|
||||
format!("target/debug/examples/{DLL_PREFIX}loadable_extension{DLL_SUFFIX}"),
|
||||
None,
|
||||
)?;
|
||||
db.load_extension_disable()?;
|
||||
|
@ -4,7 +4,7 @@ use std::os::raw::{c_char, c_int};
|
||||
use rusqlite::ffi;
|
||||
use rusqlite::functions::FunctionFlags;
|
||||
use rusqlite::types::{ToSqlOutput, Value};
|
||||
use rusqlite::{to_sqlite_error, Connection, Result};
|
||||
use rusqlite::{Connection, Result};
|
||||
|
||||
/// # build
|
||||
/// ```sh
|
||||
@ -20,21 +20,15 @@ use rusqlite::{to_sqlite_error, Connection, Result};
|
||||
/// ```
|
||||
#[allow(clippy::not_unsafe_ptr_arg_deref)]
|
||||
#[no_mangle]
|
||||
pub extern "C" fn sqlite3_extension_init(
|
||||
pub unsafe 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 {
|
||||
if p_api.is_null() {
|
||||
return ffi::SQLITE_ERROR;
|
||||
} else if let Err(err) = extension_init(db, p_api) {
|
||||
return unsafe { to_sqlite_error(&err, pz_err_msg) };
|
||||
}
|
||||
ffi::SQLITE_OK
|
||||
Connection::extension_init2(db, pz_err_msg, p_api, extension_init)
|
||||
}
|
||||
|
||||
fn extension_init(db: *mut ffi::sqlite3, p_api: *mut ffi::sqlite3_api_routines) -> Result<()> {
|
||||
let db = unsafe { Connection::extension_init2(db, p_api)? };
|
||||
fn extension_init(db: Connection) -> Result<bool> {
|
||||
db.create_scalar_function(
|
||||
"rusqlite_test_function",
|
||||
0,
|
||||
@ -46,5 +40,5 @@ fn extension_init(db: *mut ffi::sqlite3, p_api: *mut ffi::sqlite3_api_routines)
|
||||
},
|
||||
)?;
|
||||
rusqlite::trace::log(ffi::SQLITE_WARNING, "Rusqlite extension initialized");
|
||||
Ok(())
|
||||
Ok(false)
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "libsqlite3-sys"
|
||||
version = "0.28.0"
|
||||
version = "0.30.1"
|
||||
authors = ["The rusqlite developers"]
|
||||
edition = "2021"
|
||||
repository = "https://github.com/rusqlite/rusqlite"
|
||||
@ -35,16 +35,16 @@ with-asan = []
|
||||
wasm32-wasi-vfs = []
|
||||
|
||||
[dependencies]
|
||||
openssl-sys = { version = "0.9", optional = true }
|
||||
openssl-sys = { version = "0.9.103", optional = true }
|
||||
|
||||
[build-dependencies]
|
||||
bindgen = { version = "0.69", optional = true, default-features = false, features = ["runtime"] }
|
||||
bindgen = { version = "0.70", 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 }
|
||||
cc = { version = "1.1.6", optional = true }
|
||||
vcpkg = { version = "0.2.15", optional = true }
|
||||
# for loadable_extension:
|
||||
prettyplease = {version = "0.2", optional = true }
|
||||
prettyplease = {version = "0.2.20", optional = true }
|
||||
# like bindgen
|
||||
quote = { version = "1", optional = true, default-features = false }
|
||||
quote = { version = "1.0.36", optional = true, default-features = false }
|
||||
# like bindgen
|
||||
syn = { version = "2.0", optional = true, features = ["full", "extra-traits", "visit-mut"] }
|
||||
syn = { version = "2.0.72", optional = true, features = ["full", "extra-traits", "visit-mut"] }
|
||||
|
@ -1,32 +1,31 @@
|
||||
/* automatically generated by rust-bindgen 0.60.1 */
|
||||
/* automatically generated by rust-bindgen 0.69.4 */
|
||||
|
||||
extern "C" {
|
||||
pub fn sqlite3_auto_extension(
|
||||
xEntryPoint: ::std::option::Option<
|
||||
unsafe extern "C" fn(
|
||||
db: *mut sqlite3,
|
||||
pzErrMsg: *mut *const ::std::os::raw::c_char,
|
||||
pThunk: *const sqlite3_api_routines,
|
||||
pzErrMsg: *mut *mut ::std::os::raw::c_char,
|
||||
_: *const sqlite3_api_routines,
|
||||
) -> ::std::os::raw::c_int,
|
||||
>,
|
||||
) -> ::std::os::raw::c_int;
|
||||
}
|
||||
|
||||
extern "C" {
|
||||
pub fn sqlite3_cancel_auto_extension(
|
||||
xEntryPoint: ::std::option::Option<
|
||||
unsafe extern "C" fn(
|
||||
db: *mut sqlite3,
|
||||
pzErrMsg: *mut *const ::std::os::raw::c_char,
|
||||
pThunk: *const sqlite3_api_routines,
|
||||
pzErrMsg: *mut *mut ::std::os::raw::c_char,
|
||||
_: *const sqlite3_api_routines,
|
||||
) -> ::std::os::raw::c_int,
|
||||
>,
|
||||
) -> ::std::os::raw::c_int;
|
||||
}
|
||||
|
||||
pub const SQLITE_VERSION: &[u8; 7usize] = b"3.14.0\0";
|
||||
pub const SQLITE_VERSION: &[u8; 7] = b"3.14.0\0";
|
||||
pub const SQLITE_VERSION_NUMBER: i32 = 3014000;
|
||||
pub const SQLITE_SOURCE_ID: &[u8; 61usize] =
|
||||
pub const SQLITE_SOURCE_ID: &[u8; 61] =
|
||||
b"2016-08-08 13:40:27 d5e98057028abcf7217d0d2b2e29bbbcdf09d6de\0";
|
||||
pub const SQLITE_OK: i32 = 0;
|
||||
pub const SQLITE_ERROR: i32 = 1;
|
||||
@ -383,7 +382,6 @@ pub const SQLITE_SCANSTAT_SELECTID: i32 = 5;
|
||||
pub const NOT_WITHIN: i32 = 0;
|
||||
pub const PARTLY_WITHIN: i32 = 1;
|
||||
pub const FULLY_WITHIN: i32 = 2;
|
||||
pub const __SQLITESESSION_H_: i32 = 1;
|
||||
pub const SQLITE_CHANGESET_DATA: i32 = 1;
|
||||
pub const SQLITE_CHANGESET_NOTFOUND: i32 = 2;
|
||||
pub const SQLITE_CHANGESET_CONFLICT: i32 = 3;
|
||||
@ -398,7 +396,7 @@ pub const FTS5_TOKENIZE_DOCUMENT: i32 = 4;
|
||||
pub const FTS5_TOKENIZE_AUX: i32 = 8;
|
||||
pub const FTS5_TOKEN_COLOCATED: i32 = 1;
|
||||
extern "C" {
|
||||
pub static mut sqlite3_version: [::std::os::raw::c_char; 0usize];
|
||||
pub static sqlite3_version: [::std::os::raw::c_char; 0usize];
|
||||
}
|
||||
extern "C" {
|
||||
pub fn sqlite3_libversion() -> *const ::std::os::raw::c_char;
|
||||
@ -432,9 +430,6 @@ pub type sqlite3_uint64 = sqlite_uint64;
|
||||
extern "C" {
|
||||
pub fn sqlite3_close(arg1: *mut sqlite3) -> ::std::os::raw::c_int;
|
||||
}
|
||||
extern "C" {
|
||||
pub fn sqlite3_close_v2(arg1: *mut sqlite3) -> ::std::os::raw::c_int;
|
||||
}
|
||||
pub type sqlite3_callback = ::std::option::Option<
|
||||
unsafe extern "C" fn(
|
||||
arg1: *mut ::std::os::raw::c_void,
|
||||
@ -771,9 +766,6 @@ extern "C" {
|
||||
extern "C" {
|
||||
pub fn sqlite3_complete(sql: *const ::std::os::raw::c_char) -> ::std::os::raw::c_int;
|
||||
}
|
||||
extern "C" {
|
||||
pub fn sqlite3_complete16(sql: *const ::std::os::raw::c_void) -> ::std::os::raw::c_int;
|
||||
}
|
||||
extern "C" {
|
||||
pub fn sqlite3_busy_handler(
|
||||
arg1: *mut sqlite3,
|
||||
@ -922,12 +914,6 @@ extern "C" {
|
||||
ppDb: *mut *mut sqlite3,
|
||||
) -> ::std::os::raw::c_int;
|
||||
}
|
||||
extern "C" {
|
||||
pub fn sqlite3_open16(
|
||||
filename: *const ::std::os::raw::c_void,
|
||||
ppDb: *mut *mut sqlite3,
|
||||
) -> ::std::os::raw::c_int;
|
||||
}
|
||||
extern "C" {
|
||||
pub fn sqlite3_open_v2(
|
||||
filename: *const ::std::os::raw::c_char,
|
||||
@ -965,9 +951,6 @@ extern "C" {
|
||||
extern "C" {
|
||||
pub fn sqlite3_errmsg(arg1: *mut sqlite3) -> *const ::std::os::raw::c_char;
|
||||
}
|
||||
extern "C" {
|
||||
pub fn sqlite3_errmsg16(arg1: *mut sqlite3) -> *const ::std::os::raw::c_void;
|
||||
}
|
||||
extern "C" {
|
||||
pub fn sqlite3_errstr(arg1: ::std::os::raw::c_int) -> *const ::std::os::raw::c_char;
|
||||
}
|
||||
@ -983,15 +966,6 @@ extern "C" {
|
||||
newVal: ::std::os::raw::c_int,
|
||||
) -> ::std::os::raw::c_int;
|
||||
}
|
||||
extern "C" {
|
||||
pub fn sqlite3_prepare(
|
||||
db: *mut sqlite3,
|
||||
zSql: *const ::std::os::raw::c_char,
|
||||
nByte: ::std::os::raw::c_int,
|
||||
ppStmt: *mut *mut sqlite3_stmt,
|
||||
pzTail: *mut *const ::std::os::raw::c_char,
|
||||
) -> ::std::os::raw::c_int;
|
||||
}
|
||||
extern "C" {
|
||||
pub fn sqlite3_prepare_v2(
|
||||
db: *mut sqlite3,
|
||||
@ -1001,24 +975,6 @@ extern "C" {
|
||||
pzTail: *mut *const ::std::os::raw::c_char,
|
||||
) -> ::std::os::raw::c_int;
|
||||
}
|
||||
extern "C" {
|
||||
pub fn sqlite3_prepare16(
|
||||
db: *mut sqlite3,
|
||||
zSql: *const ::std::os::raw::c_void,
|
||||
nByte: ::std::os::raw::c_int,
|
||||
ppStmt: *mut *mut sqlite3_stmt,
|
||||
pzTail: *mut *const ::std::os::raw::c_void,
|
||||
) -> ::std::os::raw::c_int;
|
||||
}
|
||||
extern "C" {
|
||||
pub fn sqlite3_prepare16_v2(
|
||||
db: *mut sqlite3,
|
||||
zSql: *const ::std::os::raw::c_void,
|
||||
nByte: ::std::os::raw::c_int,
|
||||
ppStmt: *mut *mut sqlite3_stmt,
|
||||
pzTail: *mut *const ::std::os::raw::c_void,
|
||||
) -> ::std::os::raw::c_int;
|
||||
}
|
||||
extern "C" {
|
||||
pub fn sqlite3_sql(pStmt: *mut sqlite3_stmt) -> *const ::std::os::raw::c_char;
|
||||
}
|
||||
@ -1096,15 +1052,6 @@ extern "C" {
|
||||
arg5: ::std::option::Option<unsafe extern "C" fn(arg1: *mut ::std::os::raw::c_void)>,
|
||||
) -> ::std::os::raw::c_int;
|
||||
}
|
||||
extern "C" {
|
||||
pub fn sqlite3_bind_text16(
|
||||
arg1: *mut sqlite3_stmt,
|
||||
arg2: ::std::os::raw::c_int,
|
||||
arg3: *const ::std::os::raw::c_void,
|
||||
arg4: ::std::os::raw::c_int,
|
||||
arg5: ::std::option::Option<unsafe extern "C" fn(arg1: *mut ::std::os::raw::c_void)>,
|
||||
) -> ::std::os::raw::c_int;
|
||||
}
|
||||
extern "C" {
|
||||
pub fn sqlite3_bind_text64(
|
||||
arg1: *mut sqlite3_stmt,
|
||||
@ -1163,60 +1110,30 @@ extern "C" {
|
||||
N: ::std::os::raw::c_int,
|
||||
) -> *const ::std::os::raw::c_char;
|
||||
}
|
||||
extern "C" {
|
||||
pub fn sqlite3_column_name16(
|
||||
arg1: *mut sqlite3_stmt,
|
||||
N: ::std::os::raw::c_int,
|
||||
) -> *const ::std::os::raw::c_void;
|
||||
}
|
||||
extern "C" {
|
||||
pub fn sqlite3_column_database_name(
|
||||
arg1: *mut sqlite3_stmt,
|
||||
arg2: ::std::os::raw::c_int,
|
||||
) -> *const ::std::os::raw::c_char;
|
||||
}
|
||||
extern "C" {
|
||||
pub fn sqlite3_column_database_name16(
|
||||
arg1: *mut sqlite3_stmt,
|
||||
arg2: ::std::os::raw::c_int,
|
||||
) -> *const ::std::os::raw::c_void;
|
||||
}
|
||||
extern "C" {
|
||||
pub fn sqlite3_column_table_name(
|
||||
arg1: *mut sqlite3_stmt,
|
||||
arg2: ::std::os::raw::c_int,
|
||||
) -> *const ::std::os::raw::c_char;
|
||||
}
|
||||
extern "C" {
|
||||
pub fn sqlite3_column_table_name16(
|
||||
arg1: *mut sqlite3_stmt,
|
||||
arg2: ::std::os::raw::c_int,
|
||||
) -> *const ::std::os::raw::c_void;
|
||||
}
|
||||
extern "C" {
|
||||
pub fn sqlite3_column_origin_name(
|
||||
arg1: *mut sqlite3_stmt,
|
||||
arg2: ::std::os::raw::c_int,
|
||||
) -> *const ::std::os::raw::c_char;
|
||||
}
|
||||
extern "C" {
|
||||
pub fn sqlite3_column_origin_name16(
|
||||
arg1: *mut sqlite3_stmt,
|
||||
arg2: ::std::os::raw::c_int,
|
||||
) -> *const ::std::os::raw::c_void;
|
||||
}
|
||||
extern "C" {
|
||||
pub fn sqlite3_column_decltype(
|
||||
arg1: *mut sqlite3_stmt,
|
||||
arg2: ::std::os::raw::c_int,
|
||||
) -> *const ::std::os::raw::c_char;
|
||||
}
|
||||
extern "C" {
|
||||
pub fn sqlite3_column_decltype16(
|
||||
arg1: *mut sqlite3_stmt,
|
||||
arg2: ::std::os::raw::c_int,
|
||||
) -> *const ::std::os::raw::c_void;
|
||||
}
|
||||
extern "C" {
|
||||
pub fn sqlite3_step(arg1: *mut sqlite3_stmt) -> ::std::os::raw::c_int;
|
||||
}
|
||||
@ -1235,12 +1152,6 @@ extern "C" {
|
||||
iCol: ::std::os::raw::c_int,
|
||||
) -> ::std::os::raw::c_int;
|
||||
}
|
||||
extern "C" {
|
||||
pub fn sqlite3_column_bytes16(
|
||||
arg1: *mut sqlite3_stmt,
|
||||
iCol: ::std::os::raw::c_int,
|
||||
) -> ::std::os::raw::c_int;
|
||||
}
|
||||
extern "C" {
|
||||
pub fn sqlite3_column_double(arg1: *mut sqlite3_stmt, iCol: ::std::os::raw::c_int) -> f64;
|
||||
}
|
||||
@ -1262,12 +1173,6 @@ extern "C" {
|
||||
iCol: ::std::os::raw::c_int,
|
||||
) -> *const ::std::os::raw::c_uchar;
|
||||
}
|
||||
extern "C" {
|
||||
pub fn sqlite3_column_text16(
|
||||
arg1: *mut sqlite3_stmt,
|
||||
iCol: ::std::os::raw::c_int,
|
||||
) -> *const ::std::os::raw::c_void;
|
||||
}
|
||||
extern "C" {
|
||||
pub fn sqlite3_column_type(
|
||||
arg1: *mut sqlite3_stmt,
|
||||
@ -1286,54 +1191,6 @@ extern "C" {
|
||||
extern "C" {
|
||||
pub fn sqlite3_reset(pStmt: *mut sqlite3_stmt) -> ::std::os::raw::c_int;
|
||||
}
|
||||
extern "C" {
|
||||
pub fn sqlite3_create_function(
|
||||
db: *mut sqlite3,
|
||||
zFunctionName: *const ::std::os::raw::c_char,
|
||||
nArg: ::std::os::raw::c_int,
|
||||
eTextRep: ::std::os::raw::c_int,
|
||||
pApp: *mut ::std::os::raw::c_void,
|
||||
xFunc: ::std::option::Option<
|
||||
unsafe extern "C" fn(
|
||||
arg1: *mut sqlite3_context,
|
||||
arg2: ::std::os::raw::c_int,
|
||||
arg3: *mut *mut sqlite3_value,
|
||||
),
|
||||
>,
|
||||
xStep: ::std::option::Option<
|
||||
unsafe extern "C" fn(
|
||||
arg1: *mut sqlite3_context,
|
||||
arg2: ::std::os::raw::c_int,
|
||||
arg3: *mut *mut sqlite3_value,
|
||||
),
|
||||
>,
|
||||
xFinal: ::std::option::Option<unsafe extern "C" fn(arg1: *mut sqlite3_context)>,
|
||||
) -> ::std::os::raw::c_int;
|
||||
}
|
||||
extern "C" {
|
||||
pub fn sqlite3_create_function16(
|
||||
db: *mut sqlite3,
|
||||
zFunctionName: *const ::std::os::raw::c_void,
|
||||
nArg: ::std::os::raw::c_int,
|
||||
eTextRep: ::std::os::raw::c_int,
|
||||
pApp: *mut ::std::os::raw::c_void,
|
||||
xFunc: ::std::option::Option<
|
||||
unsafe extern "C" fn(
|
||||
arg1: *mut sqlite3_context,
|
||||
arg2: ::std::os::raw::c_int,
|
||||
arg3: *mut *mut sqlite3_value,
|
||||
),
|
||||
>,
|
||||
xStep: ::std::option::Option<
|
||||
unsafe extern "C" fn(
|
||||
arg1: *mut sqlite3_context,
|
||||
arg2: ::std::os::raw::c_int,
|
||||
arg3: *mut *mut sqlite3_value,
|
||||
),
|
||||
>,
|
||||
xFinal: ::std::option::Option<unsafe extern "C" fn(arg1: *mut sqlite3_context)>,
|
||||
) -> ::std::os::raw::c_int;
|
||||
}
|
||||
extern "C" {
|
||||
pub fn sqlite3_create_function_v2(
|
||||
db: *mut sqlite3,
|
||||
@ -1396,9 +1253,6 @@ extern "C" {
|
||||
extern "C" {
|
||||
pub fn sqlite3_value_bytes(arg1: *mut sqlite3_value) -> ::std::os::raw::c_int;
|
||||
}
|
||||
extern "C" {
|
||||
pub fn sqlite3_value_bytes16(arg1: *mut sqlite3_value) -> ::std::os::raw::c_int;
|
||||
}
|
||||
extern "C" {
|
||||
pub fn sqlite3_value_double(arg1: *mut sqlite3_value) -> f64;
|
||||
}
|
||||
@ -1411,15 +1265,6 @@ extern "C" {
|
||||
extern "C" {
|
||||
pub fn sqlite3_value_text(arg1: *mut sqlite3_value) -> *const ::std::os::raw::c_uchar;
|
||||
}
|
||||
extern "C" {
|
||||
pub fn sqlite3_value_text16(arg1: *mut sqlite3_value) -> *const ::std::os::raw::c_void;
|
||||
}
|
||||
extern "C" {
|
||||
pub fn sqlite3_value_text16le(arg1: *mut sqlite3_value) -> *const ::std::os::raw::c_void;
|
||||
}
|
||||
extern "C" {
|
||||
pub fn sqlite3_value_text16be(arg1: *mut sqlite3_value) -> *const ::std::os::raw::c_void;
|
||||
}
|
||||
extern "C" {
|
||||
pub fn sqlite3_value_type(arg1: *mut sqlite3_value) -> ::std::os::raw::c_int;
|
||||
}
|
||||
@ -1489,13 +1334,6 @@ extern "C" {
|
||||
arg3: ::std::os::raw::c_int,
|
||||
);
|
||||
}
|
||||
extern "C" {
|
||||
pub fn sqlite3_result_error16(
|
||||
arg1: *mut sqlite3_context,
|
||||
arg2: *const ::std::os::raw::c_void,
|
||||
arg3: ::std::os::raw::c_int,
|
||||
);
|
||||
}
|
||||
extern "C" {
|
||||
pub fn sqlite3_result_error_toobig(arg1: *mut sqlite3_context);
|
||||
}
|
||||
@ -1531,30 +1369,6 @@ extern "C" {
|
||||
encoding: ::std::os::raw::c_uchar,
|
||||
);
|
||||
}
|
||||
extern "C" {
|
||||
pub fn sqlite3_result_text16(
|
||||
arg1: *mut sqlite3_context,
|
||||
arg2: *const ::std::os::raw::c_void,
|
||||
arg3: ::std::os::raw::c_int,
|
||||
arg4: ::std::option::Option<unsafe extern "C" fn(arg1: *mut ::std::os::raw::c_void)>,
|
||||
);
|
||||
}
|
||||
extern "C" {
|
||||
pub fn sqlite3_result_text16le(
|
||||
arg1: *mut sqlite3_context,
|
||||
arg2: *const ::std::os::raw::c_void,
|
||||
arg3: ::std::os::raw::c_int,
|
||||
arg4: ::std::option::Option<unsafe extern "C" fn(arg1: *mut ::std::os::raw::c_void)>,
|
||||
);
|
||||
}
|
||||
extern "C" {
|
||||
pub fn sqlite3_result_text16be(
|
||||
arg1: *mut sqlite3_context,
|
||||
arg2: *const ::std::os::raw::c_void,
|
||||
arg3: ::std::os::raw::c_int,
|
||||
arg4: ::std::option::Option<unsafe extern "C" fn(arg1: *mut ::std::os::raw::c_void)>,
|
||||
);
|
||||
}
|
||||
extern "C" {
|
||||
pub fn sqlite3_result_value(arg1: *mut sqlite3_context, arg2: *mut sqlite3_value);
|
||||
}
|
||||
@ -1570,23 +1384,6 @@ extern "C" {
|
||||
extern "C" {
|
||||
pub fn sqlite3_result_subtype(arg1: *mut sqlite3_context, arg2: ::std::os::raw::c_uint);
|
||||
}
|
||||
extern "C" {
|
||||
pub fn sqlite3_create_collation(
|
||||
arg1: *mut sqlite3,
|
||||
zName: *const ::std::os::raw::c_char,
|
||||
eTextRep: ::std::os::raw::c_int,
|
||||
pArg: *mut ::std::os::raw::c_void,
|
||||
xCompare: ::std::option::Option<
|
||||
unsafe extern "C" fn(
|
||||
arg1: *mut ::std::os::raw::c_void,
|
||||
arg2: ::std::os::raw::c_int,
|
||||
arg3: *const ::std::os::raw::c_void,
|
||||
arg4: ::std::os::raw::c_int,
|
||||
arg5: *const ::std::os::raw::c_void,
|
||||
) -> ::std::os::raw::c_int,
|
||||
>,
|
||||
) -> ::std::os::raw::c_int;
|
||||
}
|
||||
extern "C" {
|
||||
pub fn sqlite3_create_collation_v2(
|
||||
arg1: *mut sqlite3,
|
||||
@ -1605,23 +1402,6 @@ extern "C" {
|
||||
xDestroy: ::std::option::Option<unsafe extern "C" fn(arg1: *mut ::std::os::raw::c_void)>,
|
||||
) -> ::std::os::raw::c_int;
|
||||
}
|
||||
extern "C" {
|
||||
pub fn sqlite3_create_collation16(
|
||||
arg1: *mut sqlite3,
|
||||
zName: *const ::std::os::raw::c_void,
|
||||
eTextRep: ::std::os::raw::c_int,
|
||||
pArg: *mut ::std::os::raw::c_void,
|
||||
xCompare: ::std::option::Option<
|
||||
unsafe extern "C" fn(
|
||||
arg1: *mut ::std::os::raw::c_void,
|
||||
arg2: ::std::os::raw::c_int,
|
||||
arg3: *const ::std::os::raw::c_void,
|
||||
arg4: ::std::os::raw::c_int,
|
||||
arg5: *const ::std::os::raw::c_void,
|
||||
) -> ::std::os::raw::c_int,
|
||||
>,
|
||||
) -> ::std::os::raw::c_int;
|
||||
}
|
||||
extern "C" {
|
||||
pub fn sqlite3_collation_needed(
|
||||
arg1: *mut sqlite3,
|
||||
@ -1636,20 +1416,6 @@ extern "C" {
|
||||
>,
|
||||
) -> ::std::os::raw::c_int;
|
||||
}
|
||||
extern "C" {
|
||||
pub fn sqlite3_collation_needed16(
|
||||
arg1: *mut sqlite3,
|
||||
arg2: *mut ::std::os::raw::c_void,
|
||||
arg3: ::std::option::Option<
|
||||
unsafe extern "C" fn(
|
||||
arg1: *mut ::std::os::raw::c_void,
|
||||
arg2: *mut sqlite3,
|
||||
eTextRep: ::std::os::raw::c_int,
|
||||
arg3: *const ::std::os::raw::c_void,
|
||||
),
|
||||
>,
|
||||
) -> ::std::os::raw::c_int;
|
||||
}
|
||||
extern "C" {
|
||||
pub fn sqlite3_sleep(arg1: ::std::os::raw::c_int) -> ::std::os::raw::c_int;
|
||||
}
|
||||
@ -1926,14 +1692,6 @@ pub struct sqlite3_index_constraint_usage {
|
||||
pub argvIndex: ::std::os::raw::c_int,
|
||||
pub omit: ::std::os::raw::c_uchar,
|
||||
}
|
||||
extern "C" {
|
||||
pub fn sqlite3_create_module(
|
||||
db: *mut sqlite3,
|
||||
zName: *const ::std::os::raw::c_char,
|
||||
p: *const sqlite3_module,
|
||||
pClientData: *mut ::std::os::raw::c_void,
|
||||
) -> ::std::os::raw::c_int;
|
||||
}
|
||||
extern "C" {
|
||||
pub fn sqlite3_create_module_v2(
|
||||
db: *mut sqlite3,
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* automatically generated by rust-bindgen 0.69.1 */
|
||||
/* automatically generated by rust-bindgen 0.69.4 */
|
||||
|
||||
pub const SQLITE_VERSION: &[u8; 7] = b"3.14.0\0";
|
||||
pub const SQLITE_VERSION_NUMBER: i32 = 3014000;
|
||||
@ -2673,30 +2673,6 @@ pub unsafe fn sqlite3_bind_text(
|
||||
(fun)(arg1, arg2, arg3, n, arg4)
|
||||
}
|
||||
|
||||
static __SQLITE3_BIND_TEXT16: ::std::sync::atomic::AtomicPtr<()> = ::std::sync::atomic::AtomicPtr::new(
|
||||
::std::ptr::null_mut(),
|
||||
);
|
||||
pub unsafe fn sqlite3_bind_text16(
|
||||
arg1: *mut sqlite3_stmt,
|
||||
arg2: ::std::os::raw::c_int,
|
||||
arg3: *const ::std::os::raw::c_void,
|
||||
arg4: ::std::os::raw::c_int,
|
||||
arg5: ::std::option::Option<unsafe extern "C" fn(arg1: *mut ::std::os::raw::c_void)>,
|
||||
) -> ::std::os::raw::c_int {
|
||||
let ptr = __SQLITE3_BIND_TEXT16.load(::std::sync::atomic::Ordering::Acquire);
|
||||
assert!(! ptr.is_null(), "SQLite API not initialized or SQLite feature omitted");
|
||||
let fun: unsafe extern "C" fn(
|
||||
arg1: *mut sqlite3_stmt,
|
||||
arg2: ::std::os::raw::c_int,
|
||||
arg3: *const ::std::os::raw::c_void,
|
||||
arg4: ::std::os::raw::c_int,
|
||||
arg5: ::std::option::Option<
|
||||
unsafe extern "C" fn(arg1: *mut ::std::os::raw::c_void),
|
||||
>,
|
||||
) -> ::std::os::raw::c_int = ::std::mem::transmute(ptr);
|
||||
(fun)(arg1, arg2, arg3, arg4, arg5)
|
||||
}
|
||||
|
||||
static __SQLITE3_BIND_VALUE: ::std::sync::atomic::AtomicPtr<()> = ::std::sync::atomic::AtomicPtr::new(
|
||||
::std::ptr::null_mut(),
|
||||
);
|
||||
@ -2815,38 +2791,6 @@ pub unsafe fn sqlite3_collation_needed(
|
||||
(fun)(arg1, arg2, arg3)
|
||||
}
|
||||
|
||||
static __SQLITE3_COLLATION_NEEDED16: ::std::sync::atomic::AtomicPtr<()> = ::std::sync::atomic::AtomicPtr::new(
|
||||
::std::ptr::null_mut(),
|
||||
);
|
||||
pub unsafe fn sqlite3_collation_needed16(
|
||||
arg1: *mut sqlite3,
|
||||
arg2: *mut ::std::os::raw::c_void,
|
||||
arg3: ::std::option::Option<
|
||||
unsafe extern "C" fn(
|
||||
arg1: *mut ::std::os::raw::c_void,
|
||||
arg2: *mut sqlite3,
|
||||
eTextRep: ::std::os::raw::c_int,
|
||||
arg3: *const ::std::os::raw::c_void,
|
||||
),
|
||||
>,
|
||||
) -> ::std::os::raw::c_int {
|
||||
let ptr = __SQLITE3_COLLATION_NEEDED16.load(::std::sync::atomic::Ordering::Acquire);
|
||||
assert!(! ptr.is_null(), "SQLite API not initialized or SQLite feature omitted");
|
||||
let fun: unsafe extern "C" fn(
|
||||
arg1: *mut sqlite3,
|
||||
arg2: *mut ::std::os::raw::c_void,
|
||||
arg3: ::std::option::Option<
|
||||
unsafe extern "C" fn(
|
||||
arg1: *mut ::std::os::raw::c_void,
|
||||
arg2: *mut sqlite3,
|
||||
eTextRep: ::std::os::raw::c_int,
|
||||
arg3: *const ::std::os::raw::c_void,
|
||||
),
|
||||
>,
|
||||
) -> ::std::os::raw::c_int = ::std::mem::transmute(ptr);
|
||||
(fun)(arg1, arg2, arg3)
|
||||
}
|
||||
|
||||
static __SQLITE3_COLUMN_BLOB: ::std::sync::atomic::AtomicPtr<()> = ::std::sync::atomic::AtomicPtr::new(
|
||||
::std::ptr::null_mut(),
|
||||
);
|
||||
@ -2879,22 +2823,6 @@ pub unsafe fn sqlite3_column_bytes(
|
||||
(fun)(arg1, iCol)
|
||||
}
|
||||
|
||||
static __SQLITE3_COLUMN_BYTES16: ::std::sync::atomic::AtomicPtr<()> = ::std::sync::atomic::AtomicPtr::new(
|
||||
::std::ptr::null_mut(),
|
||||
);
|
||||
pub unsafe fn sqlite3_column_bytes16(
|
||||
arg1: *mut sqlite3_stmt,
|
||||
iCol: ::std::os::raw::c_int,
|
||||
) -> ::std::os::raw::c_int {
|
||||
let ptr = __SQLITE3_COLUMN_BYTES16.load(::std::sync::atomic::Ordering::Acquire);
|
||||
assert!(! ptr.is_null(), "SQLite API not initialized or SQLite feature omitted");
|
||||
let fun: unsafe extern "C" fn(
|
||||
arg1: *mut sqlite3_stmt,
|
||||
iCol: ::std::os::raw::c_int,
|
||||
) -> ::std::os::raw::c_int = ::std::mem::transmute(ptr);
|
||||
(fun)(arg1, iCol)
|
||||
}
|
||||
|
||||
static __SQLITE3_COLUMN_COUNT: ::std::sync::atomic::AtomicPtr<()> = ::std::sync::atomic::AtomicPtr::new(
|
||||
::std::ptr::null_mut(),
|
||||
);
|
||||
@ -2924,23 +2852,6 @@ pub unsafe fn sqlite3_column_database_name(
|
||||
(fun)(arg1, arg2)
|
||||
}
|
||||
|
||||
static __SQLITE3_COLUMN_DATABASE_NAME16: ::std::sync::atomic::AtomicPtr<()> = ::std::sync::atomic::AtomicPtr::new(
|
||||
::std::ptr::null_mut(),
|
||||
);
|
||||
pub unsafe fn sqlite3_column_database_name16(
|
||||
arg1: *mut sqlite3_stmt,
|
||||
arg2: ::std::os::raw::c_int,
|
||||
) -> *const ::std::os::raw::c_void {
|
||||
let ptr = __SQLITE3_COLUMN_DATABASE_NAME16
|
||||
.load(::std::sync::atomic::Ordering::Acquire);
|
||||
assert!(! ptr.is_null(), "SQLite API not initialized or SQLite feature omitted");
|
||||
let fun: unsafe extern "C" fn(
|
||||
arg1: *mut sqlite3_stmt,
|
||||
arg2: ::std::os::raw::c_int,
|
||||
) -> *const ::std::os::raw::c_void = ::std::mem::transmute(ptr);
|
||||
(fun)(arg1, arg2)
|
||||
}
|
||||
|
||||
static __SQLITE3_COLUMN_DECLTYPE: ::std::sync::atomic::AtomicPtr<()> = ::std::sync::atomic::AtomicPtr::new(
|
||||
::std::ptr::null_mut(),
|
||||
);
|
||||
@ -2957,22 +2868,6 @@ pub unsafe fn sqlite3_column_decltype(
|
||||
(fun)(arg1, i)
|
||||
}
|
||||
|
||||
static __SQLITE3_COLUMN_DECLTYPE16: ::std::sync::atomic::AtomicPtr<()> = ::std::sync::atomic::AtomicPtr::new(
|
||||
::std::ptr::null_mut(),
|
||||
);
|
||||
pub unsafe fn sqlite3_column_decltype16(
|
||||
arg1: *mut sqlite3_stmt,
|
||||
arg2: ::std::os::raw::c_int,
|
||||
) -> *const ::std::os::raw::c_void {
|
||||
let ptr = __SQLITE3_COLUMN_DECLTYPE16.load(::std::sync::atomic::Ordering::Acquire);
|
||||
assert!(! ptr.is_null(), "SQLite API not initialized or SQLite feature omitted");
|
||||
let fun: unsafe extern "C" fn(
|
||||
arg1: *mut sqlite3_stmt,
|
||||
arg2: ::std::os::raw::c_int,
|
||||
) -> *const ::std::os::raw::c_void = ::std::mem::transmute(ptr);
|
||||
(fun)(arg1, arg2)
|
||||
}
|
||||
|
||||
static __SQLITE3_COLUMN_DOUBLE: ::std::sync::atomic::AtomicPtr<()> = ::std::sync::atomic::AtomicPtr::new(
|
||||
::std::ptr::null_mut(),
|
||||
);
|
||||
@ -3037,22 +2932,6 @@ pub unsafe fn sqlite3_column_name(
|
||||
(fun)(arg1, arg2)
|
||||
}
|
||||
|
||||
static __SQLITE3_COLUMN_NAME16: ::std::sync::atomic::AtomicPtr<()> = ::std::sync::atomic::AtomicPtr::new(
|
||||
::std::ptr::null_mut(),
|
||||
);
|
||||
pub unsafe fn sqlite3_column_name16(
|
||||
arg1: *mut sqlite3_stmt,
|
||||
arg2: ::std::os::raw::c_int,
|
||||
) -> *const ::std::os::raw::c_void {
|
||||
let ptr = __SQLITE3_COLUMN_NAME16.load(::std::sync::atomic::Ordering::Acquire);
|
||||
assert!(! ptr.is_null(), "SQLite API not initialized or SQLite feature omitted");
|
||||
let fun: unsafe extern "C" fn(
|
||||
arg1: *mut sqlite3_stmt,
|
||||
arg2: ::std::os::raw::c_int,
|
||||
) -> *const ::std::os::raw::c_void = ::std::mem::transmute(ptr);
|
||||
(fun)(arg1, arg2)
|
||||
}
|
||||
|
||||
static __SQLITE3_COLUMN_ORIGIN_NAME: ::std::sync::atomic::AtomicPtr<()> = ::std::sync::atomic::AtomicPtr::new(
|
||||
::std::ptr::null_mut(),
|
||||
);
|
||||
@ -3069,23 +2948,6 @@ pub unsafe fn sqlite3_column_origin_name(
|
||||
(fun)(arg1, arg2)
|
||||
}
|
||||
|
||||
static __SQLITE3_COLUMN_ORIGIN_NAME16: ::std::sync::atomic::AtomicPtr<()> = ::std::sync::atomic::AtomicPtr::new(
|
||||
::std::ptr::null_mut(),
|
||||
);
|
||||
pub unsafe fn sqlite3_column_origin_name16(
|
||||
arg1: *mut sqlite3_stmt,
|
||||
arg2: ::std::os::raw::c_int,
|
||||
) -> *const ::std::os::raw::c_void {
|
||||
let ptr = __SQLITE3_COLUMN_ORIGIN_NAME16
|
||||
.load(::std::sync::atomic::Ordering::Acquire);
|
||||
assert!(! ptr.is_null(), "SQLite API not initialized or SQLite feature omitted");
|
||||
let fun: unsafe extern "C" fn(
|
||||
arg1: *mut sqlite3_stmt,
|
||||
arg2: ::std::os::raw::c_int,
|
||||
) -> *const ::std::os::raw::c_void = ::std::mem::transmute(ptr);
|
||||
(fun)(arg1, arg2)
|
||||
}
|
||||
|
||||
static __SQLITE3_COLUMN_TABLE_NAME: ::std::sync::atomic::AtomicPtr<()> = ::std::sync::atomic::AtomicPtr::new(
|
||||
::std::ptr::null_mut(),
|
||||
);
|
||||
@ -3102,22 +2964,6 @@ pub unsafe fn sqlite3_column_table_name(
|
||||
(fun)(arg1, arg2)
|
||||
}
|
||||
|
||||
static __SQLITE3_COLUMN_TABLE_NAME16: ::std::sync::atomic::AtomicPtr<()> = ::std::sync::atomic::AtomicPtr::new(
|
||||
::std::ptr::null_mut(),
|
||||
);
|
||||
pub unsafe fn sqlite3_column_table_name16(
|
||||
arg1: *mut sqlite3_stmt,
|
||||
arg2: ::std::os::raw::c_int,
|
||||
) -> *const ::std::os::raw::c_void {
|
||||
let ptr = __SQLITE3_COLUMN_TABLE_NAME16.load(::std::sync::atomic::Ordering::Acquire);
|
||||
assert!(! ptr.is_null(), "SQLite API not initialized or SQLite feature omitted");
|
||||
let fun: unsafe extern "C" fn(
|
||||
arg1: *mut sqlite3_stmt,
|
||||
arg2: ::std::os::raw::c_int,
|
||||
) -> *const ::std::os::raw::c_void = ::std::mem::transmute(ptr);
|
||||
(fun)(arg1, arg2)
|
||||
}
|
||||
|
||||
static __SQLITE3_COLUMN_TEXT: ::std::sync::atomic::AtomicPtr<()> = ::std::sync::atomic::AtomicPtr::new(
|
||||
::std::ptr::null_mut(),
|
||||
);
|
||||
@ -3134,22 +2980,6 @@ pub unsafe fn sqlite3_column_text(
|
||||
(fun)(arg1, iCol)
|
||||
}
|
||||
|
||||
static __SQLITE3_COLUMN_TEXT16: ::std::sync::atomic::AtomicPtr<()> = ::std::sync::atomic::AtomicPtr::new(
|
||||
::std::ptr::null_mut(),
|
||||
);
|
||||
pub unsafe fn sqlite3_column_text16(
|
||||
arg1: *mut sqlite3_stmt,
|
||||
iCol: ::std::os::raw::c_int,
|
||||
) -> *const ::std::os::raw::c_void {
|
||||
let ptr = __SQLITE3_COLUMN_TEXT16.load(::std::sync::atomic::Ordering::Acquire);
|
||||
assert!(! ptr.is_null(), "SQLite API not initialized or SQLite feature omitted");
|
||||
let fun: unsafe extern "C" fn(
|
||||
arg1: *mut sqlite3_stmt,
|
||||
iCol: ::std::os::raw::c_int,
|
||||
) -> *const ::std::os::raw::c_void = ::std::mem::transmute(ptr);
|
||||
(fun)(arg1, iCol)
|
||||
}
|
||||
|
||||
static __SQLITE3_COLUMN_TYPE: ::std::sync::atomic::AtomicPtr<()> = ::std::sync::atomic::AtomicPtr::new(
|
||||
::std::ptr::null_mut(),
|
||||
);
|
||||
@ -3220,220 +3050,6 @@ pub unsafe fn sqlite3_complete(
|
||||
(fun)(sql)
|
||||
}
|
||||
|
||||
static __SQLITE3_COMPLETE16: ::std::sync::atomic::AtomicPtr<()> = ::std::sync::atomic::AtomicPtr::new(
|
||||
::std::ptr::null_mut(),
|
||||
);
|
||||
pub unsafe fn sqlite3_complete16(
|
||||
sql: *const ::std::os::raw::c_void,
|
||||
) -> ::std::os::raw::c_int {
|
||||
let ptr = __SQLITE3_COMPLETE16.load(::std::sync::atomic::Ordering::Acquire);
|
||||
assert!(! ptr.is_null(), "SQLite API not initialized or SQLite feature omitted");
|
||||
let fun: unsafe extern "C" fn(
|
||||
sql: *const ::std::os::raw::c_void,
|
||||
) -> ::std::os::raw::c_int = ::std::mem::transmute(ptr);
|
||||
(fun)(sql)
|
||||
}
|
||||
|
||||
static __SQLITE3_CREATE_COLLATION: ::std::sync::atomic::AtomicPtr<()> = ::std::sync::atomic::AtomicPtr::new(
|
||||
::std::ptr::null_mut(),
|
||||
);
|
||||
pub unsafe fn sqlite3_create_collation(
|
||||
arg1: *mut sqlite3,
|
||||
arg2: *const ::std::os::raw::c_char,
|
||||
arg3: ::std::os::raw::c_int,
|
||||
arg4: *mut ::std::os::raw::c_void,
|
||||
arg5: ::std::option::Option<
|
||||
unsafe extern "C" fn(
|
||||
arg1: *mut ::std::os::raw::c_void,
|
||||
arg2: ::std::os::raw::c_int,
|
||||
arg3: *const ::std::os::raw::c_void,
|
||||
arg4: ::std::os::raw::c_int,
|
||||
arg5: *const ::std::os::raw::c_void,
|
||||
) -> ::std::os::raw::c_int,
|
||||
>,
|
||||
) -> ::std::os::raw::c_int {
|
||||
let ptr = __SQLITE3_CREATE_COLLATION.load(::std::sync::atomic::Ordering::Acquire);
|
||||
assert!(! ptr.is_null(), "SQLite API not initialized or SQLite feature omitted");
|
||||
let fun: unsafe extern "C" fn(
|
||||
arg1: *mut sqlite3,
|
||||
arg2: *const ::std::os::raw::c_char,
|
||||
arg3: ::std::os::raw::c_int,
|
||||
arg4: *mut ::std::os::raw::c_void,
|
||||
arg5: ::std::option::Option<
|
||||
unsafe extern "C" fn(
|
||||
arg1: *mut ::std::os::raw::c_void,
|
||||
arg2: ::std::os::raw::c_int,
|
||||
arg3: *const ::std::os::raw::c_void,
|
||||
arg4: ::std::os::raw::c_int,
|
||||
arg5: *const ::std::os::raw::c_void,
|
||||
) -> ::std::os::raw::c_int,
|
||||
>,
|
||||
) -> ::std::os::raw::c_int = ::std::mem::transmute(ptr);
|
||||
(fun)(arg1, arg2, arg3, arg4, arg5)
|
||||
}
|
||||
|
||||
static __SQLITE3_CREATE_COLLATION16: ::std::sync::atomic::AtomicPtr<()> = ::std::sync::atomic::AtomicPtr::new(
|
||||
::std::ptr::null_mut(),
|
||||
);
|
||||
pub unsafe fn sqlite3_create_collation16(
|
||||
arg1: *mut sqlite3,
|
||||
arg2: *const ::std::os::raw::c_void,
|
||||
arg3: ::std::os::raw::c_int,
|
||||
arg4: *mut ::std::os::raw::c_void,
|
||||
arg5: ::std::option::Option<
|
||||
unsafe extern "C" fn(
|
||||
arg1: *mut ::std::os::raw::c_void,
|
||||
arg2: ::std::os::raw::c_int,
|
||||
arg3: *const ::std::os::raw::c_void,
|
||||
arg4: ::std::os::raw::c_int,
|
||||
arg5: *const ::std::os::raw::c_void,
|
||||
) -> ::std::os::raw::c_int,
|
||||
>,
|
||||
) -> ::std::os::raw::c_int {
|
||||
let ptr = __SQLITE3_CREATE_COLLATION16.load(::std::sync::atomic::Ordering::Acquire);
|
||||
assert!(! ptr.is_null(), "SQLite API not initialized or SQLite feature omitted");
|
||||
let fun: unsafe extern "C" fn(
|
||||
arg1: *mut sqlite3,
|
||||
arg2: *const ::std::os::raw::c_void,
|
||||
arg3: ::std::os::raw::c_int,
|
||||
arg4: *mut ::std::os::raw::c_void,
|
||||
arg5: ::std::option::Option<
|
||||
unsafe extern "C" fn(
|
||||
arg1: *mut ::std::os::raw::c_void,
|
||||
arg2: ::std::os::raw::c_int,
|
||||
arg3: *const ::std::os::raw::c_void,
|
||||
arg4: ::std::os::raw::c_int,
|
||||
arg5: *const ::std::os::raw::c_void,
|
||||
) -> ::std::os::raw::c_int,
|
||||
>,
|
||||
) -> ::std::os::raw::c_int = ::std::mem::transmute(ptr);
|
||||
(fun)(arg1, arg2, arg3, arg4, arg5)
|
||||
}
|
||||
|
||||
static __SQLITE3_CREATE_FUNCTION: ::std::sync::atomic::AtomicPtr<()> = ::std::sync::atomic::AtomicPtr::new(
|
||||
::std::ptr::null_mut(),
|
||||
);
|
||||
pub unsafe fn sqlite3_create_function(
|
||||
arg1: *mut sqlite3,
|
||||
arg2: *const ::std::os::raw::c_char,
|
||||
arg3: ::std::os::raw::c_int,
|
||||
arg4: ::std::os::raw::c_int,
|
||||
arg5: *mut ::std::os::raw::c_void,
|
||||
xFunc: ::std::option::Option<
|
||||
unsafe extern "C" fn(
|
||||
arg1: *mut sqlite3_context,
|
||||
arg2: ::std::os::raw::c_int,
|
||||
arg3: *mut *mut sqlite3_value,
|
||||
),
|
||||
>,
|
||||
xStep: ::std::option::Option<
|
||||
unsafe extern "C" fn(
|
||||
arg1: *mut sqlite3_context,
|
||||
arg2: ::std::os::raw::c_int,
|
||||
arg3: *mut *mut sqlite3_value,
|
||||
),
|
||||
>,
|
||||
xFinal: ::std::option::Option<unsafe extern "C" fn(arg1: *mut sqlite3_context)>,
|
||||
) -> ::std::os::raw::c_int {
|
||||
let ptr = __SQLITE3_CREATE_FUNCTION.load(::std::sync::atomic::Ordering::Acquire);
|
||||
assert!(! ptr.is_null(), "SQLite API not initialized or SQLite feature omitted");
|
||||
let fun: unsafe extern "C" fn(
|
||||
arg1: *mut sqlite3,
|
||||
arg2: *const ::std::os::raw::c_char,
|
||||
arg3: ::std::os::raw::c_int,
|
||||
arg4: ::std::os::raw::c_int,
|
||||
arg5: *mut ::std::os::raw::c_void,
|
||||
xFunc: ::std::option::Option<
|
||||
unsafe extern "C" fn(
|
||||
arg1: *mut sqlite3_context,
|
||||
arg2: ::std::os::raw::c_int,
|
||||
arg3: *mut *mut sqlite3_value,
|
||||
),
|
||||
>,
|
||||
xStep: ::std::option::Option<
|
||||
unsafe extern "C" fn(
|
||||
arg1: *mut sqlite3_context,
|
||||
arg2: ::std::os::raw::c_int,
|
||||
arg3: *mut *mut sqlite3_value,
|
||||
),
|
||||
>,
|
||||
xFinal: ::std::option::Option<unsafe extern "C" fn(arg1: *mut sqlite3_context)>,
|
||||
) -> ::std::os::raw::c_int = ::std::mem::transmute(ptr);
|
||||
(fun)(arg1, arg2, arg3, arg4, arg5, xFunc, xStep, xFinal)
|
||||
}
|
||||
|
||||
static __SQLITE3_CREATE_FUNCTION16: ::std::sync::atomic::AtomicPtr<()> = ::std::sync::atomic::AtomicPtr::new(
|
||||
::std::ptr::null_mut(),
|
||||
);
|
||||
pub unsafe fn sqlite3_create_function16(
|
||||
arg1: *mut sqlite3,
|
||||
arg2: *const ::std::os::raw::c_void,
|
||||
arg3: ::std::os::raw::c_int,
|
||||
arg4: ::std::os::raw::c_int,
|
||||
arg5: *mut ::std::os::raw::c_void,
|
||||
xFunc: ::std::option::Option<
|
||||
unsafe extern "C" fn(
|
||||
arg1: *mut sqlite3_context,
|
||||
arg2: ::std::os::raw::c_int,
|
||||
arg3: *mut *mut sqlite3_value,
|
||||
),
|
||||
>,
|
||||
xStep: ::std::option::Option<
|
||||
unsafe extern "C" fn(
|
||||
arg1: *mut sqlite3_context,
|
||||
arg2: ::std::os::raw::c_int,
|
||||
arg3: *mut *mut sqlite3_value,
|
||||
),
|
||||
>,
|
||||
xFinal: ::std::option::Option<unsafe extern "C" fn(arg1: *mut sqlite3_context)>,
|
||||
) -> ::std::os::raw::c_int {
|
||||
let ptr = __SQLITE3_CREATE_FUNCTION16.load(::std::sync::atomic::Ordering::Acquire);
|
||||
assert!(! ptr.is_null(), "SQLite API not initialized or SQLite feature omitted");
|
||||
let fun: unsafe extern "C" fn(
|
||||
arg1: *mut sqlite3,
|
||||
arg2: *const ::std::os::raw::c_void,
|
||||
arg3: ::std::os::raw::c_int,
|
||||
arg4: ::std::os::raw::c_int,
|
||||
arg5: *mut ::std::os::raw::c_void,
|
||||
xFunc: ::std::option::Option<
|
||||
unsafe extern "C" fn(
|
||||
arg1: *mut sqlite3_context,
|
||||
arg2: ::std::os::raw::c_int,
|
||||
arg3: *mut *mut sqlite3_value,
|
||||
),
|
||||
>,
|
||||
xStep: ::std::option::Option<
|
||||
unsafe extern "C" fn(
|
||||
arg1: *mut sqlite3_context,
|
||||
arg2: ::std::os::raw::c_int,
|
||||
arg3: *mut *mut sqlite3_value,
|
||||
),
|
||||
>,
|
||||
xFinal: ::std::option::Option<unsafe extern "C" fn(arg1: *mut sqlite3_context)>,
|
||||
) -> ::std::os::raw::c_int = ::std::mem::transmute(ptr);
|
||||
(fun)(arg1, arg2, arg3, arg4, arg5, xFunc, xStep, xFinal)
|
||||
}
|
||||
|
||||
static __SQLITE3_CREATE_MODULE: ::std::sync::atomic::AtomicPtr<()> = ::std::sync::atomic::AtomicPtr::new(
|
||||
::std::ptr::null_mut(),
|
||||
);
|
||||
pub unsafe fn sqlite3_create_module(
|
||||
arg1: *mut sqlite3,
|
||||
arg2: *const ::std::os::raw::c_char,
|
||||
arg3: *const sqlite3_module,
|
||||
arg4: *mut ::std::os::raw::c_void,
|
||||
) -> ::std::os::raw::c_int {
|
||||
let ptr = __SQLITE3_CREATE_MODULE.load(::std::sync::atomic::Ordering::Acquire);
|
||||
assert!(! ptr.is_null(), "SQLite API not initialized or SQLite feature omitted");
|
||||
let fun: unsafe extern "C" fn(
|
||||
arg1: *mut sqlite3,
|
||||
arg2: *const ::std::os::raw::c_char,
|
||||
arg3: *const sqlite3_module,
|
||||
arg4: *mut ::std::os::raw::c_void,
|
||||
) -> ::std::os::raw::c_int = ::std::mem::transmute(ptr);
|
||||
(fun)(arg1, arg2, arg3, arg4)
|
||||
}
|
||||
|
||||
static __SQLITE3_DATA_COUNT: ::std::sync::atomic::AtomicPtr<()> = ::std::sync::atomic::AtomicPtr::new(
|
||||
::std::ptr::null_mut(),
|
||||
);
|
||||
@ -3512,18 +3128,6 @@ pub unsafe fn sqlite3_errmsg(arg1: *mut sqlite3) -> *const ::std::os::raw::c_cha
|
||||
(fun)(arg1)
|
||||
}
|
||||
|
||||
static __SQLITE3_ERRMSG16: ::std::sync::atomic::AtomicPtr<()> = ::std::sync::atomic::AtomicPtr::new(
|
||||
::std::ptr::null_mut(),
|
||||
);
|
||||
pub unsafe fn sqlite3_errmsg16(arg1: *mut sqlite3) -> *const ::std::os::raw::c_void {
|
||||
let ptr = __SQLITE3_ERRMSG16.load(::std::sync::atomic::Ordering::Acquire);
|
||||
assert!(! ptr.is_null(), "SQLite API not initialized or SQLite feature omitted");
|
||||
let fun: unsafe extern "C" fn(arg1: *mut sqlite3) -> *const ::std::os::raw::c_void = ::std::mem::transmute(
|
||||
ptr,
|
||||
);
|
||||
(fun)(arg1)
|
||||
}
|
||||
|
||||
static __SQLITE3_EXEC: ::std::sync::atomic::AtomicPtr<()> = ::std::sync::atomic::AtomicPtr::new(
|
||||
::std::ptr::null_mut(),
|
||||
);
|
||||
@ -3710,66 +3314,6 @@ pub unsafe fn sqlite3_open(
|
||||
(fun)(arg1, arg2)
|
||||
}
|
||||
|
||||
static __SQLITE3_OPEN16: ::std::sync::atomic::AtomicPtr<()> = ::std::sync::atomic::AtomicPtr::new(
|
||||
::std::ptr::null_mut(),
|
||||
);
|
||||
pub unsafe fn sqlite3_open16(
|
||||
arg1: *const ::std::os::raw::c_void,
|
||||
arg2: *mut *mut sqlite3,
|
||||
) -> ::std::os::raw::c_int {
|
||||
let ptr = __SQLITE3_OPEN16.load(::std::sync::atomic::Ordering::Acquire);
|
||||
assert!(! ptr.is_null(), "SQLite API not initialized or SQLite feature omitted");
|
||||
let fun: unsafe extern "C" fn(
|
||||
arg1: *const ::std::os::raw::c_void,
|
||||
arg2: *mut *mut sqlite3,
|
||||
) -> ::std::os::raw::c_int = ::std::mem::transmute(ptr);
|
||||
(fun)(arg1, arg2)
|
||||
}
|
||||
|
||||
static __SQLITE3_PREPARE: ::std::sync::atomic::AtomicPtr<()> = ::std::sync::atomic::AtomicPtr::new(
|
||||
::std::ptr::null_mut(),
|
||||
);
|
||||
pub unsafe fn sqlite3_prepare(
|
||||
arg1: *mut sqlite3,
|
||||
arg2: *const ::std::os::raw::c_char,
|
||||
arg3: ::std::os::raw::c_int,
|
||||
arg4: *mut *mut sqlite3_stmt,
|
||||
arg5: *mut *const ::std::os::raw::c_char,
|
||||
) -> ::std::os::raw::c_int {
|
||||
let ptr = __SQLITE3_PREPARE.load(::std::sync::atomic::Ordering::Acquire);
|
||||
assert!(! ptr.is_null(), "SQLite API not initialized or SQLite feature omitted");
|
||||
let fun: unsafe extern "C" fn(
|
||||
arg1: *mut sqlite3,
|
||||
arg2: *const ::std::os::raw::c_char,
|
||||
arg3: ::std::os::raw::c_int,
|
||||
arg4: *mut *mut sqlite3_stmt,
|
||||
arg5: *mut *const ::std::os::raw::c_char,
|
||||
) -> ::std::os::raw::c_int = ::std::mem::transmute(ptr);
|
||||
(fun)(arg1, arg2, arg3, arg4, arg5)
|
||||
}
|
||||
|
||||
static __SQLITE3_PREPARE16: ::std::sync::atomic::AtomicPtr<()> = ::std::sync::atomic::AtomicPtr::new(
|
||||
::std::ptr::null_mut(),
|
||||
);
|
||||
pub unsafe fn sqlite3_prepare16(
|
||||
arg1: *mut sqlite3,
|
||||
arg2: *const ::std::os::raw::c_void,
|
||||
arg3: ::std::os::raw::c_int,
|
||||
arg4: *mut *mut sqlite3_stmt,
|
||||
arg5: *mut *const ::std::os::raw::c_void,
|
||||
) -> ::std::os::raw::c_int {
|
||||
let ptr = __SQLITE3_PREPARE16.load(::std::sync::atomic::Ordering::Acquire);
|
||||
assert!(! ptr.is_null(), "SQLite API not initialized or SQLite feature omitted");
|
||||
let fun: unsafe extern "C" fn(
|
||||
arg1: *mut sqlite3,
|
||||
arg2: *const ::std::os::raw::c_void,
|
||||
arg3: ::std::os::raw::c_int,
|
||||
arg4: *mut *mut sqlite3_stmt,
|
||||
arg5: *mut *const ::std::os::raw::c_void,
|
||||
) -> ::std::os::raw::c_int = ::std::mem::transmute(ptr);
|
||||
(fun)(arg1, arg2, arg3, arg4, arg5)
|
||||
}
|
||||
|
||||
static __SQLITE3_PROFILE: ::std::sync::atomic::AtomicPtr<()> = ::std::sync::atomic::AtomicPtr::new(
|
||||
::std::ptr::null_mut(),
|
||||
);
|
||||
@ -3906,24 +3450,6 @@ pub unsafe fn sqlite3_result_error(
|
||||
(fun)(arg1, arg2, arg3)
|
||||
}
|
||||
|
||||
static __SQLITE3_RESULT_ERROR16: ::std::sync::atomic::AtomicPtr<()> = ::std::sync::atomic::AtomicPtr::new(
|
||||
::std::ptr::null_mut(),
|
||||
);
|
||||
pub unsafe fn sqlite3_result_error16(
|
||||
arg1: *mut sqlite3_context,
|
||||
arg2: *const ::std::os::raw::c_void,
|
||||
arg3: ::std::os::raw::c_int,
|
||||
) {
|
||||
let ptr = __SQLITE3_RESULT_ERROR16.load(::std::sync::atomic::Ordering::Acquire);
|
||||
assert!(! ptr.is_null(), "SQLite API not initialized or SQLite feature omitted");
|
||||
let fun: unsafe extern "C" fn(
|
||||
arg1: *mut sqlite3_context,
|
||||
arg2: *const ::std::os::raw::c_void,
|
||||
arg3: ::std::os::raw::c_int,
|
||||
) = ::std::mem::transmute(ptr);
|
||||
(fun)(arg1, arg2, arg3)
|
||||
}
|
||||
|
||||
static __SQLITE3_RESULT_INT: ::std::sync::atomic::AtomicPtr<()> = ::std::sync::atomic::AtomicPtr::new(
|
||||
::std::ptr::null_mut(),
|
||||
);
|
||||
@ -3986,72 +3512,6 @@ pub unsafe fn sqlite3_result_text(
|
||||
(fun)(arg1, arg2, arg3, arg4)
|
||||
}
|
||||
|
||||
static __SQLITE3_RESULT_TEXT16: ::std::sync::atomic::AtomicPtr<()> = ::std::sync::atomic::AtomicPtr::new(
|
||||
::std::ptr::null_mut(),
|
||||
);
|
||||
pub unsafe fn sqlite3_result_text16(
|
||||
arg1: *mut sqlite3_context,
|
||||
arg2: *const ::std::os::raw::c_void,
|
||||
arg3: ::std::os::raw::c_int,
|
||||
arg4: ::std::option::Option<unsafe extern "C" fn(arg1: *mut ::std::os::raw::c_void)>,
|
||||
) {
|
||||
let ptr = __SQLITE3_RESULT_TEXT16.load(::std::sync::atomic::Ordering::Acquire);
|
||||
assert!(! ptr.is_null(), "SQLite API not initialized or SQLite feature omitted");
|
||||
let fun: unsafe extern "C" fn(
|
||||
arg1: *mut sqlite3_context,
|
||||
arg2: *const ::std::os::raw::c_void,
|
||||
arg3: ::std::os::raw::c_int,
|
||||
arg4: ::std::option::Option<
|
||||
unsafe extern "C" fn(arg1: *mut ::std::os::raw::c_void),
|
||||
>,
|
||||
) = ::std::mem::transmute(ptr);
|
||||
(fun)(arg1, arg2, arg3, arg4)
|
||||
}
|
||||
|
||||
static __SQLITE3_RESULT_TEXT16BE: ::std::sync::atomic::AtomicPtr<()> = ::std::sync::atomic::AtomicPtr::new(
|
||||
::std::ptr::null_mut(),
|
||||
);
|
||||
pub unsafe fn sqlite3_result_text16be(
|
||||
arg1: *mut sqlite3_context,
|
||||
arg2: *const ::std::os::raw::c_void,
|
||||
arg3: ::std::os::raw::c_int,
|
||||
arg4: ::std::option::Option<unsafe extern "C" fn(arg1: *mut ::std::os::raw::c_void)>,
|
||||
) {
|
||||
let ptr = __SQLITE3_RESULT_TEXT16BE.load(::std::sync::atomic::Ordering::Acquire);
|
||||
assert!(! ptr.is_null(), "SQLite API not initialized or SQLite feature omitted");
|
||||
let fun: unsafe extern "C" fn(
|
||||
arg1: *mut sqlite3_context,
|
||||
arg2: *const ::std::os::raw::c_void,
|
||||
arg3: ::std::os::raw::c_int,
|
||||
arg4: ::std::option::Option<
|
||||
unsafe extern "C" fn(arg1: *mut ::std::os::raw::c_void),
|
||||
>,
|
||||
) = ::std::mem::transmute(ptr);
|
||||
(fun)(arg1, arg2, arg3, arg4)
|
||||
}
|
||||
|
||||
static __SQLITE3_RESULT_TEXT16LE: ::std::sync::atomic::AtomicPtr<()> = ::std::sync::atomic::AtomicPtr::new(
|
||||
::std::ptr::null_mut(),
|
||||
);
|
||||
pub unsafe fn sqlite3_result_text16le(
|
||||
arg1: *mut sqlite3_context,
|
||||
arg2: *const ::std::os::raw::c_void,
|
||||
arg3: ::std::os::raw::c_int,
|
||||
arg4: ::std::option::Option<unsafe extern "C" fn(arg1: *mut ::std::os::raw::c_void)>,
|
||||
) {
|
||||
let ptr = __SQLITE3_RESULT_TEXT16LE.load(::std::sync::atomic::Ordering::Acquire);
|
||||
assert!(! ptr.is_null(), "SQLite API not initialized or SQLite feature omitted");
|
||||
let fun: unsafe extern "C" fn(
|
||||
arg1: *mut sqlite3_context,
|
||||
arg2: *const ::std::os::raw::c_void,
|
||||
arg3: ::std::os::raw::c_int,
|
||||
arg4: ::std::option::Option<
|
||||
unsafe extern "C" fn(arg1: *mut ::std::os::raw::c_void),
|
||||
>,
|
||||
) = ::std::mem::transmute(ptr);
|
||||
(fun)(arg1, arg2, arg3, arg4)
|
||||
}
|
||||
|
||||
static __SQLITE3_RESULT_VALUE: ::std::sync::atomic::AtomicPtr<()> = ::std::sync::atomic::AtomicPtr::new(
|
||||
::std::ptr::null_mut(),
|
||||
);
|
||||
@ -4303,18 +3763,6 @@ pub unsafe fn sqlite3_value_bytes(arg1: *mut sqlite3_value) -> ::std::os::raw::c
|
||||
(fun)(arg1)
|
||||
}
|
||||
|
||||
static __SQLITE3_VALUE_BYTES16: ::std::sync::atomic::AtomicPtr<()> = ::std::sync::atomic::AtomicPtr::new(
|
||||
::std::ptr::null_mut(),
|
||||
);
|
||||
pub unsafe fn sqlite3_value_bytes16(arg1: *mut sqlite3_value) -> ::std::os::raw::c_int {
|
||||
let ptr = __SQLITE3_VALUE_BYTES16.load(::std::sync::atomic::Ordering::Acquire);
|
||||
assert!(! ptr.is_null(), "SQLite API not initialized or SQLite feature omitted");
|
||||
let fun: unsafe extern "C" fn(arg1: *mut sqlite3_value) -> ::std::os::raw::c_int = ::std::mem::transmute(
|
||||
ptr,
|
||||
);
|
||||
(fun)(arg1)
|
||||
}
|
||||
|
||||
static __SQLITE3_VALUE_DOUBLE: ::std::sync::atomic::AtomicPtr<()> = ::std::sync::atomic::AtomicPtr::new(
|
||||
::std::ptr::null_mut(),
|
||||
);
|
||||
@ -4379,48 +3827,6 @@ pub unsafe fn sqlite3_value_text(
|
||||
(fun)(arg1)
|
||||
}
|
||||
|
||||
static __SQLITE3_VALUE_TEXT16: ::std::sync::atomic::AtomicPtr<()> = ::std::sync::atomic::AtomicPtr::new(
|
||||
::std::ptr::null_mut(),
|
||||
);
|
||||
pub unsafe fn sqlite3_value_text16(
|
||||
arg1: *mut sqlite3_value,
|
||||
) -> *const ::std::os::raw::c_void {
|
||||
let ptr = __SQLITE3_VALUE_TEXT16.load(::std::sync::atomic::Ordering::Acquire);
|
||||
assert!(! ptr.is_null(), "SQLite API not initialized or SQLite feature omitted");
|
||||
let fun: unsafe extern "C" fn(
|
||||
arg1: *mut sqlite3_value,
|
||||
) -> *const ::std::os::raw::c_void = ::std::mem::transmute(ptr);
|
||||
(fun)(arg1)
|
||||
}
|
||||
|
||||
static __SQLITE3_VALUE_TEXT16BE: ::std::sync::atomic::AtomicPtr<()> = ::std::sync::atomic::AtomicPtr::new(
|
||||
::std::ptr::null_mut(),
|
||||
);
|
||||
pub unsafe fn sqlite3_value_text16be(
|
||||
arg1: *mut sqlite3_value,
|
||||
) -> *const ::std::os::raw::c_void {
|
||||
let ptr = __SQLITE3_VALUE_TEXT16BE.load(::std::sync::atomic::Ordering::Acquire);
|
||||
assert!(! ptr.is_null(), "SQLite API not initialized or SQLite feature omitted");
|
||||
let fun: unsafe extern "C" fn(
|
||||
arg1: *mut sqlite3_value,
|
||||
) -> *const ::std::os::raw::c_void = ::std::mem::transmute(ptr);
|
||||
(fun)(arg1)
|
||||
}
|
||||
|
||||
static __SQLITE3_VALUE_TEXT16LE: ::std::sync::atomic::AtomicPtr<()> = ::std::sync::atomic::AtomicPtr::new(
|
||||
::std::ptr::null_mut(),
|
||||
);
|
||||
pub unsafe fn sqlite3_value_text16le(
|
||||
arg1: *mut sqlite3_value,
|
||||
) -> *const ::std::os::raw::c_void {
|
||||
let ptr = __SQLITE3_VALUE_TEXT16LE.load(::std::sync::atomic::Ordering::Acquire);
|
||||
assert!(! ptr.is_null(), "SQLite API not initialized or SQLite feature omitted");
|
||||
let fun: unsafe extern "C" fn(
|
||||
arg1: *mut sqlite3_value,
|
||||
) -> *const ::std::os::raw::c_void = ::std::mem::transmute(ptr);
|
||||
(fun)(arg1)
|
||||
}
|
||||
|
||||
static __SQLITE3_VALUE_TYPE: ::std::sync::atomic::AtomicPtr<()> = ::std::sync::atomic::AtomicPtr::new(
|
||||
::std::ptr::null_mut(),
|
||||
);
|
||||
@ -4473,28 +3879,6 @@ pub unsafe fn sqlite3_prepare_v2(
|
||||
(fun)(arg1, arg2, arg3, arg4, arg5)
|
||||
}
|
||||
|
||||
static __SQLITE3_PREPARE16_V2: ::std::sync::atomic::AtomicPtr<()> = ::std::sync::atomic::AtomicPtr::new(
|
||||
::std::ptr::null_mut(),
|
||||
);
|
||||
pub unsafe fn sqlite3_prepare16_v2(
|
||||
arg1: *mut sqlite3,
|
||||
arg2: *const ::std::os::raw::c_void,
|
||||
arg3: ::std::os::raw::c_int,
|
||||
arg4: *mut *mut sqlite3_stmt,
|
||||
arg5: *mut *const ::std::os::raw::c_void,
|
||||
) -> ::std::os::raw::c_int {
|
||||
let ptr = __SQLITE3_PREPARE16_V2.load(::std::sync::atomic::Ordering::Acquire);
|
||||
assert!(! ptr.is_null(), "SQLite API not initialized or SQLite feature omitted");
|
||||
let fun: unsafe extern "C" fn(
|
||||
arg1: *mut sqlite3,
|
||||
arg2: *const ::std::os::raw::c_void,
|
||||
arg3: ::std::os::raw::c_int,
|
||||
arg4: *mut *mut sqlite3_stmt,
|
||||
arg5: *mut *const ::std::os::raw::c_void,
|
||||
) -> ::std::os::raw::c_int = ::std::mem::transmute(ptr);
|
||||
(fun)(arg1, arg2, arg3, arg4, arg5)
|
||||
}
|
||||
|
||||
static __SQLITE3_CLEAR_BINDINGS: ::std::sync::atomic::AtomicPtr<()> = ::std::sync::atomic::AtomicPtr::new(
|
||||
::std::ptr::null_mut(),
|
||||
);
|
||||
@ -5498,18 +4882,6 @@ pub unsafe fn sqlite3_vtab_on_conflict(arg1: *mut sqlite3) -> ::std::os::raw::c_
|
||||
(fun)(arg1)
|
||||
}
|
||||
|
||||
static __SQLITE3_CLOSE_V2: ::std::sync::atomic::AtomicPtr<()> = ::std::sync::atomic::AtomicPtr::new(
|
||||
::std::ptr::null_mut(),
|
||||
);
|
||||
pub unsafe fn sqlite3_close_v2(arg1: *mut sqlite3) -> ::std::os::raw::c_int {
|
||||
let ptr = __SQLITE3_CLOSE_V2.load(::std::sync::atomic::Ordering::Acquire);
|
||||
assert!(! ptr.is_null(), "SQLite API not initialized or SQLite feature omitted");
|
||||
let fun: unsafe extern "C" fn(arg1: *mut sqlite3) -> ::std::os::raw::c_int = ::std::mem::transmute(
|
||||
ptr,
|
||||
);
|
||||
(fun)(arg1)
|
||||
}
|
||||
|
||||
static __SQLITE3_DB_FILENAME: ::std::sync::atomic::AtomicPtr<()> = ::std::sync::atomic::AtomicPtr::new(
|
||||
::std::ptr::null_mut(),
|
||||
);
|
||||
@ -6167,10 +5539,6 @@ pub unsafe fn rusqlite_extension_init2(
|
||||
__SQLITE3_BIND_TEXT
|
||||
.store(fun as usize as *mut (), ::std::sync::atomic::Ordering::Release);
|
||||
}
|
||||
if let Some(fun) = (*p_api).bind_text16 {
|
||||
__SQLITE3_BIND_TEXT16
|
||||
.store(fun as usize as *mut (), ::std::sync::atomic::Ordering::Release);
|
||||
}
|
||||
if let Some(fun) = (*p_api).bind_value {
|
||||
__SQLITE3_BIND_VALUE
|
||||
.store(fun as usize as *mut (), ::std::sync::atomic::Ordering::Release);
|
||||
@ -6195,10 +5563,6 @@ pub unsafe fn rusqlite_extension_init2(
|
||||
__SQLITE3_COLLATION_NEEDED
|
||||
.store(fun as usize as *mut (), ::std::sync::atomic::Ordering::Release);
|
||||
}
|
||||
if let Some(fun) = (*p_api).collation_needed16 {
|
||||
__SQLITE3_COLLATION_NEEDED16
|
||||
.store(fun as usize as *mut (), ::std::sync::atomic::Ordering::Release);
|
||||
}
|
||||
if let Some(fun) = (*p_api).column_blob {
|
||||
__SQLITE3_COLUMN_BLOB
|
||||
.store(fun as usize as *mut (), ::std::sync::atomic::Ordering::Release);
|
||||
@ -6207,10 +5571,6 @@ pub unsafe fn rusqlite_extension_init2(
|
||||
__SQLITE3_COLUMN_BYTES
|
||||
.store(fun as usize as *mut (), ::std::sync::atomic::Ordering::Release);
|
||||
}
|
||||
if let Some(fun) = (*p_api).column_bytes16 {
|
||||
__SQLITE3_COLUMN_BYTES16
|
||||
.store(fun as usize as *mut (), ::std::sync::atomic::Ordering::Release);
|
||||
}
|
||||
if let Some(fun) = (*p_api).column_count {
|
||||
__SQLITE3_COLUMN_COUNT
|
||||
.store(fun as usize as *mut (), ::std::sync::atomic::Ordering::Release);
|
||||
@ -6219,18 +5579,10 @@ pub unsafe fn rusqlite_extension_init2(
|
||||
__SQLITE3_COLUMN_DATABASE_NAME
|
||||
.store(fun as usize as *mut (), ::std::sync::atomic::Ordering::Release);
|
||||
}
|
||||
if let Some(fun) = (*p_api).column_database_name16 {
|
||||
__SQLITE3_COLUMN_DATABASE_NAME16
|
||||
.store(fun as usize as *mut (), ::std::sync::atomic::Ordering::Release);
|
||||
}
|
||||
if let Some(fun) = (*p_api).column_decltype {
|
||||
__SQLITE3_COLUMN_DECLTYPE
|
||||
.store(fun as usize as *mut (), ::std::sync::atomic::Ordering::Release);
|
||||
}
|
||||
if let Some(fun) = (*p_api).column_decltype16 {
|
||||
__SQLITE3_COLUMN_DECLTYPE16
|
||||
.store(fun as usize as *mut (), ::std::sync::atomic::Ordering::Release);
|
||||
}
|
||||
if let Some(fun) = (*p_api).column_double {
|
||||
__SQLITE3_COLUMN_DOUBLE
|
||||
.store(fun as usize as *mut (), ::std::sync::atomic::Ordering::Release);
|
||||
@ -6247,34 +5599,18 @@ pub unsafe fn rusqlite_extension_init2(
|
||||
__SQLITE3_COLUMN_NAME
|
||||
.store(fun as usize as *mut (), ::std::sync::atomic::Ordering::Release);
|
||||
}
|
||||
if let Some(fun) = (*p_api).column_name16 {
|
||||
__SQLITE3_COLUMN_NAME16
|
||||
.store(fun as usize as *mut (), ::std::sync::atomic::Ordering::Release);
|
||||
}
|
||||
if let Some(fun) = (*p_api).column_origin_name {
|
||||
__SQLITE3_COLUMN_ORIGIN_NAME
|
||||
.store(fun as usize as *mut (), ::std::sync::atomic::Ordering::Release);
|
||||
}
|
||||
if let Some(fun) = (*p_api).column_origin_name16 {
|
||||
__SQLITE3_COLUMN_ORIGIN_NAME16
|
||||
.store(fun as usize as *mut (), ::std::sync::atomic::Ordering::Release);
|
||||
}
|
||||
if let Some(fun) = (*p_api).column_table_name {
|
||||
__SQLITE3_COLUMN_TABLE_NAME
|
||||
.store(fun as usize as *mut (), ::std::sync::atomic::Ordering::Release);
|
||||
}
|
||||
if let Some(fun) = (*p_api).column_table_name16 {
|
||||
__SQLITE3_COLUMN_TABLE_NAME16
|
||||
.store(fun as usize as *mut (), ::std::sync::atomic::Ordering::Release);
|
||||
}
|
||||
if let Some(fun) = (*p_api).column_text {
|
||||
__SQLITE3_COLUMN_TEXT
|
||||
.store(fun as usize as *mut (), ::std::sync::atomic::Ordering::Release);
|
||||
}
|
||||
if let Some(fun) = (*p_api).column_text16 {
|
||||
__SQLITE3_COLUMN_TEXT16
|
||||
.store(fun as usize as *mut (), ::std::sync::atomic::Ordering::Release);
|
||||
}
|
||||
if let Some(fun) = (*p_api).column_type {
|
||||
__SQLITE3_COLUMN_TYPE
|
||||
.store(fun as usize as *mut (), ::std::sync::atomic::Ordering::Release);
|
||||
@ -6291,30 +5627,6 @@ pub unsafe fn rusqlite_extension_init2(
|
||||
__SQLITE3_COMPLETE
|
||||
.store(fun as usize as *mut (), ::std::sync::atomic::Ordering::Release);
|
||||
}
|
||||
if let Some(fun) = (*p_api).complete16 {
|
||||
__SQLITE3_COMPLETE16
|
||||
.store(fun as usize as *mut (), ::std::sync::atomic::Ordering::Release);
|
||||
}
|
||||
if let Some(fun) = (*p_api).create_collation {
|
||||
__SQLITE3_CREATE_COLLATION
|
||||
.store(fun as usize as *mut (), ::std::sync::atomic::Ordering::Release);
|
||||
}
|
||||
if let Some(fun) = (*p_api).create_collation16 {
|
||||
__SQLITE3_CREATE_COLLATION16
|
||||
.store(fun as usize as *mut (), ::std::sync::atomic::Ordering::Release);
|
||||
}
|
||||
if let Some(fun) = (*p_api).create_function {
|
||||
__SQLITE3_CREATE_FUNCTION
|
||||
.store(fun as usize as *mut (), ::std::sync::atomic::Ordering::Release);
|
||||
}
|
||||
if let Some(fun) = (*p_api).create_function16 {
|
||||
__SQLITE3_CREATE_FUNCTION16
|
||||
.store(fun as usize as *mut (), ::std::sync::atomic::Ordering::Release);
|
||||
}
|
||||
if let Some(fun) = (*p_api).create_module {
|
||||
__SQLITE3_CREATE_MODULE
|
||||
.store(fun as usize as *mut (), ::std::sync::atomic::Ordering::Release);
|
||||
}
|
||||
if let Some(fun) = (*p_api).data_count {
|
||||
__SQLITE3_DATA_COUNT
|
||||
.store(fun as usize as *mut (), ::std::sync::atomic::Ordering::Release);
|
||||
@ -6339,10 +5651,6 @@ pub unsafe fn rusqlite_extension_init2(
|
||||
__SQLITE3_ERRMSG
|
||||
.store(fun as usize as *mut (), ::std::sync::atomic::Ordering::Release);
|
||||
}
|
||||
if let Some(fun) = (*p_api).errmsg16 {
|
||||
__SQLITE3_ERRMSG16
|
||||
.store(fun as usize as *mut (), ::std::sync::atomic::Ordering::Release);
|
||||
}
|
||||
if let Some(fun) = (*p_api).exec {
|
||||
__SQLITE3_EXEC
|
||||
.store(fun as usize as *mut (), ::std::sync::atomic::Ordering::Release);
|
||||
@ -6391,18 +5699,6 @@ pub unsafe fn rusqlite_extension_init2(
|
||||
__SQLITE3_OPEN
|
||||
.store(fun as usize as *mut (), ::std::sync::atomic::Ordering::Release);
|
||||
}
|
||||
if let Some(fun) = (*p_api).open16 {
|
||||
__SQLITE3_OPEN16
|
||||
.store(fun as usize as *mut (), ::std::sync::atomic::Ordering::Release);
|
||||
}
|
||||
if let Some(fun) = (*p_api).prepare {
|
||||
__SQLITE3_PREPARE
|
||||
.store(fun as usize as *mut (), ::std::sync::atomic::Ordering::Release);
|
||||
}
|
||||
if let Some(fun) = (*p_api).prepare16 {
|
||||
__SQLITE3_PREPARE16
|
||||
.store(fun as usize as *mut (), ::std::sync::atomic::Ordering::Release);
|
||||
}
|
||||
if let Some(fun) = (*p_api).profile {
|
||||
__SQLITE3_PROFILE
|
||||
.store(fun as usize as *mut (), ::std::sync::atomic::Ordering::Release);
|
||||
@ -6431,10 +5727,6 @@ pub unsafe fn rusqlite_extension_init2(
|
||||
__SQLITE3_RESULT_ERROR
|
||||
.store(fun as usize as *mut (), ::std::sync::atomic::Ordering::Release);
|
||||
}
|
||||
if let Some(fun) = (*p_api).result_error16 {
|
||||
__SQLITE3_RESULT_ERROR16
|
||||
.store(fun as usize as *mut (), ::std::sync::atomic::Ordering::Release);
|
||||
}
|
||||
if let Some(fun) = (*p_api).result_int {
|
||||
__SQLITE3_RESULT_INT
|
||||
.store(fun as usize as *mut (), ::std::sync::atomic::Ordering::Release);
|
||||
@ -6451,18 +5743,6 @@ pub unsafe fn rusqlite_extension_init2(
|
||||
__SQLITE3_RESULT_TEXT
|
||||
.store(fun as usize as *mut (), ::std::sync::atomic::Ordering::Release);
|
||||
}
|
||||
if let Some(fun) = (*p_api).result_text16 {
|
||||
__SQLITE3_RESULT_TEXT16
|
||||
.store(fun as usize as *mut (), ::std::sync::atomic::Ordering::Release);
|
||||
}
|
||||
if let Some(fun) = (*p_api).result_text16be {
|
||||
__SQLITE3_RESULT_TEXT16BE
|
||||
.store(fun as usize as *mut (), ::std::sync::atomic::Ordering::Release);
|
||||
}
|
||||
if let Some(fun) = (*p_api).result_text16le {
|
||||
__SQLITE3_RESULT_TEXT16LE
|
||||
.store(fun as usize as *mut (), ::std::sync::atomic::Ordering::Release);
|
||||
}
|
||||
if let Some(fun) = (*p_api).result_value {
|
||||
__SQLITE3_RESULT_VALUE
|
||||
.store(fun as usize as *mut (), ::std::sync::atomic::Ordering::Release);
|
||||
@ -6511,10 +5791,6 @@ pub unsafe fn rusqlite_extension_init2(
|
||||
__SQLITE3_VALUE_BYTES
|
||||
.store(fun as usize as *mut (), ::std::sync::atomic::Ordering::Release);
|
||||
}
|
||||
if let Some(fun) = (*p_api).value_bytes16 {
|
||||
__SQLITE3_VALUE_BYTES16
|
||||
.store(fun as usize as *mut (), ::std::sync::atomic::Ordering::Release);
|
||||
}
|
||||
if let Some(fun) = (*p_api).value_double {
|
||||
__SQLITE3_VALUE_DOUBLE
|
||||
.store(fun as usize as *mut (), ::std::sync::atomic::Ordering::Release);
|
||||
@ -6535,18 +5811,6 @@ pub unsafe fn rusqlite_extension_init2(
|
||||
__SQLITE3_VALUE_TEXT
|
||||
.store(fun as usize as *mut (), ::std::sync::atomic::Ordering::Release);
|
||||
}
|
||||
if let Some(fun) = (*p_api).value_text16 {
|
||||
__SQLITE3_VALUE_TEXT16
|
||||
.store(fun as usize as *mut (), ::std::sync::atomic::Ordering::Release);
|
||||
}
|
||||
if let Some(fun) = (*p_api).value_text16be {
|
||||
__SQLITE3_VALUE_TEXT16BE
|
||||
.store(fun as usize as *mut (), ::std::sync::atomic::Ordering::Release);
|
||||
}
|
||||
if let Some(fun) = (*p_api).value_text16le {
|
||||
__SQLITE3_VALUE_TEXT16LE
|
||||
.store(fun as usize as *mut (), ::std::sync::atomic::Ordering::Release);
|
||||
}
|
||||
if let Some(fun) = (*p_api).value_type {
|
||||
__SQLITE3_VALUE_TYPE
|
||||
.store(fun as usize as *mut (), ::std::sync::atomic::Ordering::Release);
|
||||
@ -6559,10 +5823,6 @@ pub unsafe fn rusqlite_extension_init2(
|
||||
__SQLITE3_PREPARE_V2
|
||||
.store(fun as usize as *mut (), ::std::sync::atomic::Ordering::Release);
|
||||
}
|
||||
if let Some(fun) = (*p_api).prepare16_v2 {
|
||||
__SQLITE3_PREPARE16_V2
|
||||
.store(fun as usize as *mut (), ::std::sync::atomic::Ordering::Release);
|
||||
}
|
||||
if let Some(fun) = (*p_api).clear_bindings {
|
||||
__SQLITE3_CLEAR_BINDINGS
|
||||
.store(fun as usize as *mut (), ::std::sync::atomic::Ordering::Release);
|
||||
@ -6803,10 +6063,6 @@ pub unsafe fn rusqlite_extension_init2(
|
||||
__SQLITE3_VTAB_ON_CONFLICT
|
||||
.store(fun as usize as *mut (), ::std::sync::atomic::Ordering::Release);
|
||||
}
|
||||
if let Some(fun) = (*p_api).close_v2 {
|
||||
__SQLITE3_CLOSE_V2
|
||||
.store(fun as usize as *mut (), ::std::sync::atomic::Ordering::Release);
|
||||
}
|
||||
if let Some(fun) = (*p_api).db_filename {
|
||||
__SQLITE3_DB_FILENAME
|
||||
.store(fun as usize as *mut (), ::std::sync::atomic::Ordering::Release);
|
||||
|
@ -6,7 +6,7 @@ use std::path::Path;
|
||||
///
|
||||
/// Note that there is no way to know at compile-time which system we'll be
|
||||
/// targeting, and this test must be made at run-time (of the build script) See
|
||||
/// https://doc.rust-lang.org/cargo/reference/environment-variables.html#environment-variables-cargo-sets-for-build-scripts
|
||||
/// <https://doc.rust-lang.org/cargo/reference/environment-variables.html#environment-variables-cargo-sets-for-build-scripts>
|
||||
fn win_target() -> bool {
|
||||
env::var("CARGO_CFG_WINDOWS").is_ok()
|
||||
}
|
||||
@ -131,12 +131,12 @@ mod build_bundled {
|
||||
.flag("-DSQLITE_ENABLE_LOAD_EXTENSION=1")
|
||||
.flag("-DSQLITE_ENABLE_MEMORY_MANAGEMENT")
|
||||
.flag("-DSQLITE_ENABLE_RTREE")
|
||||
.flag("-DSQLITE_ENABLE_STAT2")
|
||||
.flag("-DSQLITE_ENABLE_STAT4")
|
||||
.flag("-DSQLITE_SOUNDEX")
|
||||
.flag("-DSQLITE_THREADSAFE=1")
|
||||
.flag("-DSQLITE_USE_URI")
|
||||
.flag("-DHAVE_USLEEP=1")
|
||||
.flag("-DHAVE_ISNAN")
|
||||
.flag("-D_POSIX_THREAD_SAFE_FUNCTIONS") // cross compile with MinGW
|
||||
.warnings(false);
|
||||
|
||||
@ -156,25 +156,34 @@ mod build_bundled {
|
||||
let (lib_dir, inc_dir) = match (lib_dir, inc_dir) {
|
||||
(Some(lib_dir), Some(inc_dir)) => {
|
||||
use_openssl = true;
|
||||
(lib_dir, inc_dir)
|
||||
(vec![lib_dir], inc_dir)
|
||||
}
|
||||
(lib_dir, inc_dir) => match find_openssl_dir(&host, &target) {
|
||||
None => {
|
||||
if is_windows && !cfg!(feature = "bundled-sqlcipher-vendored-openssl") {
|
||||
panic!("Missing environment variable OPENSSL_DIR or OPENSSL_DIR is not set")
|
||||
} else {
|
||||
(PathBuf::new(), PathBuf::new())
|
||||
(vec![PathBuf::new()], PathBuf::new())
|
||||
}
|
||||
}
|
||||
Some(openssl_dir) => {
|
||||
let lib_dir = lib_dir.unwrap_or_else(|| openssl_dir.join("lib"));
|
||||
let lib_dir = lib_dir.map(|d| vec![d]).unwrap_or_else(|| {
|
||||
let mut lib_dirs = vec![];
|
||||
// OpenSSL 3.0 now puts its libraries in lib64/ by default,
|
||||
// check for both it and lib/.
|
||||
if openssl_dir.join("lib64").exists() {
|
||||
lib_dirs.push(openssl_dir.join("lib64"));
|
||||
}
|
||||
if openssl_dir.join("lib").exists() {
|
||||
lib_dirs.push(openssl_dir.join("lib"));
|
||||
}
|
||||
lib_dirs
|
||||
});
|
||||
let inc_dir = inc_dir.unwrap_or_else(|| openssl_dir.join("include"));
|
||||
|
||||
assert!(
|
||||
Path::new(&lib_dir).exists(),
|
||||
"OpenSSL library directory does not exist: {}",
|
||||
lib_dir.to_string_lossy()
|
||||
);
|
||||
if !lib_dir.iter().all(|p| p.exists()) {
|
||||
panic!("OpenSSL library directory does not exist: {lib_dir:?}");
|
||||
}
|
||||
|
||||
if !Path::new(&inc_dir).exists() {
|
||||
panic!(
|
||||
@ -196,8 +205,10 @@ mod build_bundled {
|
||||
} else if use_openssl {
|
||||
cfg.include(inc_dir.to_string_lossy().as_ref());
|
||||
let lib_name = if is_windows { "libcrypto" } else { "crypto" };
|
||||
println!("cargo:rustc-link-lib=dylib={}", lib_name);
|
||||
println!("cargo:rustc-link-search={}", lib_dir.to_string_lossy());
|
||||
println!("cargo:rustc-link-lib=dylib={lib_name}");
|
||||
for lib_dir_item in &lib_dir {
|
||||
println!("cargo:rustc-link-search={}", lib_dir_item.to_string_lossy());
|
||||
}
|
||||
} else if is_apple {
|
||||
cfg.flag("-DSQLCIPHER_CRYPTO_CC");
|
||||
println!("cargo:rustc-link-lib=framework=Security");
|
||||
@ -225,25 +236,6 @@ mod build_bundled {
|
||||
cfg.static_crt(true);
|
||||
}
|
||||
|
||||
// Older versions of visual studio don't support c99 (including isnan), which
|
||||
// causes a build failure when the linker fails to find the `isnan`
|
||||
// function. `sqlite` provides its own implementation, using the fact
|
||||
// that x != x when x is NaN.
|
||||
//
|
||||
// There may be other platforms that don't support `isnan`, they should be
|
||||
// tested for here.
|
||||
if is_compiler("msvc") {
|
||||
use cc::windows_registry::{find_vs_version, VsVers};
|
||||
let vs_has_nan = match find_vs_version() {
|
||||
Ok(ver) => ver != VsVers::Vs12,
|
||||
Err(_msg) => false,
|
||||
};
|
||||
if vs_has_nan {
|
||||
cfg.flag("-DHAVE_ISNAN");
|
||||
}
|
||||
} else {
|
||||
cfg.flag("-DHAVE_ISNAN");
|
||||
}
|
||||
if !win_target() {
|
||||
cfg.flag("-DHAVE_LOCALTIME_R");
|
||||
}
|
||||
@ -272,17 +264,17 @@ mod build_bundled {
|
||||
}
|
||||
|
||||
if let Ok(limit) = env::var("SQLITE_MAX_VARIABLE_NUMBER") {
|
||||
cfg.flag(&format!("-DSQLITE_MAX_VARIABLE_NUMBER={limit}"));
|
||||
cfg.flag(format!("-DSQLITE_MAX_VARIABLE_NUMBER={limit}"));
|
||||
}
|
||||
println!("cargo:rerun-if-env-changed=SQLITE_MAX_VARIABLE_NUMBER");
|
||||
|
||||
if let Ok(limit) = env::var("SQLITE_MAX_EXPR_DEPTH") {
|
||||
cfg.flag(&format!("-DSQLITE_MAX_EXPR_DEPTH={limit}"));
|
||||
cfg.flag(format!("-DSQLITE_MAX_EXPR_DEPTH={limit}"));
|
||||
}
|
||||
println!("cargo:rerun-if-env-changed=SQLITE_MAX_EXPR_DEPTH");
|
||||
|
||||
if let Ok(limit) = env::var("SQLITE_MAX_COLUMN") {
|
||||
cfg.flag(&format!("-DSQLITE_MAX_COLUMN={limit}"));
|
||||
cfg.flag(format!("-DSQLITE_MAX_COLUMN={limit}"));
|
||||
}
|
||||
println!("cargo:rerun-if-env-changed=SQLITE_MAX_COLUMN");
|
||||
|
||||
@ -291,9 +283,9 @@ mod build_bundled {
|
||||
if extra.starts_with("-D") || extra.starts_with("-U") {
|
||||
cfg.flag(extra);
|
||||
} else if extra.starts_with("SQLITE_") {
|
||||
cfg.flag(&format!("-D{extra}"));
|
||||
cfg.flag(format!("-D{extra}"));
|
||||
} else {
|
||||
panic!("Don't understand {} in LIBSQLITE3_FLAGS", extra);
|
||||
panic!("Don't understand {extra} in LIBSQLITE3_FLAGS");
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -344,7 +336,7 @@ pub enum HeaderLocation {
|
||||
}
|
||||
|
||||
impl From<HeaderLocation> for String {
|
||||
fn from(header: HeaderLocation) -> String {
|
||||
fn from(header: HeaderLocation) -> Self {
|
||||
match header {
|
||||
HeaderLocation::FromEnvironment => {
|
||||
let prefix = env_prefix();
|
||||
@ -487,8 +479,8 @@ mod build_linked {
|
||||
}
|
||||
|
||||
#[cfg(not(feature = "buildtime_bindgen"))]
|
||||
#[allow(dead_code)]
|
||||
mod bindings {
|
||||
#![allow(dead_code)]
|
||||
use super::HeaderLocation;
|
||||
|
||||
use std::path::Path;
|
||||
@ -554,8 +546,8 @@ mod bindings {
|
||||
xEntryPoint: ::std::option::Option<
|
||||
unsafe extern "C" fn(
|
||||
db: *mut sqlite3,
|
||||
pzErrMsg: *mut *const ::std::os::raw::c_char,
|
||||
pThunk: *const sqlite3_api_routines,
|
||||
pzErrMsg: *mut *mut ::std::os::raw::c_char,
|
||||
_: *const sqlite3_api_routines,
|
||||
) -> ::std::os::raw::c_int,
|
||||
>,
|
||||
) -> ::std::os::raw::c_int;
|
||||
@ -568,13 +560,19 @@ mod bindings {
|
||||
xEntryPoint: ::std::option::Option<
|
||||
unsafe extern "C" fn(
|
||||
db: *mut sqlite3,
|
||||
pzErrMsg: *mut *const ::std::os::raw::c_char,
|
||||
pThunk: *const sqlite3_api_routines,
|
||||
pzErrMsg: *mut *mut ::std::os::raw::c_char,
|
||||
_: *const sqlite3_api_routines,
|
||||
) -> ::std::os::raw::c_int,
|
||||
>,
|
||||
) -> ::std::os::raw::c_int;
|
||||
}"#,
|
||||
);
|
||||
)
|
||||
.blocklist_function(".*16.*")
|
||||
.blocklist_function("sqlite3_close_v2")
|
||||
.blocklist_function("sqlite3_create_collation")
|
||||
.blocklist_function("sqlite3_create_function")
|
||||
.blocklist_function("sqlite3_create_module")
|
||||
.blocklist_function("sqlite3_prepare");
|
||||
}
|
||||
|
||||
if cfg!(any(feature = "sqlcipher", feature = "bundled-sqlcipher")) {
|
||||
@ -671,13 +669,20 @@ mod loadable_extension {
|
||||
let ident = field.ident.expect("unnamed field");
|
||||
let span = ident.span();
|
||||
let name = ident.to_string();
|
||||
if name == "vmprintf" || name == "xvsnprintf" || name == "str_vappendf" {
|
||||
if name.contains("16") {
|
||||
continue; // skip UTF-16 api as rust uses UTF-8
|
||||
} else 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"
|
||||
|| name == "create_collation"
|
||||
|| name == "create_function"
|
||||
|| name == "create_module"
|
||||
|| name == "prepare"
|
||||
|| name == "close_v2"
|
||||
{
|
||||
continue; // omit deprecated
|
||||
}
|
||||
|
423
libsqlite3-sys/sqlcipher/bindgen_bundled_version.rs
vendored
423
libsqlite3-sys/sqlcipher/bindgen_bundled_version.rs
vendored
@ -1,33 +1,32 @@
|
||||
/* automatically generated by rust-bindgen 0.63.0 */
|
||||
/* automatically generated by rust-bindgen 0.69.4 */
|
||||
|
||||
extern "C" {
|
||||
pub fn sqlite3_auto_extension(
|
||||
xEntryPoint: ::std::option::Option<
|
||||
unsafe extern "C" fn(
|
||||
db: *mut sqlite3,
|
||||
pzErrMsg: *mut *const ::std::os::raw::c_char,
|
||||
pThunk: *const sqlite3_api_routines,
|
||||
pzErrMsg: *mut *mut ::std::os::raw::c_char,
|
||||
_: *const sqlite3_api_routines,
|
||||
) -> ::std::os::raw::c_int,
|
||||
>,
|
||||
) -> ::std::os::raw::c_int;
|
||||
}
|
||||
|
||||
extern "C" {
|
||||
pub fn sqlite3_cancel_auto_extension(
|
||||
xEntryPoint: ::std::option::Option<
|
||||
unsafe extern "C" fn(
|
||||
db: *mut sqlite3,
|
||||
pzErrMsg: *mut *const ::std::os::raw::c_char,
|
||||
pThunk: *const sqlite3_api_routines,
|
||||
pzErrMsg: *mut *mut ::std::os::raw::c_char,
|
||||
_: *const sqlite3_api_routines,
|
||||
) -> ::std::os::raw::c_int,
|
||||
>,
|
||||
) -> ::std::os::raw::c_int;
|
||||
}
|
||||
|
||||
pub const SQLITE_VERSION: &[u8; 7usize] = b"3.39.4\0";
|
||||
pub const SQLITE_VERSION_NUMBER: i32 = 3039004;
|
||||
pub const SQLITE_SOURCE_ID: &[u8; 85usize] =
|
||||
b"2022-09-29 15:55:41 a29f9949895322123f7c38fbe94c649a9d6e6c9cd0c3b41c96d694552f26alt1\0";
|
||||
pub const SQLITE_VERSION: &[u8; 7] = b"3.45.3\0";
|
||||
pub const SQLITE_VERSION_NUMBER: i32 = 3045003;
|
||||
pub const SQLITE_SOURCE_ID: &[u8; 85] =
|
||||
b"2024-04-15 13:34:05 8653b758870e6ef0c98d46b3ace27849054af85da891eb121e9aaa537f1ealt1\0";
|
||||
pub const SQLITE_OK: i32 = 0;
|
||||
pub const SQLITE_ERROR: i32 = 1;
|
||||
pub const SQLITE_INTERNAL: i32 = 2;
|
||||
@ -95,6 +94,7 @@ pub const SQLITE_IOERR_COMMIT_ATOMIC: i32 = 7690;
|
||||
pub const SQLITE_IOERR_ROLLBACK_ATOMIC: i32 = 7946;
|
||||
pub const SQLITE_IOERR_DATA: i32 = 8202;
|
||||
pub const SQLITE_IOERR_CORRUPTFS: i32 = 8458;
|
||||
pub const SQLITE_IOERR_IN_PAGE: i32 = 8714;
|
||||
pub const SQLITE_LOCKED_SHAREDCACHE: i32 = 262;
|
||||
pub const SQLITE_LOCKED_VTAB: i32 = 518;
|
||||
pub const SQLITE_BUSY_RECOVERY: i32 = 261;
|
||||
@ -130,6 +130,7 @@ pub const SQLITE_CONSTRAINT_PINNED: i32 = 2835;
|
||||
pub const SQLITE_CONSTRAINT_DATATYPE: i32 = 3091;
|
||||
pub const SQLITE_NOTICE_RECOVER_WAL: i32 = 283;
|
||||
pub const SQLITE_NOTICE_RECOVER_ROLLBACK: i32 = 539;
|
||||
pub const SQLITE_NOTICE_RBU: i32 = 795;
|
||||
pub const SQLITE_WARNING_AUTOINDEX: i32 = 284;
|
||||
pub const SQLITE_AUTH_USER: i32 = 279;
|
||||
pub const SQLITE_OK_LOAD_PERMANENTLY: i32 = 256;
|
||||
@ -220,6 +221,7 @@ pub const SQLITE_FCNTL_RESERVE_BYTES: i32 = 38;
|
||||
pub const SQLITE_FCNTL_CKPT_START: i32 = 39;
|
||||
pub const SQLITE_FCNTL_EXTERNAL_READER: i32 = 40;
|
||||
pub const SQLITE_FCNTL_CKSM_FILE: i32 = 41;
|
||||
pub const SQLITE_FCNTL_RESET_CACHE: i32 = 42;
|
||||
pub const SQLITE_GET_LOCKPROXYFILE: i32 = 2;
|
||||
pub const SQLITE_SET_LOCKPROXYFILE: i32 = 3;
|
||||
pub const SQLITE_LAST_ERRNO: i32 = 4;
|
||||
@ -259,6 +261,7 @@ pub const SQLITE_CONFIG_STMTJRNL_SPILL: i32 = 26;
|
||||
pub const SQLITE_CONFIG_SMALL_MALLOC: i32 = 27;
|
||||
pub const SQLITE_CONFIG_SORTERREF_SIZE: i32 = 28;
|
||||
pub const SQLITE_CONFIG_MEMDB_MAXSIZE: i32 = 29;
|
||||
pub const SQLITE_CONFIG_ROWID_IN_VIEW: i32 = 30;
|
||||
pub const SQLITE_DBCONFIG_MAINDBNAME: i32 = 1000;
|
||||
pub const SQLITE_DBCONFIG_LOOKASIDE: i32 = 1001;
|
||||
pub const SQLITE_DBCONFIG_ENABLE_FKEY: i32 = 1002;
|
||||
@ -277,7 +280,9 @@ pub const SQLITE_DBCONFIG_DQS_DDL: i32 = 1014;
|
||||
pub const SQLITE_DBCONFIG_ENABLE_VIEW: i32 = 1015;
|
||||
pub const SQLITE_DBCONFIG_LEGACY_FILE_FORMAT: i32 = 1016;
|
||||
pub const SQLITE_DBCONFIG_TRUSTED_SCHEMA: i32 = 1017;
|
||||
pub const SQLITE_DBCONFIG_MAX: i32 = 1017;
|
||||
pub const SQLITE_DBCONFIG_STMT_SCANSTATUS: i32 = 1018;
|
||||
pub const SQLITE_DBCONFIG_REVERSE_SCANORDER: i32 = 1019;
|
||||
pub const SQLITE_DBCONFIG_MAX: i32 = 1019;
|
||||
pub const SQLITE_DENY: i32 = 1;
|
||||
pub const SQLITE_IGNORE: i32 = 2;
|
||||
pub const SQLITE_CREATE_INDEX: i32 = 1;
|
||||
@ -330,9 +335,9 @@ pub const SQLITE_LIMIT_LIKE_PATTERN_LENGTH: i32 = 8;
|
||||
pub const SQLITE_LIMIT_VARIABLE_NUMBER: i32 = 9;
|
||||
pub const SQLITE_LIMIT_TRIGGER_DEPTH: i32 = 10;
|
||||
pub const SQLITE_LIMIT_WORKER_THREADS: i32 = 11;
|
||||
pub const SQLITE_PREPARE_PERSISTENT: i32 = 1;
|
||||
pub const SQLITE_PREPARE_NORMALIZE: i32 = 2;
|
||||
pub const SQLITE_PREPARE_NO_VTAB: i32 = 4;
|
||||
pub const SQLITE_PREPARE_PERSISTENT: ::std::os::raw::c_uint = 1;
|
||||
pub const SQLITE_PREPARE_NORMALIZE: ::std::os::raw::c_uint = 2;
|
||||
pub const SQLITE_PREPARE_NO_VTAB: ::std::os::raw::c_uint = 4;
|
||||
pub const SQLITE_INTEGER: i32 = 1;
|
||||
pub const SQLITE_FLOAT: i32 = 2;
|
||||
pub const SQLITE_BLOB: i32 = 4;
|
||||
@ -349,6 +354,7 @@ pub const SQLITE_DETERMINISTIC: i32 = 2048;
|
||||
pub const SQLITE_DIRECTONLY: i32 = 524288;
|
||||
pub const SQLITE_SUBTYPE: i32 = 1048576;
|
||||
pub const SQLITE_INNOCUOUS: i32 = 2097152;
|
||||
pub const SQLITE_RESULT_SUBTYPE: i32 = 16777216;
|
||||
pub const SQLITE_WIN32_DATA_DIRECTORY_TYPE: i32 = 1;
|
||||
pub const SQLITE_WIN32_TEMP_DIRECTORY_TYPE: i32 = 2;
|
||||
pub const SQLITE_TXN_NONE: i32 = 0;
|
||||
@ -393,6 +399,7 @@ pub const SQLITE_TESTCTRL_FIRST: i32 = 5;
|
||||
pub const SQLITE_TESTCTRL_PRNG_SAVE: i32 = 5;
|
||||
pub const SQLITE_TESTCTRL_PRNG_RESTORE: i32 = 6;
|
||||
pub const SQLITE_TESTCTRL_PRNG_RESET: i32 = 7;
|
||||
pub const SQLITE_TESTCTRL_FK_NO_ACTION: i32 = 7;
|
||||
pub const SQLITE_TESTCTRL_BITVEC_TEST: i32 = 8;
|
||||
pub const SQLITE_TESTCTRL_FAULT_INSTALL: i32 = 9;
|
||||
pub const SQLITE_TESTCTRL_BENIGN_MALLOC_HOOKS: i32 = 10;
|
||||
@ -400,6 +407,7 @@ pub const SQLITE_TESTCTRL_PENDING_BYTE: i32 = 11;
|
||||
pub const SQLITE_TESTCTRL_ASSERT: i32 = 12;
|
||||
pub const SQLITE_TESTCTRL_ALWAYS: i32 = 13;
|
||||
pub const SQLITE_TESTCTRL_RESERVE: i32 = 14;
|
||||
pub const SQLITE_TESTCTRL_JSON_SELFCHECK: i32 = 14;
|
||||
pub const SQLITE_TESTCTRL_OPTIMIZATIONS: i32 = 15;
|
||||
pub const SQLITE_TESTCTRL_ISKEYWORD: i32 = 16;
|
||||
pub const SQLITE_TESTCTRL_SCRATCHMALLOC: i32 = 17;
|
||||
@ -421,7 +429,8 @@ pub const SQLITE_TESTCTRL_SEEK_COUNT: i32 = 30;
|
||||
pub const SQLITE_TESTCTRL_TRACEFLAGS: i32 = 31;
|
||||
pub const SQLITE_TESTCTRL_TUNE: i32 = 32;
|
||||
pub const SQLITE_TESTCTRL_LOGEST: i32 = 33;
|
||||
pub const SQLITE_TESTCTRL_LAST: i32 = 33;
|
||||
pub const SQLITE_TESTCTRL_USELONGDOUBLE: i32 = 34;
|
||||
pub const SQLITE_TESTCTRL_LAST: i32 = 34;
|
||||
pub const SQLITE_STATUS_MEMORY_USED: i32 = 0;
|
||||
pub const SQLITE_STATUS_PAGECACHE_USED: i32 = 1;
|
||||
pub const SQLITE_STATUS_PAGECACHE_OVERFLOW: i32 = 2;
|
||||
@ -462,6 +471,7 @@ pub const SQLITE_CHECKPOINT_TRUNCATE: i32 = 3;
|
||||
pub const SQLITE_VTAB_CONSTRAINT_SUPPORT: i32 = 1;
|
||||
pub const SQLITE_VTAB_INNOCUOUS: i32 = 2;
|
||||
pub const SQLITE_VTAB_DIRECTONLY: i32 = 3;
|
||||
pub const SQLITE_VTAB_USES_ALL_SCHEMAS: i32 = 4;
|
||||
pub const SQLITE_ROLLBACK: i32 = 1;
|
||||
pub const SQLITE_FAIL: i32 = 3;
|
||||
pub const SQLITE_REPLACE: i32 = 5;
|
||||
@ -471,18 +481,23 @@ pub const SQLITE_SCANSTAT_EST: i32 = 2;
|
||||
pub const SQLITE_SCANSTAT_NAME: i32 = 3;
|
||||
pub const SQLITE_SCANSTAT_EXPLAIN: i32 = 4;
|
||||
pub const SQLITE_SCANSTAT_SELECTID: i32 = 5;
|
||||
pub const SQLITE_SERIALIZE_NOCOPY: i32 = 1;
|
||||
pub const SQLITE_DESERIALIZE_FREEONCLOSE: i32 = 1;
|
||||
pub const SQLITE_DESERIALIZE_RESIZEABLE: i32 = 2;
|
||||
pub const SQLITE_DESERIALIZE_READONLY: i32 = 4;
|
||||
pub const SQLITE_SCANSTAT_PARENTID: i32 = 6;
|
||||
pub const SQLITE_SCANSTAT_NCYCLE: i32 = 7;
|
||||
pub const SQLITE_SCANSTAT_COMPLEX: i32 = 1;
|
||||
pub const SQLITE_SERIALIZE_NOCOPY: ::std::os::raw::c_uint = 1;
|
||||
pub const SQLITE_DESERIALIZE_FREEONCLOSE: ::std::os::raw::c_uint = 1;
|
||||
pub const SQLITE_DESERIALIZE_RESIZEABLE: ::std::os::raw::c_uint = 2;
|
||||
pub const SQLITE_DESERIALIZE_READONLY: ::std::os::raw::c_uint = 4;
|
||||
pub const NOT_WITHIN: i32 = 0;
|
||||
pub const PARTLY_WITHIN: i32 = 1;
|
||||
pub const FULLY_WITHIN: i32 = 2;
|
||||
pub const __SQLITESESSION_H_: i32 = 1;
|
||||
pub const SQLITE_SESSION_OBJCONFIG_SIZE: i32 = 1;
|
||||
pub const SQLITE_SESSION_OBJCONFIG_ROWID: i32 = 2;
|
||||
pub const SQLITE_CHANGESETSTART_INVERT: i32 = 2;
|
||||
pub const SQLITE_CHANGESETAPPLY_NOSAVEPOINT: i32 = 1;
|
||||
pub const SQLITE_CHANGESETAPPLY_INVERT: i32 = 2;
|
||||
pub const SQLITE_CHANGESETAPPLY_IGNORENOOP: i32 = 4;
|
||||
pub const SQLITE_CHANGESETAPPLY_FKNOACTION: i32 = 8;
|
||||
pub const SQLITE_CHANGESET_DATA: i32 = 1;
|
||||
pub const SQLITE_CHANGESET_NOTFOUND: i32 = 2;
|
||||
pub const SQLITE_CHANGESET_CONFLICT: i32 = 3;
|
||||
@ -532,9 +547,6 @@ pub type sqlite3_uint64 = sqlite_uint64;
|
||||
extern "C" {
|
||||
pub fn sqlite3_close(arg1: *mut sqlite3) -> ::std::os::raw::c_int;
|
||||
}
|
||||
extern "C" {
|
||||
pub fn sqlite3_close_v2(arg1: *mut sqlite3) -> ::std::os::raw::c_int;
|
||||
}
|
||||
pub type sqlite3_callback = ::std::option::Option<
|
||||
unsafe extern "C" fn(
|
||||
arg1: *mut ::std::os::raw::c_void,
|
||||
@ -683,6 +695,7 @@ pub struct sqlite3_mutex {
|
||||
pub struct sqlite3_api_routines {
|
||||
_unused: [u8; 0],
|
||||
}
|
||||
pub type sqlite3_filename = *const ::std::os::raw::c_char;
|
||||
pub type sqlite3_syscall_ptr = ::std::option::Option<unsafe extern "C" fn()>;
|
||||
#[repr(C)]
|
||||
#[derive(Debug, Copy, Clone)]
|
||||
@ -696,7 +709,7 @@ pub struct sqlite3_vfs {
|
||||
pub xOpen: ::std::option::Option<
|
||||
unsafe extern "C" fn(
|
||||
arg1: *mut sqlite3_vfs,
|
||||
zName: *const ::std::os::raw::c_char,
|
||||
zName: sqlite3_filename,
|
||||
arg2: *mut sqlite3_file,
|
||||
flags: ::std::os::raw::c_int,
|
||||
pOutFlags: *mut ::std::os::raw::c_int,
|
||||
@ -878,10 +891,10 @@ extern "C" {
|
||||
pub fn sqlite3_interrupt(arg1: *mut sqlite3);
|
||||
}
|
||||
extern "C" {
|
||||
pub fn sqlite3_complete(sql: *const ::std::os::raw::c_char) -> ::std::os::raw::c_int;
|
||||
pub fn sqlite3_is_interrupted(arg1: *mut sqlite3) -> ::std::os::raw::c_int;
|
||||
}
|
||||
extern "C" {
|
||||
pub fn sqlite3_complete16(sql: *const ::std::os::raw::c_void) -> ::std::os::raw::c_int;
|
||||
pub fn sqlite3_complete(sql: *const ::std::os::raw::c_char) -> ::std::os::raw::c_int;
|
||||
}
|
||||
extern "C" {
|
||||
pub fn sqlite3_busy_handler(
|
||||
@ -1031,12 +1044,6 @@ extern "C" {
|
||||
ppDb: *mut *mut sqlite3,
|
||||
) -> ::std::os::raw::c_int;
|
||||
}
|
||||
extern "C" {
|
||||
pub fn sqlite3_open16(
|
||||
filename: *const ::std::os::raw::c_void,
|
||||
ppDb: *mut *mut sqlite3,
|
||||
) -> ::std::os::raw::c_int;
|
||||
}
|
||||
extern "C" {
|
||||
pub fn sqlite3_open_v2(
|
||||
filename: *const ::std::os::raw::c_char,
|
||||
@ -1047,44 +1054,38 @@ extern "C" {
|
||||
}
|
||||
extern "C" {
|
||||
pub fn sqlite3_uri_parameter(
|
||||
zFilename: *const ::std::os::raw::c_char,
|
||||
z: sqlite3_filename,
|
||||
zParam: *const ::std::os::raw::c_char,
|
||||
) -> *const ::std::os::raw::c_char;
|
||||
}
|
||||
extern "C" {
|
||||
pub fn sqlite3_uri_boolean(
|
||||
zFile: *const ::std::os::raw::c_char,
|
||||
z: sqlite3_filename,
|
||||
zParam: *const ::std::os::raw::c_char,
|
||||
bDefault: ::std::os::raw::c_int,
|
||||
) -> ::std::os::raw::c_int;
|
||||
}
|
||||
extern "C" {
|
||||
pub fn sqlite3_uri_int64(
|
||||
arg1: *const ::std::os::raw::c_char,
|
||||
arg1: sqlite3_filename,
|
||||
arg2: *const ::std::os::raw::c_char,
|
||||
arg3: sqlite3_int64,
|
||||
) -> sqlite3_int64;
|
||||
}
|
||||
extern "C" {
|
||||
pub fn sqlite3_uri_key(
|
||||
zFilename: *const ::std::os::raw::c_char,
|
||||
z: sqlite3_filename,
|
||||
N: ::std::os::raw::c_int,
|
||||
) -> *const ::std::os::raw::c_char;
|
||||
}
|
||||
extern "C" {
|
||||
pub fn sqlite3_filename_database(
|
||||
arg1: *const ::std::os::raw::c_char,
|
||||
) -> *const ::std::os::raw::c_char;
|
||||
pub fn sqlite3_filename_database(arg1: sqlite3_filename) -> *const ::std::os::raw::c_char;
|
||||
}
|
||||
extern "C" {
|
||||
pub fn sqlite3_filename_journal(
|
||||
arg1: *const ::std::os::raw::c_char,
|
||||
) -> *const ::std::os::raw::c_char;
|
||||
pub fn sqlite3_filename_journal(arg1: sqlite3_filename) -> *const ::std::os::raw::c_char;
|
||||
}
|
||||
extern "C" {
|
||||
pub fn sqlite3_filename_wal(
|
||||
arg1: *const ::std::os::raw::c_char,
|
||||
) -> *const ::std::os::raw::c_char;
|
||||
pub fn sqlite3_filename_wal(arg1: sqlite3_filename) -> *const ::std::os::raw::c_char;
|
||||
}
|
||||
extern "C" {
|
||||
pub fn sqlite3_database_file_object(arg1: *const ::std::os::raw::c_char) -> *mut sqlite3_file;
|
||||
@ -1096,10 +1097,10 @@ extern "C" {
|
||||
zWal: *const ::std::os::raw::c_char,
|
||||
nParam: ::std::os::raw::c_int,
|
||||
azParam: *mut *const ::std::os::raw::c_char,
|
||||
) -> *mut ::std::os::raw::c_char;
|
||||
) -> sqlite3_filename;
|
||||
}
|
||||
extern "C" {
|
||||
pub fn sqlite3_free_filename(arg1: *mut ::std::os::raw::c_char);
|
||||
pub fn sqlite3_free_filename(arg1: sqlite3_filename);
|
||||
}
|
||||
extern "C" {
|
||||
pub fn sqlite3_errcode(db: *mut sqlite3) -> ::std::os::raw::c_int;
|
||||
@ -1110,9 +1111,6 @@ extern "C" {
|
||||
extern "C" {
|
||||
pub fn sqlite3_errmsg(arg1: *mut sqlite3) -> *const ::std::os::raw::c_char;
|
||||
}
|
||||
extern "C" {
|
||||
pub fn sqlite3_errmsg16(arg1: *mut sqlite3) -> *const ::std::os::raw::c_void;
|
||||
}
|
||||
extern "C" {
|
||||
pub fn sqlite3_errstr(arg1: ::std::os::raw::c_int) -> *const ::std::os::raw::c_char;
|
||||
}
|
||||
@ -1131,15 +1129,6 @@ extern "C" {
|
||||
newVal: ::std::os::raw::c_int,
|
||||
) -> ::std::os::raw::c_int;
|
||||
}
|
||||
extern "C" {
|
||||
pub fn sqlite3_prepare(
|
||||
db: *mut sqlite3,
|
||||
zSql: *const ::std::os::raw::c_char,
|
||||
nByte: ::std::os::raw::c_int,
|
||||
ppStmt: *mut *mut sqlite3_stmt,
|
||||
pzTail: *mut *const ::std::os::raw::c_char,
|
||||
) -> ::std::os::raw::c_int;
|
||||
}
|
||||
extern "C" {
|
||||
pub fn sqlite3_prepare_v2(
|
||||
db: *mut sqlite3,
|
||||
@ -1159,34 +1148,6 @@ extern "C" {
|
||||
pzTail: *mut *const ::std::os::raw::c_char,
|
||||
) -> ::std::os::raw::c_int;
|
||||
}
|
||||
extern "C" {
|
||||
pub fn sqlite3_prepare16(
|
||||
db: *mut sqlite3,
|
||||
zSql: *const ::std::os::raw::c_void,
|
||||
nByte: ::std::os::raw::c_int,
|
||||
ppStmt: *mut *mut sqlite3_stmt,
|
||||
pzTail: *mut *const ::std::os::raw::c_void,
|
||||
) -> ::std::os::raw::c_int;
|
||||
}
|
||||
extern "C" {
|
||||
pub fn sqlite3_prepare16_v2(
|
||||
db: *mut sqlite3,
|
||||
zSql: *const ::std::os::raw::c_void,
|
||||
nByte: ::std::os::raw::c_int,
|
||||
ppStmt: *mut *mut sqlite3_stmt,
|
||||
pzTail: *mut *const ::std::os::raw::c_void,
|
||||
) -> ::std::os::raw::c_int;
|
||||
}
|
||||
extern "C" {
|
||||
pub fn sqlite3_prepare16_v3(
|
||||
db: *mut sqlite3,
|
||||
zSql: *const ::std::os::raw::c_void,
|
||||
nByte: ::std::os::raw::c_int,
|
||||
prepFlags: ::std::os::raw::c_uint,
|
||||
ppStmt: *mut *mut sqlite3_stmt,
|
||||
pzTail: *mut *const ::std::os::raw::c_void,
|
||||
) -> ::std::os::raw::c_int;
|
||||
}
|
||||
extern "C" {
|
||||
pub fn sqlite3_sql(pStmt: *mut sqlite3_stmt) -> *const ::std::os::raw::c_char;
|
||||
}
|
||||
@ -1199,6 +1160,12 @@ extern "C" {
|
||||
extern "C" {
|
||||
pub fn sqlite3_stmt_isexplain(pStmt: *mut sqlite3_stmt) -> ::std::os::raw::c_int;
|
||||
}
|
||||
extern "C" {
|
||||
pub fn sqlite3_stmt_explain(
|
||||
pStmt: *mut sqlite3_stmt,
|
||||
eMode: ::std::os::raw::c_int,
|
||||
) -> ::std::os::raw::c_int;
|
||||
}
|
||||
extern "C" {
|
||||
pub fn sqlite3_stmt_busy(arg1: *mut sqlite3_stmt) -> ::std::os::raw::c_int;
|
||||
}
|
||||
@ -1266,15 +1233,6 @@ extern "C" {
|
||||
arg5: ::std::option::Option<unsafe extern "C" fn(arg1: *mut ::std::os::raw::c_void)>,
|
||||
) -> ::std::os::raw::c_int;
|
||||
}
|
||||
extern "C" {
|
||||
pub fn sqlite3_bind_text16(
|
||||
arg1: *mut sqlite3_stmt,
|
||||
arg2: ::std::os::raw::c_int,
|
||||
arg3: *const ::std::os::raw::c_void,
|
||||
arg4: ::std::os::raw::c_int,
|
||||
arg5: ::std::option::Option<unsafe extern "C" fn(arg1: *mut ::std::os::raw::c_void)>,
|
||||
) -> ::std::os::raw::c_int;
|
||||
}
|
||||
extern "C" {
|
||||
pub fn sqlite3_bind_text64(
|
||||
arg1: *mut sqlite3_stmt,
|
||||
@ -1342,60 +1300,30 @@ extern "C" {
|
||||
N: ::std::os::raw::c_int,
|
||||
) -> *const ::std::os::raw::c_char;
|
||||
}
|
||||
extern "C" {
|
||||
pub fn sqlite3_column_name16(
|
||||
arg1: *mut sqlite3_stmt,
|
||||
N: ::std::os::raw::c_int,
|
||||
) -> *const ::std::os::raw::c_void;
|
||||
}
|
||||
extern "C" {
|
||||
pub fn sqlite3_column_database_name(
|
||||
arg1: *mut sqlite3_stmt,
|
||||
arg2: ::std::os::raw::c_int,
|
||||
) -> *const ::std::os::raw::c_char;
|
||||
}
|
||||
extern "C" {
|
||||
pub fn sqlite3_column_database_name16(
|
||||
arg1: *mut sqlite3_stmt,
|
||||
arg2: ::std::os::raw::c_int,
|
||||
) -> *const ::std::os::raw::c_void;
|
||||
}
|
||||
extern "C" {
|
||||
pub fn sqlite3_column_table_name(
|
||||
arg1: *mut sqlite3_stmt,
|
||||
arg2: ::std::os::raw::c_int,
|
||||
) -> *const ::std::os::raw::c_char;
|
||||
}
|
||||
extern "C" {
|
||||
pub fn sqlite3_column_table_name16(
|
||||
arg1: *mut sqlite3_stmt,
|
||||
arg2: ::std::os::raw::c_int,
|
||||
) -> *const ::std::os::raw::c_void;
|
||||
}
|
||||
extern "C" {
|
||||
pub fn sqlite3_column_origin_name(
|
||||
arg1: *mut sqlite3_stmt,
|
||||
arg2: ::std::os::raw::c_int,
|
||||
) -> *const ::std::os::raw::c_char;
|
||||
}
|
||||
extern "C" {
|
||||
pub fn sqlite3_column_origin_name16(
|
||||
arg1: *mut sqlite3_stmt,
|
||||
arg2: ::std::os::raw::c_int,
|
||||
) -> *const ::std::os::raw::c_void;
|
||||
}
|
||||
extern "C" {
|
||||
pub fn sqlite3_column_decltype(
|
||||
arg1: *mut sqlite3_stmt,
|
||||
arg2: ::std::os::raw::c_int,
|
||||
) -> *const ::std::os::raw::c_char;
|
||||
}
|
||||
extern "C" {
|
||||
pub fn sqlite3_column_decltype16(
|
||||
arg1: *mut sqlite3_stmt,
|
||||
arg2: ::std::os::raw::c_int,
|
||||
) -> *const ::std::os::raw::c_void;
|
||||
}
|
||||
extern "C" {
|
||||
pub fn sqlite3_step(arg1: *mut sqlite3_stmt) -> ::std::os::raw::c_int;
|
||||
}
|
||||
@ -1429,12 +1357,6 @@ extern "C" {
|
||||
iCol: ::std::os::raw::c_int,
|
||||
) -> *const ::std::os::raw::c_uchar;
|
||||
}
|
||||
extern "C" {
|
||||
pub fn sqlite3_column_text16(
|
||||
arg1: *mut sqlite3_stmt,
|
||||
iCol: ::std::os::raw::c_int,
|
||||
) -> *const ::std::os::raw::c_void;
|
||||
}
|
||||
extern "C" {
|
||||
pub fn sqlite3_column_value(
|
||||
arg1: *mut sqlite3_stmt,
|
||||
@ -1447,12 +1369,6 @@ extern "C" {
|
||||
iCol: ::std::os::raw::c_int,
|
||||
) -> ::std::os::raw::c_int;
|
||||
}
|
||||
extern "C" {
|
||||
pub fn sqlite3_column_bytes16(
|
||||
arg1: *mut sqlite3_stmt,
|
||||
iCol: ::std::os::raw::c_int,
|
||||
) -> ::std::os::raw::c_int;
|
||||
}
|
||||
extern "C" {
|
||||
pub fn sqlite3_column_type(
|
||||
arg1: *mut sqlite3_stmt,
|
||||
@ -1465,54 +1381,6 @@ extern "C" {
|
||||
extern "C" {
|
||||
pub fn sqlite3_reset(pStmt: *mut sqlite3_stmt) -> ::std::os::raw::c_int;
|
||||
}
|
||||
extern "C" {
|
||||
pub fn sqlite3_create_function(
|
||||
db: *mut sqlite3,
|
||||
zFunctionName: *const ::std::os::raw::c_char,
|
||||
nArg: ::std::os::raw::c_int,
|
||||
eTextRep: ::std::os::raw::c_int,
|
||||
pApp: *mut ::std::os::raw::c_void,
|
||||
xFunc: ::std::option::Option<
|
||||
unsafe extern "C" fn(
|
||||
arg1: *mut sqlite3_context,
|
||||
arg2: ::std::os::raw::c_int,
|
||||
arg3: *mut *mut sqlite3_value,
|
||||
),
|
||||
>,
|
||||
xStep: ::std::option::Option<
|
||||
unsafe extern "C" fn(
|
||||
arg1: *mut sqlite3_context,
|
||||
arg2: ::std::os::raw::c_int,
|
||||
arg3: *mut *mut sqlite3_value,
|
||||
),
|
||||
>,
|
||||
xFinal: ::std::option::Option<unsafe extern "C" fn(arg1: *mut sqlite3_context)>,
|
||||
) -> ::std::os::raw::c_int;
|
||||
}
|
||||
extern "C" {
|
||||
pub fn sqlite3_create_function16(
|
||||
db: *mut sqlite3,
|
||||
zFunctionName: *const ::std::os::raw::c_void,
|
||||
nArg: ::std::os::raw::c_int,
|
||||
eTextRep: ::std::os::raw::c_int,
|
||||
pApp: *mut ::std::os::raw::c_void,
|
||||
xFunc: ::std::option::Option<
|
||||
unsafe extern "C" fn(
|
||||
arg1: *mut sqlite3_context,
|
||||
arg2: ::std::os::raw::c_int,
|
||||
arg3: *mut *mut sqlite3_value,
|
||||
),
|
||||
>,
|
||||
xStep: ::std::option::Option<
|
||||
unsafe extern "C" fn(
|
||||
arg1: *mut sqlite3_context,
|
||||
arg2: ::std::os::raw::c_int,
|
||||
arg3: *mut *mut sqlite3_value,
|
||||
),
|
||||
>,
|
||||
xFinal: ::std::option::Option<unsafe extern "C" fn(arg1: *mut sqlite3_context)>,
|
||||
) -> ::std::os::raw::c_int;
|
||||
}
|
||||
extern "C" {
|
||||
pub fn sqlite3_create_function_v2(
|
||||
db: *mut sqlite3,
|
||||
@ -1616,21 +1484,9 @@ extern "C" {
|
||||
extern "C" {
|
||||
pub fn sqlite3_value_text(arg1: *mut sqlite3_value) -> *const ::std::os::raw::c_uchar;
|
||||
}
|
||||
extern "C" {
|
||||
pub fn sqlite3_value_text16(arg1: *mut sqlite3_value) -> *const ::std::os::raw::c_void;
|
||||
}
|
||||
extern "C" {
|
||||
pub fn sqlite3_value_text16le(arg1: *mut sqlite3_value) -> *const ::std::os::raw::c_void;
|
||||
}
|
||||
extern "C" {
|
||||
pub fn sqlite3_value_text16be(arg1: *mut sqlite3_value) -> *const ::std::os::raw::c_void;
|
||||
}
|
||||
extern "C" {
|
||||
pub fn sqlite3_value_bytes(arg1: *mut sqlite3_value) -> ::std::os::raw::c_int;
|
||||
}
|
||||
extern "C" {
|
||||
pub fn sqlite3_value_bytes16(arg1: *mut sqlite3_value) -> ::std::os::raw::c_int;
|
||||
}
|
||||
extern "C" {
|
||||
pub fn sqlite3_value_type(arg1: *mut sqlite3_value) -> ::std::os::raw::c_int;
|
||||
}
|
||||
@ -1643,6 +1499,9 @@ extern "C" {
|
||||
extern "C" {
|
||||
pub fn sqlite3_value_frombind(arg1: *mut sqlite3_value) -> ::std::os::raw::c_int;
|
||||
}
|
||||
extern "C" {
|
||||
pub fn sqlite3_value_encoding(arg1: *mut sqlite3_value) -> ::std::os::raw::c_int;
|
||||
}
|
||||
extern "C" {
|
||||
pub fn sqlite3_value_subtype(arg1: *mut sqlite3_value) -> ::std::os::raw::c_uint;
|
||||
}
|
||||
@ -1678,6 +1537,20 @@ extern "C" {
|
||||
arg3: ::std::option::Option<unsafe extern "C" fn(arg1: *mut ::std::os::raw::c_void)>,
|
||||
);
|
||||
}
|
||||
extern "C" {
|
||||
pub fn sqlite3_get_clientdata(
|
||||
arg1: *mut sqlite3,
|
||||
arg2: *const ::std::os::raw::c_char,
|
||||
) -> *mut ::std::os::raw::c_void;
|
||||
}
|
||||
extern "C" {
|
||||
pub fn sqlite3_set_clientdata(
|
||||
arg1: *mut sqlite3,
|
||||
arg2: *const ::std::os::raw::c_char,
|
||||
arg3: *mut ::std::os::raw::c_void,
|
||||
arg4: ::std::option::Option<unsafe extern "C" fn(arg1: *mut ::std::os::raw::c_void)>,
|
||||
) -> ::std::os::raw::c_int;
|
||||
}
|
||||
pub type sqlite3_destructor_type =
|
||||
::std::option::Option<unsafe extern "C" fn(arg1: *mut ::std::os::raw::c_void)>;
|
||||
extern "C" {
|
||||
@ -1706,13 +1579,6 @@ extern "C" {
|
||||
arg3: ::std::os::raw::c_int,
|
||||
);
|
||||
}
|
||||
extern "C" {
|
||||
pub fn sqlite3_result_error16(
|
||||
arg1: *mut sqlite3_context,
|
||||
arg2: *const ::std::os::raw::c_void,
|
||||
arg3: ::std::os::raw::c_int,
|
||||
);
|
||||
}
|
||||
extern "C" {
|
||||
pub fn sqlite3_result_error_toobig(arg1: *mut sqlite3_context);
|
||||
}
|
||||
@ -1748,30 +1614,6 @@ extern "C" {
|
||||
encoding: ::std::os::raw::c_uchar,
|
||||
);
|
||||
}
|
||||
extern "C" {
|
||||
pub fn sqlite3_result_text16(
|
||||
arg1: *mut sqlite3_context,
|
||||
arg2: *const ::std::os::raw::c_void,
|
||||
arg3: ::std::os::raw::c_int,
|
||||
arg4: ::std::option::Option<unsafe extern "C" fn(arg1: *mut ::std::os::raw::c_void)>,
|
||||
);
|
||||
}
|
||||
extern "C" {
|
||||
pub fn sqlite3_result_text16le(
|
||||
arg1: *mut sqlite3_context,
|
||||
arg2: *const ::std::os::raw::c_void,
|
||||
arg3: ::std::os::raw::c_int,
|
||||
arg4: ::std::option::Option<unsafe extern "C" fn(arg1: *mut ::std::os::raw::c_void)>,
|
||||
);
|
||||
}
|
||||
extern "C" {
|
||||
pub fn sqlite3_result_text16be(
|
||||
arg1: *mut sqlite3_context,
|
||||
arg2: *const ::std::os::raw::c_void,
|
||||
arg3: ::std::os::raw::c_int,
|
||||
arg4: ::std::option::Option<unsafe extern "C" fn(arg1: *mut ::std::os::raw::c_void)>,
|
||||
);
|
||||
}
|
||||
extern "C" {
|
||||
pub fn sqlite3_result_value(arg1: *mut sqlite3_context, arg2: *mut sqlite3_value);
|
||||
}
|
||||
@ -1795,23 +1637,6 @@ extern "C" {
|
||||
extern "C" {
|
||||
pub fn sqlite3_result_subtype(arg1: *mut sqlite3_context, arg2: ::std::os::raw::c_uint);
|
||||
}
|
||||
extern "C" {
|
||||
pub fn sqlite3_create_collation(
|
||||
arg1: *mut sqlite3,
|
||||
zName: *const ::std::os::raw::c_char,
|
||||
eTextRep: ::std::os::raw::c_int,
|
||||
pArg: *mut ::std::os::raw::c_void,
|
||||
xCompare: ::std::option::Option<
|
||||
unsafe extern "C" fn(
|
||||
arg1: *mut ::std::os::raw::c_void,
|
||||
arg2: ::std::os::raw::c_int,
|
||||
arg3: *const ::std::os::raw::c_void,
|
||||
arg4: ::std::os::raw::c_int,
|
||||
arg5: *const ::std::os::raw::c_void,
|
||||
) -> ::std::os::raw::c_int,
|
||||
>,
|
||||
) -> ::std::os::raw::c_int;
|
||||
}
|
||||
extern "C" {
|
||||
pub fn sqlite3_create_collation_v2(
|
||||
arg1: *mut sqlite3,
|
||||
@ -1830,23 +1655,6 @@ extern "C" {
|
||||
xDestroy: ::std::option::Option<unsafe extern "C" fn(arg1: *mut ::std::os::raw::c_void)>,
|
||||
) -> ::std::os::raw::c_int;
|
||||
}
|
||||
extern "C" {
|
||||
pub fn sqlite3_create_collation16(
|
||||
arg1: *mut sqlite3,
|
||||
zName: *const ::std::os::raw::c_void,
|
||||
eTextRep: ::std::os::raw::c_int,
|
||||
pArg: *mut ::std::os::raw::c_void,
|
||||
xCompare: ::std::option::Option<
|
||||
unsafe extern "C" fn(
|
||||
arg1: *mut ::std::os::raw::c_void,
|
||||
arg2: ::std::os::raw::c_int,
|
||||
arg3: *const ::std::os::raw::c_void,
|
||||
arg4: ::std::os::raw::c_int,
|
||||
arg5: *const ::std::os::raw::c_void,
|
||||
) -> ::std::os::raw::c_int,
|
||||
>,
|
||||
) -> ::std::os::raw::c_int;
|
||||
}
|
||||
extern "C" {
|
||||
pub fn sqlite3_collation_needed(
|
||||
arg1: *mut sqlite3,
|
||||
@ -1861,20 +1669,6 @@ extern "C" {
|
||||
>,
|
||||
) -> ::std::os::raw::c_int;
|
||||
}
|
||||
extern "C" {
|
||||
pub fn sqlite3_collation_needed16(
|
||||
arg1: *mut sqlite3,
|
||||
arg2: *mut ::std::os::raw::c_void,
|
||||
arg3: ::std::option::Option<
|
||||
unsafe extern "C" fn(
|
||||
arg1: *mut ::std::os::raw::c_void,
|
||||
arg2: *mut sqlite3,
|
||||
eTextRep: ::std::os::raw::c_int,
|
||||
arg3: *const ::std::os::raw::c_void,
|
||||
),
|
||||
>,
|
||||
) -> ::std::os::raw::c_int;
|
||||
}
|
||||
extern "C" {
|
||||
pub fn sqlite3_key(
|
||||
db: *mut sqlite3,
|
||||
@ -1929,12 +1723,6 @@ extern "C" {
|
||||
zValue: *const ::std::os::raw::c_char,
|
||||
) -> ::std::os::raw::c_int;
|
||||
}
|
||||
extern "C" {
|
||||
pub fn sqlite3_win32_set_directory16(
|
||||
type_: ::std::os::raw::c_ulong,
|
||||
zValue: *const ::std::os::raw::c_void,
|
||||
) -> ::std::os::raw::c_int;
|
||||
}
|
||||
extern "C" {
|
||||
pub fn sqlite3_get_autocommit(arg1: *mut sqlite3) -> ::std::os::raw::c_int;
|
||||
}
|
||||
@ -1951,7 +1739,7 @@ extern "C" {
|
||||
pub fn sqlite3_db_filename(
|
||||
db: *mut sqlite3,
|
||||
zDbName: *const ::std::os::raw::c_char,
|
||||
) -> *const ::std::os::raw::c_char;
|
||||
) -> sqlite3_filename;
|
||||
}
|
||||
extern "C" {
|
||||
pub fn sqlite3_db_readonly(
|
||||
@ -2198,6 +1986,15 @@ pub struct sqlite3_module {
|
||||
pub xShadowName: ::std::option::Option<
|
||||
unsafe extern "C" fn(arg1: *const ::std::os::raw::c_char) -> ::std::os::raw::c_int,
|
||||
>,
|
||||
pub xIntegrity: ::std::option::Option<
|
||||
unsafe extern "C" fn(
|
||||
pVTab: *mut sqlite3_vtab,
|
||||
zSchema: *const ::std::os::raw::c_char,
|
||||
zTabName: *const ::std::os::raw::c_char,
|
||||
mFlags: ::std::os::raw::c_int,
|
||||
pzErr: *mut *mut ::std::os::raw::c_char,
|
||||
) -> ::std::os::raw::c_int,
|
||||
>,
|
||||
}
|
||||
#[repr(C)]
|
||||
#[derive(Debug, Copy, Clone)]
|
||||
@ -2236,14 +2033,6 @@ pub struct sqlite3_index_constraint_usage {
|
||||
pub argvIndex: ::std::os::raw::c_int,
|
||||
pub omit: ::std::os::raw::c_uchar,
|
||||
}
|
||||
extern "C" {
|
||||
pub fn sqlite3_create_module(
|
||||
db: *mut sqlite3,
|
||||
zName: *const ::std::os::raw::c_char,
|
||||
p: *const sqlite3_module,
|
||||
pClientData: *mut ::std::os::raw::c_void,
|
||||
) -> ::std::os::raw::c_int;
|
||||
}
|
||||
extern "C" {
|
||||
pub fn sqlite3_create_module_v2(
|
||||
db: *mut sqlite3,
|
||||
@ -2759,6 +2548,15 @@ extern "C" {
|
||||
pOut: *mut ::std::os::raw::c_void,
|
||||
) -> ::std::os::raw::c_int;
|
||||
}
|
||||
extern "C" {
|
||||
pub fn sqlite3_stmt_scanstatus_v2(
|
||||
pStmt: *mut sqlite3_stmt,
|
||||
idx: ::std::os::raw::c_int,
|
||||
iScanStatusOp: ::std::os::raw::c_int,
|
||||
flags: ::std::os::raw::c_int,
|
||||
pOut: *mut ::std::os::raw::c_void,
|
||||
) -> ::std::os::raw::c_int;
|
||||
}
|
||||
extern "C" {
|
||||
pub fn sqlite3_stmt_scanstatus_reset(arg1: *mut sqlite3_stmt);
|
||||
}
|
||||
@ -3086,6 +2884,16 @@ extern "C" {
|
||||
ppOut: *mut *mut ::std::os::raw::c_void,
|
||||
) -> ::std::os::raw::c_int;
|
||||
}
|
||||
extern "C" {
|
||||
pub fn sqlite3changeset_upgrade(
|
||||
db: *mut sqlite3,
|
||||
zDb: *const ::std::os::raw::c_char,
|
||||
nIn: ::std::os::raw::c_int,
|
||||
pIn: *const ::std::os::raw::c_void,
|
||||
pnOut: *mut ::std::os::raw::c_int,
|
||||
ppOut: *mut *mut ::std::os::raw::c_void,
|
||||
) -> ::std::os::raw::c_int;
|
||||
}
|
||||
#[repr(C)]
|
||||
#[derive(Debug, Copy, Clone)]
|
||||
pub struct sqlite3_changegroup {
|
||||
@ -3094,6 +2902,13 @@ pub struct sqlite3_changegroup {
|
||||
extern "C" {
|
||||
pub fn sqlite3changegroup_new(pp: *mut *mut sqlite3_changegroup) -> ::std::os::raw::c_int;
|
||||
}
|
||||
extern "C" {
|
||||
pub fn sqlite3changegroup_schema(
|
||||
arg1: *mut sqlite3_changegroup,
|
||||
arg2: *mut sqlite3,
|
||||
zDb: *const ::std::os::raw::c_char,
|
||||
) -> ::std::os::raw::c_int;
|
||||
}
|
||||
extern "C" {
|
||||
pub fn sqlite3changegroup_add(
|
||||
arg1: *mut sqlite3_changegroup,
|
||||
@ -3555,6 +3370,24 @@ pub struct Fts5ExtensionApi {
|
||||
piCol: *mut ::std::os::raw::c_int,
|
||||
),
|
||||
>,
|
||||
pub xQueryToken: ::std::option::Option<
|
||||
unsafe extern "C" fn(
|
||||
arg1: *mut Fts5Context,
|
||||
iPhrase: ::std::os::raw::c_int,
|
||||
iToken: ::std::os::raw::c_int,
|
||||
ppToken: *mut *const ::std::os::raw::c_char,
|
||||
pnToken: *mut ::std::os::raw::c_int,
|
||||
) -> ::std::os::raw::c_int,
|
||||
>,
|
||||
pub xInstToken: ::std::option::Option<
|
||||
unsafe extern "C" fn(
|
||||
arg1: *mut Fts5Context,
|
||||
iIdx: ::std::os::raw::c_int,
|
||||
iToken: ::std::os::raw::c_int,
|
||||
arg2: *mut *const ::std::os::raw::c_char,
|
||||
arg3: *mut ::std::os::raw::c_int,
|
||||
) -> ::std::os::raw::c_int,
|
||||
>,
|
||||
}
|
||||
#[repr(C)]
|
||||
#[derive(Debug, Copy, Clone)]
|
||||
@ -3601,7 +3434,7 @@ pub struct fts5_api {
|
||||
unsafe extern "C" fn(
|
||||
pApi: *mut fts5_api,
|
||||
zName: *const ::std::os::raw::c_char,
|
||||
pContext: *mut ::std::os::raw::c_void,
|
||||
pUserData: *mut ::std::os::raw::c_void,
|
||||
pTokenizer: *mut fts5_tokenizer,
|
||||
xDestroy: ::std::option::Option<unsafe extern "C" fn(arg1: *mut ::std::os::raw::c_void)>,
|
||||
) -> ::std::os::raw::c_int,
|
||||
@ -3610,7 +3443,7 @@ pub struct fts5_api {
|
||||
unsafe extern "C" fn(
|
||||
pApi: *mut fts5_api,
|
||||
zName: *const ::std::os::raw::c_char,
|
||||
ppContext: *mut *mut ::std::os::raw::c_void,
|
||||
ppUserData: *mut *mut ::std::os::raw::c_void,
|
||||
pTokenizer: *mut fts5_tokenizer,
|
||||
) -> ::std::os::raw::c_int,
|
||||
>,
|
||||
@ -3618,7 +3451,7 @@ pub struct fts5_api {
|
||||
unsafe extern "C" fn(
|
||||
pApi: *mut fts5_api,
|
||||
zName: *const ::std::os::raw::c_char,
|
||||
pContext: *mut ::std::os::raw::c_void,
|
||||
pUserData: *mut ::std::os::raw::c_void,
|
||||
xFunction: fts5_extension_function,
|
||||
xDestroy: ::std::option::Option<unsafe extern "C" fn(arg1: *mut ::std::os::raw::c_void)>,
|
||||
) -> ::std::os::raw::c_int,
|
||||
|
31852
libsqlite3-sys/sqlcipher/sqlite3.c
vendored
31852
libsqlite3-sys/sqlcipher/sqlite3.c
vendored
File diff suppressed because it is too large
Load Diff
966
libsqlite3-sys/sqlcipher/sqlite3.h
vendored
966
libsqlite3-sys/sqlcipher/sqlite3.h
vendored
File diff suppressed because it is too large
Load Diff
22
libsqlite3-sys/sqlcipher/sqlite3ext.h
vendored
22
libsqlite3-sys/sqlcipher/sqlite3ext.h
vendored
@ -331,9 +331,9 @@ struct sqlite3_api_routines {
|
||||
const char *(*filename_journal)(const char*);
|
||||
const char *(*filename_wal)(const char*);
|
||||
/* Version 3.32.0 and later */
|
||||
char *(*create_filename)(const char*,const char*,const char*,
|
||||
const char *(*create_filename)(const char*,const char*,const char*,
|
||||
int,const char**);
|
||||
void (*free_filename)(char*);
|
||||
void (*free_filename)(const char*);
|
||||
sqlite3_file *(*database_file_object)(const char*);
|
||||
/* Version 3.34.0 and later */
|
||||
int (*txn_state)(sqlite3*,const char*);
|
||||
@ -357,6 +357,15 @@ struct sqlite3_api_routines {
|
||||
unsigned char *(*serialize)(sqlite3*,const char *,sqlite3_int64*,
|
||||
unsigned int);
|
||||
const char *(*db_name)(sqlite3*,int);
|
||||
/* Version 3.40.0 and later */
|
||||
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*));
|
||||
};
|
||||
|
||||
/*
|
||||
@ -681,6 +690,15 @@ typedef int (*sqlite3_loadext_entry)(
|
||||
#define sqlite3_serialize sqlite3_api->serialize
|
||||
#endif
|
||||
#define sqlite3_db_name sqlite3_api->db_name
|
||||
/* Version 3.40.0 and later */
|
||||
#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)
|
||||
|
279
libsqlite3-sys/sqlite3/bindgen_bundled_version.rs
vendored
279
libsqlite3-sys/sqlite3/bindgen_bundled_version.rs
vendored
@ -1,12 +1,12 @@
|
||||
/* automatically generated by rust-bindgen 0.69.2 */
|
||||
/* automatically generated by rust-bindgen 0.69.4 */
|
||||
|
||||
extern "C" {
|
||||
pub fn sqlite3_auto_extension(
|
||||
xEntryPoint: ::std::option::Option<
|
||||
unsafe extern "C" fn(
|
||||
db: *mut sqlite3,
|
||||
pzErrMsg: *mut *const ::std::os::raw::c_char,
|
||||
pThunk: *const sqlite3_api_routines,
|
||||
pzErrMsg: *mut *mut ::std::os::raw::c_char,
|
||||
_: *const sqlite3_api_routines,
|
||||
) -> ::std::os::raw::c_int,
|
||||
>,
|
||||
) -> ::std::os::raw::c_int;
|
||||
@ -16,17 +16,17 @@ extern "C" {
|
||||
xEntryPoint: ::std::option::Option<
|
||||
unsafe extern "C" fn(
|
||||
db: *mut sqlite3,
|
||||
pzErrMsg: *mut *const ::std::os::raw::c_char,
|
||||
pThunk: *const sqlite3_api_routines,
|
||||
pzErrMsg: *mut *mut ::std::os::raw::c_char,
|
||||
_: *const sqlite3_api_routines,
|
||||
) -> ::std::os::raw::c_int,
|
||||
>,
|
||||
) -> ::std::os::raw::c_int;
|
||||
}
|
||||
|
||||
pub const SQLITE_VERSION: &[u8; 7] = b"3.45.1\0";
|
||||
pub const SQLITE_VERSION_NUMBER: i32 = 3045001;
|
||||
pub const SQLITE_VERSION: &[u8; 7] = b"3.46.1\0";
|
||||
pub const SQLITE_VERSION_NUMBER: i32 = 3046001;
|
||||
pub const SQLITE_SOURCE_ID: &[u8; 85] =
|
||||
b"2024-01-30 16:01:20 e876e51a0ed5c5b3126f52e532044363a014bc594cfefa87ffb5b82257cc467a\0";
|
||||
b"2024-08-13 09:16:08 c9c2ab54ba1f5f46360f1b4f35d849cd3f080e6fc2b6c60e91b16c63f69a1e33\0";
|
||||
pub const SQLITE_OK: i32 = 0;
|
||||
pub const SQLITE_ERROR: i32 = 1;
|
||||
pub const SQLITE_INTERNAL: i32 = 2;
|
||||
@ -261,6 +261,7 @@ pub const SQLITE_CONFIG_STMTJRNL_SPILL: i32 = 26;
|
||||
pub const SQLITE_CONFIG_SMALL_MALLOC: i32 = 27;
|
||||
pub const SQLITE_CONFIG_SORTERREF_SIZE: i32 = 28;
|
||||
pub const SQLITE_CONFIG_MEMDB_MAXSIZE: i32 = 29;
|
||||
pub const SQLITE_CONFIG_ROWID_IN_VIEW: i32 = 30;
|
||||
pub const SQLITE_DBCONFIG_MAINDBNAME: i32 = 1000;
|
||||
pub const SQLITE_DBCONFIG_LOOKASIDE: i32 = 1001;
|
||||
pub const SQLITE_DBCONFIG_ENABLE_FKEY: i32 = 1002;
|
||||
@ -546,9 +547,6 @@ pub type sqlite3_uint64 = sqlite_uint64;
|
||||
extern "C" {
|
||||
pub fn sqlite3_close(arg1: *mut sqlite3) -> ::std::os::raw::c_int;
|
||||
}
|
||||
extern "C" {
|
||||
pub fn sqlite3_close_v2(arg1: *mut sqlite3) -> ::std::os::raw::c_int;
|
||||
}
|
||||
pub type sqlite3_callback = ::std::option::Option<
|
||||
unsafe extern "C" fn(
|
||||
arg1: *mut ::std::os::raw::c_void,
|
||||
@ -898,9 +896,6 @@ extern "C" {
|
||||
extern "C" {
|
||||
pub fn sqlite3_complete(sql: *const ::std::os::raw::c_char) -> ::std::os::raw::c_int;
|
||||
}
|
||||
extern "C" {
|
||||
pub fn sqlite3_complete16(sql: *const ::std::os::raw::c_void) -> ::std::os::raw::c_int;
|
||||
}
|
||||
extern "C" {
|
||||
pub fn sqlite3_busy_handler(
|
||||
arg1: *mut sqlite3,
|
||||
@ -1049,12 +1044,6 @@ extern "C" {
|
||||
ppDb: *mut *mut sqlite3,
|
||||
) -> ::std::os::raw::c_int;
|
||||
}
|
||||
extern "C" {
|
||||
pub fn sqlite3_open16(
|
||||
filename: *const ::std::os::raw::c_void,
|
||||
ppDb: *mut *mut sqlite3,
|
||||
) -> ::std::os::raw::c_int;
|
||||
}
|
||||
extern "C" {
|
||||
pub fn sqlite3_open_v2(
|
||||
filename: *const ::std::os::raw::c_char,
|
||||
@ -1122,9 +1111,6 @@ extern "C" {
|
||||
extern "C" {
|
||||
pub fn sqlite3_errmsg(arg1: *mut sqlite3) -> *const ::std::os::raw::c_char;
|
||||
}
|
||||
extern "C" {
|
||||
pub fn sqlite3_errmsg16(arg1: *mut sqlite3) -> *const ::std::os::raw::c_void;
|
||||
}
|
||||
extern "C" {
|
||||
pub fn sqlite3_errstr(arg1: ::std::os::raw::c_int) -> *const ::std::os::raw::c_char;
|
||||
}
|
||||
@ -1143,15 +1129,6 @@ extern "C" {
|
||||
newVal: ::std::os::raw::c_int,
|
||||
) -> ::std::os::raw::c_int;
|
||||
}
|
||||
extern "C" {
|
||||
pub fn sqlite3_prepare(
|
||||
db: *mut sqlite3,
|
||||
zSql: *const ::std::os::raw::c_char,
|
||||
nByte: ::std::os::raw::c_int,
|
||||
ppStmt: *mut *mut sqlite3_stmt,
|
||||
pzTail: *mut *const ::std::os::raw::c_char,
|
||||
) -> ::std::os::raw::c_int;
|
||||
}
|
||||
extern "C" {
|
||||
pub fn sqlite3_prepare_v2(
|
||||
db: *mut sqlite3,
|
||||
@ -1171,34 +1148,6 @@ extern "C" {
|
||||
pzTail: *mut *const ::std::os::raw::c_char,
|
||||
) -> ::std::os::raw::c_int;
|
||||
}
|
||||
extern "C" {
|
||||
pub fn sqlite3_prepare16(
|
||||
db: *mut sqlite3,
|
||||
zSql: *const ::std::os::raw::c_void,
|
||||
nByte: ::std::os::raw::c_int,
|
||||
ppStmt: *mut *mut sqlite3_stmt,
|
||||
pzTail: *mut *const ::std::os::raw::c_void,
|
||||
) -> ::std::os::raw::c_int;
|
||||
}
|
||||
extern "C" {
|
||||
pub fn sqlite3_prepare16_v2(
|
||||
db: *mut sqlite3,
|
||||
zSql: *const ::std::os::raw::c_void,
|
||||
nByte: ::std::os::raw::c_int,
|
||||
ppStmt: *mut *mut sqlite3_stmt,
|
||||
pzTail: *mut *const ::std::os::raw::c_void,
|
||||
) -> ::std::os::raw::c_int;
|
||||
}
|
||||
extern "C" {
|
||||
pub fn sqlite3_prepare16_v3(
|
||||
db: *mut sqlite3,
|
||||
zSql: *const ::std::os::raw::c_void,
|
||||
nByte: ::std::os::raw::c_int,
|
||||
prepFlags: ::std::os::raw::c_uint,
|
||||
ppStmt: *mut *mut sqlite3_stmt,
|
||||
pzTail: *mut *const ::std::os::raw::c_void,
|
||||
) -> ::std::os::raw::c_int;
|
||||
}
|
||||
extern "C" {
|
||||
pub fn sqlite3_sql(pStmt: *mut sqlite3_stmt) -> *const ::std::os::raw::c_char;
|
||||
}
|
||||
@ -1284,15 +1233,6 @@ extern "C" {
|
||||
arg5: ::std::option::Option<unsafe extern "C" fn(arg1: *mut ::std::os::raw::c_void)>,
|
||||
) -> ::std::os::raw::c_int;
|
||||
}
|
||||
extern "C" {
|
||||
pub fn sqlite3_bind_text16(
|
||||
arg1: *mut sqlite3_stmt,
|
||||
arg2: ::std::os::raw::c_int,
|
||||
arg3: *const ::std::os::raw::c_void,
|
||||
arg4: ::std::os::raw::c_int,
|
||||
arg5: ::std::option::Option<unsafe extern "C" fn(arg1: *mut ::std::os::raw::c_void)>,
|
||||
) -> ::std::os::raw::c_int;
|
||||
}
|
||||
extern "C" {
|
||||
pub fn sqlite3_bind_text64(
|
||||
arg1: *mut sqlite3_stmt,
|
||||
@ -1360,60 +1300,30 @@ extern "C" {
|
||||
N: ::std::os::raw::c_int,
|
||||
) -> *const ::std::os::raw::c_char;
|
||||
}
|
||||
extern "C" {
|
||||
pub fn sqlite3_column_name16(
|
||||
arg1: *mut sqlite3_stmt,
|
||||
N: ::std::os::raw::c_int,
|
||||
) -> *const ::std::os::raw::c_void;
|
||||
}
|
||||
extern "C" {
|
||||
pub fn sqlite3_column_database_name(
|
||||
arg1: *mut sqlite3_stmt,
|
||||
arg2: ::std::os::raw::c_int,
|
||||
) -> *const ::std::os::raw::c_char;
|
||||
}
|
||||
extern "C" {
|
||||
pub fn sqlite3_column_database_name16(
|
||||
arg1: *mut sqlite3_stmt,
|
||||
arg2: ::std::os::raw::c_int,
|
||||
) -> *const ::std::os::raw::c_void;
|
||||
}
|
||||
extern "C" {
|
||||
pub fn sqlite3_column_table_name(
|
||||
arg1: *mut sqlite3_stmt,
|
||||
arg2: ::std::os::raw::c_int,
|
||||
) -> *const ::std::os::raw::c_char;
|
||||
}
|
||||
extern "C" {
|
||||
pub fn sqlite3_column_table_name16(
|
||||
arg1: *mut sqlite3_stmt,
|
||||
arg2: ::std::os::raw::c_int,
|
||||
) -> *const ::std::os::raw::c_void;
|
||||
}
|
||||
extern "C" {
|
||||
pub fn sqlite3_column_origin_name(
|
||||
arg1: *mut sqlite3_stmt,
|
||||
arg2: ::std::os::raw::c_int,
|
||||
) -> *const ::std::os::raw::c_char;
|
||||
}
|
||||
extern "C" {
|
||||
pub fn sqlite3_column_origin_name16(
|
||||
arg1: *mut sqlite3_stmt,
|
||||
arg2: ::std::os::raw::c_int,
|
||||
) -> *const ::std::os::raw::c_void;
|
||||
}
|
||||
extern "C" {
|
||||
pub fn sqlite3_column_decltype(
|
||||
arg1: *mut sqlite3_stmt,
|
||||
arg2: ::std::os::raw::c_int,
|
||||
) -> *const ::std::os::raw::c_char;
|
||||
}
|
||||
extern "C" {
|
||||
pub fn sqlite3_column_decltype16(
|
||||
arg1: *mut sqlite3_stmt,
|
||||
arg2: ::std::os::raw::c_int,
|
||||
) -> *const ::std::os::raw::c_void;
|
||||
}
|
||||
extern "C" {
|
||||
pub fn sqlite3_step(arg1: *mut sqlite3_stmt) -> ::std::os::raw::c_int;
|
||||
}
|
||||
@ -1447,12 +1357,6 @@ extern "C" {
|
||||
iCol: ::std::os::raw::c_int,
|
||||
) -> *const ::std::os::raw::c_uchar;
|
||||
}
|
||||
extern "C" {
|
||||
pub fn sqlite3_column_text16(
|
||||
arg1: *mut sqlite3_stmt,
|
||||
iCol: ::std::os::raw::c_int,
|
||||
) -> *const ::std::os::raw::c_void;
|
||||
}
|
||||
extern "C" {
|
||||
pub fn sqlite3_column_value(
|
||||
arg1: *mut sqlite3_stmt,
|
||||
@ -1465,12 +1369,6 @@ extern "C" {
|
||||
iCol: ::std::os::raw::c_int,
|
||||
) -> ::std::os::raw::c_int;
|
||||
}
|
||||
extern "C" {
|
||||
pub fn sqlite3_column_bytes16(
|
||||
arg1: *mut sqlite3_stmt,
|
||||
iCol: ::std::os::raw::c_int,
|
||||
) -> ::std::os::raw::c_int;
|
||||
}
|
||||
extern "C" {
|
||||
pub fn sqlite3_column_type(
|
||||
arg1: *mut sqlite3_stmt,
|
||||
@ -1483,54 +1381,6 @@ extern "C" {
|
||||
extern "C" {
|
||||
pub fn sqlite3_reset(pStmt: *mut sqlite3_stmt) -> ::std::os::raw::c_int;
|
||||
}
|
||||
extern "C" {
|
||||
pub fn sqlite3_create_function(
|
||||
db: *mut sqlite3,
|
||||
zFunctionName: *const ::std::os::raw::c_char,
|
||||
nArg: ::std::os::raw::c_int,
|
||||
eTextRep: ::std::os::raw::c_int,
|
||||
pApp: *mut ::std::os::raw::c_void,
|
||||
xFunc: ::std::option::Option<
|
||||
unsafe extern "C" fn(
|
||||
arg1: *mut sqlite3_context,
|
||||
arg2: ::std::os::raw::c_int,
|
||||
arg3: *mut *mut sqlite3_value,
|
||||
),
|
||||
>,
|
||||
xStep: ::std::option::Option<
|
||||
unsafe extern "C" fn(
|
||||
arg1: *mut sqlite3_context,
|
||||
arg2: ::std::os::raw::c_int,
|
||||
arg3: *mut *mut sqlite3_value,
|
||||
),
|
||||
>,
|
||||
xFinal: ::std::option::Option<unsafe extern "C" fn(arg1: *mut sqlite3_context)>,
|
||||
) -> ::std::os::raw::c_int;
|
||||
}
|
||||
extern "C" {
|
||||
pub fn sqlite3_create_function16(
|
||||
db: *mut sqlite3,
|
||||
zFunctionName: *const ::std::os::raw::c_void,
|
||||
nArg: ::std::os::raw::c_int,
|
||||
eTextRep: ::std::os::raw::c_int,
|
||||
pApp: *mut ::std::os::raw::c_void,
|
||||
xFunc: ::std::option::Option<
|
||||
unsafe extern "C" fn(
|
||||
arg1: *mut sqlite3_context,
|
||||
arg2: ::std::os::raw::c_int,
|
||||
arg3: *mut *mut sqlite3_value,
|
||||
),
|
||||
>,
|
||||
xStep: ::std::option::Option<
|
||||
unsafe extern "C" fn(
|
||||
arg1: *mut sqlite3_context,
|
||||
arg2: ::std::os::raw::c_int,
|
||||
arg3: *mut *mut sqlite3_value,
|
||||
),
|
||||
>,
|
||||
xFinal: ::std::option::Option<unsafe extern "C" fn(arg1: *mut sqlite3_context)>,
|
||||
) -> ::std::os::raw::c_int;
|
||||
}
|
||||
extern "C" {
|
||||
pub fn sqlite3_create_function_v2(
|
||||
db: *mut sqlite3,
|
||||
@ -1634,21 +1484,9 @@ extern "C" {
|
||||
extern "C" {
|
||||
pub fn sqlite3_value_text(arg1: *mut sqlite3_value) -> *const ::std::os::raw::c_uchar;
|
||||
}
|
||||
extern "C" {
|
||||
pub fn sqlite3_value_text16(arg1: *mut sqlite3_value) -> *const ::std::os::raw::c_void;
|
||||
}
|
||||
extern "C" {
|
||||
pub fn sqlite3_value_text16le(arg1: *mut sqlite3_value) -> *const ::std::os::raw::c_void;
|
||||
}
|
||||
extern "C" {
|
||||
pub fn sqlite3_value_text16be(arg1: *mut sqlite3_value) -> *const ::std::os::raw::c_void;
|
||||
}
|
||||
extern "C" {
|
||||
pub fn sqlite3_value_bytes(arg1: *mut sqlite3_value) -> ::std::os::raw::c_int;
|
||||
}
|
||||
extern "C" {
|
||||
pub fn sqlite3_value_bytes16(arg1: *mut sqlite3_value) -> ::std::os::raw::c_int;
|
||||
}
|
||||
extern "C" {
|
||||
pub fn sqlite3_value_type(arg1: *mut sqlite3_value) -> ::std::os::raw::c_int;
|
||||
}
|
||||
@ -1741,13 +1579,6 @@ extern "C" {
|
||||
arg3: ::std::os::raw::c_int,
|
||||
);
|
||||
}
|
||||
extern "C" {
|
||||
pub fn sqlite3_result_error16(
|
||||
arg1: *mut sqlite3_context,
|
||||
arg2: *const ::std::os::raw::c_void,
|
||||
arg3: ::std::os::raw::c_int,
|
||||
);
|
||||
}
|
||||
extern "C" {
|
||||
pub fn sqlite3_result_error_toobig(arg1: *mut sqlite3_context);
|
||||
}
|
||||
@ -1783,30 +1614,6 @@ extern "C" {
|
||||
encoding: ::std::os::raw::c_uchar,
|
||||
);
|
||||
}
|
||||
extern "C" {
|
||||
pub fn sqlite3_result_text16(
|
||||
arg1: *mut sqlite3_context,
|
||||
arg2: *const ::std::os::raw::c_void,
|
||||
arg3: ::std::os::raw::c_int,
|
||||
arg4: ::std::option::Option<unsafe extern "C" fn(arg1: *mut ::std::os::raw::c_void)>,
|
||||
);
|
||||
}
|
||||
extern "C" {
|
||||
pub fn sqlite3_result_text16le(
|
||||
arg1: *mut sqlite3_context,
|
||||
arg2: *const ::std::os::raw::c_void,
|
||||
arg3: ::std::os::raw::c_int,
|
||||
arg4: ::std::option::Option<unsafe extern "C" fn(arg1: *mut ::std::os::raw::c_void)>,
|
||||
);
|
||||
}
|
||||
extern "C" {
|
||||
pub fn sqlite3_result_text16be(
|
||||
arg1: *mut sqlite3_context,
|
||||
arg2: *const ::std::os::raw::c_void,
|
||||
arg3: ::std::os::raw::c_int,
|
||||
arg4: ::std::option::Option<unsafe extern "C" fn(arg1: *mut ::std::os::raw::c_void)>,
|
||||
);
|
||||
}
|
||||
extern "C" {
|
||||
pub fn sqlite3_result_value(arg1: *mut sqlite3_context, arg2: *mut sqlite3_value);
|
||||
}
|
||||
@ -1830,23 +1637,6 @@ extern "C" {
|
||||
extern "C" {
|
||||
pub fn sqlite3_result_subtype(arg1: *mut sqlite3_context, arg2: ::std::os::raw::c_uint);
|
||||
}
|
||||
extern "C" {
|
||||
pub fn sqlite3_create_collation(
|
||||
arg1: *mut sqlite3,
|
||||
zName: *const ::std::os::raw::c_char,
|
||||
eTextRep: ::std::os::raw::c_int,
|
||||
pArg: *mut ::std::os::raw::c_void,
|
||||
xCompare: ::std::option::Option<
|
||||
unsafe extern "C" fn(
|
||||
arg1: *mut ::std::os::raw::c_void,
|
||||
arg2: ::std::os::raw::c_int,
|
||||
arg3: *const ::std::os::raw::c_void,
|
||||
arg4: ::std::os::raw::c_int,
|
||||
arg5: *const ::std::os::raw::c_void,
|
||||
) -> ::std::os::raw::c_int,
|
||||
>,
|
||||
) -> ::std::os::raw::c_int;
|
||||
}
|
||||
extern "C" {
|
||||
pub fn sqlite3_create_collation_v2(
|
||||
arg1: *mut sqlite3,
|
||||
@ -1865,23 +1655,6 @@ extern "C" {
|
||||
xDestroy: ::std::option::Option<unsafe extern "C" fn(arg1: *mut ::std::os::raw::c_void)>,
|
||||
) -> ::std::os::raw::c_int;
|
||||
}
|
||||
extern "C" {
|
||||
pub fn sqlite3_create_collation16(
|
||||
arg1: *mut sqlite3,
|
||||
zName: *const ::std::os::raw::c_void,
|
||||
eTextRep: ::std::os::raw::c_int,
|
||||
pArg: *mut ::std::os::raw::c_void,
|
||||
xCompare: ::std::option::Option<
|
||||
unsafe extern "C" fn(
|
||||
arg1: *mut ::std::os::raw::c_void,
|
||||
arg2: ::std::os::raw::c_int,
|
||||
arg3: *const ::std::os::raw::c_void,
|
||||
arg4: ::std::os::raw::c_int,
|
||||
arg5: *const ::std::os::raw::c_void,
|
||||
) -> ::std::os::raw::c_int,
|
||||
>,
|
||||
) -> ::std::os::raw::c_int;
|
||||
}
|
||||
extern "C" {
|
||||
pub fn sqlite3_collation_needed(
|
||||
arg1: *mut sqlite3,
|
||||
@ -1896,20 +1669,6 @@ extern "C" {
|
||||
>,
|
||||
) -> ::std::os::raw::c_int;
|
||||
}
|
||||
extern "C" {
|
||||
pub fn sqlite3_collation_needed16(
|
||||
arg1: *mut sqlite3,
|
||||
arg2: *mut ::std::os::raw::c_void,
|
||||
arg3: ::std::option::Option<
|
||||
unsafe extern "C" fn(
|
||||
arg1: *mut ::std::os::raw::c_void,
|
||||
arg2: *mut sqlite3,
|
||||
eTextRep: ::std::os::raw::c_int,
|
||||
arg3: *const ::std::os::raw::c_void,
|
||||
),
|
||||
>,
|
||||
) -> ::std::os::raw::c_int;
|
||||
}
|
||||
extern "C" {
|
||||
pub fn sqlite3_sleep(arg1: ::std::os::raw::c_int) -> ::std::os::raw::c_int;
|
||||
}
|
||||
@ -1931,12 +1690,6 @@ extern "C" {
|
||||
zValue: *const ::std::os::raw::c_char,
|
||||
) -> ::std::os::raw::c_int;
|
||||
}
|
||||
extern "C" {
|
||||
pub fn sqlite3_win32_set_directory16(
|
||||
type_: ::std::os::raw::c_ulong,
|
||||
zValue: *const ::std::os::raw::c_void,
|
||||
) -> ::std::os::raw::c_int;
|
||||
}
|
||||
extern "C" {
|
||||
pub fn sqlite3_get_autocommit(arg1: *mut sqlite3) -> ::std::os::raw::c_int;
|
||||
}
|
||||
@ -2247,14 +2000,6 @@ pub struct sqlite3_index_constraint_usage {
|
||||
pub argvIndex: ::std::os::raw::c_int,
|
||||
pub omit: ::std::os::raw::c_uchar,
|
||||
}
|
||||
extern "C" {
|
||||
pub fn sqlite3_create_module(
|
||||
db: *mut sqlite3,
|
||||
zName: *const ::std::os::raw::c_char,
|
||||
p: *const sqlite3_module,
|
||||
pClientData: *mut ::std::os::raw::c_void,
|
||||
) -> ::std::os::raw::c_int;
|
||||
}
|
||||
extern "C" {
|
||||
pub fn sqlite3_create_module_v2(
|
||||
db: *mut sqlite3,
|
||||
@ -3138,6 +2883,12 @@ extern "C" {
|
||||
pData: *mut ::std::os::raw::c_void,
|
||||
) -> ::std::os::raw::c_int;
|
||||
}
|
||||
extern "C" {
|
||||
pub fn sqlite3changegroup_add_change(
|
||||
arg1: *mut sqlite3_changegroup,
|
||||
arg2: *mut sqlite3_changeset_iter,
|
||||
) -> ::std::os::raw::c_int;
|
||||
}
|
||||
extern "C" {
|
||||
pub fn sqlite3changegroup_output(
|
||||
arg1: *mut sqlite3_changegroup,
|
||||
|
File diff suppressed because it is too large
Load Diff
9077
libsqlite3-sys/sqlite3/sqlite3.c
vendored
9077
libsqlite3-sys/sqlite3/sqlite3.c
vendored
File diff suppressed because it is too large
Load Diff
116
libsqlite3-sys/sqlite3/sqlite3.h
vendored
116
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.45.1"
|
||||
#define SQLITE_VERSION_NUMBER 3045001
|
||||
#define SQLITE_SOURCE_ID "2024-01-30 16:01:20 e876e51a0ed5c5b3126f52e532044363a014bc594cfefa87ffb5b82257cc467a"
|
||||
#define SQLITE_VERSION "3.46.1"
|
||||
#define SQLITE_VERSION_NUMBER 3046001
|
||||
#define SQLITE_SOURCE_ID "2024-08-13 09:16:08 c9c2ab54ba1f5f46360f1b4f35d849cd3f080e6fc2b6c60e91b16c63f69a1e33"
|
||||
|
||||
/*
|
||||
** CAPI3REF: Run-Time Library Version Numbers
|
||||
@ -420,6 +420,8 @@ typedef int (*sqlite3_callback)(void*,int,char**, char**);
|
||||
** the 1st parameter to sqlite3_exec() while sqlite3_exec() is running.
|
||||
** <li> The application must not modify the SQL statement text passed into
|
||||
** the 2nd parameter of sqlite3_exec() while sqlite3_exec() is running.
|
||||
** <li> The application must not dereference the arrays or string pointers
|
||||
** passed as the 3rd and 4th callback parameters after it returns.
|
||||
** </ul>
|
||||
*/
|
||||
SQLITE_API int sqlite3_exec(
|
||||
@ -762,11 +764,11 @@ struct sqlite3_file {
|
||||
** </ul>
|
||||
** xLock() upgrades the database file lock. In other words, xLock() moves the
|
||||
** database file lock in the direction NONE toward EXCLUSIVE. The argument to
|
||||
** xLock() is always on of SHARED, RESERVED, PENDING, or EXCLUSIVE, never
|
||||
** xLock() is always one of SHARED, RESERVED, PENDING, or EXCLUSIVE, never
|
||||
** SQLITE_LOCK_NONE. If the database file lock is already at or above the
|
||||
** requested lock, then the call to xLock() is a no-op.
|
||||
** xUnlock() downgrades the database file lock to either SHARED or NONE.
|
||||
* If the lock is already at or below the requested lock state, then the call
|
||||
** If the lock is already at or below the requested lock state, then the call
|
||||
** to xUnlock() is a no-op.
|
||||
** The xCheckReservedLock() method checks whether any database connection,
|
||||
** either in this process or in some other process, is holding a RESERVED,
|
||||
@ -2141,6 +2143,22 @@ struct sqlite3_mem_methods {
|
||||
** configuration setting is never used, then the default maximum is determined
|
||||
** by the [SQLITE_MEMDB_DEFAULT_MAXSIZE] compile-time option. If that
|
||||
** compile-time option is not set, then the default maximum is 1073741824.
|
||||
**
|
||||
** [[SQLITE_CONFIG_ROWID_IN_VIEW]]
|
||||
** <dt>SQLITE_CONFIG_ROWID_IN_VIEW
|
||||
** <dd>The SQLITE_CONFIG_ROWID_IN_VIEW option enables or disables the ability
|
||||
** for VIEWs to have a ROWID. The capability can only be enabled if SQLite is
|
||||
** compiled with -DSQLITE_ALLOW_ROWID_IN_VIEW, in which case the capability
|
||||
** defaults to on. This configuration option queries the current setting or
|
||||
** changes the setting to off or on. The argument is a pointer to an integer.
|
||||
** If that integer initially holds a value of 1, then the ability for VIEWs to
|
||||
** have ROWIDs is activated. If the integer initially holds zero, then the
|
||||
** ability is deactivated. Any other initial value for the integer leaves the
|
||||
** setting unchanged. After changes, if any, the integer is written with
|
||||
** a 1 or 0, if the ability for VIEWs to have ROWIDs is on or off. If SQLite
|
||||
** is compiled without -DSQLITE_ALLOW_ROWID_IN_VIEW (which is the usual and
|
||||
** recommended case) then the integer is always filled with zero, regardless
|
||||
** if its initial value.
|
||||
** </dl>
|
||||
*/
|
||||
#define SQLITE_CONFIG_SINGLETHREAD 1 /* nil */
|
||||
@ -2172,6 +2190,7 @@ struct sqlite3_mem_methods {
|
||||
#define SQLITE_CONFIG_SMALL_MALLOC 27 /* boolean */
|
||||
#define SQLITE_CONFIG_SORTERREF_SIZE 28 /* int nByte */
|
||||
#define SQLITE_CONFIG_MEMDB_MAXSIZE 29 /* sqlite3_int64 */
|
||||
#define SQLITE_CONFIG_ROWID_IN_VIEW 30 /* int* */
|
||||
|
||||
/*
|
||||
** CAPI3REF: Database Connection Configuration Options
|
||||
@ -3286,8 +3305,8 @@ SQLITE_API int sqlite3_set_authorizer(
|
||||
#define SQLITE_RECURSIVE 33 /* NULL NULL */
|
||||
|
||||
/*
|
||||
** CAPI3REF: Tracing And Profiling Functions
|
||||
** METHOD: sqlite3
|
||||
** CAPI3REF: Deprecated Tracing And Profiling Functions
|
||||
** DEPRECATED
|
||||
**
|
||||
** These routines are deprecated. Use the [sqlite3_trace_v2()] interface
|
||||
** instead of the routines described here.
|
||||
@ -6868,6 +6887,12 @@ SQLITE_API int sqlite3_autovacuum_pages(
|
||||
** The exceptions defined in this paragraph might change in a future
|
||||
** release of SQLite.
|
||||
**
|
||||
** Whether the update hook is invoked before or after the
|
||||
** corresponding change is currently unspecified and may differ
|
||||
** depending on the type of change. Do not rely on the order of the
|
||||
** hook call with regards to the final result of the operation which
|
||||
** triggers the hook.
|
||||
**
|
||||
** The update hook implementation must not do anything that will modify
|
||||
** the database connection that invoked the update hook. Any actions
|
||||
** to modify the database connection must be deferred until after the
|
||||
@ -8338,7 +8363,7 @@ SQLITE_API int sqlite3_test_control(int op, ...);
|
||||
** The sqlite3_keyword_count() interface returns the number of distinct
|
||||
** keywords understood by SQLite.
|
||||
**
|
||||
** The sqlite3_keyword_name(N,Z,L) interface finds the N-th keyword and
|
||||
** The sqlite3_keyword_name(N,Z,L) interface finds the 0-based N-th keyword and
|
||||
** makes *Z point to that keyword expressed as UTF8 and writes the number
|
||||
** of bytes in the keyword into *L. The string that *Z points to is not
|
||||
** zero-terminated. The sqlite3_keyword_name(N,Z,L) routine returns
|
||||
@ -9917,24 +9942,45 @@ SQLITE_API const char *sqlite3_vtab_collation(sqlite3_index_info*,int);
|
||||
** <li value="2"><p>
|
||||
** ^(If the sqlite3_vtab_distinct() interface returns 2, that means
|
||||
** that the query planner does not need the rows returned in any particular
|
||||
** order, as long as rows with the same values in all "aOrderBy" columns
|
||||
** are adjacent.)^ ^(Furthermore, only a single row for each particular
|
||||
** combination of values in the columns identified by the "aOrderBy" field
|
||||
** needs to be returned.)^ ^It is always ok for two or more rows with the same
|
||||
** values in all "aOrderBy" columns to be returned, as long as all such rows
|
||||
** are adjacent. ^The virtual table may, if it chooses, omit extra rows
|
||||
** that have the same value for all columns identified by "aOrderBy".
|
||||
** ^However omitting the extra rows is optional.
|
||||
** order, as long as rows with the same values in all columns identified
|
||||
** by "aOrderBy" are adjacent.)^ ^(Furthermore, when two or more rows
|
||||
** contain the same values for all columns identified by "colUsed", all but
|
||||
** one such row may optionally be omitted from the result.)^
|
||||
** The virtual table is not required to omit rows that are duplicates
|
||||
** over the "colUsed" columns, but if the virtual table can do that without
|
||||
** too much extra effort, it could potentially help the query to run faster.
|
||||
** This mode is used for a DISTINCT query.
|
||||
** <li value="3"><p>
|
||||
** ^(If the sqlite3_vtab_distinct() interface returns 3, that means
|
||||
** that the query planner needs only distinct rows but it does need the
|
||||
** rows to be sorted.)^ ^The virtual table implementation is free to omit
|
||||
** rows that are identical in all aOrderBy columns, if it wants to, but
|
||||
** it is not required to omit any rows. This mode is used for queries
|
||||
** ^(If the sqlite3_vtab_distinct() interface returns 3, that means the
|
||||
** virtual table must return rows in the order defined by "aOrderBy" as
|
||||
** if the sqlite3_vtab_distinct() interface had returned 0. However if
|
||||
** two or more rows in the result have the same values for all columns
|
||||
** identified by "colUsed", then all but one such row may optionally be
|
||||
** omitted.)^ Like when the return value is 2, the virtual table
|
||||
** is not required to omit rows that are duplicates over the "colUsed"
|
||||
** columns, but if the virtual table can do that without
|
||||
** too much extra effort, it could potentially help the query to run faster.
|
||||
** This mode is used for queries
|
||||
** that have both DISTINCT and ORDER BY clauses.
|
||||
** </ol>
|
||||
**
|
||||
** <p>The following table summarizes the conditions under which the
|
||||
** virtual table is allowed to set the "orderByConsumed" flag based on
|
||||
** the value returned by sqlite3_vtab_distinct(). This table is a
|
||||
** restatement of the previous four paragraphs:
|
||||
**
|
||||
** <table border=1 cellspacing=0 cellpadding=10 width="90%">
|
||||
** <tr>
|
||||
** <td valign="top">sqlite3_vtab_distinct() return value
|
||||
** <td valign="top">Rows are returned in aOrderBy order
|
||||
** <td valign="top">Rows with the same value in all aOrderBy columns are adjacent
|
||||
** <td valign="top">Duplicates over all colUsed columns may be omitted
|
||||
** <tr><td>0<td>yes<td>yes<td>no
|
||||
** <tr><td>1<td>no<td>yes<td>no
|
||||
** <tr><td>2<td>no<td>yes<td>yes
|
||||
** <tr><td>3<td>yes<td>yes<td>yes
|
||||
** </table>
|
||||
**
|
||||
** ^For the purposes of comparing virtual table output values to see if the
|
||||
** values are same value for sorting purposes, two NULL values are considered
|
||||
** to be the same. In other words, the comparison operator is "IS"
|
||||
@ -11979,6 +12025,30 @@ SQLITE_API int sqlite3changegroup_schema(sqlite3_changegroup*, sqlite3*, const c
|
||||
*/
|
||||
SQLITE_API int sqlite3changegroup_add(sqlite3_changegroup*, int nData, void *pData);
|
||||
|
||||
/*
|
||||
** CAPI3REF: Add A Single Change To A Changegroup
|
||||
** METHOD: sqlite3_changegroup
|
||||
**
|
||||
** This function adds the single change currently indicated by the iterator
|
||||
** passed as the second argument to the changegroup object. The rules for
|
||||
** adding the change are just as described for [sqlite3changegroup_add()].
|
||||
**
|
||||
** If the change is successfully added to the changegroup, SQLITE_OK is
|
||||
** returned. Otherwise, an SQLite error code is returned.
|
||||
**
|
||||
** The iterator must point to a valid entry when this function is called.
|
||||
** If it does not, SQLITE_ERROR is returned and no change is added to the
|
||||
** changegroup. Additionally, the iterator must not have been opened with
|
||||
** the SQLITE_CHANGESETAPPLY_INVERT flag. In this case SQLITE_ERROR is also
|
||||
** returned.
|
||||
*/
|
||||
SQLITE_API int sqlite3changegroup_add_change(
|
||||
sqlite3_changegroup*,
|
||||
sqlite3_changeset_iter*
|
||||
);
|
||||
|
||||
|
||||
|
||||
/*
|
||||
** CAPI3REF: Obtain A Composite Changeset From A Changegroup
|
||||
** METHOD: sqlite3_changegroup
|
||||
@ -12783,8 +12853,8 @@ struct Fts5PhraseIter {
|
||||
** EXTENSION API FUNCTIONS
|
||||
**
|
||||
** xUserData(pFts):
|
||||
** Return a copy of the context pointer the extension function was
|
||||
** registered with.
|
||||
** Return a copy of the pUserData pointer passed to the xCreateFunction()
|
||||
** API when the extension function was registered.
|
||||
**
|
||||
** xColumnTotalSize(pFts, iCol, pnToken):
|
||||
** If parameter iCol is less than zero, set output variable *pnToken
|
||||
|
@ -16,17 +16,17 @@ pub enum ErrorCode {
|
||||
DatabaseBusy,
|
||||
/// A table in the database is locked
|
||||
DatabaseLocked,
|
||||
/// A malloc() failed
|
||||
/// A `malloc()` failed
|
||||
OutOfMemory,
|
||||
/// Attempt to write a readonly database
|
||||
ReadOnly,
|
||||
/// Operation terminated by sqlite3_interrupt()
|
||||
/// Operation terminated by `sqlite3_interrupt()`
|
||||
OperationInterrupted,
|
||||
/// Some kind of disk I/O error occurred
|
||||
SystemIoFailure,
|
||||
/// The database disk image is malformed
|
||||
DatabaseCorrupt,
|
||||
/// Unknown opcode in sqlite3_file_control()
|
||||
/// Unknown opcode in `sqlite3_file_control()`
|
||||
NotFound,
|
||||
/// Insertion failed because database is full
|
||||
DiskFull,
|
||||
@ -48,7 +48,7 @@ pub enum ErrorCode {
|
||||
NoLargeFileSupport,
|
||||
/// Authorization denied
|
||||
AuthorizationForStatementDenied,
|
||||
/// 2nd parameter to sqlite3_bind out of range
|
||||
/// 2nd parameter to `sqlite3_bind` out of range
|
||||
ParameterOutOfRange,
|
||||
/// File opened that is not a database file
|
||||
NotADatabase,
|
||||
@ -64,7 +64,7 @@ pub struct Error {
|
||||
|
||||
impl Error {
|
||||
#[must_use]
|
||||
pub fn new(result_code: c_int) -> Error {
|
||||
pub fn new(result_code: c_int) -> Self {
|
||||
let code = match result_code & 0xff {
|
||||
super::SQLITE_INTERNAL => ErrorCode::InternalMalfunction,
|
||||
super::SQLITE_PERM => ErrorCode::PermissionDenied,
|
||||
@ -92,7 +92,7 @@ impl Error {
|
||||
_ => ErrorCode::Unknown,
|
||||
};
|
||||
|
||||
Error {
|
||||
Self {
|
||||
code,
|
||||
extended_code: result_code,
|
||||
}
|
||||
@ -118,7 +118,7 @@ impl error::Error for Error {
|
||||
|
||||
// Result codes.
|
||||
// Note: These are not public because our bindgen bindings export whichever
|
||||
// constants are present in the current version of SQLite. We repeat them here
|
||||
// constants are present in the current version of SQLite. We repeat them here,
|
||||
// so we don't have to worry about which version of SQLite added which
|
||||
// constants, and we only use them to implement code_to_str below.
|
||||
|
||||
@ -281,20 +281,20 @@ pub fn code_to_str(code: c_int) -> &'static str {
|
||||
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
|
||||
/// 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 {
|
||||
Self::VersionMismatch {
|
||||
compile_time,
|
||||
runtime,
|
||||
} => {
|
||||
write!(f, "SQLite version mismatch: {runtime} < {compile_time}")
|
||||
}
|
||||
InitError::NullFunctionPointer => {
|
||||
Self::NullFunctionPointer => {
|
||||
write!(f, "Some sqlite3_api_routines fields are null")
|
||||
}
|
||||
}
|
||||
@ -302,3 +302,42 @@ impl ::std::fmt::Display for InitError {
|
||||
}
|
||||
#[cfg(feature = "loadable_extension")]
|
||||
impl error::Error for InitError {}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use crate::*;
|
||||
|
||||
#[test]
|
||||
pub fn error_new() {
|
||||
let assoc = vec![
|
||||
(SQLITE_INTERNAL, ErrorCode::InternalMalfunction),
|
||||
(SQLITE_PERM, ErrorCode::PermissionDenied),
|
||||
(SQLITE_ABORT_ROLLBACK, ErrorCode::OperationAborted),
|
||||
(SQLITE_BUSY_RECOVERY, ErrorCode::DatabaseBusy),
|
||||
(SQLITE_LOCKED_SHAREDCACHE, ErrorCode::DatabaseLocked),
|
||||
(SQLITE_NOMEM, ErrorCode::OutOfMemory),
|
||||
(SQLITE_IOERR_READ, ErrorCode::SystemIoFailure),
|
||||
(SQLITE_NOTFOUND, ErrorCode::NotFound),
|
||||
(SQLITE_FULL, ErrorCode::DiskFull),
|
||||
(SQLITE_PROTOCOL, ErrorCode::FileLockingProtocolFailed),
|
||||
(SQLITE_SCHEMA, ErrorCode::SchemaChanged),
|
||||
(SQLITE_TOOBIG, ErrorCode::TooBig),
|
||||
(SQLITE_MISMATCH, ErrorCode::TypeMismatch),
|
||||
(SQLITE_NOLFS, ErrorCode::NoLargeFileSupport),
|
||||
(SQLITE_RANGE, ErrorCode::ParameterOutOfRange),
|
||||
(SQLITE_NOTADB, ErrorCode::NotADatabase),
|
||||
];
|
||||
for (sqlite_code, rust_code) in assoc {
|
||||
let err = Error::new(sqlite_code);
|
||||
assert_eq!(
|
||||
err,
|
||||
Error {
|
||||
code: rust_code,
|
||||
extended_code: sqlite_code
|
||||
}
|
||||
);
|
||||
let s = format!("{err}");
|
||||
assert!(!s.is_empty());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -18,10 +18,10 @@ pub fn SQLITE_STATIC() -> sqlite3_destructor_type {
|
||||
|
||||
#[must_use]
|
||||
pub fn SQLITE_TRANSIENT() -> sqlite3_destructor_type {
|
||||
Some(unsafe { mem::transmute(-1_isize) })
|
||||
Some(unsafe { mem::transmute::<isize, unsafe extern "C" fn(*mut std::ffi::c_void)>(-1_isize) })
|
||||
}
|
||||
|
||||
#[allow(clippy::all)]
|
||||
#[allow(dead_code, clippy::all)]
|
||||
mod bindings {
|
||||
include!(concat!(env!("OUT_DIR"), "/bindgen.rs"));
|
||||
}
|
||||
|
@ -9,7 +9,7 @@ export SQLITE3_LIB_DIR="$SCRIPT_DIR/sqlite3"
|
||||
mkdir -p "$TARGET_DIR" "$SQLITE3_LIB_DIR"
|
||||
|
||||
# Download and extract amalgamation
|
||||
SQLITE=sqlite-amalgamation-3450100
|
||||
SQLITE=sqlite-amalgamation-3460100
|
||||
curl -O https://sqlite.org/2024/$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"
|
||||
@ -19,7 +19,7 @@ rm -f "$SQLITE.zip"
|
||||
export SQLITE3_INCLUDE_DIR="$SQLITE3_LIB_DIR"
|
||||
# Regenerate bindgen file for sqlite3.h
|
||||
rm -f "$SQLITE3_LIB_DIR/bindgen_bundled_version.rs"
|
||||
cargo update
|
||||
cargo update --quiet
|
||||
# Just to make sure there is only one bindgen.rs file in target dir
|
||||
find "$TARGET_DIR" -type f -name bindgen.rs -exec rm {} \;
|
||||
env LIBSQLITE3_SYS_BUNDLING=1 cargo build --features "buildtime_bindgen session" --no-default-features
|
||||
@ -38,6 +38,6 @@ rm -f "$SQLITE3_LIB_DIR/sqlite3ext.h.bk"
|
||||
|
||||
# Sanity checks
|
||||
cd "$SCRIPT_DIR/.." || { echo "fatal error" >&2; exit 1; }
|
||||
cargo update
|
||||
cargo update --quiet
|
||||
cargo test --features "backup blob chrono functions limits load_extension serde_json trace vtab bundled"
|
||||
printf ' \e[35;1mFinished\e[0m bundled sqlite3 tests\n'
|
||||
|
@ -8,7 +8,7 @@ mkdir -p "$SCRIPT_DIR/../target" "$SCRIPT_DIR/sqlcipher"
|
||||
export SQLCIPHER_LIB_DIR="$SCRIPT_DIR/sqlcipher"
|
||||
export SQLCIPHER_INCLUDE_DIR="$SQLCIPHER_LIB_DIR"
|
||||
|
||||
SQLCIPHER_VERSION="4.5.3"
|
||||
SQLCIPHER_VERSION="4.5.7"
|
||||
# Download and generate sqlcipher amalgamation
|
||||
mkdir -p $SCRIPT_DIR/sqlcipher.src
|
||||
[ -e "v${SQLCIPHER_VERSION}.tar.gz" ] || curl -sfL -O "https://github.com/sqlcipher/sqlcipher/archive/v${SQLCIPHER_VERSION}.tar.gz"
|
||||
@ -30,6 +30,6 @@ find "$SCRIPT_DIR/../target" -type f -name bindgen.rs -exec mv {} "$SQLCIPHER_LI
|
||||
|
||||
# Sanity checks
|
||||
cd "$SCRIPT_DIR/.." || { echo "fatal error" >&2; exit 1; }
|
||||
cargo update
|
||||
cargo update --quiet
|
||||
cargo test --features "backup blob chrono functions limits load_extension serde_json trace vtab bundled-sqlcipher-vendored-openssl"
|
||||
printf ' \e[35;1mFinished\e[0m bundled-sqlcipher-vendored-openssl/sqlcipher tests\n'
|
||||
|
@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "rusqlite-macros"
|
||||
version = "0.2.0"
|
||||
version = "0.3.0"
|
||||
authors = ["The rusqlite developers"]
|
||||
edition = "2021"
|
||||
description = "Private implementation detail of rusqlite crate"
|
||||
@ -12,6 +12,6 @@ categories = ["database"]
|
||||
proc-macro = true
|
||||
|
||||
[dependencies]
|
||||
sqlite3-parser = { version = "0.12", default-features = false, features = ["YYNOERRORRECOVERY"] }
|
||||
sqlite3-parser = { version = "0.13", default-features = false, features = ["YYNOERRORRECOVERY"] }
|
||||
fallible-iterator = "0.3"
|
||||
litrs = { version = "0.4", default-features = false }
|
||||
|
@ -4,7 +4,8 @@ use litrs::StringLit;
|
||||
use proc_macro::{Delimiter, Group, Literal, Span, TokenStream, TokenTree};
|
||||
|
||||
use fallible_iterator::FallibleIterator;
|
||||
use sqlite3_parser::ast::{ParameterInfo, ToTokens};
|
||||
use sqlite3_parser::ast::fmt::ToTokens;
|
||||
use sqlite3_parser::ast::ParameterInfo;
|
||||
use sqlite3_parser::lexer::sql::Parser;
|
||||
|
||||
// https://internals.rust-lang.org/t/custom-error-diagnostics-with-procedural-macros-on-almost-stable-rust/8113
|
||||
@ -19,16 +20,15 @@ type Result<T> = std::result::Result<T, String>;
|
||||
|
||||
fn try_bind(input: TokenStream) -> Result<TokenStream> {
|
||||
let (stmt, literal) = {
|
||||
let mut iter = input.clone().into_iter();
|
||||
let mut iter = input.into_iter();
|
||||
let stmt = iter.next().unwrap();
|
||||
let literal = iter.next().unwrap();
|
||||
assert!(iter.next().is_none());
|
||||
(stmt, literal)
|
||||
};
|
||||
|
||||
let literal = match into_literal(&literal) {
|
||||
Some(it) => it,
|
||||
None => return Err("expected a plain string literal".to_string()),
|
||||
let Some(literal) = into_literal(&literal) else {
|
||||
return Err("expected a plain string literal".to_string());
|
||||
};
|
||||
let call_site = literal.span();
|
||||
let string_lit = match StringLit::try_from(literal) {
|
||||
|
62
src/auto_extension.rs
Normal file
62
src/auto_extension.rs
Normal file
@ -0,0 +1,62 @@
|
||||
//! Automatic extension loading
|
||||
use super::ffi;
|
||||
use crate::error::{check, to_sqlite_error};
|
||||
use crate::{Connection, Error, Result};
|
||||
use std::os::raw::{c_char, c_int};
|
||||
use std::panic::catch_unwind;
|
||||
|
||||
/// Automatic extension initialization routine
|
||||
pub type AutoExtension = fn(Connection) -> Result<()>;
|
||||
|
||||
/// Raw automatic extension initialization routine
|
||||
pub type RawAutoExtension = unsafe extern "C" fn(
|
||||
db: *mut ffi::sqlite3,
|
||||
pz_err_msg: *mut *mut c_char,
|
||||
_: *const ffi::sqlite3_api_routines,
|
||||
) -> c_int;
|
||||
|
||||
/// Bridge between `RawAutoExtension` and `AutoExtension`
|
||||
///
|
||||
/// # Safety
|
||||
/// * Opening a database from an auto-extension handler will lead to
|
||||
/// an endless recursion of the auto-handler triggering itself
|
||||
/// indirectly for each newly-opened database.
|
||||
/// * Results are undefined if the given db is closed by an auto-extension.
|
||||
/// * The list of auto-extensions should not be manipulated from an auto-extension.
|
||||
pub unsafe fn init_auto_extension(
|
||||
db: *mut ffi::sqlite3,
|
||||
pz_err_msg: *mut *mut c_char,
|
||||
ax: AutoExtension,
|
||||
) -> c_int {
|
||||
let r = catch_unwind(|| {
|
||||
let c = Connection::from_handle(db);
|
||||
c.and_then(ax)
|
||||
})
|
||||
.unwrap_or_else(|_| Err(Error::UnwindingPanic));
|
||||
match r {
|
||||
Err(e) => to_sqlite_error(&e, pz_err_msg),
|
||||
_ => ffi::SQLITE_OK,
|
||||
}
|
||||
}
|
||||
|
||||
/// Register au auto-extension
|
||||
///
|
||||
/// # Safety
|
||||
/// * Opening a database from an auto-extension handler will lead to
|
||||
/// an endless recursion of the auto-handler triggering itself
|
||||
/// indirectly for each newly-opened database.
|
||||
/// * Results are undefined if the given db is closed by an auto-extension.
|
||||
/// * The list of auto-extensions should not be manipulated from an auto-extension.
|
||||
pub unsafe fn register_auto_extension(ax: RawAutoExtension) -> Result<()> {
|
||||
check(ffi::sqlite3_auto_extension(Some(ax)))
|
||||
}
|
||||
|
||||
/// Unregister the initialization routine
|
||||
pub fn cancel_auto_extension(ax: RawAutoExtension) -> bool {
|
||||
unsafe { ffi::sqlite3_cancel_auto_extension(Some(ax)) == 1 }
|
||||
}
|
||||
|
||||
/// Disable all automatic extensions previously registered
|
||||
pub fn reset_auto_extension() {
|
||||
unsafe { ffi::sqlite3_reset_auto_extension() }
|
||||
}
|
@ -65,7 +65,7 @@ impl Connection {
|
||||
progress: Option<fn(Progress)>,
|
||||
) -> Result<()> {
|
||||
use self::StepResult::{Busy, Done, Locked, More};
|
||||
let mut dst = Connection::open(dst_path)?;
|
||||
let mut dst = Self::open(dst_path)?;
|
||||
let backup = Backup::new_with_names(self, name, &mut dst, DatabaseName::Main)?;
|
||||
|
||||
let mut r = More;
|
||||
@ -103,7 +103,7 @@ impl Connection {
|
||||
progress: Option<F>,
|
||||
) -> Result<()> {
|
||||
use self::StepResult::{Busy, Done, Locked, More};
|
||||
let src = Connection::open(src_path)?;
|
||||
let src = Self::open(src_path)?;
|
||||
let restore = Backup::new_with_names(&src, DatabaseName::Main, self, name)?;
|
||||
|
||||
let mut r = More;
|
||||
@ -316,10 +316,28 @@ impl Drop for Backup<'_, '_> {
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use super::Backup;
|
||||
use super::{Backup, Progress};
|
||||
use crate::{Connection, DatabaseName, Result};
|
||||
use std::time::Duration;
|
||||
|
||||
#[test]
|
||||
fn backup_to_path() -> Result<()> {
|
||||
let src = Connection::open_in_memory()?;
|
||||
src.execute_batch("CREATE TABLE foo AS SELECT 42 AS x")?;
|
||||
|
||||
let temp_dir = tempfile::tempdir().unwrap();
|
||||
let path = temp_dir.path().join("test.db3");
|
||||
|
||||
fn progress(_: Progress) {}
|
||||
|
||||
src.backup(DatabaseName::Main, path.as_path(), Some(progress))?;
|
||||
|
||||
let mut dst = Connection::open_in_memory()?;
|
||||
dst.restore(DatabaseName::Main, path, Some(progress))?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_backup() -> Result<()> {
|
||||
let src = Connection::open_in_memory()?;
|
||||
|
@ -50,7 +50,7 @@
|
||||
//! Using `MaybeUninit` here can be more efficient in some cases, but is
|
||||
//! often inconvenient, so both are provided.
|
||||
//!
|
||||
//! 2. Exact/inexact refers to to whether or not the entire buffer must be
|
||||
//! 2. Exact/inexact refers to whether or not the entire buffer must be
|
||||
//! filled in order for the call to be considered a success.
|
||||
//!
|
||||
//! The "exact" functions require the provided buffer be entirely filled, or
|
||||
@ -287,7 +287,7 @@ impl Blob<'_> {
|
||||
/// Close a BLOB handle.
|
||||
///
|
||||
/// Calling `close` explicitly is not required (the BLOB will be closed
|
||||
/// when the `Blob` is dropped), but it is available so you can get any
|
||||
/// when the `Blob` is dropped), but it is available, so you can get any
|
||||
/// errors that occur.
|
||||
///
|
||||
/// # Failure
|
||||
@ -413,7 +413,7 @@ pub struct ZeroBlob(pub i32);
|
||||
impl ToSql for ZeroBlob {
|
||||
#[inline]
|
||||
fn to_sql(&self) -> Result<ToSqlOutput<'_>> {
|
||||
let ZeroBlob(length) = *self;
|
||||
let Self(length) = *self;
|
||||
Ok(ToSqlOutput::ZeroBlob(length))
|
||||
}
|
||||
}
|
||||
@ -439,9 +439,12 @@ mod test {
|
||||
let (db, rowid) = db_with_test_blob()?;
|
||||
|
||||
let mut blob = db.blob_open(DatabaseName::Main, "test", "content", rowid, false)?;
|
||||
assert!(!blob.is_empty());
|
||||
assert_eq!(10, blob.len());
|
||||
assert_eq!(4, blob.write(b"Clob").unwrap());
|
||||
assert_eq!(6, blob.write(b"567890xxxxxx").unwrap()); // cannot write past 10
|
||||
assert_eq!(0, blob.write(b"5678").unwrap()); // still cannot write past 10
|
||||
blob.flush().unwrap();
|
||||
|
||||
blob.reopen(rowid)?;
|
||||
blob.close()?;
|
||||
@ -547,4 +550,12 @@ mod test {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn zero_blob() -> Result<()> {
|
||||
use crate::types::ToSql;
|
||||
let zb = super::ZeroBlob(1);
|
||||
assert!(zb.to_sql().is_ok());
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
@ -116,7 +116,7 @@ impl<'conn> Blob<'conn> {
|
||||
|
||||
if read_len == 0 {
|
||||
// We could return `Ok(&mut [])`, but it seems confusing that the
|
||||
// pointers don't match, so fabricate a empty slice of u8 with the
|
||||
// pointers don't match, so fabricate an empty slice of u8 with the
|
||||
// same base pointer as `buf`.
|
||||
let empty = unsafe { from_raw_parts_mut(buf.as_mut_ptr().cast::<u8>(), 0) };
|
||||
return Ok(empty);
|
||||
|
78
src/busy.rs
78
src/busy.rs
@ -80,12 +80,8 @@ impl InnerConnection {
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use std::sync::atomic::{AtomicBool, Ordering};
|
||||
use std::sync::mpsc::sync_channel;
|
||||
use std::thread;
|
||||
use std::time::Duration;
|
||||
|
||||
use crate::{Connection, ErrorCode, Result, TransactionBehavior};
|
||||
use std::sync::atomic::{AtomicBool, Ordering};
|
||||
|
||||
#[test]
|
||||
fn test_default_busy() -> Result<()> {
|
||||
@ -104,66 +100,28 @@ mod test {
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[ignore] // FIXME: unstable
|
||||
fn test_busy_timeout() {
|
||||
let temp_dir = tempfile::tempdir().unwrap();
|
||||
let path = temp_dir.path().join("test.db3");
|
||||
|
||||
let db2 = Connection::open(&path).unwrap();
|
||||
db2.busy_timeout(Duration::from_secs(1)).unwrap();
|
||||
|
||||
let (rx, tx) = sync_channel(0);
|
||||
let child = thread::spawn(move || {
|
||||
let mut db1 = Connection::open(&path).unwrap();
|
||||
let tx1 = db1
|
||||
.transaction_with_behavior(TransactionBehavior::Exclusive)
|
||||
.unwrap();
|
||||
rx.send(1).unwrap();
|
||||
thread::sleep(Duration::from_millis(100));
|
||||
tx1.rollback().unwrap();
|
||||
});
|
||||
|
||||
assert_eq!(tx.recv().unwrap(), 1);
|
||||
let _ = db2
|
||||
.query_row("PRAGMA schema_version", [], |row| row.get::<_, i32>(0))
|
||||
.expect("unexpected error");
|
||||
|
||||
child.join().unwrap();
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[ignore] // FIXME: unstable
|
||||
fn test_busy_handler() {
|
||||
fn test_busy_handler() -> Result<()> {
|
||||
static CALLED: AtomicBool = AtomicBool::new(false);
|
||||
fn busy_handler(_: i32) -> bool {
|
||||
CALLED.store(true, Ordering::Relaxed);
|
||||
thread::sleep(Duration::from_millis(100));
|
||||
true
|
||||
fn busy_handler(n: i32) -> bool {
|
||||
if n > 2 {
|
||||
false
|
||||
} else {
|
||||
CALLED.swap(true, Ordering::Relaxed)
|
||||
}
|
||||
}
|
||||
|
||||
let temp_dir = tempfile::tempdir().unwrap();
|
||||
let path = temp_dir.path().join("test.db3");
|
||||
let path = temp_dir.path().join("busy-handler.db3");
|
||||
|
||||
let db2 = Connection::open(&path).unwrap();
|
||||
db2.busy_handler(Some(busy_handler)).unwrap();
|
||||
|
||||
let (rx, tx) = sync_channel(0);
|
||||
let child = thread::spawn(move || {
|
||||
let mut db1 = Connection::open(&path).unwrap();
|
||||
let tx1 = db1
|
||||
.transaction_with_behavior(TransactionBehavior::Exclusive)
|
||||
.unwrap();
|
||||
rx.send(1).unwrap();
|
||||
thread::sleep(Duration::from_millis(100));
|
||||
tx1.rollback().unwrap();
|
||||
});
|
||||
|
||||
assert_eq!(tx.recv().unwrap(), 1);
|
||||
let _ = db2
|
||||
.query_row("PRAGMA schema_version", [], |row| row.get::<_, i32>(0))
|
||||
.expect("unexpected error");
|
||||
let db1 = Connection::open(&path)?;
|
||||
db1.execute_batch("CREATE TABLE IF NOT EXISTS t(a)")?;
|
||||
let db2 = Connection::open(&path)?;
|
||||
db2.busy_handler(Some(busy_handler))?;
|
||||
db1.execute_batch("BEGIN EXCLUSIVE")?;
|
||||
let err = db2.prepare("SELECT * FROM t").unwrap_err();
|
||||
assert_eq!(err.sqlite_error_code(), Some(ErrorCode::DatabaseBusy));
|
||||
assert!(CALLED.load(Ordering::Relaxed));
|
||||
|
||||
child.join().unwrap();
|
||||
db1.busy_handler(None)?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
14
src/cache.rs
14
src/cache.rs
@ -119,8 +119,8 @@ impl CachedStatement<'_> {
|
||||
impl StatementCache {
|
||||
/// Create a statement cache.
|
||||
#[inline]
|
||||
pub fn with_capacity(capacity: usize) -> StatementCache {
|
||||
StatementCache(RefCell::new(LruCache::new(capacity)))
|
||||
pub fn with_capacity(capacity: usize) -> Self {
|
||||
Self(RefCell::new(LruCache::new(capacity)))
|
||||
}
|
||||
|
||||
#[inline]
|
||||
@ -153,7 +153,7 @@ impl StatementCache {
|
||||
}
|
||||
|
||||
// Return a statement to the cache.
|
||||
fn cache_stmt(&self, stmt: RawStatement) {
|
||||
fn cache_stmt(&self, mut stmt: RawStatement) {
|
||||
if stmt.is_null() {
|
||||
return;
|
||||
}
|
||||
@ -278,10 +278,10 @@ mod test {
|
||||
fn test_ddl() -> Result<()> {
|
||||
let db = Connection::open_in_memory()?;
|
||||
db.execute_batch(
|
||||
r#"
|
||||
r"
|
||||
CREATE TABLE foo (x INT);
|
||||
INSERT INTO foo VALUES (1);
|
||||
"#,
|
||||
",
|
||||
)?;
|
||||
|
||||
let sql = "SELECT * FROM foo";
|
||||
@ -292,10 +292,10 @@ mod test {
|
||||
}
|
||||
|
||||
db.execute_batch(
|
||||
r#"
|
||||
r"
|
||||
ALTER TABLE foo ADD COLUMN y INT;
|
||||
UPDATE foo SET y = 2;
|
||||
"#,
|
||||
",
|
||||
)?;
|
||||
|
||||
{
|
||||
|
@ -1,7 +1,7 @@
|
||||
//! Add, remove, or modify a collation
|
||||
use std::cmp::Ordering;
|
||||
use std::os::raw::{c_char, c_int, c_void};
|
||||
use std::panic::{catch_unwind, UnwindSafe};
|
||||
use std::panic::catch_unwind;
|
||||
use std::ptr;
|
||||
use std::slice;
|
||||
|
||||
@ -18,7 +18,7 @@ impl Connection {
|
||||
#[inline]
|
||||
pub fn create_collation<C>(&self, collation_name: &str, x_compare: C) -> Result<()>
|
||||
where
|
||||
C: Fn(&str, &str) -> Ordering + Send + UnwindSafe + 'static,
|
||||
C: Fn(&str, &str) -> Ordering + Send + 'static,
|
||||
{
|
||||
self.db
|
||||
.borrow_mut()
|
||||
@ -27,10 +27,7 @@ impl Connection {
|
||||
|
||||
/// Collation needed callback
|
||||
#[inline]
|
||||
pub fn collation_needed(
|
||||
&self,
|
||||
x_coll_needed: fn(&Connection, &str) -> Result<()>,
|
||||
) -> Result<()> {
|
||||
pub fn collation_needed(&self, x_coll_needed: fn(&Self, &str) -> Result<()>) -> Result<()> {
|
||||
self.db.borrow_mut().collation_needed(x_coll_needed)
|
||||
}
|
||||
|
||||
@ -42,9 +39,31 @@ impl Connection {
|
||||
}
|
||||
|
||||
impl InnerConnection {
|
||||
/// ```compile_fail
|
||||
/// use rusqlite::{Connection, Result};
|
||||
/// fn main() -> Result<()> {
|
||||
/// let db = Connection::open_in_memory()?;
|
||||
/// {
|
||||
/// let mut called = std::sync::atomic::AtomicBool::new(false);
|
||||
/// db.create_collation("foo", |_, _| {
|
||||
/// called.store(true, std::sync::atomic::Ordering::Relaxed);
|
||||
/// std::cmp::Ordering::Equal
|
||||
/// })?;
|
||||
/// }
|
||||
/// let value: String = db.query_row(
|
||||
/// "WITH cte(bar) AS
|
||||
/// (VALUES ('v1'),('v2'),('v3'),('v4'),('v5'))
|
||||
/// SELECT DISTINCT bar COLLATE foo FROM cte;",
|
||||
/// [],
|
||||
/// |row| row.get(0),
|
||||
/// )?;
|
||||
/// assert_eq!(value, "v1");
|
||||
/// Ok(())
|
||||
/// }
|
||||
/// ```
|
||||
fn create_collation<C>(&mut self, collation_name: &str, x_compare: C) -> Result<()>
|
||||
where
|
||||
C: Fn(&str, &str) -> Ordering + Send + UnwindSafe + 'static,
|
||||
C: Fn(&str, &str) -> Ordering + Send + 'static,
|
||||
{
|
||||
unsafe extern "C" fn call_boxed_closure<C>(
|
||||
arg1: *mut c_void,
|
||||
@ -128,10 +147,9 @@ impl InnerConnection {
|
||||
let callback: fn(&Connection, &str) -> Result<()> = mem::transmute(arg1);
|
||||
let res = catch_unwind(|| {
|
||||
let conn = Connection::from_handle(arg2).unwrap();
|
||||
let collation_name = {
|
||||
let c_slice = CStr::from_ptr(arg3).to_bytes();
|
||||
str::from_utf8(c_slice).expect("illegal collation sequence name")
|
||||
};
|
||||
let collation_name = CStr::from_ptr(arg3)
|
||||
.to_str()
|
||||
.expect("illegal collation sequence name");
|
||||
callback(&conn, collation_name)
|
||||
});
|
||||
if res.is_err() {
|
||||
@ -180,9 +198,7 @@ mod test {
|
||||
#[test]
|
||||
fn test_unicase() -> Result<()> {
|
||||
let db = Connection::open_in_memory()?;
|
||||
|
||||
db.create_collation("unicase", unicase_compare)?;
|
||||
|
||||
collate(db)
|
||||
}
|
||||
|
||||
@ -212,4 +228,11 @@ mod test {
|
||||
db.collation_needed(collation_needed)?;
|
||||
collate(db)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn remove_collation() -> Result<()> {
|
||||
let db = Connection::open_in_memory()?;
|
||||
db.create_collation("unicase", unicase_compare)?;
|
||||
db.remove_collation("unicase")
|
||||
}
|
||||
}
|
||||
|
@ -57,7 +57,7 @@ impl Statement<'_> {
|
||||
}
|
||||
|
||||
/// Check that column name reference lifetime is limited:
|
||||
/// https://www.sqlite.org/c3ref/column_name.html
|
||||
/// <https://www.sqlite.org/c3ref/column_name.html>
|
||||
/// > The returned string pointer is valid...
|
||||
///
|
||||
/// `column_name` reference can become invalid if `stmt` is reprepared
|
||||
@ -104,7 +104,9 @@ impl Statement<'_> {
|
||||
// clippy::or_fun_call (nightly) vs clippy::unnecessary-lazy-evaluations (stable)
|
||||
.ok_or(Error::InvalidColumnIndex(col))
|
||||
.map(|slice| {
|
||||
str::from_utf8(slice.to_bytes()).expect("Invalid UTF-8 sequence in column name")
|
||||
slice
|
||||
.to_str()
|
||||
.expect("Invalid UTF-8 sequence in column name")
|
||||
})
|
||||
}
|
||||
|
||||
@ -149,7 +151,8 @@ impl Statement<'_> {
|
||||
let name = self.column_name_unwrap(i);
|
||||
let slice = self.stmt.column_decltype(i);
|
||||
let decl_type = slice.map(|s| {
|
||||
str::from_utf8(s.to_bytes()).expect("Invalid UTF-8 sequence in column declaration")
|
||||
s.to_str()
|
||||
.expect("Invalid UTF-8 sequence in column declaration")
|
||||
});
|
||||
cols.push(Column { name, decl_type });
|
||||
}
|
||||
@ -228,7 +231,7 @@ mod test {
|
||||
/// `column_name` reference should stay valid until `stmt` is reprepared (or
|
||||
/// reset) even if DB schema is altered (SQLite documentation is
|
||||
/// ambiguous here because it says reference "is valid until (...) the next
|
||||
/// call to sqlite3_column_name() or sqlite3_column_name16() on the same
|
||||
/// call to `sqlite3_column_name()` or `sqlite3_column_name16()` on the same
|
||||
/// column.". We assume that reference is valid if only
|
||||
/// `sqlite3_column_name()` is used):
|
||||
#[test]
|
||||
|
@ -20,7 +20,7 @@ pub enum DbConfig {
|
||||
SQLITE_DBCONFIG_ENABLE_FKEY = ffi::SQLITE_DBCONFIG_ENABLE_FKEY,
|
||||
/// Enable or disable triggers.
|
||||
SQLITE_DBCONFIG_ENABLE_TRIGGER = ffi::SQLITE_DBCONFIG_ENABLE_TRIGGER,
|
||||
/// Enable or disable the fts3_tokenizer() function which is part of the
|
||||
/// Enable or disable the `fts3_tokenizer()` function which is part of the
|
||||
/// FTS3 full-text search engine extension.
|
||||
SQLITE_DBCONFIG_ENABLE_FTS3_TOKENIZER = ffi::SQLITE_DBCONFIG_ENABLE_FTS3_TOKENIZER, // 3.12.0
|
||||
//SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION = 1005,
|
||||
@ -37,7 +37,7 @@ pub enum DbConfig {
|
||||
SQLITE_DBCONFIG_RESET_DATABASE = 1009, // 3.24.0
|
||||
/// Activates or deactivates the "defensive" flag for a database connection.
|
||||
SQLITE_DBCONFIG_DEFENSIVE = 1010, // 3.26.0
|
||||
/// Activates or deactivates the "writable_schema" flag.
|
||||
/// Activates or deactivates the `writable_schema` flag.
|
||||
#[cfg(feature = "modern_sqlite")]
|
||||
SQLITE_DBCONFIG_WRITABLE_SCHEMA = 1011, // 3.28.0
|
||||
/// Activates or deactivates the legacy behavior of the ALTER TABLE RENAME
|
||||
@ -59,11 +59,11 @@ pub enum DbConfig {
|
||||
#[cfg(feature = "modern_sqlite")]
|
||||
SQLITE_DBCONFIG_LEGACY_FILE_FORMAT = 1016, // 3.31.0
|
||||
/// Tells SQLite to assume that database schemas (the contents of the
|
||||
/// sqlite_master tables) are untainted by malicious content.
|
||||
/// `sqlite_master` tables) are untainted by malicious content.
|
||||
#[cfg(feature = "modern_sqlite")]
|
||||
SQLITE_DBCONFIG_TRUSTED_SCHEMA = 1017, // 3.31.0
|
||||
/// Sets or clears a flag that enables collection of the
|
||||
/// sqlite3_stmt_scanstatus_v2() statistics
|
||||
/// `sqlite3_stmt_scanstatus_v2()` statistics
|
||||
#[cfg(feature = "modern_sqlite")]
|
||||
SQLITE_DBCONFIG_STMT_SCANSTATUS = 1018, // 3.42.0
|
||||
/// Changes the default order in which tables and indexes are scanned
|
||||
|
@ -55,10 +55,9 @@ pub(super) unsafe fn set_result(
|
||||
if length > c_int::MAX as usize {
|
||||
ffi::sqlite3_result_error_toobig(ctx);
|
||||
} else {
|
||||
let (c_str, len, destructor) = match str_for_sqlite(s) {
|
||||
Ok(c_str) => c_str,
|
||||
let Ok((c_str, len, destructor)) = str_for_sqlite(s) else {
|
||||
// TODO sqlite3_result_error
|
||||
Err(_) => return ffi::sqlite3_result_error_code(ctx, ffi::SQLITE_MISUSE),
|
||||
return ffi::sqlite3_result_error_code(ctx, ffi::SQLITE_MISUSE);
|
||||
};
|
||||
// TODO sqlite3_result_text64 // 3.8.7
|
||||
ffi::sqlite3_result_text(ctx, c_str, len, destructor);
|
||||
|
206
src/error.rs
206
src/error.rs
@ -101,9 +101,7 @@ pub enum Error {
|
||||
#[allow(dead_code)]
|
||||
ModuleError(String),
|
||||
|
||||
/// An unwinding panic occurs in an UDF (user-defined function).
|
||||
#[cfg(feature = "functions")]
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "functions")))]
|
||||
/// An unwinding panic occurs in a UDF (user-defined function).
|
||||
UnwindingPanic,
|
||||
|
||||
/// An error returned when
|
||||
@ -145,59 +143,63 @@ pub enum Error {
|
||||
#[cfg(feature = "loadable_extension")]
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "loadable_extension")))]
|
||||
InitError(ffi::InitError),
|
||||
/// Error when the schema of a particular database is requested, but the index
|
||||
/// is out of range.
|
||||
#[cfg(feature = "modern_sqlite")] // 3.39.0
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "modern_sqlite")))]
|
||||
InvalidDatabaseIndex(usize),
|
||||
}
|
||||
|
||||
impl PartialEq for Error {
|
||||
fn eq(&self, other: &Error) -> bool {
|
||||
fn eq(&self, other: &Self) -> bool {
|
||||
match (self, other) {
|
||||
(Error::SqliteFailure(e1, s1), Error::SqliteFailure(e2, s2)) => e1 == e2 && s1 == s2,
|
||||
(Error::SqliteSingleThreadedMode, Error::SqliteSingleThreadedMode) => true,
|
||||
(Error::IntegralValueOutOfRange(i1, n1), Error::IntegralValueOutOfRange(i2, n2)) => {
|
||||
(Self::SqliteFailure(e1, s1), Self::SqliteFailure(e2, s2)) => e1 == e2 && s1 == s2,
|
||||
(Self::SqliteSingleThreadedMode, Self::SqliteSingleThreadedMode) => true,
|
||||
(Self::IntegralValueOutOfRange(i1, n1), Self::IntegralValueOutOfRange(i2, n2)) => {
|
||||
i1 == i2 && n1 == n2
|
||||
}
|
||||
(Error::Utf8Error(e1), Error::Utf8Error(e2)) => e1 == e2,
|
||||
(Error::NulError(e1), Error::NulError(e2)) => e1 == e2,
|
||||
(Error::InvalidParameterName(n1), Error::InvalidParameterName(n2)) => n1 == n2,
|
||||
(Error::InvalidPath(p1), Error::InvalidPath(p2)) => p1 == p2,
|
||||
(Error::ExecuteReturnedResults, Error::ExecuteReturnedResults) => true,
|
||||
(Error::QueryReturnedNoRows, Error::QueryReturnedNoRows) => true,
|
||||
(Error::InvalidColumnIndex(i1), Error::InvalidColumnIndex(i2)) => i1 == i2,
|
||||
(Error::InvalidColumnName(n1), Error::InvalidColumnName(n2)) => n1 == n2,
|
||||
(Error::InvalidColumnType(i1, n1, t1), Error::InvalidColumnType(i2, n2, t2)) => {
|
||||
(Self::Utf8Error(e1), Self::Utf8Error(e2)) => e1 == e2,
|
||||
(Self::NulError(e1), Self::NulError(e2)) => e1 == e2,
|
||||
(Self::InvalidParameterName(n1), Self::InvalidParameterName(n2)) => n1 == n2,
|
||||
(Self::InvalidPath(p1), Self::InvalidPath(p2)) => p1 == p2,
|
||||
(Self::ExecuteReturnedResults, Self::ExecuteReturnedResults) => true,
|
||||
(Self::QueryReturnedNoRows, Self::QueryReturnedNoRows) => true,
|
||||
(Self::InvalidColumnIndex(i1), Self::InvalidColumnIndex(i2)) => i1 == i2,
|
||||
(Self::InvalidColumnName(n1), Self::InvalidColumnName(n2)) => n1 == n2,
|
||||
(Self::InvalidColumnType(i1, n1, t1), Self::InvalidColumnType(i2, n2, t2)) => {
|
||||
i1 == i2 && t1 == t2 && n1 == n2
|
||||
}
|
||||
(Error::StatementChangedRows(n1), Error::StatementChangedRows(n2)) => n1 == n2,
|
||||
(Self::StatementChangedRows(n1), Self::StatementChangedRows(n2)) => n1 == n2,
|
||||
#[cfg(feature = "functions")]
|
||||
(
|
||||
Error::InvalidFunctionParameterType(i1, t1),
|
||||
Error::InvalidFunctionParameterType(i2, t2),
|
||||
Self::InvalidFunctionParameterType(i1, t1),
|
||||
Self::InvalidFunctionParameterType(i2, t2),
|
||||
) => i1 == i2 && t1 == t2,
|
||||
#[cfg(feature = "vtab")]
|
||||
(
|
||||
Error::InvalidFilterParameterType(i1, t1),
|
||||
Error::InvalidFilterParameterType(i2, t2),
|
||||
Self::InvalidFilterParameterType(i1, t1),
|
||||
Self::InvalidFilterParameterType(i2, t2),
|
||||
) => i1 == i2 && t1 == t2,
|
||||
(Error::InvalidQuery, Error::InvalidQuery) => true,
|
||||
(Self::InvalidQuery, Self::InvalidQuery) => true,
|
||||
#[cfg(feature = "vtab")]
|
||||
(Error::ModuleError(s1), Error::ModuleError(s2)) => s1 == s2,
|
||||
(Self::ModuleError(s1), Self::ModuleError(s2)) => s1 == s2,
|
||||
(Self::UnwindingPanic, Self::UnwindingPanic) => true,
|
||||
#[cfg(feature = "functions")]
|
||||
(Error::UnwindingPanic, Error::UnwindingPanic) => true,
|
||||
#[cfg(feature = "functions")]
|
||||
(Error::GetAuxWrongType, Error::GetAuxWrongType) => true,
|
||||
(Error::InvalidParameterCount(i1, n1), Error::InvalidParameterCount(i2, n2)) => {
|
||||
(Self::GetAuxWrongType, Self::GetAuxWrongType) => true,
|
||||
(Self::InvalidParameterCount(i1, n1), Self::InvalidParameterCount(i2, n2)) => {
|
||||
i1 == i2 && n1 == n2
|
||||
}
|
||||
#[cfg(feature = "blob")]
|
||||
(Error::BlobSizeError, Error::BlobSizeError) => true,
|
||||
(Self::BlobSizeError, Self::BlobSizeError) => true,
|
||||
#[cfg(feature = "modern_sqlite")]
|
||||
(
|
||||
Error::SqlInputError {
|
||||
Self::SqlInputError {
|
||||
error: e1,
|
||||
msg: m1,
|
||||
sql: s1,
|
||||
offset: o1,
|
||||
},
|
||||
Error::SqlInputError {
|
||||
Self::SqlInputError {
|
||||
error: e2,
|
||||
msg: m2,
|
||||
sql: s2,
|
||||
@ -205,7 +207,9 @@ impl PartialEq for Error {
|
||||
},
|
||||
) => e1 == e2 && m1 == m2 && s1 == s2 && o1 == o2,
|
||||
#[cfg(feature = "loadable_extension")]
|
||||
(Error::InitError(e1), Error::InitError(e2)) => e1 == e2,
|
||||
(Self::InitError(e1), Self::InitError(e2)) => e1 == e2,
|
||||
#[cfg(feature = "modern_sqlite")]
|
||||
(Self::InvalidDatabaseIndex(i1), Self::InvalidDatabaseIndex(i2)) => i1 == i2,
|
||||
(..) => false,
|
||||
}
|
||||
}
|
||||
@ -213,15 +217,15 @@ impl PartialEq for Error {
|
||||
|
||||
impl From<str::Utf8Error> for Error {
|
||||
#[cold]
|
||||
fn from(err: str::Utf8Error) -> Error {
|
||||
Error::Utf8Error(err)
|
||||
fn from(err: str::Utf8Error) -> Self {
|
||||
Self::Utf8Error(err)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<std::ffi::NulError> for Error {
|
||||
#[cold]
|
||||
fn from(err: std::ffi::NulError) -> Error {
|
||||
Error::NulError(err)
|
||||
fn from(err: std::ffi::NulError) -> Self {
|
||||
Self::NulError(err)
|
||||
}
|
||||
}
|
||||
|
||||
@ -231,18 +235,18 @@ const UNKNOWN_COLUMN: usize = usize::MAX;
|
||||
/// to allow use of `get_raw(…).as_…()?` in callbacks that take `Error`.
|
||||
impl From<FromSqlError> for Error {
|
||||
#[cold]
|
||||
fn from(err: FromSqlError) -> Error {
|
||||
fn from(err: FromSqlError) -> Self {
|
||||
// The error type requires index and type fields, but they aren't known in this
|
||||
// context.
|
||||
match err {
|
||||
FromSqlError::OutOfRange(val) => Error::IntegralValueOutOfRange(UNKNOWN_COLUMN, val),
|
||||
FromSqlError::OutOfRange(val) => Self::IntegralValueOutOfRange(UNKNOWN_COLUMN, val),
|
||||
FromSqlError::InvalidBlobSize { .. } => {
|
||||
Error::FromSqlConversionFailure(UNKNOWN_COLUMN, Type::Blob, Box::new(err))
|
||||
Self::FromSqlConversionFailure(UNKNOWN_COLUMN, Type::Blob, Box::new(err))
|
||||
}
|
||||
FromSqlError::Other(source) => {
|
||||
Error::FromSqlConversionFailure(UNKNOWN_COLUMN, Type::Null, source)
|
||||
Self::FromSqlConversionFailure(UNKNOWN_COLUMN, Type::Null, source)
|
||||
}
|
||||
_ => Error::FromSqlConversionFailure(UNKNOWN_COLUMN, Type::Null, Box::new(err)),
|
||||
_ => Self::FromSqlConversionFailure(UNKNOWN_COLUMN, Type::Null, Box::new(err)),
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -250,83 +254,84 @@ impl From<FromSqlError> for Error {
|
||||
#[cfg(feature = "loadable_extension")]
|
||||
impl From<ffi::InitError> for Error {
|
||||
#[cold]
|
||||
fn from(err: ffi::InitError) -> Error {
|
||||
Error::InitError(err)
|
||||
fn from(err: ffi::InitError) -> Self {
|
||||
Self::InitError(err)
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for Error {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
match *self {
|
||||
Error::SqliteFailure(ref err, None) => err.fmt(f),
|
||||
Error::SqliteFailure(_, Some(ref s)) => write!(f, "{s}"),
|
||||
Error::SqliteSingleThreadedMode => write!(
|
||||
Self::SqliteFailure(ref err, None) => err.fmt(f),
|
||||
Self::SqliteFailure(_, Some(ref s)) => write!(f, "{s}"),
|
||||
Self::SqliteSingleThreadedMode => write!(
|
||||
f,
|
||||
"SQLite was compiled or configured for single-threaded use only"
|
||||
),
|
||||
Error::FromSqlConversionFailure(i, ref t, ref err) => {
|
||||
Self::FromSqlConversionFailure(i, ref t, ref err) => {
|
||||
if i != UNKNOWN_COLUMN {
|
||||
write!(f, "Conversion error from type {t} at index: {i}, {err}")
|
||||
} else {
|
||||
err.fmt(f)
|
||||
}
|
||||
}
|
||||
Error::IntegralValueOutOfRange(col, val) => {
|
||||
Self::IntegralValueOutOfRange(col, val) => {
|
||||
if col != UNKNOWN_COLUMN {
|
||||
write!(f, "Integer {val} out of range at index {col}")
|
||||
} else {
|
||||
write!(f, "Integer {val} out of range")
|
||||
}
|
||||
}
|
||||
Error::Utf8Error(ref err) => err.fmt(f),
|
||||
Error::NulError(ref err) => err.fmt(f),
|
||||
Error::InvalidParameterName(ref name) => write!(f, "Invalid parameter name: {name}"),
|
||||
Error::InvalidPath(ref p) => write!(f, "Invalid path: {}", p.to_string_lossy()),
|
||||
Error::ExecuteReturnedResults => {
|
||||
Self::Utf8Error(ref err) => err.fmt(f),
|
||||
Self::NulError(ref err) => err.fmt(f),
|
||||
Self::InvalidParameterName(ref name) => write!(f, "Invalid parameter name: {name}"),
|
||||
Self::InvalidPath(ref p) => write!(f, "Invalid path: {}", p.to_string_lossy()),
|
||||
Self::ExecuteReturnedResults => {
|
||||
write!(f, "Execute returned results - did you mean to call query?")
|
||||
}
|
||||
Error::QueryReturnedNoRows => write!(f, "Query returned no rows"),
|
||||
Error::InvalidColumnIndex(i) => write!(f, "Invalid column index: {i}"),
|
||||
Error::InvalidColumnName(ref name) => write!(f, "Invalid column name: {name}"),
|
||||
Error::InvalidColumnType(i, ref name, ref t) => {
|
||||
Self::QueryReturnedNoRows => write!(f, "Query returned no rows"),
|
||||
Self::InvalidColumnIndex(i) => write!(f, "Invalid column index: {i}"),
|
||||
Self::InvalidColumnName(ref name) => write!(f, "Invalid column name: {name}"),
|
||||
Self::InvalidColumnType(i, ref name, ref t) => {
|
||||
write!(f, "Invalid column type {t} at index: {i}, name: {name}")
|
||||
}
|
||||
Error::InvalidParameterCount(i1, n1) => write!(
|
||||
Self::InvalidParameterCount(i1, n1) => write!(
|
||||
f,
|
||||
"Wrong number of parameters passed to query. Got {i1}, needed {n1}"
|
||||
),
|
||||
Error::StatementChangedRows(i) => write!(f, "Query changed {i} rows"),
|
||||
Self::StatementChangedRows(i) => write!(f, "Query changed {i} rows"),
|
||||
|
||||
#[cfg(feature = "functions")]
|
||||
Error::InvalidFunctionParameterType(i, ref t) => {
|
||||
Self::InvalidFunctionParameterType(i, ref t) => {
|
||||
write!(f, "Invalid function parameter type {t} at index {i}")
|
||||
}
|
||||
#[cfg(feature = "vtab")]
|
||||
Error::InvalidFilterParameterType(i, ref t) => {
|
||||
Self::InvalidFilterParameterType(i, ref t) => {
|
||||
write!(f, "Invalid filter parameter type {t} at index {i}")
|
||||
}
|
||||
#[cfg(feature = "functions")]
|
||||
Error::UserFunctionError(ref err) => err.fmt(f),
|
||||
Error::ToSqlConversionFailure(ref err) => err.fmt(f),
|
||||
Error::InvalidQuery => write!(f, "Query is not read-only"),
|
||||
Self::UserFunctionError(ref err) => err.fmt(f),
|
||||
Self::ToSqlConversionFailure(ref err) => err.fmt(f),
|
||||
Self::InvalidQuery => write!(f, "Query is not read-only"),
|
||||
#[cfg(feature = "vtab")]
|
||||
Error::ModuleError(ref desc) => write!(f, "{desc}"),
|
||||
Self::ModuleError(ref desc) => write!(f, "{desc}"),
|
||||
Self::UnwindingPanic => write!(f, "unwinding panic"),
|
||||
#[cfg(feature = "functions")]
|
||||
Error::UnwindingPanic => write!(f, "unwinding panic"),
|
||||
#[cfg(feature = "functions")]
|
||||
Error::GetAuxWrongType => write!(f, "get_aux called with wrong type"),
|
||||
Error::MultipleStatement => write!(f, "Multiple statements provided"),
|
||||
Self::GetAuxWrongType => write!(f, "get_aux called with wrong type"),
|
||||
Self::MultipleStatement => write!(f, "Multiple statements provided"),
|
||||
#[cfg(feature = "blob")]
|
||||
Error::BlobSizeError => "Blob size is insufficient".fmt(f),
|
||||
Self::BlobSizeError => "Blob size is insufficient".fmt(f),
|
||||
#[cfg(feature = "modern_sqlite")]
|
||||
Error::SqlInputError {
|
||||
Self::SqlInputError {
|
||||
ref msg,
|
||||
offset,
|
||||
ref sql,
|
||||
..
|
||||
} => write!(f, "{msg} in {sql} at offset {offset}"),
|
||||
#[cfg(feature = "loadable_extension")]
|
||||
Error::InitError(ref err) => err.fmt(f),
|
||||
Self::InitError(ref err) => err.fmt(f),
|
||||
#[cfg(feature = "modern_sqlite")]
|
||||
Self::InvalidDatabaseIndex(i) => write!(f, "Invalid database index: {i}"),
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -334,50 +339,51 @@ impl fmt::Display for Error {
|
||||
impl error::Error for Error {
|
||||
fn source(&self) -> Option<&(dyn error::Error + 'static)> {
|
||||
match *self {
|
||||
Error::SqliteFailure(ref err, _) => Some(err),
|
||||
Error::Utf8Error(ref err) => Some(err),
|
||||
Error::NulError(ref err) => Some(err),
|
||||
Self::SqliteFailure(ref err, _) => Some(err),
|
||||
Self::Utf8Error(ref err) => Some(err),
|
||||
Self::NulError(ref err) => Some(err),
|
||||
|
||||
Error::IntegralValueOutOfRange(..)
|
||||
| Error::SqliteSingleThreadedMode
|
||||
| Error::InvalidParameterName(_)
|
||||
| Error::ExecuteReturnedResults
|
||||
| Error::QueryReturnedNoRows
|
||||
| Error::InvalidColumnIndex(_)
|
||||
| Error::InvalidColumnName(_)
|
||||
| Error::InvalidColumnType(..)
|
||||
| Error::InvalidPath(_)
|
||||
| Error::InvalidParameterCount(..)
|
||||
| Error::StatementChangedRows(_)
|
||||
| Error::InvalidQuery
|
||||
| Error::MultipleStatement => None,
|
||||
Self::IntegralValueOutOfRange(..)
|
||||
| Self::SqliteSingleThreadedMode
|
||||
| Self::InvalidParameterName(_)
|
||||
| Self::ExecuteReturnedResults
|
||||
| Self::QueryReturnedNoRows
|
||||
| Self::InvalidColumnIndex(_)
|
||||
| Self::InvalidColumnName(_)
|
||||
| Self::InvalidColumnType(..)
|
||||
| Self::InvalidPath(_)
|
||||
| Self::InvalidParameterCount(..)
|
||||
| Self::StatementChangedRows(_)
|
||||
| Self::InvalidQuery
|
||||
| Self::MultipleStatement => None,
|
||||
|
||||
#[cfg(feature = "functions")]
|
||||
Error::InvalidFunctionParameterType(..) => None,
|
||||
Self::InvalidFunctionParameterType(..) => None,
|
||||
#[cfg(feature = "vtab")]
|
||||
Error::InvalidFilterParameterType(..) => None,
|
||||
Self::InvalidFilterParameterType(..) => None,
|
||||
|
||||
#[cfg(feature = "functions")]
|
||||
Error::UserFunctionError(ref err) => Some(&**err),
|
||||
Self::UserFunctionError(ref err) => Some(&**err),
|
||||
|
||||
Error::FromSqlConversionFailure(_, _, ref err)
|
||||
| Error::ToSqlConversionFailure(ref err) => Some(&**err),
|
||||
Self::FromSqlConversionFailure(_, _, ref err)
|
||||
| Self::ToSqlConversionFailure(ref err) => Some(&**err),
|
||||
|
||||
#[cfg(feature = "vtab")]
|
||||
Error::ModuleError(_) => None,
|
||||
Self::ModuleError(_) => None,
|
||||
|
||||
Self::UnwindingPanic => None,
|
||||
|
||||
#[cfg(feature = "functions")]
|
||||
Error::UnwindingPanic => None,
|
||||
|
||||
#[cfg(feature = "functions")]
|
||||
Error::GetAuxWrongType => None,
|
||||
Self::GetAuxWrongType => None,
|
||||
|
||||
#[cfg(feature = "blob")]
|
||||
Error::BlobSizeError => None,
|
||||
Self::BlobSizeError => None,
|
||||
#[cfg(feature = "modern_sqlite")]
|
||||
Error::SqlInputError { ref error, .. } => Some(error),
|
||||
Self::SqlInputError { ref error, .. } => Some(error),
|
||||
#[cfg(feature = "loadable_extension")]
|
||||
Error::InitError(ref err) => Some(err),
|
||||
Self::InitError(ref err) => Some(err),
|
||||
#[cfg(feature = "modern_sqlite")]
|
||||
Self::InvalidDatabaseIndex(_) => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -267,7 +267,7 @@ pub type SubType = Option<std::os::raw::c_uint>;
|
||||
|
||||
/// Result of an SQL function
|
||||
pub trait SqlFnOutput {
|
||||
/// Converts Rust value to SQLite value with an optional sub-type
|
||||
/// Converts Rust value to SQLite value with an optional subtype
|
||||
fn to_sql(&self) -> Result<(ToSqlOutput<'_>, SubType)>;
|
||||
}
|
||||
|
||||
@ -381,19 +381,19 @@ bitflags::bitflags! {
|
||||
const SQLITE_DETERMINISTIC = ffi::SQLITE_DETERMINISTIC; // 3.8.3
|
||||
/// Means that the function may only be invoked from top-level SQL.
|
||||
const SQLITE_DIRECTONLY = 0x0000_0008_0000; // 3.30.0
|
||||
/// Indicates to SQLite that a function may call `sqlite3_value_subtype()` to inspect the sub-types of its arguments.
|
||||
/// Indicates to SQLite that a function may call `sqlite3_value_subtype()` to inspect the subtypes of its arguments.
|
||||
const SQLITE_SUBTYPE = 0x0000_0010_0000; // 3.30.0
|
||||
/// Means that the function is unlikely to cause problems even if misused.
|
||||
const SQLITE_INNOCUOUS = 0x0000_0020_0000; // 3.31.0
|
||||
/// Indicates to SQLite that a function might call `sqlite3_result_subtype()` to cause a sub-type to be associated with its result.
|
||||
/// Indicates to SQLite that a function might call `sqlite3_result_subtype()` to cause a subtype to be associated with its result.
|
||||
const SQLITE_RESULT_SUBTYPE = 0x0000_0100_0000; // 3.45.0
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for FunctionFlags {
|
||||
#[inline]
|
||||
fn default() -> FunctionFlags {
|
||||
FunctionFlags::SQLITE_UTF8
|
||||
fn default() -> Self {
|
||||
Self::SQLITE_UTF8
|
||||
}
|
||||
}
|
||||
|
||||
@ -444,7 +444,7 @@ impl Connection {
|
||||
x_func: F,
|
||||
) -> Result<()>
|
||||
where
|
||||
F: FnMut(&Context<'_>) -> Result<T> + Send + UnwindSafe + 'static,
|
||||
F: FnMut(&Context<'_>) -> Result<T> + Send + 'static,
|
||||
T: SqlFnOutput,
|
||||
{
|
||||
self.db
|
||||
@ -518,6 +518,27 @@ impl Connection {
|
||||
}
|
||||
|
||||
impl InnerConnection {
|
||||
/// ```compile_fail
|
||||
/// use rusqlite::{functions::FunctionFlags, Connection, Result};
|
||||
/// fn main() -> Result<()> {
|
||||
/// let db = Connection::open_in_memory()?;
|
||||
/// {
|
||||
/// let mut called = std::sync::atomic::AtomicBool::new(false);
|
||||
/// db.create_scalar_function(
|
||||
/// "test",
|
||||
/// 0,
|
||||
/// FunctionFlags::SQLITE_UTF8 | FunctionFlags::SQLITE_DETERMINISTIC,
|
||||
/// |_| {
|
||||
/// called.store(true, std::sync::atomic::Ordering::Relaxed);
|
||||
/// Ok(true)
|
||||
/// },
|
||||
/// );
|
||||
/// }
|
||||
/// let result: Result<bool> = db.query_row("SELECT test()", [], |r| r.get(0));
|
||||
/// assert!(result?);
|
||||
/// Ok(())
|
||||
/// }
|
||||
/// ```
|
||||
fn create_scalar_function<F, T>(
|
||||
&mut self,
|
||||
fn_name: &str,
|
||||
@ -526,7 +547,7 @@ impl InnerConnection {
|
||||
x_func: F,
|
||||
) -> Result<()>
|
||||
where
|
||||
F: FnMut(&Context<'_>) -> Result<T> + Send + UnwindSafe + 'static,
|
||||
F: FnMut(&Context<'_>) -> Result<T> + Send + 'static,
|
||||
T: SqlFnOutput,
|
||||
{
|
||||
unsafe extern "C" fn call_boxed_closure<F, T>(
|
||||
@ -670,9 +691,7 @@ unsafe extern "C" fn call_boxed_step<A, D, T>(
|
||||
D: Aggregate<A, T>,
|
||||
T: SqlFnOutput,
|
||||
{
|
||||
let pac = if let Some(pac) = aggregate_context(ctx, std::mem::size_of::<*mut A>()) {
|
||||
pac
|
||||
} else {
|
||||
let Some(pac) = aggregate_context(ctx, std::mem::size_of::<*mut A>()) else {
|
||||
ffi::sqlite3_result_error_nomem(ctx);
|
||||
return;
|
||||
};
|
||||
@ -718,9 +737,7 @@ unsafe extern "C" fn call_boxed_inverse<A, W, T>(
|
||||
W: WindowAggregate<A, T>,
|
||||
T: SqlFnOutput,
|
||||
{
|
||||
let pac = if let Some(pac) = aggregate_context(ctx, std::mem::size_of::<*mut A>()) {
|
||||
pac
|
||||
} else {
|
||||
let Some(pac) = aggregate_context(ctx, std::mem::size_of::<*mut A>()) else {
|
||||
ffi::sqlite3_result_error_nomem(ctx);
|
||||
return;
|
||||
};
|
||||
@ -834,7 +851,14 @@ mod test {
|
||||
use crate::{Connection, Error, Result};
|
||||
|
||||
fn half(ctx: &Context<'_>) -> Result<c_double> {
|
||||
assert!(!ctx.is_empty());
|
||||
assert_eq!(ctx.len(), 1, "called with unexpected number of arguments");
|
||||
assert!(unsafe {
|
||||
ctx.get_connection()
|
||||
.as_ref()
|
||||
.map(::std::ops::Deref::deref)
|
||||
.is_ok()
|
||||
});
|
||||
let value = ctx.get::<c_double>(0)?;
|
||||
Ok(value / 2f64)
|
||||
}
|
||||
|
@ -2,13 +2,19 @@
|
||||
#![allow(non_camel_case_types)]
|
||||
|
||||
use std::os::raw::{c_char, c_int, c_void};
|
||||
use std::panic::{catch_unwind, RefUnwindSafe};
|
||||
use std::panic::catch_unwind;
|
||||
use std::ptr;
|
||||
|
||||
use crate::ffi;
|
||||
|
||||
use crate::{Connection, InnerConnection};
|
||||
|
||||
#[cfg(feature = "preupdate_hook")]
|
||||
pub use preupdate_hook::*;
|
||||
|
||||
#[cfg(feature = "preupdate_hook")]
|
||||
mod preupdate_hook;
|
||||
|
||||
/// Action Codes
|
||||
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
|
||||
#[repr(i32)]
|
||||
@ -27,12 +33,12 @@ pub enum Action {
|
||||
|
||||
impl From<i32> for Action {
|
||||
#[inline]
|
||||
fn from(code: i32) -> Action {
|
||||
fn from(code: i32) -> Self {
|
||||
match code {
|
||||
ffi::SQLITE_DELETE => Action::SQLITE_DELETE,
|
||||
ffi::SQLITE_INSERT => Action::SQLITE_INSERT,
|
||||
ffi::SQLITE_UPDATE => Action::SQLITE_UPDATE,
|
||||
_ => Action::UNKNOWN,
|
||||
ffi::SQLITE_DELETE => Self::SQLITE_DELETE,
|
||||
ffi::SQLITE_INSERT => Self::SQLITE_INSERT,
|
||||
ffi::SQLITE_UPDATE => Self::SQLITE_UPDATE,
|
||||
_ => Self::UNKNOWN,
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -366,7 +372,7 @@ impl Connection {
|
||||
/// The callback parameters are:
|
||||
///
|
||||
/// - the type of database update (`SQLITE_INSERT`, `SQLITE_UPDATE` or
|
||||
/// `SQLITE_DELETE`),
|
||||
/// `SQLITE_DELETE`),
|
||||
/// - the name of the database ("main", "temp", ...),
|
||||
/// - the name of the table that is updated,
|
||||
/// - the ROWID of the row that is updated.
|
||||
@ -388,7 +394,7 @@ impl Connection {
|
||||
/// If the progress callback returns `true`, the operation is interrupted.
|
||||
pub fn progress_handler<F>(&self, num_ops: c_int, handler: Option<F>)
|
||||
where
|
||||
F: FnMut() -> bool + Send + RefUnwindSafe + 'static,
|
||||
F: FnMut() -> bool + Send + 'static,
|
||||
{
|
||||
self.db.borrow_mut().progress_handler(num_ops, handler);
|
||||
}
|
||||
@ -398,7 +404,7 @@ impl Connection {
|
||||
#[inline]
|
||||
pub fn authorizer<'c, F>(&self, hook: Option<F>)
|
||||
where
|
||||
F: for<'r> FnMut(AuthContext<'r>) -> Authorization + Send + RefUnwindSafe + 'static,
|
||||
F: for<'r> FnMut(AuthContext<'r>) -> Authorization + Send + 'static,
|
||||
{
|
||||
self.db.borrow_mut().authorizer(hook);
|
||||
}
|
||||
@ -414,6 +420,27 @@ impl InnerConnection {
|
||||
self.authorizer(None::<fn(AuthContext<'_>) -> Authorization>);
|
||||
}
|
||||
|
||||
/// ```compile_fail
|
||||
/// use rusqlite::{Connection, Result};
|
||||
/// fn main() -> Result<()> {
|
||||
/// let db = Connection::open_in_memory()?;
|
||||
/// {
|
||||
/// let mut called = std::sync::atomic::AtomicBool::new(false);
|
||||
/// db.commit_hook(Some(|| {
|
||||
/// called.store(true, std::sync::atomic::Ordering::Relaxed);
|
||||
/// true
|
||||
/// }));
|
||||
/// }
|
||||
/// assert!(db
|
||||
/// .execute_batch(
|
||||
/// "BEGIN;
|
||||
/// CREATE TABLE foo (t TEXT);
|
||||
/// COMMIT;",
|
||||
/// )
|
||||
/// .is_err());
|
||||
/// Ok(())
|
||||
/// }
|
||||
/// ```
|
||||
fn commit_hook<F>(&mut self, hook: Option<F>)
|
||||
where
|
||||
F: FnMut() -> bool + Send + 'static,
|
||||
@ -459,6 +486,26 @@ impl InnerConnection {
|
||||
self.free_commit_hook = free_commit_hook;
|
||||
}
|
||||
|
||||
/// ```compile_fail
|
||||
/// use rusqlite::{Connection, Result};
|
||||
/// fn main() -> Result<()> {
|
||||
/// let db = Connection::open_in_memory()?;
|
||||
/// {
|
||||
/// let mut called = std::sync::atomic::AtomicBool::new(false);
|
||||
/// db.rollback_hook(Some(|| {
|
||||
/// called.store(true, std::sync::atomic::Ordering::Relaxed);
|
||||
/// }));
|
||||
/// }
|
||||
/// assert!(db
|
||||
/// .execute_batch(
|
||||
/// "BEGIN;
|
||||
/// CREATE TABLE foo (t TEXT);
|
||||
/// ROLLBACK;",
|
||||
/// )
|
||||
/// .is_err());
|
||||
/// Ok(())
|
||||
/// }
|
||||
/// ```
|
||||
fn rollback_hook<F>(&mut self, hook: Option<F>)
|
||||
where
|
||||
F: FnMut() + Send + 'static,
|
||||
@ -500,6 +547,19 @@ impl InnerConnection {
|
||||
self.free_rollback_hook = free_rollback_hook;
|
||||
}
|
||||
|
||||
/// ```compile_fail
|
||||
/// use rusqlite::{Connection, Result};
|
||||
/// fn main() -> Result<()> {
|
||||
/// let db = Connection::open_in_memory()?;
|
||||
/// {
|
||||
/// let mut called = std::sync::atomic::AtomicBool::new(false);
|
||||
/// db.update_hook(Some(|_, _: &str, _: &str, _| {
|
||||
/// called.store(true, std::sync::atomic::Ordering::Relaxed);
|
||||
/// }));
|
||||
/// }
|
||||
/// db.execute_batch("CREATE TABLE foo AS SELECT 1 AS bar;")
|
||||
/// }
|
||||
/// ```
|
||||
fn update_hook<F>(&mut self, hook: Option<F>)
|
||||
where
|
||||
F: FnMut(Action, &str, &str, i64) + Send + 'static,
|
||||
@ -552,9 +612,29 @@ impl InnerConnection {
|
||||
self.free_update_hook = free_update_hook;
|
||||
}
|
||||
|
||||
/// ```compile_fail
|
||||
/// use rusqlite::{Connection, Result};
|
||||
/// fn main() -> Result<()> {
|
||||
/// let db = Connection::open_in_memory()?;
|
||||
/// {
|
||||
/// let mut called = std::sync::atomic::AtomicBool::new(false);
|
||||
/// db.progress_handler(
|
||||
/// 1,
|
||||
/// Some(|| {
|
||||
/// called.store(true, std::sync::atomic::Ordering::Relaxed);
|
||||
/// true
|
||||
/// }),
|
||||
/// );
|
||||
/// }
|
||||
/// assert!(db
|
||||
/// .execute_batch("BEGIN; CREATE TABLE foo (t TEXT); COMMIT;")
|
||||
/// .is_err());
|
||||
/// Ok(())
|
||||
/// }
|
||||
/// ```
|
||||
fn progress_handler<F>(&mut self, num_ops: c_int, handler: Option<F>)
|
||||
where
|
||||
F: FnMut() -> bool + Send + RefUnwindSafe + 'static,
|
||||
F: FnMut() -> bool + Send + 'static,
|
||||
{
|
||||
unsafe extern "C" fn call_boxed_closure<F>(p_arg: *mut c_void) -> c_int
|
||||
where
|
||||
@ -584,9 +664,26 @@ impl InnerConnection {
|
||||
};
|
||||
}
|
||||
|
||||
/// ```compile_fail
|
||||
/// use rusqlite::{Connection, Result};
|
||||
/// fn main() -> Result<()> {
|
||||
/// let db = Connection::open_in_memory()?;
|
||||
/// {
|
||||
/// let mut called = std::sync::atomic::AtomicBool::new(false);
|
||||
/// db.authorizer(Some(|_: rusqlite::hooks::AuthContext<'_>| {
|
||||
/// called.store(true, std::sync::atomic::Ordering::Relaxed);
|
||||
/// rusqlite::hooks::Authorization::Deny
|
||||
/// }));
|
||||
/// }
|
||||
/// assert!(db
|
||||
/// .execute_batch("BEGIN; CREATE TABLE foo (t TEXT); COMMIT;")
|
||||
/// .is_err());
|
||||
/// Ok(())
|
||||
/// }
|
||||
/// ```
|
||||
fn authorizer<'c, F>(&'c mut self, authorizer: Option<F>)
|
||||
where
|
||||
F: for<'r> FnMut(AuthContext<'r>) -> Authorization + Send + RefUnwindSafe + 'static,
|
||||
F: for<'r> FnMut(AuthContext<'r>) -> Authorization + Send + 'static,
|
||||
{
|
||||
unsafe extern "C" fn call_boxed_closure<'c, F>(
|
||||
p_arg: *mut c_void,
|
||||
@ -666,7 +763,8 @@ unsafe fn expect_optional_utf8<'a>(
|
||||
if p_str.is_null() {
|
||||
return None;
|
||||
}
|
||||
std::str::from_utf8(std::ffi::CStr::from_ptr(p_str).to_bytes())
|
||||
std::ffi::CStr::from_ptr(p_str)
|
||||
.to_str()
|
||||
.unwrap_or_else(|_| panic!("received non-utf8 string as {description}"))
|
||||
.into()
|
||||
}
|
372
src/hooks/preupdate_hook.rs
Normal file
372
src/hooks/preupdate_hook.rs
Normal file
@ -0,0 +1,372 @@
|
||||
use std::fmt::Debug;
|
||||
use std::os::raw::{c_char, c_int, c_void};
|
||||
use std::panic::catch_unwind;
|
||||
use std::ptr;
|
||||
|
||||
use super::expect_utf8;
|
||||
use super::free_boxed_hook;
|
||||
use super::Action;
|
||||
use crate::error::check;
|
||||
use crate::ffi;
|
||||
use crate::inner_connection::InnerConnection;
|
||||
use crate::types::ValueRef;
|
||||
use crate::Connection;
|
||||
use crate::Result;
|
||||
|
||||
/// The possible cases for when a PreUpdateHook gets triggered. Allows access to the relevant
|
||||
/// functions for each case through the contained values.
|
||||
#[derive(Debug)]
|
||||
pub enum PreUpdateCase {
|
||||
/// Pre-update hook was triggered by an insert.
|
||||
Insert(PreUpdateNewValueAccessor),
|
||||
/// Pre-update hook was triggered by a delete.
|
||||
Delete(PreUpdateOldValueAccessor),
|
||||
/// Pre-update hook was triggered by an update.
|
||||
Update {
|
||||
#[allow(missing_docs)]
|
||||
old_value_accessor: PreUpdateOldValueAccessor,
|
||||
#[allow(missing_docs)]
|
||||
new_value_accessor: PreUpdateNewValueAccessor,
|
||||
},
|
||||
/// This variant is not normally produced by SQLite. You may encounter it
|
||||
/// if you're using a different version than what's supported by this library.
|
||||
Unknown,
|
||||
}
|
||||
|
||||
impl From<PreUpdateCase> for Action {
|
||||
fn from(puc: PreUpdateCase) -> Action {
|
||||
match puc {
|
||||
PreUpdateCase::Insert(_) => Action::SQLITE_INSERT,
|
||||
PreUpdateCase::Delete(_) => Action::SQLITE_DELETE,
|
||||
PreUpdateCase::Update { .. } => Action::SQLITE_UPDATE,
|
||||
PreUpdateCase::Unknown => Action::UNKNOWN,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// An accessor to access the old values of the row being deleted/updated during the preupdate callback.
|
||||
#[derive(Debug)]
|
||||
pub struct PreUpdateOldValueAccessor {
|
||||
db: *mut ffi::sqlite3,
|
||||
old_row_id: i64,
|
||||
}
|
||||
|
||||
impl PreUpdateOldValueAccessor {
|
||||
/// Get the amount of columns in the row being deleted/updated.
|
||||
pub fn get_column_count(&self) -> i32 {
|
||||
unsafe { ffi::sqlite3_preupdate_count(self.db) }
|
||||
}
|
||||
|
||||
/// Get the depth of the query that triggered the preupdate hook.
|
||||
/// Returns 0 if the preupdate callback was invoked as a result of
|
||||
/// a direct insert, update, or delete operation;
|
||||
/// 1 for inserts, updates, or deletes invoked by top-level triggers;
|
||||
/// 2 for changes resulting from triggers called by top-level triggers; and so forth.
|
||||
pub fn get_query_depth(&self) -> i32 {
|
||||
unsafe { ffi::sqlite3_preupdate_depth(self.db) }
|
||||
}
|
||||
|
||||
/// Get the row id of the row being updated/deleted.
|
||||
pub fn get_old_row_id(&self) -> i64 {
|
||||
self.old_row_id
|
||||
}
|
||||
|
||||
/// Get the value of the row being updated/deleted at the specified index.
|
||||
pub fn get_old_column_value(&self, i: i32) -> Result<ValueRef> {
|
||||
let mut p_value: *mut ffi::sqlite3_value = ptr::null_mut();
|
||||
unsafe {
|
||||
check(ffi::sqlite3_preupdate_old(self.db, i, &mut p_value))?;
|
||||
Ok(ValueRef::from_value(p_value))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// An accessor to access the new values of the row being inserted/updated
|
||||
/// during the preupdate callback.
|
||||
#[derive(Debug)]
|
||||
pub struct PreUpdateNewValueAccessor {
|
||||
db: *mut ffi::sqlite3,
|
||||
new_row_id: i64,
|
||||
}
|
||||
|
||||
impl PreUpdateNewValueAccessor {
|
||||
/// Get the amount of columns in the row being inserted/updated.
|
||||
pub fn get_column_count(&self) -> i32 {
|
||||
unsafe { ffi::sqlite3_preupdate_count(self.db) }
|
||||
}
|
||||
|
||||
/// Get the depth of the query that triggered the preupdate hook.
|
||||
/// Returns 0 if the preupdate callback was invoked as a result of
|
||||
/// a direct insert, update, or delete operation;
|
||||
/// 1 for inserts, updates, or deletes invoked by top-level triggers;
|
||||
/// 2 for changes resulting from triggers called by top-level triggers; and so forth.
|
||||
pub fn get_query_depth(&self) -> i32 {
|
||||
unsafe { ffi::sqlite3_preupdate_depth(self.db) }
|
||||
}
|
||||
|
||||
/// Get the row id of the row being inserted/updated.
|
||||
pub fn get_new_row_id(&self) -> i64 {
|
||||
self.new_row_id
|
||||
}
|
||||
|
||||
/// Get the value of the row being updated/deleted at the specified index.
|
||||
pub fn get_new_column_value(&self, i: i32) -> Result<ValueRef> {
|
||||
let mut p_value: *mut ffi::sqlite3_value = ptr::null_mut();
|
||||
unsafe {
|
||||
check(ffi::sqlite3_preupdate_new(self.db, i, &mut p_value))?;
|
||||
Ok(ValueRef::from_value(p_value))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Connection {
|
||||
/// Register a callback function to be invoked before
|
||||
/// a row is updated, inserted or deleted.
|
||||
///
|
||||
/// The callback parameters are:
|
||||
///
|
||||
/// - the name of the database ("main", "temp", ...),
|
||||
/// - the name of the table that is updated,
|
||||
/// - a variant of the PreUpdateCase enum which allows access to extra functions depending
|
||||
/// on whether it's an update, delete or insert.
|
||||
#[inline]
|
||||
pub fn preupdate_hook<F>(&self, hook: Option<F>)
|
||||
where
|
||||
F: FnMut(Action, &str, &str, &PreUpdateCase) + Send + 'static,
|
||||
{
|
||||
self.db.borrow_mut().preupdate_hook(hook);
|
||||
}
|
||||
}
|
||||
|
||||
impl InnerConnection {
|
||||
#[inline]
|
||||
pub fn remove_preupdate_hook(&mut self) {
|
||||
self.preupdate_hook(None::<fn(Action, &str, &str, &PreUpdateCase)>);
|
||||
}
|
||||
|
||||
/// ```compile_fail
|
||||
/// use rusqlite::{Connection, Result, hooks::PreUpdateCase};
|
||||
/// fn main() -> Result<()> {
|
||||
/// let db = Connection::open_in_memory()?;
|
||||
/// {
|
||||
/// let mut called = std::sync::atomic::AtomicBool::new(false);
|
||||
/// db.preupdate_hook(Some(|action, db: &str, tbl: &str, case: &PreUpdateCase| {
|
||||
/// called.store(true, std::sync::atomic::Ordering::Relaxed);
|
||||
/// }));
|
||||
/// }
|
||||
/// db.execute_batch("CREATE TABLE foo AS SELECT 1 AS bar;")
|
||||
/// }
|
||||
/// ```
|
||||
fn preupdate_hook<F>(&mut self, hook: Option<F>)
|
||||
where
|
||||
F: FnMut(Action, &str, &str, &PreUpdateCase) + Send + 'static,
|
||||
{
|
||||
unsafe extern "C" fn call_boxed_closure<F>(
|
||||
p_arg: *mut c_void,
|
||||
sqlite: *mut ffi::sqlite3,
|
||||
action_code: c_int,
|
||||
db_name: *const c_char,
|
||||
tbl_name: *const c_char,
|
||||
old_row_id: i64,
|
||||
new_row_id: i64,
|
||||
) where
|
||||
F: FnMut(Action, &str, &str, &PreUpdateCase),
|
||||
{
|
||||
let action = Action::from(action_code);
|
||||
|
||||
let preupdate_case = match action {
|
||||
Action::SQLITE_INSERT => PreUpdateCase::Insert(PreUpdateNewValueAccessor {
|
||||
db: sqlite,
|
||||
new_row_id,
|
||||
}),
|
||||
Action::SQLITE_DELETE => PreUpdateCase::Delete(PreUpdateOldValueAccessor {
|
||||
db: sqlite,
|
||||
old_row_id,
|
||||
}),
|
||||
Action::SQLITE_UPDATE => PreUpdateCase::Update {
|
||||
old_value_accessor: PreUpdateOldValueAccessor {
|
||||
db: sqlite,
|
||||
old_row_id,
|
||||
},
|
||||
new_value_accessor: PreUpdateNewValueAccessor {
|
||||
db: sqlite,
|
||||
new_row_id,
|
||||
},
|
||||
},
|
||||
Action::UNKNOWN => PreUpdateCase::Unknown,
|
||||
};
|
||||
|
||||
drop(catch_unwind(|| {
|
||||
let boxed_hook: *mut F = p_arg.cast::<F>();
|
||||
(*boxed_hook)(
|
||||
action,
|
||||
expect_utf8(db_name, "database name"),
|
||||
expect_utf8(tbl_name, "table name"),
|
||||
&preupdate_case,
|
||||
);
|
||||
}));
|
||||
}
|
||||
|
||||
let free_preupdate_hook = if hook.is_some() {
|
||||
Some(free_boxed_hook::<F> as unsafe fn(*mut c_void))
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
let previous_hook = match hook {
|
||||
Some(hook) => {
|
||||
let boxed_hook: *mut F = Box::into_raw(Box::new(hook));
|
||||
unsafe {
|
||||
ffi::sqlite3_preupdate_hook(
|
||||
self.db(),
|
||||
Some(call_boxed_closure::<F>),
|
||||
boxed_hook.cast(),
|
||||
)
|
||||
}
|
||||
}
|
||||
_ => unsafe { ffi::sqlite3_preupdate_hook(self.db(), None, ptr::null_mut()) },
|
||||
};
|
||||
if !previous_hook.is_null() {
|
||||
if let Some(free_boxed_hook) = self.free_preupdate_hook {
|
||||
unsafe { free_boxed_hook(previous_hook) };
|
||||
}
|
||||
}
|
||||
self.free_preupdate_hook = free_preupdate_hook;
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use std::sync::atomic::{AtomicBool, Ordering};
|
||||
|
||||
use super::super::Action;
|
||||
use super::PreUpdateCase;
|
||||
use crate::{Connection, Result};
|
||||
|
||||
#[test]
|
||||
fn test_preupdate_hook_insert() -> Result<()> {
|
||||
let db = Connection::open_in_memory()?;
|
||||
|
||||
static CALLED: AtomicBool = AtomicBool::new(false);
|
||||
|
||||
db.preupdate_hook(Some(|action, db: &str, tbl: &str, case: &PreUpdateCase| {
|
||||
assert_eq!(Action::SQLITE_INSERT, action);
|
||||
assert_eq!("main", db);
|
||||
assert_eq!("foo", tbl);
|
||||
match case {
|
||||
PreUpdateCase::Insert(accessor) => {
|
||||
assert_eq!(1, accessor.get_column_count());
|
||||
assert_eq!(1, accessor.get_new_row_id());
|
||||
assert_eq!(0, accessor.get_query_depth());
|
||||
// out of bounds access should return an error
|
||||
assert!(accessor.get_new_column_value(1).is_err());
|
||||
assert_eq!(
|
||||
"lisa",
|
||||
accessor.get_new_column_value(0).unwrap().as_str().unwrap()
|
||||
);
|
||||
assert_eq!(0, accessor.get_query_depth());
|
||||
}
|
||||
_ => panic!("wrong preupdate case"),
|
||||
}
|
||||
CALLED.store(true, Ordering::Relaxed);
|
||||
}));
|
||||
db.execute_batch("CREATE TABLE foo (t TEXT)")?;
|
||||
db.execute_batch("INSERT INTO foo VALUES ('lisa')")?;
|
||||
assert!(CALLED.load(Ordering::Relaxed));
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_preupdate_hook_delete() -> Result<()> {
|
||||
let db = Connection::open_in_memory()?;
|
||||
|
||||
static CALLED: AtomicBool = AtomicBool::new(false);
|
||||
|
||||
db.execute_batch("CREATE TABLE foo (t TEXT)")?;
|
||||
db.execute_batch("INSERT INTO foo VALUES ('lisa')")?;
|
||||
|
||||
db.preupdate_hook(Some(|action, db: &str, tbl: &str, case: &PreUpdateCase| {
|
||||
assert_eq!(Action::SQLITE_DELETE, action);
|
||||
assert_eq!("main", db);
|
||||
assert_eq!("foo", tbl);
|
||||
match case {
|
||||
PreUpdateCase::Delete(accessor) => {
|
||||
assert_eq!(1, accessor.get_column_count());
|
||||
assert_eq!(1, accessor.get_old_row_id());
|
||||
assert_eq!(0, accessor.get_query_depth());
|
||||
// out of bounds access should return an error
|
||||
assert!(accessor.get_old_column_value(1).is_err());
|
||||
assert_eq!(
|
||||
"lisa",
|
||||
accessor.get_old_column_value(0).unwrap().as_str().unwrap()
|
||||
);
|
||||
assert_eq!(0, accessor.get_query_depth());
|
||||
}
|
||||
_ => panic!("wrong preupdate case"),
|
||||
}
|
||||
CALLED.store(true, Ordering::Relaxed);
|
||||
}));
|
||||
|
||||
db.execute_batch("DELETE from foo")?;
|
||||
assert!(CALLED.load(Ordering::Relaxed));
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_preupdate_hook_update() -> Result<()> {
|
||||
let db = Connection::open_in_memory()?;
|
||||
|
||||
static CALLED: AtomicBool = AtomicBool::new(false);
|
||||
|
||||
db.execute_batch("CREATE TABLE foo (t TEXT)")?;
|
||||
db.execute_batch("INSERT INTO foo VALUES ('lisa')")?;
|
||||
|
||||
db.preupdate_hook(Some(|action, db: &str, tbl: &str, case: &PreUpdateCase| {
|
||||
assert_eq!(Action::SQLITE_UPDATE, action);
|
||||
assert_eq!("main", db);
|
||||
assert_eq!("foo", tbl);
|
||||
match case {
|
||||
PreUpdateCase::Update {
|
||||
old_value_accessor,
|
||||
new_value_accessor,
|
||||
} => {
|
||||
assert_eq!(1, old_value_accessor.get_column_count());
|
||||
assert_eq!(1, old_value_accessor.get_old_row_id());
|
||||
assert_eq!(0, old_value_accessor.get_query_depth());
|
||||
// out of bounds access should return an error
|
||||
assert!(old_value_accessor.get_old_column_value(1).is_err());
|
||||
assert_eq!(
|
||||
"lisa",
|
||||
old_value_accessor
|
||||
.get_old_column_value(0)
|
||||
.unwrap()
|
||||
.as_str()
|
||||
.unwrap()
|
||||
);
|
||||
assert_eq!(0, old_value_accessor.get_query_depth());
|
||||
|
||||
assert_eq!(1, new_value_accessor.get_column_count());
|
||||
assert_eq!(1, new_value_accessor.get_new_row_id());
|
||||
assert_eq!(0, new_value_accessor.get_query_depth());
|
||||
// out of bounds access should return an error
|
||||
assert!(new_value_accessor.get_new_column_value(1).is_err());
|
||||
assert_eq!(
|
||||
"janice",
|
||||
new_value_accessor
|
||||
.get_new_column_value(0)
|
||||
.unwrap()
|
||||
.as_str()
|
||||
.unwrap()
|
||||
);
|
||||
assert_eq!(0, new_value_accessor.get_query_depth());
|
||||
}
|
||||
_ => panic!("wrong preupdate case"),
|
||||
}
|
||||
CALLED.store(true, Ordering::Relaxed);
|
||||
}));
|
||||
|
||||
db.execute_batch("UPDATE foo SET t = 'janice'")?;
|
||||
assert!(CALLED.load(Ordering::Relaxed));
|
||||
Ok(())
|
||||
}
|
||||
}
|
@ -12,6 +12,7 @@ use super::{Connection, InterruptHandle, OpenFlags, PrepFlags, Result};
|
||||
use crate::error::{error_from_handle, error_from_sqlite_code, error_with_offset, Error};
|
||||
use crate::raw_statement::RawStatement;
|
||||
use crate::statement::Statement;
|
||||
use crate::version_number;
|
||||
|
||||
pub struct InnerConnection {
|
||||
pub db: *mut ffi::sqlite3,
|
||||
@ -19,7 +20,7 @@ pub struct InnerConnection {
|
||||
// a `sqlite3_interrupt`, and vice versa, so we take this mutex during
|
||||
// those functions. This protects a copy of the `db` pointer (which is
|
||||
// cleared on closing), however the main copy, `db`, is unprotected.
|
||||
// Otherwise, a long running query would prevent calling interrupt, as
|
||||
// Otherwise, a long-running query would prevent calling interrupt, as
|
||||
// interrupt would only acquire the lock after the query's completion.
|
||||
interrupt_lock: Arc<Mutex<*mut ffi::sqlite3>>,
|
||||
#[cfg(feature = "hooks")]
|
||||
@ -32,6 +33,8 @@ pub struct InnerConnection {
|
||||
pub progress_handler: Option<Box<dyn FnMut() -> bool + Send>>,
|
||||
#[cfg(feature = "hooks")]
|
||||
pub authorizer: Option<crate::hooks::BoxedAuthorizer>,
|
||||
#[cfg(feature = "preupdate_hook")]
|
||||
pub free_preupdate_hook: Option<unsafe fn(*mut ::std::os::raw::c_void)>,
|
||||
owned: bool,
|
||||
}
|
||||
|
||||
@ -40,10 +43,10 @@ unsafe impl Send for InnerConnection {}
|
||||
impl InnerConnection {
|
||||
#[allow(clippy::mutex_atomic, clippy::arc_with_non_send_sync)] // See unsafe impl Send / Sync for InterruptHandle
|
||||
#[inline]
|
||||
pub unsafe fn new(db: *mut ffi::sqlite3, owned: bool) -> InnerConnection {
|
||||
InnerConnection {
|
||||
pub unsafe fn new(db: *mut ffi::sqlite3, owned: bool) -> Self {
|
||||
Self {
|
||||
db,
|
||||
interrupt_lock: Arc::new(Mutex::new(db)),
|
||||
interrupt_lock: Arc::new(Mutex::new(if owned { db } else { ptr::null_mut() })),
|
||||
#[cfg(feature = "hooks")]
|
||||
free_commit_hook: None,
|
||||
#[cfg(feature = "hooks")]
|
||||
@ -54,15 +57,17 @@ impl InnerConnection {
|
||||
progress_handler: None,
|
||||
#[cfg(feature = "hooks")]
|
||||
authorizer: None,
|
||||
#[cfg(feature = "preupdate_hook")]
|
||||
free_preupdate_hook: None,
|
||||
owned,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn open_with_flags(
|
||||
c_path: &CStr,
|
||||
flags: OpenFlags,
|
||||
mut flags: OpenFlags,
|
||||
vfs: Option<&CStr>,
|
||||
) -> Result<InnerConnection> {
|
||||
) -> Result<Self> {
|
||||
ensure_safe_sqlite_threading_mode()?;
|
||||
|
||||
let z_vfs = match vfs {
|
||||
@ -70,6 +75,14 @@ impl InnerConnection {
|
||||
None => ptr::null(),
|
||||
};
|
||||
|
||||
// turn on extended results code before opening database to have a better diagnostic if a failure happens
|
||||
let exrescode = if version_number() >= 3_037_000 {
|
||||
flags |= OpenFlags::SQLITE_OPEN_EXRESCODE;
|
||||
true
|
||||
} else {
|
||||
false // flag SQLITE_OPEN_EXRESCODE is ignored by SQLite version < 3.37.0
|
||||
};
|
||||
|
||||
unsafe {
|
||||
let mut db: *mut ffi::sqlite3 = ptr::null_mut();
|
||||
let r = ffi::sqlite3_open_v2(c_path.as_ptr(), &mut db, flags.bits(), z_vfs);
|
||||
@ -99,7 +112,9 @@ impl InnerConnection {
|
||||
}
|
||||
|
||||
// attempt to turn on extended results code; don't fail if we can't.
|
||||
ffi::sqlite3_extended_result_codes(db, 1);
|
||||
if !exrescode {
|
||||
ffi::sqlite3_extended_result_codes(db, 1);
|
||||
}
|
||||
|
||||
let r = ffi::sqlite3_busy_timeout(db, 5000);
|
||||
if r != ffi::SQLITE_OK {
|
||||
@ -108,7 +123,7 @@ impl InnerConnection {
|
||||
return Err(e);
|
||||
}
|
||||
|
||||
Ok(InnerConnection::new(db, true))
|
||||
Ok(Self::new(db, true))
|
||||
}
|
||||
}
|
||||
|
||||
@ -119,7 +134,7 @@ impl InnerConnection {
|
||||
|
||||
#[inline]
|
||||
pub fn decode_result(&self, code: c_int) -> Result<()> {
|
||||
unsafe { InnerConnection::decode_result_raw(self.db(), code) }
|
||||
unsafe { Self::decode_result_raw(self.db(), code) }
|
||||
}
|
||||
|
||||
#[inline]
|
||||
@ -137,9 +152,10 @@ impl InnerConnection {
|
||||
return Ok(());
|
||||
}
|
||||
self.remove_hooks();
|
||||
self.remove_preupdate_hook();
|
||||
let mut shared_handle = self.interrupt_lock.lock().unwrap();
|
||||
assert!(
|
||||
!shared_handle.is_null(),
|
||||
!self.owned || !shared_handle.is_null(),
|
||||
"Bug: Somehow interrupt_lock was cleared before the DB was closed"
|
||||
);
|
||||
if !self.owned {
|
||||
@ -150,7 +166,7 @@ impl InnerConnection {
|
||||
let r = ffi::sqlite3_close(self.db);
|
||||
// Need to use _raw because _guard has a reference out, and
|
||||
// decode_result takes &mut self.
|
||||
let r = InnerConnection::decode_result_raw(self.db, r);
|
||||
let r = Self::decode_result_raw(self.db, r);
|
||||
if r.is_ok() {
|
||||
*shared_handle = ptr::null_mut();
|
||||
self.db = ptr::null_mut();
|
||||
@ -210,7 +226,6 @@ impl InnerConnection {
|
||||
let mut c_stmt: *mut ffi::sqlite3_stmt = ptr::null_mut();
|
||||
let (c_sql, len, _) = str_for_sqlite(sql.as_bytes())?;
|
||||
let mut c_tail: *const c_char = ptr::null();
|
||||
// TODO sqlite3_prepare_v3 (https://sqlite.org/c3ref/c_prepare_normalize.html) // 3.20.0, #728
|
||||
#[cfg(not(feature = "unlock_notify"))]
|
||||
let r = unsafe { self.prepare_(c_sql, len, flags, &mut c_stmt, &mut c_tail) };
|
||||
#[cfg(feature = "unlock_notify")]
|
||||
@ -327,6 +342,10 @@ impl InnerConnection {
|
||||
#[inline]
|
||||
fn remove_hooks(&mut self) {}
|
||||
|
||||
#[cfg(not(feature = "preupdate_hook"))]
|
||||
#[inline]
|
||||
fn remove_preupdate_hook(&mut self) {}
|
||||
|
||||
pub fn db_readonly(&self, db_name: super::DatabaseName<'_>) -> Result<bool> {
|
||||
let name = db_name.as_cstring()?;
|
||||
let r = unsafe { ffi::sqlite3_db_readonly(self.db, name.as_ptr()) };
|
||||
@ -375,6 +394,11 @@ impl InnerConnection {
|
||||
pub fn release_memory(&self) -> Result<()> {
|
||||
self.decode_result(unsafe { ffi::sqlite3_db_release_memory(self.db) })
|
||||
}
|
||||
|
||||
#[cfg(feature = "modern_sqlite")] // 3.41.0
|
||||
pub fn is_interrupted(&self) -> bool {
|
||||
unsafe { ffi::sqlite3_is_interrupted(self.db) == 1 }
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for InnerConnection {
|
||||
|
156
src/lib.rs
156
src/lib.rs
@ -93,6 +93,8 @@ pub use rusqlite_macros::__bind;
|
||||
|
||||
mod error;
|
||||
|
||||
#[cfg(not(feature = "loadable_extension"))]
|
||||
pub mod auto_extension;
|
||||
#[cfg(feature = "backup")]
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "backup")))]
|
||||
pub mod backup;
|
||||
@ -149,7 +151,7 @@ pub(crate) use util::SmallCString;
|
||||
// Number of cached prepared statements we'll hold on to.
|
||||
const STATEMENT_CACHE_DEFAULT_CAPACITY: usize = 16;
|
||||
|
||||
/// A macro making it more convenient to longer lists of
|
||||
/// A macro making it more convenient to pass longer lists of
|
||||
/// parameters as a `&[&dyn ToSql]`.
|
||||
///
|
||||
/// # Example
|
||||
@ -289,8 +291,7 @@ impl<T> OptionalExtension<T> for Result<T> {
|
||||
}
|
||||
|
||||
unsafe fn errmsg_to_string(errmsg: *const c_char) -> String {
|
||||
let c_slice = CStr::from_ptr(errmsg).to_bytes();
|
||||
String::from_utf8_lossy(c_slice).into_owned()
|
||||
CStr::from_ptr(errmsg).to_string_lossy().into_owned()
|
||||
}
|
||||
|
||||
fn str_to_cstring(s: &str) -> Result<SmallCString> {
|
||||
@ -365,7 +366,7 @@ impl DatabaseName<'_> {
|
||||
fn as_cstring(&self) -> Result<SmallCString> {
|
||||
use self::DatabaseName::{Attached, Main, Temp};
|
||||
match *self {
|
||||
Main => str_to_cstring("main"),
|
||||
Main => str_to_cstring("main"), // TODO C-string literals
|
||||
Temp => str_to_cstring("temp"),
|
||||
Attached(s) => str_to_cstring(s),
|
||||
}
|
||||
@ -376,6 +377,7 @@ impl DatabaseName<'_> {
|
||||
pub struct Connection {
|
||||
db: RefCell<InnerConnection>,
|
||||
cache: StatementCache,
|
||||
transaction_behavior: TransactionBehavior,
|
||||
}
|
||||
|
||||
unsafe impl Send for Connection {}
|
||||
@ -441,9 +443,9 @@ impl Connection {
|
||||
/// Will return `Err` if `path` cannot be converted to a C-compatible string
|
||||
/// or if the underlying SQLite open call fails.
|
||||
#[inline]
|
||||
pub fn open<P: AsRef<Path>>(path: P) -> Result<Connection> {
|
||||
pub fn open<P: AsRef<Path>>(path: P) -> Result<Self> {
|
||||
let flags = OpenFlags::default();
|
||||
Connection::open_with_flags(path, flags)
|
||||
Self::open_with_flags(path, flags)
|
||||
}
|
||||
|
||||
/// Open a new connection to an in-memory SQLite database.
|
||||
@ -452,9 +454,9 @@ impl Connection {
|
||||
///
|
||||
/// Will return `Err` if the underlying SQLite open call fails.
|
||||
#[inline]
|
||||
pub fn open_in_memory() -> Result<Connection> {
|
||||
pub fn open_in_memory() -> Result<Self> {
|
||||
let flags = OpenFlags::default();
|
||||
Connection::open_in_memory_with_flags(flags)
|
||||
Self::open_in_memory_with_flags(flags)
|
||||
}
|
||||
|
||||
/// Open a new connection to a SQLite database.
|
||||
@ -467,11 +469,12 @@ impl Connection {
|
||||
/// Will return `Err` if `path` cannot be converted to a C-compatible
|
||||
/// string or if the underlying SQLite open call fails.
|
||||
#[inline]
|
||||
pub fn open_with_flags<P: AsRef<Path>>(path: P, flags: OpenFlags) -> Result<Connection> {
|
||||
pub fn open_with_flags<P: AsRef<Path>>(path: P, flags: OpenFlags) -> Result<Self> {
|
||||
let c_path = path_to_cstring(path.as_ref())?;
|
||||
InnerConnection::open_with_flags(&c_path, flags, None).map(|db| Connection {
|
||||
InnerConnection::open_with_flags(&c_path, flags, None).map(|db| Self {
|
||||
db: RefCell::new(db),
|
||||
cache: StatementCache::with_capacity(STATEMENT_CACHE_DEFAULT_CAPACITY),
|
||||
transaction_behavior: TransactionBehavior::Deferred,
|
||||
})
|
||||
}
|
||||
|
||||
@ -490,12 +493,13 @@ impl Connection {
|
||||
path: P,
|
||||
flags: OpenFlags,
|
||||
vfs: &str,
|
||||
) -> Result<Connection> {
|
||||
) -> Result<Self> {
|
||||
let c_path = path_to_cstring(path.as_ref())?;
|
||||
let c_vfs = str_to_cstring(vfs)?;
|
||||
InnerConnection::open_with_flags(&c_path, flags, Some(&c_vfs)).map(|db| Connection {
|
||||
InnerConnection::open_with_flags(&c_path, flags, Some(&c_vfs)).map(|db| Self {
|
||||
db: RefCell::new(db),
|
||||
cache: StatementCache::with_capacity(STATEMENT_CACHE_DEFAULT_CAPACITY),
|
||||
transaction_behavior: TransactionBehavior::Deferred,
|
||||
})
|
||||
}
|
||||
|
||||
@ -508,8 +512,8 @@ impl Connection {
|
||||
///
|
||||
/// Will return `Err` if the underlying SQLite open call fails.
|
||||
#[inline]
|
||||
pub fn open_in_memory_with_flags(flags: OpenFlags) -> Result<Connection> {
|
||||
Connection::open_with_flags(":memory:", flags)
|
||||
pub fn open_in_memory_with_flags(flags: OpenFlags) -> Result<Self> {
|
||||
Self::open_with_flags(":memory:", flags)
|
||||
}
|
||||
|
||||
/// Open a new connection to an in-memory SQLite database using the specific
|
||||
@ -523,8 +527,8 @@ impl Connection {
|
||||
/// Will return `Err` if `vfs` cannot be converted to a C-compatible
|
||||
/// string or if the underlying SQLite open call fails.
|
||||
#[inline]
|
||||
pub fn open_in_memory_with_flags_and_vfs(flags: OpenFlags, vfs: &str) -> Result<Connection> {
|
||||
Connection::open_with_flags_and_vfs(":memory:", flags, vfs)
|
||||
pub fn open_in_memory_with_flags_and_vfs(flags: OpenFlags, vfs: &str) -> Result<Self> {
|
||||
Self::open_with_flags_and_vfs(":memory:", flags, vfs)
|
||||
}
|
||||
|
||||
/// Convenience method to run multiple SQL statements (that cannot take any
|
||||
@ -788,7 +792,7 @@ impl Connection {
|
||||
///
|
||||
/// Will return `Err` if the underlying SQLite call fails.
|
||||
#[inline]
|
||||
pub fn close(self) -> Result<(), (Connection, Error)> {
|
||||
pub fn close(self) -> Result<(), (Self, Error)> {
|
||||
self.flush_prepared_statement_cache();
|
||||
let r = self.db.borrow_mut().close();
|
||||
r.map_err(move |err| (self, err))
|
||||
@ -943,23 +947,40 @@ impl Connection {
|
||||
///
|
||||
/// This function is unsafe because improper use may impact the Connection.
|
||||
#[inline]
|
||||
pub unsafe fn from_handle(db: *mut ffi::sqlite3) -> Result<Connection> {
|
||||
pub unsafe fn from_handle(db: *mut ffi::sqlite3) -> Result<Self> {
|
||||
let db = InnerConnection::new(db, false);
|
||||
Ok(Connection {
|
||||
Ok(Self {
|
||||
db: RefCell::new(db),
|
||||
cache: StatementCache::with_capacity(STATEMENT_CACHE_DEFAULT_CAPACITY),
|
||||
transaction_behavior: TransactionBehavior::Deferred,
|
||||
})
|
||||
}
|
||||
|
||||
/// Like SQLITE_EXTENSION_INIT2 macro
|
||||
/// Helper to register an SQLite extension written in Rust.
|
||||
/// For [persistent](https://sqlite.org/loadext.html#persistent_loadable_extensions) extension,
|
||||
/// `init` should return `Ok(true)`.
|
||||
/// # Safety
|
||||
/// * Results are undefined if `init` does not just register features.
|
||||
#[cfg(feature = "loadable_extension")]
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "loadable_extension")))]
|
||||
pub unsafe fn extension_init2(
|
||||
db: *mut ffi::sqlite3,
|
||||
pz_err_msg: *mut *mut c_char,
|
||||
p_api: *mut ffi::sqlite3_api_routines,
|
||||
) -> Result<Connection> {
|
||||
ffi::rusqlite_extension_init2(p_api)?;
|
||||
Connection::from_handle(db)
|
||||
init: fn(Self) -> Result<bool>,
|
||||
) -> c_int {
|
||||
if p_api.is_null() {
|
||||
return ffi::SQLITE_ERROR;
|
||||
}
|
||||
match ffi::rusqlite_extension_init2(p_api)
|
||||
.map_err(Error::from)
|
||||
.and(Self::from_handle(db))
|
||||
.and_then(init)
|
||||
{
|
||||
Err(err) => to_sqlite_error(&err, pz_err_msg),
|
||||
Ok(true) => ffi::SQLITE_OK_LOAD_PERMANENTLY,
|
||||
_ => ffi::SQLITE_OK,
|
||||
}
|
||||
}
|
||||
|
||||
/// Create a `Connection` from a raw owned handle.
|
||||
@ -975,15 +996,16 @@ impl Connection {
|
||||
/// and owned by the caller, e.g. as a result of calling
|
||||
/// `ffi::sqlite3_open`().
|
||||
#[inline]
|
||||
pub unsafe fn from_handle_owned(db: *mut ffi::sqlite3) -> Result<Connection> {
|
||||
pub unsafe fn from_handle_owned(db: *mut ffi::sqlite3) -> Result<Self> {
|
||||
let db = InnerConnection::new(db, true);
|
||||
Ok(Connection {
|
||||
Ok(Self {
|
||||
db: RefCell::new(db),
|
||||
cache: StatementCache::with_capacity(STATEMENT_CACHE_DEFAULT_CAPACITY),
|
||||
transaction_behavior: TransactionBehavior::Deferred,
|
||||
})
|
||||
}
|
||||
|
||||
/// Get access to a handle that can be used to interrupt long running
|
||||
/// Get access to a handle that can be used to interrupt long-running
|
||||
/// queries from another thread.
|
||||
#[inline]
|
||||
pub fn get_interrupt_handle(&self) -> InterruptHandle {
|
||||
@ -1037,6 +1059,32 @@ impl Connection {
|
||||
pub fn is_readonly(&self, db_name: DatabaseName<'_>) -> Result<bool> {
|
||||
self.db.borrow().db_readonly(db_name)
|
||||
}
|
||||
|
||||
/// Return the schema name for a database connection
|
||||
///
|
||||
/// ## Failure
|
||||
///
|
||||
/// Return an `Error::InvalidDatabaseIndex` if `index` is out of range.
|
||||
#[cfg(feature = "modern_sqlite")] // 3.39.0
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "modern_sqlite")))]
|
||||
pub fn db_name(&self, index: usize) -> Result<String> {
|
||||
unsafe {
|
||||
let db = self.handle();
|
||||
let name = ffi::sqlite3_db_name(db, index as c_int);
|
||||
if name.is_null() {
|
||||
Err(Error::InvalidDatabaseIndex(index))
|
||||
} else {
|
||||
Ok(CStr::from_ptr(name).to_str()?.to_owned())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Determine whether an interrupt is currently in effect
|
||||
#[cfg(feature = "modern_sqlite")] // 3.41.0
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "modern_sqlite")))]
|
||||
pub fn is_interrupted(&self) -> bool {
|
||||
self.db.borrow().is_interrupted()
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Debug for Connection {
|
||||
@ -1073,7 +1121,7 @@ pub struct Batch<'conn, 'sql> {
|
||||
|
||||
impl<'conn, 'sql> Batch<'conn, 'sql> {
|
||||
/// Constructor
|
||||
pub fn new(conn: &'conn Connection, sql: &'sql str) -> Batch<'conn, 'sql> {
|
||||
pub fn new(conn: &'conn Connection, sql: &'sql str) -> Self {
|
||||
Batch { conn, sql, tail: 0 }
|
||||
}
|
||||
|
||||
@ -1122,7 +1170,7 @@ bitflags::bitflags! {
|
||||
/// If the database does not already exist, an error is returned.
|
||||
const SQLITE_OPEN_READ_ONLY = ffi::SQLITE_OPEN_READONLY;
|
||||
/// The database is opened for reading and writing if possible,
|
||||
/// or reading only if the file is write protected by the operating system.
|
||||
/// or reading only if the file is write-protected by the operating system.
|
||||
/// In either case the database must already exist, otherwise an error is returned.
|
||||
const SQLITE_OPEN_READ_WRITE = ffi::SQLITE_OPEN_READWRITE;
|
||||
/// The database is created if it does not already exist
|
||||
@ -1182,13 +1230,13 @@ bitflags::bitflags! {
|
||||
|
||||
impl Default for OpenFlags {
|
||||
#[inline]
|
||||
fn default() -> OpenFlags {
|
||||
fn default() -> Self {
|
||||
// Note: update the `Connection::open` and top-level `OpenFlags` docs if
|
||||
// you change these.
|
||||
OpenFlags::SQLITE_OPEN_READ_WRITE
|
||||
| OpenFlags::SQLITE_OPEN_CREATE
|
||||
| OpenFlags::SQLITE_OPEN_NO_MUTEX
|
||||
| OpenFlags::SQLITE_OPEN_URI
|
||||
Self::SQLITE_OPEN_READ_WRITE
|
||||
| Self::SQLITE_OPEN_CREATE
|
||||
| Self::SQLITE_OPEN_NO_MUTEX
|
||||
| Self::SQLITE_OPEN_URI
|
||||
}
|
||||
}
|
||||
|
||||
@ -1343,7 +1391,7 @@ mod test {
|
||||
assert_eq!(Some(""), db.path());
|
||||
let path = tmp.path().join("file.db");
|
||||
let db = Connection::open(path)?;
|
||||
assert!(db.path().map(|p| p.ends_with("file.db")).unwrap_or(false));
|
||||
assert!(db.path().is_some_and(|p| p.ends_with("file.db")));
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@ -1657,7 +1705,7 @@ mod test {
|
||||
let db = Connection::open_in_memory()?;
|
||||
assert_eq!("memory", db.one_column::<String>("PRAGMA journal_mode")?);
|
||||
let mode = db.one_column::<String>("PRAGMA journal_mode=off")?;
|
||||
if cfg!(features = "bundled") {
|
||||
if cfg!(feature = "bundled") {
|
||||
assert_eq!(mode, "off");
|
||||
} else {
|
||||
// Note: system SQLite on macOS defaults to "off" rather than
|
||||
@ -1827,7 +1875,7 @@ mod test {
|
||||
db.close().unwrap();
|
||||
handle.interrupt();
|
||||
|
||||
// Look at it's internals to see if we cleared it out properly.
|
||||
// Look at its internals to see if we cleared it out properly.
|
||||
let db_guard = handle.db_lock.lock().unwrap();
|
||||
assert!(db_guard.is_null());
|
||||
// It would be nice to test that we properly handle close/interrupt
|
||||
@ -1883,7 +1931,7 @@ mod test {
|
||||
#[test]
|
||||
fn test_from_handle_owned() -> Result<()> {
|
||||
let mut handle: *mut ffi::sqlite3 = std::ptr::null_mut();
|
||||
let r = unsafe { ffi::sqlite3_open(":memory:\0".as_ptr() as *const c_char, &mut handle) };
|
||||
let r = unsafe { ffi::sqlite3_open(c":memory:".as_ptr(), &mut handle) };
|
||||
assert_eq!(r, ffi::SQLITE_OK);
|
||||
let db = unsafe { Connection::from_handle_owned(handle) }?;
|
||||
db.execute_batch("PRAGMA VACUUM")?;
|
||||
@ -1903,8 +1951,8 @@ mod test {
|
||||
impl fmt::Display for CustomError {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> {
|
||||
match *self {
|
||||
CustomError::SomeError => write!(f, "my custom error"),
|
||||
CustomError::Sqlite(ref se) => write!(f, "my custom error: {se}"),
|
||||
Self::SomeError => write!(f, "my custom error"),
|
||||
Self::Sqlite(ref se) => write!(f, "my custom error: {se}"),
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1916,15 +1964,15 @@ mod test {
|
||||
|
||||
fn cause(&self) -> Option<&dyn StdError> {
|
||||
match *self {
|
||||
CustomError::SomeError => None,
|
||||
CustomError::Sqlite(ref se) => Some(se),
|
||||
Self::SomeError => None,
|
||||
Self::Sqlite(ref se) => Some(se),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Error> for CustomError {
|
||||
fn from(se: Error) -> CustomError {
|
||||
CustomError::Sqlite(se)
|
||||
fn from(se: Error) -> Self {
|
||||
Self::Sqlite(se)
|
||||
}
|
||||
}
|
||||
|
||||
@ -2206,4 +2254,26 @@ mod test {
|
||||
assert_eq!((v1.as_str(), v2), (name, age));
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(feature = "modern_sqlite")]
|
||||
fn test_db_name() -> Result<()> {
|
||||
let db = Connection::open_in_memory()?;
|
||||
assert_eq!(db.db_name(0).unwrap(), "main");
|
||||
assert_eq!(db.db_name(1).unwrap(), "temp");
|
||||
assert_eq!(db.db_name(2), Err(Error::InvalidDatabaseIndex(2)));
|
||||
db.execute_batch("ATTACH DATABASE ':memory:' AS xyz;")?;
|
||||
assert_eq!(db.db_name(2).unwrap(), "xyz");
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(feature = "modern_sqlite")]
|
||||
fn test_is_interrupted() -> Result<()> {
|
||||
let db = Connection::open_in_memory()?;
|
||||
assert!(!db.is_interrupted());
|
||||
db.get_interrupt_handle().interrupt();
|
||||
assert!(db.is_interrupted());
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
@ -53,7 +53,7 @@ use sealed::Sealed;
|
||||
///
|
||||
/// (Note: in this case we don't implement this for slices for coherence
|
||||
/// reasons, so it really is only for the "reference to array" types —
|
||||
/// hence why the number of parameters must be <= 32 or you need to
|
||||
/// hence why the number of parameters must be <= 32, or you need to
|
||||
/// reach for `rusqlite::params!`)
|
||||
///
|
||||
/// Unfortunately, in the current design it's not possible to allow this for
|
||||
@ -108,7 +108,7 @@ use sealed::Sealed;
|
||||
/// parameters, or lists where the number of parameters exceeds 32.
|
||||
///
|
||||
/// - As a slice of `&[(&str, &dyn ToSql)]`. This is what essentially all of
|
||||
/// these boil down to in the end, conceptually at least. In theory you can
|
||||
/// these boil down to in the end, conceptually at least. In theory, you can
|
||||
/// pass this as `stmt`.
|
||||
///
|
||||
/// - As array references, similar to the positional params. This looks like
|
||||
@ -124,7 +124,7 @@ use sealed::Sealed;
|
||||
/// ```rust,no_run
|
||||
/// # use rusqlite::{Connection, Result, named_params};
|
||||
/// fn insert(conn: &Connection) -> Result<()> {
|
||||
/// let mut stmt = conn.prepare("INSERT INTO test (key, value) VALUES (:key, :value)")?;
|
||||
/// let mut stmt = conn.prepare("INSERT INTO test (key, value) VALUES (:key, :val)")?;
|
||||
/// // Using `rusqlite::params!`:
|
||||
/// stmt.execute(named_params! { ":key": "one", ":val": 2 })?;
|
||||
/// // Alternatively:
|
||||
@ -196,7 +196,7 @@ pub trait Params: Sealed {
|
||||
// forces people to use `params![...]` or `rusqlite::params_from_iter` for long
|
||||
// homogeneous lists of parameters. This is not that big of a deal, but is
|
||||
// unfortunate, especially because I mostly did it because I wanted a simple
|
||||
// syntax for no-params that didnt require importing -- the empty tuple fits
|
||||
// syntax for no-params that didn't require importing -- the empty tuple fits
|
||||
// that nicely, but I didn't think of it until much later.
|
||||
//
|
||||
// Admittedly, if we did have the generic impl, then we *wouldn't* support the
|
||||
@ -264,7 +264,7 @@ macro_rules! single_tuple_impl {
|
||||
}
|
||||
}
|
||||
|
||||
// We use a the macro for the rest, but don't bother with trying to implement it
|
||||
// We use a macro for the rest, but don't bother with trying to implement it
|
||||
// in a single invocation (it's possible to do, but my attempts were almost the
|
||||
// same amount of code as just writing it out this way, and much more dense --
|
||||
// it is a more complicated case than the TryFrom macro we have for row->tuple).
|
||||
@ -407,7 +407,7 @@ impl_for_array_ref!(
|
||||
/// production-ready:
|
||||
///
|
||||
/// - production code should ensure `usernames` isn't so large that it will
|
||||
/// surpass [`conn.limit(Limit::SQLITE_LIMIT_VARIABLE_NUMBER)`][limits]),
|
||||
/// surpass [`conn.limit(Limit::SQLITE_LIMIT_VARIABLE_NUMBER)`][limits],
|
||||
/// chunking if too large. (Note that the limits api requires rusqlite to have
|
||||
/// the "limits" feature).
|
||||
///
|
||||
|
@ -12,8 +12,8 @@ pub struct Sql {
|
||||
}
|
||||
|
||||
impl Sql {
|
||||
pub fn new() -> Sql {
|
||||
Sql { buf: String::new() }
|
||||
pub fn new() -> Self {
|
||||
Self { buf: String::new() }
|
||||
}
|
||||
|
||||
pub fn push_pragma(
|
||||
|
@ -29,8 +29,8 @@ pub struct RawStatement {
|
||||
|
||||
impl RawStatement {
|
||||
#[inline]
|
||||
pub unsafe fn new(stmt: *mut ffi::sqlite3_stmt, tail: usize) -> RawStatement {
|
||||
RawStatement {
|
||||
pub unsafe fn new(stmt: *mut ffi::sqlite3_stmt, tail: usize) -> Self {
|
||||
Self {
|
||||
ptr: stmt,
|
||||
tail,
|
||||
cache: ParamIndexCache::default(),
|
||||
@ -169,7 +169,7 @@ impl RawStatement {
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn clear_bindings(&self) {
|
||||
pub fn clear_bindings(&mut self) {
|
||||
unsafe {
|
||||
ffi::sqlite3_clear_bindings(self.ptr);
|
||||
} // rc is always SQLITE_OK
|
||||
|
36
src/row.rs
36
src/row.rs
@ -5,7 +5,7 @@ use std::convert;
|
||||
use super::{Error, Result, Statement};
|
||||
use crate::types::{FromSql, FromSqlError, ValueRef};
|
||||
|
||||
/// An handle for the resulting rows of a query.
|
||||
/// A handle for the resulting rows of a query.
|
||||
#[must_use = "Rows is lazy and will do nothing unless consumed"]
|
||||
pub struct Rows<'stmt> {
|
||||
pub(crate) stmt: Option<&'stmt Statement<'stmt>>,
|
||||
@ -90,7 +90,7 @@ impl<'stmt> Rows<'stmt> {
|
||||
|
||||
impl<'stmt> Rows<'stmt> {
|
||||
#[inline]
|
||||
pub(crate) fn new(stmt: &'stmt Statement<'stmt>) -> Rows<'stmt> {
|
||||
pub(crate) fn new(stmt: &'stmt Statement<'stmt>) -> Self {
|
||||
Rows {
|
||||
stmt: Some(stmt),
|
||||
row: None,
|
||||
@ -305,7 +305,7 @@ impl<'stmt> Row<'stmt> {
|
||||
/// allowing data to be read out of a row without copying.
|
||||
///
|
||||
/// This `ValueRef` is valid only as long as this Row, which is enforced by
|
||||
/// it's lifetime. This means that while this method is completely safe,
|
||||
/// its lifetime. This means that while this method is completely safe,
|
||||
/// it can be somewhat difficult to use, and most callers will be better
|
||||
/// served by [`get`](Row::get) or [`get_unwrap`](Row::get_unwrap).
|
||||
///
|
||||
@ -329,7 +329,7 @@ impl<'stmt> Row<'stmt> {
|
||||
/// allowing data to be read out of a row without copying.
|
||||
///
|
||||
/// This `ValueRef` is valid only as long as this Row, which is enforced by
|
||||
/// it's lifetime. This means that while this method is completely safe,
|
||||
/// its lifetime. This means that while this method is completely safe,
|
||||
/// it can be difficult to use, and most callers will be better served by
|
||||
/// [`get`](Row::get) or [`get_unwrap`](Row::get_unwrap).
|
||||
///
|
||||
@ -359,7 +359,7 @@ impl<'stmt> std::fmt::Debug for Row<'stmt> {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
let mut dm = f.debug_map();
|
||||
for c in 0..self.stmt.column_count() {
|
||||
let name = self.stmt.column_name(c);
|
||||
let name = self.stmt.column_name(c).expect("valid column index");
|
||||
dm.key(&name);
|
||||
let value = self.get_ref(c);
|
||||
match value {
|
||||
@ -463,7 +463,6 @@ tuples_try_from_row!(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P);
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
#![allow(clippy::redundant_closure)] // false positives due to lifetime issues; clippy issue #5594
|
||||
use crate::{Connection, Result};
|
||||
|
||||
#[test]
|
||||
@ -614,4 +613,29 @@ mod tests {
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn as_ref() -> Result<()> {
|
||||
let conn = Connection::open_in_memory()?;
|
||||
let mut stmt = conn.prepare("SELECT 'Lisa' as name, 1 as id")?;
|
||||
let rows = stmt.query([])?;
|
||||
assert_eq!(rows.as_ref().unwrap().column_count(), 2);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn debug() -> Result<()> {
|
||||
let conn = Connection::open_in_memory()?;
|
||||
let mut stmt = conn.prepare(
|
||||
"SELECT 'Lisa' as name, 1 as id, 3.14 as pi, X'53514C697465' as blob, NULL as void",
|
||||
)?;
|
||||
let mut rows = stmt.query([])?;
|
||||
let row = rows.next()?.unwrap();
|
||||
let s = format!("{row:?}");
|
||||
assert_eq!(
|
||||
s,
|
||||
r#"{"name": (Text, "Lisa"), "id": (Integer, 1), "pi": (Real, 3.14), "blob": (Blob, 6), "void": (Null, ())}"#
|
||||
);
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
121
src/session.rs
121
src/session.rs
@ -5,13 +5,13 @@ use std::ffi::CStr;
|
||||
use std::io::{Read, Write};
|
||||
use std::marker::PhantomData;
|
||||
use std::os::raw::{c_char, c_int, c_uchar, c_void};
|
||||
use std::panic::{catch_unwind, RefUnwindSafe};
|
||||
use std::panic::catch_unwind;
|
||||
use std::ptr;
|
||||
use std::slice::{from_raw_parts, from_raw_parts_mut};
|
||||
|
||||
use fallible_streaming_iterator::FallibleStreamingIterator;
|
||||
|
||||
use crate::error::{check, error_from_sqlite_code};
|
||||
use crate::error::{check, error_from_sqlite_code, Error};
|
||||
use crate::ffi;
|
||||
use crate::hooks::Action;
|
||||
use crate::types::ValueRef;
|
||||
@ -59,25 +59,22 @@ impl Session<'_> {
|
||||
/// Set a table filter
|
||||
pub fn table_filter<F>(&mut self, filter: Option<F>)
|
||||
where
|
||||
F: Fn(&str) -> bool + Send + RefUnwindSafe + 'static,
|
||||
F: Fn(&str) -> bool + Send + 'static,
|
||||
{
|
||||
unsafe extern "C" fn call_boxed_closure<F>(
|
||||
p_arg: *mut c_void,
|
||||
tbl_str: *const c_char,
|
||||
) -> c_int
|
||||
where
|
||||
F: Fn(&str) -> bool + RefUnwindSafe,
|
||||
F: Fn(&str) -> bool,
|
||||
{
|
||||
use std::str;
|
||||
|
||||
let boxed_filter: *mut F = p_arg as *mut F;
|
||||
let tbl_name = {
|
||||
let c_slice = CStr::from_ptr(tbl_str).to_bytes();
|
||||
str::from_utf8(c_slice)
|
||||
};
|
||||
let tbl_name = CStr::from_ptr(tbl_str).to_str();
|
||||
c_int::from(
|
||||
catch_unwind(|| (*boxed_filter)(tbl_name.expect("non-utf8 table name")))
|
||||
.unwrap_or_default(),
|
||||
catch_unwind(|| {
|
||||
let boxed_filter: *mut F = p_arg.cast::<F>();
|
||||
(*boxed_filter)(tbl_name.expect("non-utf8 table name"))
|
||||
})
|
||||
.unwrap_or_default(),
|
||||
)
|
||||
}
|
||||
|
||||
@ -426,7 +423,11 @@ impl ChangesetItem {
|
||||
col as i32,
|
||||
&mut p_value,
|
||||
))?;
|
||||
Ok(ValueRef::from_value(p_value))
|
||||
if p_value.is_null() {
|
||||
Err(Error::InvalidColumnIndex(col))
|
||||
} else {
|
||||
Ok(ValueRef::from_value(p_value))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -452,7 +453,11 @@ impl ChangesetItem {
|
||||
unsafe {
|
||||
let mut p_value: *mut ffi::sqlite3_value = ptr::null_mut();
|
||||
check(ffi::sqlite3changeset_new(self.it, col as i32, &mut p_value))?;
|
||||
Ok(ValueRef::from_value(p_value))
|
||||
if p_value.is_null() {
|
||||
Err(Error::InvalidColumnIndex(col))
|
||||
} else {
|
||||
Ok(ValueRef::from_value(p_value))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -465,7 +470,11 @@ impl ChangesetItem {
|
||||
unsafe {
|
||||
let mut p_value: *mut ffi::sqlite3_value = ptr::null_mut();
|
||||
check(ffi::sqlite3changeset_old(self.it, col as i32, &mut p_value))?;
|
||||
Ok(ValueRef::from_value(p_value))
|
||||
if p_value.is_null() {
|
||||
Err(Error::InvalidColumnIndex(col))
|
||||
} else {
|
||||
Ok(ValueRef::from_value(p_value))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -581,8 +590,8 @@ impl Connection {
|
||||
/// Apply a changeset to a database
|
||||
pub fn apply<F, C>(&self, cs: &Changeset, filter: Option<F>, conflict: C) -> Result<()>
|
||||
where
|
||||
F: Fn(&str) -> bool + Send + RefUnwindSafe + 'static,
|
||||
C: Fn(ConflictType, ChangesetItem) -> ConflictAction + Send + RefUnwindSafe + 'static,
|
||||
F: Fn(&str) -> bool + Send + 'static,
|
||||
C: Fn(ConflictType, ChangesetItem) -> ConflictAction + Send + 'static,
|
||||
{
|
||||
let db = self.db.borrow_mut().db;
|
||||
|
||||
@ -619,8 +628,8 @@ impl Connection {
|
||||
conflict: C,
|
||||
) -> Result<()>
|
||||
where
|
||||
F: Fn(&str) -> bool + Send + RefUnwindSafe + 'static,
|
||||
C: Fn(ConflictType, ChangesetItem) -> ConflictAction + Send + RefUnwindSafe + 'static,
|
||||
F: Fn(&str) -> bool + Send + 'static,
|
||||
C: Fn(ConflictType, ChangesetItem) -> ConflictAction + Send + 'static,
|
||||
{
|
||||
let input_ref = &input;
|
||||
let db = self.db.borrow_mut().db;
|
||||
@ -694,22 +703,21 @@ pub enum ConflictAction {
|
||||
|
||||
unsafe extern "C" fn call_filter<F, C>(p_ctx: *mut c_void, tbl_str: *const c_char) -> c_int
|
||||
where
|
||||
F: Fn(&str) -> bool + Send + RefUnwindSafe + 'static,
|
||||
C: Fn(ConflictType, ChangesetItem) -> ConflictAction + Send + RefUnwindSafe + 'static,
|
||||
F: Fn(&str) -> bool + Send + 'static,
|
||||
C: Fn(ConflictType, ChangesetItem) -> ConflictAction + Send + 'static,
|
||||
{
|
||||
use std::str;
|
||||
|
||||
let tuple: *mut (Option<F>, C) = p_ctx as *mut (Option<F>, C);
|
||||
let tbl_name = {
|
||||
let c_slice = CStr::from_ptr(tbl_str).to_bytes();
|
||||
str::from_utf8(c_slice)
|
||||
};
|
||||
match *tuple {
|
||||
(Some(ref filter), _) => c_int::from(
|
||||
catch_unwind(|| filter(tbl_name.expect("illegal table name"))).unwrap_or_default(),
|
||||
),
|
||||
_ => unimplemented!(),
|
||||
}
|
||||
let tbl_name = CStr::from_ptr(tbl_str).to_str();
|
||||
c_int::from(
|
||||
catch_unwind(|| {
|
||||
let tuple: *mut (Option<F>, C) = p_ctx.cast::<(Option<F>, C)>();
|
||||
if let Some(ref filter) = (*tuple).0 {
|
||||
filter(tbl_name.expect("illegal table name"))
|
||||
} else {
|
||||
true
|
||||
}
|
||||
})
|
||||
.unwrap_or_default(),
|
||||
)
|
||||
}
|
||||
|
||||
unsafe extern "C" fn call_conflict<F, C>(
|
||||
@ -718,13 +726,15 @@ unsafe extern "C" fn call_conflict<F, C>(
|
||||
p: *mut ffi::sqlite3_changeset_iter,
|
||||
) -> c_int
|
||||
where
|
||||
F: Fn(&str) -> bool + Send + RefUnwindSafe + 'static,
|
||||
C: Fn(ConflictType, ChangesetItem) -> ConflictAction + Send + RefUnwindSafe + 'static,
|
||||
F: Fn(&str) -> bool + Send + 'static,
|
||||
C: Fn(ConflictType, ChangesetItem) -> ConflictAction + Send + 'static,
|
||||
{
|
||||
let tuple: *mut (Option<F>, C) = p_ctx as *mut (Option<F>, C);
|
||||
let conflict_type = ConflictType::from(e_conflict);
|
||||
let item = ChangesetItem { it: p };
|
||||
if let Ok(action) = catch_unwind(|| (*tuple).1(conflict_type, item)) {
|
||||
if let Ok(action) = catch_unwind(|| {
|
||||
let tuple: *mut (Option<F>, C) = p_ctx.cast::<(Option<F>, C)>();
|
||||
(*tuple).1(conflict_type, item)
|
||||
}) {
|
||||
action as c_int
|
||||
} else {
|
||||
ffi::SQLITE_CHANGESET_ABORT
|
||||
@ -771,7 +781,7 @@ mod test {
|
||||
use crate::hooks::Action;
|
||||
use crate::{Connection, Result};
|
||||
|
||||
fn one_changeset() -> Result<Changeset> {
|
||||
fn one_changeset_insert() -> Result<Changeset> {
|
||||
let db = Connection::open_in_memory()?;
|
||||
db.execute_batch("CREATE TABLE foo(t TEXT PRIMARY KEY NOT NULL);")?;
|
||||
|
||||
@ -784,6 +794,20 @@ mod test {
|
||||
session.changeset()
|
||||
}
|
||||
|
||||
fn one_changeset_update() -> Result<Changeset> {
|
||||
let db = Connection::open_in_memory()?;
|
||||
db.execute_batch(
|
||||
"CREATE TABLE foo(t TEXT PRIMARY KEY NOT NULL, i INTEGER NOT NULL DEFAULT 0);",
|
||||
)?;
|
||||
db.execute_batch("INSERT INTO foo (t) VALUES ('bar');")?;
|
||||
|
||||
let mut session = Session::new(&db)?;
|
||||
session.attach(None)?;
|
||||
db.execute("UPDATE foo SET i=100 WHERE t='bar';", [])?;
|
||||
|
||||
session.changeset()
|
||||
}
|
||||
|
||||
fn one_changeset_strm() -> Result<Vec<u8>> {
|
||||
let db = Connection::open_in_memory()?;
|
||||
db.execute_batch("CREATE TABLE foo(t TEXT PRIMARY KEY NOT NULL);")?;
|
||||
@ -801,7 +825,7 @@ mod test {
|
||||
|
||||
#[test]
|
||||
fn test_changeset() -> Result<()> {
|
||||
let changeset = one_changeset()?;
|
||||
let changeset = one_changeset_insert()?;
|
||||
let mut iter = changeset.iter()?;
|
||||
let item = iter.next()?;
|
||||
assert!(item.is_some());
|
||||
@ -834,9 +858,22 @@ mod test {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_changeset_values() -> Result<()> {
|
||||
let changeset = one_changeset_update()?;
|
||||
let mut iter = changeset.iter()?;
|
||||
let item = iter.next()?.unwrap();
|
||||
|
||||
let new_value = item.new_value(0); // unchanged
|
||||
assert_eq!(Err(crate::Error::InvalidColumnIndex(0)), new_value);
|
||||
let new_value = item.new_value(1)?; // updated
|
||||
assert_eq!(Ok(100), new_value.as_i64());
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_changeset_apply() -> Result<()> {
|
||||
let changeset = one_changeset()?;
|
||||
let changeset = one_changeset_insert()?;
|
||||
|
||||
let db = Connection::open_in_memory()?;
|
||||
db.execute_batch("CREATE TABLE foo(t TEXT PRIMARY KEY NOT NULL);")?;
|
||||
|
@ -441,7 +441,8 @@ impl Statement<'_> {
|
||||
#[inline]
|
||||
pub fn parameter_name(&self, index: usize) -> Option<&'_ str> {
|
||||
self.stmt.bind_parameter_name(index as i32).map(|name| {
|
||||
str::from_utf8(name.to_bytes()).expect("Invalid UTF-8 sequence in parameter name")
|
||||
name.to_str()
|
||||
.expect("Invalid UTF-8 sequence in parameter name")
|
||||
})
|
||||
}
|
||||
|
||||
@ -560,7 +561,7 @@ impl Statement<'_> {
|
||||
///
|
||||
/// Any unbound parameters will have `NULL` as their value.
|
||||
///
|
||||
/// This should not generally be used outside of special cases, and
|
||||
/// This should not generally be used outside special cases, and
|
||||
/// functions in the [`Statement::execute`] family should be preferred.
|
||||
///
|
||||
/// # Failure
|
||||
@ -579,7 +580,7 @@ impl Statement<'_> {
|
||||
///
|
||||
/// Any unbound parameters will have `NULL` as their value.
|
||||
///
|
||||
/// This should not generally be used outside of special cases, and
|
||||
/// This should not generally be used outside special cases, and
|
||||
/// functions in the [`Statement::query`] family should be preferred.
|
||||
///
|
||||
/// Note that if the SQL does not return results, [`Statement::raw_execute`]
|
||||
@ -766,7 +767,7 @@ impl fmt::Debug for Statement<'_> {
|
||||
let sql = if self.stmt.is_null() {
|
||||
Ok("")
|
||||
} else {
|
||||
str::from_utf8(self.stmt.sql().unwrap().to_bytes())
|
||||
self.stmt.sql().unwrap().to_str()
|
||||
};
|
||||
f.debug_struct("Statement")
|
||||
.field("conn", self.conn)
|
||||
@ -875,23 +876,23 @@ impl Statement<'_> {
|
||||
#[derive(Clone, Copy, PartialEq, Eq)]
|
||||
#[non_exhaustive]
|
||||
pub enum StatementStatus {
|
||||
/// Equivalent to SQLITE_STMTSTATUS_FULLSCAN_STEP
|
||||
/// Equivalent to `SQLITE_STMTSTATUS_FULLSCAN_STEP`
|
||||
FullscanStep = 1,
|
||||
/// Equivalent to SQLITE_STMTSTATUS_SORT
|
||||
/// Equivalent to `SQLITE_STMTSTATUS_SORT`
|
||||
Sort = 2,
|
||||
/// Equivalent to SQLITE_STMTSTATUS_AUTOINDEX
|
||||
/// Equivalent to `SQLITE_STMTSTATUS_AUTOINDEX`
|
||||
AutoIndex = 3,
|
||||
/// Equivalent to SQLITE_STMTSTATUS_VM_STEP
|
||||
/// Equivalent to `SQLITE_STMTSTATUS_VM_STEP`
|
||||
VmStep = 4,
|
||||
/// Equivalent to SQLITE_STMTSTATUS_REPREPARE (3.20.0)
|
||||
/// Equivalent to `SQLITE_STMTSTATUS_REPREPARE` (3.20.0)
|
||||
RePrepare = 5,
|
||||
/// Equivalent to SQLITE_STMTSTATUS_RUN (3.20.0)
|
||||
/// Equivalent to `SQLITE_STMTSTATUS_RUN` (3.20.0)
|
||||
Run = 6,
|
||||
/// Equivalent to SQLITE_STMTSTATUS_FILTER_MISS
|
||||
/// Equivalent to `SQLITE_STMTSTATUS_FILTER_MISS`
|
||||
FilterMiss = 7,
|
||||
/// Equivalent to SQLITE_STMTSTATUS_FILTER_HIT
|
||||
/// Equivalent to `SQLITE_STMTSTATUS_FILTER_HIT`
|
||||
FilterHit = 8,
|
||||
/// Equivalent to SQLITE_STMTSTATUS_MEMUSED (3.20.0)
|
||||
/// Equivalent to `SQLITE_STMTSTATUS_MEMUSED` (3.20.0)
|
||||
MemUsed = 99,
|
||||
}
|
||||
|
||||
@ -1018,7 +1019,7 @@ mod test {
|
||||
let doubled_id: i32 = rows.next().unwrap()?;
|
||||
assert_eq!(1, doubled_id);
|
||||
|
||||
// second row should be Err
|
||||
// second row should be an `Err`
|
||||
#[allow(clippy::match_wild_err_arm)]
|
||||
match rows.next().unwrap() {
|
||||
Ok(_) => panic!("invalid Ok"),
|
||||
|
22
src/trace.rs
22
src/trace.rs
@ -27,10 +27,9 @@ use crate::Connection;
|
||||
#[cfg(not(feature = "loadable_extension"))]
|
||||
pub unsafe fn config_log(callback: Option<fn(c_int, &str)>) -> crate::Result<()> {
|
||||
extern "C" fn log_callback(p_arg: *mut c_void, err: c_int, msg: *const c_char) {
|
||||
let c_slice = unsafe { CStr::from_ptr(msg).to_bytes() };
|
||||
let s = unsafe { CStr::from_ptr(msg).to_string_lossy() };
|
||||
let callback: fn(c_int, &str) = unsafe { mem::transmute(p_arg) };
|
||||
|
||||
let s = String::from_utf8_lossy(c_slice);
|
||||
drop(catch_unwind(|| callback(err, &s)));
|
||||
}
|
||||
|
||||
@ -72,8 +71,7 @@ impl Connection {
|
||||
pub fn trace(&mut self, trace_fn: Option<fn(&str)>) {
|
||||
unsafe extern "C" fn trace_callback(p_arg: *mut c_void, z_sql: *const c_char) {
|
||||
let trace_fn: fn(&str) = mem::transmute(p_arg);
|
||||
let c_slice = CStr::from_ptr(z_sql).to_bytes();
|
||||
let s = String::from_utf8_lossy(c_slice);
|
||||
let s = CStr::from_ptr(z_sql).to_string_lossy();
|
||||
drop(catch_unwind(|| trace_fn(&s)));
|
||||
}
|
||||
|
||||
@ -100,8 +98,7 @@ impl Connection {
|
||||
nanoseconds: u64,
|
||||
) {
|
||||
let profile_fn: fn(&str, Duration) = mem::transmute(p_arg);
|
||||
let c_slice = CStr::from_ptr(z_sql).to_bytes();
|
||||
let s = String::from_utf8_lossy(c_slice);
|
||||
let s = CStr::from_ptr(z_sql).to_string_lossy();
|
||||
const NANOS_PER_SEC: u64 = 1_000_000_000;
|
||||
|
||||
let duration = Duration::new(
|
||||
@ -125,17 +122,15 @@ impl Connection {
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use lazy_static::lazy_static;
|
||||
use std::sync::Mutex;
|
||||
use std::sync::{LazyLock, Mutex};
|
||||
use std::time::Duration;
|
||||
|
||||
use crate::{Connection, Result};
|
||||
|
||||
#[test]
|
||||
fn test_trace() -> Result<()> {
|
||||
lazy_static! {
|
||||
static ref TRACED_STMTS: Mutex<Vec<String>> = Mutex::new(Vec::new());
|
||||
}
|
||||
static TRACED_STMTS: LazyLock<Mutex<Vec<String>>> =
|
||||
LazyLock::new(|| Mutex::new(Vec::new()));
|
||||
fn tracer(s: &str) {
|
||||
let mut traced_stmts = TRACED_STMTS.lock().unwrap();
|
||||
traced_stmts.push(s.to_owned());
|
||||
@ -162,9 +157,8 @@ mod test {
|
||||
|
||||
#[test]
|
||||
fn test_profile() -> Result<()> {
|
||||
lazy_static! {
|
||||
static ref PROFILED: Mutex<Vec<(String, Duration)>> = Mutex::new(Vec::new());
|
||||
}
|
||||
static PROFILED: LazyLock<Mutex<Vec<(String, Duration)>>> =
|
||||
LazyLock::new(|| Mutex::new(Vec::new()));
|
||||
fn profiler(s: &str, d: Duration) {
|
||||
let mut profiled = PROFILED.lock().unwrap();
|
||||
profiled.push((s.to_owned(), d));
|
||||
|
@ -100,7 +100,7 @@ impl Transaction<'_> {
|
||||
/// transactions.
|
||||
///
|
||||
/// Even though we don't mutate the connection, we take a `&mut Connection`
|
||||
/// so as to prevent nested transactions on the same connection. For cases
|
||||
/// to prevent nested transactions on the same connection. For cases
|
||||
/// where this is unacceptable, [`Transaction::new_unchecked`] is available.
|
||||
#[inline]
|
||||
pub fn new(conn: &mut Connection, behavior: TransactionBehavior) -> Result<Transaction<'_>> {
|
||||
@ -377,11 +377,11 @@ impl Drop for Savepoint<'_> {
|
||||
#[cfg(feature = "modern_sqlite")] // 3.37.0
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "modern_sqlite")))]
|
||||
pub enum TransactionState {
|
||||
/// Equivalent to SQLITE_TXN_NONE
|
||||
/// Equivalent to `SQLITE_TXN_NONE`
|
||||
None,
|
||||
/// Equivalent to SQLITE_TXN_READ
|
||||
/// Equivalent to `SQLITE_TXN_READ`
|
||||
Read,
|
||||
/// Equivalent to SQLITE_TXN_WRITE
|
||||
/// Equivalent to `SQLITE_TXN_WRITE`
|
||||
Write,
|
||||
}
|
||||
|
||||
@ -414,7 +414,7 @@ impl Connection {
|
||||
/// Will return `Err` if the underlying SQLite call fails.
|
||||
#[inline]
|
||||
pub fn transaction(&mut self) -> Result<Transaction<'_>> {
|
||||
Transaction::new(self, TransactionBehavior::Deferred)
|
||||
Transaction::new(self, self.transaction_behavior)
|
||||
}
|
||||
|
||||
/// Begin a new transaction with a specified behavior.
|
||||
@ -464,7 +464,7 @@ impl Connection {
|
||||
/// Will return `Err` if the underlying SQLite call fails. The specific
|
||||
/// error returned if transactions are nested is currently unspecified.
|
||||
pub fn unchecked_transaction(&self) -> Result<Transaction<'_>> {
|
||||
Transaction::new_unchecked(self, TransactionBehavior::Deferred)
|
||||
Transaction::new_unchecked(self, self.transaction_behavior)
|
||||
}
|
||||
|
||||
/// Begin a new savepoint with the default behavior (DEFERRED).
|
||||
@ -518,6 +518,34 @@ impl Connection {
|
||||
) -> Result<TransactionState> {
|
||||
self.db.borrow().txn_state(db_name)
|
||||
}
|
||||
|
||||
/// Set the default transaction behavior for the connection.
|
||||
///
|
||||
/// ## Note
|
||||
///
|
||||
/// This will only apply to transactions initiated by [`transaction`](Connection::transaction)
|
||||
/// or [`unchecked_transaction`](Connection::unchecked_transaction).
|
||||
///
|
||||
/// ## Example
|
||||
///
|
||||
/// ```rust,no_run
|
||||
/// # use rusqlite::{Connection, Result, TransactionBehavior};
|
||||
/// # fn do_queries_part_1(_conn: &Connection) -> Result<()> { Ok(()) }
|
||||
/// # fn do_queries_part_2(_conn: &Connection) -> Result<()> { Ok(()) }
|
||||
/// fn perform_queries(conn: &mut Connection) -> Result<()> {
|
||||
/// conn.set_transaction_behavior(TransactionBehavior::Immediate);
|
||||
///
|
||||
/// let tx = conn.transaction()?;
|
||||
///
|
||||
/// do_queries_part_1(&tx)?; // tx causes rollback if this fails
|
||||
/// do_queries_part_2(&tx)?; // tx causes rollback if this fails
|
||||
///
|
||||
/// tx.commit()
|
||||
/// }
|
||||
/// ```
|
||||
pub fn set_transaction_behavior(&mut self, behavior: TransactionBehavior) {
|
||||
self.transaction_behavior = behavior;
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
@ -624,12 +652,12 @@ mod test {
|
||||
let mut sp1 = tx.savepoint()?;
|
||||
sp1.execute_batch("INSERT INTO foo VALUES(2)")?;
|
||||
assert_current_sum(3, &sp1)?;
|
||||
// will rollback sp1
|
||||
// will roll back sp1
|
||||
{
|
||||
let mut sp2 = sp1.savepoint()?;
|
||||
sp2.execute_batch("INSERT INTO foo VALUES(4)")?;
|
||||
assert_current_sum(7, &sp2)?;
|
||||
// will rollback sp2
|
||||
// will roll back sp2
|
||||
{
|
||||
let sp3 = sp2.savepoint()?;
|
||||
sp3.execute_batch("INSERT INTO foo VALUES(8)")?;
|
||||
@ -775,4 +803,27 @@ mod test {
|
||||
db.execute_batch("ROLLBACK")?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(feature = "modern_sqlite")]
|
||||
fn auto_commit() -> Result<()> {
|
||||
use super::TransactionState;
|
||||
let db = Connection::open_in_memory()?;
|
||||
db.execute_batch("CREATE TABLE t(i UNIQUE);")?;
|
||||
assert!(db.is_autocommit());
|
||||
let mut stmt = db.prepare("SELECT name FROM sqlite_master")?;
|
||||
assert_eq!(TransactionState::None, db.transaction_state(None)?);
|
||||
{
|
||||
let mut rows = stmt.query([])?;
|
||||
assert!(rows.next()?.is_some()); // start reading
|
||||
assert_eq!(TransactionState::Read, db.transaction_state(None)?);
|
||||
db.execute("INSERT INTO t VALUES (1)", [])?; // auto-commit
|
||||
assert_eq!(TransactionState::Read, db.transaction_state(None)?);
|
||||
assert!(rows.next()?.is_some()); // still reading
|
||||
assert_eq!(TransactionState::Read, db.transaction_state(None)?);
|
||||
assert!(rows.next()?.is_none()); // end
|
||||
assert_eq!(TransactionState::None, db.transaction_state(None)?);
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
@ -20,7 +20,7 @@ impl FromSql for NaiveDate {
|
||||
fn column_result(value: ValueRef<'_>) -> FromSqlResult<Self> {
|
||||
value
|
||||
.as_str()
|
||||
.and_then(|s| match NaiveDate::parse_from_str(s, "%F") {
|
||||
.and_then(|s| match Self::parse_from_str(s, "%F") {
|
||||
Ok(dt) => Ok(dt),
|
||||
Err(err) => Err(FromSqlError::Other(Box::new(err))),
|
||||
})
|
||||
@ -45,7 +45,7 @@ impl FromSql for NaiveTime {
|
||||
8 => "%T",
|
||||
_ => "%T%.f",
|
||||
};
|
||||
match NaiveTime::parse_from_str(s, fmt) {
|
||||
match Self::parse_from_str(s, fmt) {
|
||||
Ok(dt) => Ok(dt),
|
||||
Err(err) => Err(FromSqlError::Other(Box::new(err))),
|
||||
}
|
||||
@ -75,7 +75,7 @@ impl FromSql for NaiveDateTime {
|
||||
"%F %T%.f"
|
||||
};
|
||||
|
||||
match NaiveDateTime::parse_from_str(s, fmt) {
|
||||
match Self::parse_from_str(s, fmt) {
|
||||
Ok(dt) => Ok(dt),
|
||||
Err(err) => Err(FromSqlError::Other(Box::new(err))),
|
||||
}
|
||||
|
@ -28,16 +28,16 @@ pub enum FromSqlError {
|
||||
}
|
||||
|
||||
impl PartialEq for FromSqlError {
|
||||
fn eq(&self, other: &FromSqlError) -> bool {
|
||||
fn eq(&self, other: &Self) -> bool {
|
||||
match (self, other) {
|
||||
(FromSqlError::InvalidType, FromSqlError::InvalidType) => true,
|
||||
(FromSqlError::OutOfRange(n1), FromSqlError::OutOfRange(n2)) => n1 == n2,
|
||||
(Self::InvalidType, Self::InvalidType) => true,
|
||||
(Self::OutOfRange(n1), Self::OutOfRange(n2)) => n1 == n2,
|
||||
(
|
||||
FromSqlError::InvalidBlobSize {
|
||||
Self::InvalidBlobSize {
|
||||
expected_size: es1,
|
||||
blob_size: bs1,
|
||||
},
|
||||
FromSqlError::InvalidBlobSize {
|
||||
Self::InvalidBlobSize {
|
||||
expected_size: es2,
|
||||
blob_size: bs2,
|
||||
},
|
||||
@ -50,9 +50,9 @@ impl PartialEq for FromSqlError {
|
||||
impl fmt::Display for FromSqlError {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
match *self {
|
||||
FromSqlError::InvalidType => write!(f, "Invalid type"),
|
||||
FromSqlError::OutOfRange(i) => write!(f, "Value {i} out of range"),
|
||||
FromSqlError::InvalidBlobSize {
|
||||
Self::InvalidType => write!(f, "Invalid type"),
|
||||
Self::OutOfRange(i) => write!(f, "Value {i} out of range"),
|
||||
Self::InvalidBlobSize {
|
||||
expected_size,
|
||||
blob_size,
|
||||
} => {
|
||||
@ -61,14 +61,14 @@ impl fmt::Display for FromSqlError {
|
||||
"Cannot read {expected_size} byte value out of {blob_size} byte blob"
|
||||
)
|
||||
}
|
||||
FromSqlError::Other(ref err) => err.fmt(f),
|
||||
Self::Other(ref err) => err.fmt(f),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Error for FromSqlError {
|
||||
fn source(&self) -> Option<&(dyn Error + 'static)> {
|
||||
if let FromSqlError::Other(ref err) = self {
|
||||
if let Self::Other(ref err) = self {
|
||||
Some(&**err)
|
||||
} else {
|
||||
None
|
||||
@ -144,8 +144,8 @@ impl FromSql for f32 {
|
||||
#[inline]
|
||||
fn column_result(value: ValueRef<'_>) -> FromSqlResult<Self> {
|
||||
match value {
|
||||
ValueRef::Integer(i) => Ok(i as f32),
|
||||
ValueRef::Real(f) => Ok(f as f32),
|
||||
ValueRef::Integer(i) => Ok(i as Self),
|
||||
ValueRef::Real(f) => Ok(f as Self),
|
||||
_ => Err(FromSqlError::InvalidType),
|
||||
}
|
||||
}
|
||||
@ -155,7 +155,7 @@ impl FromSql for f64 {
|
||||
#[inline]
|
||||
fn column_result(value: ValueRef<'_>) -> FromSqlResult<Self> {
|
||||
match value {
|
||||
ValueRef::Integer(i) => Ok(i as f64),
|
||||
ValueRef::Integer(i) => Ok(i as Self),
|
||||
ValueRef::Real(f) => Ok(f),
|
||||
_ => Err(FromSqlError::InvalidType),
|
||||
}
|
||||
@ -221,7 +221,7 @@ impl FromSql for i128 {
|
||||
#[inline]
|
||||
fn column_result(value: ValueRef<'_>) -> FromSqlResult<Self> {
|
||||
let bytes = <[u8; 16]>::column_result(value)?;
|
||||
Ok(i128::from_be_bytes(bytes) ^ (1_i128 << 127))
|
||||
Ok(Self::from_be_bytes(bytes) ^ (1_i128 << 127))
|
||||
}
|
||||
}
|
||||
|
||||
@ -231,7 +231,7 @@ impl FromSql for uuid::Uuid {
|
||||
#[inline]
|
||||
fn column_result(value: ValueRef<'_>) -> FromSqlResult<Self> {
|
||||
let bytes = <[u8; 16]>::column_result(value)?;
|
||||
Ok(uuid::Uuid::from_u128(u128::from_be_bytes(bytes)))
|
||||
Ok(Self::from_u128(u128::from_be_bytes(bytes)))
|
||||
}
|
||||
}
|
||||
|
||||
|
137
src/types/jiff.rs
Normal file
137
src/types/jiff.rs
Normal file
@ -0,0 +1,137 @@
|
||||
//! Convert some `jiff` types.
|
||||
|
||||
use jiff::civil::{Date, DateTime, Time};
|
||||
use std::str::FromStr;
|
||||
|
||||
use crate::types::{FromSql, FromSqlError, FromSqlResult, ToSql, ToSqlOutput, ValueRef};
|
||||
use crate::Result;
|
||||
|
||||
/// Gregorian calendar date => "YYYY-MM-DD"
|
||||
impl ToSql for Date {
|
||||
#[inline]
|
||||
fn to_sql(&self) -> Result<ToSqlOutput<'_>> {
|
||||
let s = self.to_string();
|
||||
Ok(ToSqlOutput::from(s))
|
||||
}
|
||||
}
|
||||
|
||||
/// "YYYY-MM-DD" => Gregorian calendar date.
|
||||
impl FromSql for Date {
|
||||
#[inline]
|
||||
fn column_result(value: ValueRef<'_>) -> FromSqlResult<Self> {
|
||||
value.as_str().and_then(|s| match Self::from_str(s) {
|
||||
Ok(d) => Ok(d),
|
||||
Err(err) => Err(FromSqlError::Other(Box::new(err))),
|
||||
})
|
||||
}
|
||||
}
|
||||
/// time => "HH:MM:SS.SSS"
|
||||
impl ToSql for Time {
|
||||
#[inline]
|
||||
fn to_sql(&self) -> Result<ToSqlOutput<'_>> {
|
||||
let date_str = self.to_string();
|
||||
Ok(ToSqlOutput::from(date_str))
|
||||
}
|
||||
}
|
||||
|
||||
/// "HH:MM:SS.SSS" => time.
|
||||
impl FromSql for Time {
|
||||
fn column_result(value: ValueRef<'_>) -> FromSqlResult<Self> {
|
||||
value.as_str().and_then(|s| match Self::from_str(s) {
|
||||
Ok(t) => Ok(t),
|
||||
Err(err) => Err(FromSqlError::Other(Box::new(err))),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
/// Gregorian datetime => "YYYY-MM-DDTHH:MM:SS.SSS"
|
||||
impl ToSql for DateTime {
|
||||
#[inline]
|
||||
fn to_sql(&self) -> Result<ToSqlOutput<'_>> {
|
||||
let s = self.to_string();
|
||||
Ok(ToSqlOutput::from(s))
|
||||
}
|
||||
}
|
||||
|
||||
/// "YYYY-MM-DDTHH:MM:SS.SSS" => Gregorian datetime.
|
||||
impl FromSql for DateTime {
|
||||
fn column_result(value: ValueRef<'_>) -> FromSqlResult<Self> {
|
||||
value.as_str().and_then(|s| match Self::from_str(s) {
|
||||
Ok(dt) => Ok(dt),
|
||||
Err(err) => Err(FromSqlError::Other(Box::new(err))),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use crate::{Connection, Result};
|
||||
use jiff::civil::{Date, DateTime, Time};
|
||||
|
||||
fn checked_memory_handle() -> Result<Connection> {
|
||||
let db = Connection::open_in_memory()?;
|
||||
db.execute_batch("CREATE TABLE foo (t TEXT, b BLOB)")?;
|
||||
Ok(db)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_date() -> Result<()> {
|
||||
let db = checked_memory_handle()?;
|
||||
let date = Date::constant(2016, 2, 23);
|
||||
db.execute("INSERT INTO foo (t) VALUES (?1)", [date])?;
|
||||
|
||||
let s: String = db.one_column("SELECT t FROM foo")?;
|
||||
assert_eq!("2016-02-23", s);
|
||||
let t: Date = db.one_column("SELECT t FROM foo")?;
|
||||
assert_eq!(date, t);
|
||||
|
||||
db.execute("UPDATE foo set b = date(t)", [])?;
|
||||
let t: Date = db.one_column("SELECT b FROM foo")?;
|
||||
assert_eq!(date, t);
|
||||
|
||||
let r: Result<Date> = db.one_column("SELECT '2023-02-29'");
|
||||
assert!(r.is_err());
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_time() -> Result<()> {
|
||||
let db = checked_memory_handle()?;
|
||||
let time = Time::constant(23, 56, 4, 0);
|
||||
db.execute("INSERT INTO foo (t) VALUES (?1)", [time])?;
|
||||
|
||||
let s: String = db.one_column("SELECT t FROM foo")?;
|
||||
assert_eq!("23:56:04", s);
|
||||
let v: Time = db.one_column("SELECT t FROM foo")?;
|
||||
assert_eq!(time, v);
|
||||
|
||||
db.execute("UPDATE foo set b = time(t)", [])?;
|
||||
let v: Time = db.one_column("SELECT b FROM foo")?;
|
||||
assert_eq!(time, v);
|
||||
|
||||
let r: Result<Time> = db.one_column("SELECT '25:22:45'");
|
||||
assert!(r.is_err());
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_date_time() -> Result<()> {
|
||||
let db = checked_memory_handle()?;
|
||||
let dt = DateTime::constant(2016, 2, 23, 23, 56, 4, 0);
|
||||
|
||||
db.execute("INSERT INTO foo (t) VALUES (?1)", [dt])?;
|
||||
|
||||
let s: String = db.one_column("SELECT t FROM foo")?;
|
||||
assert_eq!("2016-02-23T23:56:04", s);
|
||||
let v: DateTime = db.one_column("SELECT t FROM foo")?;
|
||||
assert_eq!(dt, v);
|
||||
|
||||
db.execute("UPDATE foo set b = datetime(t)", [])?;
|
||||
let v: DateTime = db.one_column("SELECT b FROM foo")?;
|
||||
assert_eq!(dt, v);
|
||||
|
||||
let r: Result<DateTime> = db.one_column("SELECT '2023-02-29T00:00:00'");
|
||||
assert!(r.is_err());
|
||||
Ok(())
|
||||
}
|
||||
}
|
@ -81,6 +81,9 @@ use std::fmt;
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "chrono")))]
|
||||
mod chrono;
|
||||
mod from_sql;
|
||||
#[cfg(feature = "jiff")]
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "jiff")))]
|
||||
mod jiff;
|
||||
#[cfg(feature = "serde_json")]
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "serde_json")))]
|
||||
mod serde_json;
|
||||
@ -128,11 +131,11 @@ pub enum Type {
|
||||
impl fmt::Display for Type {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
match *self {
|
||||
Type::Null => f.pad("Null"),
|
||||
Type::Integer => f.pad("Integer"),
|
||||
Type::Real => f.pad("Real"),
|
||||
Type::Text => f.pad("Text"),
|
||||
Type::Blob => f.pad("Blob"),
|
||||
Self::Null => f.pad("Null"),
|
||||
Self::Integer => f.pad("Integer"),
|
||||
Self::Real => f.pad("Real"),
|
||||
Self::Text => f.pad("Text"),
|
||||
Self::Blob => f.pad("Blob"),
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -385,9 +388,8 @@ mod test {
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[allow(clippy::float_cmp)]
|
||||
fn test_numeric_conversions() -> Result<()> {
|
||||
#![allow(clippy::float_cmp)]
|
||||
|
||||
// Test what happens when we store an f32 and retrieve an i32 etc.
|
||||
let db = Connection::open_in_memory()?;
|
||||
db.execute_batch("CREATE TABLE foo (x)")?;
|
||||
|
@ -18,9 +18,9 @@ impl ToSql for Value {
|
||||
#[inline]
|
||||
fn to_sql(&self) -> Result<ToSqlOutput<'_>> {
|
||||
match self {
|
||||
Value::Null => Ok(ToSqlOutput::Borrowed(ValueRef::Null)),
|
||||
Value::Number(n) if n.is_i64() => Ok(ToSqlOutput::from(n.as_i64().unwrap())),
|
||||
Value::Number(n) if n.is_f64() => Ok(ToSqlOutput::from(n.as_f64().unwrap())),
|
||||
Self::Null => Ok(ToSqlOutput::Borrowed(ValueRef::Null)),
|
||||
Self::Number(n) if n.is_i64() => Ok(ToSqlOutput::from(n.as_i64().unwrap())),
|
||||
Self::Number(n) if n.is_f64() => Ok(ToSqlOutput::from(n.as_f64().unwrap())),
|
||||
_ => serde_json::to_string(self)
|
||||
.map(ToSqlOutput::from)
|
||||
.map_err(|err| Error::ToSqlConversionFailure(err.into())),
|
||||
@ -47,14 +47,14 @@ impl FromSql for Value {
|
||||
match value {
|
||||
ValueRef::Text(s) => serde_json::from_slice(s), // KO for b"text"
|
||||
ValueRef::Blob(b) => serde_json::from_slice(b),
|
||||
ValueRef::Integer(i) => Ok(Value::Number(Number::from(i))),
|
||||
ValueRef::Integer(i) => Ok(Self::Number(Number::from(i))),
|
||||
ValueRef::Real(f) => {
|
||||
match Number::from_f64(f) {
|
||||
Some(n) => Ok(Value::Number(n)),
|
||||
Some(n) => Ok(Self::Number(n)),
|
||||
_ => return Err(FromSqlError::InvalidType), // FIXME
|
||||
}
|
||||
}
|
||||
ValueRef::Null => Ok(Value::Null),
|
||||
ValueRef::Null => Ok(Self::Null),
|
||||
}
|
||||
.map_err(|err| FromSqlError::Other(Box::new(err)))
|
||||
}
|
||||
|
@ -7,6 +7,7 @@
|
||||
//! - Format 2: "YYYY-MM-DD HH:MM"
|
||||
//! - Format 5: "YYYY-MM-DDTHH:MM"
|
||||
//! - Format 8: "HH:MM"
|
||||
//!
|
||||
//! without an explicit second value will assume 0 seconds.
|
||||
//! Time String that contain an optional timezone without an explicit date are unsupported.
|
||||
//! All other assumptions described in [Time Values](https://sqlite.org/lang_datefunc.html#time_values) section are unsupported.
|
||||
@ -50,7 +51,7 @@ const LEGACY_DATE_TIME_FORMAT: &[FormatItem<'_>] = format_description!(
|
||||
"[year]-[month]-[day] [hour]:[minute]:[second]:[subsecond] [offset_hour sign:mandatory]:[offset_minute]"
|
||||
);
|
||||
|
||||
/// OffsetDatetime => RFC3339 format ("YYYY-MM-DD HH:MM:SS.SSS[+-]HH:MM")
|
||||
/// `OffsetDatetime` => RFC3339 format ("YYYY-MM-DD HH:MM:SS.SSS[+-]HH:MM")
|
||||
impl ToSql for OffsetDateTime {
|
||||
#[inline]
|
||||
fn to_sql(&self) -> Result<ToSqlOutput<'_>> {
|
||||
@ -68,12 +69,12 @@ impl FromSql for OffsetDateTime {
|
||||
value.as_str().and_then(|s| {
|
||||
if let Some(b' ') = s.as_bytes().get(23) {
|
||||
// legacy
|
||||
return OffsetDateTime::parse(s, &LEGACY_DATE_TIME_FORMAT)
|
||||
return Self::parse(s, &LEGACY_DATE_TIME_FORMAT)
|
||||
.map_err(|err| FromSqlError::Other(Box::new(err)));
|
||||
}
|
||||
if s[8..].contains('+') || s[8..].contains('-') {
|
||||
// Formats 2-7 with timezone
|
||||
return OffsetDateTime::parse(s, &OFFSET_DATE_TIME_FORMAT)
|
||||
return Self::parse(s, &OFFSET_DATE_TIME_FORMAT)
|
||||
.map_err(|err| FromSqlError::Other(Box::new(err)));
|
||||
}
|
||||
// Formats 2-7 without timezone
|
||||
@ -100,7 +101,7 @@ impl FromSql for Date {
|
||||
#[inline]
|
||||
fn column_result(value: ValueRef<'_>) -> FromSqlResult<Self> {
|
||||
value.as_str().and_then(|s| {
|
||||
Date::parse(s, &DATE_FORMAT).map_err(|err| FromSqlError::Other(err.into()))
|
||||
Self::parse(s, &DATE_FORMAT).map_err(|err| FromSqlError::Other(err.into()))
|
||||
})
|
||||
}
|
||||
}
|
||||
@ -121,7 +122,7 @@ impl FromSql for Time {
|
||||
#[inline]
|
||||
fn column_result(value: ValueRef<'_>) -> FromSqlResult<Self> {
|
||||
value.as_str().and_then(|s| {
|
||||
Time::parse(s, &TIME_FORMAT).map_err(|err| FromSqlError::Other(err.into()))
|
||||
Self::parse(s, &TIME_FORMAT).map_err(|err| FromSqlError::Other(err.into()))
|
||||
})
|
||||
}
|
||||
}
|
||||
@ -148,7 +149,7 @@ impl FromSql for PrimitiveDateTime {
|
||||
#[inline]
|
||||
fn column_result(value: ValueRef<'_>) -> FromSqlResult<Self> {
|
||||
value.as_str().and_then(|s| {
|
||||
PrimitiveDateTime::parse(s, &PRIMITIVE_DATE_TIME_FORMAT)
|
||||
Self::parse(s, &PRIMITIVE_DATE_TIME_FORMAT)
|
||||
.map_err(|err| FromSqlError::Other(err.into()))
|
||||
})
|
||||
}
|
||||
|
@ -310,10 +310,24 @@ impl<T: ToSql> ToSql for Option<T> {
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use super::ToSql;
|
||||
use super::{ToSql, ToSqlOutput};
|
||||
use crate::{types::Value, types::ValueRef, Result};
|
||||
|
||||
fn is_to_sql<T: ToSql>() {}
|
||||
|
||||
#[test]
|
||||
fn to_sql() -> Result<()> {
|
||||
assert_eq!(
|
||||
ToSqlOutput::Borrowed(ValueRef::Null).to_sql()?,
|
||||
ToSqlOutput::Borrowed(ValueRef::Null)
|
||||
);
|
||||
assert_eq!(
|
||||
ToSqlOutput::Owned(Value::Null).to_sql()?,
|
||||
ToSqlOutput::Borrowed(ValueRef::Null)
|
||||
);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_integral_types() {
|
||||
is_to_sql::<i8>();
|
||||
|
@ -18,7 +18,7 @@ impl FromSql for Url {
|
||||
match value {
|
||||
ValueRef::Text(s) => {
|
||||
let s = std::str::from_utf8(s).map_err(|e| FromSqlError::Other(Box::new(e)))?;
|
||||
Url::parse(s).map_err(|e| FromSqlError::Other(Box::new(e)))
|
||||
Self::parse(s).map_err(|e| FromSqlError::Other(Box::new(e)))
|
||||
}
|
||||
_ => Err(FromSqlError::InvalidType),
|
||||
}
|
||||
|
@ -21,22 +21,22 @@ pub enum Value {
|
||||
|
||||
impl From<Null> for Value {
|
||||
#[inline]
|
||||
fn from(_: Null) -> Value {
|
||||
Value::Null
|
||||
fn from(_: Null) -> Self {
|
||||
Self::Null
|
||||
}
|
||||
}
|
||||
|
||||
impl From<bool> for Value {
|
||||
#[inline]
|
||||
fn from(i: bool) -> Value {
|
||||
Value::Integer(i as i64)
|
||||
fn from(i: bool) -> Self {
|
||||
Self::Integer(i as i64)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<isize> for Value {
|
||||
#[inline]
|
||||
fn from(i: isize) -> Value {
|
||||
Value::Integer(i as i64)
|
||||
fn from(i: isize) -> Self {
|
||||
Self::Integer(i as i64)
|
||||
}
|
||||
}
|
||||
|
||||
@ -44,10 +44,10 @@ impl From<isize> for Value {
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "i128_blob")))]
|
||||
impl From<i128> for Value {
|
||||
#[inline]
|
||||
fn from(i: i128) -> Value {
|
||||
fn from(i: i128) -> Self {
|
||||
// We store these biased (e.g. with the most significant bit flipped)
|
||||
// so that comparisons with negative numbers work properly.
|
||||
Value::Blob(i128::to_be_bytes(i ^ (1_i128 << 127)).to_vec())
|
||||
Self::Blob(i128::to_be_bytes(i ^ (1_i128 << 127)).to_vec())
|
||||
}
|
||||
}
|
||||
|
||||
@ -55,8 +55,8 @@ impl From<i128> for Value {
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "uuid")))]
|
||||
impl From<uuid::Uuid> for Value {
|
||||
#[inline]
|
||||
fn from(id: uuid::Uuid) -> Value {
|
||||
Value::Blob(id.as_bytes().to_vec())
|
||||
fn from(id: uuid::Uuid) -> Self {
|
||||
Self::Blob(id.as_bytes().to_vec())
|
||||
}
|
||||
}
|
||||
|
||||
@ -80,48 +80,48 @@ from_i64!(u32);
|
||||
|
||||
impl From<i64> for Value {
|
||||
#[inline]
|
||||
fn from(i: i64) -> Value {
|
||||
Value::Integer(i)
|
||||
fn from(i: i64) -> Self {
|
||||
Self::Integer(i)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<f32> for Value {
|
||||
#[inline]
|
||||
fn from(f: f32) -> Value {
|
||||
Value::Real(f.into())
|
||||
fn from(f: f32) -> Self {
|
||||
Self::Real(f.into())
|
||||
}
|
||||
}
|
||||
|
||||
impl From<f64> for Value {
|
||||
#[inline]
|
||||
fn from(f: f64) -> Value {
|
||||
Value::Real(f)
|
||||
fn from(f: f64) -> Self {
|
||||
Self::Real(f)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<String> for Value {
|
||||
#[inline]
|
||||
fn from(s: String) -> Value {
|
||||
Value::Text(s)
|
||||
fn from(s: String) -> Self {
|
||||
Self::Text(s)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Vec<u8>> for Value {
|
||||
#[inline]
|
||||
fn from(v: Vec<u8>) -> Value {
|
||||
Value::Blob(v)
|
||||
fn from(v: Vec<u8>) -> Self {
|
||||
Self::Blob(v)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> From<Option<T>> for Value
|
||||
where
|
||||
T: Into<Value>,
|
||||
T: Into<Self>,
|
||||
{
|
||||
#[inline]
|
||||
fn from(v: Option<T>) -> Value {
|
||||
fn from(v: Option<T>) -> Self {
|
||||
match v {
|
||||
Some(x) => x.into(),
|
||||
None => Value::Null,
|
||||
None => Self::Null,
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -132,11 +132,33 @@ impl Value {
|
||||
#[must_use]
|
||||
pub fn data_type(&self) -> Type {
|
||||
match *self {
|
||||
Value::Null => Type::Null,
|
||||
Value::Integer(_) => Type::Integer,
|
||||
Value::Real(_) => Type::Real,
|
||||
Value::Text(_) => Type::Text,
|
||||
Value::Blob(_) => Type::Blob,
|
||||
Self::Null => Type::Null,
|
||||
Self::Integer(_) => Type::Integer,
|
||||
Self::Real(_) => Type::Real,
|
||||
Self::Text(_) => Type::Text,
|
||||
Self::Blob(_) => Type::Blob,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use super::Value;
|
||||
use crate::types::Type;
|
||||
|
||||
#[test]
|
||||
fn from() {
|
||||
assert_eq!(Value::from(2f32), Value::Real(2f64));
|
||||
assert_eq!(Value::from(3.), Value::Real(3.));
|
||||
assert_eq!(Value::from(vec![0u8]), Value::Blob(vec![0u8]));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn data_type() {
|
||||
assert_eq!(Value::Null.data_type(), Type::Null);
|
||||
assert_eq!(Value::Integer(0).data_type(), Type::Integer);
|
||||
assert_eq!(Value::Real(0.).data_type(), Type::Real);
|
||||
assert_eq!(Value::Text(String::new()).data_type(), Type::Text);
|
||||
assert_eq!(Value::Blob(vec![]).data_type(), Type::Blob);
|
||||
}
|
||||
}
|
||||
|
@ -1,7 +1,7 @@
|
||||
use super::{Type, Value};
|
||||
use crate::types::{FromSqlError, FromSqlResult};
|
||||
|
||||
/// A non-owning [dynamic type value](http://sqlite.org/datatype3.html). Typically the
|
||||
/// A non-owning [dynamic type value](http://sqlite.org/datatype3.html). Typically, the
|
||||
/// memory backing this value is owned by SQLite.
|
||||
///
|
||||
/// See [`Value`](Value) for an owning dynamic type value.
|
||||
@ -47,7 +47,7 @@ impl<'a> ValueRef<'a> {
|
||||
|
||||
/// If `self` is case `Null` returns None.
|
||||
/// If `self` is case `Integer`, returns the integral value.
|
||||
/// Otherwise returns [`Err(Error::InvalidColumnType)`](crate::Error::InvalidColumnType).
|
||||
/// Otherwise, returns [`Err(Error::InvalidColumnType)`](crate::Error::InvalidColumnType).
|
||||
#[inline]
|
||||
pub fn as_i64_or_null(&self) -> FromSqlResult<Option<i64>> {
|
||||
match *self {
|
||||
@ -69,7 +69,7 @@ impl<'a> ValueRef<'a> {
|
||||
|
||||
/// If `self` is case `Null` returns None.
|
||||
/// If `self` is case `Real`, returns the floating point value.
|
||||
/// Otherwise returns [`Err(Error::InvalidColumnType)`](crate::Error::InvalidColumnType).
|
||||
/// Otherwise, returns [`Err(Error::InvalidColumnType)`](crate::Error::InvalidColumnType).
|
||||
#[inline]
|
||||
pub fn as_f64_or_null(&self) -> FromSqlResult<Option<f64>> {
|
||||
match *self {
|
||||
@ -93,7 +93,7 @@ impl<'a> ValueRef<'a> {
|
||||
|
||||
/// If `self` is case `Null` returns None.
|
||||
/// If `self` is case `Text`, returns the string value.
|
||||
/// Otherwise returns [`Err(Error::InvalidColumnType)`](crate::Error::InvalidColumnType).
|
||||
/// Otherwise, returns [`Err(Error::InvalidColumnType)`](crate::Error::InvalidColumnType).
|
||||
#[inline]
|
||||
pub fn as_str_or_null(&self) -> FromSqlResult<Option<&'a str>> {
|
||||
match *self {
|
||||
@ -117,7 +117,7 @@ impl<'a> ValueRef<'a> {
|
||||
|
||||
/// If `self` is case `Null` returns None.
|
||||
/// If `self` is case `Blob`, returns the byte slice.
|
||||
/// Otherwise returns [`Err(Error::InvalidColumnType)`](crate::Error::InvalidColumnType).
|
||||
/// Otherwise, returns [`Err(Error::InvalidColumnType)`](crate::Error::InvalidColumnType).
|
||||
#[inline]
|
||||
pub fn as_blob_or_null(&self) -> FromSqlResult<Option<&'a [u8]>> {
|
||||
match *self {
|
||||
@ -153,16 +153,16 @@ impl<'a> ValueRef<'a> {
|
||||
impl From<ValueRef<'_>> for Value {
|
||||
#[inline]
|
||||
#[track_caller]
|
||||
fn from(borrowed: ValueRef<'_>) -> Value {
|
||||
fn from(borrowed: ValueRef<'_>) -> Self {
|
||||
match borrowed {
|
||||
ValueRef::Null => Value::Null,
|
||||
ValueRef::Integer(i) => Value::Integer(i),
|
||||
ValueRef::Real(r) => Value::Real(r),
|
||||
ValueRef::Null => Self::Null,
|
||||
ValueRef::Integer(i) => Self::Integer(i),
|
||||
ValueRef::Real(r) => Self::Real(r),
|
||||
ValueRef::Text(s) => {
|
||||
let s = std::str::from_utf8(s).expect("invalid UTF-8");
|
||||
Value::Text(s.to_string())
|
||||
Self::Text(s.to_string())
|
||||
}
|
||||
ValueRef::Blob(b) => Value::Blob(b.to_vec()),
|
||||
ValueRef::Blob(b) => Self::Blob(b.to_vec()),
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -183,7 +183,7 @@ impl<'a> From<&'a [u8]> for ValueRef<'a> {
|
||||
|
||||
impl<'a> From<&'a Value> for ValueRef<'a> {
|
||||
#[inline]
|
||||
fn from(value: &'a Value) -> ValueRef<'a> {
|
||||
fn from(value: &'a Value) -> Self {
|
||||
match *value {
|
||||
Value::Null => ValueRef::Null,
|
||||
Value::Integer(i) => ValueRef::Integer(i),
|
||||
@ -196,10 +196,10 @@ impl<'a> From<&'a Value> for ValueRef<'a> {
|
||||
|
||||
impl<'a, T> From<Option<T>> for ValueRef<'a>
|
||||
where
|
||||
T: Into<ValueRef<'a>>,
|
||||
T: Into<Self>,
|
||||
{
|
||||
#[inline]
|
||||
fn from(s: Option<T>) -> ValueRef<'a> {
|
||||
fn from(s: Option<T>) -> Self {
|
||||
match s {
|
||||
Some(x) => x.into(),
|
||||
None => ValueRef::Null,
|
||||
@ -207,9 +207,14 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(any(feature = "functions", feature = "session", feature = "vtab"))]
|
||||
#[cfg(any(
|
||||
feature = "functions",
|
||||
feature = "session",
|
||||
feature = "vtab",
|
||||
feature = "preupdate_hook"
|
||||
))]
|
||||
impl<'a> ValueRef<'a> {
|
||||
pub(crate) unsafe fn from_value(value: *mut crate::ffi::sqlite3_value) -> ValueRef<'a> {
|
||||
pub(crate) unsafe fn from_value(value: *mut crate::ffi::sqlite3_value) -> Self {
|
||||
use crate::ffi;
|
||||
use std::slice::from_raw_parts;
|
||||
|
||||
@ -256,3 +261,75 @@ impl<'a> ValueRef<'a> {
|
||||
// TODO sqlite3_value_nochange // 3.22.0 & VTab xUpdate
|
||||
// TODO sqlite3_value_frombind // 3.28.0
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use super::ValueRef;
|
||||
use crate::types::FromSqlResult;
|
||||
|
||||
#[test]
|
||||
fn as_i64() -> FromSqlResult<()> {
|
||||
assert!(ValueRef::Real(1.0).as_i64().is_err());
|
||||
assert_eq!(ValueRef::Integer(1).as_i64(), Ok(1));
|
||||
Ok(())
|
||||
}
|
||||
#[test]
|
||||
fn as_i64_or_null() -> FromSqlResult<()> {
|
||||
assert_eq!(ValueRef::Null.as_i64_or_null(), Ok(None));
|
||||
assert!(ValueRef::Real(1.0).as_i64_or_null().is_err());
|
||||
assert_eq!(ValueRef::Integer(1).as_i64_or_null(), Ok(Some(1)));
|
||||
Ok(())
|
||||
}
|
||||
#[test]
|
||||
fn as_f64() -> FromSqlResult<()> {
|
||||
assert!(ValueRef::Integer(1).as_f64().is_err());
|
||||
assert_eq!(ValueRef::Real(1.0).as_f64(), Ok(1.0));
|
||||
Ok(())
|
||||
}
|
||||
#[test]
|
||||
fn as_f64_or_null() -> FromSqlResult<()> {
|
||||
assert_eq!(ValueRef::Null.as_f64_or_null(), Ok(None));
|
||||
assert!(ValueRef::Integer(1).as_f64_or_null().is_err());
|
||||
assert_eq!(ValueRef::Real(1.0).as_f64_or_null(), Ok(Some(1.0)));
|
||||
Ok(())
|
||||
}
|
||||
#[test]
|
||||
fn as_str() -> FromSqlResult<()> {
|
||||
assert!(ValueRef::Null.as_str().is_err());
|
||||
assert_eq!(ValueRef::Text(b"").as_str(), Ok(""));
|
||||
Ok(())
|
||||
}
|
||||
#[test]
|
||||
fn as_str_or_null() -> FromSqlResult<()> {
|
||||
assert_eq!(ValueRef::Null.as_str_or_null(), Ok(None));
|
||||
assert!(ValueRef::Integer(1).as_str_or_null().is_err());
|
||||
assert_eq!(ValueRef::Text(b"").as_str_or_null(), Ok(Some("")));
|
||||
Ok(())
|
||||
}
|
||||
#[test]
|
||||
fn as_blob() -> FromSqlResult<()> {
|
||||
assert!(ValueRef::Null.as_blob().is_err());
|
||||
assert_eq!(ValueRef::Blob(b"").as_blob(), Ok(&b""[..]));
|
||||
Ok(())
|
||||
}
|
||||
#[test]
|
||||
fn as_blob_or_null() -> FromSqlResult<()> {
|
||||
assert_eq!(ValueRef::Null.as_blob_or_null(), Ok(None));
|
||||
assert!(ValueRef::Integer(1).as_blob_or_null().is_err());
|
||||
assert_eq!(ValueRef::Blob(b"").as_blob_or_null(), Ok(Some(&b""[..])));
|
||||
Ok(())
|
||||
}
|
||||
#[test]
|
||||
fn as_bytes() -> FromSqlResult<()> {
|
||||
assert!(ValueRef::Null.as_bytes().is_err());
|
||||
assert_eq!(ValueRef::Blob(b"").as_bytes(), Ok(&b""[..]));
|
||||
Ok(())
|
||||
}
|
||||
#[test]
|
||||
fn as_bytes_or_null() -> FromSqlResult<()> {
|
||||
assert_eq!(ValueRef::Null.as_bytes_or_null(), Ok(None));
|
||||
assert!(ValueRef::Integer(1).as_bytes_or_null().is_err());
|
||||
assert_eq!(ValueRef::Blob(b"").as_bytes_or_null(), Ok(Some(&b""[..])));
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
@ -14,8 +14,8 @@ struct UnlockNotification {
|
||||
|
||||
#[allow(clippy::mutex_atomic)]
|
||||
impl UnlockNotification {
|
||||
fn new() -> UnlockNotification {
|
||||
UnlockNotification {
|
||||
fn new() -> Self {
|
||||
Self {
|
||||
cond: Condvar::new(),
|
||||
mutex: Mutex::new(false),
|
||||
}
|
||||
|
@ -103,7 +103,7 @@ impl SqliteMallocString {
|
||||
/// fails, we call `handle_alloc_error` which aborts the program after
|
||||
/// calling a global hook.
|
||||
///
|
||||
/// This means it's safe to use in extern "C" functions even outside of
|
||||
/// This means it's safe to use in extern "C" functions even outside
|
||||
/// `catch_unwind`.
|
||||
pub(crate) fn from_str(s: &str) -> Self {
|
||||
let s = if s.as_bytes().contains(&0) {
|
||||
|
@ -40,7 +40,7 @@ use crate::{Connection, Result};
|
||||
|
||||
// http://sqlite.org/bindptr.html
|
||||
|
||||
pub(crate) const ARRAY_TYPE: *const c_char = (b"rarray\0" as *const u8).cast::<c_char>();
|
||||
pub(crate) const ARRAY_TYPE: *const c_char = c"rarray".as_ptr();
|
||||
|
||||
pub(crate) unsafe extern "C" fn free_array(p: *mut c_void) {
|
||||
drop(Rc::from_raw(p as *const Vec<Value>));
|
||||
@ -81,8 +81,8 @@ unsafe impl<'vtab> VTab<'vtab> for ArrayTab {
|
||||
_: &mut VTabConnection,
|
||||
_aux: Option<&()>,
|
||||
_args: &[&[u8]],
|
||||
) -> Result<(String, ArrayTab)> {
|
||||
let vtab = ArrayTab {
|
||||
) -> Result<(String, Self)> {
|
||||
let vtab = Self {
|
||||
base: ffi::sqlite3_vtab::default(),
|
||||
};
|
||||
Ok(("CREATE TABLE x(value,pointer hidden)".to_owned(), vtab))
|
||||
|
@ -91,14 +91,14 @@ unsafe impl<'vtab> VTab<'vtab> for CsvTab {
|
||||
db: &mut VTabConnection,
|
||||
_aux: Option<&()>,
|
||||
args: &[&[u8]],
|
||||
) -> Result<(String, CsvTab)> {
|
||||
) -> Result<(String, Self)> {
|
||||
if args.len() < 4 {
|
||||
return Err(Error::ModuleError("no CSV file specified".to_owned()));
|
||||
}
|
||||
|
||||
let mut vtab = CsvTab {
|
||||
let mut vtab = Self {
|
||||
base: ffi::sqlite3_vtab::default(),
|
||||
filename: "".to_owned(),
|
||||
filename: String::new(),
|
||||
has_headers: false,
|
||||
delimiter: b',',
|
||||
quote: b'"',
|
||||
@ -115,7 +115,7 @@ unsafe impl<'vtab> VTab<'vtab> for CsvTab {
|
||||
if !Path::new(value).exists() {
|
||||
return Err(Error::ModuleError(format!("file '{value}' does not exist")));
|
||||
}
|
||||
vtab.filename = value.to_owned();
|
||||
value.clone_into(&mut vtab.filename);
|
||||
}
|
||||
"schema" => {
|
||||
schema = Some(value.to_owned());
|
||||
@ -148,7 +148,7 @@ unsafe impl<'vtab> VTab<'vtab> for CsvTab {
|
||||
}
|
||||
}
|
||||
"delimiter" => {
|
||||
if let Some(b) = CsvTab::parse_byte(value) {
|
||||
if let Some(b) = Self::parse_byte(value) {
|
||||
vtab.delimiter = b;
|
||||
} else {
|
||||
return Err(Error::ModuleError(format!(
|
||||
@ -157,7 +157,7 @@ unsafe impl<'vtab> VTab<'vtab> for CsvTab {
|
||||
}
|
||||
}
|
||||
"quote" => {
|
||||
if let Some(b) = CsvTab::parse_byte(value) {
|
||||
if let Some(b) = Self::parse_byte(value) {
|
||||
if b == b'0' {
|
||||
vtab.quote = 0;
|
||||
} else {
|
||||
@ -335,8 +335,8 @@ unsafe impl VTabCursor for CsvTabCursor<'_> {
|
||||
|
||||
impl From<csv::Error> for Error {
|
||||
#[cold]
|
||||
fn from(err: csv::Error) -> Error {
|
||||
Error::ModuleError(err.to_string())
|
||||
fn from(err: csv::Error) -> Self {
|
||||
Self::ModuleError(err.to_string())
|
||||
}
|
||||
}
|
||||
|
||||
@ -350,7 +350,9 @@ mod test {
|
||||
fn test_csv_module() -> Result<()> {
|
||||
let db = Connection::open_in_memory()?;
|
||||
csvtab::load_module(&db)?;
|
||||
db.execute_batch("CREATE VIRTUAL TABLE vtab USING csv(filename='test.csv', header=yes)")?;
|
||||
db.execute_batch(
|
||||
"CREATE VIRTUAL TABLE vtab USING csv(filename = 'test.csv', header = yes)",
|
||||
)?;
|
||||
|
||||
{
|
||||
let mut s = db.prepare("SELECT rowid, * FROM vtab")?;
|
||||
|
@ -3,10 +3,10 @@
|
||||
//! Follow these steps to create your own virtual table:
|
||||
//! 1. Write implementation of [`VTab`] and [`VTabCursor`] traits.
|
||||
//! 2. Create an instance of the [`Module`] structure specialized for [`VTab`]
|
||||
//! impl. from step 1.
|
||||
//! impl. from step 1.
|
||||
//! 3. Register your [`Module`] structure using [`Connection::create_module`].
|
||||
//! 4. Run a `CREATE VIRTUAL TABLE` command that specifies the new module in the
|
||||
//! `USING` clause.
|
||||
//! `USING` clause.
|
||||
//!
|
||||
//! (See [SQLite doc](http://sqlite.org/vtab.html))
|
||||
use std::borrow::Cow::{self, Borrowed, Owned};
|
||||
@ -137,7 +137,7 @@ macro_rules! module {
|
||||
};
|
||||
}
|
||||
|
||||
/// Create an modifiable virtual table implementation.
|
||||
/// Create a modifiable virtual table implementation.
|
||||
///
|
||||
/// Step 2 of [Creating New Virtual Table Implementations](https://sqlite.org/vtab.html#creating_new_virtual_table_implementations).
|
||||
#[must_use]
|
||||
@ -189,13 +189,13 @@ pub fn eponymous_only_module<'vtab, T: VTab<'vtab>>() -> &'static Module<'vtab,
|
||||
#[non_exhaustive]
|
||||
#[derive(Debug, Clone, Copy, Eq, PartialEq)]
|
||||
pub enum VTabConfig {
|
||||
/// Equivalent to SQLITE_VTAB_CONSTRAINT_SUPPORT
|
||||
/// Equivalent to `SQLITE_VTAB_CONSTRAINT_SUPPORT`
|
||||
ConstraintSupport = 1,
|
||||
/// Equivalent to SQLITE_VTAB_INNOCUOUS
|
||||
/// Equivalent to `SQLITE_VTAB_INNOCUOUS`
|
||||
Innocuous = 2,
|
||||
/// Equivalent to SQLITE_VTAB_DIRECTONLY
|
||||
/// Equivalent to `SQLITE_VTAB_DIRECTONLY`
|
||||
DirectOnly = 3,
|
||||
/// Equivalent to SQLITE_VTAB_USES_ALL_SCHEMAS
|
||||
/// Equivalent to `SQLITE_VTAB_USES_ALL_SCHEMAS`
|
||||
UsesAllSchemas = 4,
|
||||
}
|
||||
|
||||
@ -345,25 +345,25 @@ pub enum IndexConstraintOp {
|
||||
}
|
||||
|
||||
impl From<u8> for IndexConstraintOp {
|
||||
fn from(code: u8) -> IndexConstraintOp {
|
||||
fn from(code: u8) -> Self {
|
||||
match code {
|
||||
2 => IndexConstraintOp::SQLITE_INDEX_CONSTRAINT_EQ,
|
||||
4 => IndexConstraintOp::SQLITE_INDEX_CONSTRAINT_GT,
|
||||
8 => IndexConstraintOp::SQLITE_INDEX_CONSTRAINT_LE,
|
||||
16 => IndexConstraintOp::SQLITE_INDEX_CONSTRAINT_LT,
|
||||
32 => IndexConstraintOp::SQLITE_INDEX_CONSTRAINT_GE,
|
||||
64 => IndexConstraintOp::SQLITE_INDEX_CONSTRAINT_MATCH,
|
||||
65 => IndexConstraintOp::SQLITE_INDEX_CONSTRAINT_LIKE,
|
||||
66 => IndexConstraintOp::SQLITE_INDEX_CONSTRAINT_GLOB,
|
||||
67 => IndexConstraintOp::SQLITE_INDEX_CONSTRAINT_REGEXP,
|
||||
68 => IndexConstraintOp::SQLITE_INDEX_CONSTRAINT_NE,
|
||||
69 => IndexConstraintOp::SQLITE_INDEX_CONSTRAINT_ISNOT,
|
||||
70 => IndexConstraintOp::SQLITE_INDEX_CONSTRAINT_ISNOTNULL,
|
||||
71 => IndexConstraintOp::SQLITE_INDEX_CONSTRAINT_ISNULL,
|
||||
72 => IndexConstraintOp::SQLITE_INDEX_CONSTRAINT_IS,
|
||||
73 => IndexConstraintOp::SQLITE_INDEX_CONSTRAINT_LIMIT,
|
||||
74 => IndexConstraintOp::SQLITE_INDEX_CONSTRAINT_OFFSET,
|
||||
v => IndexConstraintOp::SQLITE_INDEX_CONSTRAINT_FUNCTION(v),
|
||||
2 => Self::SQLITE_INDEX_CONSTRAINT_EQ,
|
||||
4 => Self::SQLITE_INDEX_CONSTRAINT_GT,
|
||||
8 => Self::SQLITE_INDEX_CONSTRAINT_LE,
|
||||
16 => Self::SQLITE_INDEX_CONSTRAINT_LT,
|
||||
32 => Self::SQLITE_INDEX_CONSTRAINT_GE,
|
||||
64 => Self::SQLITE_INDEX_CONSTRAINT_MATCH,
|
||||
65 => Self::SQLITE_INDEX_CONSTRAINT_LIKE,
|
||||
66 => Self::SQLITE_INDEX_CONSTRAINT_GLOB,
|
||||
67 => Self::SQLITE_INDEX_CONSTRAINT_REGEXP,
|
||||
68 => Self::SQLITE_INDEX_CONSTRAINT_NE,
|
||||
69 => Self::SQLITE_INDEX_CONSTRAINT_ISNOT,
|
||||
70 => Self::SQLITE_INDEX_CONSTRAINT_ISNOTNULL,
|
||||
71 => Self::SQLITE_INDEX_CONSTRAINT_ISNULL,
|
||||
72 => Self::SQLITE_INDEX_CONSTRAINT_IS,
|
||||
73 => Self::SQLITE_INDEX_CONSTRAINT_LIMIT,
|
||||
74 => Self::SQLITE_INDEX_CONSTRAINT_OFFSET,
|
||||
v => Self::SQLITE_INDEX_CONSTRAINT_FUNCTION(v),
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -480,7 +480,7 @@ impl IndexInfo {
|
||||
}
|
||||
}
|
||||
|
||||
/// Mask of SQLITE_INDEX_SCAN_* flags.
|
||||
/// Mask of `SQLITE_INDEX_SCAN_*` flags.
|
||||
#[inline]
|
||||
pub fn set_idx_flags(&mut self, flags: IndexFlags) {
|
||||
unsafe { (*self.0).idxFlags = flags.bits() };
|
||||
@ -759,10 +759,9 @@ impl Values<'_> {
|
||||
None
|
||||
} else {
|
||||
Some(unsafe {
|
||||
let rc = array::Array::from_raw(ptr as *const Vec<Value>);
|
||||
let array = rc.clone();
|
||||
array::Array::into_raw(rc); // don't consume it
|
||||
array
|
||||
let ptr = ptr as *const Vec<Value>;
|
||||
array::Array::increment_strong_count(ptr); // don't consume it
|
||||
array::Array::from_raw(ptr)
|
||||
})
|
||||
}
|
||||
}
|
||||
@ -923,7 +922,7 @@ pub fn parameter(c_slice: &[u8]) -> Result<(&str, &str)> {
|
||||
if let Some(key) = split.next() {
|
||||
if let Some(value) = split.next() {
|
||||
let param = key.trim();
|
||||
let value = dequote(value);
|
||||
let value = dequote(value.trim());
|
||||
return Ok((param, value));
|
||||
}
|
||||
}
|
||||
@ -1081,12 +1080,12 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
unsafe extern "C" fn rust_open<'vtab, T: 'vtab>(
|
||||
unsafe extern "C" fn rust_open<'vtab, T>(
|
||||
vtab: *mut ffi::sqlite3_vtab,
|
||||
pp_cursor: *mut *mut ffi::sqlite3_vtab_cursor,
|
||||
) -> c_int
|
||||
where
|
||||
T: VTab<'vtab>,
|
||||
T: VTab<'vtab> + 'vtab,
|
||||
{
|
||||
let vt = vtab.cast::<T>();
|
||||
match (*vt).open() {
|
||||
@ -1187,14 +1186,14 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
unsafe extern "C" fn rust_update<'vtab, T: 'vtab>(
|
||||
unsafe extern "C" fn rust_update<'vtab, T>(
|
||||
vtab: *mut ffi::sqlite3_vtab,
|
||||
argc: c_int,
|
||||
argv: *mut *mut ffi::sqlite3_value,
|
||||
p_rowid: *mut ffi::sqlite3_int64,
|
||||
) -> c_int
|
||||
where
|
||||
T: UpdateVTab<'vtab>,
|
||||
T: UpdateVTab<'vtab> + 'vtab,
|
||||
{
|
||||
assert!(argc >= 1);
|
||||
let args = slice::from_raw_parts_mut(argv, argc as usize);
|
||||
|
@ -14,7 +14,7 @@ use crate::vtab::{
|
||||
};
|
||||
use crate::{Connection, Error, Result};
|
||||
|
||||
/// Register the "generate_series" module.
|
||||
/// Register the `generate_series` module.
|
||||
pub fn load_module(conn: &Connection) -> Result<()> {
|
||||
let aux: Option<()> = None;
|
||||
conn.create_module("generate_series", eponymous_only_module::<SeriesTab>(), aux)
|
||||
@ -60,8 +60,8 @@ unsafe impl<'vtab> VTab<'vtab> for SeriesTab {
|
||||
db: &mut VTabConnection,
|
||||
_aux: Option<&()>,
|
||||
_args: &[&[u8]],
|
||||
) -> Result<(String, SeriesTab)> {
|
||||
let vtab = SeriesTab {
|
||||
) -> Result<(String, Self)> {
|
||||
let vtab = Self {
|
||||
base: ffi::sqlite3_vtab::default(),
|
||||
};
|
||||
db.config(VTabConfig::Innocuous)?;
|
||||
|
@ -36,7 +36,7 @@ impl VTabLog {
|
||||
_: Option<&()>,
|
||||
args: &[&[u8]],
|
||||
is_create: bool,
|
||||
) -> Result<(String, VTabLog)> {
|
||||
) -> Result<(String, Self)> {
|
||||
static N_INST: AtomicUsize = AtomicUsize::new(1);
|
||||
let i_inst = N_INST.fetch_add(1, Ordering::SeqCst);
|
||||
println!(
|
||||
@ -80,7 +80,7 @@ impl VTabLog {
|
||||
if schema.is_none() {
|
||||
return Err(Error::ModuleError("no schema defined".to_owned()));
|
||||
}
|
||||
let vtab = VTabLog {
|
||||
let vtab = Self {
|
||||
base: ffi::sqlite3_vtab::default(),
|
||||
n_row: n_row.unwrap_or(10),
|
||||
i_inst,
|
||||
@ -105,7 +105,7 @@ unsafe impl<'vtab> VTab<'vtab> for VTabLog {
|
||||
aux: Option<&Self::Aux>,
|
||||
args: &[&[u8]],
|
||||
) -> Result<(String, Self)> {
|
||||
VTabLog::connect_create(db, aux, args, false)
|
||||
Self::connect_create(db, aux, args, false)
|
||||
}
|
||||
|
||||
fn best_index(&self, info: &mut IndexInfo) -> Result<()> {
|
||||
@ -138,7 +138,7 @@ impl<'vtab> CreateVTab<'vtab> for VTabLog {
|
||||
aux: Option<&Self::Aux>,
|
||||
args: &[&[u8]],
|
||||
) -> Result<(String, Self)> {
|
||||
VTabLog::connect_create(db, aux, args, true)
|
||||
Self::connect_create(db, aux, args, true)
|
||||
}
|
||||
|
||||
fn destroy(&self) -> Result<()> {
|
||||
|
41
tests/auto_ext.rs
Normal file
41
tests/auto_ext.rs
Normal file
@ -0,0 +1,41 @@
|
||||
#[cfg(all(feature = "bundled", not(feature = "loadable_extension")))]
|
||||
#[test]
|
||||
fn auto_ext() -> rusqlite::Result<()> {
|
||||
use rusqlite::auto_extension::*;
|
||||
use rusqlite::{ffi, Connection, Error, Result};
|
||||
use std::os::raw::{c_char, c_int};
|
||||
|
||||
fn test_ok(_: Connection) -> Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
unsafe extern "C" fn sqlite_test_ok(
|
||||
db: *mut ffi::sqlite3,
|
||||
pz_err_msg: *mut *mut c_char,
|
||||
_: *const ffi::sqlite3_api_routines,
|
||||
) -> c_int {
|
||||
init_auto_extension(db, pz_err_msg, test_ok)
|
||||
}
|
||||
fn test_err(_: Connection) -> Result<()> {
|
||||
Err(Error::SqliteFailure(
|
||||
ffi::Error::new(ffi::SQLITE_CORRUPT),
|
||||
Some("AutoExtErr".to_owned()),
|
||||
))
|
||||
}
|
||||
unsafe extern "C" fn sqlite_test_err(
|
||||
db: *mut ffi::sqlite3,
|
||||
pz_err_msg: *mut *mut c_char,
|
||||
_: *const ffi::sqlite3_api_routines,
|
||||
) -> c_int {
|
||||
init_auto_extension(db, pz_err_msg, test_err)
|
||||
}
|
||||
|
||||
//assert!(!cancel_auto_extension(sqlite_test_ok));
|
||||
unsafe { register_auto_extension(sqlite_test_ok)? };
|
||||
Connection::open_in_memory()?;
|
||||
assert!(cancel_auto_extension(sqlite_test_ok));
|
||||
assert!(!cancel_auto_extension(sqlite_test_ok));
|
||||
unsafe { register_auto_extension(sqlite_test_err)? };
|
||||
Connection::open_in_memory().unwrap_err();
|
||||
reset_auto_extension();
|
||||
Ok(())
|
||||
}
|
@ -4,13 +4,11 @@
|
||||
|
||||
#[cfg(feature = "trace")]
|
||||
fn main() {
|
||||
use lazy_static::lazy_static;
|
||||
use std::os::raw::c_int;
|
||||
use std::sync::Mutex;
|
||||
use std::sync::{LazyLock, Mutex};
|
||||
|
||||
lazy_static! {
|
||||
static ref LOGS_RECEIVED: Mutex<Vec<(c_int, String)>> = Mutex::new(Vec::new());
|
||||
}
|
||||
static LOGS_RECEIVED: LazyLock<Mutex<Vec<(c_int, String)>>> =
|
||||
LazyLock::new(|| Mutex::new(Vec::new()));
|
||||
|
||||
fn log_handler(err: c_int, message: &str) {
|
||||
let mut logs_received = LOGS_RECEIVED.lock().unwrap();
|
||||
|
@ -27,8 +27,8 @@ fn test_dummy_module() -> rusqlite::Result<()> {
|
||||
_: &mut VTabConnection,
|
||||
_aux: Option<&()>,
|
||||
_args: &[&[u8]],
|
||||
) -> Result<(String, DummyTab)> {
|
||||
let vtab = DummyTab {
|
||||
) -> Result<(String, Self)> {
|
||||
let vtab = Self {
|
||||
base: sqlite3_vtab::default(),
|
||||
};
|
||||
Ok(("CREATE TABLE x(value)".to_owned(), vtab))
|
||||
|
Loading…
x
Reference in New Issue
Block a user