-
Notifications
You must be signed in to change notification settings - Fork 470
Expand file tree
/
Copy pathbind.rs
More file actions
71 lines (65 loc) · 2.16 KB
/
bind.rs
File metadata and controls
71 lines (65 loc) · 2.16 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
use crate::{ffi, Error, Result, Statement};
use std::ffi::CStr;
mod sealed {
use std::ffi::CStr;
/// This trait exists just to ensure that the only impls of `trait BindIndex`
/// that are allowed are ones in this crate.
pub trait Sealed {}
impl Sealed for usize {}
impl Sealed for &str {}
impl Sealed for &CStr {}
}
/// A trait implemented by types that can index into parameters of a statement.
///
/// It is only implemented for `usize` and `&str` and `&CStr`.
pub trait BindIndex: sealed::Sealed {
/// Returns the index of the associated parameter, or `Error` if no such
/// parameter exists.
fn idx(&self, stmt: &Statement<'_>) -> Result<usize>;
}
impl BindIndex for usize {
#[inline]
fn idx(&self, _: &Statement<'_>) -> Result<usize> {
// No validation
Ok(*self)
}
}
impl BindIndex for &'_ str {
fn idx(&self, stmt: &Statement<'_>) -> Result<usize> {
match stmt.parameter_index(self)? {
Some(idx) => Ok(idx),
None => Err(Error::InvalidParameterName(self.to_string())),
}
}
}
/// C-string literal to avoid alloc
impl BindIndex for &CStr {
fn idx(&self, stmt: &Statement<'_>) -> Result<usize> {
let r = unsafe { ffi::sqlite3_bind_parameter_index(stmt.ptr(), self.as_ptr()) };
match r {
0 => Err(Error::InvalidParameterName(
self.to_string_lossy().to_string(),
)),
i => Ok(i as usize),
}
}
}
#[cfg(all(test, not(miri)))]
mod test {
use crate::{ffi, Connection, Error, Result};
#[test]
fn invalid_name() -> Result<()> {
let db = Connection::open_in_memory()?;
let mut stmt = db.prepare("SELECT 1")?;
let err = stmt.raw_bind_parameter(1, 1).unwrap_err();
assert_eq!(
err.sqlite_error_code(),
Some(ffi::ErrorCode::ParameterOutOfRange),
);
let err = stmt.raw_bind_parameter(":p1", 1).unwrap_err();
assert_eq!(err, Error::InvalidParameterName(":p1".to_owned()));
let err = stmt.raw_bind_parameter(c"x", 1).unwrap_err();
assert_eq!(err, Error::InvalidParameterName("x".to_owned()));
Ok(())
}
}