Merge remote-tracking branch 'origin/master' into ptr_as_ptr

This commit is contained in:
gwenn 2022-01-06 18:20:01 +01:00
commit cc4f059d9b
30 changed files with 173 additions and 151 deletions

View File

@ -50,12 +50,12 @@ jobs:
- run: cargo test --features bundled --workspace --all-targets --verbose
- run: cargo test --features bundled --workspace --doc --verbose
- name: Test Features
# TODO: clang is installed on these -- but `bindgen` can't find it...
if: matrix.os != 'windows-latest'
run: |
cargo test --features 'bundled-full session buildtime_bindgen' --all-targets --workspace --verbose
cargo test --features 'bundled-full session buildtime_bindgen' --doc --workspace --verbose
- name: Add llvm path on Windows
if: matrix.os == 'windows-latest'
run: echo "C:\msys64\mingw64\bin" | Out-File -FilePath $env:GITHUB_PATH -Encoding utf8 -Append
- run: cargo test --features 'bundled-full session buildtime_bindgen' --all-targets --workspace --verbose
- run: cargo test --features 'bundled-full session buildtime_bindgen' --doc --workspace --verbose
# TODO: move into own action for better caching
- name: Static build
@ -97,11 +97,12 @@ jobs:
- run: cargo test --features 'modern-full bundled-sqlcipher-vendored-openssl' --all-targets --workspace --verbose
- run: cargo test --features 'modern-full bundled-sqlcipher-vendored-openssl' --doc --workspace --verbose
- name: Test Features
if: matrix.os != 'windows-latest'
run: |
cargo test --features 'bundled-full session buildtime_bindgen' --all-targets --workspace --verbose
cargo test --features 'bundled-full session buildtime_bindgen' --doc --workspace --verbose
- name: Add llvm path on Windows
if: matrix.os == 'windows-latest'
run: echo "C:\msys64\mingw64\bin" | Out-File -FilePath $env:GITHUB_PATH -Encoding utf8 -Append
- run: cargo test --features 'bundled-full session buildtime_bindgen' --all-targets --workspace --verbose
- run: cargo test --features 'bundled-full session buildtime_bindgen' --doc --workspace --verbose
winsqlite3:
name: Test with winsqlite3

View File

@ -1,13 +1,12 @@
# Rusqlite
[![Travis Build Status](https://api.travis-ci.org/rusqlite/rusqlite.svg?branch=master)](https://travis-ci.org/rusqlite/rusqlite)
[![AppVeyor Build Status](https://ci.appveyor.com/api/projects/status/github/rusqlite/rusqlite?branch=master&svg=true)](https://ci.appveyor.com/project/rusqlite/rusqlite)
[![Build Status](https://github.com/rusqlite/rusqlite/workflows/CI/badge.svg)](https://github.com/rusqlite/rusqlite/actions)
[![dependency status](https://deps.rs/repo/github/rusqlite/rusqlite/status.svg)](https://deps.rs/repo/github/rusqlite/rusqlite)
[![Latest Version](https://img.shields.io/crates/v/rusqlite.svg)](https://crates.io/crates/rusqlite)
[![Gitter](https://badges.gitter.im/rusqlite.svg)](https://gitter.im/rusqlite/community?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge)
[![Docs](https://docs.rs/rusqlite/badge.svg)](https://docs.rs/rusqlite)
[![codecov](https://codecov.io/gh/rusqlite/rusqlite/branch/master/graph/badge.svg)](https://codecov.io/gh/rusqlite/rusqlite)
[![Documentation](https://docs.rs/rusqlite/badge.svg)](https://docs.rs/rusqlite)
[![Build Status (GitHub)](https://github.com/rusqlite/rusqlite/workflows/CI/badge.svg)](https://github.com/rusqlite/rusqlite/actions)
[![Build Status (AppVeyor)](https://ci.appveyor.com/api/projects/status/github/rusqlite/rusqlite?branch=master&svg=true)](https://ci.appveyor.com/project/rusqlite/rusqlite)
[![Code Coverage](https://codecov.io/gh/rusqlite/rusqlite/branch/master/graph/badge.svg)](https://codecov.io/gh/rusqlite/rusqlite)
[![Dependency Status](https://deps.rs/repo/github/rusqlite/rusqlite/status.svg)](https://deps.rs/repo/github/rusqlite/rusqlite)
[![Discord Chat](https://img.shields.io/discord/927966344266256434.svg?logo=discord)](https://discord.gg/G6Se6Yzw)
Rusqlite is an ergonomic wrapper for using SQLite from Rust. It attempts to expose
an interface similar to [rust-postgres](https://github.com/sfackler/rust-postgres).
@ -212,7 +211,7 @@ here: https://github.com/rusqlite/rusqlite/graphs/contributors
## Community
Currently there's a gitter channel set up for rusqlite [here](https://gitter.im/rusqlite/community).
Feel free to join the [Rusqlite Discord Server](https://discord.gg/G6Se6Yzw) to discuss or get help with `rusqlite` or `libsqlite3-sys`.
## License

View File

@ -46,9 +46,9 @@ fn main() {
features 'bundled' and 'bundled-windows'. If you want a bundled build of
SQLCipher (available for the moment only on Unix), use feature 'bundled-sqlcipher'
or 'bundled-sqlcipher-vendored-openssl' to also bundle OpenSSL crypto."
)
);
}
build_linked::main(&out_dir, &out_path)
build_linked::main(&out_dir, &out_path);
} else if cfg!(feature = "bundled")
|| (win_target() && cfg!(feature = "bundled-windows"))
|| cfg!(feature = "bundled-sqlcipher")
@ -66,7 +66,7 @@ fn main() {
)))]
panic!("The runtime test should not run this branch, which has not compiled any logic.")
} else {
build_linked::main(&out_dir, &out_path)
build_linked::main(&out_dir, &out_path);
}
}
@ -168,7 +168,7 @@ mod build_bundled {
panic!(
"OpenSSL include directory does not exist: {}",
inc_dir.to_string_lossy()
)
);
}
use_openssl = true;
@ -429,19 +429,17 @@ mod build_linked {
}
// See if pkg-config can do everything for us.
match pkg_config::Config::new()
if let Ok(mut lib) = pkg_config::Config::new()
.print_system_libs(false)
.probe(link_lib)
{
Ok(mut lib) => {
if let Some(mut header) = lib.include_paths.pop() {
header.push("sqlite3.h");
HeaderLocation::FromPath(header.to_string_lossy().into())
} else {
HeaderLocation::Wrapper
}
}
Err(_) => {
} else {
// No env var set and pkg-config couldn't help; just output the link-lib
// request and hope that the library exists on the system paths. We used to
// output /usr/lib explicitly, but that can introduce other linking problems;
@ -450,7 +448,6 @@ mod build_linked {
HeaderLocation::Wrapper
}
}
}
fn try_vcpkg() -> Option<HeaderLocation> {
if cfg!(feature = "vcpkg") && is_compiler("msvc") {

View File

@ -63,6 +63,7 @@ pub struct Error {
}
impl Error {
#[must_use]
pub fn new(result_code: c_int) -> Error {
let code = match result_code & 0xff {
super::SQLITE_INTERNAL => ErrorCode::InternalMalfunction,
@ -192,6 +193,7 @@ const SQLITE_WARNING_AUTOINDEX: c_int = SQLITE_WARNING | (1 << 8);
const SQLITE_AUTH_USER: c_int = super::SQLITE_AUTH | (1 << 8);
#[must_use]
pub fn code_to_str(code: c_int) -> &'static str {
match code {
super::SQLITE_OK => "Successful result",

View File

@ -12,12 +12,14 @@ use std::mem;
mod error;
#[must_use]
pub fn SQLITE_STATIC() -> sqlite3_destructor_type {
None
}
#[must_use]
pub fn SQLITE_TRANSIENT() -> sqlite3_destructor_type {
Some(unsafe { mem::transmute(-1isize) })
Some(unsafe { mem::transmute(-1_isize) })
}
/// Run-Time Limit Categories

View File

@ -107,7 +107,7 @@ impl Connection {
let restore = Backup::new_with_names(&src, DatabaseName::Main, self, name)?;
let mut r = More;
let mut busy_count = 0i32;
let mut busy_count = 0_i32;
'restore_loop: while r == More || r == Busy {
r = restore.step(100)?;
if let Some(ref f) = progress {
@ -231,6 +231,7 @@ impl Backup<'_, '_> {
/// Gets the progress of the backup as of the last call to
/// [`step`](Backup::step).
#[inline]
#[must_use]
pub fn progress(&self) -> Progress {
unsafe {
Progress {
@ -296,7 +297,7 @@ impl Backup<'_, '_> {
loop {
let r = self.step(pages_per_step)?;
if let Some(progress) = progress {
progress(self.progress())
progress(self.progress());
}
match r {
More | Busy | Locked => thread::sleep(pause_between_pages),

View File

@ -265,12 +265,14 @@ impl Blob<'_> {
/// Return the size in bytes of the BLOB.
#[inline]
#[must_use]
pub fn size(&self) -> i32 {
unsafe { ffi::sqlite3_blob_bytes(self.blob) }
}
/// Return the current size in bytes of the BLOB.
#[inline]
#[must_use]
pub fn len(&self) -> usize {
use std::convert::TryInto;
self.size().try_into().unwrap()
@ -278,6 +280,7 @@ impl Blob<'_> {
/// Return true if the BLOB is empty.
#[inline]
#[must_use]
pub fn is_empty(&self) -> bool {
self.size() == 0
}

View File

@ -46,13 +46,13 @@ impl Connection {
/// can set the capacity manually using this method.
#[inline]
pub fn set_prepared_statement_cache_capacity(&self, capacity: usize) {
self.cache.set_capacity(capacity)
self.cache.set_capacity(capacity);
}
/// Remove/finalize all prepared statements currently in the cache.
#[inline]
pub fn flush_prepared_statement_cache(&self) {
self.cache.flush()
self.cache.flush();
}
}
@ -122,7 +122,7 @@ impl StatementCache {
#[inline]
fn set_capacity(&self, capacity: usize) {
self.0.borrow_mut().set_capacity(capacity)
self.0.borrow_mut().set_capacity(capacity);
}
// Search the cache for a prepared-statement object that implements `sql`.
@ -169,7 +169,7 @@ impl StatementCache {
#[inline]
fn flush(&self) {
let mut cache = self.0.borrow_mut();
cache.clear()
cache.clear();
}
}

View File

@ -12,12 +12,14 @@ pub struct Column<'stmt> {
impl Column<'_> {
/// Returns the name of the column.
#[inline]
#[must_use]
pub fn name(&self) -> &str {
self.name
}
/// Returns the type of the column (`None` for expression).
#[inline]
#[must_use]
pub fn decl_type(&self) -> Option<&str> {
self.decl_type
}

View File

@ -64,17 +64,17 @@ pub enum DbConfig {
impl Connection {
/// Returns the current value of a `config`.
///
/// - SQLITE_DBCONFIG_ENABLE_FKEY: return `false` or `true` to indicate
/// - `SQLITE_DBCONFIG_ENABLE_FKEY`: return `false` or `true` to indicate
/// whether FK enforcement is off or on
/// - SQLITE_DBCONFIG_ENABLE_TRIGGER: return `false` or `true` to indicate
/// - `SQLITE_DBCONFIG_ENABLE_TRIGGER`: return `false` or `true` to indicate
/// whether triggers are disabled or enabled
/// - SQLITE_DBCONFIG_ENABLE_FTS3_TOKENIZER: return `false` or `true` to
/// indicate whether fts3_tokenizer are disabled or enabled
/// - SQLITE_DBCONFIG_NO_CKPT_ON_CLOSE: return `false` to indicate
/// - `SQLITE_DBCONFIG_ENABLE_FTS3_TOKENIZER`: return `false` or `true` to
/// indicate whether `fts3_tokenizer` are disabled or enabled
/// - `SQLITE_DBCONFIG_NO_CKPT_ON_CLOSE`: return `false` to indicate
/// checkpoints-on-close are not disabled or `true` if they are
/// - SQLITE_DBCONFIG_ENABLE_QPSG: return `false` or `true` to indicate
/// - `SQLITE_DBCONFIG_ENABLE_QPSG`: return `false` or `true` to indicate
/// whether the QPSG is disabled or enabled
/// - SQLITE_DBCONFIG_TRIGGER_EQP: return `false` to indicate
/// - `SQLITE_DBCONFIG_TRIGGER_EQP`: return `false` to indicate
/// output-for-trigger are not disabled or `true` if it is
#[inline]
pub fn db_config(&self, config: DbConfig) -> Result<bool> {
@ -93,17 +93,17 @@ impl Connection {
/// Make configuration changes to a database connection
///
/// - SQLITE_DBCONFIG_ENABLE_FKEY: `false` to disable FK enforcement, `true`
/// - `SQLITE_DBCONFIG_ENABLE_FKEY`: `false` to disable FK enforcement, `true`
/// to enable FK enforcement
/// - SQLITE_DBCONFIG_ENABLE_TRIGGER: `false` to disable triggers, `true` to
/// - `SQLITE_DBCONFIG_ENABLE_TRIGGER`: `false` to disable triggers, `true` to
/// enable triggers
/// - SQLITE_DBCONFIG_ENABLE_FTS3_TOKENIZER: `false` to disable
/// fts3_tokenizer(), `true` to enable fts3_tokenizer()
/// - SQLITE_DBCONFIG_NO_CKPT_ON_CLOSE: `false` (the default) to enable
/// - `SQLITE_DBCONFIG_ENABLE_FTS3_TOKENIZER`: `false` to disable
/// `fts3_tokenizer()`, `true` to enable `fts3_tokenizer()`
/// - `SQLITE_DBCONFIG_NO_CKPT_ON_CLOSE`: `false` (the default) to enable
/// checkpoints-on-close, `true` to disable them
/// - SQLITE_DBCONFIG_ENABLE_QPSG: `false` to disable the QPSG, `true` to
/// - `SQLITE_DBCONFIG_ENABLE_QPSG`: `false` to disable the QPSG, `true` to
/// enable QPSG
/// - SQLITE_DBCONFIG_TRIGGER_EQP: `false` to disable output for trigger
/// - `SQLITE_DBCONFIG_TRIGGER_EQP`: `false` to disable output for trigger
/// programs, `true` to enable it
#[inline]
pub fn set_db_config(&self, config: DbConfig, new_val: bool) -> Result<bool> {

View File

@ -58,7 +58,7 @@ pub(super) unsafe fn set_result(ctx: *mut sqlite3_context, result: &ToSqlOutput<
if length > c_int::max_value() as usize {
ffi::sqlite3_result_error_toobig(ctx);
} else if length == 0 {
ffi::sqlite3_result_zeroblob(ctx, 0)
ffi::sqlite3_result_zeroblob(ctx, 0);
} else {
ffi::sqlite3_result_blob(
ctx,

View File

@ -84,20 +84,17 @@ unsafe fn report_error(ctx: *mut sqlite3_context, err: &Error) {
ffi::SQLITE_CONSTRAINT
}
match *err {
Error::SqliteFailure(ref err, ref s) => {
if let Error::SqliteFailure(ref err, ref s) = *err {
ffi::sqlite3_result_error_code(ctx, err.extended_code);
if let Some(Ok(cstr)) = s.as_ref().map(|s| str_to_cstring(s)) {
ffi::sqlite3_result_error(ctx, cstr.as_ptr(), -1);
}
}
_ => {
} else {
ffi::sqlite3_result_error_code(ctx, constraint_error_code());
if let Ok(cstr) = str_to_cstring(&err.to_string()) {
ffi::sqlite3_result_error(ctx, cstr.as_ptr(), -1);
}
}
}
}
unsafe extern "C" fn free_boxed_value<T>(p: *mut c_void) {
@ -114,12 +111,14 @@ pub struct Context<'a> {
impl Context<'_> {
/// Returns the number of arguments to the function.
#[inline]
#[must_use]
pub fn len(&self) -> usize {
self.args.len()
}
/// Returns `true` when there is no argument.
#[inline]
#[must_use]
pub fn is_empty(&self) -> bool {
self.args.is_empty()
}
@ -157,6 +156,7 @@ impl Context<'_> {
/// Will panic if `idx` is greater than or equal to
/// [`self.len()`](Context::len).
#[inline]
#[must_use]
pub fn get_raw(&self, idx: usize) -> ValueRef<'_> {
let arg = self.args[idx];
unsafe { ValueRef::from_value(arg) }
@ -200,7 +200,7 @@ impl Context<'_> {
arg,
raw.cast(),
Some(free_boxed_value::<AuxInner>),
)
);
};
Ok(orig)
}
@ -287,7 +287,7 @@ where
fn finalize(&self, _: &mut Context<'_>, _: Option<A>) -> Result<T>;
}
/// WindowAggregate is the callback interface for
/// `WindowAggregate` is the callback interface for
/// user-defined aggregate window function.
#[cfg(feature = "window")]
#[cfg_attr(docsrs, doc(cfg(feature = "window")))]
@ -617,12 +617,11 @@ unsafe extern "C" fn call_boxed_step<A, D, T>(
D: Aggregate<A, T>,
T: ToSql,
{
let pac = match aggregate_context(ctx, ::std::mem::size_of::<*mut A>()) {
Some(pac) => pac,
None => {
let pac = if let Some(pac) = aggregate_context(ctx, ::std::mem::size_of::<*mut A>()) {
pac
} else {
ffi::sqlite3_result_error_nomem(ctx);
return;
}
};
let r = catch_unwind(|| {
@ -665,12 +664,11 @@ unsafe extern "C" fn call_boxed_inverse<A, W, T>(
W: WindowAggregate<A, T>,
T: ToSql,
{
let pac = match aggregate_context(ctx, ::std::mem::size_of::<*mut A>()) {
Some(pac) => pac,
None => {
let pac = if let Some(pac) = aggregate_context(ctx, ::std::mem::size_of::<*mut A>()) {
pac
} else {
ffi::sqlite3_result_error_nomem(ctx);
return;
}
};
let r = catch_unwind(|| {

View File

@ -367,8 +367,8 @@ impl Connection {
///
/// The callback parameters are:
///
/// - the type of database update (SQLITE_INSERT, SQLITE_UPDATE or
/// SQLITE_DELETE),
/// - the type of database update (`SQLITE_INSERT`, `SQLITE_UPDATE` or
/// `SQLITE_DELETE`),
/// - the name of the database ("main", "temp", ...),
/// - the name of the table that is updated,
/// - the ROWID of the row that is updated.
@ -402,7 +402,7 @@ impl Connection {
where
F: for<'r> FnMut(AuthContext<'r>) -> Authorization + Send + RefUnwindSafe + 'static,
{
self.db.borrow_mut().authorizer(hook)
self.db.borrow_mut().authorizer(hook);
}
}
@ -577,8 +577,7 @@ impl InnerConnection {
}
}
match handler {
Some(handler) => {
if let Some(handler) = handler {
let boxed_handler = Box::new(handler);
unsafe {
ffi::sqlite3_progress_handler(
@ -586,14 +585,12 @@ impl InnerConnection {
num_ops,
Some(call_boxed_closure::<F>),
&*boxed_handler as *const F as *mut _,
)
);
}
self.progress_handler = Some(boxed_handler);
}
_ => {
} else {
unsafe { ffi::sqlite3_progress_handler(self.db(), num_ops, None, ptr::null_mut()) }
self.progress_handler = None;
}
};
}
@ -629,8 +626,7 @@ impl InnerConnection {
let boxed_hook: *mut F = p_arg.cast::<F>();
(*boxed_hook)(auth_ctx)
})
.map(Authorization::into_raw)
.unwrap_or_else(|_| ffi::SQLITE_ERROR)
.map_or_else(|_| ffi::SQLITE_ERROR, Authorization::into_raw)
}
let callback_fn = authorizer
@ -644,8 +640,7 @@ impl InnerConnection {
callback_fn,
boxed_authorizer
.as_ref()
.map(|f| &**f as *const F as *mut _)
.unwrap_or_else(ptr::null_mut),
.map_or_else(ptr::null_mut, |f| &**f as *const F as *mut _),
)
} {
ffi::SQLITE_OK => {

View File

@ -450,7 +450,7 @@ impl Connection {
///
/// # Failure
///
/// Will return `Err` if vfs` cannot be converted to a C-compatible
/// Will return `Err` if `vfs` cannot be converted to a C-compatible
/// string or if the underlying SQLite open call fails.
#[inline]
pub fn open_in_memory_with_flags_and_vfs(flags: OpenFlags, vfs: &str) -> Result<Connection> {

View File

@ -99,7 +99,7 @@ use sealed::Sealed;
///
/// - As a slice of `&[(&str, &dyn ToSql)]`. This is what essentially all of
/// these boil down to in the end, conceptually at least. In theory you can
/// pass this as `stmt.
/// pass this as `stmt`.
///
/// - As array references, similar to the positional params. This looks like
/// `thing.query(&[(":foo", &1i32), (":bar", &2i32)])` or

View File

@ -143,7 +143,7 @@ impl Sql {
if ch == quote {
self.buf.push(ch);
}
self.buf.push(ch)
self.buf.push(ch);
}
self.buf.push(quote);
}

View File

@ -1,5 +1,6 @@
use super::ffi;
use super::StatementStatus;
use crate::util::ParamIndexCache;
#[cfg(feature = "modern_sqlite")]
use crate::util::SqliteMallocString;
use std::ffi::CStr;
@ -13,7 +14,7 @@ pub struct RawStatement {
ptr: *mut ffi::sqlite3_stmt,
tail: usize,
// Cached indices of named parameters, computed on the fly.
cache: crate::util::ParamIndexCache,
cache: ParamIndexCache,
// Cached SQL (trimmed) that we use as the key when we're in the statement
// cache. This is None for statements which didn't come from the statement
// cache.
@ -33,7 +34,7 @@ impl RawStatement {
RawStatement {
ptr: stmt,
tail,
cache: Default::default(),
cache: ParamIndexCache::default(),
statement_cache_key: None,
}
}

View File

@ -80,6 +80,7 @@ impl<'stmt> Rows<'stmt> {
}
/// Give access to the underlying statement
#[must_use]
pub fn as_ref(&self) -> Option<&Statement<'stmt>> {
self.stmt
}
@ -187,7 +188,7 @@ where
/// `FallibleStreamingIterator` differs from the standard library's `Iterator`
/// in two ways:
/// * each call to `next` (sqlite3_step) can fail.
/// * each call to `next` (`sqlite3_step`) can fail.
/// * returned `Row` is valid until `next` is called again or `Statement` is
/// reset or finalized.
///
@ -209,8 +210,8 @@ impl<'stmt> FallibleStreamingIterator for Rows<'stmt> {
#[inline]
fn advance(&mut self) -> Result<()> {
match self.stmt {
Some(stmt) => match stmt.step() {
if let Some(stmt) = self.stmt {
match stmt.step() {
Ok(true) => {
self.row = Some(Row { stmt });
Ok(())
@ -225,13 +226,12 @@ impl<'stmt> FallibleStreamingIterator for Rows<'stmt> {
self.row = None;
Err(e)
}
},
None => {
}
} else {
self.row = None;
Ok(())
}
}
}
#[inline]
fn get(&self) -> Option<&Row<'stmt>> {

View File

@ -31,19 +31,18 @@ pub unsafe fn config_log(callback: Option<fn(c_int, &str)>) -> Result<()> {
let callback: fn(c_int, &str) = unsafe { mem::transmute(p_arg) };
let s = String::from_utf8_lossy(c_slice);
let _ = catch_unwind(|| callback(err, &s));
drop(catch_unwind(|| callback(err, &s)));
}
let rc = match callback {
Some(f) => ffi::sqlite3_config(
let rc = if let Some(f) = callback {
ffi::sqlite3_config(
ffi::SQLITE_CONFIG_LOG,
log_callback as extern "C" fn(_, _, _),
f as *mut c_void,
),
None => {
)
} else {
let nullptr: *mut c_void = ptr::null_mut();
ffi::sqlite3_config(ffi::SQLITE_CONFIG_LOG, nullptr, nullptr)
}
};
if rc == ffi::SQLITE_OK {
@ -75,7 +74,7 @@ impl Connection {
let trace_fn: fn(&str) = mem::transmute(p_arg);
let c_slice = CStr::from_ptr(z_sql).to_bytes();
let s = String::from_utf8_lossy(c_slice);
let _ = catch_unwind(|| trace_fn(&s));
drop(catch_unwind(|| trace_fn(&s)));
}
let c = self.db.borrow_mut();
@ -109,7 +108,7 @@ impl Connection {
nanoseconds / NANOS_PER_SEC,
(nanoseconds % NANOS_PER_SEC) as u32,
);
let _ = catch_unwind(|| profile_fn(&s, duration));
drop(catch_unwind(|| profile_fn(&s, duration)));
}
let c = self.db.borrow_mut();

View File

@ -169,6 +169,7 @@ impl Transaction<'_> {
/// Get the current setting for what happens to the transaction when it is
/// dropped.
#[inline]
#[must_use]
pub fn drop_behavior(&self) -> DropBehavior {
self.drop_behavior
}
@ -177,7 +178,7 @@ impl Transaction<'_> {
/// dropped.
#[inline]
pub fn set_drop_behavior(&mut self, drop_behavior: DropBehavior) {
self.drop_behavior = drop_behavior
self.drop_behavior = drop_behavior;
}
/// A convenience method which consumes and commits a transaction.
@ -296,6 +297,7 @@ impl Savepoint<'_> {
/// Get the current setting for what happens to the savepoint when it is
/// dropped.
#[inline]
#[must_use]
pub fn drop_behavior(&self) -> DropBehavior {
self.drop_behavior
}
@ -304,7 +306,7 @@ impl Savepoint<'_> {
/// dropped.
#[inline]
pub fn set_drop_behavior(&mut self, drop_behavior: DropBehavior) {
self.drop_behavior = drop_behavior
self.drop_behavior = drop_behavior;
}
/// A convenience method which consumes and commits a savepoint.

View File

@ -177,7 +177,7 @@ impl FromSql for std::sync::Arc<str> {
impl FromSql for Vec<u8> {
#[inline]
fn column_result(value: ValueRef<'_>) -> FromSqlResult<Self> {
value.as_blob().map(|b| b.to_vec())
value.as_blob().map(<[u8]>::to_vec)
}
}
@ -198,7 +198,7 @@ impl FromSql for i128 {
#[inline]
fn column_result(value: ValueRef<'_>) -> FromSqlResult<Self> {
let bytes = <[u8; 16]>::column_result(value)?;
Ok(i128::from_be_bytes(bytes) ^ (1i128 << 127))
Ok(i128::from_be_bytes(bytes) ^ (1_i128 << 127))
}
}

View File

@ -47,7 +47,7 @@ impl FromSql for OffsetDateTime {
len if len <= 19 => {
// TODO YYYY-MM-DDTHH:MM:SS
PrimitiveDateTime::parse(s, &PRIMITIVE_SHORT_DATE_TIME_FORMAT)
.map(|d| d.assume_utc())
.map(PrimitiveDateTime::assume_utc)
}
_ if s.as_bytes()[19] == b':' => {
// legacy
@ -56,7 +56,7 @@ impl FromSql for OffsetDateTime {
_ if s.as_bytes()[19] == b'.' => OffsetDateTime::parse(s, &OFFSET_DATE_TIME_FORMAT)
.or_else(|err| {
PrimitiveDateTime::parse(s, &PRIMITIVE_DATE_TIME_FORMAT)
.map(|d| d.assume_utc())
.map(PrimitiveDateTime::assume_utc)
.map_err(|_| err)
}),
_ => OffsetDateTime::parse(s, &OFFSET_SHORT_DATE_TIME_FORMAT),

View File

@ -47,7 +47,7 @@ impl From<i128> for Value {
fn from(i: i128) -> Value {
// We store these biased (e.g. with the most significant bit flipped)
// so that comparisons with negative numbers work properly.
Value::Blob(i128::to_be_bytes(i ^ (1i128 << 127)).to_vec())
Value::Blob(i128::to_be_bytes(i ^ (1_i128 << 127)).to_vec())
}
}
@ -129,6 +129,7 @@ where
impl Value {
/// Returns SQLite fundamental datatype.
#[inline]
#[must_use]
pub fn data_type(&self) -> Type {
match *self {
Value::Null => Type::Null,

View File

@ -22,6 +22,7 @@ pub enum ValueRef<'a> {
impl ValueRef<'_> {
/// Returns SQLite fundamental datatype.
#[inline]
#[must_use]
pub fn data_type(&self) -> Type {
match *self {
ValueRef::Null => Type::Null,

View File

@ -45,7 +45,7 @@ unsafe extern "C" fn unlock_notify_cb(ap_arg: *mut *mut c_void, n_arg: c_int) {
use std::slice::from_raw_parts;
let args = from_raw_parts(ap_arg as *const &UnlockNotification, n_arg as usize);
for un in args {
let _ = catch_unwind(std::panic::AssertUnwindSafe(|| un.fired()));
drop(catch_unwind(std::panic::AssertUnwindSafe(|| un.fired())));
}
}

View File

@ -1,7 +1,7 @@
use smallvec::{smallvec, SmallVec};
use std::ffi::{CStr, CString, NulError};
/// Similar to std::ffi::CString, but avoids heap allocating if the string is
/// Similar to `std::ffi::CString`, but avoids heap allocating if the string is
/// small enough. Also guarantees it's input is UTF-8 -- used for cases where we
/// need to pass a NUL-terminated string to SQLite, and we have a `&str`.
#[derive(Clone, PartialEq, Eq, PartialOrd, Ord)]
@ -10,7 +10,7 @@ pub(crate) struct SmallCString(smallvec::SmallVec<[u8; 16]>);
impl SmallCString {
#[inline]
pub fn new(s: &str) -> Result<Self, NulError> {
if s.as_bytes().contains(&0u8) {
if s.as_bytes().contains(&0_u8) {
return Err(Self::fabricate_nul_error(s));
}
let mut buf = SmallVec::with_capacity(s.len() + 1);
@ -31,7 +31,7 @@ impl SmallCString {
/// Get the bytes not including the NUL terminator. E.g. the bytes which
/// make up our `str`:
/// - `SmallCString::new("foo").as_bytes_without_nul() == b"foo"`
/// - `SmallCString::new("foo").as_bytes_with_nul() == b"foo\0"
/// - `SmallCString::new("foo").as_bytes_with_nul() == b"foo\0"`
#[inline]
pub fn as_bytes_without_nul(&self) -> &[u8] {
self.debug_checks();

View File

@ -38,7 +38,7 @@ pub(crate) struct SqliteMallocString {
impl SqliteMallocString {
/// SAFETY: Caller must be certain that `m` a nul-terminated c string
/// allocated by sqlite3_malloc, and that SQLite expects us to free it!
/// allocated by `sqlite3_malloc`, and that SQLite expects us to free it!
#[inline]
pub(crate) unsafe fn from_raw_nonnull(ptr: NonNull<c_char>) -> Self {
Self {
@ -48,7 +48,7 @@ impl SqliteMallocString {
}
/// SAFETY: Caller must be certain that `m` a nul-terminated c string
/// allocated by sqlite3_malloc, and that SQLite expects us to free it!
/// allocated by `sqlite3_malloc`, and that SQLite expects us to free it!
#[inline]
pub(crate) unsafe fn from_raw(ptr: *mut c_char) -> Option<Self> {
NonNull::new(ptr).map(|p| Self::from_raw_nonnull(p))
@ -95,13 +95,13 @@ impl SqliteMallocString {
/// If `s` contains internal NULs, we'll replace them with
/// `NUL_REPLACE_CHAR`.
///
/// Except for debug_asserts which may trigger during testing, this function
/// Except for `debug_assert`s which may trigger during testing, this function
/// never panics. If we hit integer overflow or the allocation fails, we
/// call `handle_alloc_error` which aborts the program after calling a
/// global hook.
///
/// This means it's safe to use in extern "C" functions even outside of
/// catch_unwind.
/// `catch_unwind`.
pub(crate) fn from_str(s: &str) -> Self {
use std::convert::TryFrom;
let s = if s.as_bytes().contains(&0) {

View File

@ -6,6 +6,7 @@ use std::ffi::CStr;
///
/// See [`sqlite3_libversion_number()`](https://www.sqlite.org/c3ref/libversion.html).
#[inline]
#[must_use]
pub fn version_number() -> i32 {
unsafe { ffi::sqlite3_libversion_number() }
}
@ -14,6 +15,7 @@ pub fn version_number() -> i32 {
///
/// See [`sqlite3_libversion()`](https://www.sqlite.org/c3ref/libversion.html).
#[inline]
#[must_use]
pub fn version() -> &'static str {
let cstr = unsafe { CStr::from_ptr(ffi::sqlite3_libversion()) };
cstr.to_str()

View File

@ -44,7 +44,7 @@ use crate::{Connection, Result};
pub(crate) const ARRAY_TYPE: *const c_char = (b"rarray\0" as *const u8).cast::<c_char>();
pub(crate) unsafe extern "C" fn free_array(p: *mut c_void) {
let _: Array = Rc::from_raw(p as *const Vec<Value>);
drop(Rc::from_raw(p as *const Vec<Value>));
}
/// Array parameter / pointer
@ -106,11 +106,11 @@ unsafe impl<'vtab> VTab<'vtab> for ArrayTab {
}
}
if ptr_idx {
info.set_estimated_cost(1f64);
info.set_estimated_cost(1_f64);
info.set_estimated_rows(100);
info.set_idx_num(1);
} else {
info.set_estimated_cost(2_147_483_647f64);
info.set_estimated_cost(2_147_483_647_f64);
info.set_estimated_rows(2_147_483_647);
info.set_idx_num(0);
}

View File

@ -79,7 +79,7 @@ union ModuleZeroHack {
// structs are allowed to be zeroed.
const ZERO_MODULE: ffi::sqlite3_module = unsafe {
ModuleZeroHack {
bytes: [0u8; std::mem::size_of::<ffi::sqlite3_module>()],
bytes: [0_u8; std::mem::size_of::<ffi::sqlite3_module>()],
}
.module
};
@ -87,6 +87,7 @@ const ZERO_MODULE: ffi::sqlite3_module = unsafe {
/// Create a read-only virtual table implementation.
///
/// Step 2 of [Creating New Virtual Table Implementations](https://sqlite.org/vtab.html#creating_new_virtual_table_implementations).
#[must_use]
pub fn read_only_module<'vtab, T: CreateVTab<'vtab>>() -> &'static Module<'vtab, T> {
// The xConnect and xCreate methods do the same thing, but they must be
// different so that the virtual table is not an eponymous virtual table.
@ -126,6 +127,7 @@ pub fn read_only_module<'vtab, T: CreateVTab<'vtab>>() -> &'static Module<'vtab,
/// Create an eponymous only virtual table implementation.
///
/// Step 2 of [Creating New Virtual Table Implementations](https://sqlite.org/vtab.html#creating_new_virtual_table_implementations).
#[must_use]
pub fn eponymous_only_module<'vtab, T: VTab<'vtab>>() -> &'static Module<'vtab, T> {
// A virtual table is eponymous if its xCreate method is the exact same function
// as the xConnect method For eponymous-only virtual tables, the xCreate
@ -193,7 +195,7 @@ impl VTabConnection {
///
/// # Safety
///
/// The first item in a struct implementing VTab must be
/// The first item in a struct implementing `VTab` must be
/// `rusqlite::sqlite3_vtab`, and the struct must be `#[repr(C)]`.
///
/// ```rust,ignore
@ -326,6 +328,7 @@ impl IndexInfo {
/// Record WHERE clause constraints.
#[inline]
#[must_use]
pub fn constraints(&self) -> IndexConstraintIter<'_> {
let constraints =
unsafe { slice::from_raw_parts((*self.0).aConstraint, (*self.0).nConstraint as usize) };
@ -336,6 +339,7 @@ impl IndexInfo {
/// Information about the ORDER BY clause.
#[inline]
#[must_use]
pub fn order_bys(&self) -> OrderByIter<'_> {
let order_bys =
unsafe { slice::from_raw_parts((*self.0).aOrderBy, (*self.0).nOrderBy as usize) };
@ -346,6 +350,7 @@ impl IndexInfo {
/// Number of terms in the ORDER BY clause
#[inline]
#[must_use]
pub fn num_of_order_by(&self) -> usize {
unsafe { (*self.0).nOrderBy as usize }
}
@ -448,18 +453,21 @@ pub struct IndexConstraint<'a>(&'a ffi::sqlite3_index_constraint);
impl IndexConstraint<'_> {
/// Column constrained. -1 for ROWID
#[inline]
#[must_use]
pub fn column(&self) -> c_int {
self.0.iColumn
}
/// Constraint operator
#[inline]
#[must_use]
pub fn operator(&self) -> IndexConstraintOp {
IndexConstraintOp::from(self.0.op)
}
/// True if this constraint is usable
#[inline]
#[must_use]
pub fn is_usable(&self) -> bool {
self.0.usable != 0
}
@ -509,12 +517,14 @@ pub struct OrderBy<'a>(&'a ffi::sqlite3_index_info_sqlite3_index_orderby);
impl OrderBy<'_> {
/// Column number
#[inline]
#[must_use]
pub fn column(&self) -> c_int {
self.0.iColumn
}
/// True for DESC. False for ASC.
#[inline]
#[must_use]
pub fn is_order_by_desc(&self) -> bool {
self.0.desc != 0
}
@ -581,12 +591,14 @@ pub struct Values<'a> {
impl Values<'_> {
/// Returns the number of values.
#[inline]
#[must_use]
pub fn len(&self) -> usize {
self.args.len()
}
/// Returns `true` if there is no value.
#[inline]
#[must_use]
pub fn is_empty(&self) -> bool {
self.args.is_empty()
}
@ -629,6 +641,7 @@ impl Values<'_> {
/// Turns `Values` into an iterator.
#[inline]
#[must_use]
pub fn iter(&self) -> ValueIter<'_> {
ValueIter {
iter: self.args.iter(),
@ -720,6 +733,7 @@ impl InnerConnection {
/// Escape double-quote (`"`) character occurrences by
/// doubling them (`""`).
#[must_use]
pub fn escape_double_quote(identifier: &str) -> Cow<'_, str> {
if identifier.contains('"') {
// escape quote by doubling them
@ -729,6 +743,7 @@ pub fn escape_double_quote(identifier: &str) -> Cow<'_, str> {
}
}
/// Dequote string
#[must_use]
pub fn dequote(s: &str) -> &str {
if s.len() < 2 {
return s;
@ -746,6 +761,7 @@ pub fn dequote(s: &str) -> &str {
/// 1 yes true on
/// 0 no false off
/// ```
#[must_use]
pub fn parse_boolean(s: &str) -> Option<bool> {
if s.eq_ignore_ascii_case("yes")
|| s.eq_ignore_ascii_case("on")
@ -919,7 +935,7 @@ where
let vt = vtab.cast::<T>();
match (*vt).destroy() {
Ok(_) => {
let _: Box<T> = Box::from_raw(vt);
drop(Box::from_raw(vt));
ffi::SQLITE_OK
}
Err(Error::SqliteFailure(err, s)) => {