Skip to content
This repository was archived by the owner on Jul 25, 2020. It is now read-only.

Revamp Cursor::get_{text,blob} functions #94

Merged
merged 2 commits into from
Jul 27, 2014
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
53 changes: 30 additions & 23 deletions src/cursor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,10 @@
use ffi::*;
use libc::{c_int, c_void};
use std::collections::HashMap;
use std::mem::transmute;
use std::str;
use std::slice;
use std::c_str::CString;
use types::*;

/// The database cursor.
Expand Down Expand Up @@ -93,13 +95,13 @@ impl<'db> Cursor<'db> {
let mut i = 0;
let mut sqlrow = HashMap::new();
while i < column_cnt {
let name = self.get_column_name(i);
let name = self.get_column_name(i).to_string();
let coltype = self.get_column_type(i);
let res = match coltype {
SQLITE_INTEGER => sqlrow.insert(name, Integer(self.get_int(i))),
SQLITE_FLOAT => sqlrow.insert(name, Float64(self.get_f64(i))),
SQLITE_TEXT => sqlrow.insert(name, Text(self.get_text(i))),
SQLITE_BLOB => sqlrow.insert(name, Blob(self.get_blob(i))),
SQLITE_TEXT => sqlrow.insert(name, Text(self.get_text(i).unwrap().to_string())),
SQLITE_BLOB => sqlrow.insert(name, Blob(self.get_blob(i).unwrap().to_vec())),
SQLITE_NULL => sqlrow.insert(name, Null),
};
if res == false {
Expand All @@ -119,20 +121,14 @@ impl<'db> Cursor<'db> {

///
/// See http://www.sqlite.org/c3ref/column_blob.html
pub fn get_bytes(&self, i: int) -> int {
unsafe {
sqlite3_column_bytes(self.stmt, i as c_int) as int
}
}

///
/// See http://www.sqlite.org/c3ref/column_blob.html
pub fn get_blob(&self, i: int) -> Vec<u8> {
let len = self.get_bytes(i);
unsafe {
slice::raw::buf_as_slice(
sqlite3_column_blob(self.stmt, i as c_int), len as uint,
|bytes| Vec::from_slice(bytes))
pub fn get_blob<'a>(&'a self, i: int) -> Option<&'a [u8]> {
let ptr = unsafe {sqlite3_column_blob(self.stmt, i as c_int)};
let len = unsafe {sqlite3_column_bytes(self.stmt, i as c_int)} as uint;
if ptr.is_null() {
None
} else {
// make `bytes` outlive the `buf_as_slice` call
unsafe {slice::raw::buf_as_slice(ptr, len, |bytes: &[u8]| Some(transmute(bytes)))}
}
}

Expand Down Expand Up @@ -162,9 +158,18 @@ impl<'db> Cursor<'db> {

///
/// See http://www.sqlite.org/c3ref/column_blob.html
pub fn get_text(&self, i: int) -> String {
unsafe {
return str::raw::from_c_str( sqlite3_column_text(self.stmt, i as c_int) );
pub fn get_text<'a>(&'a self, i: int) -> Option<&'a str> {
let ptr = unsafe {sqlite3_column_text(self.stmt, i as c_int)};
let len = unsafe {sqlite3_column_bytes(self.stmt, i as c_int)} as uint;
if ptr.is_null() {
None
} else {
unsafe {
slice::raw::buf_as_slice(ptr as *const u8, len, |bytes| {
let text: &str = str::raw::from_utf8(bytes);
Some(transmute(text)) // make `text` outlive the `buf_as_slice` call
})
}
}
}

Expand All @@ -189,9 +194,11 @@ impl<'db> Cursor<'db> {

/// Returns the name of the column with index `i` in the result set.
/// See http://www.sqlite.org/c3ref/column_name.html
pub fn get_column_name(&self, i: int) -> String {
pub fn get_column_name<'a>(&'a self, i: int) -> &'a str {
unsafe {
return str::raw::from_c_str( sqlite3_column_name(self.stmt, i as c_int) );
let name = CString::new(sqlite3_column_name(self.stmt, i as c_int), false);
let namestr: &str = str::raw::from_utf8(name.as_bytes_no_nul());
transmute(namestr) // make it outlive the original `CString`
}
}

Expand Down Expand Up @@ -219,7 +226,7 @@ impl<'db> Cursor<'db> {
let mut i = 0;
let mut r = Vec::new();
while i < cnt {
r.push(self.get_column_name(i));
r.push(self.get_column_name(i).to_string());
i += 1;
}
return r;
Expand Down
4 changes: 2 additions & 2 deletions src/database.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ use cursor::*;
use ffi::*;
use libc::c_int;
use std::ptr;
use std::str;
use std::string;
use types::*;

/// The database connection.
Expand Down Expand Up @@ -62,7 +62,7 @@ impl Database {
/// See http://www.sqlite.org/c3ref/errcode.html
pub fn get_errmsg(&self) -> String {
unsafe {
str::raw::from_c_str(sqlite3_errmsg(self.dbh))
string::raw::from_buf(sqlite3_errmsg(self.dbh) as *const u8)
}
}

Expand Down
19 changes: 17 additions & 2 deletions src/sqlite3.rs
Original file line number Diff line number Diff line change
Expand Up @@ -172,7 +172,7 @@ mod tests {

let sth = checked_prepare(&database, "SELECT v FROM test WHERE id = 1;");
assert!(sth.step() == SQLITE_ROW);
assert!(sth.get_blob(0) == vec!(0x00, 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xff));
assert!(sth.get_blob(0) == Some([0x00, 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xff].as_slice()));
assert!(sth.step() == SQLITE_DONE);
}

Expand Down Expand Up @@ -298,7 +298,7 @@ mod tests {
COMMIT;
"
);
debug!("test `last insert_id`: {}", (database.get_last_insert_rowid() as u64).to_string() );
debug!("test `last insert_id`: {}", database.get_last_insert_rowid());
assert!(database.get_last_insert_rowid() == 1_i64);
}

Expand Down Expand Up @@ -343,5 +343,20 @@ mod tests {
return r.unwrap() == v;
}
}

#[test]
fn get_text_without_step() {
let db = checked_open();
let c = checked_prepare(&db, "select 1 + 1");
assert_eq!(c.get_text(0), None);
}

#[test]
fn get_text_on_bogus_col() {
let db = checked_open();
let c = checked_prepare(&db, "select 1 + 1");
c.step();
assert_eq!(c.get_text(1), None);
}
}