mirror of
https://github.com/isar/rusqlite.git
synced 2025-02-01 05:40:50 +08:00
Merge remote-tracking branch 'jgallagher/master' into vtab
This commit is contained in:
commit
eab16402be
@ -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)
|
||||
|
||||
|
@ -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
|
||||
|
22
appveyor.yml
Normal file
22
appveyor.yml
Normal file
@ -0,0 +1,22 @@
|
||||
environment:
|
||||
TARGET: 1.6.0-x86_64-pc-windows-gnu
|
||||
MSYS2_BITS: 64
|
||||
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"
|
||||
- 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-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
|
||||
|
||||
test_script:
|
||||
- cargo test --lib --verbose
|
||||
- cargo test --lib --features "backup blob functions load_extension trace"
|
||||
|
||||
cache:
|
||||
- C:\Users\appveyor\.cargo
|
@ -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;
|
||||
|
18
src/blob.rs
18
src/blob.rs
@ -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};
|
||||
|
@ -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;
|
||||
}
|
||||
};
|
||||
|
||||
let a: Option<A> = if (*pac).is_null() {
|
||||
// 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)
|
||||
}
|
||||
}
|
||||
None => None,
|
||||
};
|
||||
|
||||
match (*boxed_aggr).finalize(a) {
|
||||
|
Loading…
x
Reference in New Issue
Block a user