Merge remote-tracking branch 'jgallagher/master' into vtab

This commit is contained in:
gwenn 2017-09-11 19:45:22 +02:00
commit c842e789bd
29 changed files with 576 additions and 430 deletions

1
.gitattributes vendored Normal file
View File

@ -0,0 +1 @@
libsqlite3-sys/sqlite3 linguist-vendored

View File

@ -18,3 +18,7 @@ rusqlite contributors
* [Omar Ferrer](https://github.com/chamakits)
* [Lee Jenkins](https://github.com/reddraggone9)
* [miedzinski](https://github.com/miedzinski)
* [aidanhs](https://github.com/aidanhs)
* [Steven Fackler](https://github.com/sfackler)
* [Davide Aversa](https://github.com/THeK3nger)
* [mcgoo](https://github.com/mcgoo)

View File

@ -1,6 +1,6 @@
[package]
name = "rusqlite"
version = "0.11.0"
version = "0.12.0"
authors = ["John Gallagher <jgallagher@bignerdranch.com>"]
description = "Ergonomic wrapper for SQLite"
repository = "https://github.com/jgallagher/rusqlite"
@ -30,11 +30,11 @@ vtab = ["libsqlite3-sys/min_sqlite_version_3_7_7"]
csvtab = ["csv"]
[dependencies]
time = "0.1"
bitflags = "0.7"
time = "0.1.0"
bitflags = "0.9"
lru-cache = "0.1"
chrono = { version = "0.3", optional = true }
serde_json = { version = "0.9", optional = true }
serde_json = { version = "1.0", optional = true }
[dev-dependencies]
tempdir = "0.3"

View File

@ -1,3 +1,10 @@
# Version 0.12.0 (2017-05-29)
* Defines HAVE\_USLEEP when building with a bundled SQLite (#263).
* Updates dependencies to their latest versions, particularly serde to 1.0.
* Adds support for vcpkg on Windows.
* Adds `ToSql` impls for `str` and `[u8]`.
# Version 0.11.0 (2017-04-06)
* Avoid publicly exporting SQLite constants multiple times from libsqlite3-sys.

View File

@ -94,17 +94,27 @@ features](http://doc.crates.io/manifest.html#the-features-section). They are:
## Notes on building rusqlite and libsqlite3-sys
`libsqlite3-sys` is a separate crate from `rusqlite` that provides the Rust
declarations for SQLite's C API. By default, `libsqlite3-sys` attempts to use
pkg-config to find a SQLite library that already exists on your system. You can
adjust this behavior in a couple of ways:
declarations for SQLite's C API. By default, `libsqlite3-sys` attempts to find a SQLite library that already exists on your system using pkg-config, or a
[Vcpkg](https://github.com/Microsoft/vcpkg) installation for MSVC ABI builds.
You can adjust this behavior in a number of ways:
* If you use the `bundled` feature, `libsqlite3-sys` will use the
[gcc](https://crates.io/crates/gcc) crate to compile SQLite from source and
link against that. This source is embedded in the `libsqlite3-sys` crate and
is currently SQLite 3.17.0 (as of `rusqlite` 0.10.1 / `libsqlite3-sys`
0.7.1). This is probably the simplest solution to any build problems.
0.7.1). This is probably the simplest solution to any build problems. You can enable this by adding the following in your `Cargo.toml` file:
```
[dependencies.rusqlite]
version = "0.11.0"
features = ["bundled"]
```
* You can set the `SQLITE3_LIB_DIR` to point to directory containing the SQLite
library.
* Installing the sqlite3 development packages will usually be all that is required, but
the build helpers for [pkg-config](https://github.com/alexcrichton/pkg-config-rs)
and [vcpkg](https://github.com/mcgoo/vcpkg-rs) have some additional configuration
options. The default when using vcpkg is to dynamically link. `vcpkg install sqlite3:x64-windows` will install the required library.
### Binding generation

View File

@ -1,6 +1,12 @@
environment:
TARGET: 1.15.0-x86_64-pc-windows-gnu
matrix:
- TARGET: 1.15.0-x86_64-pc-windows-gnu
MSYS2_BITS: 64
- TARGET: 1.15.0-x86_64-pc-windows-msvc
VCPKG_DEFAULT_TRIPLET: x64-windows
- TARGET: nightly-x86_64-pc-windows-msvc
VCPKG_DEFAULT_TRIPLET: x64-windows-static
RUSTFLAGS: -Ctarget-feature=+crt-static
install:
- ps: Start-FileDownload "https://static.rust-lang.org/dist/rust-${env:TARGET}.exe"
- rust-%TARGET%.exe /VERYSILENT /NORESTART /DIR="C:\Program Files (x86)\Rust"
@ -9,11 +15,18 @@ install:
- rustc -V
- cargo -V
- ps: Start-FileDownload 'https://sqlite.org/2017/sqlite-dll-win64-x64-3170000.zip' # download SQLite dll (useful only when the `bundled` feature is not set)
- cmd: 7z e sqlite-dll-win64-x64-3170000.zip -y > nul
- if not defined VCPKG_DEFAULT_TRIPLET 7z e sqlite-dll-win64-x64-3170000.zip -y > nul
- ps: Start-FileDownload 'https://sqlite.org/2017/sqlite-amalgamation-3170000.zip' # download SQLite headers (useful only when the `bundled` feature is not set)
- cmd: 7z e sqlite-amalgamation-3170000.zip -y > nul
- SET SQLITE3_LIB_DIR=%APPVEYOR_BUILD_FOLDER% # specify where the SQLite dll has been downloaded (useful only when the `bundled` feature is not set)
- SET SQLITE3_INCLUDE_DIR=%APPVEYOR_BUILD_FOLDER% # specify where the SQLite headers have been downloaded (useful only when the `bundled` feature is not set)
- if not defined VCPKG_DEFAULT_TRIPLET 7z e sqlite-amalgamation-3170000.zip -y > nul
- if not defined VCPKG_DEFAULT_TRIPLET SET SQLITE3_LIB_DIR=%APPVEYOR_BUILD_FOLDER% # specify where the SQLite dll has been downloaded (useful only when the `bundled` feature is not set)
- if not defined VCPKG_DEFAULT_TRIPLET SET SQLITE3_INCLUDE_DIR=%APPVEYOR_BUILD_FOLDER% # specify where the SQLite headers have been downloaded (useful only when the `bundled` feature is not set)
# install vcpkg and the sqlite3 package
- if defined VCPKG_DEFAULT_TRIPLET git clone https://github.com/Microsoft/vcpkg c:\projects\vcpkg
- if defined VCPKG_DEFAULT_TRIPLET c:\projects\vcpkg\bootstrap-vcpkg.bat
- if defined VCPKG_DEFAULT_TRIPLET set VCPKG_ROOT=c:\projects\vcpkg
- if defined VCPKG_DEFAULT_TRIPLET %VCPKG_ROOT%\vcpkg.exe install sqlite3
- if defined VCPKG_DEFAULT_TRIPLET appveyor DownloadFile http://releases.llvm.org/4.0.0/LLVM-4.0.0-win64.exe
- if defined VCPKG_DEFAULT_TRIPLET LLVM-4.0.0-win64.exe /S
build: false

View File

@ -1,6 +1,6 @@
[package]
name = "libsqlite3-sys"
version = "0.8.0"
version = "0.8.1"
authors = ["John Gallagher <jgallagher@bignerdranch.com>"]
repository = "https://github.com/jgallagher/rusqlite"
description = "Native bindings to the libsqlite3 library"
@ -13,16 +13,19 @@ categories = ["database", "external-ffi-bindings"]
[features]
default = ["min_sqlite_version_3_6_8"]
bundled = ["gcc"]
buildtime_bindgen = ["bindgen", "pkg-config"]
min_sqlite_version_3_6_8 = ["pkg-config"]
min_sqlite_version_3_6_11 = ["pkg-config"]
min_sqlite_version_3_6_23 = ["pkg-config"]
min_sqlite_version_3_7_3 = ["pkg-config"]
min_sqlite_version_3_7_4 = ["pkg-config"]
min_sqlite_version_3_7_7 = ["pkg-config"]
min_sqlite_version_3_7_16 = ["pkg-config"]
buildtime_bindgen = ["bindgen", "pkg-config", "vcpkg"]
min_sqlite_version_3_6_8 = ["pkg-config", "vcpkg"]
min_sqlite_version_3_6_11 = ["pkg-config", "vcpkg"]
min_sqlite_version_3_6_23 = ["pkg-config", "vcpkg"]
min_sqlite_version_3_7_3 = ["pkg-config", "vcpkg"]
min_sqlite_version_3_7_4 = ["pkg-config", "vcpkg"]
min_sqlite_version_3_7_7 = ["pkg-config", "vcpkg"]
min_sqlite_version_3_7_16 = ["pkg-config", "vcpkg"]
[build-dependencies]
bindgen = { version = "0.21", optional = true }
bindgen = { version = "0.23", optional = true }
pkg-config = { version = "0.3", optional = true }
gcc = { version = "0.3", optional = true }
[target.'cfg(target_env = "msvc")'.build-dependencies]
vcpkg = { version = "0.2", optional = true }

View File

@ -34,6 +34,7 @@ mod build {
.flag("-DSQLITE_SOUNDEX")
.flag("-DSQLITE_THREADSAFE=1")
.flag("-DSQLITE_USE_URI")
.flag("-DHAVE_USLEEP=1")
.compile("libsqlite3.a");
}
}
@ -42,6 +43,9 @@ mod build {
mod build {
extern crate pkg_config;
#[cfg(all(feature = "vcpkg", target_env = "msvc"))]
extern crate vcpkg;
use std::env;
pub enum HeaderLocation {
@ -79,6 +83,10 @@ mod build {
return HeaderLocation::FromEnvironment;
}
if let Some(header) = try_vcpkg() {
return header;
}
// See if pkg-config can do everything for us.
match pkg_config::Config::new().print_system_libs(false).probe("sqlite3") {
Ok(mut lib) => {
@ -100,6 +108,23 @@ mod build {
}
}
#[cfg(all(feature = "vcpkg", target_env = "msvc"))]
fn try_vcpkg() -> Option<HeaderLocation> {
// See if vcpkg can find it.
if let Ok(mut lib) = vcpkg::Config::new().probe("sqlite3") {
if let Some(mut header) = lib.include_paths.pop() {
header.push("sqlite3.h");
return Some(HeaderLocation::FromPath(header.to_string_lossy().into()));
}
}
None
}
#[cfg(not(all(feature = "vcpkg", target_env = "msvc")))]
fn try_vcpkg() -> Option<HeaderLocation> {
None
}
#[cfg(not(feature = "buildtime_bindgen"))]
mod bindings {
use super::HeaderLocation;
@ -142,7 +167,7 @@ mod build {
mod bindings {
extern crate bindgen;
use self::bindgen::chooser::{TypeChooser, IntKind};
use self::bindgen::callbacks::{ParseCallbacks, IntKind};
use super::HeaderLocation;
use std::env;
@ -153,7 +178,7 @@ mod build {
#[derive(Debug)]
struct SqliteTypeChooser;
impl TypeChooser for SqliteTypeChooser {
impl ParseCallbacks for SqliteTypeChooser {
fn int_macro(&self, _name: &str, value: i64) -> Option<IntKind> {
if value >= i32::min_value() as i64 && value <= i32::max_value() as i64 {
Some(IntKind::I32)
@ -169,7 +194,7 @@ mod build {
let mut output = Vec::new();
bindgen::builder()
.header(header.clone())
.type_chooser(Box::new(SqliteTypeChooser))
.parse_callbacks(Box::new(SqliteTypeChooser))
.generate()
.expect(&format!("could not run bindgen on header {}", header))
.write(Box::new(&mut output))

View File

@ -64,29 +64,29 @@ pub struct Error {
impl Error {
pub fn new(result_code: c_int) -> Error {
let code = match result_code & 0xff {
SQLITE_INTERNAL => ErrorCode::InternalMalfunction,
SQLITE_PERM => ErrorCode::PermissionDenied,
SQLITE_ABORT => ErrorCode::OperationAborted,
SQLITE_BUSY => ErrorCode::DatabaseBusy,
SQLITE_LOCKED => ErrorCode::DatabaseLocked,
SQLITE_NOMEM => ErrorCode::OutOfMemory,
SQLITE_READONLY => ErrorCode::ReadOnly,
SQLITE_INTERRUPT => ErrorCode::OperationInterrupted,
SQLITE_IOERR => ErrorCode::SystemIOFailure,
SQLITE_CORRUPT => ErrorCode::DatabaseCorrupt,
SQLITE_NOTFOUND => ErrorCode::NotFound,
SQLITE_FULL => ErrorCode::DiskFull,
SQLITE_CANTOPEN => ErrorCode::CannotOpen,
SQLITE_PROTOCOL => ErrorCode::FileLockingProtocolFailed,
SQLITE_SCHEMA => ErrorCode::SchemaChanged,
SQLITE_TOOBIG => ErrorCode::TooBig,
SQLITE_CONSTRAINT=> ErrorCode::ConstraintViolation,
SQLITE_MISMATCH => ErrorCode::TypeMismatch,
SQLITE_MISUSE => ErrorCode::APIMisuse,
SQLITE_NOLFS => ErrorCode::NoLargeFileSupport,
SQLITE_AUTH => ErrorCode::AuthorizationForStatementDenied,
SQLITE_RANGE => ErrorCode::ParameterOutOfRange,
SQLITE_NOTADB => ErrorCode::NotADatabase,
super::SQLITE_INTERNAL => ErrorCode::InternalMalfunction,
super::SQLITE_PERM => ErrorCode::PermissionDenied,
super::SQLITE_ABORT => ErrorCode::OperationAborted,
super::SQLITE_BUSY => ErrorCode::DatabaseBusy,
super::SQLITE_LOCKED => ErrorCode::DatabaseLocked,
super::SQLITE_NOMEM => ErrorCode::OutOfMemory,
super::SQLITE_READONLY => ErrorCode::ReadOnly,
super::SQLITE_INTERRUPT => ErrorCode::OperationInterrupted,
super::SQLITE_IOERR => ErrorCode::SystemIOFailure,
super::SQLITE_CORRUPT => ErrorCode::DatabaseCorrupt,
super::SQLITE_NOTFOUND => ErrorCode::NotFound,
super::SQLITE_FULL => ErrorCode::DiskFull,
super::SQLITE_CANTOPEN => ErrorCode::CannotOpen,
super::SQLITE_PROTOCOL => ErrorCode::FileLockingProtocolFailed,
super::SQLITE_SCHEMA => ErrorCode::SchemaChanged,
super::SQLITE_TOOBIG => ErrorCode::TooBig,
super::SQLITE_CONSTRAINT=> ErrorCode::ConstraintViolation,
super::SQLITE_MISMATCH => ErrorCode::TypeMismatch,
super::SQLITE_MISUSE => ErrorCode::APIMisuse,
super::SQLITE_NOLFS => ErrorCode::NoLargeFileSupport,
super::SQLITE_AUTH => ErrorCode::AuthorizationForStatementDenied,
super::SQLITE_RANGE => ErrorCode::ParameterOutOfRange,
super::SQLITE_NOTADB => ErrorCode::NotADatabase,
_ => ErrorCode::Unknown,
};
@ -114,146 +114,100 @@ impl error::Error for Error {
// in the current version of SQLite. We repeat them here so we don't have to worry about which
// version of SQLite added which constants, and we only use them to implement code_to_str below.
const SQLITE_OK : c_int = 0;
const SQLITE_ERROR : c_int = 1;
const SQLITE_INTERNAL : c_int = 2;
const SQLITE_PERM : c_int = 3;
const SQLITE_ABORT : c_int = 4;
const SQLITE_BUSY : c_int = 5;
const SQLITE_LOCKED : c_int = 6;
const SQLITE_NOMEM : c_int = 7;
const SQLITE_READONLY : c_int = 8;
const SQLITE_INTERRUPT : c_int = 9;
const SQLITE_IOERR : c_int = 10;
const SQLITE_CORRUPT : c_int = 11;
const SQLITE_NOTFOUND : c_int = 12;
const SQLITE_FULL : c_int = 13;
const SQLITE_CANTOPEN : c_int = 14;
const SQLITE_PROTOCOL : c_int = 15;
const SQLITE_EMPTY : c_int = 16;
const SQLITE_SCHEMA : c_int = 17;
const SQLITE_TOOBIG : c_int = 18;
const SQLITE_CONSTRAINT: c_int = 19;
const SQLITE_MISMATCH : c_int = 20;
const SQLITE_MISUSE : c_int = 21;
const SQLITE_NOLFS : c_int = 22;
const SQLITE_AUTH : c_int = 23;
const SQLITE_FORMAT : c_int = 24;
const SQLITE_RANGE : c_int = 25;
const SQLITE_NOTADB : c_int = 26;
const SQLITE_NOTICE : c_int = 27;
const SQLITE_WARNING : c_int = 28;
const SQLITE_ROW : c_int = 100;
const SQLITE_DONE : c_int = 101;
// Extended result codes.
const SQLITE_IOERR_READ : c_int = (SQLITE_IOERR | (1<<8));
const SQLITE_IOERR_SHORT_READ : c_int = (SQLITE_IOERR | (2<<8));
const SQLITE_IOERR_WRITE : c_int = (SQLITE_IOERR | (3<<8));
const SQLITE_IOERR_FSYNC : c_int = (SQLITE_IOERR | (4<<8));
const SQLITE_IOERR_DIR_FSYNC : c_int = (SQLITE_IOERR | (5<<8));
const SQLITE_IOERR_TRUNCATE : c_int = (SQLITE_IOERR | (6<<8));
const SQLITE_IOERR_FSTAT : c_int = (SQLITE_IOERR | (7<<8));
const SQLITE_IOERR_UNLOCK : c_int = (SQLITE_IOERR | (8<<8));
const SQLITE_IOERR_RDLOCK : c_int = (SQLITE_IOERR | (9<<8));
const SQLITE_IOERR_DELETE : c_int = (SQLITE_IOERR | (10<<8));
const SQLITE_IOERR_BLOCKED : c_int = (SQLITE_IOERR | (11<<8));
const SQLITE_IOERR_NOMEM : c_int = (SQLITE_IOERR | (12<<8));
const SQLITE_IOERR_ACCESS : c_int = (SQLITE_IOERR | (13<<8));
const SQLITE_IOERR_CHECKRESERVEDLOCK : c_int = (SQLITE_IOERR | (14<<8));
const SQLITE_IOERR_LOCK : c_int = (SQLITE_IOERR | (15<<8));
const SQLITE_IOERR_CLOSE : c_int = (SQLITE_IOERR | (16<<8));
const SQLITE_IOERR_DIR_CLOSE : c_int = (SQLITE_IOERR | (17<<8));
const SQLITE_IOERR_SHMOPEN : c_int = (SQLITE_IOERR | (18<<8));
const SQLITE_IOERR_SHMSIZE : c_int = (SQLITE_IOERR | (19<<8));
const SQLITE_IOERR_SHMLOCK : c_int = (SQLITE_IOERR | (20<<8));
const SQLITE_IOERR_SHMMAP : c_int = (SQLITE_IOERR | (21<<8));
const SQLITE_IOERR_SEEK : c_int = (SQLITE_IOERR | (22<<8));
const SQLITE_IOERR_DELETE_NOENT : c_int = (SQLITE_IOERR | (23<<8));
const SQLITE_IOERR_MMAP : c_int = (SQLITE_IOERR | (24<<8));
const SQLITE_IOERR_GETTEMPPATH : c_int = (SQLITE_IOERR | (25<<8));
const SQLITE_IOERR_CONVPATH : c_int = (SQLITE_IOERR | (26<<8));
const SQLITE_IOERR_VNODE : c_int = (SQLITE_IOERR | (27<<8));
const SQLITE_LOCKED_SHAREDCACHE : c_int = (SQLITE_LOCKED | (1<<8));
const SQLITE_BUSY_RECOVERY : c_int = (SQLITE_BUSY | (1<<8));
const SQLITE_BUSY_SNAPSHOT : c_int = (SQLITE_BUSY | (2<<8));
const SQLITE_CANTOPEN_NOTEMPDIR : c_int = (SQLITE_CANTOPEN | (1<<8));
const SQLITE_CANTOPEN_ISDIR : c_int = (SQLITE_CANTOPEN | (2<<8));
const SQLITE_CANTOPEN_FULLPATH : c_int = (SQLITE_CANTOPEN | (3<<8));
const SQLITE_CANTOPEN_CONVPATH : c_int = (SQLITE_CANTOPEN | (4<<8));
const SQLITE_CORRUPT_VTAB : c_int = (SQLITE_CORRUPT | (1<<8));
const SQLITE_READONLY_RECOVERY : c_int = (SQLITE_READONLY | (1<<8));
const SQLITE_READONLY_CANTLOCK : c_int = (SQLITE_READONLY | (2<<8));
const SQLITE_READONLY_ROLLBACK : c_int = (SQLITE_READONLY | (3<<8));
const SQLITE_READONLY_DBMOVED : c_int = (SQLITE_READONLY | (4<<8));
const SQLITE_ABORT_ROLLBACK : c_int = (SQLITE_ABORT | (2<<8));
const SQLITE_CONSTRAINT_CHECK : c_int = (SQLITE_CONSTRAINT | (1<<8));
const SQLITE_CONSTRAINT_COMMITHOOK : c_int = (SQLITE_CONSTRAINT | (2<<8));
const SQLITE_CONSTRAINT_FOREIGNKEY : c_int = (SQLITE_CONSTRAINT | (3<<8));
const SQLITE_CONSTRAINT_FUNCTION : c_int = (SQLITE_CONSTRAINT | (4<<8));
const SQLITE_CONSTRAINT_NOTNULL : c_int = (SQLITE_CONSTRAINT | (5<<8));
const SQLITE_CONSTRAINT_PRIMARYKEY : c_int = (SQLITE_CONSTRAINT | (6<<8));
const SQLITE_CONSTRAINT_TRIGGER : c_int = (SQLITE_CONSTRAINT | (7<<8));
const SQLITE_CONSTRAINT_UNIQUE : c_int = (SQLITE_CONSTRAINT | (8<<8));
const SQLITE_CONSTRAINT_VTAB : c_int = (SQLITE_CONSTRAINT | (9<<8));
const SQLITE_CONSTRAINT_ROWID : c_int = (SQLITE_CONSTRAINT |(10<<8));
const SQLITE_IOERR_SHMOPEN : c_int = (super::SQLITE_IOERR | (18<<8));
const SQLITE_IOERR_SHMSIZE : c_int = (super::SQLITE_IOERR | (19<<8));
const SQLITE_IOERR_SHMLOCK : c_int = (super::SQLITE_IOERR | (20<<8));
const SQLITE_IOERR_SHMMAP : c_int = (super::SQLITE_IOERR | (21<<8));
const SQLITE_IOERR_SEEK : c_int = (super::SQLITE_IOERR | (22<<8));
const SQLITE_IOERR_DELETE_NOENT : c_int = (super::SQLITE_IOERR | (23<<8));
const SQLITE_IOERR_MMAP : c_int = (super::SQLITE_IOERR | (24<<8));
const SQLITE_IOERR_GETTEMPPATH : c_int = (super::SQLITE_IOERR | (25<<8));
const SQLITE_IOERR_CONVPATH : c_int = (super::SQLITE_IOERR | (26<<8));
const SQLITE_IOERR_VNODE : c_int = (super::SQLITE_IOERR | (27<<8));
const SQLITE_LOCKED_SHAREDCACHE : c_int = (super::SQLITE_LOCKED | (1<<8));
const SQLITE_BUSY_RECOVERY : c_int = (super::SQLITE_BUSY | (1<<8));
const SQLITE_BUSY_SNAPSHOT : c_int = (super::SQLITE_BUSY | (2<<8));
const SQLITE_CANTOPEN_NOTEMPDIR : c_int = (super::SQLITE_CANTOPEN | (1<<8));
const SQLITE_CANTOPEN_ISDIR : c_int = (super::SQLITE_CANTOPEN | (2<<8));
const SQLITE_CANTOPEN_FULLPATH : c_int = (super::SQLITE_CANTOPEN | (3<<8));
const SQLITE_CANTOPEN_CONVPATH : c_int = (super::SQLITE_CANTOPEN | (4<<8));
const SQLITE_CORRUPT_VTAB : c_int = (super::SQLITE_CORRUPT | (1<<8));
const SQLITE_READONLY_RECOVERY : c_int = (super::SQLITE_READONLY | (1<<8));
const SQLITE_READONLY_CANTLOCK : c_int = (super::SQLITE_READONLY | (2<<8));
const SQLITE_READONLY_ROLLBACK : c_int = (super::SQLITE_READONLY | (3<<8));
const SQLITE_READONLY_DBMOVED : c_int = (super::SQLITE_READONLY | (4<<8));
const SQLITE_ABORT_ROLLBACK : c_int = (super::SQLITE_ABORT | (2<<8));
const SQLITE_CONSTRAINT_CHECK : c_int = (super::SQLITE_CONSTRAINT | (1<<8));
const SQLITE_CONSTRAINT_COMMITHOOK : c_int = (super::SQLITE_CONSTRAINT | (2<<8));
const SQLITE_CONSTRAINT_FOREIGNKEY : c_int = (super::SQLITE_CONSTRAINT | (3<<8));
const SQLITE_CONSTRAINT_FUNCTION : c_int = (super::SQLITE_CONSTRAINT | (4<<8));
const SQLITE_CONSTRAINT_NOTNULL : c_int = (super::SQLITE_CONSTRAINT | (5<<8));
const SQLITE_CONSTRAINT_PRIMARYKEY : c_int = (super::SQLITE_CONSTRAINT | (6<<8));
const SQLITE_CONSTRAINT_TRIGGER : c_int = (super::SQLITE_CONSTRAINT | (7<<8));
const SQLITE_CONSTRAINT_UNIQUE : c_int = (super::SQLITE_CONSTRAINT | (8<<8));
const SQLITE_CONSTRAINT_VTAB : c_int = (super::SQLITE_CONSTRAINT | (9<<8));
const SQLITE_CONSTRAINT_ROWID : c_int = (super::SQLITE_CONSTRAINT |(10<<8));
const SQLITE_NOTICE_RECOVER_WAL : c_int = (SQLITE_NOTICE | (1<<8));
const SQLITE_NOTICE_RECOVER_ROLLBACK : c_int = (SQLITE_NOTICE | (2<<8));
const SQLITE_WARNING_AUTOINDEX : c_int = (SQLITE_WARNING | (1<<8));
const SQLITE_AUTH_USER : c_int = (SQLITE_AUTH | (1<<8));
const SQLITE_AUTH_USER : c_int = (super::SQLITE_AUTH | (1<<8));
pub fn code_to_str(code: c_int) -> &'static str {
match code {
SQLITE_OK => "Successful result",
SQLITE_ERROR => "SQL error or missing database",
SQLITE_INTERNAL => "Internal logic error in SQLite",
SQLITE_PERM => "Access permission denied",
SQLITE_ABORT => "Callback routine requested an abort",
SQLITE_BUSY => "The database file is locked",
SQLITE_LOCKED => "A table in the database is locked",
SQLITE_NOMEM => "A malloc() failed",
SQLITE_READONLY => "Attempt to write a readonly database",
SQLITE_INTERRUPT => "Operation terminated by sqlite3_interrupt()",
SQLITE_IOERR => "Some kind of disk I/O error occurred",
SQLITE_CORRUPT => "The database disk image is malformed",
SQLITE_NOTFOUND => "Unknown opcode in sqlite3_file_control()",
SQLITE_FULL => "Insertion failed because database is full",
SQLITE_CANTOPEN => "Unable to open the database file",
SQLITE_PROTOCOL => "Database lock protocol error",
SQLITE_EMPTY => "Database is empty",
SQLITE_SCHEMA => "The database schema changed",
SQLITE_TOOBIG => "String or BLOB exceeds size limit",
SQLITE_CONSTRAINT=> "Abort due to constraint violation",
SQLITE_MISMATCH => "Data type mismatch",
SQLITE_MISUSE => "Library used incorrectly",
SQLITE_NOLFS => "Uses OS features not supported on host",
SQLITE_AUTH => "Authorization denied",
SQLITE_FORMAT => "Auxiliary database format error",
SQLITE_RANGE => "2nd parameter to sqlite3_bind out of range",
SQLITE_NOTADB => "File opened that is not a database file",
super::SQLITE_OK => "Successful result",
super::SQLITE_ERROR => "SQL error or missing database",
super::SQLITE_INTERNAL => "Internal logic error in SQLite",
super::SQLITE_PERM => "Access permission denied",
super::SQLITE_ABORT => "Callback routine requested an abort",
super::SQLITE_BUSY => "The database file is locked",
super::SQLITE_LOCKED => "A table in the database is locked",
super::SQLITE_NOMEM => "A malloc() failed",
super::SQLITE_READONLY => "Attempt to write a readonly database",
super::SQLITE_INTERRUPT => "Operation terminated by sqlite3_interrupt()",
super::SQLITE_IOERR => "Some kind of disk I/O error occurred",
super::SQLITE_CORRUPT => "The database disk image is malformed",
super::SQLITE_NOTFOUND => "Unknown opcode in sqlite3_file_control()",
super::SQLITE_FULL => "Insertion failed because database is full",
super::SQLITE_CANTOPEN => "Unable to open the database file",
super::SQLITE_PROTOCOL => "Database lock protocol error",
super::SQLITE_EMPTY => "Database is empty",
super::SQLITE_SCHEMA => "The database schema changed",
super::SQLITE_TOOBIG => "String or BLOB exceeds size limit",
super::SQLITE_CONSTRAINT=> "Abort due to constraint violation",
super::SQLITE_MISMATCH => "Data type mismatch",
super::SQLITE_MISUSE => "Library used incorrectly",
super::SQLITE_NOLFS => "Uses OS features not supported on host",
super::SQLITE_AUTH => "Authorization denied",
super::SQLITE_FORMAT => "Auxiliary database format error",
super::SQLITE_RANGE => "2nd parameter to sqlite3_bind out of range",
super::SQLITE_NOTADB => "File opened that is not a database file",
SQLITE_NOTICE => "Notifications from sqlite3_log()",
SQLITE_WARNING => "Warnings from sqlite3_log()",
SQLITE_ROW => "sqlite3_step() has another row ready",
SQLITE_DONE => "sqlite3_step() has finished executing",
super::SQLITE_ROW => "sqlite3_step() has another row ready",
super::SQLITE_DONE => "sqlite3_step() has finished executing",
SQLITE_IOERR_READ => "Error reading from disk",
SQLITE_IOERR_SHORT_READ => "Unable to obtain number of requested bytes (file truncated?)",
SQLITE_IOERR_WRITE => "Error writing to disk",
SQLITE_IOERR_FSYNC => "Error flushing data to persistent storage (fsync)",
SQLITE_IOERR_DIR_FSYNC => "Error calling fsync on a directory",
SQLITE_IOERR_TRUNCATE => "Error attempting to truncate file",
SQLITE_IOERR_FSTAT => "Error invoking fstat to get file metadata",
SQLITE_IOERR_UNLOCK => "I/O error within xUnlock of a VFS object",
SQLITE_IOERR_RDLOCK => "I/O error within xLock of a VFS object (trying to obtain a read lock)",
SQLITE_IOERR_DELETE => "I/O error within xDelete of a VFS object",
SQLITE_IOERR_BLOCKED => "SQLITE_IOERR_BLOCKED", // no longer used
SQLITE_IOERR_NOMEM => "Out of memory in I/O layer",
SQLITE_IOERR_ACCESS => "I/O error within xAccess of a VFS object",
SQLITE_IOERR_CHECKRESERVEDLOCK => "I/O error within then xCheckReservedLock method",
SQLITE_IOERR_LOCK => "I/O error in the advisory file locking layer",
SQLITE_IOERR_CLOSE => "I/O error within the xClose method",
SQLITE_IOERR_DIR_CLOSE => "SQLITE_IOERR_DIR_CLOSE", // no longer used
super::SQLITE_IOERR_READ => "Error reading from disk",
super::SQLITE_IOERR_SHORT_READ => "Unable to obtain number of requested bytes (file truncated?)",
super::SQLITE_IOERR_WRITE => "Error writing to disk",
super::SQLITE_IOERR_FSYNC => "Error flushing data to persistent storage (fsync)",
super::SQLITE_IOERR_DIR_FSYNC => "Error calling fsync on a directory",
super::SQLITE_IOERR_TRUNCATE => "Error attempting to truncate file",
super::SQLITE_IOERR_FSTAT => "Error invoking fstat to get file metadata",
super::SQLITE_IOERR_UNLOCK => "I/O error within xUnlock of a VFS object",
super::SQLITE_IOERR_RDLOCK => "I/O error within xLock of a VFS object (trying to obtain a read lock)",
super::SQLITE_IOERR_DELETE => "I/O error within xDelete of a VFS object",
super::SQLITE_IOERR_BLOCKED => "SQLITE_IOERR_BLOCKED", // no longer used
super::SQLITE_IOERR_NOMEM => "Out of memory in I/O layer",
super::SQLITE_IOERR_ACCESS => "I/O error within xAccess of a VFS object",
super::SQLITE_IOERR_CHECKRESERVEDLOCK => "I/O error within then xCheckReservedLock method",
super::SQLITE_IOERR_LOCK => "I/O error in the advisory file locking layer",
super::SQLITE_IOERR_CLOSE => "I/O error within the xClose method",
super::SQLITE_IOERR_DIR_CLOSE => "SQLITE_IOERR_DIR_CLOSE", // no longer used
SQLITE_IOERR_SHMOPEN => "I/O error within the xShmMap method (trying to open a new shared-memory segment)",
SQLITE_IOERR_SHMSIZE => "I/O error within the xShmMap method (trying to resize an existing shared-memory segment)",
SQLITE_IOERR_SHMLOCK => "SQLITE_IOERR_SHMLOCK", // no longer used

View File

@ -19,26 +19,26 @@ pub fn SQLITE_TRANSIENT() -> sqlite3_destructor_type {
#[repr(C)]
pub enum Limit {
/// The maximum size of any string or BLOB or table row, in bytes.
SQLITE_LIMIT_LENGTH = 0,
SQLITE_LIMIT_LENGTH = SQLITE_LIMIT_LENGTH as isize,
/// The maximum length of an SQL statement, in bytes.
SQLITE_LIMIT_SQL_LENGTH = 1,
SQLITE_LIMIT_SQL_LENGTH = SQLITE_LIMIT_SQL_LENGTH as isize,
/// The maximum number of columns in a table definition or in the result set of a SELECT
/// or the maximum number of columns in an index or in an ORDER BY or GROUP BY clause.
SQLITE_LIMIT_COLUMN = 2,
SQLITE_LIMIT_COLUMN = SQLITE_LIMIT_COLUMN as isize,
/// The maximum depth of the parse tree on any expression.
SQLITE_LIMIT_EXPR_DEPTH = 3,
SQLITE_LIMIT_EXPR_DEPTH = SQLITE_LIMIT_EXPR_DEPTH as isize,
/// The maximum number of terms in a compound SELECT statement.
SQLITE_LIMIT_COMPOUND_SELECT = 4,
SQLITE_LIMIT_COMPOUND_SELECT = SQLITE_LIMIT_COMPOUND_SELECT as isize,
/// The maximum number of instructions in a virtual machine program used to implement an SQL statement.
SQLITE_LIMIT_VDBE_OP = 5,
SQLITE_LIMIT_VDBE_OP = SQLITE_LIMIT_VDBE_OP as isize,
/// The maximum number of arguments on a function.
SQLITE_LIMIT_FUNCTION_ARG = 6,
SQLITE_LIMIT_FUNCTION_ARG = SQLITE_LIMIT_FUNCTION_ARG as isize,
/// The maximum number of attached databases.
SQLITE_LIMIT_ATTACHED = 7,
SQLITE_LIMIT_ATTACHED = SQLITE_LIMIT_ATTACHED as isize,
/// The maximum length of the pattern argument to the LIKE or GLOB operators.
SQLITE_LIMIT_LIKE_PATTERN_LENGTH = 8,
SQLITE_LIMIT_LIKE_PATTERN_LENGTH = SQLITE_LIMIT_LIKE_PATTERN_LENGTH as isize,
/// The maximum index number of any parameter in an SQL statement.
SQLITE_LIMIT_VARIABLE_NUMBER = 9,
SQLITE_LIMIT_VARIABLE_NUMBER = SQLITE_LIMIT_VARIABLE_NUMBER as isize,
/// The maximum depth of recursion for triggers.
SQLITE_LIMIT_TRIGGER_DEPTH = 10,
/// The maximum number of auxiliary worker threads that a single prepared statement may start.

View File

@ -92,7 +92,8 @@ impl Connection {
if read_only { 0 } else { 1 },
&mut blob)
};
c.decode_result(rc).map(|_| {
c.decode_result(rc)
.map(|_| {
Blob {
conn: self,
blob: blob,
@ -266,7 +267,8 @@ mod test {
fn test_blob() {
let (db, rowid) = db_with_test_blob().unwrap();
let mut blob = db.blob_open(DatabaseName::Main, "test", "content", rowid, false).unwrap();
let mut blob = db.blob_open(DatabaseName::Main, "test", "content", rowid, false)
.unwrap();
assert_eq!(4, blob.write(b"Clob").unwrap());
assert_eq!(6, blob.write(b"567890xxxxxx").unwrap()); // cannot write past 10
assert_eq!(0, blob.write(b"5678").unwrap()); // still cannot write past 10
@ -274,7 +276,8 @@ mod test {
blob.reopen(rowid).unwrap();
blob.close().unwrap();
blob = db.blob_open(DatabaseName::Main, "test", "content", rowid, true).unwrap();
blob = db.blob_open(DatabaseName::Main, "test", "content", rowid, true)
.unwrap();
let mut bytes = [0u8; 5];
assert_eq!(5, blob.read(&mut bytes[..]).unwrap());
assert_eq!(&bytes, b"Clob5");
@ -314,7 +317,8 @@ mod test {
fn test_blob_in_bufreader() {
let (db, rowid) = db_with_test_blob().unwrap();
let mut blob = db.blob_open(DatabaseName::Main, "test", "content", rowid, false).unwrap();
let mut blob = db.blob_open(DatabaseName::Main, "test", "content", rowid, false)
.unwrap();
assert_eq!(8, blob.write(b"one\ntwo\n").unwrap());
blob.reopen(rowid).unwrap();
@ -338,7 +342,8 @@ mod test {
let (db, rowid) = db_with_test_blob().unwrap();
{
let blob = db.blob_open(DatabaseName::Main, "test", "content", rowid, false).unwrap();
let blob = db.blob_open(DatabaseName::Main, "test", "content", rowid, false)
.unwrap();
let mut writer = BufWriter::new(blob);
// trying to write too much and then flush should fail
@ -357,7 +362,8 @@ mod test {
}
{
let blob = db.blob_open(DatabaseName::Main, "test", "content", rowid, false).unwrap();
let blob = db.blob_open(DatabaseName::Main, "test", "content", rowid, false)
.unwrap();
let mut writer = BufWriter::new(blob);
// trying to write_all too much should fail

View File

@ -280,7 +280,8 @@ mod test {
#[test]
fn test_connection_close() {
let conn = Connection::open_in_memory().unwrap();
conn.prepare_cached("SELECT * FROM sqlite_master;").unwrap();
conn.prepare_cached("SELECT * FROM sqlite_master;")
.unwrap();
conn.close().expect("connection not closed");
}

View File

@ -145,18 +145,14 @@ impl error::Error for Error {
match *self {
Error::SqliteFailure(ref err, None) => err.description(),
Error::SqliteFailure(_, Some(ref s)) => s,
Error::SqliteSingleThreadedMode => {
"SQLite was compiled or configured for single-threaded use only"
}
Error::SqliteSingleThreadedMode => "SQLite was compiled or configured for single-threaded use only",
Error::FromSqlConversionFailure(_, _, ref err) => err.description(),
Error::IntegralValueOutOfRange(_, _) => "integral value out of range of requested type",
Error::Utf8Error(ref err) => err.description(),
Error::InvalidParameterName(_) => "invalid parameter name",
Error::NulError(ref err) => err.description(),
Error::InvalidPath(_) => "invalid path",
Error::ExecuteReturnedResults => {
"execute returned results - did you mean to call query?"
}
Error::ExecuteReturnedResults => "execute returned results - did you mean to call query?",
Error::QueryReturnedNoRows => "query returned no rows",
Error::InvalidColumnIndex(_) => "invalid column index",
Error::InvalidColumnName(_) => "invalid column name",

View File

@ -119,9 +119,13 @@ pub unsafe fn report_error(ctx: *mut sqlite3_context, err: &Error) {
// if we're on the bundled version (since it's at least 3.17.0) and the normal constraint
// error code if not.
#[cfg(feature = "bundled")]
fn constraint_error_code() -> i32 { ffi::SQLITE_CONSTRAINT_FUNCTION }
fn constraint_error_code() -> i32 {
ffi::SQLITE_CONSTRAINT_FUNCTION
}
#[cfg(not(feature = "bundled"))]
fn constraint_error_code() -> i32 { ffi::SQLITE_CONSTRAINT }
fn constraint_error_code() -> i32 {
ffi::SQLITE_CONSTRAINT
}
match *err {
Error::SqliteFailure(ref err, ref s) => {
@ -154,19 +158,24 @@ impl<'a> ValueRef<'a> {
let s = CStr::from_ptr(text as *const c_char);
// sqlite3_value_text returns UTF8 data, so our unwrap here should be fine.
let s = s.to_str().expect("sqlite3_value_text returned invalid UTF-8");
let s = s.to_str()
.expect("sqlite3_value_text returned invalid UTF-8");
ValueRef::Text(s)
}
ffi::SQLITE_BLOB => {
let blob = ffi::sqlite3_value_blob(value);
assert!(!blob.is_null(),
"unexpected SQLITE_BLOB value type with NULL data");
let (blob, len) = (ffi::sqlite3_value_blob(value), ffi::sqlite3_value_bytes(value));
let len = ffi::sqlite3_value_bytes(value);
assert!(len >= 0,
"unexpected negative return from sqlite3_value_bytes");
if len > 0 {
assert!(!blob.is_null(),
"unexpected SQLITE_BLOB value type with NULL data");
ValueRef::Blob(from_raw_parts(blob as *const u8, len as usize))
} else {
// The return value from sqlite3_value_blob() for a zero-length BLOB
// is a NULL pointer.
ValueRef::Blob(&[])
}
}
_ => unreachable!("sqlite3_value_type returned invalid value"),
}
@ -207,7 +216,10 @@ impl<'a> Context<'a> {
FromSqlError::InvalidType => {
Error::InvalidFunctionParameterType(idx, value.data_type())
}
FromSqlError::OutOfRange(i) => Error::IntegralValueOutOfRange(idx as c_int, i),
FromSqlError::OutOfRange(i) => {
Error::IntegralValueOutOfRange(idx as c_int,
i)
}
FromSqlError::Other(err) => {
Error::FromSqlConversionFailure(idx, value.data_type(), err)
}
@ -304,7 +316,9 @@ impl Connection {
where F: FnMut(&Context) -> Result<T>,
T: ToSql
{
self.db.borrow_mut().create_scalar_function(fn_name, n_arg, deterministic, x_func)
self.db
.borrow_mut()
.create_scalar_function(fn_name, n_arg, deterministic, x_func)
}
/// Attach a user-defined aggregate function to this database connection.
@ -720,17 +734,16 @@ mod test {
#[test]
fn test_sum() {
let db = Connection::open_in_memory().unwrap();
db.create_aggregate_function("my_sum", 1, true, Sum).unwrap();
db.create_aggregate_function("my_sum", 1, true, Sum)
.unwrap();
// sum should return NULL when given no columns (contrast with count below)
let no_result = "SELECT my_sum(i) FROM (SELECT 2 AS i WHERE 1 <> 1)";
let result: Option<i64> = db.query_row(no_result, &[], |r| r.get(0))
.unwrap();
let result: Option<i64> = db.query_row(no_result, &[], |r| r.get(0)).unwrap();
assert!(result.is_none());
let single_sum = "SELECT my_sum(i) FROM (SELECT 2 AS i UNION ALL SELECT 2)";
let result: i64 = db.query_row(single_sum, &[], |r| r.get(0))
.unwrap();
let result: i64 = db.query_row(single_sum, &[], |r| r.get(0)).unwrap();
assert_eq!(4, result);
let dual_sum = "SELECT my_sum(i), my_sum(j) FROM (SELECT 2 AS i, 1 AS j UNION ALL SELECT \
@ -743,7 +756,8 @@ mod test {
#[test]
fn test_count() {
let db = Connection::open_in_memory().unwrap();
db.create_aggregate_function("my_count", -1, true, Count).unwrap();
db.create_aggregate_function("my_count", -1, true, Count)
.unwrap();
// count should return 0 when given no columns (contrast with sum above)
let no_result = "SELECT my_count(i) FROM (SELECT 2 AS i WHERE 1 <> 1)";
@ -751,8 +765,7 @@ mod test {
assert_eq!(result, 0);
let single_sum = "SELECT my_count(i) FROM (SELECT 2 AS i UNION ALL SELECT 2)";
let result: i64 = db.query_row(single_sum, &[], |r| r.get(0))
.unwrap();
let result: i64 = db.query_row(single_sum, &[], |r| r.get(0)).unwrap();
assert_eq!(2, result);
}
}

View File

@ -297,7 +297,8 @@ impl Connection {
/// Will return `Err` if `sql` cannot be converted to a C-compatible string or if the
/// underlying SQLite call fails.
pub fn execute(&self, sql: &str, params: &[&ToSql]) -> Result<c_int> {
self.prepare(sql).and_then(|mut stmt| stmt.execute(params))
self.prepare(sql)
.and_then(|mut stmt| stmt.execute(params))
}
/// Convenience method to prepare and execute a single SQL statement with named parameter(s).
@ -319,7 +320,8 @@ impl Connection {
/// Will return `Err` if `sql` cannot be converted to a C-compatible string or if the
/// underlying SQLite call fails.
pub fn execute_named(&self, sql: &str, params: &[(&str, &ToSql)]) -> Result<c_int> {
self.prepare(sql).and_then(|mut stmt| stmt.execute_named(params))
self.prepare(sql)
.and_then(|mut stmt| stmt.execute_named(params))
}
/// Get the SQLite rowid of the most recent successful INSERT.
@ -408,7 +410,9 @@ impl Connection {
let mut stmt = try!(self.prepare(sql));
let mut rows = try!(stmt.query(params));
rows.get_expected_row().map_err(E::from).and_then(|r| f(&r))
rows.get_expected_row()
.map_err(E::from)
.and_then(|r| f(&r))
}
/// Convenience method to execute a query that is expected to return a single row.
@ -536,7 +540,9 @@ impl Connection {
dylib_path: P,
entry_point: Option<&str>)
-> Result<()> {
self.db.borrow_mut().load_extension(dylib_path.as_ref(), entry_point)
self.db
.borrow_mut()
.load_extension(dylib_path.as_ref(), entry_point)
}
/// Get access to the underlying SQLite database connection handle.
@ -580,16 +586,16 @@ bitflags! {
#[doc = "Flags for opening SQLite database connections."]
#[doc = "See [sqlite3_open_v2](http://www.sqlite.org/c3ref/open.html) for details."]
#[repr(C)]
pub flags OpenFlags: ::std::os::raw::c_int {
const SQLITE_OPEN_READ_ONLY = 0x00000001,
const SQLITE_OPEN_READ_WRITE = 0x00000002,
const SQLITE_OPEN_CREATE = 0x00000004,
const SQLITE_OPEN_URI = 0x00000040,
const SQLITE_OPEN_MEMORY = 0x00000080,
const SQLITE_OPEN_NO_MUTEX = 0x00008000,
const SQLITE_OPEN_FULL_MUTEX = 0x00010000,
const SQLITE_OPEN_SHARED_CACHE = 0x00020000,
const SQLITE_OPEN_PRIVATE_CACHE = 0x00040000,
pub struct OpenFlags: ::std::os::raw::c_int {
const SQLITE_OPEN_READ_ONLY = ffi::SQLITE_OPEN_READONLY;
const SQLITE_OPEN_READ_WRITE = ffi::SQLITE_OPEN_READWRITE;
const SQLITE_OPEN_CREATE = ffi::SQLITE_OPEN_CREATE;
const SQLITE_OPEN_URI = 0x00000040;
const SQLITE_OPEN_MEMORY = 0x00000080;
const SQLITE_OPEN_NO_MUTEX = ffi::SQLITE_OPEN_NOMUTEX;
const SQLITE_OPEN_FULL_MUTEX = ffi::SQLITE_OPEN_FULLMUTEX;
const SQLITE_OPEN_SHARED_CACHE = 0x00020000;
const SQLITE_OPEN_PRIVATE_CACHE = 0x00040000;
}
}
@ -851,7 +857,8 @@ impl InnerConnection {
&mut c_stmt,
ptr::null_mut())
};
self.decode_result(r).map(|_| Statement::new(conn, RawStatement::new(c_stmt)))
self.decode_result(r)
.map(|_| Statement::new(conn, RawStatement::new(c_stmt)))
}
fn changes(&mut self) -> c_int {
@ -1001,12 +1008,15 @@ mod test {
db.execute_batch("CREATE TABLE foo(x INTEGER)").unwrap();
assert_eq!(1,
db.execute("INSERT INTO foo(x) VALUES (?)", &[&1i32]).unwrap());
db.execute("INSERT INTO foo(x) VALUES (?)", &[&1i32])
.unwrap());
assert_eq!(1,
db.execute("INSERT INTO foo(x) VALUES (?)", &[&2i32]).unwrap());
db.execute("INSERT INTO foo(x) VALUES (?)", &[&2i32])
.unwrap());
assert_eq!(3i32,
db.query_row::<i32, _>("SELECT SUM(x) FROM foo", &[], |r| r.get(0)).unwrap());
db.query_row::<i32, _>("SELECT SUM(x) FROM foo", &[], |r| r.get(0))
.unwrap());
}
#[test]
@ -1063,7 +1073,8 @@ mod test {
assert_eq!(insert_stmt.execute(&[&2i32]).unwrap(), 1);
assert_eq!(insert_stmt.execute(&[&3i32]).unwrap(), 1);
let mut query = db.prepare("SELECT x FROM foo WHERE x < ? ORDER BY x DESC").unwrap();
let mut query = db.prepare("SELECT x FROM foo WHERE x < ? ORDER BY x DESC")
.unwrap();
{
let mut rows = query.query(&[&4i32]).unwrap();
let mut v = Vec::<i32>::new();
@ -1148,8 +1159,10 @@ mod test {
#[test]
fn test_last_insert_rowid() {
let db = checked_memory_handle();
db.execute_batch("CREATE TABLE foo(x INTEGER PRIMARY KEY)").unwrap();
db.execute_batch("INSERT INTO foo DEFAULT VALUES").unwrap();
db.execute_batch("CREATE TABLE foo(x INTEGER PRIMARY KEY)")
.unwrap();
db.execute_batch("INSERT INTO foo DEFAULT VALUES")
.unwrap();
assert_eq!(db.last_insert_rowid(), 1);

View File

@ -25,7 +25,8 @@ impl<'conn> LoadExtensionGuard<'conn> {
/// Attempt to enable loading extensions. Loading extensions will be disabled when this
/// guard goes out of scope. Cannot be meaningfully nested.
pub fn new(conn: &Connection) -> Result<LoadExtensionGuard> {
conn.load_extension_enable().map(|_| LoadExtensionGuard { conn: conn })
conn.load_extension_enable()
.map(|_| LoadExtensionGuard { conn: conn })
}
}

View File

@ -28,7 +28,8 @@ impl<'stmt> Rows<'stmt> {
/// "streaming iterator". For a more natural interface, consider using `query_map`
/// or `query_and_then` instead, which return types that implement `Iterator`.
pub fn next<'a>(&'a mut self) -> Option<Result<Row<'a, 'stmt>>> {
self.stmt.and_then(|stmt| match stmt.step() {
self.stmt
.and_then(|stmt| match stmt.step() {
Ok(true) => {
Some(Ok(Row {
stmt: stmt,
@ -89,10 +90,7 @@ impl<'stmt, T, F> MappedRowsCrateImpl<'stmt, T, F> for MappedRows<'stmt, F>
where F: FnMut(&Row) -> T
{
fn new(rows: Rows<'stmt>, f: F) -> MappedRows<'stmt, F> {
MappedRows {
rows: rows,
map: f,
}
MappedRows { rows: rows, map: f }
}
}
@ -103,7 +101,9 @@ impl<'conn, T, F> Iterator for MappedRows<'conn, F>
fn next(&mut self) -> Option<Result<T>> {
let map = &mut self.map;
self.rows.next().map(|row_result| row_result.map(|row| (map)(&row)))
self.rows
.next()
.map(|row_result| row_result.map(|row| (map)(&row)))
}
}
@ -124,10 +124,7 @@ impl<'stmt, T, E, F> AndThenRowsCrateImpl<'stmt, T, E, F> for AndThenRows<'stmt,
where F: FnMut(&Row) -> result::Result<T, E>
{
fn new(rows: Rows<'stmt>, f: F) -> AndThenRows<'stmt, F> {
AndThenRows {
rows: rows,
map: f,
}
AndThenRows { rows: rows, map: f }
}
}
@ -139,10 +136,9 @@ impl<'stmt, T, E, F> Iterator for AndThenRows<'stmt, F>
fn next(&mut self) -> Option<Self::Item> {
let map = &mut self.map;
self.rows.next().map(|row_result| {
row_result.map_err(E::from)
.and_then(|row| (map)(&row))
})
self.rows
.next()
.map(|row_result| row_result.map_err(E::from).and_then(|row| (map)(&row)))
}
}
@ -182,8 +178,13 @@ impl<'a, 'stmt> Row<'a, 'stmt> {
let idx = try!(idx.idx(self.stmt));
let value = self.stmt.value_ref(idx);
FromSql::column_result(value).map_err(|err| match err {
FromSqlError::InvalidType => Error::InvalidColumnType(idx, value.data_type()),
FromSqlError::OutOfRange(i) => Error::IntegralValueOutOfRange(idx, i),
FromSqlError::InvalidType => {
Error::InvalidColumnType(idx,
value.data_type())
}
FromSqlError::OutOfRange(i) => {
Error::IntegralValueOutOfRange(idx, i)
}
FromSqlError::Other(err) => {
Error::FromSqlConversionFailure(idx as usize, value.data_type(), err)
}

View File

@ -405,10 +405,15 @@ impl<'conn> Statement<'conn> {
.decode_result(unsafe { ffi::sqlite3_bind_zeroblob(ptr, col, len) });
}
};
self.conn.decode_result(match value {
self.conn
.decode_result(match value {
ValueRef::Null => unsafe { ffi::sqlite3_bind_null(ptr, col) },
ValueRef::Integer(i) => unsafe { ffi::sqlite3_bind_int64(ptr, col, i) },
ValueRef::Real(r) => unsafe { ffi::sqlite3_bind_double(ptr, col, r) },
ValueRef::Integer(i) => unsafe {
ffi::sqlite3_bind_int64(ptr, col, i)
},
ValueRef::Real(r) => unsafe {
ffi::sqlite3_bind_double(ptr, col, r)
},
ValueRef::Text(s) => unsafe {
let length = s.len();
if length > ::std::i32::MAX as usize {
@ -524,7 +529,8 @@ impl<'conn> StatementCrateImpl<'conn> for Statement<'conn> {
};
// sqlite3_column_text returns UTF8 data, so our unwrap here should be fine.
let s = s.to_str().expect("sqlite3_column_text returned invalid UTF-8");
let s = s.to_str()
.expect("sqlite3_column_text returned invalid UTF-8");
ValueRef::Text(s)
}
ffi::SQLITE_BLOB => {
@ -570,9 +576,11 @@ mod test {
let db = Connection::open_in_memory().unwrap();
db.execute_batch("CREATE TABLE foo(x INTEGER)").unwrap();
assert_eq!(db.execute_named("INSERT INTO foo(x) VALUES (:x)", &[(":x", &1i32)]).unwrap(),
assert_eq!(db.execute_named("INSERT INTO foo(x) VALUES (:x)", &[(":x", &1i32)])
.unwrap(),
1);
assert_eq!(db.execute_named("INSERT INTO foo(x) VALUES (:x)", &[(":x", &2i32)]).unwrap(),
assert_eq!(db.execute_named("INSERT INTO foo(x) VALUES (:x)", &[(":x", &2i32)])
.unwrap(),
1);
assert_eq!(3i32,
@ -589,7 +597,8 @@ mod test {
INTEGER)";
db.execute_batch(sql).unwrap();
let mut stmt = db.prepare("INSERT INTO test (name) VALUES (:name)").unwrap();
let mut stmt = db.prepare("INSERT INTO test (name) VALUES (:name)")
.unwrap();
stmt.execute_named(&[(":name", &"one")]).unwrap();
assert_eq!(1i32,
@ -608,7 +617,8 @@ mod test {
"#;
db.execute_batch(sql).unwrap();
let mut stmt = db.prepare("SELECT id FROM test where name = :name").unwrap();
let mut stmt = db.prepare("SELECT id FROM test where name = :name")
.unwrap();
let mut rows = stmt.query_named(&[(":name", &"one")]).unwrap();
let id: i32 = rows.next().unwrap().unwrap().get(0);
@ -624,7 +634,8 @@ mod test {
"#;
db.execute_batch(sql).unwrap();
let mut stmt = db.prepare("SELECT id FROM test where name = :name").unwrap();
let mut stmt = db.prepare("SELECT id FROM test where name = :name")
.unwrap();
let mut rows = stmt.query_map_named(&[(":name", &"one")], |row| {
let id: i32 = row.get(0);
2 * id
@ -676,7 +687,8 @@ mod test {
let sql = "CREATE TABLE test (x TEXT, y TEXT)";
db.execute_batch(sql).unwrap();
let mut stmt = db.prepare("INSERT INTO test (x, y) VALUES (:x, :y)").unwrap();
let mut stmt = db.prepare("INSERT INTO test (x, y) VALUES (:x, :y)")
.unwrap();
stmt.execute_named(&[(":x", &"one")]).unwrap();
let result: Option<String> =
@ -691,7 +703,8 @@ mod test {
let sql = "CREATE TABLE test (x TEXT, y TEXT)";
db.execute_batch(sql).unwrap();
let mut stmt = db.prepare("INSERT INTO test (x, y) VALUES (:x, :y)").unwrap();
let mut stmt = db.prepare("INSERT INTO test (x, y) VALUES (:x, :y)")
.unwrap();
stmt.execute_named(&[(":x", &"one")]).unwrap();
stmt.execute_named(&[(":y", &"two")]).unwrap();
@ -704,15 +717,18 @@ mod test {
#[test]
fn test_insert() {
let db = Connection::open_in_memory().unwrap();
db.execute_batch("CREATE TABLE foo(x INTEGER UNIQUE)").unwrap();
let mut stmt = db.prepare("INSERT OR IGNORE INTO foo (x) VALUES (?)").unwrap();
db.execute_batch("CREATE TABLE foo(x INTEGER UNIQUE)")
.unwrap();
let mut stmt = db.prepare("INSERT OR IGNORE INTO foo (x) VALUES (?)")
.unwrap();
assert_eq!(stmt.insert(&[&1i32]).unwrap(), 1);
assert_eq!(stmt.insert(&[&2i32]).unwrap(), 2);
match stmt.insert(&[&1i32]).unwrap_err() {
Error::StatementChangedRows(0) => (),
err => panic!("Unexpected error {}", err),
}
let mut multi = db.prepare("INSERT INTO foo (x) SELECT 3 UNION ALL SELECT 4").unwrap();
let mut multi = db.prepare("INSERT INTO foo (x) SELECT 3 UNION ALL SELECT 4")
.unwrap();
match multi.insert(&[]).unwrap_err() {
Error::StatementChangedRows(2) => (),
err => panic!("Unexpected error {}", err),
@ -729,9 +745,15 @@ mod test {
")
.unwrap();
assert_eq!(db.prepare("INSERT INTO foo VALUES (10)").unwrap().insert(&[]).unwrap(),
assert_eq!(db.prepare("INSERT INTO foo VALUES (10)")
.unwrap()
.insert(&[])
.unwrap(),
1);
assert_eq!(db.prepare("INSERT INTO bar VALUES (10)").unwrap().insert(&[]).unwrap(),
assert_eq!(db.prepare("INSERT INTO bar VALUES (10)")
.unwrap()
.insert(&[])
.unwrap(),
1);
}

View File

@ -100,7 +100,8 @@ impl<'conn> Transaction<'conn> {
TransactionBehavior::Immediate => "BEGIN IMMEDIATE",
TransactionBehavior::Exclusive => "BEGIN EXCLUSIVE",
};
conn.execute_batch(query).map(move |_| {
conn.execute_batch(query)
.map(move |_| {
Transaction {
conn: conn,
drop_behavior: DropBehavior::Rollback,
@ -216,7 +217,8 @@ impl<'conn> Savepoint<'conn> {
name: T)
-> Result<Savepoint> {
let name = name.into();
conn.execute_batch(&format!("SAVEPOINT {}", name)).map(|_| {
conn.execute_batch(&format!("SAVEPOINT {}", name))
.map(|_| {
Savepoint {
conn: conn,
name: name,
@ -269,7 +271,8 @@ impl<'conn> Savepoint<'conn> {
fn commit_(&mut self) -> Result<()> {
self.committed = true;
self.conn.execute_batch(&format!("RELEASE {}", self.name))
self.conn
.execute_batch(&format!("RELEASE {}", self.name))
}
/// A convenience method which rolls back a savepoint.
@ -279,7 +282,8 @@ impl<'conn> Savepoint<'conn> {
/// Unlike `Transaction`s, savepoints remain active after they have been rolled back,
/// and can be rolled back again or committed.
pub fn rollback(&mut self) -> Result<()> {
self.conn.execute_batch(&format!("ROLLBACK TO {}", self.name))
self.conn
.execute_batch(&format!("ROLLBACK TO {}", self.name))
}
/// Consumes the savepoint, committing or rolling back according to the current setting
@ -549,7 +553,8 @@ mod test {
}
fn assert_current_sum(x: i32, conn: &Connection) {
let i = conn.query_row::<i32, _>("SELECT SUM(x) FROM foo", &[], |r| r.get(0)).unwrap();
let i = conn.query_row::<i32, _>("SELECT SUM(x) FROM foo", &[], |r| r.get(0))
.unwrap();
assert_eq!(x, i);
}
}

View File

@ -19,7 +19,9 @@ impl ToSql for NaiveDate {
/// "YYYY-MM-DD" => ISO 8601 calendar date without timezone.
impl FromSql for NaiveDate {
fn column_result(value: ValueRef) -> FromSqlResult<Self> {
value.as_str().and_then(|s| match NaiveDate::parse_from_str(s, "%Y-%m-%d") {
value
.as_str()
.and_then(|s| match NaiveDate::parse_from_str(s, "%Y-%m-%d") {
Ok(dt) => Ok(dt),
Err(err) => Err(FromSqlError::Other(Box::new(err))),
})
@ -37,7 +39,9 @@ impl ToSql for NaiveTime {
/// "HH:MM"/"HH:MM:SS"/"HH:MM:SS.SSS" => ISO 8601 time without timezone.
impl FromSql for NaiveTime {
fn column_result(value: ValueRef) -> FromSqlResult<Self> {
value.as_str().and_then(|s| {
value
.as_str()
.and_then(|s| {
let fmt = match s.len() {
5 => "%H:%M",
8 => "%H:%M:%S",
@ -63,7 +67,9 @@ impl ToSql for NaiveDateTime {
/// without timezone. ("YYYY-MM-DDTHH:MM:SS"/"YYYY-MM-DDTHH:MM:SS.SSS" also supported)
impl FromSql for NaiveDateTime {
fn column_result(value: ValueRef) -> FromSqlResult<Self> {
value.as_str().and_then(|s| {
value
.as_str()
.and_then(|s| {
let fmt = if s.len() >= 11 && s.as_bytes()[10] == b'T' {
"%Y-%m-%dT%H:%M:%S%.f"
} else {
@ -130,7 +136,8 @@ mod test {
fn checked_memory_handle() -> Connection {
let db = Connection::open_in_memory().unwrap();
db.execute_batch("CREATE TABLE foo (t TEXT, i INTEGER, f FLOAT, b BLOB)").unwrap();
db.execute_batch("CREATE TABLE foo (t TEXT, i INTEGER, f FLOAT, b BLOB)")
.unwrap();
db
}
@ -138,11 +145,14 @@ mod test {
fn test_naive_date() {
let db = checked_memory_handle();
let date = NaiveDate::from_ymd(2016, 2, 23);
db.execute("INSERT INTO foo (t) VALUES (?)", &[&date]).unwrap();
db.execute("INSERT INTO foo (t) VALUES (?)", &[&date])
.unwrap();
let s: String = db.query_row("SELECT t FROM foo", &[], |r| r.get(0)).unwrap();
let s: String = db.query_row("SELECT t FROM foo", &[], |r| r.get(0))
.unwrap();
assert_eq!("2016-02-23", s);
let t: NaiveDate = db.query_row("SELECT t FROM foo", &[], |r| r.get(0)).unwrap();
let t: NaiveDate = db.query_row("SELECT t FROM foo", &[], |r| r.get(0))
.unwrap();
assert_eq!(date, t);
}
@ -150,11 +160,14 @@ mod test {
fn test_naive_time() {
let db = checked_memory_handle();
let time = NaiveTime::from_hms(23, 56, 4);
db.execute("INSERT INTO foo (t) VALUES (?)", &[&time]).unwrap();
db.execute("INSERT INTO foo (t) VALUES (?)", &[&time])
.unwrap();
let s: String = db.query_row("SELECT t FROM foo", &[], |r| r.get(0)).unwrap();
let s: String = db.query_row("SELECT t FROM foo", &[], |r| r.get(0))
.unwrap();
assert_eq!("23:56:04", s);
let v: NaiveTime = db.query_row("SELECT t FROM foo", &[], |r| r.get(0)).unwrap();
let v: NaiveTime = db.query_row("SELECT t FROM foo", &[], |r| r.get(0))
.unwrap();
assert_eq!(time, v);
}
@ -165,15 +178,20 @@ mod test {
let time = NaiveTime::from_hms(23, 56, 4);
let dt = NaiveDateTime::new(date, time);
db.execute("INSERT INTO foo (t) VALUES (?)", &[&dt]).unwrap();
db.execute("INSERT INTO foo (t) VALUES (?)", &[&dt])
.unwrap();
let s: String = db.query_row("SELECT t FROM foo", &[], |r| r.get(0)).unwrap();
let s: String = db.query_row("SELECT t FROM foo", &[], |r| r.get(0))
.unwrap();
assert_eq!("2016-02-23T23:56:04", s);
let v: NaiveDateTime = db.query_row("SELECT t FROM foo", &[], |r| r.get(0)).unwrap();
let v: NaiveDateTime = db.query_row("SELECT t FROM foo", &[], |r| r.get(0))
.unwrap();
assert_eq!(dt, v);
db.execute("UPDATE foo set b = datetime(t)", &[]).unwrap(); // "YYYY-MM-DD HH:MM:SS"
let hms: NaiveDateTime = db.query_row("SELECT b FROM foo", &[], |r| r.get(0)).unwrap();
db.execute("UPDATE foo set b = datetime(t)", &[])
.unwrap(); // "YYYY-MM-DD HH:MM:SS"
let hms: NaiveDateTime = db.query_row("SELECT b FROM foo", &[], |r| r.get(0))
.unwrap();
assert_eq!(dt, hms);
}
@ -185,12 +203,15 @@ mod test {
let dt = NaiveDateTime::new(date, time);
let utc = UTC.from_utc_datetime(&dt);
db.execute("INSERT INTO foo (t) VALUES (?)", &[&utc]).unwrap();
db.execute("INSERT INTO foo (t) VALUES (?)", &[&utc])
.unwrap();
let s: String = db.query_row("SELECT t FROM foo", &[], |r| r.get(0)).unwrap();
let s: String = db.query_row("SELECT t FROM foo", &[], |r| r.get(0))
.unwrap();
assert_eq!("2016-02-23T23:56:04.789+00:00", s);
let v1: DateTime<UTC> = db.query_row("SELECT t FROM foo", &[], |r| r.get(0)).unwrap();
let v1: DateTime<UTC> = db.query_row("SELECT t FROM foo", &[], |r| r.get(0))
.unwrap();
assert_eq!(utc, v1);
let v2: DateTime<UTC> = db.query_row("SELECT '2016-02-23 23:56:04.789'", &[], |r| r.get(0))
@ -202,7 +223,8 @@ mod test {
assert_eq!(utc - Duration::milliseconds(789), v3);
let v4: DateTime<UTC> =
db.query_row("SELECT '2016-02-23 23:56:04.789+00:00'", &[], |r| r.get(0)).unwrap();
db.query_row("SELECT '2016-02-23 23:56:04.789+00:00'", &[], |r| r.get(0))
.unwrap();
assert_eq!(utc, v4);
}
@ -214,13 +236,16 @@ mod test {
let dt = NaiveDateTime::new(date, time);
let local = Local.from_local_datetime(&dt).single().unwrap();
db.execute("INSERT INTO foo (t) VALUES (?)", &[&local]).unwrap();
db.execute("INSERT INTO foo (t) VALUES (?)", &[&local])
.unwrap();
// Stored string should be in UTC
let s: String = db.query_row("SELECT t FROM foo", &[], |r| r.get(0)).unwrap();
let s: String = db.query_row("SELECT t FROM foo", &[], |r| r.get(0))
.unwrap();
assert!(s.ends_with("+00:00"));
let v: DateTime<Local> = db.query_row("SELECT t FROM foo", &[], |r| r.get(0)).unwrap();
let v: DateTime<Local> = db.query_row("SELECT t FROM foo", &[], |r| r.get(0))
.unwrap();
assert_eq!(local, v);
}
}

View File

@ -164,7 +164,9 @@ mod test {
}
for n in in_range {
assert_eq!(*n,
db.query_row("SELECT ?", &[n], |r| r.get::<_, T>(0)).unwrap().into());
db.query_row("SELECT ?", &[n], |r| r.get::<_, T>(0))
.unwrap()
.into());
}
}

View File

@ -119,7 +119,8 @@ mod test {
fn checked_memory_handle() -> Connection {
let db = Connection::open_in_memory().unwrap();
db.execute_batch("CREATE TABLE foo (b BLOB, t TEXT, i INTEGER, f FLOAT, n)").unwrap();
db.execute_batch("CREATE TABLE foo (b BLOB, t TEXT, i INTEGER, f FLOAT, n)")
.unwrap();
db
}
@ -128,9 +129,11 @@ mod test {
let db = checked_memory_handle();
let v1234 = vec![1u8, 2, 3, 4];
db.execute("INSERT INTO foo(b) VALUES (?)", &[&v1234]).unwrap();
db.execute("INSERT INTO foo(b) VALUES (?)", &[&v1234])
.unwrap();
let v: Vec<u8> = db.query_row("SELECT b FROM foo", &[], |r| r.get(0)).unwrap();
let v: Vec<u8> = db.query_row("SELECT b FROM foo", &[], |r| r.get(0))
.unwrap();
assert_eq!(v, v1234);
}
@ -139,9 +142,11 @@ mod test {
let db = checked_memory_handle();
let empty = vec![];
db.execute("INSERT INTO foo(b) VALUES (?)", &[&empty]).unwrap();
db.execute("INSERT INTO foo(b) VALUES (?)", &[&empty])
.unwrap();
let v: Vec<u8> = db.query_row("SELECT b FROM foo", &[], |r| r.get(0)).unwrap();
let v: Vec<u8> = db.query_row("SELECT b FROM foo", &[], |r| r.get(0))
.unwrap();
assert_eq!(v, empty);
}
@ -150,9 +155,11 @@ mod test {
let db = checked_memory_handle();
let s = "hello, world!";
db.execute("INSERT INTO foo(t) VALUES (?)", &[&s]).unwrap();
db.execute("INSERT INTO foo(t) VALUES (?)", &[&s])
.unwrap();
let from: String = db.query_row("SELECT t FROM foo", &[], |r| r.get(0)).unwrap();
let from: String = db.query_row("SELECT t FROM foo", &[], |r| r.get(0))
.unwrap();
assert_eq!(from, s);
}
@ -161,9 +168,11 @@ mod test {
let db = checked_memory_handle();
let s = "hello, world!";
db.execute("INSERT INTO foo(t) VALUES (?)", &[&s.to_owned()]).unwrap();
db.execute("INSERT INTO foo(t) VALUES (?)", &[&s.to_owned()])
.unwrap();
let from: String = db.query_row("SELECT t FROM foo", &[], |r| r.get(0)).unwrap();
let from: String = db.query_row("SELECT t FROM foo", &[], |r| r.get(0))
.unwrap();
assert_eq!(from, s);
}
@ -171,10 +180,12 @@ mod test {
fn test_value() {
let db = checked_memory_handle();
db.execute("INSERT INTO foo(i) VALUES (?)", &[&Value::Integer(10)]).unwrap();
db.execute("INSERT INTO foo(i) VALUES (?)", &[&Value::Integer(10)])
.unwrap();
assert_eq!(10i64,
db.query_row::<i64, _>("SELECT i FROM foo", &[], |r| r.get(0)).unwrap());
db.query_row::<i64, _>("SELECT i FROM foo", &[], |r| r.get(0))
.unwrap());
}
#[test]
@ -184,10 +195,13 @@ mod test {
let s = Some("hello, world!");
let b = Some(vec![1u8, 2, 3, 4]);
db.execute("INSERT INTO foo(t) VALUES (?)", &[&s]).unwrap();
db.execute("INSERT INTO foo(b) VALUES (?)", &[&b]).unwrap();
db.execute("INSERT INTO foo(t) VALUES (?)", &[&s])
.unwrap();
db.execute("INSERT INTO foo(b) VALUES (?)", &[&b])
.unwrap();
let mut stmt = db.prepare("SELECT t, b FROM foo ORDER BY ROWID ASC").unwrap();
let mut stmt = db.prepare("SELECT t, b FROM foo ORDER BY ROWID ASC")
.unwrap();
let mut rows = stmt.query(&[]).unwrap();
{
@ -232,9 +246,15 @@ mod test {
assert_eq!("text", row.get_checked::<i32, String>(1).unwrap());
assert_eq!(1, row.get_checked::<i32, c_int>(2).unwrap());
assert!((1.5 - row.get_checked::<i32, c_double>(3).unwrap()).abs() < EPSILON);
assert!(row.get_checked::<i32, Option<c_int>>(4).unwrap().is_none());
assert!(row.get_checked::<i32, Option<c_double>>(4).unwrap().is_none());
assert!(row.get_checked::<i32, Option<String>>(4).unwrap().is_none());
assert!(row.get_checked::<i32, Option<c_int>>(4)
.unwrap()
.is_none());
assert!(row.get_checked::<i32, Option<c_double>>(4)
.unwrap()
.is_none());
assert!(row.get_checked::<i32, Option<String>>(4)
.unwrap()
.is_none());
// check some invalid types

View File

@ -32,7 +32,8 @@ mod test {
fn checked_memory_handle() -> Connection {
let db = Connection::open_in_memory().unwrap();
db.execute_batch("CREATE TABLE foo (t TEXT, b BLOB)").unwrap();
db.execute_batch("CREATE TABLE foo (t TEXT, b BLOB)")
.unwrap();
db
}
@ -46,9 +47,11 @@ mod test {
&[&data, &json.as_bytes()])
.unwrap();
let t: serde_json::Value = db.query_row("SELECT t FROM foo", &[], |r| r.get(0)).unwrap();
let t: serde_json::Value = db.query_row("SELECT t FROM foo", &[], |r| r.get(0))
.unwrap();
assert_eq!(data, t);
let b: serde_json::Value = db.query_row("SELECT b FROM foo", &[], |r| r.get(0)).unwrap();
let b: serde_json::Value = db.query_row("SELECT b FROM foo", &[], |r| r.get(0))
.unwrap();
assert_eq!(data, b);
}
}

View File

@ -7,14 +7,19 @@ const SQLITE_DATETIME_FMT: &'static str = "%Y-%m-%d %H:%M:%S";
impl ToSql for time::Timespec {
fn to_sql(&self) -> Result<ToSqlOutput> {
let time_string = time::at_utc(*self).strftime(SQLITE_DATETIME_FMT).unwrap().to_string();
let time_string = time::at_utc(*self)
.strftime(SQLITE_DATETIME_FMT)
.unwrap()
.to_string();
Ok(ToSqlOutput::from(time_string))
}
}
impl FromSql for time::Timespec {
fn column_result(value: ValueRef) -> FromSqlResult<Self> {
value.as_str().and_then(|s| match time::strptime(s, SQLITE_DATETIME_FMT) {
value
.as_str()
.and_then(|s| match time::strptime(s, SQLITE_DATETIME_FMT) {
Ok(tm) => Ok(tm.to_timespec()),
Err(err) => Err(FromSqlError::Other(Box::new(err))),
})
@ -28,7 +33,8 @@ mod test {
fn checked_memory_handle() -> Connection {
let db = Connection::open_in_memory().unwrap();
db.execute_batch("CREATE TABLE foo (t TEXT, i INTEGER, f FLOAT)").unwrap();
db.execute_batch("CREATE TABLE foo (t TEXT, i INTEGER, f FLOAT)")
.unwrap();
db
}
@ -40,9 +46,11 @@ mod test {
sec: 10_000,
nsec: 0,
};
db.execute("INSERT INTO foo(t) VALUES (?)", &[&ts]).unwrap();
db.execute("INSERT INTO foo(t) VALUES (?)", &[&ts])
.unwrap();
let from: time::Timespec = db.query_row("SELECT t FROM foo", &[], |r| r.get(0)).unwrap();
let from: time::Timespec = db.query_row("SELECT t FROM foo", &[], |r| r.get(0))
.unwrap();
assert_eq!(from, ts);
}
}

View File

@ -94,12 +94,24 @@ impl ToSql for String {
}
}
impl ToSql for str {
fn to_sql(&self) -> Result<ToSqlOutput> {
Ok(ToSqlOutput::from(self))
}
}
impl ToSql for Vec<u8> {
fn to_sql(&self) -> Result<ToSqlOutput> {
Ok(ToSqlOutput::from(self.as_slice()))
}
}
impl ToSql for [u8] {
fn to_sql(&self) -> Result<ToSqlOutput> {
Ok(ToSqlOutput::from(self))
}
}
impl ToSql for Value {
fn to_sql(&self) -> Result<ToSqlOutput> {
Ok(ToSqlOutput::from(self))

View File

@ -13,5 +13,6 @@ pub fn version_number() -> i32 {
/// See [sqlite3_libversion()](https://www.sqlite.org/c3ref/libversion.html).
pub fn version() -> &'static str {
let cstr = unsafe { CStr::from_ptr(ffi::sqlite3_libversion()) };
cstr.to_str().expect("SQLite version string is not valid UTF8 ?!")
cstr.to_str()
.expect("SQLite version string is not valid UTF8 ?!")
}

View File

@ -56,13 +56,13 @@ pub trait VTab<C: VTabCursor<Self>>: Sized {
bitflags! {
#[doc = "Index constraint operator."]
#[repr(C)]
pub flags IndexConstraintOp: ::std::os::raw::c_uchar {
const SQLITE_INDEX_CONSTRAINT_EQ = 2,
const SQLITE_INDEX_CONSTRAINT_GT = 4,
const SQLITE_INDEX_CONSTRAINT_LE = 8,
const SQLITE_INDEX_CONSTRAINT_LT = 16,
const SQLITE_INDEX_CONSTRAINT_GE = 32,
const SQLITE_INDEX_CONSTRAINT_MATCH = 64,
pub struct IndexConstraintOp: ::std::os::raw::c_uchar {
const SQLITE_INDEX_CONSTRAINT_EQ = 2;
const SQLITE_INDEX_CONSTRAINT_GT = 4;
const SQLITE_INDEX_CONSTRAINT_LE = 8;
const SQLITE_INDEX_CONSTRAINT_LT = 16;
const SQLITE_INDEX_CONSTRAINT_GE = 32;
const SQLITE_INDEX_CONSTRAINT_MATCH = 64;
}
}
@ -96,7 +96,7 @@ impl IndexInfo {
/// if `argv_index` > 0, constraint is part of argv to xFilter
pub fn constraint_usage(&mut self, constraint_idx: usize) -> IndexConstraintUsage {
let mut constraint_usages = unsafe {
let constraint_usages = unsafe {
slice::from_raw_parts_mut((*self.0).aConstraintUsage, (*self.0).nConstraint as usize)
};
IndexConstraintUsage(&mut constraint_usages[constraint_idx])

View File

@ -37,17 +37,17 @@ const SERIES_COLUMN_STEP: c_int = 3;
bitflags! {
#[repr(C)]
flags QueryPlanFlags: ::std::os::raw::c_int {
struct QueryPlanFlags: ::std::os::raw::c_int {
// start = $value -- constraint exists
const START = 1,
const START = 1;
// stop = $value -- constraint exists
const STOP = 2,
const STOP = 2;
// step = $value -- constraint exists
const STEP = 4,
const STEP = 4;
// output in descending order
const DESC = 8,
const DESC = 8;
// Both start and stop
const BOTH = START.bits | STOP.bits,
const BOTH = START.bits | STOP.bits;
}
}