From 1bf3e580559e8c901f89a19183e04edeacaff82e Mon Sep 17 00:00:00 2001 From: gwenn Date: Sun, 24 Jan 2016 16:32:39 +0100 Subject: [PATCH 01/23] Add appveyor configuration file --- appveyor.yml | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) create mode 100644 appveyor.yml diff --git a/appveyor.yml b/appveyor.yml new file mode 100644 index 0000000..3abfa08 --- /dev/null +++ b/appveyor.yml @@ -0,0 +1,19 @@ +environment: + TARGET: x86_64-pc-windows-msvc +install: + - ps: Start-FileDownload "https://static.rust-lang.org/dist/rust-nightly-${env:TARGET}.exe" + - rust-nightly-%TARGET%.exe /VERYSILENT /NORESTART /DIR="C:\Program Files (x86)\Rust" + - SET PATH=%PATH%;C:\Program Files (x86)\Rust\bin + - rustc -V + - cargo -V + - ps: Start-FileDownload 'http://sqlite.org/2015/sqlite-dll-win64-x64-3090200.zip' + - cmd: 7z e sqlite-dll-win64-x64-3090200.zip -y > nul + +build: false + +test_script: + - cargo test + +branches: + only: + - appveyor \ No newline at end of file From 6a1554d91e59cae8a53c191f76e505e6fc9ff16a Mon Sep 17 00:00:00 2001 From: gwenn Date: Sun, 24 Jan 2016 17:00:57 +0100 Subject: [PATCH 02/23] Try to fix appveyor build by setting SQLITE3_LIB_DIR --- appveyor.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/appveyor.yml b/appveyor.yml index 3abfa08..0c3b522 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -8,6 +8,7 @@ install: - cargo -V - ps: Start-FileDownload 'http://sqlite.org/2015/sqlite-dll-win64-x64-3090200.zip' - cmd: 7z e sqlite-dll-win64-x64-3090200.zip -y > nul + - SET SQLITE3_LIB_DIR=%APPVEYOR_BUILD_FOLDER% build: false From b8e3db433861afc859715258aa54387cea4720f6 Mon Sep 17 00:00:00 2001 From: gwenn Date: Sun, 24 Jan 2016 17:26:19 +0100 Subject: [PATCH 03/23] Try to fix error: cannot open input file 'sqlite3.lib' --- appveyor.yml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/appveyor.yml b/appveyor.yml index 0c3b522..7e0ba01 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -6,9 +6,10 @@ install: - SET PATH=%PATH%;C:\Program Files (x86)\Rust\bin - rustc -V - cargo -V - - ps: Start-FileDownload 'http://sqlite.org/2015/sqlite-dll-win64-x64-3090200.zip' - - cmd: 7z e sqlite-dll-win64-x64-3090200.zip -y > nul + - ps: Start-FileDownload 'http://sqlite.org/2016/sqlite-uap-3100200.vsix' + - cmd: 7z e sqlite-uap-3100200.vsix DesignTime/Debug/x64/ Redist/Debug/x64/ -y > nul - SET SQLITE3_LIB_DIR=%APPVEYOR_BUILD_FOLDER% + - cmd: VsixInstaller /q /a /i sqlite-uap-3100200.vsix build: false From 9b97d88362c31ff503d8deeeb13f71be76336908 Mon Sep 17 00:00:00 2001 From: gwenn Date: Sun, 24 Jan 2016 17:32:07 +0100 Subject: [PATCH 04/23] Try to fix appveyor --- appveyor.yml | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/appveyor.yml b/appveyor.yml index 7e0ba01..e562852 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -9,7 +9,7 @@ install: - ps: Start-FileDownload 'http://sqlite.org/2016/sqlite-uap-3100200.vsix' - cmd: 7z e sqlite-uap-3100200.vsix DesignTime/Debug/x64/ Redist/Debug/x64/ -y > nul - SET SQLITE3_LIB_DIR=%APPVEYOR_BUILD_FOLDER% - - cmd: VsixInstaller /q /a /i sqlite-uap-3100200.vsix +# - cmd: VsixInstaller /q /a /i sqlite-uap-3100200.vsix build: false @@ -18,4 +18,7 @@ test_script: branches: only: - - appveyor \ No newline at end of file + - appveyor + +cache: + - C:\Users\appveyor\.cargo From 32c31cdb6078277bb22db95c79bd4d236689143b Mon Sep 17 00:00:00 2001 From: gwenn Date: Sun, 24 Jan 2016 18:54:54 +0100 Subject: [PATCH 05/23] Try to fix appveyor build. --- appveyor.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/appveyor.yml b/appveyor.yml index e562852..4df3fdd 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -7,14 +7,14 @@ install: - rustc -V - cargo -V - ps: Start-FileDownload 'http://sqlite.org/2016/sqlite-uap-3100200.vsix' - - cmd: 7z e sqlite-uap-3100200.vsix DesignTime/Debug/x64/ Redist/Debug/x64/ -y > nul + - cmd: 7z e sqlite-uap-3100200.vsix DesignTime/Retail/x64/ Redist/Retail/x64/ -y > nul - SET SQLITE3_LIB_DIR=%APPVEYOR_BUILD_FOLDER% # - cmd: VsixInstaller /q /a /i sqlite-uap-3100200.vsix build: false test_script: - - cargo test + - cargo test --lib branches: only: From 9dc91c7e588fa5f0824abedf38a6d843e3ef00c2 Mon Sep 17 00:00:00 2001 From: gwenn Date: Mon, 25 Jan 2016 18:35:22 +0100 Subject: [PATCH 06/23] Update appveyor.yml --- appveyor.yml | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/appveyor.yml b/appveyor.yml index 4df3fdd..abe001b 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -1,20 +1,21 @@ environment: TARGET: x86_64-pc-windows-msvc install: - - ps: Start-FileDownload "https://static.rust-lang.org/dist/rust-nightly-${env:TARGET}.exe" + - ps: Start-FileDownload "https://static.rust-lang.org/dist/rust-1.6.0-${env:TARGET}.exe" - rust-nightly-%TARGET%.exe /VERYSILENT /NORESTART /DIR="C:\Program Files (x86)\Rust" - SET PATH=%PATH%;C:\Program Files (x86)\Rust\bin - rustc -V - cargo -V - - ps: Start-FileDownload 'http://sqlite.org/2016/sqlite-uap-3100200.vsix' - - cmd: 7z e sqlite-uap-3100200.vsix DesignTime/Retail/x64/ Redist/Retail/x64/ -y > nul +# - ps: Start-FileDownload 'http://sqlite.org/2016/sqlite-uap-3100200.vsix' +# - cmd: 7z e sqlite-uap-3100200.vsix DesignTime/Retail/x64/ Redist/Retail/x64/ -y > nul + - ps: Start-FileDownload 'http://sqlite.org/2015/sqlite-dll-win64-x64-3090200.zip' + - cmd: 7z e sqlite-dll-win64-x64-3090200.zip -y > nul - SET SQLITE3_LIB_DIR=%APPVEYOR_BUILD_FOLDER% -# - cmd: VsixInstaller /q /a /i sqlite-uap-3100200.vsix build: false test_script: - - cargo test --lib + - cargo test --lib --verbose branches: only: From eda881349ac33289b1144d2521965ca4569c29c9 Mon Sep 17 00:00:00 2001 From: gwenn Date: Mon, 25 Jan 2016 18:36:06 +0100 Subject: [PATCH 07/23] Update appveyor.yml --- appveyor.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/appveyor.yml b/appveyor.yml index abe001b..2bf2e65 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -2,7 +2,7 @@ environment: TARGET: x86_64-pc-windows-msvc install: - ps: Start-FileDownload "https://static.rust-lang.org/dist/rust-1.6.0-${env:TARGET}.exe" - - rust-nightly-%TARGET%.exe /VERYSILENT /NORESTART /DIR="C:\Program Files (x86)\Rust" + - rust-1.6.0-%TARGET%.exe /VERYSILENT /NORESTART /DIR="C:\Program Files (x86)\Rust" - SET PATH=%PATH%;C:\Program Files (x86)\Rust\bin - rustc -V - cargo -V From ec7565383fcdc04086c235eddd045ceba011031d Mon Sep 17 00:00:00 2001 From: gwenn Date: Mon, 25 Jan 2016 19:04:52 +0100 Subject: [PATCH 08/23] Update appveyor.yml --- appveyor.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/appveyor.yml b/appveyor.yml index 2bf2e65..ec70a85 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -6,10 +6,10 @@ install: - SET PATH=%PATH%;C:\Program Files (x86)\Rust\bin - rustc -V - cargo -V -# - ps: Start-FileDownload 'http://sqlite.org/2016/sqlite-uap-3100200.vsix' -# - cmd: 7z e sqlite-uap-3100200.vsix DesignTime/Retail/x64/ Redist/Retail/x64/ -y > nul - - ps: Start-FileDownload 'http://sqlite.org/2015/sqlite-dll-win64-x64-3090200.zip' - - cmd: 7z e sqlite-dll-win64-x64-3090200.zip -y > nul + - ps: Start-FileDownload 'http://sqlite.org/2016/sqlite-uap-3100200.vsix' + - cmd: 7z e sqlite-uap-3100200.vsix DesignTime/Retail/x64/ Redist/Retail/x64/ -y > nul +# - ps: Start-FileDownload 'http://sqlite.org/2015/sqlite-dll-win64-x64-3090200.zip' +# - cmd: 7z e sqlite-dll-win64-x64-3090200.zip -y > nul - SET SQLITE3_LIB_DIR=%APPVEYOR_BUILD_FOLDER% build: false From ea14115d6c1e767c0b0d7d36fa7a72d5320f3a45 Mon Sep 17 00:00:00 2001 From: gwenn Date: Thu, 28 Jan 2016 18:12:23 +0100 Subject: [PATCH 09/23] Ensure there is no allocation in final aggregation step. --- src/functions.rs | 29 +++++++++++++---------------- 1 file changed, 13 insertions(+), 16 deletions(-) diff --git a/src/functions.rs b/src/functions.rs index 0b9b51a..e64861a 100644 --- a/src/functions.rs +++ b/src/functions.rs @@ -489,8 +489,8 @@ impl InnerConnection { where D: Aggregate, T: ToResult { - unsafe fn aggregate_context(ctx: *mut sqlite3_context) -> Option<*mut *mut A> { - let pac = ffi::sqlite3_aggregate_context(ctx, ::std::mem::size_of::<*mut A>() as c_int) + unsafe fn aggregate_context(ctx: *mut sqlite3_context, bytes: usize) -> Option<*mut *mut A> { + let pac = ffi::sqlite3_aggregate_context(ctx, bytes as c_int) as *mut *mut A; if pac.is_null() { return None; @@ -525,7 +525,7 @@ impl InnerConnection { assert!(!boxed_aggr.is_null(), "Internal error - null aggregate pointer"); - let pac = match aggregate_context(ctx) { + let pac = match aggregate_context(ctx, ::std::mem::size_of::<*mut A>()) { Some(pac) => pac, None => { ffi::sqlite3_result_error_nomem(ctx); @@ -556,19 +556,16 @@ impl InnerConnection { assert!(!boxed_aggr.is_null(), "Internal error - null aggregate pointer"); - let pac = match aggregate_context(ctx) { - Some(pac) => pac, - None => { - ffi::sqlite3_result_error_nomem(ctx); - return; - } - }; - - let a: Option = if (*pac).is_null() { - None - } else { - let a = Box::from_raw(*pac); - Some(*a) + // Within the xFinal callback, it is customary to set N=0 in calls to + // sqlite3_aggregate_context(C,N) so that no pointless memory allocations occur. + let a: Option = match aggregate_context(ctx, 0) { + Some(pac) => if (*pac).is_null() { + None + } else { + let a = Box::from_raw(*pac); + Some(*a) + }, + None => None, }; match (*boxed_aggr).finalize(a) { From b0261791b80af2f526acb54274245e444ef02541 Mon Sep 17 00:00:00 2001 From: gwenn Date: Thu, 28 Jan 2016 18:25:33 +0100 Subject: [PATCH 10/23] Try appveyor with the gnu/mingw version. --- appveyor.yml | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/appveyor.yml b/appveyor.yml index 4df3fdd..b9d09f5 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -1,15 +1,16 @@ environment: - TARGET: x86_64-pc-windows-msvc + TARGET: 1.6.0-x86_64-pc-windows-gnu + MSYS2_BITS: 64 install: - - ps: Start-FileDownload "https://static.rust-lang.org/dist/rust-nightly-${env:TARGET}.exe" - - rust-nightly-%TARGET%.exe /VERYSILENT /NORESTART /DIR="C:\Program Files (x86)\Rust" + - ps: Start-FileDownload "https://static.rust-lang.org/dist/rust-${env:TARGET}.exe" + - rust-%TARGET%.exe /VERYSILENT /NORESTART /DIR="C:\Program Files (x86)\Rust" - SET PATH=%PATH%;C:\Program Files (x86)\Rust\bin + - if defined MSYS2_BITS set PATH=%PATH%;C:\msys64\mingw%MSYS2_BITS%\bin - rustc -V - cargo -V - - ps: Start-FileDownload 'http://sqlite.org/2016/sqlite-uap-3100200.vsix' - - cmd: 7z e sqlite-uap-3100200.vsix DesignTime/Retail/x64/ Redist/Retail/x64/ -y > nul + - ps: Start-FileDownload 'http://sqlite.org/2015/sqlite-dll-win64-x64-3090200.zip' + - cmd: 7z e sqlite-dll-win64-x64-3090200.zip -y > nul - SET SQLITE3_LIB_DIR=%APPVEYOR_BUILD_FOLDER% -# - cmd: VsixInstaller /q /a /i sqlite-uap-3100200.vsix build: false From 7b174093bf5c0c26880025b2192f1aed8de24c8c Mon Sep 17 00:00:00 2001 From: gwenn Date: Thu, 28 Jan 2016 19:10:37 +0100 Subject: [PATCH 11/23] Fix URL --- appveyor.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/appveyor.yml b/appveyor.yml index df6e7c7..7983572 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -2,8 +2,8 @@ environment: TARGET: 1.6.0-x86_64-pc-windows-gnu MSYS2_BITS: 64 install: - - ps: Start-FileDownload "https://static.rust-lang.org/dist/rust-1.6.0-${env:TARGET}.exe" - - rust-1.6.0-%TARGET%.exe /VERYSILENT /NORESTART /DIR="C:\Program Files (x86)\Rust" + - ps: Start-FileDownload "https://static.rust-lang.org/dist/rust-${env:TARGET}.exe" + - rust-%TARGET%.exe /VERYSILENT /NORESTART /DIR="C:\Program Files (x86)\Rust" - SET PATH=%PATH%;C:\Program Files (x86)\Rust\bin - if defined MSYS2_BITS set PATH=%PATH%;C:\msys64\mingw%MSYS2_BITS%\bin - rustc -V From 78cc7f2306412093c568afe1f15cfa5127c504dc Mon Sep 17 00:00:00 2001 From: gwenn Date: Thu, 28 Jan 2016 20:26:59 +0100 Subject: [PATCH 12/23] Upgrade to SQLite 3.10.2 --- appveyor.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/appveyor.yml b/appveyor.yml index 7983572..a253f36 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -8,8 +8,8 @@ install: - if defined MSYS2_BITS set PATH=%PATH%;C:\msys64\mingw%MSYS2_BITS%\bin - rustc -V - cargo -V - - ps: Start-FileDownload 'http://sqlite.org/2015/sqlite-dll-win64-x64-3090200.zip' - - cmd: 7z e sqlite-dll-win64-x64-3090200.zip -y > nul + - ps: Start-FileDownload 'http://sqlite.org/2015/sqlite-dll-win64-x64-3100200.zip' + - cmd: 7z e sqlite-dll-win64-x64-3100200.zip -y > nul - SET SQLITE3_LIB_DIR=%APPVEYOR_BUILD_FOLDER% build: false From eb521c0f3a3698e79365730d8076f39311b99b7b Mon Sep 17 00:00:00 2001 From: gwenn Date: Thu, 28 Jan 2016 20:35:00 +0100 Subject: [PATCH 13/23] Fix URL --- appveyor.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/appveyor.yml b/appveyor.yml index a253f36..c5484fe 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -8,7 +8,7 @@ install: - if defined MSYS2_BITS set PATH=%PATH%;C:\msys64\mingw%MSYS2_BITS%\bin - rustc -V - cargo -V - - ps: Start-FileDownload 'http://sqlite.org/2015/sqlite-dll-win64-x64-3100200.zip' + - ps: Start-FileDownload 'http://sqlite.org/2016/sqlite-dll-win64-x64-3100200.zip' - cmd: 7z e sqlite-dll-win64-x64-3100200.zip -y > nul - SET SQLITE3_LIB_DIR=%APPVEYOR_BUILD_FOLDER% From f4882773733f1ef7d9763e45a982b5d29dc6874a Mon Sep 17 00:00:00 2001 From: gwenn Date: Sun, 31 Jan 2016 18:17:28 +0100 Subject: [PATCH 14/23] Introduce ZeoBlob struct. --- src/blob.rs | 3 ++- src/types.rs | 15 +++++++++++++++ 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/src/blob.rs b/src/blob.rs index a13f3e7..e33b812 100644 --- a/src/blob.rs +++ b/src/blob.rs @@ -17,6 +17,7 @@ //! extern crate rusqlite; //! //! use rusqlite::{Connection, DatabaseName}; +//! use rusqlite::types::ZeroBlob; //! use std::io::{Read, Write, Seek, SeekFrom}; //! //! fn main() { @@ -38,7 +39,7 @@ //! let bytes_read = blob.read(&mut buf[..]).unwrap(); //! assert_eq!(bytes_read, 10); // note we read 10 bytes because the blob has size 10 //! -//! db.execute("INSERT INTO test (content) VALUES (ZEROBLOB(64))", &[]).unwrap(); +//! db.execute("INSERT INTO test (content) VALUES (?)", &[&ZeroBlob(64)]).unwrap(); //! //! // given a new row ID, we can reopen the blob on that row //! let rowid = db.last_insert_rowid(); diff --git a/src/types.rs b/src/types.rs index de3d709..3c474eb 100644 --- a/src/types.rs +++ b/src/types.rs @@ -194,6 +194,21 @@ impl ToSql for Null { } } +/// BLOB of length N that is filled with zeroes. +/// Zeroblobs are intended to serve as placeholders for BLOBs whose content is later written using incremental BLOB I/O routines. +/// A negative value for the zeroblob results in a zero-length BLOB. +#[cfg(feature = "blob")] +#[derive(Copy,Clone)] +pub struct ZeroBlob(pub i32); + +#[cfg(feature = "blob")] +impl ToSql for ZeroBlob { + unsafe fn bind_parameter(&self, stmt: *mut sqlite3_stmt, col: c_int) -> c_int { + let ZeroBlob(length) = *self; + ffi::sqlite3_bind_zeroblob(stmt, col, length) + } +} + macro_rules! raw_from_impl( ($t:ty, $f:ident, $c:expr) => ( impl FromSql for $t { From f4c3ba0fa2b90321114828c005fe3730720c804f Mon Sep 17 00:00:00 2001 From: John Gallagher Date: Mon, 1 Feb 2016 10:48:30 -0500 Subject: [PATCH 15/23] rustfmt --- src/functions.rs | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/src/functions.rs b/src/functions.rs index e64861a..49e0032 100644 --- a/src/functions.rs +++ b/src/functions.rs @@ -489,9 +489,10 @@ impl InnerConnection { where D: Aggregate, T: ToResult { - unsafe fn aggregate_context(ctx: *mut sqlite3_context, bytes: usize) -> Option<*mut *mut A> { - let pac = ffi::sqlite3_aggregate_context(ctx, bytes as c_int) - as *mut *mut A; + unsafe fn aggregate_context(ctx: *mut sqlite3_context, + bytes: usize) + -> Option<*mut *mut A> { + let pac = ffi::sqlite3_aggregate_context(ctx, bytes as c_int) as *mut *mut A; if pac.is_null() { return None; } @@ -559,12 +560,14 @@ impl InnerConnection { // Within the xFinal callback, it is customary to set N=0 in calls to // sqlite3_aggregate_context(C,N) so that no pointless memory allocations occur. let a: Option = match aggregate_context(ctx, 0) { - Some(pac) => if (*pac).is_null() { - None - } else { - let a = Box::from_raw(*pac); - Some(*a) - }, + Some(pac) => { + if (*pac).is_null() { + None + } else { + let a = Box::from_raw(*pac); + Some(*a) + } + } None => None, }; From e041f971e8404882ef3ffd84f1b80d21dde8ec64 Mon Sep 17 00:00:00 2001 From: John Gallagher Date: Mon, 1 Feb 2016 11:09:25 -0500 Subject: [PATCH 16/23] Update appveyor configuration: * Test all branches * Test all features --- appveyor.yml | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/appveyor.yml b/appveyor.yml index c5484fe..9fb260e 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -16,10 +16,7 @@ build: false test_script: - cargo test --lib --verbose - -branches: - only: - - appveyor + - cargo test --lib --features "backup blob functions load_extension trace" cache: - C:\Users\appveyor\.cargo From 43613a0020a5fdbc636527a844bcee76f0a964ab Mon Sep 17 00:00:00 2001 From: gwenn Date: Mon, 1 Feb 2016 18:13:07 +0100 Subject: [PATCH 17/23] Moves ZeroBlob from types to blob module. --- src/blob.rs | 17 ++++++++++++++++- src/types.rs | 15 --------------- 2 files changed, 16 insertions(+), 16 deletions(-) diff --git a/src/blob.rs b/src/blob.rs index e33b812..f8b1710 100644 --- a/src/blob.rs +++ b/src/blob.rs @@ -17,7 +17,7 @@ //! extern crate rusqlite; //! //! use rusqlite::{Connection, DatabaseName}; -//! use rusqlite::types::ZeroBlob; +//! use rusqlite::blob::ZeroBlob; //! use std::io::{Read, Write, Seek, SeekFrom}; //! //! fn main() { @@ -52,8 +52,10 @@ use std::io; use std::cmp::min; use std::mem; use std::ptr; +use libc::c_int; use super::ffi; +use super::types::ToSql; use {Result, Connection, DatabaseName}; /// Handle to an open BLOB. @@ -233,6 +235,19 @@ impl<'conn> Drop for Blob<'conn> { } } +/// BLOB of length N that is filled with zeroes. +/// Zeroblobs are intended to serve as placeholders for BLOBs whose content is later written using incremental BLOB I/O routines. +/// A negative value for the zeroblob results in a zero-length BLOB. +#[derive(Copy,Clone)] +pub struct ZeroBlob(pub i32); + +impl ToSql for ZeroBlob { + unsafe fn bind_parameter(&self, stmt: *mut ffi::sqlite3_stmt, col: c_int) -> c_int { + let ZeroBlob(length) = *self; + ffi::sqlite3_bind_zeroblob(stmt, col, length) + } +} + #[cfg(test)] mod test { use std::io::{BufReader, BufRead, BufWriter, Read, Write, Seek, SeekFrom}; diff --git a/src/types.rs b/src/types.rs index 3c474eb..de3d709 100644 --- a/src/types.rs +++ b/src/types.rs @@ -194,21 +194,6 @@ impl ToSql for Null { } } -/// BLOB of length N that is filled with zeroes. -/// Zeroblobs are intended to serve as placeholders for BLOBs whose content is later written using incremental BLOB I/O routines. -/// A negative value for the zeroblob results in a zero-length BLOB. -#[cfg(feature = "blob")] -#[derive(Copy,Clone)] -pub struct ZeroBlob(pub i32); - -#[cfg(feature = "blob")] -impl ToSql for ZeroBlob { - unsafe fn bind_parameter(&self, stmt: *mut sqlite3_stmt, col: c_int) -> c_int { - let ZeroBlob(length) = *self; - ffi::sqlite3_bind_zeroblob(stmt, col, length) - } -} - macro_rules! raw_from_impl( ($t:ty, $f:ident, $c:expr) => ( impl FromSql for $t { From 2d0175b7dd60b30fcc7cc718c6fb03e24d7ecbf8 Mon Sep 17 00:00:00 2001 From: gwenn Date: Mon, 1 Feb 2016 18:41:52 +0100 Subject: [PATCH 18/23] Fix warning with Rust 1.6 warning: lint raw_pointer_derive has been removed: using derive with raw pointers is ok --- libsqlite3-sys/src/bindgen.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libsqlite3-sys/src/bindgen.rs b/libsqlite3-sys/src/bindgen.rs index a60be96..1b60335 100644 --- a/libsqlite3-sys/src/bindgen.rs +++ b/libsqlite3-sys/src/bindgen.rs @@ -1,4 +1,4 @@ -#![allow(raw_pointer_derive, non_snake_case, non_camel_case_types)] +#![allow(non_snake_case, non_camel_case_types)] /* automatically generated by rust-bindgen */ pub type va_list = __builtin_va_list; From 73e805a488b3f5ef56d6205534d6c6fe9a93780e Mon Sep 17 00:00:00 2001 From: John Gallagher Date: Mon, 1 Feb 2016 14:18:12 -0500 Subject: [PATCH 19/23] Update Changelog with changes from recent PR merges --- Changelog.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Changelog.md b/Changelog.md index b7d2363..40c1642 100644 --- a/Changelog.md +++ b/Changelog.md @@ -4,6 +4,9 @@ * Adds `types::Value` for dynamic column types. * Adds support for user-defined aggregate functions (behind the existing `functions` Cargo feature). * Introduces a `RowIndex` trait allowing columns to be fetched via index (as before) or name (new). +* Introduces `ZeroBlob` type under the `blob` module/feature exposing SQLite's zeroblob API. +* Adds CI testing for Windows via AppVeyor. +* Fixes a warning building libsqlite3-sys under Rust 1.6. # Version 0.6.0 (2015-12-17) From 414938931803cccde663202330e4b123686eb25d Mon Sep 17 00:00:00 2001 From: John Gallagher Date: Mon, 1 Feb 2016 14:19:51 -0500 Subject: [PATCH 20/23] Add AppVeyor build status to README --- README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index a813174..bc56bc3 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,7 @@ # Rusqlite -[![Build Status](https://api.travis-ci.org/jgallagher/rusqlite.svg?branch=master)](https://travis-ci.org/jgallagher/rusqlite) +[![Travis Build Status](https://api.travis-ci.org/jgallagher/rusqlite.svg?branch=master)](https://travis-ci.org/jgallagher/rusqlite) +[![AppVeyor Build Status](https://ci.appveyor.com/api/projects/status/github/jgallagher/rusqlite?branch=master&svg=true)](https://ci.appveyor.com/project/jgallagher/rusqlite) 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). View the full From a793f8c8c57edbc23f69fdd0b171f3fea2d99996 Mon Sep 17 00:00:00 2001 From: John Gallagher Date: Mon, 1 Feb 2016 14:30:51 -0500 Subject: [PATCH 21/23] Remove scary lifetime-of-rows-may-panic from README. Closes #119. --- README.md | 39 --------------------------------------- src/lib.rs | 11 ++++------- 2 files changed, 4 insertions(+), 46 deletions(-) diff --git a/README.md b/README.md index bc56bc3..05635c7 100644 --- a/README.md +++ b/README.md @@ -73,45 +73,6 @@ features](http://doc.crates.io/manifest.html#the-features-section). They are: * [`blob`](http://jgallagher.github.io/rusqlite/rusqlite/blob/index.html) gives `std::io::{Read, Write, Seek}` access to SQL BLOBs. -### Design of Rows and Row - -To retrieve the result rows from a query, SQLite requires you to call -[sqlite3_step()](https://www.sqlite.org/c3ref/step.html) on a prepared statement. You can only -retrieve the values of the "current" row. From the Rust point of view, this means that each row -is only valid until the next row is fetched. [rust-sqlite3](https://github.com/dckc/rust-sqlite3) -solves this the correct way with lifetimes. However, this means that the result rows do not -satisfy the [Iterator](http://doc.rust-lang.org/std/iter/trait.Iterator.html) trait, which means -you cannot (as easily) loop over the rows, or use many of the helpful Iterator methods like `map` -and `filter`. - -Instead, Rusqlite's `Rows` handle does conform to `Iterator`. It ensures safety by -performing checks at runtime to ensure you do not try to retrieve the values of a "stale" row, and -will panic if you do so. A specific example that will panic: - -```rust -fn bad_function_will_panic(conn: &Connection) -> Result { - let mut stmt = try!(conn.prepare("SELECT id FROM my_table")); - let mut rows = try!(stmt.query(&[])); - - let row0 = try!(rows.next().unwrap()); - // row 0 is valid now... - - let row1 = try!(rows.next().unwrap()); - // row 0 is now STALE, and row 1 is valid - - let my_id = row0.get(0); // WILL PANIC because row 0 is stale - Ok(my_id) -} -``` - -There are other, less obvious things that may result in a panic as well, such as calling -`collect()` on a `Rows` and then trying to use the collected rows. - -Strongly consider using the method `query_map()` instead, if you can. -`query_map()` returns an iterator over rows-mapped-to-some-type. This -iterator does not have any of the above issues with panics due to attempting to -access stale rows. - ## Author John Gallagher, johnkgallagher@gmail.com diff --git a/src/lib.rs b/src/lib.rs index d4b445e..7a11f64 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -983,6 +983,9 @@ pub type SqliteRows<'stmt> = Rows<'stmt>; /// /// ## Warning /// +/// Strongly consider using `query_map` or `query_and_then` instead of `query`; the former do not +/// suffer from the following problem. +/// /// Due to the way SQLite returns result rows of a query, it is not safe to attempt to get values /// from a row after it has become stale (i.e., `next()` has been called again on the `Rows` /// iterator). For example: @@ -994,7 +997,7 @@ pub type SqliteRows<'stmt> = Rows<'stmt>; /// let mut rows = try!(stmt.query(&[])); /// /// let row0 = try!(rows.next().unwrap()); -/// // row 0 is value now... +/// // row 0 is valid for now... /// /// let row1 = try!(rows.next().unwrap()); /// // row 0 is now STALE, and row 1 is valid @@ -1008,12 +1011,6 @@ pub type SqliteRows<'stmt> = Rows<'stmt>; /// (which would result in a collection of rows, only the last of which can safely be used) and /// `min`/`max` (which could return a stale row unless the last row happened to be the min or max, /// respectively). -/// -/// This problem could be solved by changing the signature of `next` to tie the lifetime of the -/// returned row to the lifetime of (a mutable reference to) the result rows handle, but this would -/// no longer implement `Iterator`, and therefore you would lose access to the majority of -/// functions which are useful (such as support for `for ... in ...` looping, `map`, `filter`, -/// etc.). pub struct Rows<'stmt> { stmt: &'stmt Statement<'stmt>, current_row: Rc>, From 350fd11fed963b73f8e4b0ec206c57e0f4c636fe Mon Sep 17 00:00:00 2001 From: John Gallagher Date: Mon, 1 Feb 2016 15:21:03 -0500 Subject: [PATCH 22/23] Add a `handle()` method to unsafely get the underlying SQLite connection. Doc comments suggest opening issues on rusqlite for any uses of `handle()`, as uses indicate areas where rusqlite insufficiently wraps SQLite. --- src/lib.rs | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/lib.rs b/src/lib.rs index 7a11f64..6b52a95 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -494,6 +494,18 @@ impl Connection { self.db.borrow_mut().load_extension(dylib_path.as_ref(), entry_point) } + /// Get access to the underlying SQLite database connection handle. + /// + /// # Warning + /// + /// You should not need to use this function. If you do need to, please [open an issue + /// on the rusqlite repository](https://github.com/jgallagher/rusqlite/issues) and describe + /// your use case. This function is unsafe because it gives you raw access to the SQLite + /// connection, and what you do with it could impact the safety of this `Connection`. + pub unsafe fn handle(&self) -> *mut ffi::Struct_sqlite3 { + self.db.borrow().db() + } + fn decode_result(&self, code: c_int) -> Result<()> { self.db.borrow_mut().decode_result(code) } From d6d9fa9f6324500e765cff9ca28047577406f732 Mon Sep 17 00:00:00 2001 From: John Gallagher Date: Mon, 1 Feb 2016 15:23:05 -0500 Subject: [PATCH 23/23] Add handle() to Changelog --- Changelog.md | 1 + 1 file changed, 1 insertion(+) diff --git a/Changelog.md b/Changelog.md index 40c1642..63828da 100644 --- a/Changelog.md +++ b/Changelog.md @@ -7,6 +7,7 @@ * Introduces `ZeroBlob` type under the `blob` module/feature exposing SQLite's zeroblob API. * Adds CI testing for Windows via AppVeyor. * Fixes a warning building libsqlite3-sys under Rust 1.6. +* Adds an unsafe `handle()` method to `Connection`. Please file an issue if you actually use it. # Version 0.6.0 (2015-12-17)