mirror of
https://github.com/isar/rusqlite.git
synced 2024-11-23 09:09:19 +08:00
Allow getting a ValueRef out of Row and Context, fixes #259
This commit is contained in:
parent
73d7606ebc
commit
3d82f7199a
@ -139,6 +139,16 @@ impl<'a> Context<'a> {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns the `idx`th argument as a `ValueRef`.
|
||||||
|
///
|
||||||
|
/// # Failure
|
||||||
|
///
|
||||||
|
/// Will panic if `idx` is greater than or equal to `self.len()`.
|
||||||
|
pub fn get_raw(&self, idx: usize) -> ValueRef<'a> {
|
||||||
|
let arg = self.args[idx];
|
||||||
|
unsafe { ValueRef::from_value(arg) }
|
||||||
|
}
|
||||||
|
|
||||||
/// Sets the auxilliary data associated with a particular parameter. See
|
/// Sets the auxilliary data associated with a particular parameter. See
|
||||||
/// https://www.sqlite.org/c3ref/get_auxdata.html for a discussion of
|
/// https://www.sqlite.org/c3ref/get_auxdata.html for a discussion of
|
||||||
/// this feature, or the unit tests of this module for an example.
|
/// this feature, or the unit tests of this module for an example.
|
||||||
@ -530,8 +540,10 @@ mod test {
|
|||||||
let is_match = {
|
let is_match = {
|
||||||
let re = saved_re.unwrap_or_else(|| new_re.as_ref().unwrap());
|
let re = saved_re.unwrap_or_else(|| new_re.as_ref().unwrap());
|
||||||
|
|
||||||
let text = try!(ctx.get::<String>(1));
|
let text = ctx.get_raw(1).as_str().map_err(|e|
|
||||||
re.is_match(&text)
|
Error::UserFunctionError(e.into()))?;
|
||||||
|
|
||||||
|
re.is_match(text)
|
||||||
};
|
};
|
||||||
|
|
||||||
if let Some(re) = new_re {
|
if let Some(re) = new_re {
|
||||||
|
23
src/lib.rs
23
src/lib.rs
@ -1592,6 +1592,29 @@ mod test {
|
|||||||
// degree of reliability.
|
// degree of reliability.
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_get_raw() {
|
||||||
|
let db = checked_memory_handle();
|
||||||
|
db.execute_batch("CREATE TABLE foo(i, x);").unwrap();
|
||||||
|
let vals = ["foobar", "1234", "qwerty"];
|
||||||
|
let mut insert_stmt = db.prepare("INSERT INTO foo(i, x) VALUES(?, ?)").unwrap();
|
||||||
|
for (i, v) in vals.iter().enumerate() {
|
||||||
|
let i_to_insert = i as i64;
|
||||||
|
assert_eq!(insert_stmt.execute(&[&i_to_insert as &dyn ToSql, &v]).unwrap(), 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut query = db.prepare("SELECT i, x FROM foo").unwrap();
|
||||||
|
let mut rows = query.query(NO_PARAMS).unwrap();
|
||||||
|
|
||||||
|
while let Some(res) = rows.next() {
|
||||||
|
let row = res.unwrap();
|
||||||
|
let i = row.get_raw(0).as_i64().unwrap();
|
||||||
|
let expect = vals[i as usize];
|
||||||
|
let x = row.get_raw("x").as_str().unwrap();
|
||||||
|
assert_eq!(x, expect);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
mod query_and_then_tests {
|
mod query_and_then_tests {
|
||||||
extern crate libsqlite3_sys as ffi;
|
extern crate libsqlite3_sys as ffi;
|
||||||
use super::*;
|
use super::*;
|
||||||
|
47
src/row.rs
47
src/row.rs
@ -2,7 +2,7 @@ use std::marker::PhantomData;
|
|||||||
use std::{convert, result};
|
use std::{convert, result};
|
||||||
|
|
||||||
use super::{Error, Result, Statement};
|
use super::{Error, Result, Statement};
|
||||||
use types::{FromSql, FromSqlError};
|
use types::{FromSql, FromSqlError, ValueRef};
|
||||||
|
|
||||||
/// An handle for the resulting rows of a query.
|
/// An handle for the resulting rows of a query.
|
||||||
pub struct Rows<'stmt> {
|
pub struct Rows<'stmt> {
|
||||||
@ -126,7 +126,7 @@ where
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// A single result row of a query.
|
/// A single result row of a query.
|
||||||
pub struct Row<'a, 'stmt> {
|
pub struct Row<'a, 'stmt: 'a> {
|
||||||
stmt: &'stmt Statement<'stmt>,
|
stmt: &'stmt Statement<'stmt>,
|
||||||
phantom: PhantomData<&'a ()>,
|
phantom: PhantomData<&'a ()>,
|
||||||
}
|
}
|
||||||
@ -173,6 +173,49 @@ impl<'a, 'stmt> Row<'a, 'stmt> {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Get the value of a particular column of the result row as a `ValueRef`,
|
||||||
|
/// allowing data to be read out of a row without copying.
|
||||||
|
///
|
||||||
|
/// This `ValueRef` is valid only as long as this Row, which is enforced by
|
||||||
|
/// it's lifetime. This means that while this method is completely safe,
|
||||||
|
/// it can be somewhat difficult to use, and most callers will be better
|
||||||
|
/// served by `get` or `get_checked`.
|
||||||
|
///
|
||||||
|
/// ## Failure
|
||||||
|
///
|
||||||
|
/// Returns an `Error::InvalidColumnIndex` if `idx` is outside the valid
|
||||||
|
/// column range for this row.
|
||||||
|
///
|
||||||
|
/// Returns an `Error::InvalidColumnName` if `idx` is not a valid column
|
||||||
|
/// name for this row.
|
||||||
|
pub fn get_raw_checked<I: RowIndex>(&self, idx: I) -> Result<ValueRef<'a>> {
|
||||||
|
let idx = idx.idx(self.stmt)?;
|
||||||
|
// Narrowing from `ValueRef<'stmt>` (which `self.stmt.value_ref(idx)`
|
||||||
|
// returns) to `ValueRef<'a>` is needed because it's only valid until
|
||||||
|
// the next call to sqlite3_step.
|
||||||
|
let val_ref = self.stmt.value_ref(idx);
|
||||||
|
Ok(val_ref)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Get the value of a particular column of the result row as a `ValueRef`,
|
||||||
|
/// allowing data to be read out of a row without copying.
|
||||||
|
///
|
||||||
|
/// This `ValueRef` is valid only as long as this Row, which is enforced by
|
||||||
|
/// it's lifetime. This means that while this method is completely safe,
|
||||||
|
/// it can be difficult to use, and most callers will be better served by
|
||||||
|
/// `get` or `get_checked`.
|
||||||
|
///
|
||||||
|
/// ## Failure
|
||||||
|
///
|
||||||
|
/// Panics if calling `row.get_raw_checked(idx)` would return an error,
|
||||||
|
/// including:
|
||||||
|
///
|
||||||
|
/// * If `idx` is outside the range of columns in the returned query.
|
||||||
|
/// * If `idx` is not a valid column name for this row.
|
||||||
|
pub fn get_raw<I: RowIndex>(&self, idx: I) -> ValueRef<'a> {
|
||||||
|
self.get_raw_checked(idx).unwrap()
|
||||||
|
}
|
||||||
|
|
||||||
/// Return the number of columns in the current row.
|
/// Return the number of columns in the current row.
|
||||||
pub fn column_count(&self) -> usize {
|
pub fn column_count(&self) -> usize {
|
||||||
self.stmt.column_count()
|
self.stmt.column_count()
|
||||||
|
@ -52,7 +52,7 @@ impl<'a> ValueRef<'a> {
|
|||||||
|
|
||||||
/// If `self` is case `Text`, returns the string value. Otherwise, returns
|
/// If `self` is case `Text`, returns the string value. Otherwise, returns
|
||||||
/// `Err(Error::InvalidColumnType)`.
|
/// `Err(Error::InvalidColumnType)`.
|
||||||
pub fn as_str(&self) -> FromSqlResult<&str> {
|
pub fn as_str(&self) -> FromSqlResult<&'a str> {
|
||||||
match *self {
|
match *self {
|
||||||
ValueRef::Text(t) => Ok(t),
|
ValueRef::Text(t) => Ok(t),
|
||||||
_ => Err(FromSqlError::InvalidType),
|
_ => Err(FromSqlError::InvalidType),
|
||||||
@ -61,7 +61,7 @@ impl<'a> ValueRef<'a> {
|
|||||||
|
|
||||||
/// If `self` is case `Blob`, returns the byte slice. Otherwise, returns
|
/// If `self` is case `Blob`, returns the byte slice. Otherwise, returns
|
||||||
/// `Err(Error::InvalidColumnType)`.
|
/// `Err(Error::InvalidColumnType)`.
|
||||||
pub fn as_blob(&self) -> FromSqlResult<&[u8]> {
|
pub fn as_blob(&self) -> FromSqlResult<&'a [u8]> {
|
||||||
match *self {
|
match *self {
|
||||||
ValueRef::Blob(b) => Ok(b),
|
ValueRef::Blob(b) => Ok(b),
|
||||||
_ => Err(FromSqlError::InvalidType),
|
_ => Err(FromSqlError::InvalidType),
|
||||||
|
Loading…
Reference in New Issue
Block a user