mirror of
https://github.com/isar/rusqlite.git
synced 2024-11-25 02:21:37 +08:00
Merge branch 'master' into captured_identifiers
This commit is contained in:
commit
e8f73c93c4
2
.github/workflows/main.yml
vendored
2
.github/workflows/main.yml
vendored
@ -49,7 +49,7 @@ jobs:
|
|||||||
# The `{ sharedKey: ... }` allows different actions to share the cache.
|
# The `{ sharedKey: ... }` allows different actions to share the cache.
|
||||||
# We're using a `fullBuild` key mostly as a "this needs to do the
|
# 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
|
# 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'`), which is very
|
||||||
# slow, and has several deps.
|
# slow, and has several deps.
|
||||||
- uses: Swatinem/rust-cache@v2
|
- uses: Swatinem/rust-cache@v2
|
||||||
with: { sharedKey: fullBuild }
|
with: { sharedKey: fullBuild }
|
||||||
|
@ -3,10 +3,10 @@ name = "rusqlite"
|
|||||||
# Note: Update version in README.md when you change this.
|
# Note: Update version in README.md when you change this.
|
||||||
version = "0.29.0"
|
version = "0.29.0"
|
||||||
authors = ["The rusqlite developers"]
|
authors = ["The rusqlite developers"]
|
||||||
edition = "2018"
|
edition = "2021"
|
||||||
description = "Ergonomic wrapper for SQLite"
|
description = "Ergonomic wrapper for SQLite"
|
||||||
repository = "https://github.com/rusqlite/rusqlite"
|
repository = "https://github.com/rusqlite/rusqlite"
|
||||||
documentation = "http://docs.rs/rusqlite/"
|
documentation = "https://docs.rs/rusqlite/"
|
||||||
readme = "README.md"
|
readme = "README.md"
|
||||||
keywords = ["sqlite", "database", "ffi"]
|
keywords = ["sqlite", "database", "ffi"]
|
||||||
license = "MIT"
|
license = "MIT"
|
||||||
@ -77,6 +77,8 @@ column_decltype = []
|
|||||||
wasm32-wasi-vfs = ["libsqlite3-sys/wasm32-wasi-vfs"]
|
wasm32-wasi-vfs = ["libsqlite3-sys/wasm32-wasi-vfs"]
|
||||||
# Note: doesn't support 32-bit.
|
# Note: doesn't support 32-bit.
|
||||||
winsqlite3 = ["libsqlite3-sys/winsqlite3"]
|
winsqlite3 = ["libsqlite3-sys/winsqlite3"]
|
||||||
|
# 3.23.0
|
||||||
|
serialize = ["modern_sqlite"]
|
||||||
|
|
||||||
# Helper feature for enabling most non-build-related optional features
|
# Helper feature for enabling most non-build-related optional features
|
||||||
# or dependencies (except `session`). This is useful for running tests / clippy
|
# or dependencies (except `session`). This is useful for running tests / clippy
|
||||||
@ -118,7 +120,7 @@ chrono = { version = "0.4", optional = true, default-features = false, features
|
|||||||
serde_json = { version = "1.0", optional = true }
|
serde_json = { version = "1.0", optional = true }
|
||||||
csv = { version = "1.1", optional = true }
|
csv = { version = "1.1", optional = true }
|
||||||
url = { version = "2.1", optional = true }
|
url = { version = "2.1", optional = true }
|
||||||
fallible-iterator = "0.2"
|
fallible-iterator = "0.3"
|
||||||
fallible-streaming-iterator = "0.1"
|
fallible-streaming-iterator = "0.1"
|
||||||
uuid = { version = "1.0", optional = true }
|
uuid = { version = "1.0", optional = true }
|
||||||
smallvec = "1.6.1"
|
smallvec = "1.6.1"
|
||||||
|
14
Changelog.md
14
Changelog.md
@ -15,7 +15,7 @@ For version 0.15.0 and above, see [Releases](https://github.com/rusqlite/rusqlit
|
|||||||
* Add DropBehavior::Panic to enforce intentional commit or rollback.
|
* Add DropBehavior::Panic to enforce intentional commit or rollback.
|
||||||
* Implement `sqlite3_update_hook` (#260, #328), `sqlite3_commit_hook` and `sqlite3_rollback_hook`.
|
* Implement `sqlite3_update_hook` (#260, #328), `sqlite3_commit_hook` and `sqlite3_rollback_hook`.
|
||||||
* Add support to unlock notification behind `unlock_notify` feature (#294, #331).
|
* Add support to unlock notification behind `unlock_notify` feature (#294, #331).
|
||||||
* Make `Statement::column_index` case insensitive (#330).
|
* Make `Statement::column_index` case-insensitive (#330).
|
||||||
* Add comment to justify `&mut Connection` in `Transaction`.
|
* Add comment to justify `&mut Connection` in `Transaction`.
|
||||||
* Fix `tyvar_behind_raw_pointer` warnings.
|
* Fix `tyvar_behind_raw_pointer` warnings.
|
||||||
* Fix handful of clippy warnings.
|
* Fix handful of clippy warnings.
|
||||||
@ -29,7 +29,7 @@ For version 0.15.0 and above, see [Releases](https://github.com/rusqlite/rusqlit
|
|||||||
# Version 0.13.0 (2017-11-13)
|
# Version 0.13.0 (2017-11-13)
|
||||||
|
|
||||||
* Added ToSqlConversionFailure case to Error enum.
|
* Added ToSqlConversionFailure case to Error enum.
|
||||||
* Now depends on chrono 0.4, bitflats 1.0, and (optionally) cc 1.0 / bindgen 0.31.
|
* Now depends on chrono 0.4, bitflags 1.0, and (optionally) cc 1.0 / bindgen 0.31.
|
||||||
* The ToSql/FromSql implementations for time::Timespec now include
|
* The ToSql/FromSql implementations for time::Timespec now include
|
||||||
and expect fractional seconds and timezone in the serialized string.
|
and expect fractional seconds and timezone in the serialized string.
|
||||||
* The RowIndex type used in Row::get is now publicly exported.
|
* The RowIndex type used in Row::get is now publicly exported.
|
||||||
@ -61,18 +61,18 @@ For version 0.15.0 and above, see [Releases](https://github.com/rusqlite/rusqlit
|
|||||||
* Adds `version()` and `version_number()` functions for querying the version of SQLite in use.
|
* Adds `version()` and `version_number()` functions for querying the version of SQLite in use.
|
||||||
* Adds the `limits` feature, exposing `limit()` and `set_limit()` methods on `Connection`.
|
* Adds the `limits` feature, exposing `limit()` and `set_limit()` methods on `Connection`.
|
||||||
* Updates to `libsqlite3-sys` 0.7.0, which runs rust-bindgen at build-time instead of assuming the
|
* Updates to `libsqlite3-sys` 0.7.0, which runs rust-bindgen at build-time instead of assuming the
|
||||||
precense of all expected SQLite constants and functions.
|
presence of all expected SQLite constants and functions.
|
||||||
* Clarifies supported SQLite versions. Running with SQLite older than 3.6.8 now panics, and
|
* Clarifies supported SQLite versions. Running with SQLite older than 3.6.8 now panics, and
|
||||||
some features will not compile unless a sufficiently-recent SQLite version is used. See
|
some features will not compile unless a sufficiently-recent SQLite version is used. See
|
||||||
the README for requirements of particular features.
|
the README for requirements of particular features.
|
||||||
* When running with SQLite 3.6.x, rusqlite attempts to perform SQLite initialization. If it fails,
|
* When running with SQLite 3.6.x, rusqlite attempts to perform SQLite initialization. If it fails,
|
||||||
rusqlite will panic since it cannot ensure the threading mode for SQLite. This check can by
|
rusqlite will panic since it cannot ensure the threading mode for SQLite. This check can be
|
||||||
skipped by calling the unsafe function `rusqlite::bypass_sqlite_initialization()`. This is
|
skipped by calling the unsafe function `rusqlite::bypass_sqlite_initialization()`. This is
|
||||||
technically a breaking change but is unlikely to affect anyone in practice, since prior to this
|
technically a breaking change but is unlikely to affect anyone in practice, since prior to this
|
||||||
version the check that rusqlite was using would cause a segfault if linked against a SQLite
|
version the check that rusqlite was using would cause a segfault if linked against a SQLite
|
||||||
older than 3.7.0.
|
older than 3.7.0.
|
||||||
* rusqlite now performs a one-time check (prior to the first connection attempt) that the runtime
|
* rusqlite now performs a one-time check (prior to the first connection attempt) that the runtime
|
||||||
SQLite version is at least as new as the SQLite version found at buildtime. This check can by
|
SQLite version is at least as new as the SQLite version found at buildtime. This check can be
|
||||||
skipped by calling the unsafe function `rusqlite::bypass_sqlite_version_check()`.
|
skipped by calling the unsafe function `rusqlite::bypass_sqlite_version_check()`.
|
||||||
* Removes the `libc` dependency in favor of using `std::os::raw`
|
* Removes the `libc` dependency in favor of using `std::os::raw`
|
||||||
|
|
||||||
@ -137,7 +137,7 @@ For version 0.15.0 and above, see [Releases](https://github.com/rusqlite/rusqlit
|
|||||||
This behavior is more correct. Previously there were runtime checks to prevent misuse, but
|
This behavior is more correct. Previously there were runtime checks to prevent misuse, but
|
||||||
other changes in this release to reset statements as soon as possible introduced yet another
|
other changes in this release to reset statements as soon as possible introduced yet another
|
||||||
hazard related to the lack of these lifetime connections. We were already recommending the
|
hazard related to the lack of these lifetime connections. We were already recommending the
|
||||||
use of `query_map` and `query_and_then` over raw `query`; both of theose still return handles
|
use of `query_map` and `query_and_then` over raw `query`; both of those still return handles
|
||||||
that implement `Iterator`.
|
that implement `Iterator`.
|
||||||
* BREAKING CHANGE: `Transaction::savepoint()` now returns a `Savepoint` instead of another
|
* BREAKING CHANGE: `Transaction::savepoint()` now returns a `Savepoint` instead of another
|
||||||
`Transaction`. Unlike `Transaction`, `Savepoint`s can be rolled back while keeping the current
|
`Transaction`. Unlike `Transaction`, `Savepoint`s can be rolled back while keeping the current
|
||||||
@ -239,7 +239,7 @@ For version 0.15.0 and above, see [Releases](https://github.com/rusqlite/rusqlit
|
|||||||
|
|
||||||
* Add `column_names()` to `SqliteStatement`.
|
* Add `column_names()` to `SqliteStatement`.
|
||||||
* By default, include `SQLITE_OPEN_NO_MUTEX` and `SQLITE_OPEN_URI` flags when opening a
|
* By default, include `SQLITE_OPEN_NO_MUTEX` and `SQLITE_OPEN_URI` flags when opening a
|
||||||
new conneciton.
|
new connection.
|
||||||
* Fix generated bindings (e.g., `sqlite3_exec` was wrong).
|
* Fix generated bindings (e.g., `sqlite3_exec` was wrong).
|
||||||
* Use now-generated `sqlite3_destructor_type` to define `SQLITE_STATIC` and `SQLITE_TRANSIENT`.
|
* Use now-generated `sqlite3_destructor_type` to define `SQLITE_STATIC` and `SQLITE_TRANSIENT`.
|
||||||
|
|
||||||
|
@ -113,8 +113,8 @@ features](https://doc.rust-lang.org/cargo/reference/manifest.html#the-features-s
|
|||||||
and [`ToSql`](https://docs.rs/rusqlite/~0/rusqlite/types/trait.ToSql.html) for the
|
and [`ToSql`](https://docs.rs/rusqlite/~0/rusqlite/types/trait.ToSql.html) for the
|
||||||
`Value` type from the [`serde_json` crate](https://crates.io/crates/serde_json).
|
`Value` type from the [`serde_json` crate](https://crates.io/crates/serde_json).
|
||||||
* `time` implements [`FromSql`](https://docs.rs/rusqlite/~0/rusqlite/types/trait.FromSql.html)
|
* `time` implements [`FromSql`](https://docs.rs/rusqlite/~0/rusqlite/types/trait.FromSql.html)
|
||||||
and [`ToSql`](https://docs.rs/rusqlite/~0/rusqlite/types/trait.ToSql.html) for the
|
and [`ToSql`](https://docs.rs/rusqlite/~0/rusqlite/types/trait.ToSql.html) for various
|
||||||
`time::OffsetDateTime` type from the [`time` crate](https://crates.io/crates/time).
|
types from the [`time` crate](https://crates.io/crates/time).
|
||||||
* `url` implements [`FromSql`](https://docs.rs/rusqlite/~0/rusqlite/types/trait.FromSql.html)
|
* `url` implements [`FromSql`](https://docs.rs/rusqlite/~0/rusqlite/types/trait.FromSql.html)
|
||||||
and [`ToSql`](https://docs.rs/rusqlite/~0/rusqlite/types/trait.ToSql.html) for the
|
and [`ToSql`](https://docs.rs/rusqlite/~0/rusqlite/types/trait.ToSql.html) for the
|
||||||
`Url` type from the [`url` crate](https://crates.io/crates/url).
|
`Url` type from the [`url` crate](https://crates.io/crates/url).
|
||||||
|
@ -1,2 +1 @@
|
|||||||
doc-valid-idents = ["SQLite", "lang_transaction"]
|
doc-valid-idents = ["SQLite", "lang_transaction"]
|
||||||
msrv = "1.55.0"
|
|
||||||
|
@ -44,7 +44,7 @@ winsqlite3 = []
|
|||||||
openssl-sys = { version = "0.9", optional = true }
|
openssl-sys = { version = "0.9", optional = true }
|
||||||
|
|
||||||
[build-dependencies]
|
[build-dependencies]
|
||||||
bindgen = { version = "0.64", optional = true, default-features = false, features = ["runtime"] }
|
bindgen = { version = "0.66", optional = true, default-features = false, features = ["runtime"] }
|
||||||
pkg-config = { version = "0.3.19", optional = true }
|
pkg-config = { version = "0.3.19", optional = true }
|
||||||
cc = { version = "1.0", optional = true }
|
cc = { version = "1.0", optional = true }
|
||||||
vcpkg = { version = "0.2", optional = true }
|
vcpkg = { version = "0.2", optional = true }
|
||||||
|
@ -26,17 +26,26 @@ fn is_compiler(compiler_name: &str) -> bool {
|
|||||||
env::var("CARGO_CFG_TARGET_ENV").map_or(false, |v| v == compiler_name)
|
env::var("CARGO_CFG_TARGET_ENV").map_or(false, |v| v == compiler_name)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Copy bindgen file from `dir` to `out_path`.
|
||||||
|
fn copy_bindings<T: AsRef<Path>>(dir: &str, bindgen_name: &str, out_path: T) {
|
||||||
|
std::fs::copy(format!("{dir}/{bindgen_name}"), out_path)
|
||||||
|
.expect("Could not copy bindings to output directory");
|
||||||
|
}
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
let out_dir = env::var("OUT_DIR").unwrap();
|
let out_dir = env::var("OUT_DIR").unwrap();
|
||||||
let out_path = Path::new(&out_dir).join("bindgen.rs");
|
let out_path = Path::new(&out_dir).join("bindgen.rs");
|
||||||
if cfg!(feature = "in_gecko") {
|
if cfg!(feature = "in_gecko") {
|
||||||
// When inside mozilla-central, we are included into the build with
|
// When inside mozilla-central, we are included into the build with
|
||||||
// sqlite3.o directly, so we don't want to provide any linker arguments.
|
// sqlite3.o directly, so we don't want to provide any linker arguments.
|
||||||
std::fs::copy("sqlite3/bindgen_bundled_version.rs", out_path)
|
copy_bindings("sqlite3", "bindgen_bundled_version.rs", out_path);
|
||||||
.expect("Could not copy bindings to output directory");
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if cfg!(all(
|
|
||||||
|
println!("cargo:rerun-if-env-changed=LIBSQLITE3_SYS_USE_PKG_CONFIG");
|
||||||
|
if env::var_os("LIBSQLITE3_SYS_USE_PKG_CONFIG").map_or(false, |s| s != "0") {
|
||||||
|
build_linked::main(&out_dir, &out_path);
|
||||||
|
} else if cfg!(all(
|
||||||
feature = "sqlcipher",
|
feature = "sqlcipher",
|
||||||
not(feature = "bundled-sqlcipher")
|
not(feature = "bundled-sqlcipher")
|
||||||
)) {
|
)) {
|
||||||
@ -92,17 +101,13 @@ mod build_bundled {
|
|||||||
#[cfg(feature = "buildtime_bindgen")]
|
#[cfg(feature = "buildtime_bindgen")]
|
||||||
{
|
{
|
||||||
use super::{bindings, HeaderLocation};
|
use super::{bindings, HeaderLocation};
|
||||||
let header = HeaderLocation::FromPath(format!("{}/sqlite3.h", lib_name));
|
let header = HeaderLocation::FromPath(lib_name.to_owned());
|
||||||
bindings::write_to_out_dir(header, out_path);
|
bindings::write_to_out_dir(header, out_path);
|
||||||
}
|
}
|
||||||
#[cfg(not(feature = "buildtime_bindgen"))]
|
#[cfg(not(feature = "buildtime_bindgen"))]
|
||||||
{
|
{
|
||||||
use std::fs;
|
super::copy_bindings(lib_name, "bindgen_bundled_version.rs", out_path);
|
||||||
fs::copy(format!("{lib_name}/bindgen_bundled_version.rs"), out_path)
|
|
||||||
.expect("Could not copy bindings to output directory");
|
|
||||||
}
|
}
|
||||||
// println!("cargo:rerun-if-changed=sqlite3/sqlite3.c");
|
|
||||||
// println!("cargo:rerun-if-changed=sqlcipher/sqlite3.c");
|
|
||||||
println!("cargo:rerun-if-changed={lib_name}/sqlite3.c");
|
println!("cargo:rerun-if-changed={lib_name}/sqlite3.c");
|
||||||
println!("cargo:rerun-if-changed=sqlite3/wasm32-wasi-vfs.c");
|
println!("cargo:rerun-if-changed=sqlite3/wasm32-wasi-vfs.c");
|
||||||
let mut cfg = cc::Build::new();
|
let mut cfg = cc::Build::new();
|
||||||
@ -236,7 +241,7 @@ mod build_bundled {
|
|||||||
cfg.flag("-DHAVE_LOCALTIME_R");
|
cfg.flag("-DHAVE_LOCALTIME_R");
|
||||||
}
|
}
|
||||||
// Target wasm32-wasi can't compile the default VFS
|
// Target wasm32-wasi can't compile the default VFS
|
||||||
if is_compiler("wasm32-wasi") {
|
if env::var("TARGET").map_or(false, |v| v == "wasm32-wasi") {
|
||||||
cfg.flag("-DSQLITE_OS_OTHER")
|
cfg.flag("-DSQLITE_OS_OTHER")
|
||||||
// https://github.com/rust-lang/rust/issues/74393
|
// https://github.com/rust-lang/rust/issues/74393
|
||||||
.flag("-DLONGDOUBLE_TYPE=double");
|
.flag("-DLONGDOUBLE_TYPE=double");
|
||||||
@ -264,6 +269,11 @@ mod build_bundled {
|
|||||||
}
|
}
|
||||||
println!("cargo:rerun-if-env-changed=SQLITE_MAX_EXPR_DEPTH");
|
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}"));
|
||||||
|
}
|
||||||
|
println!("cargo:rerun-if-env-changed=SQLITE_MAX_COLUMN");
|
||||||
|
|
||||||
if let Ok(extras) = env::var("LIBSQLITE3_FLAGS") {
|
if let Ok(extras) = env::var("LIBSQLITE3_FLAGS") {
|
||||||
for extra in extras.split_whitespace() {
|
for extra in extras.split_whitespace() {
|
||||||
if extra.starts_with("-D") || extra.starts_with("-U") {
|
if extra.starts_with("-D") || extra.starts_with("-U") {
|
||||||
@ -338,7 +348,7 @@ impl From<HeaderLocation> for String {
|
|||||||
header
|
header
|
||||||
}
|
}
|
||||||
HeaderLocation::Wrapper => "wrapper.h".into(),
|
HeaderLocation::Wrapper => "wrapper.h".into(),
|
||||||
HeaderLocation::FromPath(path) => path,
|
HeaderLocation::FromPath(path) => format!("{}/sqlite3.h", path),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -365,11 +375,7 @@ mod build_linked {
|
|||||||
// on buildtime_bindgen instead, but this is still supported as we
|
// on buildtime_bindgen instead, but this is still supported as we
|
||||||
// have runtime version checks and there are good reasons to not
|
// have runtime version checks and there are good reasons to not
|
||||||
// want to run bindgen.
|
// want to run bindgen.
|
||||||
std::fs::copy(
|
super::copy_bindings(lib_name(), "bindgen_bundled_version.rs", out_path);
|
||||||
format!("{}/bindgen_bundled_version.rs", lib_name()),
|
|
||||||
out_path,
|
|
||||||
)
|
|
||||||
.expect("Could not copy bindings to output directory");
|
|
||||||
} else {
|
} else {
|
||||||
bindings::write_to_out_dir(header, out_path);
|
bindings::write_to_out_dir(header, out_path);
|
||||||
}
|
}
|
||||||
@ -427,8 +433,7 @@ mod build_linked {
|
|||||||
.print_system_libs(false)
|
.print_system_libs(false)
|
||||||
.probe(link_lib)
|
.probe(link_lib)
|
||||||
{
|
{
|
||||||
if let Some(mut header) = lib.include_paths.pop() {
|
if let Some(header) = lib.include_paths.pop() {
|
||||||
header.push("sqlite3.h");
|
|
||||||
HeaderLocation::FromPath(header.to_string_lossy().into())
|
HeaderLocation::FromPath(header.to_string_lossy().into())
|
||||||
} else {
|
} else {
|
||||||
HeaderLocation::Wrapper
|
HeaderLocation::Wrapper
|
||||||
@ -447,8 +452,7 @@ mod build_linked {
|
|||||||
if cfg!(feature = "vcpkg") && is_compiler("msvc") {
|
if cfg!(feature = "vcpkg") && is_compiler("msvc") {
|
||||||
// See if vcpkg can find it.
|
// See if vcpkg can find it.
|
||||||
if let Ok(mut lib) = vcpkg::Config::new().probe(lib_name()) {
|
if let Ok(mut lib) = vcpkg::Config::new().probe(lib_name()) {
|
||||||
if let Some(mut header) = lib.include_paths.pop() {
|
if let Some(header) = lib.include_paths.pop() {
|
||||||
header.push("sqlite3.h");
|
|
||||||
return Some(HeaderLocation::FromPath(header.to_string_lossy().into()));
|
return Some(HeaderLocation::FromPath(header.to_string_lossy().into()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -464,14 +468,13 @@ mod bindings {
|
|||||||
#![allow(dead_code)]
|
#![allow(dead_code)]
|
||||||
use super::HeaderLocation;
|
use super::HeaderLocation;
|
||||||
|
|
||||||
use std::fs;
|
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
|
|
||||||
static PREBUILT_BINDGEN_PATHS: &[&str] = &["bindgen-bindings/bindgen_3.14.0.rs"];
|
static PREBUILT_BINDGENS: &[&str] = &["bindgen_3.14.0.rs"];
|
||||||
|
|
||||||
pub fn write_to_out_dir(_header: HeaderLocation, out_path: &Path) {
|
pub fn write_to_out_dir(_header: HeaderLocation, out_path: &Path) {
|
||||||
let in_path = PREBUILT_BINDGEN_PATHS[PREBUILT_BINDGEN_PATHS.len() - 1];
|
let name = PREBUILT_BINDGENS[PREBUILT_BINDGENS.len() - 1];
|
||||||
fs::copy(in_path, out_path).expect("Could not copy bindings to output directory");
|
super::copy_bindings("bindgen-bindings", name, out_path);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -480,8 +483,6 @@ mod bindings {
|
|||||||
use super::HeaderLocation;
|
use super::HeaderLocation;
|
||||||
use bindgen::callbacks::{IntKind, ParseCallbacks};
|
use bindgen::callbacks::{IntKind, ParseCallbacks};
|
||||||
|
|
||||||
use std::fs::OpenOptions;
|
|
||||||
use std::io::Write;
|
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
|
|
||||||
use super::win_target;
|
use super::win_target;
|
||||||
@ -490,19 +491,16 @@ mod bindings {
|
|||||||
struct SqliteTypeChooser;
|
struct SqliteTypeChooser;
|
||||||
|
|
||||||
impl ParseCallbacks for SqliteTypeChooser {
|
impl ParseCallbacks for SqliteTypeChooser {
|
||||||
fn int_macro(&self, _name: &str, value: i64) -> Option<IntKind> {
|
fn int_macro(&self, name: &str, _value: i64) -> Option<IntKind> {
|
||||||
if value >= i32::MIN as i64 && value <= i32::MAX as i64 {
|
if name == "SQLITE_SERIALIZE_NOCOPY"
|
||||||
Some(IntKind::I32)
|
|| name.starts_with("SQLITE_DESERIALIZE_")
|
||||||
|
|| name.starts_with("SQLITE_PREPARE_")
|
||||||
|
{
|
||||||
|
Some(IntKind::UInt)
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn item_name(&self, original_item_name: &str) -> Option<String> {
|
|
||||||
original_item_name
|
|
||||||
.strip_prefix("sqlite3_index_info_")
|
|
||||||
.map(|s| s.to_owned())
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Are we generating the bundled bindings? Used to avoid emitting things
|
// Are we generating the bundled bindings? Used to avoid emitting things
|
||||||
@ -519,8 +517,9 @@ mod bindings {
|
|||||||
|
|
||||||
pub fn write_to_out_dir(header: HeaderLocation, out_path: &Path) {
|
pub fn write_to_out_dir(header: HeaderLocation, out_path: &Path) {
|
||||||
let header: String = header.into();
|
let header: String = header.into();
|
||||||
let mut output = Vec::new();
|
|
||||||
let mut bindings = bindgen::builder()
|
let mut bindings = bindgen::builder()
|
||||||
|
.default_macro_constant_type(bindgen::MacroTypeVariation::Signed)
|
||||||
|
.disable_nested_struct_naming()
|
||||||
.trust_clang_mangling(false)
|
.trust_clang_mangling(false)
|
||||||
.header(header.clone())
|
.header(header.clone())
|
||||||
.parse_callbacks(Box::new(SqliteTypeChooser))
|
.parse_callbacks(Box::new(SqliteTypeChooser))
|
||||||
@ -551,8 +550,7 @@ mod bindings {
|
|||||||
>,
|
>,
|
||||||
) -> ::std::os::raw::c_int;
|
) -> ::std::os::raw::c_int;
|
||||||
}"#,
|
}"#,
|
||||||
)
|
);
|
||||||
.rustfmt_bindings(true);
|
|
||||||
|
|
||||||
if cfg!(any(feature = "sqlcipher", feature = "bundled-sqlcipher")) {
|
if cfg!(any(feature = "sqlcipher", feature = "bundled-sqlcipher")) {
|
||||||
bindings = bindings.clang_arg("-DSQLITE_HAS_CODEC");
|
bindings = bindings.clang_arg("-DSQLITE_HAS_CODEC");
|
||||||
@ -620,38 +618,14 @@ mod bindings {
|
|||||||
.blocklist_function("sqlite3_vsnprintf")
|
.blocklist_function("sqlite3_vsnprintf")
|
||||||
.blocklist_function("sqlite3_str_vappendf")
|
.blocklist_function("sqlite3_str_vappendf")
|
||||||
.blocklist_type("va_list")
|
.blocklist_type("va_list")
|
||||||
.blocklist_type("__builtin_va_list")
|
.blocklist_item("__.*");
|
||||||
.blocklist_type("__gnuc_va_list")
|
|
||||||
.blocklist_type("__va_list_tag")
|
|
||||||
.blocklist_item("__GNUC_VA_LIST");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bindings
|
bindings
|
||||||
.layout_tests(false)
|
.layout_tests(false)
|
||||||
.generate()
|
.generate()
|
||||||
.unwrap_or_else(|_| panic!("could not run bindgen on header {}", header))
|
.unwrap_or_else(|_| panic!("could not run bindgen on header {}", header))
|
||||||
.write(Box::new(&mut output))
|
.write_to_file(out_path)
|
||||||
.expect("could not write output of bindgen");
|
|
||||||
let mut output = String::from_utf8(output).expect("bindgen output was not UTF-8?!");
|
|
||||||
|
|
||||||
// rusqlite's functions feature ors in the SQLITE_DETERMINISTIC flag when it
|
|
||||||
// can. This flag was added in SQLite 3.8.3, but oring it in in prior
|
|
||||||
// versions of SQLite is harmless. We don't want to not build just
|
|
||||||
// because this flag is missing (e.g., if we're linking against
|
|
||||||
// SQLite 3.7.x), so append the flag manually if it isn't present in bindgen's
|
|
||||||
// output.
|
|
||||||
if !output.contains("pub const SQLITE_DETERMINISTIC") {
|
|
||||||
output.push_str("\npub const SQLITE_DETERMINISTIC: i32 = 2048;\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
let mut file = OpenOptions::new()
|
|
||||||
.write(true)
|
|
||||||
.truncate(true)
|
|
||||||
.create(true)
|
|
||||||
.open(out_path)
|
|
||||||
.unwrap_or_else(|_| panic!("Could not write to {:?}", out_path));
|
|
||||||
|
|
||||||
file.write_all(output.as_bytes())
|
|
||||||
.unwrap_or_else(|_| panic!("Could not write to {:?}", out_path));
|
.unwrap_or_else(|_| panic!("Could not write to {:?}", out_path));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
781
libsqlite3-sys/sqlite3/bindgen_bundled_version.rs
vendored
781
libsqlite3-sys/sqlite3/bindgen_bundled_version.rs
vendored
@ -1,4 +1,4 @@
|
|||||||
/* automatically generated by rust-bindgen 0.64.0 */
|
/* automatically generated by rust-bindgen 0.66.0 */
|
||||||
|
|
||||||
extern "C" {
|
extern "C" {
|
||||||
pub fn sqlite3_auto_extension(
|
pub fn sqlite3_auto_extension(
|
||||||
@ -11,7 +11,6 @@ extern "C" {
|
|||||||
>,
|
>,
|
||||||
) -> ::std::os::raw::c_int;
|
) -> ::std::os::raw::c_int;
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C" {
|
extern "C" {
|
||||||
pub fn sqlite3_cancel_auto_extension(
|
pub fn sqlite3_cancel_auto_extension(
|
||||||
xEntryPoint: ::std::option::Option<
|
xEntryPoint: ::std::option::Option<
|
||||||
@ -24,10 +23,72 @@ extern "C" {
|
|||||||
) -> ::std::os::raw::c_int;
|
) -> ::std::os::raw::c_int;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub const SQLITE_VERSION: &[u8; 7usize] = b"3.41.2\0";
|
pub const SQLITE_VERSION: &[u8; 7] = b"3.42.0\0";
|
||||||
pub const SQLITE_VERSION_NUMBER: i32 = 3041002;
|
pub const SQLITE_VERSION_NUMBER: i32 = 3042000;
|
||||||
pub const SQLITE_SOURCE_ID: &[u8; 85usize] =
|
pub const SQLITE_SOURCE_ID: &[u8; 85] =
|
||||||
b"2023-03-22 11:56:21 0d1fc92f94cb6b76bffe3ec34d69cffde2924203304e8ffc4155597af0c191da\0";
|
b"2023-05-16 12:36:15 831d0fb2836b71c9bc51067c49fee4b8f18047814f2ff22d817d25195cf350b0\0";
|
||||||
|
extern "C" {
|
||||||
|
pub static sqlite3_version: [::std::os::raw::c_char; 0usize];
|
||||||
|
}
|
||||||
|
extern "C" {
|
||||||
|
pub fn sqlite3_libversion() -> *const ::std::os::raw::c_char;
|
||||||
|
}
|
||||||
|
extern "C" {
|
||||||
|
pub fn sqlite3_sourceid() -> *const ::std::os::raw::c_char;
|
||||||
|
}
|
||||||
|
extern "C" {
|
||||||
|
pub fn sqlite3_libversion_number() -> ::std::os::raw::c_int;
|
||||||
|
}
|
||||||
|
extern "C" {
|
||||||
|
pub fn sqlite3_compileoption_used(
|
||||||
|
zOptName: *const ::std::os::raw::c_char,
|
||||||
|
) -> ::std::os::raw::c_int;
|
||||||
|
}
|
||||||
|
extern "C" {
|
||||||
|
pub fn sqlite3_compileoption_get(N: ::std::os::raw::c_int) -> *const ::std::os::raw::c_char;
|
||||||
|
}
|
||||||
|
extern "C" {
|
||||||
|
pub fn sqlite3_threadsafe() -> ::std::os::raw::c_int;
|
||||||
|
}
|
||||||
|
#[repr(C)]
|
||||||
|
#[derive(Debug, Copy, Clone)]
|
||||||
|
pub struct sqlite3 {
|
||||||
|
_unused: [u8; 0],
|
||||||
|
}
|
||||||
|
pub type sqlite_int64 = ::std::os::raw::c_longlong;
|
||||||
|
pub type sqlite_uint64 = ::std::os::raw::c_ulonglong;
|
||||||
|
pub type sqlite3_int64 = sqlite_int64;
|
||||||
|
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,
|
||||||
|
arg2: ::std::os::raw::c_int,
|
||||||
|
arg3: *mut *mut ::std::os::raw::c_char,
|
||||||
|
arg4: *mut *mut ::std::os::raw::c_char,
|
||||||
|
) -> ::std::os::raw::c_int,
|
||||||
|
>;
|
||||||
|
extern "C" {
|
||||||
|
pub fn sqlite3_exec(
|
||||||
|
arg1: *mut sqlite3,
|
||||||
|
sql: *const ::std::os::raw::c_char,
|
||||||
|
callback: ::std::option::Option<
|
||||||
|
unsafe extern "C" fn(
|
||||||
|
arg1: *mut ::std::os::raw::c_void,
|
||||||
|
arg2: ::std::os::raw::c_int,
|
||||||
|
arg3: *mut *mut ::std::os::raw::c_char,
|
||||||
|
arg4: *mut *mut ::std::os::raw::c_char,
|
||||||
|
) -> ::std::os::raw::c_int,
|
||||||
|
>,
|
||||||
|
arg2: *mut ::std::os::raw::c_void,
|
||||||
|
errmsg: *mut *mut ::std::os::raw::c_char,
|
||||||
|
) -> ::std::os::raw::c_int;
|
||||||
|
}
|
||||||
pub const SQLITE_OK: i32 = 0;
|
pub const SQLITE_OK: i32 = 0;
|
||||||
pub const SQLITE_ERROR: i32 = 1;
|
pub const SQLITE_ERROR: i32 = 1;
|
||||||
pub const SQLITE_INTERNAL: i32 = 2;
|
pub const SQLITE_INTERNAL: i32 = 2;
|
||||||
@ -181,389 +242,6 @@ pub const SQLITE_LOCK_EXCLUSIVE: i32 = 4;
|
|||||||
pub const SQLITE_SYNC_NORMAL: i32 = 2;
|
pub const SQLITE_SYNC_NORMAL: i32 = 2;
|
||||||
pub const SQLITE_SYNC_FULL: i32 = 3;
|
pub const SQLITE_SYNC_FULL: i32 = 3;
|
||||||
pub const SQLITE_SYNC_DATAONLY: i32 = 16;
|
pub const SQLITE_SYNC_DATAONLY: i32 = 16;
|
||||||
pub const SQLITE_FCNTL_LOCKSTATE: i32 = 1;
|
|
||||||
pub const SQLITE_FCNTL_GET_LOCKPROXYFILE: i32 = 2;
|
|
||||||
pub const SQLITE_FCNTL_SET_LOCKPROXYFILE: i32 = 3;
|
|
||||||
pub const SQLITE_FCNTL_LAST_ERRNO: i32 = 4;
|
|
||||||
pub const SQLITE_FCNTL_SIZE_HINT: i32 = 5;
|
|
||||||
pub const SQLITE_FCNTL_CHUNK_SIZE: i32 = 6;
|
|
||||||
pub const SQLITE_FCNTL_FILE_POINTER: i32 = 7;
|
|
||||||
pub const SQLITE_FCNTL_SYNC_OMITTED: i32 = 8;
|
|
||||||
pub const SQLITE_FCNTL_WIN32_AV_RETRY: i32 = 9;
|
|
||||||
pub const SQLITE_FCNTL_PERSIST_WAL: i32 = 10;
|
|
||||||
pub const SQLITE_FCNTL_OVERWRITE: i32 = 11;
|
|
||||||
pub const SQLITE_FCNTL_VFSNAME: i32 = 12;
|
|
||||||
pub const SQLITE_FCNTL_POWERSAFE_OVERWRITE: i32 = 13;
|
|
||||||
pub const SQLITE_FCNTL_PRAGMA: i32 = 14;
|
|
||||||
pub const SQLITE_FCNTL_BUSYHANDLER: i32 = 15;
|
|
||||||
pub const SQLITE_FCNTL_TEMPFILENAME: i32 = 16;
|
|
||||||
pub const SQLITE_FCNTL_MMAP_SIZE: i32 = 18;
|
|
||||||
pub const SQLITE_FCNTL_TRACE: i32 = 19;
|
|
||||||
pub const SQLITE_FCNTL_HAS_MOVED: i32 = 20;
|
|
||||||
pub const SQLITE_FCNTL_SYNC: i32 = 21;
|
|
||||||
pub const SQLITE_FCNTL_COMMIT_PHASETWO: i32 = 22;
|
|
||||||
pub const SQLITE_FCNTL_WIN32_SET_HANDLE: i32 = 23;
|
|
||||||
pub const SQLITE_FCNTL_WAL_BLOCK: i32 = 24;
|
|
||||||
pub const SQLITE_FCNTL_ZIPVFS: i32 = 25;
|
|
||||||
pub const SQLITE_FCNTL_RBU: i32 = 26;
|
|
||||||
pub const SQLITE_FCNTL_VFS_POINTER: i32 = 27;
|
|
||||||
pub const SQLITE_FCNTL_JOURNAL_POINTER: i32 = 28;
|
|
||||||
pub const SQLITE_FCNTL_WIN32_GET_HANDLE: i32 = 29;
|
|
||||||
pub const SQLITE_FCNTL_PDB: i32 = 30;
|
|
||||||
pub const SQLITE_FCNTL_BEGIN_ATOMIC_WRITE: i32 = 31;
|
|
||||||
pub const SQLITE_FCNTL_COMMIT_ATOMIC_WRITE: i32 = 32;
|
|
||||||
pub const SQLITE_FCNTL_ROLLBACK_ATOMIC_WRITE: i32 = 33;
|
|
||||||
pub const SQLITE_FCNTL_LOCK_TIMEOUT: i32 = 34;
|
|
||||||
pub const SQLITE_FCNTL_DATA_VERSION: i32 = 35;
|
|
||||||
pub const SQLITE_FCNTL_SIZE_LIMIT: i32 = 36;
|
|
||||||
pub const SQLITE_FCNTL_CKPT_DONE: i32 = 37;
|
|
||||||
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;
|
|
||||||
pub const SQLITE_ACCESS_EXISTS: i32 = 0;
|
|
||||||
pub const SQLITE_ACCESS_READWRITE: i32 = 1;
|
|
||||||
pub const SQLITE_ACCESS_READ: i32 = 2;
|
|
||||||
pub const SQLITE_SHM_UNLOCK: i32 = 1;
|
|
||||||
pub const SQLITE_SHM_LOCK: i32 = 2;
|
|
||||||
pub const SQLITE_SHM_SHARED: i32 = 4;
|
|
||||||
pub const SQLITE_SHM_EXCLUSIVE: i32 = 8;
|
|
||||||
pub const SQLITE_SHM_NLOCK: i32 = 8;
|
|
||||||
pub const SQLITE_CONFIG_SINGLETHREAD: i32 = 1;
|
|
||||||
pub const SQLITE_CONFIG_MULTITHREAD: i32 = 2;
|
|
||||||
pub const SQLITE_CONFIG_SERIALIZED: i32 = 3;
|
|
||||||
pub const SQLITE_CONFIG_MALLOC: i32 = 4;
|
|
||||||
pub const SQLITE_CONFIG_GETMALLOC: i32 = 5;
|
|
||||||
pub const SQLITE_CONFIG_SCRATCH: i32 = 6;
|
|
||||||
pub const SQLITE_CONFIG_PAGECACHE: i32 = 7;
|
|
||||||
pub const SQLITE_CONFIG_HEAP: i32 = 8;
|
|
||||||
pub const SQLITE_CONFIG_MEMSTATUS: i32 = 9;
|
|
||||||
pub const SQLITE_CONFIG_MUTEX: i32 = 10;
|
|
||||||
pub const SQLITE_CONFIG_GETMUTEX: i32 = 11;
|
|
||||||
pub const SQLITE_CONFIG_LOOKASIDE: i32 = 13;
|
|
||||||
pub const SQLITE_CONFIG_PCACHE: i32 = 14;
|
|
||||||
pub const SQLITE_CONFIG_GETPCACHE: i32 = 15;
|
|
||||||
pub const SQLITE_CONFIG_LOG: i32 = 16;
|
|
||||||
pub const SQLITE_CONFIG_URI: i32 = 17;
|
|
||||||
pub const SQLITE_CONFIG_PCACHE2: i32 = 18;
|
|
||||||
pub const SQLITE_CONFIG_GETPCACHE2: i32 = 19;
|
|
||||||
pub const SQLITE_CONFIG_COVERING_INDEX_SCAN: i32 = 20;
|
|
||||||
pub const SQLITE_CONFIG_SQLLOG: i32 = 21;
|
|
||||||
pub const SQLITE_CONFIG_MMAP_SIZE: i32 = 22;
|
|
||||||
pub const SQLITE_CONFIG_WIN32_HEAPSIZE: i32 = 23;
|
|
||||||
pub const SQLITE_CONFIG_PCACHE_HDRSZ: i32 = 24;
|
|
||||||
pub const SQLITE_CONFIG_PMASZ: i32 = 25;
|
|
||||||
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_DBCONFIG_MAINDBNAME: i32 = 1000;
|
|
||||||
pub const SQLITE_DBCONFIG_LOOKASIDE: i32 = 1001;
|
|
||||||
pub const SQLITE_DBCONFIG_ENABLE_FKEY: i32 = 1002;
|
|
||||||
pub const SQLITE_DBCONFIG_ENABLE_TRIGGER: i32 = 1003;
|
|
||||||
pub const SQLITE_DBCONFIG_ENABLE_FTS3_TOKENIZER: i32 = 1004;
|
|
||||||
pub const SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION: i32 = 1005;
|
|
||||||
pub const SQLITE_DBCONFIG_NO_CKPT_ON_CLOSE: i32 = 1006;
|
|
||||||
pub const SQLITE_DBCONFIG_ENABLE_QPSG: i32 = 1007;
|
|
||||||
pub const SQLITE_DBCONFIG_TRIGGER_EQP: i32 = 1008;
|
|
||||||
pub const SQLITE_DBCONFIG_RESET_DATABASE: i32 = 1009;
|
|
||||||
pub const SQLITE_DBCONFIG_DEFENSIVE: i32 = 1010;
|
|
||||||
pub const SQLITE_DBCONFIG_WRITABLE_SCHEMA: i32 = 1011;
|
|
||||||
pub const SQLITE_DBCONFIG_LEGACY_ALTER_TABLE: i32 = 1012;
|
|
||||||
pub const SQLITE_DBCONFIG_DQS_DML: i32 = 1013;
|
|
||||||
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_DENY: i32 = 1;
|
|
||||||
pub const SQLITE_IGNORE: i32 = 2;
|
|
||||||
pub const SQLITE_CREATE_INDEX: i32 = 1;
|
|
||||||
pub const SQLITE_CREATE_TABLE: i32 = 2;
|
|
||||||
pub const SQLITE_CREATE_TEMP_INDEX: i32 = 3;
|
|
||||||
pub const SQLITE_CREATE_TEMP_TABLE: i32 = 4;
|
|
||||||
pub const SQLITE_CREATE_TEMP_TRIGGER: i32 = 5;
|
|
||||||
pub const SQLITE_CREATE_TEMP_VIEW: i32 = 6;
|
|
||||||
pub const SQLITE_CREATE_TRIGGER: i32 = 7;
|
|
||||||
pub const SQLITE_CREATE_VIEW: i32 = 8;
|
|
||||||
pub const SQLITE_DELETE: i32 = 9;
|
|
||||||
pub const SQLITE_DROP_INDEX: i32 = 10;
|
|
||||||
pub const SQLITE_DROP_TABLE: i32 = 11;
|
|
||||||
pub const SQLITE_DROP_TEMP_INDEX: i32 = 12;
|
|
||||||
pub const SQLITE_DROP_TEMP_TABLE: i32 = 13;
|
|
||||||
pub const SQLITE_DROP_TEMP_TRIGGER: i32 = 14;
|
|
||||||
pub const SQLITE_DROP_TEMP_VIEW: i32 = 15;
|
|
||||||
pub const SQLITE_DROP_TRIGGER: i32 = 16;
|
|
||||||
pub const SQLITE_DROP_VIEW: i32 = 17;
|
|
||||||
pub const SQLITE_INSERT: i32 = 18;
|
|
||||||
pub const SQLITE_PRAGMA: i32 = 19;
|
|
||||||
pub const SQLITE_READ: i32 = 20;
|
|
||||||
pub const SQLITE_SELECT: i32 = 21;
|
|
||||||
pub const SQLITE_TRANSACTION: i32 = 22;
|
|
||||||
pub const SQLITE_UPDATE: i32 = 23;
|
|
||||||
pub const SQLITE_ATTACH: i32 = 24;
|
|
||||||
pub const SQLITE_DETACH: i32 = 25;
|
|
||||||
pub const SQLITE_ALTER_TABLE: i32 = 26;
|
|
||||||
pub const SQLITE_REINDEX: i32 = 27;
|
|
||||||
pub const SQLITE_ANALYZE: i32 = 28;
|
|
||||||
pub const SQLITE_CREATE_VTABLE: i32 = 29;
|
|
||||||
pub const SQLITE_DROP_VTABLE: i32 = 30;
|
|
||||||
pub const SQLITE_FUNCTION: i32 = 31;
|
|
||||||
pub const SQLITE_SAVEPOINT: i32 = 32;
|
|
||||||
pub const SQLITE_COPY: i32 = 0;
|
|
||||||
pub const SQLITE_RECURSIVE: i32 = 33;
|
|
||||||
pub const SQLITE_TRACE_STMT: i32 = 1;
|
|
||||||
pub const SQLITE_TRACE_PROFILE: i32 = 2;
|
|
||||||
pub const SQLITE_TRACE_ROW: i32 = 4;
|
|
||||||
pub const SQLITE_TRACE_CLOSE: i32 = 8;
|
|
||||||
pub const SQLITE_LIMIT_LENGTH: i32 = 0;
|
|
||||||
pub const SQLITE_LIMIT_SQL_LENGTH: i32 = 1;
|
|
||||||
pub const SQLITE_LIMIT_COLUMN: i32 = 2;
|
|
||||||
pub const SQLITE_LIMIT_EXPR_DEPTH: i32 = 3;
|
|
||||||
pub const SQLITE_LIMIT_COMPOUND_SELECT: i32 = 4;
|
|
||||||
pub const SQLITE_LIMIT_VDBE_OP: i32 = 5;
|
|
||||||
pub const SQLITE_LIMIT_FUNCTION_ARG: i32 = 6;
|
|
||||||
pub const SQLITE_LIMIT_ATTACHED: i32 = 7;
|
|
||||||
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_INTEGER: i32 = 1;
|
|
||||||
pub const SQLITE_FLOAT: i32 = 2;
|
|
||||||
pub const SQLITE_BLOB: i32 = 4;
|
|
||||||
pub const SQLITE_NULL: i32 = 5;
|
|
||||||
pub const SQLITE_TEXT: i32 = 3;
|
|
||||||
pub const SQLITE3_TEXT: i32 = 3;
|
|
||||||
pub const SQLITE_UTF8: i32 = 1;
|
|
||||||
pub const SQLITE_UTF16LE: i32 = 2;
|
|
||||||
pub const SQLITE_UTF16BE: i32 = 3;
|
|
||||||
pub const SQLITE_UTF16: i32 = 4;
|
|
||||||
pub const SQLITE_ANY: i32 = 5;
|
|
||||||
pub const SQLITE_UTF16_ALIGNED: i32 = 8;
|
|
||||||
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_WIN32_DATA_DIRECTORY_TYPE: i32 = 1;
|
|
||||||
pub const SQLITE_WIN32_TEMP_DIRECTORY_TYPE: i32 = 2;
|
|
||||||
pub const SQLITE_TXN_NONE: i32 = 0;
|
|
||||||
pub const SQLITE_TXN_READ: i32 = 1;
|
|
||||||
pub const SQLITE_TXN_WRITE: i32 = 2;
|
|
||||||
pub const SQLITE_INDEX_SCAN_UNIQUE: i32 = 1;
|
|
||||||
pub const SQLITE_INDEX_CONSTRAINT_EQ: i32 = 2;
|
|
||||||
pub const SQLITE_INDEX_CONSTRAINT_GT: i32 = 4;
|
|
||||||
pub const SQLITE_INDEX_CONSTRAINT_LE: i32 = 8;
|
|
||||||
pub const SQLITE_INDEX_CONSTRAINT_LT: i32 = 16;
|
|
||||||
pub const SQLITE_INDEX_CONSTRAINT_GE: i32 = 32;
|
|
||||||
pub const SQLITE_INDEX_CONSTRAINT_MATCH: i32 = 64;
|
|
||||||
pub const SQLITE_INDEX_CONSTRAINT_LIKE: i32 = 65;
|
|
||||||
pub const SQLITE_INDEX_CONSTRAINT_GLOB: i32 = 66;
|
|
||||||
pub const SQLITE_INDEX_CONSTRAINT_REGEXP: i32 = 67;
|
|
||||||
pub const SQLITE_INDEX_CONSTRAINT_NE: i32 = 68;
|
|
||||||
pub const SQLITE_INDEX_CONSTRAINT_ISNOT: i32 = 69;
|
|
||||||
pub const SQLITE_INDEX_CONSTRAINT_ISNOTNULL: i32 = 70;
|
|
||||||
pub const SQLITE_INDEX_CONSTRAINT_ISNULL: i32 = 71;
|
|
||||||
pub const SQLITE_INDEX_CONSTRAINT_IS: i32 = 72;
|
|
||||||
pub const SQLITE_INDEX_CONSTRAINT_LIMIT: i32 = 73;
|
|
||||||
pub const SQLITE_INDEX_CONSTRAINT_OFFSET: i32 = 74;
|
|
||||||
pub const SQLITE_INDEX_CONSTRAINT_FUNCTION: i32 = 150;
|
|
||||||
pub const SQLITE_MUTEX_FAST: i32 = 0;
|
|
||||||
pub const SQLITE_MUTEX_RECURSIVE: i32 = 1;
|
|
||||||
pub const SQLITE_MUTEX_STATIC_MAIN: i32 = 2;
|
|
||||||
pub const SQLITE_MUTEX_STATIC_MEM: i32 = 3;
|
|
||||||
pub const SQLITE_MUTEX_STATIC_MEM2: i32 = 4;
|
|
||||||
pub const SQLITE_MUTEX_STATIC_OPEN: i32 = 4;
|
|
||||||
pub const SQLITE_MUTEX_STATIC_PRNG: i32 = 5;
|
|
||||||
pub const SQLITE_MUTEX_STATIC_LRU: i32 = 6;
|
|
||||||
pub const SQLITE_MUTEX_STATIC_LRU2: i32 = 7;
|
|
||||||
pub const SQLITE_MUTEX_STATIC_PMEM: i32 = 7;
|
|
||||||
pub const SQLITE_MUTEX_STATIC_APP1: i32 = 8;
|
|
||||||
pub const SQLITE_MUTEX_STATIC_APP2: i32 = 9;
|
|
||||||
pub const SQLITE_MUTEX_STATIC_APP3: i32 = 10;
|
|
||||||
pub const SQLITE_MUTEX_STATIC_VFS1: i32 = 11;
|
|
||||||
pub const SQLITE_MUTEX_STATIC_VFS2: i32 = 12;
|
|
||||||
pub const SQLITE_MUTEX_STATIC_VFS3: i32 = 13;
|
|
||||||
pub const SQLITE_MUTEX_STATIC_MASTER: i32 = 2;
|
|
||||||
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_BITVEC_TEST: i32 = 8;
|
|
||||||
pub const SQLITE_TESTCTRL_FAULT_INSTALL: i32 = 9;
|
|
||||||
pub const SQLITE_TESTCTRL_BENIGN_MALLOC_HOOKS: i32 = 10;
|
|
||||||
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_OPTIMIZATIONS: i32 = 15;
|
|
||||||
pub const SQLITE_TESTCTRL_ISKEYWORD: i32 = 16;
|
|
||||||
pub const SQLITE_TESTCTRL_SCRATCHMALLOC: i32 = 17;
|
|
||||||
pub const SQLITE_TESTCTRL_INTERNAL_FUNCTIONS: i32 = 17;
|
|
||||||
pub const SQLITE_TESTCTRL_LOCALTIME_FAULT: i32 = 18;
|
|
||||||
pub const SQLITE_TESTCTRL_EXPLAIN_STMT: i32 = 19;
|
|
||||||
pub const SQLITE_TESTCTRL_ONCE_RESET_THRESHOLD: i32 = 19;
|
|
||||||
pub const SQLITE_TESTCTRL_NEVER_CORRUPT: i32 = 20;
|
|
||||||
pub const SQLITE_TESTCTRL_VDBE_COVERAGE: i32 = 21;
|
|
||||||
pub const SQLITE_TESTCTRL_BYTEORDER: i32 = 22;
|
|
||||||
pub const SQLITE_TESTCTRL_ISINIT: i32 = 23;
|
|
||||||
pub const SQLITE_TESTCTRL_SORTER_MMAP: i32 = 24;
|
|
||||||
pub const SQLITE_TESTCTRL_IMPOSTER: i32 = 25;
|
|
||||||
pub const SQLITE_TESTCTRL_PARSER_COVERAGE: i32 = 26;
|
|
||||||
pub const SQLITE_TESTCTRL_RESULT_INTREAL: i32 = 27;
|
|
||||||
pub const SQLITE_TESTCTRL_PRNG_SEED: i32 = 28;
|
|
||||||
pub const SQLITE_TESTCTRL_EXTRA_SCHEMA_CHECKS: i32 = 29;
|
|
||||||
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_STATUS_MEMORY_USED: i32 = 0;
|
|
||||||
pub const SQLITE_STATUS_PAGECACHE_USED: i32 = 1;
|
|
||||||
pub const SQLITE_STATUS_PAGECACHE_OVERFLOW: i32 = 2;
|
|
||||||
pub const SQLITE_STATUS_SCRATCH_USED: i32 = 3;
|
|
||||||
pub const SQLITE_STATUS_SCRATCH_OVERFLOW: i32 = 4;
|
|
||||||
pub const SQLITE_STATUS_MALLOC_SIZE: i32 = 5;
|
|
||||||
pub const SQLITE_STATUS_PARSER_STACK: i32 = 6;
|
|
||||||
pub const SQLITE_STATUS_PAGECACHE_SIZE: i32 = 7;
|
|
||||||
pub const SQLITE_STATUS_SCRATCH_SIZE: i32 = 8;
|
|
||||||
pub const SQLITE_STATUS_MALLOC_COUNT: i32 = 9;
|
|
||||||
pub const SQLITE_DBSTATUS_LOOKASIDE_USED: i32 = 0;
|
|
||||||
pub const SQLITE_DBSTATUS_CACHE_USED: i32 = 1;
|
|
||||||
pub const SQLITE_DBSTATUS_SCHEMA_USED: i32 = 2;
|
|
||||||
pub const SQLITE_DBSTATUS_STMT_USED: i32 = 3;
|
|
||||||
pub const SQLITE_DBSTATUS_LOOKASIDE_HIT: i32 = 4;
|
|
||||||
pub const SQLITE_DBSTATUS_LOOKASIDE_MISS_SIZE: i32 = 5;
|
|
||||||
pub const SQLITE_DBSTATUS_LOOKASIDE_MISS_FULL: i32 = 6;
|
|
||||||
pub const SQLITE_DBSTATUS_CACHE_HIT: i32 = 7;
|
|
||||||
pub const SQLITE_DBSTATUS_CACHE_MISS: i32 = 8;
|
|
||||||
pub const SQLITE_DBSTATUS_CACHE_WRITE: i32 = 9;
|
|
||||||
pub const SQLITE_DBSTATUS_DEFERRED_FKS: i32 = 10;
|
|
||||||
pub const SQLITE_DBSTATUS_CACHE_USED_SHARED: i32 = 11;
|
|
||||||
pub const SQLITE_DBSTATUS_CACHE_SPILL: i32 = 12;
|
|
||||||
pub const SQLITE_DBSTATUS_MAX: i32 = 12;
|
|
||||||
pub const SQLITE_STMTSTATUS_FULLSCAN_STEP: i32 = 1;
|
|
||||||
pub const SQLITE_STMTSTATUS_SORT: i32 = 2;
|
|
||||||
pub const SQLITE_STMTSTATUS_AUTOINDEX: i32 = 3;
|
|
||||||
pub const SQLITE_STMTSTATUS_VM_STEP: i32 = 4;
|
|
||||||
pub const SQLITE_STMTSTATUS_REPREPARE: i32 = 5;
|
|
||||||
pub const SQLITE_STMTSTATUS_RUN: i32 = 6;
|
|
||||||
pub const SQLITE_STMTSTATUS_FILTER_MISS: i32 = 7;
|
|
||||||
pub const SQLITE_STMTSTATUS_FILTER_HIT: i32 = 8;
|
|
||||||
pub const SQLITE_STMTSTATUS_MEMUSED: i32 = 99;
|
|
||||||
pub const SQLITE_CHECKPOINT_PASSIVE: i32 = 0;
|
|
||||||
pub const SQLITE_CHECKPOINT_FULL: i32 = 1;
|
|
||||||
pub const SQLITE_CHECKPOINT_RESTART: i32 = 2;
|
|
||||||
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_ROLLBACK: i32 = 1;
|
|
||||||
pub const SQLITE_FAIL: i32 = 3;
|
|
||||||
pub const SQLITE_REPLACE: i32 = 5;
|
|
||||||
pub const SQLITE_SCANSTAT_NLOOP: i32 = 0;
|
|
||||||
pub const SQLITE_SCANSTAT_NVISIT: i32 = 1;
|
|
||||||
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_SCANSTAT_PARENTID: i32 = 6;
|
|
||||||
pub const SQLITE_SCANSTAT_NCYCLE: i32 = 7;
|
|
||||||
pub const SQLITE_SCANSTAT_COMPLEX: i32 = 1;
|
|
||||||
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 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_CHANGESETSTART_INVERT: i32 = 2;
|
|
||||||
pub const SQLITE_CHANGESETAPPLY_NOSAVEPOINT: i32 = 1;
|
|
||||||
pub const SQLITE_CHANGESETAPPLY_INVERT: i32 = 2;
|
|
||||||
pub const SQLITE_CHANGESET_DATA: i32 = 1;
|
|
||||||
pub const SQLITE_CHANGESET_NOTFOUND: i32 = 2;
|
|
||||||
pub const SQLITE_CHANGESET_CONFLICT: i32 = 3;
|
|
||||||
pub const SQLITE_CHANGESET_CONSTRAINT: i32 = 4;
|
|
||||||
pub const SQLITE_CHANGESET_FOREIGN_KEY: i32 = 5;
|
|
||||||
pub const SQLITE_CHANGESET_OMIT: i32 = 0;
|
|
||||||
pub const SQLITE_CHANGESET_REPLACE: i32 = 1;
|
|
||||||
pub const SQLITE_CHANGESET_ABORT: i32 = 2;
|
|
||||||
pub const SQLITE_SESSION_CONFIG_STRMSIZE: i32 = 1;
|
|
||||||
pub const FTS5_TOKENIZE_QUERY: i32 = 1;
|
|
||||||
pub const FTS5_TOKENIZE_PREFIX: i32 = 2;
|
|
||||||
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 sqlite3_version: [::std::os::raw::c_char; 0usize];
|
|
||||||
}
|
|
||||||
extern "C" {
|
|
||||||
pub fn sqlite3_libversion() -> *const ::std::os::raw::c_char;
|
|
||||||
}
|
|
||||||
extern "C" {
|
|
||||||
pub fn sqlite3_sourceid() -> *const ::std::os::raw::c_char;
|
|
||||||
}
|
|
||||||
extern "C" {
|
|
||||||
pub fn sqlite3_libversion_number() -> ::std::os::raw::c_int;
|
|
||||||
}
|
|
||||||
extern "C" {
|
|
||||||
pub fn sqlite3_compileoption_used(
|
|
||||||
zOptName: *const ::std::os::raw::c_char,
|
|
||||||
) -> ::std::os::raw::c_int;
|
|
||||||
}
|
|
||||||
extern "C" {
|
|
||||||
pub fn sqlite3_compileoption_get(N: ::std::os::raw::c_int) -> *const ::std::os::raw::c_char;
|
|
||||||
}
|
|
||||||
extern "C" {
|
|
||||||
pub fn sqlite3_threadsafe() -> ::std::os::raw::c_int;
|
|
||||||
}
|
|
||||||
#[repr(C)]
|
|
||||||
#[derive(Debug, Copy, Clone)]
|
|
||||||
pub struct sqlite3 {
|
|
||||||
_unused: [u8; 0],
|
|
||||||
}
|
|
||||||
pub type sqlite_int64 = ::std::os::raw::c_longlong;
|
|
||||||
pub type sqlite_uint64 = ::std::os::raw::c_ulonglong;
|
|
||||||
pub type sqlite3_int64 = sqlite_int64;
|
|
||||||
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,
|
|
||||||
arg2: ::std::os::raw::c_int,
|
|
||||||
arg3: *mut *mut ::std::os::raw::c_char,
|
|
||||||
arg4: *mut *mut ::std::os::raw::c_char,
|
|
||||||
) -> ::std::os::raw::c_int,
|
|
||||||
>;
|
|
||||||
extern "C" {
|
|
||||||
pub fn sqlite3_exec(
|
|
||||||
arg1: *mut sqlite3,
|
|
||||||
sql: *const ::std::os::raw::c_char,
|
|
||||||
callback: ::std::option::Option<
|
|
||||||
unsafe extern "C" fn(
|
|
||||||
arg1: *mut ::std::os::raw::c_void,
|
|
||||||
arg2: ::std::os::raw::c_int,
|
|
||||||
arg3: *mut *mut ::std::os::raw::c_char,
|
|
||||||
arg4: *mut *mut ::std::os::raw::c_char,
|
|
||||||
) -> ::std::os::raw::c_int,
|
|
||||||
>,
|
|
||||||
arg2: *mut ::std::os::raw::c_void,
|
|
||||||
errmsg: *mut *mut ::std::os::raw::c_char,
|
|
||||||
) -> ::std::os::raw::c_int;
|
|
||||||
}
|
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
#[derive(Debug, Copy, Clone)]
|
#[derive(Debug, Copy, Clone)]
|
||||||
pub struct sqlite3_file {
|
pub struct sqlite3_file {
|
||||||
@ -678,6 +356,50 @@ pub struct sqlite3_io_methods {
|
|||||||
) -> ::std::os::raw::c_int,
|
) -> ::std::os::raw::c_int,
|
||||||
>,
|
>,
|
||||||
}
|
}
|
||||||
|
pub const SQLITE_FCNTL_LOCKSTATE: i32 = 1;
|
||||||
|
pub const SQLITE_FCNTL_GET_LOCKPROXYFILE: i32 = 2;
|
||||||
|
pub const SQLITE_FCNTL_SET_LOCKPROXYFILE: i32 = 3;
|
||||||
|
pub const SQLITE_FCNTL_LAST_ERRNO: i32 = 4;
|
||||||
|
pub const SQLITE_FCNTL_SIZE_HINT: i32 = 5;
|
||||||
|
pub const SQLITE_FCNTL_CHUNK_SIZE: i32 = 6;
|
||||||
|
pub const SQLITE_FCNTL_FILE_POINTER: i32 = 7;
|
||||||
|
pub const SQLITE_FCNTL_SYNC_OMITTED: i32 = 8;
|
||||||
|
pub const SQLITE_FCNTL_WIN32_AV_RETRY: i32 = 9;
|
||||||
|
pub const SQLITE_FCNTL_PERSIST_WAL: i32 = 10;
|
||||||
|
pub const SQLITE_FCNTL_OVERWRITE: i32 = 11;
|
||||||
|
pub const SQLITE_FCNTL_VFSNAME: i32 = 12;
|
||||||
|
pub const SQLITE_FCNTL_POWERSAFE_OVERWRITE: i32 = 13;
|
||||||
|
pub const SQLITE_FCNTL_PRAGMA: i32 = 14;
|
||||||
|
pub const SQLITE_FCNTL_BUSYHANDLER: i32 = 15;
|
||||||
|
pub const SQLITE_FCNTL_TEMPFILENAME: i32 = 16;
|
||||||
|
pub const SQLITE_FCNTL_MMAP_SIZE: i32 = 18;
|
||||||
|
pub const SQLITE_FCNTL_TRACE: i32 = 19;
|
||||||
|
pub const SQLITE_FCNTL_HAS_MOVED: i32 = 20;
|
||||||
|
pub const SQLITE_FCNTL_SYNC: i32 = 21;
|
||||||
|
pub const SQLITE_FCNTL_COMMIT_PHASETWO: i32 = 22;
|
||||||
|
pub const SQLITE_FCNTL_WIN32_SET_HANDLE: i32 = 23;
|
||||||
|
pub const SQLITE_FCNTL_WAL_BLOCK: i32 = 24;
|
||||||
|
pub const SQLITE_FCNTL_ZIPVFS: i32 = 25;
|
||||||
|
pub const SQLITE_FCNTL_RBU: i32 = 26;
|
||||||
|
pub const SQLITE_FCNTL_VFS_POINTER: i32 = 27;
|
||||||
|
pub const SQLITE_FCNTL_JOURNAL_POINTER: i32 = 28;
|
||||||
|
pub const SQLITE_FCNTL_WIN32_GET_HANDLE: i32 = 29;
|
||||||
|
pub const SQLITE_FCNTL_PDB: i32 = 30;
|
||||||
|
pub const SQLITE_FCNTL_BEGIN_ATOMIC_WRITE: i32 = 31;
|
||||||
|
pub const SQLITE_FCNTL_COMMIT_ATOMIC_WRITE: i32 = 32;
|
||||||
|
pub const SQLITE_FCNTL_ROLLBACK_ATOMIC_WRITE: i32 = 33;
|
||||||
|
pub const SQLITE_FCNTL_LOCK_TIMEOUT: i32 = 34;
|
||||||
|
pub const SQLITE_FCNTL_DATA_VERSION: i32 = 35;
|
||||||
|
pub const SQLITE_FCNTL_SIZE_LIMIT: i32 = 36;
|
||||||
|
pub const SQLITE_FCNTL_CKPT_DONE: i32 = 37;
|
||||||
|
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;
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
#[derive(Debug, Copy, Clone)]
|
#[derive(Debug, Copy, Clone)]
|
||||||
pub struct sqlite3_mutex {
|
pub struct sqlite3_mutex {
|
||||||
@ -809,6 +531,14 @@ pub struct sqlite3_vfs {
|
|||||||
) -> *const ::std::os::raw::c_char,
|
) -> *const ::std::os::raw::c_char,
|
||||||
>,
|
>,
|
||||||
}
|
}
|
||||||
|
pub const SQLITE_ACCESS_EXISTS: i32 = 0;
|
||||||
|
pub const SQLITE_ACCESS_READWRITE: i32 = 1;
|
||||||
|
pub const SQLITE_ACCESS_READ: i32 = 2;
|
||||||
|
pub const SQLITE_SHM_UNLOCK: i32 = 1;
|
||||||
|
pub const SQLITE_SHM_LOCK: i32 = 2;
|
||||||
|
pub const SQLITE_SHM_SHARED: i32 = 4;
|
||||||
|
pub const SQLITE_SHM_EXCLUSIVE: i32 = 8;
|
||||||
|
pub const SQLITE_SHM_NLOCK: i32 = 8;
|
||||||
extern "C" {
|
extern "C" {
|
||||||
pub fn sqlite3_initialize() -> ::std::os::raw::c_int;
|
pub fn sqlite3_initialize() -> ::std::os::raw::c_int;
|
||||||
}
|
}
|
||||||
@ -856,6 +586,55 @@ pub struct sqlite3_mem_methods {
|
|||||||
pub xShutdown: ::std::option::Option<unsafe extern "C" fn(arg1: *mut ::std::os::raw::c_void)>,
|
pub xShutdown: ::std::option::Option<unsafe extern "C" fn(arg1: *mut ::std::os::raw::c_void)>,
|
||||||
pub pAppData: *mut ::std::os::raw::c_void,
|
pub pAppData: *mut ::std::os::raw::c_void,
|
||||||
}
|
}
|
||||||
|
pub const SQLITE_CONFIG_SINGLETHREAD: i32 = 1;
|
||||||
|
pub const SQLITE_CONFIG_MULTITHREAD: i32 = 2;
|
||||||
|
pub const SQLITE_CONFIG_SERIALIZED: i32 = 3;
|
||||||
|
pub const SQLITE_CONFIG_MALLOC: i32 = 4;
|
||||||
|
pub const SQLITE_CONFIG_GETMALLOC: i32 = 5;
|
||||||
|
pub const SQLITE_CONFIG_SCRATCH: i32 = 6;
|
||||||
|
pub const SQLITE_CONFIG_PAGECACHE: i32 = 7;
|
||||||
|
pub const SQLITE_CONFIG_HEAP: i32 = 8;
|
||||||
|
pub const SQLITE_CONFIG_MEMSTATUS: i32 = 9;
|
||||||
|
pub const SQLITE_CONFIG_MUTEX: i32 = 10;
|
||||||
|
pub const SQLITE_CONFIG_GETMUTEX: i32 = 11;
|
||||||
|
pub const SQLITE_CONFIG_LOOKASIDE: i32 = 13;
|
||||||
|
pub const SQLITE_CONFIG_PCACHE: i32 = 14;
|
||||||
|
pub const SQLITE_CONFIG_GETPCACHE: i32 = 15;
|
||||||
|
pub const SQLITE_CONFIG_LOG: i32 = 16;
|
||||||
|
pub const SQLITE_CONFIG_URI: i32 = 17;
|
||||||
|
pub const SQLITE_CONFIG_PCACHE2: i32 = 18;
|
||||||
|
pub const SQLITE_CONFIG_GETPCACHE2: i32 = 19;
|
||||||
|
pub const SQLITE_CONFIG_COVERING_INDEX_SCAN: i32 = 20;
|
||||||
|
pub const SQLITE_CONFIG_SQLLOG: i32 = 21;
|
||||||
|
pub const SQLITE_CONFIG_MMAP_SIZE: i32 = 22;
|
||||||
|
pub const SQLITE_CONFIG_WIN32_HEAPSIZE: i32 = 23;
|
||||||
|
pub const SQLITE_CONFIG_PCACHE_HDRSZ: i32 = 24;
|
||||||
|
pub const SQLITE_CONFIG_PMASZ: i32 = 25;
|
||||||
|
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_DBCONFIG_MAINDBNAME: i32 = 1000;
|
||||||
|
pub const SQLITE_DBCONFIG_LOOKASIDE: i32 = 1001;
|
||||||
|
pub const SQLITE_DBCONFIG_ENABLE_FKEY: i32 = 1002;
|
||||||
|
pub const SQLITE_DBCONFIG_ENABLE_TRIGGER: i32 = 1003;
|
||||||
|
pub const SQLITE_DBCONFIG_ENABLE_FTS3_TOKENIZER: i32 = 1004;
|
||||||
|
pub const SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION: i32 = 1005;
|
||||||
|
pub const SQLITE_DBCONFIG_NO_CKPT_ON_CLOSE: i32 = 1006;
|
||||||
|
pub const SQLITE_DBCONFIG_ENABLE_QPSG: i32 = 1007;
|
||||||
|
pub const SQLITE_DBCONFIG_TRIGGER_EQP: i32 = 1008;
|
||||||
|
pub const SQLITE_DBCONFIG_RESET_DATABASE: i32 = 1009;
|
||||||
|
pub const SQLITE_DBCONFIG_DEFENSIVE: i32 = 1010;
|
||||||
|
pub const SQLITE_DBCONFIG_WRITABLE_SCHEMA: i32 = 1011;
|
||||||
|
pub const SQLITE_DBCONFIG_LEGACY_ALTER_TABLE: i32 = 1012;
|
||||||
|
pub const SQLITE_DBCONFIG_DQS_DML: i32 = 1013;
|
||||||
|
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_STMT_SCANSTATUS: i32 = 1018;
|
||||||
|
pub const SQLITE_DBCONFIG_REVERSE_SCANORDER: i32 = 1019;
|
||||||
|
pub const SQLITE_DBCONFIG_MAX: i32 = 1019;
|
||||||
extern "C" {
|
extern "C" {
|
||||||
pub fn sqlite3_extended_result_codes(
|
pub fn sqlite3_extended_result_codes(
|
||||||
arg1: *mut sqlite3,
|
arg1: *mut sqlite3,
|
||||||
@ -984,6 +763,42 @@ extern "C" {
|
|||||||
pUserData: *mut ::std::os::raw::c_void,
|
pUserData: *mut ::std::os::raw::c_void,
|
||||||
) -> ::std::os::raw::c_int;
|
) -> ::std::os::raw::c_int;
|
||||||
}
|
}
|
||||||
|
pub const SQLITE_DENY: i32 = 1;
|
||||||
|
pub const SQLITE_IGNORE: i32 = 2;
|
||||||
|
pub const SQLITE_CREATE_INDEX: i32 = 1;
|
||||||
|
pub const SQLITE_CREATE_TABLE: i32 = 2;
|
||||||
|
pub const SQLITE_CREATE_TEMP_INDEX: i32 = 3;
|
||||||
|
pub const SQLITE_CREATE_TEMP_TABLE: i32 = 4;
|
||||||
|
pub const SQLITE_CREATE_TEMP_TRIGGER: i32 = 5;
|
||||||
|
pub const SQLITE_CREATE_TEMP_VIEW: i32 = 6;
|
||||||
|
pub const SQLITE_CREATE_TRIGGER: i32 = 7;
|
||||||
|
pub const SQLITE_CREATE_VIEW: i32 = 8;
|
||||||
|
pub const SQLITE_DELETE: i32 = 9;
|
||||||
|
pub const SQLITE_DROP_INDEX: i32 = 10;
|
||||||
|
pub const SQLITE_DROP_TABLE: i32 = 11;
|
||||||
|
pub const SQLITE_DROP_TEMP_INDEX: i32 = 12;
|
||||||
|
pub const SQLITE_DROP_TEMP_TABLE: i32 = 13;
|
||||||
|
pub const SQLITE_DROP_TEMP_TRIGGER: i32 = 14;
|
||||||
|
pub const SQLITE_DROP_TEMP_VIEW: i32 = 15;
|
||||||
|
pub const SQLITE_DROP_TRIGGER: i32 = 16;
|
||||||
|
pub const SQLITE_DROP_VIEW: i32 = 17;
|
||||||
|
pub const SQLITE_INSERT: i32 = 18;
|
||||||
|
pub const SQLITE_PRAGMA: i32 = 19;
|
||||||
|
pub const SQLITE_READ: i32 = 20;
|
||||||
|
pub const SQLITE_SELECT: i32 = 21;
|
||||||
|
pub const SQLITE_TRANSACTION: i32 = 22;
|
||||||
|
pub const SQLITE_UPDATE: i32 = 23;
|
||||||
|
pub const SQLITE_ATTACH: i32 = 24;
|
||||||
|
pub const SQLITE_DETACH: i32 = 25;
|
||||||
|
pub const SQLITE_ALTER_TABLE: i32 = 26;
|
||||||
|
pub const SQLITE_REINDEX: i32 = 27;
|
||||||
|
pub const SQLITE_ANALYZE: i32 = 28;
|
||||||
|
pub const SQLITE_CREATE_VTABLE: i32 = 29;
|
||||||
|
pub const SQLITE_DROP_VTABLE: i32 = 30;
|
||||||
|
pub const SQLITE_FUNCTION: i32 = 31;
|
||||||
|
pub const SQLITE_SAVEPOINT: i32 = 32;
|
||||||
|
pub const SQLITE_COPY: i32 = 0;
|
||||||
|
pub const SQLITE_RECURSIVE: i32 = 33;
|
||||||
extern "C" {
|
extern "C" {
|
||||||
pub fn sqlite3_trace(
|
pub fn sqlite3_trace(
|
||||||
arg1: *mut sqlite3,
|
arg1: *mut sqlite3,
|
||||||
@ -1009,6 +824,10 @@ extern "C" {
|
|||||||
arg2: *mut ::std::os::raw::c_void,
|
arg2: *mut ::std::os::raw::c_void,
|
||||||
) -> *mut ::std::os::raw::c_void;
|
) -> *mut ::std::os::raw::c_void;
|
||||||
}
|
}
|
||||||
|
pub const SQLITE_TRACE_STMT: i32 = 1;
|
||||||
|
pub const SQLITE_TRACE_PROFILE: i32 = 2;
|
||||||
|
pub const SQLITE_TRACE_ROW: i32 = 4;
|
||||||
|
pub const SQLITE_TRACE_CLOSE: i32 = 8;
|
||||||
extern "C" {
|
extern "C" {
|
||||||
pub fn sqlite3_trace_v2(
|
pub fn sqlite3_trace_v2(
|
||||||
arg1: *mut sqlite3,
|
arg1: *mut sqlite3,
|
||||||
@ -1134,6 +953,21 @@ extern "C" {
|
|||||||
newVal: ::std::os::raw::c_int,
|
newVal: ::std::os::raw::c_int,
|
||||||
) -> ::std::os::raw::c_int;
|
) -> ::std::os::raw::c_int;
|
||||||
}
|
}
|
||||||
|
pub const SQLITE_LIMIT_LENGTH: i32 = 0;
|
||||||
|
pub const SQLITE_LIMIT_SQL_LENGTH: i32 = 1;
|
||||||
|
pub const SQLITE_LIMIT_COLUMN: i32 = 2;
|
||||||
|
pub const SQLITE_LIMIT_EXPR_DEPTH: i32 = 3;
|
||||||
|
pub const SQLITE_LIMIT_COMPOUND_SELECT: i32 = 4;
|
||||||
|
pub const SQLITE_LIMIT_VDBE_OP: i32 = 5;
|
||||||
|
pub const SQLITE_LIMIT_FUNCTION_ARG: i32 = 6;
|
||||||
|
pub const SQLITE_LIMIT_ATTACHED: i32 = 7;
|
||||||
|
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: ::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;
|
||||||
extern "C" {
|
extern "C" {
|
||||||
pub fn sqlite3_prepare(
|
pub fn sqlite3_prepare(
|
||||||
db: *mut sqlite3,
|
db: *mut sqlite3,
|
||||||
@ -1405,6 +1239,12 @@ extern "C" {
|
|||||||
extern "C" {
|
extern "C" {
|
||||||
pub fn sqlite3_data_count(pStmt: *mut sqlite3_stmt) -> ::std::os::raw::c_int;
|
pub fn sqlite3_data_count(pStmt: *mut sqlite3_stmt) -> ::std::os::raw::c_int;
|
||||||
}
|
}
|
||||||
|
pub const SQLITE_INTEGER: i32 = 1;
|
||||||
|
pub const SQLITE_FLOAT: i32 = 2;
|
||||||
|
pub const SQLITE_BLOB: i32 = 4;
|
||||||
|
pub const SQLITE_NULL: i32 = 5;
|
||||||
|
pub const SQLITE_TEXT: i32 = 3;
|
||||||
|
pub const SQLITE3_TEXT: i32 = 3;
|
||||||
extern "C" {
|
extern "C" {
|
||||||
pub fn sqlite3_column_blob(
|
pub fn sqlite3_column_blob(
|
||||||
arg1: *mut sqlite3_stmt,
|
arg1: *mut sqlite3_stmt,
|
||||||
@ -1567,6 +1407,16 @@ extern "C" {
|
|||||||
xDestroy: ::std::option::Option<unsafe extern "C" fn(arg1: *mut ::std::os::raw::c_void)>,
|
xDestroy: ::std::option::Option<unsafe extern "C" fn(arg1: *mut ::std::os::raw::c_void)>,
|
||||||
) -> ::std::os::raw::c_int;
|
) -> ::std::os::raw::c_int;
|
||||||
}
|
}
|
||||||
|
pub const SQLITE_UTF8: i32 = 1;
|
||||||
|
pub const SQLITE_UTF16LE: i32 = 2;
|
||||||
|
pub const SQLITE_UTF16BE: i32 = 3;
|
||||||
|
pub const SQLITE_UTF16: i32 = 4;
|
||||||
|
pub const SQLITE_ANY: i32 = 5;
|
||||||
|
pub const SQLITE_UTF16_ALIGNED: i32 = 8;
|
||||||
|
pub const SQLITE_DETERMINISTIC: i32 = 2048;
|
||||||
|
pub const SQLITE_DIRECTONLY: i32 = 524288;
|
||||||
|
pub const SQLITE_SUBTYPE: i32 = 1048576;
|
||||||
|
pub const SQLITE_INNOCUOUS: i32 = 2097152;
|
||||||
extern "C" {
|
extern "C" {
|
||||||
pub fn sqlite3_aggregate_count(arg1: *mut sqlite3_context) -> ::std::os::raw::c_int;
|
pub fn sqlite3_aggregate_count(arg1: *mut sqlite3_context) -> ::std::os::raw::c_int;
|
||||||
}
|
}
|
||||||
@ -1908,6 +1758,8 @@ extern "C" {
|
|||||||
zValue: *const ::std::os::raw::c_void,
|
zValue: *const ::std::os::raw::c_void,
|
||||||
) -> ::std::os::raw::c_int;
|
) -> ::std::os::raw::c_int;
|
||||||
}
|
}
|
||||||
|
pub const SQLITE_WIN32_DATA_DIRECTORY_TYPE: i32 = 1;
|
||||||
|
pub const SQLITE_WIN32_TEMP_DIRECTORY_TYPE: i32 = 2;
|
||||||
extern "C" {
|
extern "C" {
|
||||||
pub fn sqlite3_get_autocommit(arg1: *mut sqlite3) -> ::std::os::raw::c_int;
|
pub fn sqlite3_get_autocommit(arg1: *mut sqlite3) -> ::std::os::raw::c_int;
|
||||||
}
|
}
|
||||||
@ -1938,6 +1790,9 @@ extern "C" {
|
|||||||
zSchema: *const ::std::os::raw::c_char,
|
zSchema: *const ::std::os::raw::c_char,
|
||||||
) -> ::std::os::raw::c_int;
|
) -> ::std::os::raw::c_int;
|
||||||
}
|
}
|
||||||
|
pub const SQLITE_TXN_NONE: i32 = 0;
|
||||||
|
pub const SQLITE_TXN_READ: i32 = 1;
|
||||||
|
pub const SQLITE_TXN_WRITE: i32 = 2;
|
||||||
extern "C" {
|
extern "C" {
|
||||||
pub fn sqlite3_next_stmt(pDb: *mut sqlite3, pStmt: *mut sqlite3_stmt) -> *mut sqlite3_stmt;
|
pub fn sqlite3_next_stmt(pDb: *mut sqlite3, pStmt: *mut sqlite3_stmt) -> *mut sqlite3_stmt;
|
||||||
}
|
}
|
||||||
@ -2209,6 +2064,24 @@ pub struct sqlite3_index_constraint_usage {
|
|||||||
pub argvIndex: ::std::os::raw::c_int,
|
pub argvIndex: ::std::os::raw::c_int,
|
||||||
pub omit: ::std::os::raw::c_uchar,
|
pub omit: ::std::os::raw::c_uchar,
|
||||||
}
|
}
|
||||||
|
pub const SQLITE_INDEX_SCAN_UNIQUE: i32 = 1;
|
||||||
|
pub const SQLITE_INDEX_CONSTRAINT_EQ: i32 = 2;
|
||||||
|
pub const SQLITE_INDEX_CONSTRAINT_GT: i32 = 4;
|
||||||
|
pub const SQLITE_INDEX_CONSTRAINT_LE: i32 = 8;
|
||||||
|
pub const SQLITE_INDEX_CONSTRAINT_LT: i32 = 16;
|
||||||
|
pub const SQLITE_INDEX_CONSTRAINT_GE: i32 = 32;
|
||||||
|
pub const SQLITE_INDEX_CONSTRAINT_MATCH: i32 = 64;
|
||||||
|
pub const SQLITE_INDEX_CONSTRAINT_LIKE: i32 = 65;
|
||||||
|
pub const SQLITE_INDEX_CONSTRAINT_GLOB: i32 = 66;
|
||||||
|
pub const SQLITE_INDEX_CONSTRAINT_REGEXP: i32 = 67;
|
||||||
|
pub const SQLITE_INDEX_CONSTRAINT_NE: i32 = 68;
|
||||||
|
pub const SQLITE_INDEX_CONSTRAINT_ISNOT: i32 = 69;
|
||||||
|
pub const SQLITE_INDEX_CONSTRAINT_ISNOTNULL: i32 = 70;
|
||||||
|
pub const SQLITE_INDEX_CONSTRAINT_ISNULL: i32 = 71;
|
||||||
|
pub const SQLITE_INDEX_CONSTRAINT_IS: i32 = 72;
|
||||||
|
pub const SQLITE_INDEX_CONSTRAINT_LIMIT: i32 = 73;
|
||||||
|
pub const SQLITE_INDEX_CONSTRAINT_OFFSET: i32 = 74;
|
||||||
|
pub const SQLITE_INDEX_CONSTRAINT_FUNCTION: i32 = 150;
|
||||||
extern "C" {
|
extern "C" {
|
||||||
pub fn sqlite3_create_module(
|
pub fn sqlite3_create_module(
|
||||||
db: *mut sqlite3,
|
db: *mut sqlite3,
|
||||||
@ -2355,6 +2228,23 @@ extern "C" {
|
|||||||
extern "C" {
|
extern "C" {
|
||||||
pub fn sqlite3_mutex_notheld(arg1: *mut sqlite3_mutex) -> ::std::os::raw::c_int;
|
pub fn sqlite3_mutex_notheld(arg1: *mut sqlite3_mutex) -> ::std::os::raw::c_int;
|
||||||
}
|
}
|
||||||
|
pub const SQLITE_MUTEX_FAST: i32 = 0;
|
||||||
|
pub const SQLITE_MUTEX_RECURSIVE: i32 = 1;
|
||||||
|
pub const SQLITE_MUTEX_STATIC_MAIN: i32 = 2;
|
||||||
|
pub const SQLITE_MUTEX_STATIC_MEM: i32 = 3;
|
||||||
|
pub const SQLITE_MUTEX_STATIC_MEM2: i32 = 4;
|
||||||
|
pub const SQLITE_MUTEX_STATIC_OPEN: i32 = 4;
|
||||||
|
pub const SQLITE_MUTEX_STATIC_PRNG: i32 = 5;
|
||||||
|
pub const SQLITE_MUTEX_STATIC_LRU: i32 = 6;
|
||||||
|
pub const SQLITE_MUTEX_STATIC_LRU2: i32 = 7;
|
||||||
|
pub const SQLITE_MUTEX_STATIC_PMEM: i32 = 7;
|
||||||
|
pub const SQLITE_MUTEX_STATIC_APP1: i32 = 8;
|
||||||
|
pub const SQLITE_MUTEX_STATIC_APP2: i32 = 9;
|
||||||
|
pub const SQLITE_MUTEX_STATIC_APP3: i32 = 10;
|
||||||
|
pub const SQLITE_MUTEX_STATIC_VFS1: i32 = 11;
|
||||||
|
pub const SQLITE_MUTEX_STATIC_VFS2: i32 = 12;
|
||||||
|
pub const SQLITE_MUTEX_STATIC_VFS3: i32 = 13;
|
||||||
|
pub const SQLITE_MUTEX_STATIC_MASTER: i32 = 2;
|
||||||
extern "C" {
|
extern "C" {
|
||||||
pub fn sqlite3_db_mutex(arg1: *mut sqlite3) -> *mut sqlite3_mutex;
|
pub fn sqlite3_db_mutex(arg1: *mut sqlite3) -> *mut sqlite3_mutex;
|
||||||
}
|
}
|
||||||
@ -2369,6 +2259,39 @@ extern "C" {
|
|||||||
extern "C" {
|
extern "C" {
|
||||||
pub fn sqlite3_test_control(op: ::std::os::raw::c_int, ...) -> ::std::os::raw::c_int;
|
pub fn sqlite3_test_control(op: ::std::os::raw::c_int, ...) -> ::std::os::raw::c_int;
|
||||||
}
|
}
|
||||||
|
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_BITVEC_TEST: i32 = 8;
|
||||||
|
pub const SQLITE_TESTCTRL_FAULT_INSTALL: i32 = 9;
|
||||||
|
pub const SQLITE_TESTCTRL_BENIGN_MALLOC_HOOKS: i32 = 10;
|
||||||
|
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_OPTIMIZATIONS: i32 = 15;
|
||||||
|
pub const SQLITE_TESTCTRL_ISKEYWORD: i32 = 16;
|
||||||
|
pub const SQLITE_TESTCTRL_SCRATCHMALLOC: i32 = 17;
|
||||||
|
pub const SQLITE_TESTCTRL_INTERNAL_FUNCTIONS: i32 = 17;
|
||||||
|
pub const SQLITE_TESTCTRL_LOCALTIME_FAULT: i32 = 18;
|
||||||
|
pub const SQLITE_TESTCTRL_EXPLAIN_STMT: i32 = 19;
|
||||||
|
pub const SQLITE_TESTCTRL_ONCE_RESET_THRESHOLD: i32 = 19;
|
||||||
|
pub const SQLITE_TESTCTRL_NEVER_CORRUPT: i32 = 20;
|
||||||
|
pub const SQLITE_TESTCTRL_VDBE_COVERAGE: i32 = 21;
|
||||||
|
pub const SQLITE_TESTCTRL_BYTEORDER: i32 = 22;
|
||||||
|
pub const SQLITE_TESTCTRL_ISINIT: i32 = 23;
|
||||||
|
pub const SQLITE_TESTCTRL_SORTER_MMAP: i32 = 24;
|
||||||
|
pub const SQLITE_TESTCTRL_IMPOSTER: i32 = 25;
|
||||||
|
pub const SQLITE_TESTCTRL_PARSER_COVERAGE: i32 = 26;
|
||||||
|
pub const SQLITE_TESTCTRL_RESULT_INTREAL: i32 = 27;
|
||||||
|
pub const SQLITE_TESTCTRL_PRNG_SEED: i32 = 28;
|
||||||
|
pub const SQLITE_TESTCTRL_EXTRA_SCHEMA_CHECKS: i32 = 29;
|
||||||
|
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;
|
||||||
extern "C" {
|
extern "C" {
|
||||||
pub fn sqlite3_keyword_count() -> ::std::os::raw::c_int;
|
pub fn sqlite3_keyword_count() -> ::std::os::raw::c_int;
|
||||||
}
|
}
|
||||||
@ -2444,6 +2367,16 @@ extern "C" {
|
|||||||
resetFlag: ::std::os::raw::c_int,
|
resetFlag: ::std::os::raw::c_int,
|
||||||
) -> ::std::os::raw::c_int;
|
) -> ::std::os::raw::c_int;
|
||||||
}
|
}
|
||||||
|
pub const SQLITE_STATUS_MEMORY_USED: i32 = 0;
|
||||||
|
pub const SQLITE_STATUS_PAGECACHE_USED: i32 = 1;
|
||||||
|
pub const SQLITE_STATUS_PAGECACHE_OVERFLOW: i32 = 2;
|
||||||
|
pub const SQLITE_STATUS_SCRATCH_USED: i32 = 3;
|
||||||
|
pub const SQLITE_STATUS_SCRATCH_OVERFLOW: i32 = 4;
|
||||||
|
pub const SQLITE_STATUS_MALLOC_SIZE: i32 = 5;
|
||||||
|
pub const SQLITE_STATUS_PARSER_STACK: i32 = 6;
|
||||||
|
pub const SQLITE_STATUS_PAGECACHE_SIZE: i32 = 7;
|
||||||
|
pub const SQLITE_STATUS_SCRATCH_SIZE: i32 = 8;
|
||||||
|
pub const SQLITE_STATUS_MALLOC_COUNT: i32 = 9;
|
||||||
extern "C" {
|
extern "C" {
|
||||||
pub fn sqlite3_db_status(
|
pub fn sqlite3_db_status(
|
||||||
arg1: *mut sqlite3,
|
arg1: *mut sqlite3,
|
||||||
@ -2453,6 +2386,20 @@ extern "C" {
|
|||||||
resetFlg: ::std::os::raw::c_int,
|
resetFlg: ::std::os::raw::c_int,
|
||||||
) -> ::std::os::raw::c_int;
|
) -> ::std::os::raw::c_int;
|
||||||
}
|
}
|
||||||
|
pub const SQLITE_DBSTATUS_LOOKASIDE_USED: i32 = 0;
|
||||||
|
pub const SQLITE_DBSTATUS_CACHE_USED: i32 = 1;
|
||||||
|
pub const SQLITE_DBSTATUS_SCHEMA_USED: i32 = 2;
|
||||||
|
pub const SQLITE_DBSTATUS_STMT_USED: i32 = 3;
|
||||||
|
pub const SQLITE_DBSTATUS_LOOKASIDE_HIT: i32 = 4;
|
||||||
|
pub const SQLITE_DBSTATUS_LOOKASIDE_MISS_SIZE: i32 = 5;
|
||||||
|
pub const SQLITE_DBSTATUS_LOOKASIDE_MISS_FULL: i32 = 6;
|
||||||
|
pub const SQLITE_DBSTATUS_CACHE_HIT: i32 = 7;
|
||||||
|
pub const SQLITE_DBSTATUS_CACHE_MISS: i32 = 8;
|
||||||
|
pub const SQLITE_DBSTATUS_CACHE_WRITE: i32 = 9;
|
||||||
|
pub const SQLITE_DBSTATUS_DEFERRED_FKS: i32 = 10;
|
||||||
|
pub const SQLITE_DBSTATUS_CACHE_USED_SHARED: i32 = 11;
|
||||||
|
pub const SQLITE_DBSTATUS_CACHE_SPILL: i32 = 12;
|
||||||
|
pub const SQLITE_DBSTATUS_MAX: i32 = 12;
|
||||||
extern "C" {
|
extern "C" {
|
||||||
pub fn sqlite3_stmt_status(
|
pub fn sqlite3_stmt_status(
|
||||||
arg1: *mut sqlite3_stmt,
|
arg1: *mut sqlite3_stmt,
|
||||||
@ -2460,6 +2407,15 @@ extern "C" {
|
|||||||
resetFlg: ::std::os::raw::c_int,
|
resetFlg: ::std::os::raw::c_int,
|
||||||
) -> ::std::os::raw::c_int;
|
) -> ::std::os::raw::c_int;
|
||||||
}
|
}
|
||||||
|
pub const SQLITE_STMTSTATUS_FULLSCAN_STEP: i32 = 1;
|
||||||
|
pub const SQLITE_STMTSTATUS_SORT: i32 = 2;
|
||||||
|
pub const SQLITE_STMTSTATUS_AUTOINDEX: i32 = 3;
|
||||||
|
pub const SQLITE_STMTSTATUS_VM_STEP: i32 = 4;
|
||||||
|
pub const SQLITE_STMTSTATUS_REPREPARE: i32 = 5;
|
||||||
|
pub const SQLITE_STMTSTATUS_RUN: i32 = 6;
|
||||||
|
pub const SQLITE_STMTSTATUS_FILTER_MISS: i32 = 7;
|
||||||
|
pub const SQLITE_STMTSTATUS_FILTER_HIT: i32 = 8;
|
||||||
|
pub const SQLITE_STMTSTATUS_MEMUSED: i32 = 99;
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
#[derive(Debug, Copy, Clone)]
|
#[derive(Debug, Copy, Clone)]
|
||||||
pub struct sqlite3_pcache {
|
pub struct sqlite3_pcache {
|
||||||
@ -2676,6 +2632,10 @@ extern "C" {
|
|||||||
pnCkpt: *mut ::std::os::raw::c_int,
|
pnCkpt: *mut ::std::os::raw::c_int,
|
||||||
) -> ::std::os::raw::c_int;
|
) -> ::std::os::raw::c_int;
|
||||||
}
|
}
|
||||||
|
pub const SQLITE_CHECKPOINT_PASSIVE: i32 = 0;
|
||||||
|
pub const SQLITE_CHECKPOINT_FULL: i32 = 1;
|
||||||
|
pub const SQLITE_CHECKPOINT_RESTART: i32 = 2;
|
||||||
|
pub const SQLITE_CHECKPOINT_TRUNCATE: i32 = 3;
|
||||||
extern "C" {
|
extern "C" {
|
||||||
pub fn sqlite3_vtab_config(
|
pub fn sqlite3_vtab_config(
|
||||||
arg1: *mut sqlite3,
|
arg1: *mut sqlite3,
|
||||||
@ -2683,6 +2643,10 @@ extern "C" {
|
|||||||
...
|
...
|
||||||
) -> ::std::os::raw::c_int;
|
) -> ::std::os::raw::c_int;
|
||||||
}
|
}
|
||||||
|
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;
|
||||||
extern "C" {
|
extern "C" {
|
||||||
pub fn sqlite3_vtab_on_conflict(arg1: *mut sqlite3) -> ::std::os::raw::c_int;
|
pub fn sqlite3_vtab_on_conflict(arg1: *mut sqlite3) -> ::std::os::raw::c_int;
|
||||||
}
|
}
|
||||||
@ -2724,6 +2688,17 @@ extern "C" {
|
|||||||
ppVal: *mut *mut sqlite3_value,
|
ppVal: *mut *mut sqlite3_value,
|
||||||
) -> ::std::os::raw::c_int;
|
) -> ::std::os::raw::c_int;
|
||||||
}
|
}
|
||||||
|
pub const SQLITE_ROLLBACK: i32 = 1;
|
||||||
|
pub const SQLITE_FAIL: i32 = 3;
|
||||||
|
pub const SQLITE_REPLACE: i32 = 5;
|
||||||
|
pub const SQLITE_SCANSTAT_NLOOP: i32 = 0;
|
||||||
|
pub const SQLITE_SCANSTAT_NVISIT: i32 = 1;
|
||||||
|
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_SCANSTAT_PARENTID: i32 = 6;
|
||||||
|
pub const SQLITE_SCANSTAT_NCYCLE: i32 = 7;
|
||||||
extern "C" {
|
extern "C" {
|
||||||
pub fn sqlite3_stmt_scanstatus(
|
pub fn sqlite3_stmt_scanstatus(
|
||||||
pStmt: *mut sqlite3_stmt,
|
pStmt: *mut sqlite3_stmt,
|
||||||
@ -2741,6 +2716,7 @@ extern "C" {
|
|||||||
pOut: *mut ::std::os::raw::c_void,
|
pOut: *mut ::std::os::raw::c_void,
|
||||||
) -> ::std::os::raw::c_int;
|
) -> ::std::os::raw::c_int;
|
||||||
}
|
}
|
||||||
|
pub const SQLITE_SCANSTAT_COMPLEX: i32 = 1;
|
||||||
extern "C" {
|
extern "C" {
|
||||||
pub fn sqlite3_stmt_scanstatus_reset(arg1: *mut sqlite3_stmt);
|
pub fn sqlite3_stmt_scanstatus_reset(arg1: *mut sqlite3_stmt);
|
||||||
}
|
}
|
||||||
@ -2832,6 +2808,7 @@ extern "C" {
|
|||||||
mFlags: ::std::os::raw::c_uint,
|
mFlags: ::std::os::raw::c_uint,
|
||||||
) -> *mut ::std::os::raw::c_uchar;
|
) -> *mut ::std::os::raw::c_uchar;
|
||||||
}
|
}
|
||||||
|
pub const SQLITE_SERIALIZE_NOCOPY: ::std::os::raw::c_uint = 1;
|
||||||
extern "C" {
|
extern "C" {
|
||||||
pub fn sqlite3_deserialize(
|
pub fn sqlite3_deserialize(
|
||||||
db: *mut sqlite3,
|
db: *mut sqlite3,
|
||||||
@ -2842,6 +2819,9 @@ extern "C" {
|
|||||||
mFlags: ::std::os::raw::c_uint,
|
mFlags: ::std::os::raw::c_uint,
|
||||||
) -> ::std::os::raw::c_int;
|
) -> ::std::os::raw::c_int;
|
||||||
}
|
}
|
||||||
|
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 type sqlite3_rtree_dbl = f64;
|
pub type sqlite3_rtree_dbl = f64;
|
||||||
extern "C" {
|
extern "C" {
|
||||||
pub fn sqlite3_rtree_geometry_callback(
|
pub fn sqlite3_rtree_geometry_callback(
|
||||||
@ -2898,6 +2878,9 @@ pub struct sqlite3_rtree_query_info {
|
|||||||
pub rScore: sqlite3_rtree_dbl,
|
pub rScore: sqlite3_rtree_dbl,
|
||||||
pub apSqlParam: *mut *mut sqlite3_value,
|
pub apSqlParam: *mut *mut sqlite3_value,
|
||||||
}
|
}
|
||||||
|
pub const NOT_WITHIN: i32 = 0;
|
||||||
|
pub const PARTLY_WITHIN: i32 = 1;
|
||||||
|
pub const FULLY_WITHIN: i32 = 2;
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
#[derive(Debug, Copy, Clone)]
|
#[derive(Debug, Copy, Clone)]
|
||||||
pub struct sqlite3_session {
|
pub struct sqlite3_session {
|
||||||
@ -2925,6 +2908,8 @@ extern "C" {
|
|||||||
pArg: *mut ::std::os::raw::c_void,
|
pArg: *mut ::std::os::raw::c_void,
|
||||||
) -> ::std::os::raw::c_int;
|
) -> ::std::os::raw::c_int;
|
||||||
}
|
}
|
||||||
|
pub const SQLITE_SESSION_OBJCONFIG_SIZE: i32 = 1;
|
||||||
|
pub const SQLITE_SESSION_OBJCONFIG_ROWID: i32 = 2;
|
||||||
extern "C" {
|
extern "C" {
|
||||||
pub fn sqlite3session_enable(
|
pub fn sqlite3session_enable(
|
||||||
pSession: *mut sqlite3_session,
|
pSession: *mut sqlite3_session,
|
||||||
@ -3001,6 +2986,7 @@ extern "C" {
|
|||||||
flags: ::std::os::raw::c_int,
|
flags: ::std::os::raw::c_int,
|
||||||
) -> ::std::os::raw::c_int;
|
) -> ::std::os::raw::c_int;
|
||||||
}
|
}
|
||||||
|
pub const SQLITE_CHANGESETSTART_INVERT: i32 = 2;
|
||||||
extern "C" {
|
extern "C" {
|
||||||
pub fn sqlite3changeset_next(pIter: *mut sqlite3_changeset_iter) -> ::std::os::raw::c_int;
|
pub fn sqlite3changeset_next(pIter: *mut sqlite3_changeset_iter) -> ::std::os::raw::c_int;
|
||||||
}
|
}
|
||||||
@ -3138,6 +3124,17 @@ extern "C" {
|
|||||||
flags: ::std::os::raw::c_int,
|
flags: ::std::os::raw::c_int,
|
||||||
) -> ::std::os::raw::c_int;
|
) -> ::std::os::raw::c_int;
|
||||||
}
|
}
|
||||||
|
pub const SQLITE_CHANGESETAPPLY_NOSAVEPOINT: i32 = 1;
|
||||||
|
pub const SQLITE_CHANGESETAPPLY_INVERT: i32 = 2;
|
||||||
|
pub const SQLITE_CHANGESETAPPLY_IGNORENOOP: i32 = 4;
|
||||||
|
pub const SQLITE_CHANGESET_DATA: i32 = 1;
|
||||||
|
pub const SQLITE_CHANGESET_NOTFOUND: i32 = 2;
|
||||||
|
pub const SQLITE_CHANGESET_CONFLICT: i32 = 3;
|
||||||
|
pub const SQLITE_CHANGESET_CONSTRAINT: i32 = 4;
|
||||||
|
pub const SQLITE_CHANGESET_FOREIGN_KEY: i32 = 5;
|
||||||
|
pub const SQLITE_CHANGESET_OMIT: i32 = 0;
|
||||||
|
pub const SQLITE_CHANGESET_REPLACE: i32 = 1;
|
||||||
|
pub const SQLITE_CHANGESET_ABORT: i32 = 2;
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
#[derive(Debug, Copy, Clone)]
|
#[derive(Debug, Copy, Clone)]
|
||||||
pub struct sqlite3_rebaser {
|
pub struct sqlite3_rebaser {
|
||||||
@ -3376,6 +3373,7 @@ extern "C" {
|
|||||||
pArg: *mut ::std::os::raw::c_void,
|
pArg: *mut ::std::os::raw::c_void,
|
||||||
) -> ::std::os::raw::c_int;
|
) -> ::std::os::raw::c_int;
|
||||||
}
|
}
|
||||||
|
pub const SQLITE_SESSION_CONFIG_STRMSIZE: i32 = 1;
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
#[derive(Debug, Copy, Clone)]
|
#[derive(Debug, Copy, Clone)]
|
||||||
pub struct Fts5Context {
|
pub struct Fts5Context {
|
||||||
@ -3575,6 +3573,11 @@ pub struct fts5_tokenizer {
|
|||||||
) -> ::std::os::raw::c_int,
|
) -> ::std::os::raw::c_int,
|
||||||
>,
|
>,
|
||||||
}
|
}
|
||||||
|
pub const FTS5_TOKENIZE_QUERY: i32 = 1;
|
||||||
|
pub const FTS5_TOKENIZE_PREFIX: i32 = 2;
|
||||||
|
pub const FTS5_TOKENIZE_DOCUMENT: i32 = 4;
|
||||||
|
pub const FTS5_TOKENIZE_AUX: i32 = 8;
|
||||||
|
pub const FTS5_TOKEN_COLOCATED: i32 = 1;
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
#[derive(Debug, Copy, Clone)]
|
#[derive(Debug, Copy, Clone)]
|
||||||
pub struct fts5_api {
|
pub struct fts5_api {
|
||||||
|
6419
libsqlite3-sys/sqlite3/sqlite3.c
vendored
6419
libsqlite3-sys/sqlite3/sqlite3.c
vendored
File diff suppressed because it is too large
Load Diff
158
libsqlite3-sys/sqlite3/sqlite3.h
vendored
158
libsqlite3-sys/sqlite3/sqlite3.h
vendored
@ -146,9 +146,9 @@ extern "C" {
|
|||||||
** [sqlite3_libversion_number()], [sqlite3_sourceid()],
|
** [sqlite3_libversion_number()], [sqlite3_sourceid()],
|
||||||
** [sqlite_version()] and [sqlite_source_id()].
|
** [sqlite_version()] and [sqlite_source_id()].
|
||||||
*/
|
*/
|
||||||
#define SQLITE_VERSION "3.41.2"
|
#define SQLITE_VERSION "3.42.0"
|
||||||
#define SQLITE_VERSION_NUMBER 3041002
|
#define SQLITE_VERSION_NUMBER 3042000
|
||||||
#define SQLITE_SOURCE_ID "2023-03-22 11:56:21 0d1fc92f94cb6b76bffe3ec34d69cffde2924203304e8ffc4155597af0c191da"
|
#define SQLITE_SOURCE_ID "2023-05-16 12:36:15 831d0fb2836b71c9bc51067c49fee4b8f18047814f2ff22d817d25195cf350b0"
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** CAPI3REF: Run-Time Library Version Numbers
|
** CAPI3REF: Run-Time Library Version Numbers
|
||||||
@ -1655,20 +1655,23 @@ SQLITE_API int sqlite3_os_end(void);
|
|||||||
** must ensure that no other SQLite interfaces are invoked by other
|
** must ensure that no other SQLite interfaces are invoked by other
|
||||||
** threads while sqlite3_config() is running.</b>
|
** threads while sqlite3_config() is running.</b>
|
||||||
**
|
**
|
||||||
** The sqlite3_config() interface
|
|
||||||
** may only be invoked prior to library initialization using
|
|
||||||
** [sqlite3_initialize()] or after shutdown by [sqlite3_shutdown()].
|
|
||||||
** ^If sqlite3_config() is called after [sqlite3_initialize()] and before
|
|
||||||
** [sqlite3_shutdown()] then it will return SQLITE_MISUSE.
|
|
||||||
** Note, however, that ^sqlite3_config() can be called as part of the
|
|
||||||
** implementation of an application-defined [sqlite3_os_init()].
|
|
||||||
**
|
|
||||||
** The first argument to sqlite3_config() is an integer
|
** The first argument to sqlite3_config() is an integer
|
||||||
** [configuration option] that determines
|
** [configuration option] that determines
|
||||||
** what property of SQLite is to be configured. Subsequent arguments
|
** what property of SQLite is to be configured. Subsequent arguments
|
||||||
** vary depending on the [configuration option]
|
** vary depending on the [configuration option]
|
||||||
** in the first argument.
|
** in the first argument.
|
||||||
**
|
**
|
||||||
|
** For most configuration options, the sqlite3_config() interface
|
||||||
|
** may only be invoked prior to library initialization using
|
||||||
|
** [sqlite3_initialize()] or after shutdown by [sqlite3_shutdown()].
|
||||||
|
** The exceptional configuration options that may be invoked at any time
|
||||||
|
** are called "anytime configuration options".
|
||||||
|
** ^If sqlite3_config() is called after [sqlite3_initialize()] and before
|
||||||
|
** [sqlite3_shutdown()] with a first argument that is not an anytime
|
||||||
|
** configuration option, then the sqlite3_config() call will return SQLITE_MISUSE.
|
||||||
|
** Note, however, that ^sqlite3_config() can be called as part of the
|
||||||
|
** implementation of an application-defined [sqlite3_os_init()].
|
||||||
|
**
|
||||||
** ^When a configuration option is set, sqlite3_config() returns [SQLITE_OK].
|
** ^When a configuration option is set, sqlite3_config() returns [SQLITE_OK].
|
||||||
** ^If the option is unknown or SQLite is unable to set the option
|
** ^If the option is unknown or SQLite is unable to set the option
|
||||||
** then this routine returns a non-zero [error code].
|
** then this routine returns a non-zero [error code].
|
||||||
@ -1776,6 +1779,23 @@ struct sqlite3_mem_methods {
|
|||||||
** These constants are the available integer configuration options that
|
** These constants are the available integer configuration options that
|
||||||
** can be passed as the first argument to the [sqlite3_config()] interface.
|
** can be passed as the first argument to the [sqlite3_config()] interface.
|
||||||
**
|
**
|
||||||
|
** Most of the configuration options for sqlite3_config()
|
||||||
|
** will only work if invoked prior to [sqlite3_initialize()] or after
|
||||||
|
** [sqlite3_shutdown()]. The few exceptions to this rule are called
|
||||||
|
** "anytime configuration options".
|
||||||
|
** ^Calling [sqlite3_config()] with a first argument that is not an
|
||||||
|
** anytime configuration option in between calls to [sqlite3_initialize()] and
|
||||||
|
** [sqlite3_shutdown()] is a no-op that returns SQLITE_MISUSE.
|
||||||
|
**
|
||||||
|
** The set of anytime configuration options can change (by insertions
|
||||||
|
** and/or deletions) from one release of SQLite to the next.
|
||||||
|
** As of SQLite version 3.42.0, the complete set of anytime configuration
|
||||||
|
** options is:
|
||||||
|
** <ul>
|
||||||
|
** <li> SQLITE_CONFIG_LOG
|
||||||
|
** <li> SQLITE_CONFIG_PCACHE_HDRSZ
|
||||||
|
** </ul>
|
||||||
|
**
|
||||||
** New configuration options may be added in future releases of SQLite.
|
** New configuration options may be added in future releases of SQLite.
|
||||||
** Existing configuration options might be discontinued. Applications
|
** Existing configuration options might be discontinued. Applications
|
||||||
** should check the return code from [sqlite3_config()] to make sure that
|
** should check the return code from [sqlite3_config()] to make sure that
|
||||||
@ -2378,7 +2398,7 @@ struct sqlite3_mem_methods {
|
|||||||
** </dd>
|
** </dd>
|
||||||
**
|
**
|
||||||
** [[SQLITE_DBCONFIG_DQS_DML]]
|
** [[SQLITE_DBCONFIG_DQS_DML]]
|
||||||
** <dt>SQLITE_DBCONFIG_DQS_DML</td>
|
** <dt>SQLITE_DBCONFIG_DQS_DML</dt>
|
||||||
** <dd>The SQLITE_DBCONFIG_DQS_DML option activates or deactivates
|
** <dd>The SQLITE_DBCONFIG_DQS_DML option activates or deactivates
|
||||||
** the legacy [double-quoted string literal] misfeature for DML statements
|
** the legacy [double-quoted string literal] misfeature for DML statements
|
||||||
** only, that is DELETE, INSERT, SELECT, and UPDATE statements. The
|
** only, that is DELETE, INSERT, SELECT, and UPDATE statements. The
|
||||||
@ -2387,7 +2407,7 @@ struct sqlite3_mem_methods {
|
|||||||
** </dd>
|
** </dd>
|
||||||
**
|
**
|
||||||
** [[SQLITE_DBCONFIG_DQS_DDL]]
|
** [[SQLITE_DBCONFIG_DQS_DDL]]
|
||||||
** <dt>SQLITE_DBCONFIG_DQS_DDL</td>
|
** <dt>SQLITE_DBCONFIG_DQS_DDL</dt>
|
||||||
** <dd>The SQLITE_DBCONFIG_DQS option activates or deactivates
|
** <dd>The SQLITE_DBCONFIG_DQS option activates or deactivates
|
||||||
** the legacy [double-quoted string literal] misfeature for DDL statements,
|
** the legacy [double-quoted string literal] misfeature for DDL statements,
|
||||||
** such as CREATE TABLE and CREATE INDEX. The
|
** such as CREATE TABLE and CREATE INDEX. The
|
||||||
@ -2396,7 +2416,7 @@ struct sqlite3_mem_methods {
|
|||||||
** </dd>
|
** </dd>
|
||||||
**
|
**
|
||||||
** [[SQLITE_DBCONFIG_TRUSTED_SCHEMA]]
|
** [[SQLITE_DBCONFIG_TRUSTED_SCHEMA]]
|
||||||
** <dt>SQLITE_DBCONFIG_TRUSTED_SCHEMA</td>
|
** <dt>SQLITE_DBCONFIG_TRUSTED_SCHEMA</dt>
|
||||||
** <dd>The SQLITE_DBCONFIG_TRUSTED_SCHEMA option tells SQLite to
|
** <dd>The SQLITE_DBCONFIG_TRUSTED_SCHEMA option tells SQLite to
|
||||||
** assume that database schemas are untainted by malicious content.
|
** assume that database schemas are untainted by malicious content.
|
||||||
** When the SQLITE_DBCONFIG_TRUSTED_SCHEMA option is disabled, SQLite
|
** When the SQLITE_DBCONFIG_TRUSTED_SCHEMA option is disabled, SQLite
|
||||||
@ -2416,7 +2436,7 @@ struct sqlite3_mem_methods {
|
|||||||
** </dd>
|
** </dd>
|
||||||
**
|
**
|
||||||
** [[SQLITE_DBCONFIG_LEGACY_FILE_FORMAT]]
|
** [[SQLITE_DBCONFIG_LEGACY_FILE_FORMAT]]
|
||||||
** <dt>SQLITE_DBCONFIG_LEGACY_FILE_FORMAT</td>
|
** <dt>SQLITE_DBCONFIG_LEGACY_FILE_FORMAT</dt>
|
||||||
** <dd>The SQLITE_DBCONFIG_LEGACY_FILE_FORMAT option activates or deactivates
|
** <dd>The SQLITE_DBCONFIG_LEGACY_FILE_FORMAT option activates or deactivates
|
||||||
** the legacy file format flag. When activated, this flag causes all newly
|
** the legacy file format flag. When activated, this flag causes all newly
|
||||||
** created database file to have a schema format version number (the 4-byte
|
** created database file to have a schema format version number (the 4-byte
|
||||||
@ -2425,7 +2445,7 @@ struct sqlite3_mem_methods {
|
|||||||
** any SQLite version back to 3.0.0 ([dateof:3.0.0]). Without this setting,
|
** any SQLite version back to 3.0.0 ([dateof:3.0.0]). Without this setting,
|
||||||
** newly created databases are generally not understandable by SQLite versions
|
** newly created databases are generally not understandable by SQLite versions
|
||||||
** prior to 3.3.0 ([dateof:3.3.0]). As these words are written, there
|
** prior to 3.3.0 ([dateof:3.3.0]). As these words are written, there
|
||||||
** is now scarcely any need to generated database files that are compatible
|
** is now scarcely any need to generate database files that are compatible
|
||||||
** all the way back to version 3.0.0, and so this setting is of little
|
** all the way back to version 3.0.0, and so this setting is of little
|
||||||
** practical use, but is provided so that SQLite can continue to claim the
|
** practical use, but is provided so that SQLite can continue to claim the
|
||||||
** ability to generate new database files that are compatible with version
|
** ability to generate new database files that are compatible with version
|
||||||
@ -2436,6 +2456,38 @@ struct sqlite3_mem_methods {
|
|||||||
** not considered a bug since SQLite versions 3.3.0 and earlier do not support
|
** not considered a bug since SQLite versions 3.3.0 and earlier do not support
|
||||||
** either generated columns or decending indexes.
|
** either generated columns or decending indexes.
|
||||||
** </dd>
|
** </dd>
|
||||||
|
**
|
||||||
|
** [[SQLITE_DBCONFIG_STMT_SCANSTATUS]]
|
||||||
|
** <dt>SQLITE_DBCONFIG_STMT_SCANSTATUS</dt>
|
||||||
|
** <dd>The SQLITE_DBCONFIG_STMT_SCANSTATUS option is only useful in
|
||||||
|
** SQLITE_ENABLE_STMT_SCANSTATUS builds. In this case, it sets or clears
|
||||||
|
** a flag that enables collection of the sqlite3_stmt_scanstatus_v2()
|
||||||
|
** statistics. For statistics to be collected, the flag must be set on
|
||||||
|
** the database handle both when the SQL statement is prepared and when it
|
||||||
|
** is stepped. The flag is set (collection of statistics is enabled)
|
||||||
|
** by default. This option takes two arguments: an integer and a pointer to
|
||||||
|
** an integer.. The first argument is 1, 0, or -1 to enable, disable, or
|
||||||
|
** leave unchanged the statement scanstatus option. If the second argument
|
||||||
|
** is not NULL, then the value of the statement scanstatus setting after
|
||||||
|
** processing the first argument is written into the integer that the second
|
||||||
|
** argument points to.
|
||||||
|
** </dd>
|
||||||
|
**
|
||||||
|
** [[SQLITE_DBCONFIG_REVERSE_SCANORDER]]
|
||||||
|
** <dt>SQLITE_DBCONFIG_REVERSE_SCANORDER</dt>
|
||||||
|
** <dd>The SQLITE_DBCONFIG_REVERSE_SCANORDER option changes the default order
|
||||||
|
** in which tables and indexes are scanned so that the scans start at the end
|
||||||
|
** and work toward the beginning rather than starting at the beginning and
|
||||||
|
** working toward the end. Setting SQLITE_DBCONFIG_REVERSE_SCANORDER is the
|
||||||
|
** same as setting [PRAGMA reverse_unordered_selects]. This option takes
|
||||||
|
** two arguments which are an integer and a pointer to an integer. The first
|
||||||
|
** argument is 1, 0, or -1 to enable, disable, or leave unchanged the
|
||||||
|
** reverse scan order flag, respectively. If the second argument is not NULL,
|
||||||
|
** then 0 or 1 is written into the integer that the second argument points to
|
||||||
|
** depending on if the reverse scan order flag is set after processing the
|
||||||
|
** first argument.
|
||||||
|
** </dd>
|
||||||
|
**
|
||||||
** </dl>
|
** </dl>
|
||||||
*/
|
*/
|
||||||
#define SQLITE_DBCONFIG_MAINDBNAME 1000 /* const char* */
|
#define SQLITE_DBCONFIG_MAINDBNAME 1000 /* const char* */
|
||||||
@ -2456,7 +2508,9 @@ struct sqlite3_mem_methods {
|
|||||||
#define SQLITE_DBCONFIG_ENABLE_VIEW 1015 /* int int* */
|
#define SQLITE_DBCONFIG_ENABLE_VIEW 1015 /* int int* */
|
||||||
#define SQLITE_DBCONFIG_LEGACY_FILE_FORMAT 1016 /* int int* */
|
#define SQLITE_DBCONFIG_LEGACY_FILE_FORMAT 1016 /* int int* */
|
||||||
#define SQLITE_DBCONFIG_TRUSTED_SCHEMA 1017 /* int int* */
|
#define SQLITE_DBCONFIG_TRUSTED_SCHEMA 1017 /* int int* */
|
||||||
#define SQLITE_DBCONFIG_MAX 1017 /* Largest DBCONFIG */
|
#define SQLITE_DBCONFIG_STMT_SCANSTATUS 1018 /* int int* */
|
||||||
|
#define SQLITE_DBCONFIG_REVERSE_SCANORDER 1019 /* int int* */
|
||||||
|
#define SQLITE_DBCONFIG_MAX 1019 /* Largest DBCONFIG */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** CAPI3REF: Enable Or Disable Extended Result Codes
|
** CAPI3REF: Enable Or Disable Extended Result Codes
|
||||||
@ -6201,6 +6255,13 @@ SQLITE_API void sqlite3_activate_cerod(
|
|||||||
** of the default VFS is not implemented correctly, or not implemented at
|
** of the default VFS is not implemented correctly, or not implemented at
|
||||||
** all, then the behavior of sqlite3_sleep() may deviate from the description
|
** all, then the behavior of sqlite3_sleep() may deviate from the description
|
||||||
** in the previous paragraphs.
|
** in the previous paragraphs.
|
||||||
|
**
|
||||||
|
** If a negative argument is passed to sqlite3_sleep() the results vary by
|
||||||
|
** VFS and operating system. Some system treat a negative argument as an
|
||||||
|
** instruction to sleep forever. Others understand it to mean do not sleep
|
||||||
|
** at all. ^In SQLite version 3.42.0 and later, a negative
|
||||||
|
** argument passed into sqlite3_sleep() is changed to zero before it is relayed
|
||||||
|
** down into the xSleep method of the VFS.
|
||||||
*/
|
*/
|
||||||
SQLITE_API int sqlite3_sleep(int);
|
SQLITE_API int sqlite3_sleep(int);
|
||||||
|
|
||||||
@ -7828,9 +7889,9 @@ SQLITE_API int sqlite3_vfs_unregister(sqlite3_vfs*);
|
|||||||
** is undefined if the mutex is not currently entered by the
|
** is undefined if the mutex is not currently entered by the
|
||||||
** calling thread or is not currently allocated.
|
** calling thread or is not currently allocated.
|
||||||
**
|
**
|
||||||
** ^If the argument to sqlite3_mutex_enter(), sqlite3_mutex_try(), or
|
** ^If the argument to sqlite3_mutex_enter(), sqlite3_mutex_try(),
|
||||||
** sqlite3_mutex_leave() is a NULL pointer, then all three routines
|
** sqlite3_mutex_leave(), or sqlite3_mutex_free() is a NULL pointer,
|
||||||
** behave as no-ops.
|
** then any of the four routines behaves as a no-op.
|
||||||
**
|
**
|
||||||
** See also: [sqlite3_mutex_held()] and [sqlite3_mutex_notheld()].
|
** See also: [sqlite3_mutex_held()] and [sqlite3_mutex_notheld()].
|
||||||
*/
|
*/
|
||||||
@ -9564,18 +9625,28 @@ SQLITE_API int sqlite3_vtab_config(sqlite3*, int op, ...);
|
|||||||
** [[SQLITE_VTAB_INNOCUOUS]]<dt>SQLITE_VTAB_INNOCUOUS</dt>
|
** [[SQLITE_VTAB_INNOCUOUS]]<dt>SQLITE_VTAB_INNOCUOUS</dt>
|
||||||
** <dd>Calls of the form
|
** <dd>Calls of the form
|
||||||
** [sqlite3_vtab_config](db,SQLITE_VTAB_INNOCUOUS) from within the
|
** [sqlite3_vtab_config](db,SQLITE_VTAB_INNOCUOUS) from within the
|
||||||
** the [xConnect] or [xCreate] methods of a [virtual table] implmentation
|
** the [xConnect] or [xCreate] methods of a [virtual table] implementation
|
||||||
** identify that virtual table as being safe to use from within triggers
|
** identify that virtual table as being safe to use from within triggers
|
||||||
** and views. Conceptually, the SQLITE_VTAB_INNOCUOUS tag means that the
|
** and views. Conceptually, the SQLITE_VTAB_INNOCUOUS tag means that the
|
||||||
** virtual table can do no serious harm even if it is controlled by a
|
** virtual table can do no serious harm even if it is controlled by a
|
||||||
** malicious hacker. Developers should avoid setting the SQLITE_VTAB_INNOCUOUS
|
** malicious hacker. Developers should avoid setting the SQLITE_VTAB_INNOCUOUS
|
||||||
** flag unless absolutely necessary.
|
** flag unless absolutely necessary.
|
||||||
** </dd>
|
** </dd>
|
||||||
|
**
|
||||||
|
** [[SQLITE_VTAB_USES_ALL_SCHEMAS]]<dt>SQLITE_VTAB_USES_ALL_SCHEMAS</dt>
|
||||||
|
** <dd>Calls of the form
|
||||||
|
** [sqlite3_vtab_config](db,SQLITE_VTAB_USES_ALL_SCHEMA) from within the
|
||||||
|
** the [xConnect] or [xCreate] methods of a [virtual table] implementation
|
||||||
|
** instruct the query planner to begin at least a read transaction on
|
||||||
|
** all schemas ("main", "temp", and any ATTACH-ed databases) whenever the
|
||||||
|
** virtual table is used.
|
||||||
|
** </dd>
|
||||||
** </dl>
|
** </dl>
|
||||||
*/
|
*/
|
||||||
#define SQLITE_VTAB_CONSTRAINT_SUPPORT 1
|
#define SQLITE_VTAB_CONSTRAINT_SUPPORT 1
|
||||||
#define SQLITE_VTAB_INNOCUOUS 2
|
#define SQLITE_VTAB_INNOCUOUS 2
|
||||||
#define SQLITE_VTAB_DIRECTONLY 3
|
#define SQLITE_VTAB_DIRECTONLY 3
|
||||||
|
#define SQLITE_VTAB_USES_ALL_SCHEMAS 4
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** CAPI3REF: Determine The Virtual Table Conflict Policy
|
** CAPI3REF: Determine The Virtual Table Conflict Policy
|
||||||
@ -10750,16 +10821,20 @@ SQLITE_API int sqlite3session_create(
|
|||||||
SQLITE_API void sqlite3session_delete(sqlite3_session *pSession);
|
SQLITE_API void sqlite3session_delete(sqlite3_session *pSession);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** CAPIREF: Conigure a Session Object
|
** CAPI3REF: Configure a Session Object
|
||||||
** METHOD: sqlite3_session
|
** METHOD: sqlite3_session
|
||||||
**
|
**
|
||||||
** This method is used to configure a session object after it has been
|
** This method is used to configure a session object after it has been
|
||||||
** created. At present the only valid value for the second parameter is
|
** created. At present the only valid values for the second parameter are
|
||||||
** [SQLITE_SESSION_OBJCONFIG_SIZE].
|
** [SQLITE_SESSION_OBJCONFIG_SIZE] and [SQLITE_SESSION_OBJCONFIG_ROWID].
|
||||||
**
|
**
|
||||||
** Arguments for sqlite3session_object_config()
|
*/
|
||||||
|
SQLITE_API int sqlite3session_object_config(sqlite3_session*, int op, void *pArg);
|
||||||
|
|
||||||
|
/*
|
||||||
|
** CAPI3REF: Options for sqlite3session_object_config
|
||||||
**
|
**
|
||||||
** The following values may passed as the the 4th parameter to
|
** The following values may passed as the the 2nd parameter to
|
||||||
** sqlite3session_object_config().
|
** sqlite3session_object_config().
|
||||||
**
|
**
|
||||||
** <dt>SQLITE_SESSION_OBJCONFIG_SIZE <dd>
|
** <dt>SQLITE_SESSION_OBJCONFIG_SIZE <dd>
|
||||||
@ -10775,12 +10850,21 @@ SQLITE_API void sqlite3session_delete(sqlite3_session *pSession);
|
|||||||
**
|
**
|
||||||
** It is an error (SQLITE_MISUSE) to attempt to modify this setting after
|
** It is an error (SQLITE_MISUSE) to attempt to modify this setting after
|
||||||
** the first table has been attached to the session object.
|
** the first table has been attached to the session object.
|
||||||
*/
|
**
|
||||||
SQLITE_API int sqlite3session_object_config(sqlite3_session*, int op, void *pArg);
|
** <dt>SQLITE_SESSION_OBJCONFIG_ROWID <dd>
|
||||||
|
** This option is used to set, clear or query the flag that enables
|
||||||
/*
|
** collection of data for tables with no explicit PRIMARY KEY.
|
||||||
|
**
|
||||||
|
** Normally, tables with no explicit PRIMARY KEY are simply ignored
|
||||||
|
** by the sessions module. However, if this flag is set, it behaves
|
||||||
|
** as if such tables have a column "_rowid_ INTEGER PRIMARY KEY" inserted
|
||||||
|
** as their leftmost columns.
|
||||||
|
**
|
||||||
|
** It is an error (SQLITE_MISUSE) to attempt to modify this setting after
|
||||||
|
** the first table has been attached to the session object.
|
||||||
*/
|
*/
|
||||||
#define SQLITE_SESSION_OBJCONFIG_SIZE 1
|
#define SQLITE_SESSION_OBJCONFIG_SIZE 1
|
||||||
|
#define SQLITE_SESSION_OBJCONFIG_ROWID 2
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** CAPI3REF: Enable Or Disable A Session Object
|
** CAPI3REF: Enable Or Disable A Session Object
|
||||||
@ -11913,9 +11997,23 @@ SQLITE_API int sqlite3changeset_apply_v2(
|
|||||||
** Invert the changeset before applying it. This is equivalent to inverting
|
** Invert the changeset before applying it. This is equivalent to inverting
|
||||||
** a changeset using sqlite3changeset_invert() before applying it. It is
|
** a changeset using sqlite3changeset_invert() before applying it. It is
|
||||||
** an error to specify this flag with a patchset.
|
** an error to specify this flag with a patchset.
|
||||||
|
**
|
||||||
|
** <dt>SQLITE_CHANGESETAPPLY_IGNORENOOP <dd>
|
||||||
|
** Do not invoke the conflict handler callback for any changes that
|
||||||
|
** would not actually modify the database even if they were applied.
|
||||||
|
** Specifically, this means that the conflict handler is not invoked
|
||||||
|
** for:
|
||||||
|
** <ul>
|
||||||
|
** <li>a delete change if the row being deleted cannot be found,
|
||||||
|
** <li>an update change if the modified fields are already set to
|
||||||
|
** their new values in the conflicting row, or
|
||||||
|
** <li>an insert change if all fields of the conflicting row match
|
||||||
|
** the row being inserted.
|
||||||
|
** </ul>
|
||||||
*/
|
*/
|
||||||
#define SQLITE_CHANGESETAPPLY_NOSAVEPOINT 0x0001
|
#define SQLITE_CHANGESETAPPLY_NOSAVEPOINT 0x0001
|
||||||
#define SQLITE_CHANGESETAPPLY_INVERT 0x0002
|
#define SQLITE_CHANGESETAPPLY_INVERT 0x0002
|
||||||
|
#define SQLITE_CHANGESETAPPLY_IGNORENOOP 0x0004
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** CAPI3REF: Constants Passed To The Conflict Handler
|
** CAPI3REF: Constants Passed To The Conflict Handler
|
||||||
|
@ -9,7 +9,7 @@ export SQLITE3_LIB_DIR="$SCRIPT_DIR/sqlite3"
|
|||||||
export SQLITE3_INCLUDE_DIR="$SQLITE3_LIB_DIR"
|
export SQLITE3_INCLUDE_DIR="$SQLITE3_LIB_DIR"
|
||||||
|
|
||||||
# Download and extract amalgamation
|
# Download and extract amalgamation
|
||||||
SQLITE=sqlite-amalgamation-3410200
|
SQLITE=sqlite-amalgamation-3420000
|
||||||
curl -O https://sqlite.org/2023/$SQLITE.zip
|
curl -O https://sqlite.org/2023/$SQLITE.zip
|
||||||
unzip -p "$SQLITE.zip" "$SQLITE/sqlite3.c" > "$SQLITE3_LIB_DIR/sqlite3.c"
|
unzip -p "$SQLITE.zip" "$SQLITE/sqlite3.c" > "$SQLITE3_LIB_DIR/sqlite3.c"
|
||||||
unzip -p "$SQLITE.zip" "$SQLITE/sqlite3.h" > "$SQLITE3_LIB_DIR/sqlite3.h"
|
unzip -p "$SQLITE.zip" "$SQLITE/sqlite3.h" > "$SQLITE3_LIB_DIR/sqlite3.h"
|
||||||
|
@ -274,7 +274,6 @@ impl Blob<'_> {
|
|||||||
#[inline]
|
#[inline]
|
||||||
#[must_use]
|
#[must_use]
|
||||||
pub fn len(&self) -> usize {
|
pub fn len(&self) -> usize {
|
||||||
use std::convert::TryInto;
|
|
||||||
self.size().try_into().unwrap()
|
self.size().try_into().unwrap()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
//! Prepared statements cache for faster execution.
|
//! Prepared statements cache for faster execution.
|
||||||
|
|
||||||
use crate::raw_statement::RawStatement;
|
use crate::raw_statement::RawStatement;
|
||||||
use crate::{Connection, Result, Statement};
|
use crate::{Connection, PrepFlags, Result, Statement};
|
||||||
use hashlink::LruCache;
|
use hashlink::LruCache;
|
||||||
use std::cell::RefCell;
|
use std::cell::RefCell;
|
||||||
use std::ops::{Deref, DerefMut};
|
use std::ops::{Deref, DerefMut};
|
||||||
@ -144,7 +144,7 @@ impl StatementCache {
|
|||||||
let mut cache = self.0.borrow_mut();
|
let mut cache = self.0.borrow_mut();
|
||||||
let stmt = match cache.remove(trimmed) {
|
let stmt = match cache.remove(trimmed) {
|
||||||
Some(raw_stmt) => Ok(Statement::new(conn, raw_stmt)),
|
Some(raw_stmt) => Ok(Statement::new(conn, raw_stmt)),
|
||||||
None => conn.prepare(trimmed),
|
None => conn.prepare_with_flags(trimmed, PrepFlags::SQLITE_PREPARE_PERSISTENT),
|
||||||
};
|
};
|
||||||
stmt.map(|mut stmt| {
|
stmt.map(|mut stmt| {
|
||||||
stmt.stmt.set_statement_cache_key(trimmed);
|
stmt.stmt.set_statement_cache_key(trimmed);
|
||||||
|
@ -203,7 +203,7 @@ mod test {
|
|||||||
assert_eq!(ty, Type::Integer);
|
assert_eq!(ty, Type::Integer);
|
||||||
}
|
}
|
||||||
e => {
|
e => {
|
||||||
panic!("Unexpected error type: {:?}", e);
|
panic!("Unexpected error type: {e:?}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
match row.get::<_, String>("y").unwrap_err() {
|
match row.get::<_, String>("y").unwrap_err() {
|
||||||
@ -213,7 +213,7 @@ mod test {
|
|||||||
assert_eq!(ty, Type::Null);
|
assert_eq!(ty, Type::Null);
|
||||||
}
|
}
|
||||||
e => {
|
e => {
|
||||||
panic!("Unexpected error type: {:?}", e);
|
panic!("Unexpected error type: {e:?}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
|
@ -61,6 +61,13 @@ pub enum DbConfig {
|
|||||||
/// sqlite_master tables) are untainted by malicious content.
|
/// sqlite_master tables) are untainted by malicious content.
|
||||||
#[cfg(feature = "modern_sqlite")]
|
#[cfg(feature = "modern_sqlite")]
|
||||||
SQLITE_DBCONFIG_TRUSTED_SCHEMA = 1017, // 3.31.0
|
SQLITE_DBCONFIG_TRUSTED_SCHEMA = 1017, // 3.31.0
|
||||||
|
/// Sets or clears a flag that enables collection of the
|
||||||
|
/// 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
|
||||||
|
#[cfg(feature = "modern_sqlite")]
|
||||||
|
SQLITE_DBCONFIG_REVERSE_SCANORDER = 1019, // 3.42.0
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Connection {
|
impl Connection {
|
||||||
|
40
src/error.rs
40
src/error.rs
@ -252,11 +252,7 @@ impl fmt::Display for Error {
|
|||||||
),
|
),
|
||||||
Error::FromSqlConversionFailure(i, ref t, ref err) => {
|
Error::FromSqlConversionFailure(i, ref t, ref err) => {
|
||||||
if i != UNKNOWN_COLUMN {
|
if i != UNKNOWN_COLUMN {
|
||||||
write!(
|
write!(f, "Conversion error from type {t} at index: {i}, {err}")
|
||||||
f,
|
|
||||||
"Conversion error from type {} at index: {}, {}",
|
|
||||||
t, i, err
|
|
||||||
)
|
|
||||||
} else {
|
} else {
|
||||||
err.fmt(f)
|
err.fmt(f)
|
||||||
}
|
}
|
||||||
@ -278,15 +274,12 @@ impl fmt::Display for Error {
|
|||||||
Error::QueryReturnedNoRows => write!(f, "Query returned no rows"),
|
Error::QueryReturnedNoRows => write!(f, "Query returned no rows"),
|
||||||
Error::InvalidColumnIndex(i) => write!(f, "Invalid column index: {i}"),
|
Error::InvalidColumnIndex(i) => write!(f, "Invalid column index: {i}"),
|
||||||
Error::InvalidColumnName(ref name) => write!(f, "Invalid column name: {name}"),
|
Error::InvalidColumnName(ref name) => write!(f, "Invalid column name: {name}"),
|
||||||
Error::InvalidColumnType(i, ref name, ref t) => write!(
|
Error::InvalidColumnType(i, ref name, ref t) => {
|
||||||
f,
|
write!(f, "Invalid column type {t} at index: {i}, name: {name}")
|
||||||
"Invalid column type {} at index: {}, name: {}",
|
}
|
||||||
t, i, name
|
|
||||||
),
|
|
||||||
Error::InvalidParameterCount(i1, n1) => write!(
|
Error::InvalidParameterCount(i1, n1) => write!(
|
||||||
f,
|
f,
|
||||||
"Wrong number of parameters passed to query. Got {}, needed {}",
|
"Wrong number of parameters passed to query. Got {i1}, needed {n1}"
|
||||||
i1, n1
|
|
||||||
),
|
),
|
||||||
Error::StatementChangedRows(i) => write!(f, "Query changed {i} rows"),
|
Error::StatementChangedRows(i) => write!(f, "Query changed {i} rows"),
|
||||||
|
|
||||||
@ -393,7 +386,6 @@ impl Error {
|
|||||||
|
|
||||||
#[cold]
|
#[cold]
|
||||||
pub fn error_from_sqlite_code(code: c_int, message: Option<String>) -> Error {
|
pub fn error_from_sqlite_code(code: c_int, message: Option<String>) -> Error {
|
||||||
// TODO sqlite3_error_offset // 3.38.0, #1130
|
|
||||||
Error::SqliteFailure(ffi::Error::new(code), message)
|
Error::SqliteFailure(ffi::Error::new(code), message)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -443,3 +435,25 @@ pub fn check(code: c_int) -> Result<()> {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Transform Rust error to SQLite error (message and code).
|
||||||
|
/// # Safety
|
||||||
|
/// This function is unsafe because it uses raw pointer
|
||||||
|
pub unsafe fn to_sqlite_error(
|
||||||
|
e: &Error,
|
||||||
|
err_msg: *mut *mut std::os::raw::c_char,
|
||||||
|
) -> std::os::raw::c_int {
|
||||||
|
use crate::util::alloc;
|
||||||
|
match e {
|
||||||
|
Error::SqliteFailure(err, s) => {
|
||||||
|
if let Some(s) = s {
|
||||||
|
*err_msg = alloc(s);
|
||||||
|
}
|
||||||
|
err.extended_code
|
||||||
|
}
|
||||||
|
err => {
|
||||||
|
*err_msg = alloc(&err.to_string());
|
||||||
|
ffi::SQLITE_ERROR
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -71,21 +71,13 @@ use crate::types::{FromSql, FromSqlError, ToSql, ValueRef};
|
|||||||
use crate::{str_to_cstring, Connection, Error, InnerConnection, Result};
|
use crate::{str_to_cstring, Connection, Error, InnerConnection, Result};
|
||||||
|
|
||||||
unsafe fn report_error(ctx: *mut sqlite3_context, err: &Error) {
|
unsafe fn report_error(ctx: *mut sqlite3_context, err: &Error) {
|
||||||
// Extended constraint error codes were added in SQLite 3.7.16. We don't have
|
|
||||||
// an explicit feature check for that, and this doesn't really warrant one.
|
|
||||||
// We'll use the extended code if we're on the bundled version (since it's
|
|
||||||
// at least 3.17.0) and the normal constraint error code if not.
|
|
||||||
fn constraint_error_code() -> i32 {
|
|
||||||
ffi::SQLITE_CONSTRAINT_FUNCTION
|
|
||||||
}
|
|
||||||
|
|
||||||
if let Error::SqliteFailure(ref err, ref s) = *err {
|
if let Error::SqliteFailure(ref err, ref s) = *err {
|
||||||
ffi::sqlite3_result_error_code(ctx, err.extended_code);
|
ffi::sqlite3_result_error_code(ctx, err.extended_code);
|
||||||
if let Some(Ok(cstr)) = s.as_ref().map(|s| str_to_cstring(s)) {
|
if let Some(Ok(cstr)) = s.as_ref().map(|s| str_to_cstring(s)) {
|
||||||
ffi::sqlite3_result_error(ctx, cstr.as_ptr(), -1);
|
ffi::sqlite3_result_error(ctx, cstr.as_ptr(), -1);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
ffi::sqlite3_result_error_code(ctx, constraint_error_code());
|
ffi::sqlite3_result_error_code(ctx, ffi::SQLITE_CONSTRAINT_FUNCTION);
|
||||||
if let Ok(cstr) = str_to_cstring(&err.to_string()) {
|
if let Ok(cstr) = str_to_cstring(&err.to_string()) {
|
||||||
ffi::sqlite3_result_error(ctx, cstr.as_ptr(), -1);
|
ffi::sqlite3_result_error(ctx, cstr.as_ptr(), -1);
|
||||||
}
|
}
|
||||||
@ -847,7 +839,7 @@ mod test {
|
|||||||
// This implementation of a regexp scalar function uses SQLite's auxiliary data
|
// This implementation of a regexp scalar function uses SQLite's auxiliary data
|
||||||
// (https://www.sqlite.org/c3ref/get_auxdata.html) to avoid recompiling the regular
|
// (https://www.sqlite.org/c3ref/get_auxdata.html) to avoid recompiling the regular
|
||||||
// expression multiple times within one query.
|
// expression multiple times within one query.
|
||||||
fn regexp_with_auxilliary(ctx: &Context<'_>) -> Result<bool> {
|
fn regexp_with_auxiliary(ctx: &Context<'_>) -> Result<bool> {
|
||||||
assert_eq!(ctx.len(), 2, "called with unexpected number of arguments");
|
assert_eq!(ctx.len(), 2, "called with unexpected number of arguments");
|
||||||
type BoxError = Box<dyn std::error::Error + Send + Sync + 'static>;
|
type BoxError = Box<dyn std::error::Error + Send + Sync + 'static>;
|
||||||
let regexp: std::sync::Arc<Regex> = ctx
|
let regexp: std::sync::Arc<Regex> = ctx
|
||||||
@ -868,7 +860,7 @@ mod test {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_function_regexp_with_auxilliary() -> Result<()> {
|
fn test_function_regexp_with_auxiliary() -> Result<()> {
|
||||||
let db = Connection::open_in_memory()?;
|
let db = Connection::open_in_memory()?;
|
||||||
db.execute_batch(
|
db.execute_batch(
|
||||||
"BEGIN;
|
"BEGIN;
|
||||||
@ -882,7 +874,7 @@ mod test {
|
|||||||
"regexp",
|
"regexp",
|
||||||
2,
|
2,
|
||||||
FunctionFlags::SQLITE_UTF8 | FunctionFlags::SQLITE_DETERMINISTIC,
|
FunctionFlags::SQLITE_UTF8 | FunctionFlags::SQLITE_DETERMINISTIC,
|
||||||
regexp_with_auxilliary,
|
regexp_with_auxiliary,
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
let result: bool = db.one_column("SELECT regexp('l.s[aeiouy]', 'lisa')")?;
|
let result: bool = db.one_column("SELECT regexp('l.s[aeiouy]', 'lisa')")?;
|
||||||
|
@ -656,7 +656,7 @@ unsafe fn free_boxed_hook<F>(p: *mut c_void) {
|
|||||||
|
|
||||||
unsafe fn expect_utf8<'a>(p_str: *const c_char, description: &'static str) -> &'a str {
|
unsafe fn expect_utf8<'a>(p_str: *const c_char, description: &'static str) -> &'a str {
|
||||||
expect_optional_utf8(p_str, description)
|
expect_optional_utf8(p_str, description)
|
||||||
.unwrap_or_else(|| panic!("received empty {}", description))
|
.unwrap_or_else(|| panic!("received empty {description}"))
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe fn expect_optional_utf8<'a>(
|
unsafe fn expect_optional_utf8<'a>(
|
||||||
@ -667,7 +667,7 @@ unsafe fn expect_optional_utf8<'a>(
|
|||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
std::str::from_utf8(std::ffi::CStr::from_ptr(p_str).to_bytes())
|
std::str::from_utf8(std::ffi::CStr::from_ptr(p_str).to_bytes())
|
||||||
.unwrap_or_else(|_| panic!("received non-utf8 string as {}", description))
|
.unwrap_or_else(|_| panic!("received non-utf8 string as {description}"))
|
||||||
.into()
|
.into()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -9,7 +9,7 @@ use std::sync::{Arc, Mutex};
|
|||||||
|
|
||||||
use super::ffi;
|
use super::ffi;
|
||||||
use super::str_for_sqlite;
|
use super::str_for_sqlite;
|
||||||
use super::{Connection, InterruptHandle, OpenFlags, Result};
|
use super::{Connection, InterruptHandle, OpenFlags, PrepFlags, Result};
|
||||||
use crate::error::{error_from_handle, error_from_sqlite_code, error_with_offset, Error};
|
use crate::error::{error_from_handle, error_from_sqlite_code, error_with_offset, Error};
|
||||||
use crate::raw_statement::RawStatement;
|
use crate::raw_statement::RawStatement;
|
||||||
use crate::statement::Statement;
|
use crate::statement::Statement;
|
||||||
@ -218,33 +218,24 @@ impl InnerConnection {
|
|||||||
unsafe { ffi::sqlite3_last_insert_rowid(self.db()) }
|
unsafe { ffi::sqlite3_last_insert_rowid(self.db()) }
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn prepare<'a>(&mut self, conn: &'a Connection, sql: &str) -> Result<Statement<'a>> {
|
pub fn prepare<'a>(
|
||||||
let mut c_stmt = ptr::null_mut();
|
&mut self,
|
||||||
|
conn: &'a Connection,
|
||||||
|
sql: &str,
|
||||||
|
flags: PrepFlags,
|
||||||
|
) -> Result<Statement<'a>> {
|
||||||
|
let mut c_stmt: *mut ffi::sqlite3_stmt = ptr::null_mut();
|
||||||
let (c_sql, len, _) = str_for_sqlite(sql.as_bytes())?;
|
let (c_sql, len, _) = str_for_sqlite(sql.as_bytes())?;
|
||||||
let mut c_tail = ptr::null();
|
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
|
// TODO sqlite3_prepare_v3 (https://sqlite.org/c3ref/c_prepare_normalize.html) // 3.20.0, #728
|
||||||
#[cfg(not(feature = "unlock_notify"))]
|
#[cfg(not(feature = "unlock_notify"))]
|
||||||
let r = unsafe {
|
let r = unsafe { self.prepare_(c_sql, len, flags, &mut c_stmt, &mut c_tail) };
|
||||||
ffi::sqlite3_prepare_v2(
|
|
||||||
self.db(),
|
|
||||||
c_sql,
|
|
||||||
len,
|
|
||||||
&mut c_stmt as *mut *mut ffi::sqlite3_stmt,
|
|
||||||
&mut c_tail as *mut *const c_char,
|
|
||||||
)
|
|
||||||
};
|
|
||||||
#[cfg(feature = "unlock_notify")]
|
#[cfg(feature = "unlock_notify")]
|
||||||
let r = unsafe {
|
let r = unsafe {
|
||||||
use crate::unlock_notify;
|
use crate::unlock_notify;
|
||||||
let mut rc;
|
let mut rc;
|
||||||
loop {
|
loop {
|
||||||
rc = ffi::sqlite3_prepare_v2(
|
rc = self.prepare_(c_sql, len, flags, &mut c_stmt, &mut c_tail);
|
||||||
self.db(),
|
|
||||||
c_sql,
|
|
||||||
len,
|
|
||||||
&mut c_stmt as *mut *mut ffi::sqlite3_stmt,
|
|
||||||
&mut c_tail as *mut *const c_char,
|
|
||||||
);
|
|
||||||
if !unlock_notify::is_locked(self.db, rc) {
|
if !unlock_notify::is_locked(self.db, rc) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -261,8 +252,6 @@ impl InnerConnection {
|
|||||||
}
|
}
|
||||||
// If the input text contains no SQL (if the input is an empty string or a
|
// If the input text contains no SQL (if the input is an empty string or a
|
||||||
// comment) then *ppStmt is set to NULL.
|
// comment) then *ppStmt is set to NULL.
|
||||||
let c_stmt: *mut ffi::sqlite3_stmt = c_stmt;
|
|
||||||
let c_tail: *const c_char = c_tail;
|
|
||||||
let tail = if c_tail.is_null() {
|
let tail = if c_tail.is_null() {
|
||||||
0
|
0
|
||||||
} else {
|
} else {
|
||||||
@ -278,6 +267,32 @@ impl InnerConnection {
|
|||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
#[cfg(not(feature = "modern_sqlite"))]
|
||||||
|
unsafe fn prepare_(
|
||||||
|
&self,
|
||||||
|
z_sql: *const c_char,
|
||||||
|
n_byte: c_int,
|
||||||
|
_: PrepFlags,
|
||||||
|
pp_stmt: *mut *mut ffi::sqlite3_stmt,
|
||||||
|
pz_tail: *mut *const c_char,
|
||||||
|
) -> c_int {
|
||||||
|
ffi::sqlite3_prepare_v2(self.db(), z_sql, n_byte, pp_stmt, pz_tail)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
#[cfg(feature = "modern_sqlite")]
|
||||||
|
unsafe fn prepare_(
|
||||||
|
&self,
|
||||||
|
z_sql: *const c_char,
|
||||||
|
n_byte: c_int,
|
||||||
|
flags: PrepFlags,
|
||||||
|
pp_stmt: *mut *mut ffi::sqlite3_stmt,
|
||||||
|
pz_tail: *mut *const c_char,
|
||||||
|
) -> c_int {
|
||||||
|
ffi::sqlite3_prepare_v3(self.db(), z_sql, n_byte, flags.bits(), pp_stmt, pz_tail)
|
||||||
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn changes(&self) -> u64 {
|
pub fn changes(&self) -> u64 {
|
||||||
#[cfg(not(feature = "modern_sqlite"))]
|
#[cfg(not(feature = "modern_sqlite"))]
|
||||||
@ -382,7 +397,7 @@ pub static BYPASS_SQLITE_INIT: AtomicBool = AtomicBool::new(false);
|
|||||||
|
|
||||||
// threading mode checks are not necessary (and do not work) on target
|
// threading mode checks are not necessary (and do not work) on target
|
||||||
// platforms that do not have threading (such as webassembly)
|
// platforms that do not have threading (such as webassembly)
|
||||||
#[cfg(any(target_arch = "wasm32"))]
|
#[cfg(target_arch = "wasm32")]
|
||||||
fn ensure_safe_sqlite_threading_mode() -> Result<()> {
|
fn ensure_safe_sqlite_threading_mode() -> Result<()> {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
76
src/lib.rs
76
src/lib.rs
@ -75,7 +75,7 @@ use crate::types::ValueRef;
|
|||||||
|
|
||||||
pub use crate::cache::CachedStatement;
|
pub use crate::cache::CachedStatement;
|
||||||
pub use crate::column::Column;
|
pub use crate::column::Column;
|
||||||
pub use crate::error::Error;
|
pub use crate::error::{to_sqlite_error, Error};
|
||||||
pub use crate::ffi::ErrorCode;
|
pub use crate::ffi::ErrorCode;
|
||||||
#[cfg(feature = "load_extension")]
|
#[cfg(feature = "load_extension")]
|
||||||
pub use crate::load_extension_guard::LoadExtensionGuard;
|
pub use crate::load_extension_guard::LoadExtensionGuard;
|
||||||
@ -122,6 +122,9 @@ mod params;
|
|||||||
mod pragma;
|
mod pragma;
|
||||||
mod raw_statement;
|
mod raw_statement;
|
||||||
mod row;
|
mod row;
|
||||||
|
#[cfg(feature = "serialize")]
|
||||||
|
#[cfg_attr(docsrs, doc(cfg(feature = "serialize")))]
|
||||||
|
pub mod serialize;
|
||||||
#[cfg(feature = "session")]
|
#[cfg(feature = "session")]
|
||||||
#[cfg_attr(docsrs, doc(cfg(feature = "session")))]
|
#[cfg_attr(docsrs, doc(cfg(feature = "session")))]
|
||||||
pub mod session;
|
pub mod session;
|
||||||
@ -759,7 +762,18 @@ impl Connection {
|
|||||||
/// or if the underlying SQLite call fails.
|
/// or if the underlying SQLite call fails.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn prepare(&self, sql: &str) -> Result<Statement<'_>> {
|
pub fn prepare(&self, sql: &str) -> Result<Statement<'_>> {
|
||||||
self.db.borrow_mut().prepare(self, sql)
|
self.prepare_with_flags(sql, PrepFlags::default())
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Prepare a SQL statement for execution.
|
||||||
|
///
|
||||||
|
/// # Failure
|
||||||
|
///
|
||||||
|
/// Will return `Err` if `sql` cannot be converted to a C-compatible string
|
||||||
|
/// or if the underlying SQLite call fails.
|
||||||
|
#[inline]
|
||||||
|
pub fn prepare_with_flags(&self, sql: &str, flags: PrepFlags) -> Result<Statement<'_>> {
|
||||||
|
self.db.borrow_mut().prepare(self, sql, flags)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Close the SQLite connection.
|
/// Close the SQLite connection.
|
||||||
@ -1073,7 +1087,7 @@ impl<'conn> Iterator for Batch<'conn, '_> {
|
|||||||
|
|
||||||
bitflags::bitflags! {
|
bitflags::bitflags! {
|
||||||
/// Flags for opening SQLite database connections. See
|
/// Flags for opening SQLite database connections. See
|
||||||
/// [sqlite3_open_v2](http://www.sqlite.org/c3ref/open.html) for details.
|
/// [sqlite3_open_v2](https://www.sqlite.org/c3ref/open.html) for details.
|
||||||
///
|
///
|
||||||
/// The default open flags are `SQLITE_OPEN_READ_WRITE | SQLITE_OPEN_CREATE
|
/// The default open flags are `SQLITE_OPEN_READ_WRITE | SQLITE_OPEN_CREATE
|
||||||
/// | SQLITE_OPEN_URI | SQLITE_OPEN_NO_MUTEX`. See [`Connection::open`] for
|
/// | SQLITE_OPEN_URI | SQLITE_OPEN_NO_MUTEX`. See [`Connection::open`] for
|
||||||
@ -1155,6 +1169,19 @@ impl Default for OpenFlags {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bitflags::bitflags! {
|
||||||
|
/// Prepare flags. See
|
||||||
|
/// [sqlite3_prepare_v3](https://sqlite.org/c3ref/c_prepare_normalize.html) for details.
|
||||||
|
#[derive(Clone, Copy, Debug, Default, Eq, Hash, PartialEq)]
|
||||||
|
#[repr(C)]
|
||||||
|
pub struct PrepFlags: ::std::os::raw::c_uint {
|
||||||
|
/// A hint to the query planner that the prepared statement will be retained for a long time and probably reused many times.
|
||||||
|
const SQLITE_PREPARE_PERSISTENT = 0x01;
|
||||||
|
/// Causes the SQL compiler to return an error (error code SQLITE_ERROR) if the statement uses any virtual tables.
|
||||||
|
const SQLITE_PREPARE_NO_VTAB = 0x04;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// rusqlite's check for a safe SQLite threading mode requires SQLite 3.7.0 or
|
/// rusqlite's check for a safe SQLite threading mode requires SQLite 3.7.0 or
|
||||||
/// later. If you are running against a SQLite older than that, rusqlite
|
/// later. If you are running against a SQLite older than that, rusqlite
|
||||||
/// attempts to ensure safety by performing configuration and initialization of
|
/// attempts to ensure safety by performing configuration and initialization of
|
||||||
@ -1211,13 +1238,21 @@ mod test {
|
|||||||
// this function is never called, but is still type checked; in
|
// this function is never called, but is still type checked; in
|
||||||
// particular, calls with specific instantiations will require
|
// particular, calls with specific instantiations will require
|
||||||
// that those types are `Send`.
|
// that those types are `Send`.
|
||||||
#[allow(dead_code, unconditional_recursion)]
|
#[allow(
|
||||||
|
dead_code,
|
||||||
|
unconditional_recursion,
|
||||||
|
clippy::extra_unused_type_parameters
|
||||||
|
)]
|
||||||
fn ensure_send<T: Send>() {
|
fn ensure_send<T: Send>() {
|
||||||
ensure_send::<Connection>();
|
ensure_send::<Connection>();
|
||||||
ensure_send::<InterruptHandle>();
|
ensure_send::<InterruptHandle>();
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(dead_code, unconditional_recursion)]
|
#[allow(
|
||||||
|
dead_code,
|
||||||
|
unconditional_recursion,
|
||||||
|
clippy::extra_unused_type_parameters
|
||||||
|
)]
|
||||||
fn ensure_sync<T: Sync>() {
|
fn ensure_sync<T: Sync>() {
|
||||||
ensure_sync::<InterruptHandle>();
|
ensure_sync::<InterruptHandle>();
|
||||||
}
|
}
|
||||||
@ -1323,9 +1358,7 @@ mod test {
|
|||||||
assert_eq!(ffi::SQLITE_CANTOPEN, e.extended_code);
|
assert_eq!(ffi::SQLITE_CANTOPEN, e.extended_code);
|
||||||
assert!(
|
assert!(
|
||||||
msg.contains(filename),
|
msg.contains(filename),
|
||||||
"error message '{}' does not contain '{}'",
|
"error message '{msg}' does not contain '{filename}'"
|
||||||
msg,
|
|
||||||
filename
|
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
panic!("SqliteFailure expected");
|
panic!("SqliteFailure expected");
|
||||||
@ -1453,8 +1486,7 @@ mod test {
|
|||||||
assert_eq!(
|
assert_eq!(
|
||||||
err,
|
err,
|
||||||
Error::ExecuteReturnedResults,
|
Error::ExecuteReturnedResults,
|
||||||
"Unexpected error: {}",
|
"Unexpected error: {err}"
|
||||||
err
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1470,7 +1502,7 @@ mod test {
|
|||||||
.unwrap_err();
|
.unwrap_err();
|
||||||
match err {
|
match err {
|
||||||
Error::MultipleStatement => (),
|
Error::MultipleStatement => (),
|
||||||
_ => panic!("Unexpected error: {}", err),
|
_ => panic!("Unexpected error: {err}"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1581,7 +1613,7 @@ mod test {
|
|||||||
let result: Result<i64> = db.one_column("SELECT x FROM foo WHERE x > 5");
|
let result: Result<i64> = db.one_column("SELECT x FROM foo WHERE x > 5");
|
||||||
match result.unwrap_err() {
|
match result.unwrap_err() {
|
||||||
Error::QueryReturnedNoRows => (),
|
Error::QueryReturnedNoRows => (),
|
||||||
err => panic!("Unexpected error {}", err),
|
err => panic!("Unexpected error {err}"),
|
||||||
}
|
}
|
||||||
|
|
||||||
let bad_query_result = db.query_row("NOT A PROPER QUERY; test123", [], |_| Ok(()));
|
let bad_query_result = db.query_row("NOT A PROPER QUERY; test123", [], |_| Ok(()));
|
||||||
@ -1633,7 +1665,7 @@ mod test {
|
|||||||
// > MEMORY or OFF and can not be changed to a different value. An
|
// > MEMORY or OFF and can not be changed to a different value. An
|
||||||
// > attempt to change the journal_mode of an in-memory database to
|
// > attempt to change the journal_mode of an in-memory database to
|
||||||
// > any setting other than MEMORY or OFF is ignored.
|
// > any setting other than MEMORY or OFF is ignored.
|
||||||
assert!(mode == "memory" || mode == "off", "Got mode {:?}", mode);
|
assert!(mode == "memory" || mode == "off", "Got mode {mode:?}");
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
@ -1720,7 +1752,7 @@ mod test {
|
|||||||
assert_eq!(err.code, ErrorCode::ConstraintViolation);
|
assert_eq!(err.code, ErrorCode::ConstraintViolation);
|
||||||
check_extended_code(err.extended_code);
|
check_extended_code(err.extended_code);
|
||||||
}
|
}
|
||||||
err => panic!("Unexpected error {}", err),
|
err => panic!("Unexpected error {err}"),
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
@ -1912,7 +1944,7 @@ mod test {
|
|||||||
|
|
||||||
match bad_type.unwrap_err() {
|
match bad_type.unwrap_err() {
|
||||||
Error::InvalidColumnType(..) => (),
|
Error::InvalidColumnType(..) => (),
|
||||||
err => panic!("Unexpected error {}", err),
|
err => panic!("Unexpected error {err}"),
|
||||||
}
|
}
|
||||||
|
|
||||||
let bad_idx: Result<Vec<String>> =
|
let bad_idx: Result<Vec<String>> =
|
||||||
@ -1920,7 +1952,7 @@ mod test {
|
|||||||
|
|
||||||
match bad_idx.unwrap_err() {
|
match bad_idx.unwrap_err() {
|
||||||
Error::InvalidColumnIndex(_) => (),
|
Error::InvalidColumnIndex(_) => (),
|
||||||
err => panic!("Unexpected error {}", err),
|
err => panic!("Unexpected error {err}"),
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
@ -1965,7 +1997,7 @@ mod test {
|
|||||||
|
|
||||||
match bad_type.unwrap_err() {
|
match bad_type.unwrap_err() {
|
||||||
CustomError::Sqlite(Error::InvalidColumnType(..)) => (),
|
CustomError::Sqlite(Error::InvalidColumnType(..)) => (),
|
||||||
err => panic!("Unexpected error {}", err),
|
err => panic!("Unexpected error {err}"),
|
||||||
}
|
}
|
||||||
|
|
||||||
let bad_idx: CustomResult<Vec<String>> = query
|
let bad_idx: CustomResult<Vec<String>> = query
|
||||||
@ -1974,7 +2006,7 @@ mod test {
|
|||||||
|
|
||||||
match bad_idx.unwrap_err() {
|
match bad_idx.unwrap_err() {
|
||||||
CustomError::Sqlite(Error::InvalidColumnIndex(_)) => (),
|
CustomError::Sqlite(Error::InvalidColumnIndex(_)) => (),
|
||||||
err => panic!("Unexpected error {}", err),
|
err => panic!("Unexpected error {err}"),
|
||||||
}
|
}
|
||||||
|
|
||||||
let non_sqlite_err: CustomResult<Vec<String>> = query
|
let non_sqlite_err: CustomResult<Vec<String>> = query
|
||||||
@ -1983,7 +2015,7 @@ mod test {
|
|||||||
|
|
||||||
match non_sqlite_err.unwrap_err() {
|
match non_sqlite_err.unwrap_err() {
|
||||||
CustomError::SomeError => (),
|
CustomError::SomeError => (),
|
||||||
err => panic!("Unexpected error {}", err),
|
err => panic!("Unexpected error {err}"),
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
@ -2020,7 +2052,7 @@ mod test {
|
|||||||
|
|
||||||
match bad_type.unwrap_err() {
|
match bad_type.unwrap_err() {
|
||||||
CustomError::Sqlite(Error::InvalidColumnType(..)) => (),
|
CustomError::Sqlite(Error::InvalidColumnType(..)) => (),
|
||||||
err => panic!("Unexpected error {}", err),
|
err => panic!("Unexpected error {err}"),
|
||||||
}
|
}
|
||||||
|
|
||||||
let bad_idx: CustomResult<String> =
|
let bad_idx: CustomResult<String> =
|
||||||
@ -2028,7 +2060,7 @@ mod test {
|
|||||||
|
|
||||||
match bad_idx.unwrap_err() {
|
match bad_idx.unwrap_err() {
|
||||||
CustomError::Sqlite(Error::InvalidColumnIndex(_)) => (),
|
CustomError::Sqlite(Error::InvalidColumnIndex(_)) => (),
|
||||||
err => panic!("Unexpected error {}", err),
|
err => panic!("Unexpected error {err}"),
|
||||||
}
|
}
|
||||||
|
|
||||||
let non_sqlite_err: CustomResult<String> =
|
let non_sqlite_err: CustomResult<String> =
|
||||||
@ -2036,7 +2068,7 @@ mod test {
|
|||||||
|
|
||||||
match non_sqlite_err.unwrap_err() {
|
match non_sqlite_err.unwrap_err() {
|
||||||
CustomError::SomeError => (),
|
CustomError::SomeError => (),
|
||||||
err => panic!("Unexpected error {}", err),
|
err => panic!("Unexpected error {err}"),
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
@ -405,18 +405,17 @@ mod test {
|
|||||||
db.pragma_update_and_check(None, "journal_mode", "OFF", |row| row.get(0))?;
|
db.pragma_update_and_check(None, "journal_mode", "OFF", |row| row.get(0))?;
|
||||||
assert!(
|
assert!(
|
||||||
journal_mode == "off" || journal_mode == "memory",
|
journal_mode == "off" || journal_mode == "memory",
|
||||||
"mode: {:?}",
|
"mode: {journal_mode:?}"
|
||||||
journal_mode,
|
|
||||||
);
|
);
|
||||||
// Sanity checks to ensure the move to a generic `ToSql` wasn't breaking
|
// Sanity checks to ensure the move to a generic `ToSql` wasn't breaking
|
||||||
let mode =
|
let mode =
|
||||||
db.pragma_update_and_check(None, "journal_mode", "OFF", |row| row.get::<_, String>(0))?;
|
db.pragma_update_and_check(None, "journal_mode", "OFF", |row| row.get::<_, String>(0))?;
|
||||||
assert!(mode == "off" || mode == "memory", "mode: {:?}", mode);
|
assert!(mode == "off" || mode == "memory", "mode: {mode:?}");
|
||||||
|
|
||||||
let param: &dyn crate::ToSql = &"OFF";
|
let param: &dyn crate::ToSql = &"OFF";
|
||||||
let mode =
|
let mode =
|
||||||
db.pragma_update_and_check(None, "journal_mode", param, |row| row.get::<_, String>(0))?;
|
db.pragma_update_and_check(None, "journal_mode", param, |row| row.get::<_, String>(0))?;
|
||||||
assert!(mode == "off" || mode == "memory", "mode: {:?}", mode);
|
assert!(mode == "off" || mode == "memory", "mode: {mode:?}");
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -257,6 +257,7 @@ impl<'stmt> Row<'stmt> {
|
|||||||
/// * If the underlying SQLite integral value is outside the range
|
/// * If the underlying SQLite integral value is outside the range
|
||||||
/// representable by `T`
|
/// representable by `T`
|
||||||
/// * If `idx` is outside the range of columns in the returned query
|
/// * If `idx` is outside the range of columns in the returned query
|
||||||
|
#[track_caller]
|
||||||
pub fn get_unwrap<I: RowIndex, T: FromSql>(&self, idx: I) -> T {
|
pub fn get_unwrap<I: RowIndex, T: FromSql>(&self, idx: I) -> T {
|
||||||
self.get(idx).unwrap()
|
self.get(idx).unwrap()
|
||||||
}
|
}
|
||||||
@ -277,6 +278,7 @@ impl<'stmt> Row<'stmt> {
|
|||||||
/// If the result type is i128 (which requires the `i128_blob` feature to be
|
/// If the result type is i128 (which requires the `i128_blob` feature to be
|
||||||
/// enabled), and the underlying SQLite column is a blob whose size is not
|
/// enabled), and the underlying SQLite column is a blob whose size is not
|
||||||
/// 16 bytes, `Error::InvalidColumnType` will also be returned.
|
/// 16 bytes, `Error::InvalidColumnType` will also be returned.
|
||||||
|
#[track_caller]
|
||||||
pub fn get<I: RowIndex, T: FromSql>(&self, idx: I) -> Result<T> {
|
pub fn get<I: RowIndex, T: FromSql>(&self, idx: I) -> Result<T> {
|
||||||
let idx = idx.idx(self.stmt)?;
|
let idx = idx.idx(self.stmt)?;
|
||||||
let value = self.stmt.value_ref(idx);
|
let value = self.stmt.value_ref(idx);
|
||||||
@ -335,6 +337,7 @@ impl<'stmt> Row<'stmt> {
|
|||||||
///
|
///
|
||||||
/// * If `idx` is outside the range of columns in the returned query.
|
/// * If `idx` is outside the range of columns in the returned query.
|
||||||
/// * If `idx` is not a valid column name for this row.
|
/// * If `idx` is not a valid column name for this row.
|
||||||
|
#[track_caller]
|
||||||
pub fn get_ref_unwrap<I: RowIndex>(&self, idx: I) -> ValueRef<'_> {
|
pub fn get_ref_unwrap<I: RowIndex>(&self, idx: I) -> ValueRef<'_> {
|
||||||
self.get_ref(idx).unwrap()
|
self.get_ref(idx).unwrap()
|
||||||
}
|
}
|
||||||
|
162
src/serialize.rs
Normal file
162
src/serialize.rs
Normal file
@ -0,0 +1,162 @@
|
|||||||
|
//! Serialize a database.
|
||||||
|
use std::convert::TryInto;
|
||||||
|
use std::marker::PhantomData;
|
||||||
|
use std::ops::Deref;
|
||||||
|
use std::ptr::NonNull;
|
||||||
|
|
||||||
|
use crate::error::error_from_handle;
|
||||||
|
use crate::ffi;
|
||||||
|
use crate::{Connection, DatabaseName, Result};
|
||||||
|
|
||||||
|
/// Shared (SQLITE_SERIALIZE_NOCOPY) serialized database
|
||||||
|
pub struct SharedData<'conn> {
|
||||||
|
phantom: PhantomData<&'conn Connection>,
|
||||||
|
ptr: NonNull<u8>,
|
||||||
|
sz: usize,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Owned serialized database
|
||||||
|
pub struct OwnedData {
|
||||||
|
ptr: NonNull<u8>,
|
||||||
|
sz: usize,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl OwnedData {
|
||||||
|
/// SAFETY: Caller must be certain that `ptr` is allocated by
|
||||||
|
/// `sqlite3_malloc`.
|
||||||
|
pub unsafe fn from_raw_nonnull(ptr: NonNull<u8>, sz: usize) -> Self {
|
||||||
|
Self { ptr, sz }
|
||||||
|
}
|
||||||
|
|
||||||
|
fn into_raw(self) -> (*mut u8, usize) {
|
||||||
|
let raw = (self.ptr.as_ptr(), self.sz);
|
||||||
|
std::mem::forget(self);
|
||||||
|
raw
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Drop for OwnedData {
|
||||||
|
fn drop(&mut self) {
|
||||||
|
unsafe {
|
||||||
|
ffi::sqlite3_free(self.ptr.as_ptr().cast());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Serialized database
|
||||||
|
pub enum Data<'conn> {
|
||||||
|
/// Shared (SQLITE_SERIALIZE_NOCOPY) serialized database
|
||||||
|
Shared(SharedData<'conn>),
|
||||||
|
/// Owned serialized database
|
||||||
|
Owned(OwnedData),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'conn> Deref for Data<'conn> {
|
||||||
|
type Target = [u8];
|
||||||
|
|
||||||
|
fn deref(&self) -> &[u8] {
|
||||||
|
let (ptr, sz) = match self {
|
||||||
|
Data::Owned(OwnedData { ptr, sz }) => (ptr.as_ptr(), *sz),
|
||||||
|
Data::Shared(SharedData { ptr, sz, .. }) => (ptr.as_ptr(), *sz),
|
||||||
|
};
|
||||||
|
unsafe { std::slice::from_raw_parts(ptr, sz) }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Connection {
|
||||||
|
/// Serialize a database.
|
||||||
|
pub fn serialize<'conn>(&'conn self, schema: DatabaseName<'_>) -> Result<Data<'conn>> {
|
||||||
|
let schema = schema.as_cstring()?;
|
||||||
|
let mut sz = 0;
|
||||||
|
let mut ptr: *mut u8 = unsafe {
|
||||||
|
ffi::sqlite3_serialize(
|
||||||
|
self.handle(),
|
||||||
|
schema.as_ptr(),
|
||||||
|
&mut sz,
|
||||||
|
ffi::SQLITE_SERIALIZE_NOCOPY,
|
||||||
|
)
|
||||||
|
};
|
||||||
|
Ok(if ptr.is_null() {
|
||||||
|
ptr = unsafe { ffi::sqlite3_serialize(self.handle(), schema.as_ptr(), &mut sz, 0) };
|
||||||
|
if ptr.is_null() {
|
||||||
|
return Err(unsafe { error_from_handle(self.handle(), ffi::SQLITE_NOMEM) });
|
||||||
|
}
|
||||||
|
Data::Owned(OwnedData {
|
||||||
|
ptr: NonNull::new(ptr).unwrap(),
|
||||||
|
sz: sz.try_into().unwrap(),
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
// shared buffer
|
||||||
|
Data::Shared(SharedData {
|
||||||
|
ptr: NonNull::new(ptr).unwrap(),
|
||||||
|
sz: sz.try_into().unwrap(),
|
||||||
|
phantom: PhantomData,
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Deserialize a database.
|
||||||
|
pub fn deserialize(
|
||||||
|
&mut self,
|
||||||
|
schema: DatabaseName<'_>,
|
||||||
|
data: OwnedData,
|
||||||
|
read_only: bool,
|
||||||
|
) -> Result<()> {
|
||||||
|
let schema = schema.as_cstring()?;
|
||||||
|
let (data, sz) = data.into_raw();
|
||||||
|
let sz = sz.try_into().unwrap();
|
||||||
|
let flags = if read_only {
|
||||||
|
ffi::SQLITE_DESERIALIZE_FREEONCLOSE | ffi::SQLITE_DESERIALIZE_READONLY
|
||||||
|
} else {
|
||||||
|
ffi::SQLITE_DESERIALIZE_FREEONCLOSE | ffi::SQLITE_DESERIALIZE_RESIZEABLE
|
||||||
|
};
|
||||||
|
let rc = unsafe {
|
||||||
|
ffi::sqlite3_deserialize(self.handle(), schema.as_ptr(), data, sz, sz, flags)
|
||||||
|
};
|
||||||
|
if rc != ffi::SQLITE_OK {
|
||||||
|
// TODO sqlite3_free(data) ?
|
||||||
|
return Err(unsafe { error_from_handle(self.handle(), rc) });
|
||||||
|
}
|
||||||
|
/* TODO
|
||||||
|
if let Some(mxSize) = mxSize {
|
||||||
|
unsafe {
|
||||||
|
ffi::sqlite3_file_control(
|
||||||
|
self.handle(),
|
||||||
|
schema.as_ptr(),
|
||||||
|
ffi::SQLITE_FCNTL_SIZE_LIMIT,
|
||||||
|
&mut mxSize,
|
||||||
|
)
|
||||||
|
};
|
||||||
|
}*/
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod test {
|
||||||
|
use super::*;
|
||||||
|
use crate::{Connection, DatabaseName, Result};
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn serialize() -> Result<()> {
|
||||||
|
let db = Connection::open_in_memory()?;
|
||||||
|
db.execute_batch("CREATE TABLE x AS SELECT 'data'")?;
|
||||||
|
let data = db.serialize(DatabaseName::Main)?;
|
||||||
|
let Data::Owned(data) = data else { panic!("expected OwnedData")};
|
||||||
|
assert!(data.sz > 0);
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn deserialize() -> Result<()> {
|
||||||
|
let src = Connection::open_in_memory()?;
|
||||||
|
src.execute_batch("CREATE TABLE x AS SELECT 'data'")?;
|
||||||
|
let data = src.serialize(DatabaseName::Main)?;
|
||||||
|
let Data::Owned(data) = data else { panic!("expected OwnedData")};
|
||||||
|
|
||||||
|
let mut dst = Connection::open_in_memory()?;
|
||||||
|
dst.deserialize(DatabaseName::Main, data, false)?;
|
||||||
|
dst.execute("DELETE FROM x", [])?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
@ -1081,12 +1081,12 @@ mod test {
|
|||||||
assert_eq!(stmt.insert([2i32])?, 2);
|
assert_eq!(stmt.insert([2i32])?, 2);
|
||||||
match stmt.insert([1i32]).unwrap_err() {
|
match stmt.insert([1i32]).unwrap_err() {
|
||||||
Error::StatementChangedRows(0) => (),
|
Error::StatementChangedRows(0) => (),
|
||||||
err => panic!("Unexpected error {}", err),
|
err => panic!("Unexpected error {err}"),
|
||||||
}
|
}
|
||||||
let mut multi = db.prepare("INSERT INTO foo (x) SELECT 3 UNION ALL SELECT 4")?;
|
let mut multi = db.prepare("INSERT INTO foo (x) SELECT 3 UNION ALL SELECT 4")?;
|
||||||
match multi.insert([]).unwrap_err() {
|
match multi.insert([]).unwrap_err() {
|
||||||
Error::StatementChangedRows(2) => (),
|
Error::StatementChangedRows(2) => (),
|
||||||
err => panic!("Unexpected error {}", err),
|
err => panic!("Unexpected error {err}"),
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
@ -1349,7 +1349,7 @@ mod test {
|
|||||||
assert_eq!(error.code, ErrorCode::Unknown);
|
assert_eq!(error.code, ErrorCode::Unknown);
|
||||||
assert_eq!(offset, 7);
|
assert_eq!(offset, 7);
|
||||||
}
|
}
|
||||||
err => panic!("Unexpected error {}", err),
|
err => panic!("Unexpected error {err}"),
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
@ -91,7 +91,6 @@ pub struct Transaction<'conn> {
|
|||||||
pub struct Savepoint<'conn> {
|
pub struct Savepoint<'conn> {
|
||||||
conn: &'conn Connection,
|
conn: &'conn Connection,
|
||||||
name: String,
|
name: String,
|
||||||
depth: u32,
|
|
||||||
drop_behavior: DropBehavior,
|
drop_behavior: DropBehavior,
|
||||||
committed: bool,
|
committed: bool,
|
||||||
}
|
}
|
||||||
@ -158,13 +157,13 @@ impl Transaction<'_> {
|
|||||||
/// ```
|
/// ```
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn savepoint(&mut self) -> Result<Savepoint<'_>> {
|
pub fn savepoint(&mut self) -> Result<Savepoint<'_>> {
|
||||||
Savepoint::with_depth(self.conn, 1)
|
Savepoint::new_(self.conn)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Create a new savepoint with a custom savepoint name. See `savepoint()`.
|
/// Create a new savepoint with a custom savepoint name. See `savepoint()`.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn savepoint_with_name<T: Into<String>>(&mut self, name: T) -> Result<Savepoint<'_>> {
|
pub fn savepoint_with_name<T: Into<String>>(&mut self, name: T) -> Result<Savepoint<'_>> {
|
||||||
Savepoint::with_depth_and_name(self.conn, 1, name)
|
Savepoint::with_name_(self.conn, name)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get the current setting for what happens to the transaction when it is
|
/// Get the current setting for what happens to the transaction when it is
|
||||||
@ -249,50 +248,44 @@ impl Drop for Transaction<'_> {
|
|||||||
|
|
||||||
impl Savepoint<'_> {
|
impl Savepoint<'_> {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn with_depth_and_name<T: Into<String>>(
|
fn with_name_<T: Into<String>>(conn: &Connection, name: T) -> Result<Savepoint<'_>> {
|
||||||
conn: &Connection,
|
|
||||||
depth: u32,
|
|
||||||
name: T,
|
|
||||||
) -> Result<Savepoint<'_>> {
|
|
||||||
let name = name.into();
|
let name = name.into();
|
||||||
conn.execute_batch(&format!("SAVEPOINT {name}"))
|
conn.execute_batch(&format!("SAVEPOINT {name}"))
|
||||||
.map(|_| Savepoint {
|
.map(|_| Savepoint {
|
||||||
conn,
|
conn,
|
||||||
name,
|
name,
|
||||||
depth,
|
|
||||||
drop_behavior: DropBehavior::Rollback,
|
drop_behavior: DropBehavior::Rollback,
|
||||||
committed: false,
|
committed: false,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn with_depth(conn: &Connection, depth: u32) -> Result<Savepoint<'_>> {
|
fn new_(conn: &Connection) -> Result<Savepoint<'_>> {
|
||||||
let name = format!("_rusqlite_sp_{depth}");
|
Savepoint::with_name_(conn, "_rusqlite_sp")
|
||||||
Savepoint::with_depth_and_name(conn, depth, name)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Begin a new savepoint. Can be nested.
|
/// Begin a new savepoint. Can be nested.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn new(conn: &mut Connection) -> Result<Savepoint<'_>> {
|
pub fn new(conn: &mut Connection) -> Result<Savepoint<'_>> {
|
||||||
Savepoint::with_depth(conn, 0)
|
Savepoint::new_(conn)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Begin a new savepoint with a user-provided savepoint name.
|
/// Begin a new savepoint with a user-provided savepoint name.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn with_name<T: Into<String>>(conn: &mut Connection, name: T) -> Result<Savepoint<'_>> {
|
pub fn with_name<T: Into<String>>(conn: &mut Connection, name: T) -> Result<Savepoint<'_>> {
|
||||||
Savepoint::with_depth_and_name(conn, 0, name)
|
Savepoint::with_name_(conn, name)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Begin a nested savepoint.
|
/// Begin a nested savepoint.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn savepoint(&mut self) -> Result<Savepoint<'_>> {
|
pub fn savepoint(&mut self) -> Result<Savepoint<'_>> {
|
||||||
Savepoint::with_depth(self.conn, self.depth + 1)
|
Savepoint::new_(self.conn)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Begin a nested savepoint with a user-provided savepoint name.
|
/// Begin a nested savepoint with a user-provided savepoint name.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn savepoint_with_name<T: Into<String>>(&mut self, name: T) -> Result<Savepoint<'_>> {
|
pub fn savepoint_with_name<T: Into<String>>(&mut self, name: T) -> Result<Savepoint<'_>> {
|
||||||
Savepoint::with_depth_and_name(self.conn, self.depth + 1, name)
|
Savepoint::with_name_(self.conn, name)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get the current setting for what happens to the savepoint when it is
|
/// Get the current setting for what happens to the savepoint when it is
|
||||||
@ -351,8 +344,10 @@ impl Savepoint<'_> {
|
|||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
match self.drop_behavior() {
|
match self.drop_behavior() {
|
||||||
DropBehavior::Commit => self.commit_().or_else(|_| self.rollback()),
|
DropBehavior::Commit => self
|
||||||
DropBehavior::Rollback => self.rollback(),
|
.commit_()
|
||||||
|
.or_else(|_| self.rollback().and_then(|_| self.commit_())),
|
||||||
|
DropBehavior::Rollback => self.rollback().and_then(|_| self.commit_()),
|
||||||
DropBehavior::Ignore => Ok(()),
|
DropBehavior::Ignore => Ok(()),
|
||||||
DropBehavior::Panic => panic!("Savepoint dropped unexpectedly."),
|
DropBehavior::Panic => panic!("Savepoint dropped unexpectedly."),
|
||||||
}
|
}
|
||||||
@ -563,7 +558,7 @@ mod test {
|
|||||||
assert_eq!(e.code, crate::ErrorCode::Unknown);
|
assert_eq!(e.code, crate::ErrorCode::Unknown);
|
||||||
assert!(m.contains("transaction"));
|
assert!(m.contains("transaction"));
|
||||||
} else {
|
} else {
|
||||||
panic!("Unexpected error type: {:?}", e);
|
panic!("Unexpected error type: {e:?}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -675,6 +670,40 @@ mod test {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_savepoint_drop_behavior_releases() -> Result<()> {
|
||||||
|
let mut db = checked_memory_handle()?;
|
||||||
|
|
||||||
|
{
|
||||||
|
let mut sp = db.savepoint()?;
|
||||||
|
sp.set_drop_behavior(DropBehavior::Commit);
|
||||||
|
}
|
||||||
|
assert!(db.is_autocommit());
|
||||||
|
{
|
||||||
|
let mut sp = db.savepoint()?;
|
||||||
|
sp.set_drop_behavior(DropBehavior::Rollback);
|
||||||
|
}
|
||||||
|
assert!(db.is_autocommit());
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_savepoint_release_error() -> Result<()> {
|
||||||
|
let mut db = checked_memory_handle()?;
|
||||||
|
|
||||||
|
db.pragma_update(None, "foreign_keys", true)?;
|
||||||
|
db.execute_batch("CREATE TABLE r(n INTEGER PRIMARY KEY NOT NULL); CREATE TABLE f(n REFERENCES r(n) DEFERRABLE INITIALLY DEFERRED);")?;
|
||||||
|
{
|
||||||
|
let mut sp = db.savepoint()?;
|
||||||
|
sp.execute("INSERT INTO f VALUES (0)", [])?;
|
||||||
|
sp.set_drop_behavior(DropBehavior::Commit);
|
||||||
|
}
|
||||||
|
assert!(db.is_autocommit());
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_savepoint_names() -> Result<()> {
|
fn test_savepoint_names() -> Result<()> {
|
||||||
let mut db = checked_memory_handle()?;
|
let mut db = checked_memory_handle()?;
|
||||||
|
@ -59,8 +59,7 @@ impl fmt::Display for FromSqlError {
|
|||||||
} => {
|
} => {
|
||||||
write!(
|
write!(
|
||||||
f,
|
f,
|
||||||
"Cannot read {} byte value out of {} byte blob",
|
"Cannot read {expected_size} byte value out of {blob_size} byte blob"
|
||||||
expected_size, blob_size
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
FromSqlError::Other(ref err) => err.fmt(f),
|
FromSqlError::Other(ref err) => err.fmt(f),
|
||||||
@ -96,6 +95,15 @@ macro_rules! from_sql_integral(
|
|||||||
i.try_into().map_err(|_| FromSqlError::OutOfRange(i))
|
i.try_into().map_err(|_| FromSqlError::OutOfRange(i))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
);
|
||||||
|
(non_zero $nz:ty, $z:ty) => (
|
||||||
|
impl FromSql for $nz {
|
||||||
|
#[inline]
|
||||||
|
fn column_result(value: ValueRef<'_>) -> FromSqlResult<Self> {
|
||||||
|
let i = <$z>::column_result(value)?;
|
||||||
|
<$nz>::new(i).ok_or(FromSqlError::OutOfRange(0))
|
||||||
|
}
|
||||||
|
}
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -110,6 +118,22 @@ from_sql_integral!(u32);
|
|||||||
from_sql_integral!(u64);
|
from_sql_integral!(u64);
|
||||||
from_sql_integral!(usize);
|
from_sql_integral!(usize);
|
||||||
|
|
||||||
|
from_sql_integral!(non_zero std::num::NonZeroIsize, isize);
|
||||||
|
from_sql_integral!(non_zero std::num::NonZeroI8, i8);
|
||||||
|
from_sql_integral!(non_zero std::num::NonZeroI16, i16);
|
||||||
|
from_sql_integral!(non_zero std::num::NonZeroI32, i32);
|
||||||
|
from_sql_integral!(non_zero std::num::NonZeroI64, i64);
|
||||||
|
#[cfg(feature = "i128_blob")]
|
||||||
|
#[cfg_attr(docsrs, doc(cfg(feature = "i128_blob")))]
|
||||||
|
from_sql_integral!(non_zero std::num::NonZeroI128, i128);
|
||||||
|
|
||||||
|
from_sql_integral!(non_zero std::num::NonZeroUsize, usize);
|
||||||
|
from_sql_integral!(non_zero std::num::NonZeroU8, u8);
|
||||||
|
from_sql_integral!(non_zero std::num::NonZeroU16, u16);
|
||||||
|
from_sql_integral!(non_zero std::num::NonZeroU32, u32);
|
||||||
|
from_sql_integral!(non_zero std::num::NonZeroU64, u64);
|
||||||
|
// std::num::NonZeroU128 is not supported since u128 isn't either
|
||||||
|
|
||||||
impl FromSql for i64 {
|
impl FromSql for i64 {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn column_result(value: ValueRef<'_>) -> FromSqlResult<Self> {
|
fn column_result(value: ValueRef<'_>) -> FromSqlResult<Self> {
|
||||||
@ -248,7 +272,7 @@ mod test {
|
|||||||
.unwrap_err();
|
.unwrap_err();
|
||||||
match err {
|
match err {
|
||||||
Error::IntegralValueOutOfRange(_, value) => assert_eq!(*n, value),
|
Error::IntegralValueOutOfRange(_, value) => assert_eq!(*n, value),
|
||||||
_ => panic!("unexpected error: {}", err),
|
_ => panic!("unexpected error: {err}"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for n in in_range {
|
for n in in_range {
|
||||||
@ -273,4 +297,70 @@ mod test {
|
|||||||
check_ranges::<u32>(&db, &[-2, -1, 4_294_967_296], &[0, 1, 4_294_967_295]);
|
check_ranges::<u32>(&db, &[-2, -1, 4_294_967_296], &[0, 1, 4_294_967_295]);
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_nonzero_ranges() -> Result<()> {
|
||||||
|
let db = Connection::open_in_memory()?;
|
||||||
|
|
||||||
|
macro_rules! check_ranges {
|
||||||
|
($nz:ty, $out_of_range:expr, $in_range:expr) => {
|
||||||
|
for &n in $out_of_range {
|
||||||
|
assert_eq!(
|
||||||
|
db.query_row("SELECT ?1", [n], |r| r.get::<_, $nz>(0)),
|
||||||
|
Err(Error::IntegralValueOutOfRange(0, n)),
|
||||||
|
"{}",
|
||||||
|
std::any::type_name::<$nz>()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
for &n in $in_range {
|
||||||
|
let non_zero = <$nz>::new(n).unwrap();
|
||||||
|
assert_eq!(
|
||||||
|
Ok(non_zero),
|
||||||
|
db.query_row("SELECT ?1", [non_zero], |r| r.get::<_, $nz>(0))
|
||||||
|
);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
check_ranges!(std::num::NonZeroI8, &[0, -129, 128], &[-128, 1, 127]);
|
||||||
|
check_ranges!(
|
||||||
|
std::num::NonZeroI16,
|
||||||
|
&[0, -32769, 32768],
|
||||||
|
&[-32768, -1, 1, 32767]
|
||||||
|
);
|
||||||
|
check_ranges!(
|
||||||
|
std::num::NonZeroI32,
|
||||||
|
&[0, -2_147_483_649, 2_147_483_648],
|
||||||
|
&[-2_147_483_648, -1, 1, 2_147_483_647]
|
||||||
|
);
|
||||||
|
check_ranges!(
|
||||||
|
std::num::NonZeroI64,
|
||||||
|
&[0],
|
||||||
|
&[-2_147_483_648, -1, 1, 2_147_483_647, i64::MAX, i64::MIN]
|
||||||
|
);
|
||||||
|
check_ranges!(
|
||||||
|
std::num::NonZeroIsize,
|
||||||
|
&[0],
|
||||||
|
&[-2_147_483_648, -1, 1, 2_147_483_647]
|
||||||
|
);
|
||||||
|
check_ranges!(std::num::NonZeroU8, &[0, -2, -1, 256], &[1, 255]);
|
||||||
|
check_ranges!(std::num::NonZeroU16, &[0, -2, -1, 65536], &[1, 65535]);
|
||||||
|
check_ranges!(
|
||||||
|
std::num::NonZeroU32,
|
||||||
|
&[0, -2, -1, 4_294_967_296],
|
||||||
|
&[1, 4_294_967_295]
|
||||||
|
);
|
||||||
|
check_ranges!(
|
||||||
|
std::num::NonZeroU64,
|
||||||
|
&[0, -2, -1, -4_294_967_296],
|
||||||
|
&[1, 4_294_967_295, i64::MAX as u64]
|
||||||
|
);
|
||||||
|
check_ranges!(
|
||||||
|
std::num::NonZeroUsize,
|
||||||
|
&[0, -2, -1, -4_294_967_296],
|
||||||
|
&[1, 4_294_967_295]
|
||||||
|
);
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -26,7 +26,8 @@
|
|||||||
//! [`ToSql`] always succeeds except when storing a `u64` or `usize` value that
|
//! [`ToSql`] always succeeds except when storing a `u64` or `usize` value that
|
||||||
//! cannot fit in an `INTEGER` (`i64`). Also note that SQLite ignores column
|
//! cannot fit in an `INTEGER` (`i64`). Also note that SQLite ignores column
|
||||||
//! types, so if you store an `i64` in a column with type `REAL` it will be
|
//! types, so if you store an `i64` in a column with type `REAL` it will be
|
||||||
//! stored as an `INTEGER`, not a `REAL`.
|
//! stored as an `INTEGER`, not a `REAL` (unless the column is part of a
|
||||||
|
//! [STRICT table](https://www.sqlite.org/stricttables.html)).
|
||||||
//!
|
//!
|
||||||
//! If the `time` feature is enabled, implementations are
|
//! If the `time` feature is enabled, implementations are
|
||||||
//! provided for `time::OffsetDateTime` that use the RFC 3339 date/time format,
|
//! provided for `time::OffsetDateTime` that use the RFC 3339 date/time format,
|
||||||
@ -210,10 +211,10 @@ mod test {
|
|||||||
fn test_option() -> Result<()> {
|
fn test_option() -> Result<()> {
|
||||||
let db = checked_memory_handle()?;
|
let db = checked_memory_handle()?;
|
||||||
|
|
||||||
let s = Some("hello, world!");
|
let s = "hello, world!";
|
||||||
let b = Some(vec![1u8, 2, 3, 4]);
|
let b = Some(vec![1u8, 2, 3, 4]);
|
||||||
|
|
||||||
db.execute("INSERT INTO foo(t) VALUES (?1)", [&s])?;
|
db.execute("INSERT INTO foo(t) VALUES (?1)", [Some(s)])?;
|
||||||
db.execute("INSERT INTO foo(b) VALUES (?1)", [&b])?;
|
db.execute("INSERT INTO foo(b) VALUES (?1)", [&b])?;
|
||||||
|
|
||||||
let mut stmt = db.prepare("SELECT t, b FROM foo ORDER BY ROWID ASC")?;
|
let mut stmt = db.prepare("SELECT t, b FROM foo ORDER BY ROWID ASC")?;
|
||||||
@ -223,7 +224,7 @@ mod test {
|
|||||||
let row1 = rows.next()?.unwrap();
|
let row1 = rows.next()?.unwrap();
|
||||||
let s1: Option<String> = row1.get_unwrap(0);
|
let s1: Option<String> = row1.get_unwrap(0);
|
||||||
let b1: Option<Vec<u8>> = row1.get_unwrap(1);
|
let b1: Option<Vec<u8>> = row1.get_unwrap(1);
|
||||||
assert_eq!(s.unwrap(), s1.unwrap());
|
assert_eq!(s, s1.unwrap());
|
||||||
assert!(b1.is_none());
|
assert!(b1.is_none());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -352,7 +353,7 @@ mod test {
|
|||||||
assert_eq!(Value::Integer(1), row.get::<_, Value>(2)?);
|
assert_eq!(Value::Integer(1), row.get::<_, Value>(2)?);
|
||||||
match row.get::<_, Value>(3)? {
|
match row.get::<_, Value>(3)? {
|
||||||
Value::Real(val) => assert!((1.5 - val).abs() < f64::EPSILON),
|
Value::Real(val) => assert!((1.5 - val).abs() < f64::EPSILON),
|
||||||
x => panic!("Invalid Value {:?}", x),
|
x => panic!("Invalid Value {x:?}"),
|
||||||
}
|
}
|
||||||
assert_eq!(Value::Null, row.get::<_, Value>(4)?);
|
assert_eq!(Value::Null, row.get::<_, Value>(4)?);
|
||||||
Ok(())
|
Ok(())
|
||||||
|
@ -1,81 +1,174 @@
|
|||||||
|
//! Convert formats 1-10 in [Time Values](https://sqlite.org/lang_datefunc.html#time_values) to time types.
|
||||||
//! [`ToSql`] and [`FromSql`] implementation for [`time::OffsetDateTime`].
|
//! [`ToSql`] and [`FromSql`] implementation for [`time::OffsetDateTime`].
|
||||||
|
//! [`ToSql`] and [`FromSql`] implementation for [`time::PrimitiveDateTime`].
|
||||||
|
//! [`ToSql`] and [`FromSql`] implementation for [`time::Date`].
|
||||||
|
//! [`ToSql`] and [`FromSql`] implementation for [`time::Time`].
|
||||||
|
//! Time Strings in:
|
||||||
|
//! - 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.
|
||||||
|
|
||||||
use crate::types::{FromSql, FromSqlError, FromSqlResult, ToSql, ToSqlOutput, ValueRef};
|
use crate::types::{FromSql, FromSqlError, FromSqlResult, ToSql, ToSqlOutput, ValueRef};
|
||||||
use crate::{Error, Result};
|
use crate::{Error, Result};
|
||||||
use time::format_description::well_known::Rfc3339;
|
|
||||||
use time::format_description::FormatItem;
|
use time::format_description::FormatItem;
|
||||||
use time::macros::format_description;
|
use time::macros::format_description;
|
||||||
use time::{OffsetDateTime, PrimitiveDateTime, UtcOffset};
|
use time::{Date, OffsetDateTime, PrimitiveDateTime, Time};
|
||||||
|
|
||||||
const PRIMITIVE_SHORT_DATE_TIME_FORMAT: &[FormatItem<'_>] =
|
const OFFSET_DATE_TIME_ENCODING: &[FormatItem<'_>] = format_description!(
|
||||||
format_description!("[year]-[month]-[day] [hour]:[minute]:[second]");
|
version = 2,
|
||||||
const PRIMITIVE_DATE_TIME_FORMAT: &[FormatItem<'_>] =
|
|
||||||
format_description!("[year]-[month]-[day] [hour]:[minute]:[second].[subsecond]");
|
|
||||||
const PRIMITIVE_DATE_TIME_Z_FORMAT: &[FormatItem<'_>] =
|
|
||||||
format_description!("[year]-[month]-[day] [hour]:[minute]:[second].[subsecond]Z");
|
|
||||||
const OFFSET_SHORT_DATE_TIME_FORMAT: &[FormatItem<'_>] = format_description!(
|
|
||||||
"[year]-[month]-[day] [hour]:[minute]:[second][offset_hour sign:mandatory]:[offset_minute]"
|
|
||||||
);
|
|
||||||
const OFFSET_DATE_TIME_FORMAT: &[FormatItem<'_>] = format_description!(
|
|
||||||
"[year]-[month]-[day] [hour]:[minute]:[second].[subsecond][offset_hour sign:mandatory]:[offset_minute]"
|
"[year]-[month]-[day] [hour]:[minute]:[second].[subsecond][offset_hour sign:mandatory]:[offset_minute]"
|
||||||
);
|
);
|
||||||
|
const PRIMITIVE_DATE_TIME_ENCODING: &[FormatItem<'_>] = format_description!(
|
||||||
|
version = 2,
|
||||||
|
"[year]-[month]-[day] [hour]:[minute]:[second].[subsecond]"
|
||||||
|
);
|
||||||
|
const TIME_ENCODING: &[FormatItem<'_>] =
|
||||||
|
format_description!(version = 2, "[hour]:[minute]:[second].[subsecond]");
|
||||||
|
|
||||||
|
const DATE_FORMAT: &[FormatItem<'_>] = format_description!(version = 2, "[year]-[month]-[day]");
|
||||||
|
const TIME_FORMAT: &[FormatItem<'_>] = format_description!(
|
||||||
|
version = 2,
|
||||||
|
"[hour]:[minute][optional [:[second][optional [.[subsecond]]]]]"
|
||||||
|
);
|
||||||
|
const PRIMITIVE_DATE_TIME_FORMAT: &[FormatItem<'_>] = format_description!(
|
||||||
|
version = 2,
|
||||||
|
"[year]-[month]-[day][first [ ][T]][hour]:[minute][optional [:[second][optional [.[subsecond]]]]]"
|
||||||
|
);
|
||||||
|
const UTC_DATE_TIME_FORMAT: &[FormatItem<'_>] = format_description!(
|
||||||
|
version = 2,
|
||||||
|
"[year]-[month]-[day][first [ ][T]][hour]:[minute][optional [:[second][optional [.[subsecond]]]]][optional [Z]]"
|
||||||
|
);
|
||||||
|
const OFFSET_DATE_TIME_FORMAT: &[FormatItem<'_>] = format_description!(
|
||||||
|
version = 2,
|
||||||
|
"[year]-[month]-[day][first [ ][T]][hour]:[minute][optional [:[second][optional [.[subsecond]]]]][offset_hour sign:mandatory]:[offset_minute]"
|
||||||
|
);
|
||||||
const LEGACY_DATE_TIME_FORMAT: &[FormatItem<'_>] = format_description!(
|
const LEGACY_DATE_TIME_FORMAT: &[FormatItem<'_>] = format_description!(
|
||||||
|
version = 2,
|
||||||
"[year]-[month]-[day] [hour]:[minute]:[second]:[subsecond] [offset_hour sign:mandatory]:[offset_minute]"
|
"[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")
|
||||||
impl ToSql for OffsetDateTime {
|
impl ToSql for OffsetDateTime {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn to_sql(&self) -> Result<ToSqlOutput<'_>> {
|
fn to_sql(&self) -> Result<ToSqlOutput<'_>> {
|
||||||
// FIXME keep original offset
|
|
||||||
let time_string = self
|
let time_string = self
|
||||||
.to_offset(UtcOffset::UTC)
|
.format(&OFFSET_DATE_TIME_ENCODING)
|
||||||
.format(&PRIMITIVE_DATE_TIME_Z_FORMAT)
|
|
||||||
.map_err(|err| Error::ToSqlConversionFailure(err.into()))?;
|
.map_err(|err| Error::ToSqlConversionFailure(err.into()))?;
|
||||||
Ok(ToSqlOutput::from(time_string))
|
Ok(ToSqlOutput::from(time_string))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Supports parsing formats 2-7 from https://www.sqlite.org/lang_datefunc.html
|
||||||
|
// Formats 2-7 without a timezone assumes UTC
|
||||||
impl FromSql for OffsetDateTime {
|
impl FromSql for OffsetDateTime {
|
||||||
fn column_result(value: ValueRef<'_>) -> FromSqlResult<Self> {
|
fn column_result(value: ValueRef<'_>) -> FromSqlResult<Self> {
|
||||||
value.as_str().and_then(|s| {
|
value.as_str().and_then(|s| {
|
||||||
if s.len() > 10 && s.as_bytes()[10] == b'T' {
|
if let Some(b' ') = s.as_bytes().get(23) {
|
||||||
// YYYY-MM-DDTHH:MM:SS.SSS[+-]HH:MM
|
// legacy
|
||||||
return OffsetDateTime::parse(s, &Rfc3339)
|
return OffsetDateTime::parse(s, &LEGACY_DATE_TIME_FORMAT)
|
||||||
.map_err(|err| FromSqlError::Other(Box::new(err)));
|
.map_err(|err| FromSqlError::Other(Box::new(err)));
|
||||||
}
|
}
|
||||||
let s = s.strip_suffix('Z').unwrap_or(s);
|
if s[8..].contains('+') || s[8..].contains('-') {
|
||||||
match s.len() {
|
// Formats 2-7 with timezone
|
||||||
len if len <= 19 => {
|
return OffsetDateTime::parse(s, &OFFSET_DATE_TIME_FORMAT)
|
||||||
// TODO YYYY-MM-DDTHH:MM:SS
|
.map_err(|err| FromSqlError::Other(Box::new(err)));
|
||||||
PrimitiveDateTime::parse(s, &PRIMITIVE_SHORT_DATE_TIME_FORMAT)
|
|
||||||
.map(PrimitiveDateTime::assume_utc)
|
|
||||||
}
|
|
||||||
_ if s.as_bytes()[19] == b':' => {
|
|
||||||
// legacy
|
|
||||||
OffsetDateTime::parse(s, &LEGACY_DATE_TIME_FORMAT)
|
|
||||||
}
|
|
||||||
_ if s.as_bytes()[19] == b'.' => OffsetDateTime::parse(s, &OFFSET_DATE_TIME_FORMAT)
|
|
||||||
.or_else(|err| {
|
|
||||||
PrimitiveDateTime::parse(s, &PRIMITIVE_DATE_TIME_FORMAT)
|
|
||||||
.map(PrimitiveDateTime::assume_utc)
|
|
||||||
.map_err(|_| err)
|
|
||||||
}),
|
|
||||||
_ => OffsetDateTime::parse(s, &OFFSET_SHORT_DATE_TIME_FORMAT),
|
|
||||||
}
|
}
|
||||||
|
// Formats 2-7 without timezone
|
||||||
|
PrimitiveDateTime::parse(s, &UTC_DATE_TIME_FORMAT)
|
||||||
|
.map(|p| p.assume_utc())
|
||||||
.map_err(|err| FromSqlError::Other(Box::new(err)))
|
.map_err(|err| FromSqlError::Other(Box::new(err)))
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// ISO 8601 calendar date without timezone => "YYYY-MM-DD"
|
||||||
|
impl ToSql for Date {
|
||||||
|
#[inline]
|
||||||
|
fn to_sql(&self) -> Result<ToSqlOutput<'_>> {
|
||||||
|
let date_str = self
|
||||||
|
.format(&DATE_FORMAT)
|
||||||
|
.map_err(|err| Error::ToSqlConversionFailure(err.into()))?;
|
||||||
|
Ok(ToSqlOutput::from(date_str))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// "YYYY-MM-DD" => ISO 8601 calendar date without timezone.
|
||||||
|
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()))
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// ISO 8601 time without timezone => "HH:MM:SS.SSS"
|
||||||
|
impl ToSql for Time {
|
||||||
|
#[inline]
|
||||||
|
fn to_sql(&self) -> Result<ToSqlOutput<'_>> {
|
||||||
|
let time_str = self
|
||||||
|
.format(&TIME_ENCODING)
|
||||||
|
.map_err(|err| Error::ToSqlConversionFailure(err.into()))?;
|
||||||
|
Ok(ToSqlOutput::from(time_str))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// "HH:MM"/"HH:MM:SS"/"HH:MM:SS.SSS" => ISO 8601 time without timezone.
|
||||||
|
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()))
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// ISO 8601 combined date and time without timezone => "YYYY-MM-DD HH:MM:SS.SSS"
|
||||||
|
impl ToSql for PrimitiveDateTime {
|
||||||
|
#[inline]
|
||||||
|
fn to_sql(&self) -> Result<ToSqlOutput<'_>> {
|
||||||
|
let date_time_str = self
|
||||||
|
.format(&PRIMITIVE_DATE_TIME_ENCODING)
|
||||||
|
.map_err(|err| Error::ToSqlConversionFailure(err.into()))?;
|
||||||
|
Ok(ToSqlOutput::from(date_time_str))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// YYYY-MM-DD HH:MM
|
||||||
|
/// YYYY-MM-DDTHH:MM
|
||||||
|
/// YYYY-MM-DD HH:MM:SS
|
||||||
|
/// YYYY-MM-DDTHH:MM:SS
|
||||||
|
/// YYYY-MM-DD HH:MM:SS.SSS
|
||||||
|
/// YYYY-MM-DDTHH:MM:SS.SSS
|
||||||
|
/// => ISO 8601 combined date and time with timezone
|
||||||
|
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)
|
||||||
|
.map_err(|err| FromSqlError::Other(err.into()))
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod test {
|
mod test {
|
||||||
use crate::{Connection, Result};
|
use crate::{Connection, Result};
|
||||||
use time::format_description::well_known::Rfc3339;
|
use time::macros::{date, datetime, time};
|
||||||
use time::OffsetDateTime;
|
use time::{Date, OffsetDateTime, PrimitiveDateTime, Time};
|
||||||
|
|
||||||
|
fn checked_memory_handle() -> Result<Connection> {
|
||||||
|
let db = Connection::open_in_memory()?;
|
||||||
|
db.execute_batch("CREATE TABLE foo (t TEXT, i INTEGER, f FLOAT, b BLOB)")?;
|
||||||
|
Ok(db)
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_offset_date_time() -> Result<()> {
|
fn test_offset_date_time() -> Result<()> {
|
||||||
let db = Connection::open_in_memory()?;
|
let db = checked_memory_handle()?;
|
||||||
db.execute_batch("CREATE TABLE foo (t TEXT, i INTEGER, f FLOAT)")?;
|
|
||||||
|
|
||||||
let mut ts_vec = vec![];
|
let mut ts_vec = vec![];
|
||||||
|
|
||||||
@ -103,47 +196,163 @@ mod test {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_string_values() -> Result<()> {
|
fn test_offset_date_time_parsing() -> Result<()> {
|
||||||
let db = Connection::open_in_memory()?;
|
let db = checked_memory_handle()?;
|
||||||
for (s, t) in vec![
|
let tests = vec![
|
||||||
|
// Rfc3339
|
||||||
(
|
(
|
||||||
"2013-10-07 08:23:19",
|
"2013-10-07T08:23:19.123456789Z",
|
||||||
Ok(OffsetDateTime::parse("2013-10-07T08:23:19Z", &Rfc3339).unwrap()),
|
datetime!(2013-10-07 8:23:19.123456789 UTC),
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
"2013-10-07 08:23:19Z",
|
"2013-10-07 08:23:19.123456789Z",
|
||||||
Ok(OffsetDateTime::parse("2013-10-07T08:23:19Z", &Rfc3339).unwrap()),
|
datetime!(2013-10-07 8:23:19.123456789 UTC),
|
||||||
|
),
|
||||||
|
// Format 2
|
||||||
|
("2013-10-07 08:23", datetime!(2013-10-07 8:23 UTC)),
|
||||||
|
("2013-10-07 08:23Z", datetime!(2013-10-07 8:23 UTC)),
|
||||||
|
("2013-10-07 08:23+04:00", datetime!(2013-10-07 8:23 +4)),
|
||||||
|
// Format 3
|
||||||
|
("2013-10-07 08:23:19", datetime!(2013-10-07 8:23:19 UTC)),
|
||||||
|
("2013-10-07 08:23:19Z", datetime!(2013-10-07 8:23:19 UTC)),
|
||||||
|
(
|
||||||
|
"2013-10-07 08:23:19+04:00",
|
||||||
|
datetime!(2013-10-07 8:23:19 +4),
|
||||||
|
),
|
||||||
|
// Format 4
|
||||||
|
(
|
||||||
|
"2013-10-07 08:23:19.123",
|
||||||
|
datetime!(2013-10-07 8:23:19.123 UTC),
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
"2013-10-07T08:23:19Z",
|
"2013-10-07 08:23:19.123Z",
|
||||||
Ok(OffsetDateTime::parse("2013-10-07T08:23:19Z", &Rfc3339).unwrap()),
|
datetime!(2013-10-07 8:23:19.123 UTC),
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
"2013-10-07 08:23:19.120",
|
"2013-10-07 08:23:19.123+04:00",
|
||||||
Ok(OffsetDateTime::parse("2013-10-07T08:23:19.120Z", &Rfc3339).unwrap()),
|
datetime!(2013-10-07 8:23:19.123 +4),
|
||||||
|
),
|
||||||
|
// Format 5
|
||||||
|
("2013-10-07T08:23", datetime!(2013-10-07 8:23 UTC)),
|
||||||
|
("2013-10-07T08:23Z", datetime!(2013-10-07 8:23 UTC)),
|
||||||
|
("2013-10-07T08:23+04:00", datetime!(2013-10-07 8:23 +4)),
|
||||||
|
// Format 6
|
||||||
|
("2013-10-07T08:23:19", datetime!(2013-10-07 8:23:19 UTC)),
|
||||||
|
("2013-10-07T08:23:19Z", datetime!(2013-10-07 8:23:19 UTC)),
|
||||||
|
(
|
||||||
|
"2013-10-07T08:23:19+04:00",
|
||||||
|
datetime!(2013-10-07 8:23:19 +4),
|
||||||
|
),
|
||||||
|
// Format 7
|
||||||
|
(
|
||||||
|
"2013-10-07T08:23:19.123",
|
||||||
|
datetime!(2013-10-07 8:23:19.123 UTC),
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
"2013-10-07 08:23:19.120Z",
|
"2013-10-07T08:23:19.123Z",
|
||||||
Ok(OffsetDateTime::parse("2013-10-07T08:23:19.120Z", &Rfc3339).unwrap()),
|
datetime!(2013-10-07 8:23:19.123 UTC),
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
"2013-10-07T08:23:19.120Z",
|
"2013-10-07T08:23:19.123+04:00",
|
||||||
Ok(OffsetDateTime::parse("2013-10-07T08:23:19.120Z", &Rfc3339).unwrap()),
|
datetime!(2013-10-07 8:23:19.123 +4),
|
||||||
),
|
),
|
||||||
|
// Legacy
|
||||||
(
|
(
|
||||||
"2013-10-07 04:23:19-04:00",
|
"2013-10-07 08:23:12:987 -07:00",
|
||||||
Ok(OffsetDateTime::parse("2013-10-07T04:23:19-04:00", &Rfc3339).unwrap()),
|
datetime!(2013-10-07 8:23:12.987 -7),
|
||||||
),
|
),
|
||||||
(
|
];
|
||||||
"2013-10-07 04:23:19.120-04:00",
|
|
||||||
Ok(OffsetDateTime::parse("2013-10-07T04:23:19.120-04:00", &Rfc3339).unwrap()),
|
for (s, t) in tests {
|
||||||
),
|
let result: OffsetDateTime = db.query_row("SELECT ?1", [s], |r| r.get(0))?;
|
||||||
(
|
assert_eq!(result, t);
|
||||||
"2013-10-07T04:23:19.120-04:00",
|
}
|
||||||
Ok(OffsetDateTime::parse("2013-10-07T04:23:19.120-04:00", &Rfc3339).unwrap()),
|
Ok(())
|
||||||
),
|
}
|
||||||
] {
|
|
||||||
let result: Result<OffsetDateTime> = db.query_row("SELECT ?1", [s], |r| r.get(0));
|
#[test]
|
||||||
|
fn test_date() -> Result<()> {
|
||||||
|
let db = checked_memory_handle()?;
|
||||||
|
let date = date!(2016 - 02 - 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);
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_time() -> Result<()> {
|
||||||
|
let db = checked_memory_handle()?;
|
||||||
|
let time = time!(23:56:04.00001);
|
||||||
|
db.execute("INSERT INTO foo (t) VALUES (?1)", [time])?;
|
||||||
|
|
||||||
|
let s: String = db.one_column("SELECT t FROM foo")?;
|
||||||
|
assert_eq!("23:56:04.00001", s);
|
||||||
|
let v: Time = db.one_column("SELECT t FROM foo")?;
|
||||||
|
assert_eq!(time, v);
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_primitive_date_time() -> Result<()> {
|
||||||
|
let db = checked_memory_handle()?;
|
||||||
|
let dt = date!(2016 - 02 - 23).with_time(time!(23:56:04));
|
||||||
|
|
||||||
|
db.execute("INSERT INTO foo (t) VALUES (?1)", [dt])?;
|
||||||
|
|
||||||
|
let s: String = db.one_column("SELECT t FROM foo")?;
|
||||||
|
assert_eq!("2016-02-23 23:56:04.0", s);
|
||||||
|
let v: PrimitiveDateTime = db.one_column("SELECT t FROM foo")?;
|
||||||
|
assert_eq!(dt, v);
|
||||||
|
|
||||||
|
db.execute("UPDATE foo set b = datetime(t)", [])?; // "YYYY-MM-DD HH:MM:SS"
|
||||||
|
let hms: PrimitiveDateTime = db.one_column("SELECT b FROM foo")?;
|
||||||
|
assert_eq!(dt, hms);
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_date_parsing() -> Result<()> {
|
||||||
|
let db = checked_memory_handle()?;
|
||||||
|
let result: Date = db.query_row("SELECT ?1", ["2013-10-07"], |r| r.get(0))?;
|
||||||
|
assert_eq!(result, date!(2013 - 10 - 07));
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_time_parsing() -> Result<()> {
|
||||||
|
let db = checked_memory_handle()?;
|
||||||
|
let tests = vec![
|
||||||
|
("08:23", time!(08:23)),
|
||||||
|
("08:23:19", time!(08:23:19)),
|
||||||
|
("08:23:19.111", time!(08:23:19.111)),
|
||||||
|
];
|
||||||
|
|
||||||
|
for (s, t) in tests {
|
||||||
|
let result: Time = db.query_row("SELECT ?1", [s], |r| r.get(0))?;
|
||||||
|
assert_eq!(result, t);
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_primitive_date_time_parsing() -> Result<()> {
|
||||||
|
let db = checked_memory_handle()?;
|
||||||
|
|
||||||
|
let tests = vec![
|
||||||
|
("2013-10-07T08:23", datetime!(2013-10-07 8:23)),
|
||||||
|
("2013-10-07T08:23:19", datetime!(2013-10-07 8:23:19)),
|
||||||
|
("2013-10-07T08:23:19.111", datetime!(2013-10-07 8:23:19.111)),
|
||||||
|
("2013-10-07 08:23", datetime!(2013-10-07 8:23)),
|
||||||
|
("2013-10-07 08:23:19", datetime!(2013-10-07 8:23:19)),
|
||||||
|
("2013-10-07 08:23:19.111", datetime!(2013-10-07 8:23:19.111)),
|
||||||
|
];
|
||||||
|
|
||||||
|
for (s, t) in tests {
|
||||||
|
let result: PrimitiveDateTime = db.query_row("SELECT ?1", [s], |r| r.get(0))?;
|
||||||
assert_eq!(result, t);
|
assert_eq!(result, t);
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
@ -151,16 +360,66 @@ mod test {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_sqlite_functions() -> Result<()> {
|
fn test_sqlite_functions() -> Result<()> {
|
||||||
let db = Connection::open_in_memory()?;
|
let db = checked_memory_handle()?;
|
||||||
let result: Result<OffsetDateTime> = db.one_column("SELECT CURRENT_TIMESTAMP");
|
db.one_column::<Time>("SELECT CURRENT_TIME").unwrap();
|
||||||
|
db.one_column::<Date>("SELECT CURRENT_DATE").unwrap();
|
||||||
|
db.one_column::<PrimitiveDateTime>("SELECT CURRENT_TIMESTAMP")
|
||||||
|
.unwrap();
|
||||||
|
db.one_column::<OffsetDateTime>("SELECT CURRENT_TIMESTAMP")
|
||||||
|
.unwrap();
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_time_param() -> Result<()> {
|
||||||
|
let db = checked_memory_handle()?;
|
||||||
|
let now = OffsetDateTime::now_utc().time();
|
||||||
|
let result: Result<bool> = db.query_row(
|
||||||
|
"SELECT 1 WHERE ?1 BETWEEN time('now', '-1 minute') AND time('now', '+1 minute')",
|
||||||
|
[now],
|
||||||
|
|r| r.get(0),
|
||||||
|
);
|
||||||
result.unwrap();
|
result.unwrap();
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_param() -> Result<()> {
|
fn test_date_param() -> Result<()> {
|
||||||
let db = Connection::open_in_memory()?;
|
let db = checked_memory_handle()?;
|
||||||
let result: Result<bool> = db.query_row("SELECT 1 WHERE ?1 BETWEEN datetime('now', '-1 minute') AND datetime('now', '+1 minute')", [OffsetDateTime::now_utc()], |r| r.get(0));
|
let now = OffsetDateTime::now_utc().date();
|
||||||
|
let result: Result<bool> = db.query_row(
|
||||||
|
"SELECT 1 WHERE ?1 BETWEEN date('now', '-1 day') AND date('now', '+1 day')",
|
||||||
|
[now],
|
||||||
|
|r| r.get(0),
|
||||||
|
);
|
||||||
|
result.unwrap();
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_primitive_date_time_param() -> Result<()> {
|
||||||
|
let db = checked_memory_handle()?;
|
||||||
|
let now = PrimitiveDateTime::new(
|
||||||
|
OffsetDateTime::now_utc().date(),
|
||||||
|
OffsetDateTime::now_utc().time(),
|
||||||
|
);
|
||||||
|
let result: Result<bool> = db.query_row(
|
||||||
|
"SELECT 1 WHERE ?1 BETWEEN datetime('now', '-1 minute') AND datetime('now', '+1 minute')",
|
||||||
|
[now],
|
||||||
|
|r| r.get(0),
|
||||||
|
);
|
||||||
|
result.unwrap();
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_offset_date_time_param() -> Result<()> {
|
||||||
|
let db = checked_memory_handle()?;
|
||||||
|
let result: Result<bool> = db.query_row(
|
||||||
|
"SELECT 1 WHERE ?1 BETWEEN datetime('now', '-1 minute') AND datetime('now', '+1 minute')",
|
||||||
|
[OffsetDateTime::now_utc()],
|
||||||
|
|r| r.get(0),
|
||||||
|
);
|
||||||
result.unwrap();
|
result.unwrap();
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
@ -51,6 +51,12 @@ macro_rules! from_value(
|
|||||||
#[inline]
|
#[inline]
|
||||||
fn from(t: $t) -> Self { ToSqlOutput::Owned(t.into())}
|
fn from(t: $t) -> Self { ToSqlOutput::Owned(t.into())}
|
||||||
}
|
}
|
||||||
|
);
|
||||||
|
(non_zero $t:ty) => (
|
||||||
|
impl From<$t> for ToSqlOutput<'_> {
|
||||||
|
#[inline]
|
||||||
|
fn from(t: $t) -> Self { ToSqlOutput::Owned(t.get().into())}
|
||||||
|
}
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
from_value!(String);
|
from_value!(String);
|
||||||
@ -68,6 +74,15 @@ from_value!(f32);
|
|||||||
from_value!(f64);
|
from_value!(f64);
|
||||||
from_value!(Vec<u8>);
|
from_value!(Vec<u8>);
|
||||||
|
|
||||||
|
from_value!(non_zero std::num::NonZeroI8);
|
||||||
|
from_value!(non_zero std::num::NonZeroI16);
|
||||||
|
from_value!(non_zero std::num::NonZeroI32);
|
||||||
|
from_value!(non_zero std::num::NonZeroI64);
|
||||||
|
from_value!(non_zero std::num::NonZeroIsize);
|
||||||
|
from_value!(non_zero std::num::NonZeroU8);
|
||||||
|
from_value!(non_zero std::num::NonZeroU16);
|
||||||
|
from_value!(non_zero std::num::NonZeroU32);
|
||||||
|
|
||||||
// It would be nice if we could avoid the heap allocation (of the `Vec`) that
|
// It would be nice if we could avoid the heap allocation (of the `Vec`) that
|
||||||
// `i128` needs in `Into<Value>`, but it's probably fine for the moment, and not
|
// `i128` needs in `Into<Value>`, but it's probably fine for the moment, and not
|
||||||
// worth adding another case to Value.
|
// worth adding another case to Value.
|
||||||
@ -75,6 +90,10 @@ from_value!(Vec<u8>);
|
|||||||
#[cfg_attr(docsrs, doc(cfg(feature = "i128_blob")))]
|
#[cfg_attr(docsrs, doc(cfg(feature = "i128_blob")))]
|
||||||
from_value!(i128);
|
from_value!(i128);
|
||||||
|
|
||||||
|
#[cfg(feature = "i128_blob")]
|
||||||
|
#[cfg_attr(docsrs, doc(cfg(feature = "i128_blob")))]
|
||||||
|
from_value!(non_zero std::num::NonZeroI128);
|
||||||
|
|
||||||
#[cfg(feature = "uuid")]
|
#[cfg(feature = "uuid")]
|
||||||
#[cfg_attr(docsrs, doc(cfg(feature = "uuid")))]
|
#[cfg_attr(docsrs, doc(cfg(feature = "uuid")))]
|
||||||
from_value!(uuid::Uuid);
|
from_value!(uuid::Uuid);
|
||||||
@ -165,10 +184,23 @@ to_sql_self!(u32);
|
|||||||
to_sql_self!(f32);
|
to_sql_self!(f32);
|
||||||
to_sql_self!(f64);
|
to_sql_self!(f64);
|
||||||
|
|
||||||
|
to_sql_self!(std::num::NonZeroI8);
|
||||||
|
to_sql_self!(std::num::NonZeroI16);
|
||||||
|
to_sql_self!(std::num::NonZeroI32);
|
||||||
|
to_sql_self!(std::num::NonZeroI64);
|
||||||
|
to_sql_self!(std::num::NonZeroIsize);
|
||||||
|
to_sql_self!(std::num::NonZeroU8);
|
||||||
|
to_sql_self!(std::num::NonZeroU16);
|
||||||
|
to_sql_self!(std::num::NonZeroU32);
|
||||||
|
|
||||||
#[cfg(feature = "i128_blob")]
|
#[cfg(feature = "i128_blob")]
|
||||||
#[cfg_attr(docsrs, doc(cfg(feature = "i128_blob")))]
|
#[cfg_attr(docsrs, doc(cfg(feature = "i128_blob")))]
|
||||||
to_sql_self!(i128);
|
to_sql_self!(i128);
|
||||||
|
|
||||||
|
#[cfg(feature = "i128_blob")]
|
||||||
|
#[cfg_attr(docsrs, doc(cfg(feature = "i128_blob")))]
|
||||||
|
to_sql_self!(std::num::NonZeroI128);
|
||||||
|
|
||||||
#[cfg(feature = "uuid")]
|
#[cfg(feature = "uuid")]
|
||||||
#[cfg_attr(docsrs, doc(cfg(feature = "uuid")))]
|
#[cfg_attr(docsrs, doc(cfg(feature = "uuid")))]
|
||||||
to_sql_self!(uuid::Uuid);
|
to_sql_self!(uuid::Uuid);
|
||||||
@ -186,12 +218,27 @@ macro_rules! to_sql_self_fallible(
|
|||||||
)))
|
)))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
);
|
||||||
|
(non_zero $t:ty) => (
|
||||||
|
impl ToSql for $t {
|
||||||
|
#[inline]
|
||||||
|
fn to_sql(&self) -> Result<ToSqlOutput<'_>> {
|
||||||
|
Ok(ToSqlOutput::Owned(Value::Integer(
|
||||||
|
i64::try_from(self.get()).map_err(
|
||||||
|
// TODO: Include the values in the error message.
|
||||||
|
|err| Error::ToSqlConversionFailure(err.into())
|
||||||
|
)?
|
||||||
|
)))
|
||||||
|
}
|
||||||
|
}
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
// Special implementations for usize and u64 because these conversions can fail.
|
// Special implementations for usize and u64 because these conversions can fail.
|
||||||
to_sql_self_fallible!(u64);
|
to_sql_self_fallible!(u64);
|
||||||
to_sql_self_fallible!(usize);
|
to_sql_self_fallible!(usize);
|
||||||
|
to_sql_self_fallible!(non_zero std::num::NonZeroU64);
|
||||||
|
to_sql_self_fallible!(non_zero std::num::NonZeroUsize);
|
||||||
|
|
||||||
impl<T: ?Sized> ToSql for &'_ T
|
impl<T: ?Sized> ToSql for &'_ T
|
||||||
where
|
where
|
||||||
@ -267,9 +314,26 @@ mod test {
|
|||||||
is_to_sql::<i16>();
|
is_to_sql::<i16>();
|
||||||
is_to_sql::<i32>();
|
is_to_sql::<i32>();
|
||||||
is_to_sql::<i64>();
|
is_to_sql::<i64>();
|
||||||
|
is_to_sql::<isize>();
|
||||||
is_to_sql::<u8>();
|
is_to_sql::<u8>();
|
||||||
is_to_sql::<u16>();
|
is_to_sql::<u16>();
|
||||||
is_to_sql::<u32>();
|
is_to_sql::<u32>();
|
||||||
|
is_to_sql::<u64>();
|
||||||
|
is_to_sql::<usize>();
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_nonzero_types() {
|
||||||
|
is_to_sql::<std::num::NonZeroI8>();
|
||||||
|
is_to_sql::<std::num::NonZeroI16>();
|
||||||
|
is_to_sql::<std::num::NonZeroI32>();
|
||||||
|
is_to_sql::<std::num::NonZeroI64>();
|
||||||
|
is_to_sql::<std::num::NonZeroIsize>();
|
||||||
|
is_to_sql::<std::num::NonZeroU8>();
|
||||||
|
is_to_sql::<std::num::NonZeroU16>();
|
||||||
|
is_to_sql::<std::num::NonZeroU32>();
|
||||||
|
is_to_sql::<std::num::NonZeroU64>();
|
||||||
|
is_to_sql::<std::num::NonZeroUsize>();
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
@ -398,6 +462,54 @@ mod test {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "i128_blob")]
|
||||||
|
#[test]
|
||||||
|
fn test_non_zero_i128() -> crate::Result<()> {
|
||||||
|
use std::num::NonZeroI128;
|
||||||
|
macro_rules! nz {
|
||||||
|
($x:expr) => {
|
||||||
|
NonZeroI128::new($x).unwrap()
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
let db = crate::Connection::open_in_memory()?;
|
||||||
|
db.execute_batch("CREATE TABLE foo (i128 BLOB, desc TEXT)")?;
|
||||||
|
db.execute(
|
||||||
|
"INSERT INTO foo(i128, desc) VALUES
|
||||||
|
(?1, 'neg one'), (?2, 'neg two'),
|
||||||
|
(?3, 'pos one'), (?4, 'pos two'),
|
||||||
|
(?5, 'min'), (?6, 'max')",
|
||||||
|
[
|
||||||
|
nz!(-1),
|
||||||
|
nz!(-2),
|
||||||
|
nz!(1),
|
||||||
|
nz!(2),
|
||||||
|
nz!(i128::MIN),
|
||||||
|
nz!(i128::MAX),
|
||||||
|
],
|
||||||
|
)?;
|
||||||
|
let mut stmt = db.prepare("SELECT i128, desc FROM foo ORDER BY i128 ASC")?;
|
||||||
|
|
||||||
|
let res = stmt
|
||||||
|
.query_map([], |row| Ok((row.get(0)?, row.get(1)?)))?
|
||||||
|
.collect::<Result<Vec<(NonZeroI128, String)>, _>>()?;
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
res,
|
||||||
|
&[
|
||||||
|
(nz!(i128::MIN), "min".to_owned()),
|
||||||
|
(nz!(-2), "neg two".to_owned()),
|
||||||
|
(nz!(-1), "neg one".to_owned()),
|
||||||
|
(nz!(1), "pos one".to_owned()),
|
||||||
|
(nz!(2), "pos two".to_owned()),
|
||||||
|
(nz!(i128::MAX), "max".to_owned()),
|
||||||
|
]
|
||||||
|
);
|
||||||
|
let err = db.query_row("SELECT ?1", [0i128], |row| row.get::<_, NonZeroI128>(0));
|
||||||
|
assert_eq!(err, Err(crate::Error::IntegralValueOutOfRange(0, 0)));
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(feature = "uuid")]
|
#[cfg(feature = "uuid")]
|
||||||
#[test]
|
#[test]
|
||||||
fn test_uuid() -> crate::Result<()> {
|
fn test_uuid() -> crate::Result<()> {
|
||||||
|
@ -74,7 +74,7 @@ mod test {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
e => {
|
e => {
|
||||||
panic!("Expected conversion failure, got {}", e);
|
panic!("Expected conversion failure, got {e}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
|
@ -158,6 +158,7 @@ impl<'a> ValueRef<'a> {
|
|||||||
|
|
||||||
impl From<ValueRef<'_>> for Value {
|
impl From<ValueRef<'_>> for Value {
|
||||||
#[inline]
|
#[inline]
|
||||||
|
#[track_caller]
|
||||||
fn from(borrowed: ValueRef<'_>) -> Value {
|
fn from(borrowed: ValueRef<'_>) -> Value {
|
||||||
match borrowed {
|
match borrowed {
|
||||||
ValueRef::Null => Value::Null,
|
ValueRef::Null => Value::Null,
|
||||||
|
@ -6,4 +6,4 @@ pub(crate) use small_cstr::SmallCString;
|
|||||||
|
|
||||||
// Doesn't use any modern features or vtab stuff, but is only used by them.
|
// Doesn't use any modern features or vtab stuff, but is only used by them.
|
||||||
mod sqlite_string;
|
mod sqlite_string;
|
||||||
pub(crate) use sqlite_string::SqliteMallocString;
|
pub(crate) use sqlite_string::{alloc, SqliteMallocString};
|
||||||
|
@ -7,6 +7,12 @@ use std::marker::PhantomData;
|
|||||||
use std::os::raw::{c_char, c_int};
|
use std::os::raw::{c_char, c_int};
|
||||||
use std::ptr::NonNull;
|
use std::ptr::NonNull;
|
||||||
|
|
||||||
|
// Space to hold this string must be obtained
|
||||||
|
// from an SQLite memory allocation function
|
||||||
|
pub(crate) fn alloc(s: &str) -> *mut c_char {
|
||||||
|
SqliteMallocString::from_str(s).into_raw()
|
||||||
|
}
|
||||||
|
|
||||||
/// A string we own that's allocated on the SQLite heap. Automatically calls
|
/// A string we own that's allocated on the SQLite heap. Automatically calls
|
||||||
/// `sqlite3_free` when dropped, unless `into_raw` (or `into_inner`) is called
|
/// `sqlite3_free` when dropped, unless `into_raw` (or `into_inner`) is called
|
||||||
/// on it. If constructed from a rust string, `sqlite3_malloc` is used.
|
/// on it. If constructed from a rust string, `sqlite3_malloc` is used.
|
||||||
@ -100,7 +106,6 @@ impl SqliteMallocString {
|
|||||||
/// 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 of
|
||||||
/// `catch_unwind`.
|
/// `catch_unwind`.
|
||||||
pub(crate) fn from_str(s: &str) -> Self {
|
pub(crate) fn from_str(s: &str) -> Self {
|
||||||
use std::convert::TryFrom;
|
|
||||||
let s = if s.as_bytes().contains(&0) {
|
let s = if s.as_bytes().contains(&0) {
|
||||||
std::borrow::Cow::Owned(make_nonnull(s))
|
std::borrow::Cow::Owned(make_nonnull(s))
|
||||||
} else {
|
} else {
|
||||||
|
@ -113,10 +113,7 @@ unsafe impl<'vtab> VTab<'vtab> for CsvTab {
|
|||||||
match param {
|
match param {
|
||||||
"filename" => {
|
"filename" => {
|
||||||
if !Path::new(value).exists() {
|
if !Path::new(value).exists() {
|
||||||
return Err(Error::ModuleError(format!(
|
return Err(Error::ModuleError(format!("file '{value}' does not exist")));
|
||||||
"file '{}' does not exist",
|
|
||||||
value
|
|
||||||
)));
|
|
||||||
}
|
}
|
||||||
vtab.filename = value.to_owned();
|
vtab.filename = value.to_owned();
|
||||||
}
|
}
|
||||||
@ -137,8 +134,7 @@ unsafe impl<'vtab> VTab<'vtab> for CsvTab {
|
|||||||
n_col = Some(n);
|
n_col = Some(n);
|
||||||
} else {
|
} else {
|
||||||
return Err(Error::ModuleError(format!(
|
return Err(Error::ModuleError(format!(
|
||||||
"unrecognized argument to 'columns': {}",
|
"unrecognized argument to 'columns': {value}"
|
||||||
value
|
|
||||||
)));
|
)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -147,8 +143,7 @@ unsafe impl<'vtab> VTab<'vtab> for CsvTab {
|
|||||||
vtab.has_headers = b;
|
vtab.has_headers = b;
|
||||||
} else {
|
} else {
|
||||||
return Err(Error::ModuleError(format!(
|
return Err(Error::ModuleError(format!(
|
||||||
"unrecognized argument to 'header': {}",
|
"unrecognized argument to 'header': {value}"
|
||||||
value
|
|
||||||
)));
|
)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -157,8 +152,7 @@ unsafe impl<'vtab> VTab<'vtab> for CsvTab {
|
|||||||
vtab.delimiter = b;
|
vtab.delimiter = b;
|
||||||
} else {
|
} else {
|
||||||
return Err(Error::ModuleError(format!(
|
return Err(Error::ModuleError(format!(
|
||||||
"unrecognized argument to 'delimiter': {}",
|
"unrecognized argument to 'delimiter': {value}"
|
||||||
value
|
|
||||||
)));
|
)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -171,15 +165,13 @@ unsafe impl<'vtab> VTab<'vtab> for CsvTab {
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
return Err(Error::ModuleError(format!(
|
return Err(Error::ModuleError(format!(
|
||||||
"unrecognized argument to 'quote': {}",
|
"unrecognized argument to 'quote': {value}"
|
||||||
value
|
|
||||||
)));
|
)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
return Err(Error::ModuleError(format!(
|
return Err(Error::ModuleError(format!(
|
||||||
"unrecognized parameter '{}'",
|
"unrecognized parameter '{param}'"
|
||||||
param
|
|
||||||
)));
|
)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -326,8 +318,7 @@ unsafe impl VTabCursor for CsvTabCursor<'_> {
|
|||||||
fn column(&self, ctx: &mut Context, col: c_int) -> Result<()> {
|
fn column(&self, ctx: &mut Context, col: c_int) -> Result<()> {
|
||||||
if col < 0 || col as usize >= self.cols.len() {
|
if col < 0 || col as usize >= self.cols.len() {
|
||||||
return Err(Error::ModuleError(format!(
|
return Err(Error::ModuleError(format!(
|
||||||
"column index out of bounds: {}",
|
"column index out of bounds: {col}"
|
||||||
col
|
|
||||||
)));
|
)));
|
||||||
}
|
}
|
||||||
if self.cols.is_empty() {
|
if self.cols.is_empty() {
|
||||||
|
@ -17,10 +17,11 @@ use std::ptr;
|
|||||||
use std::slice;
|
use std::slice;
|
||||||
|
|
||||||
use crate::context::set_result;
|
use crate::context::set_result;
|
||||||
use crate::error::error_from_sqlite_code;
|
use crate::error::{error_from_sqlite_code, to_sqlite_error};
|
||||||
use crate::ffi;
|
use crate::ffi;
|
||||||
pub use crate::ffi::{sqlite3_vtab, sqlite3_vtab_cursor};
|
pub use crate::ffi::{sqlite3_vtab, sqlite3_vtab_cursor};
|
||||||
use crate::types::{FromSql, FromSqlError, ToSql, ValueRef};
|
use crate::types::{FromSql, FromSqlError, ToSql, ValueRef};
|
||||||
|
use crate::util::alloc;
|
||||||
use crate::{str_to_cstring, Connection, Error, InnerConnection, Result};
|
use crate::{str_to_cstring, Connection, Error, InnerConnection, Result};
|
||||||
|
|
||||||
// let conn: Connection = ...;
|
// let conn: Connection = ...;
|
||||||
@ -195,6 +196,8 @@ pub enum VTabConfig {
|
|||||||
Innocuous = 2,
|
Innocuous = 2,
|
||||||
/// Equivalent to SQLITE_VTAB_DIRECTONLY
|
/// Equivalent to SQLITE_VTAB_DIRECTONLY
|
||||||
DirectOnly = 3,
|
DirectOnly = 3,
|
||||||
|
/// Equivalent to SQLITE_VTAB_USES_ALL_SCHEMAS
|
||||||
|
UsesAllSchemas = 4,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// `feature = "vtab"`
|
/// `feature = "vtab"`
|
||||||
@ -882,7 +885,7 @@ pub fn dequote(s: &str) -> &str {
|
|||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
match s.bytes().next() {
|
match s.bytes().next() {
|
||||||
Some(b) if b == b'"' || b == b'\'' => match s.bytes().rev().next() {
|
Some(b) if b == b'"' || b == b'\'' => match s.bytes().next_back() {
|
||||||
Some(e) if e == b => &s[1..s.len() - 1], // FIXME handle inner escaped quote(s)
|
Some(e) if e == b => &s[1..s.len() - 1], // FIXME handle inner escaped quote(s)
|
||||||
_ => s,
|
_ => s,
|
||||||
},
|
},
|
||||||
@ -962,8 +965,7 @@ where
|
|||||||
ffi::SQLITE_OK
|
ffi::SQLITE_OK
|
||||||
} else {
|
} else {
|
||||||
let err = error_from_sqlite_code(rc, None);
|
let err = error_from_sqlite_code(rc, None);
|
||||||
*err_msg = alloc(&err.to_string());
|
to_sqlite_error(&err, err_msg)
|
||||||
rc
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
@ -971,16 +973,7 @@ where
|
|||||||
ffi::SQLITE_ERROR
|
ffi::SQLITE_ERROR
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
Err(Error::SqliteFailure(err, s)) => {
|
Err(err) => to_sqlite_error(&err, err_msg),
|
||||||
if let Some(s) = s {
|
|
||||||
*err_msg = alloc(&s);
|
|
||||||
}
|
|
||||||
err.extended_code
|
|
||||||
}
|
|
||||||
Err(err) => {
|
|
||||||
*err_msg = alloc(&err.to_string());
|
|
||||||
ffi::SQLITE_ERROR
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1014,8 +1007,7 @@ where
|
|||||||
ffi::SQLITE_OK
|
ffi::SQLITE_OK
|
||||||
} else {
|
} else {
|
||||||
let err = error_from_sqlite_code(rc, None);
|
let err = error_from_sqlite_code(rc, None);
|
||||||
*err_msg = alloc(&err.to_string());
|
to_sqlite_error(&err, err_msg)
|
||||||
rc
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
@ -1023,16 +1015,7 @@ where
|
|||||||
ffi::SQLITE_ERROR
|
ffi::SQLITE_ERROR
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
Err(Error::SqliteFailure(err, s)) => {
|
Err(err) => to_sqlite_error(&err, err_msg),
|
||||||
if let Some(s) = s {
|
|
||||||
*err_msg = alloc(&s);
|
|
||||||
}
|
|
||||||
err.extended_code
|
|
||||||
}
|
|
||||||
Err(err) => {
|
|
||||||
*err_msg = alloc(&err.to_string());
|
|
||||||
ffi::SQLITE_ERROR
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1309,12 +1292,6 @@ unsafe fn result_error<T>(ctx: *mut ffi::sqlite3_context, result: Result<T>) ->
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Space to hold this string must be obtained
|
|
||||||
// from an SQLite memory allocation function
|
|
||||||
fn alloc(s: &str) -> *mut c_char {
|
|
||||||
crate::util::SqliteMallocString::from_str(s).into_raw()
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(feature = "array")]
|
#[cfg(feature = "array")]
|
||||||
#[cfg_attr(docsrs, doc(cfg(feature = "array")))]
|
#[cfg_attr(docsrs, doc(cfg(feature = "array")))]
|
||||||
pub mod array;
|
pub mod array;
|
||||||
|
@ -200,19 +200,19 @@ unsafe impl VTabCursor for SeriesTabCursor<'_> {
|
|||||||
let mut idx_num = QueryPlanFlags::from_bits_truncate(idx_num);
|
let mut idx_num = QueryPlanFlags::from_bits_truncate(idx_num);
|
||||||
let mut i = 0;
|
let mut i = 0;
|
||||||
if idx_num.contains(QueryPlanFlags::START) {
|
if idx_num.contains(QueryPlanFlags::START) {
|
||||||
self.min_value = args.get(i)?;
|
self.min_value = args.get::<Option<_>>(i)?.unwrap_or_default();
|
||||||
i += 1;
|
i += 1;
|
||||||
} else {
|
} else {
|
||||||
self.min_value = 0;
|
self.min_value = 0;
|
||||||
}
|
}
|
||||||
if idx_num.contains(QueryPlanFlags::STOP) {
|
if idx_num.contains(QueryPlanFlags::STOP) {
|
||||||
self.max_value = args.get(i)?;
|
self.max_value = args.get::<Option<_>>(i)?.unwrap_or_default();
|
||||||
i += 1;
|
i += 1;
|
||||||
} else {
|
} else {
|
||||||
self.max_value = 0xffff_ffff;
|
self.max_value = 0xffff_ffff;
|
||||||
}
|
}
|
||||||
if idx_num.contains(QueryPlanFlags::STEP) {
|
if idx_num.contains(QueryPlanFlags::STEP) {
|
||||||
self.step = args.get(i)?;
|
self.step = args.get::<Option<_>>(i)?.unwrap_or_default();
|
||||||
if self.step == 0 {
|
if self.step == 0 {
|
||||||
self.step = 1;
|
self.step = 1;
|
||||||
} else if self.step < 0 {
|
} else if self.step < 0 {
|
||||||
@ -316,6 +316,26 @@ mod test {
|
|||||||
let series: Vec<i32> = s.query([])?.map(|r| r.get(0)).collect()?;
|
let series: Vec<i32> = s.query([])?.map(|r| r.get(0)).collect()?;
|
||||||
assert_eq!(vec![30, 25, 20, 15, 10, 5, 0], series);
|
assert_eq!(vec![30, 25, 20, 15, 10, 5, 0], series);
|
||||||
|
|
||||||
|
let mut s = db.prepare("SELECT * FROM generate_series(NULL)")?;
|
||||||
|
let series: Vec<i32> = s.query([])?.map(|r| r.get(0)).collect()?;
|
||||||
|
let empty = Vec::<i32>::new();
|
||||||
|
assert_eq!(empty, series);
|
||||||
|
let mut s = db.prepare("SELECT * FROM generate_series(5,NULL)")?;
|
||||||
|
let series: Vec<i32> = s.query([])?.map(|r| r.get(0)).collect()?;
|
||||||
|
assert_eq!(empty, series);
|
||||||
|
let mut s = db.prepare("SELECT * FROM generate_series(5,10,NULL)")?;
|
||||||
|
let series: Vec<i32> = s.query([])?.map(|r| r.get(0)).collect()?;
|
||||||
|
assert_eq!(empty, series);
|
||||||
|
let mut s = db.prepare("SELECT * FROM generate_series(NULL,10,2)")?;
|
||||||
|
let series: Vec<i32> = s.query([])?.map(|r| r.get(0)).collect()?;
|
||||||
|
assert_eq!(empty, series);
|
||||||
|
let mut s = db.prepare("SELECT * FROM generate_series(5,NULL,2)")?;
|
||||||
|
let series: Vec<i32> = s.query([])?.map(|r| r.get(0)).collect()?;
|
||||||
|
assert_eq!(empty, series);
|
||||||
|
let mut s = db.prepare("SELECT * FROM generate_series(NULL) ORDER BY value DESC")?;
|
||||||
|
let series: Vec<i32> = s.query([])?.map(|r| r.get(0)).collect()?;
|
||||||
|
assert_eq!(empty, series);
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -56,8 +56,7 @@ impl VTabLog {
|
|||||||
"schema" => {
|
"schema" => {
|
||||||
if schema.is_some() {
|
if schema.is_some() {
|
||||||
return Err(Error::ModuleError(format!(
|
return Err(Error::ModuleError(format!(
|
||||||
"more than one '{}' parameter",
|
"more than one '{param}' parameter"
|
||||||
param
|
|
||||||
)));
|
)));
|
||||||
}
|
}
|
||||||
schema = Some(value.to_owned())
|
schema = Some(value.to_owned())
|
||||||
@ -65,8 +64,7 @@ impl VTabLog {
|
|||||||
"rows" => {
|
"rows" => {
|
||||||
if n_row.is_some() {
|
if n_row.is_some() {
|
||||||
return Err(Error::ModuleError(format!(
|
return Err(Error::ModuleError(format!(
|
||||||
"more than one '{}' parameter",
|
"more than one '{param}' parameter"
|
||||||
param
|
|
||||||
)));
|
)));
|
||||||
}
|
}
|
||||||
if let Ok(n) = i64::from_str(value) {
|
if let Ok(n) = i64::from_str(value) {
|
||||||
@ -75,8 +73,7 @@ impl VTabLog {
|
|||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
return Err(Error::ModuleError(format!(
|
return Err(Error::ModuleError(format!(
|
||||||
"unrecognized parameter '{}'",
|
"unrecognized parameter '{param}'"
|
||||||
param
|
|
||||||
)));
|
)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user