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

This commit is contained in:
gwenn
2016-02-01 20:35:30 +01:00
6 changed files with 61 additions and 19 deletions

View File

@@ -17,6 +17,7 @@
//! extern crate rusqlite;
//!
//! use rusqlite::{Connection, DatabaseName};
//! use rusqlite::blob::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();
@@ -51,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.
@@ -232,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};

View File

@@ -509,9 +509,10 @@ impl InnerConnection {
where D: Aggregate<A, T>,
T: ToResult
{
unsafe fn aggregate_context<A>(ctx: *mut sqlite3_context) -> Option<*mut *mut A> {
let pac = ffi::sqlite3_aggregate_context(ctx, ::std::mem::size_of::<*mut A>() as c_int)
as *mut *mut A;
unsafe fn aggregate_context<A>(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;
}
@@ -545,7 +546,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);
@@ -576,19 +577,18 @@ 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;
// 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<A> = match aggregate_context(ctx, 0) {
Some(pac) => {
if (*pac).is_null() {
None
} else {
let a = Box::from_raw(*pac);
Some(*a)
}
}
};
let a: Option<A> = if (*pac).is_null() {
None
} else {
let a = Box::from_raw(*pac);
Some(*a)
None => None,
};
match (*boxed_aggr).finalize(a) {