From b8b1138fcf1ed29d50f5a3f9d94a9719e35146c2 Mon Sep 17 00:00:00 2001 From: Nick Hynes Date: Sun, 25 Apr 2021 18:53:37 -0500 Subject: [PATCH] Add Statement::parameter_name --- src/raw_statement.rs | 12 ++++++++++++ src/statement.rs | 35 +++++++++++++++++++++++++++++++++++ 2 files changed, 47 insertions(+) diff --git a/src/raw_statement.rs b/src/raw_statement.rs index eda47fb..ef94d81 100644 --- a/src/raw_statement.rs +++ b/src/raw_statement.rs @@ -144,6 +144,18 @@ impl RawStatement { }) } + #[inline] + pub fn bind_parameter_name(&self, index: i32) -> Option<&CStr> { + unsafe { + let name = ffi::sqlite3_bind_parameter_name(self.ptr, index); + if name.is_null() { + None + } else { + Some(CStr::from_ptr(name)) + } + } + } + #[inline] pub fn clear_bindings(&self) -> c_int { unsafe { ffi::sqlite3_clear_bindings(self.ptr) } diff --git a/src/statement.rs b/src/statement.rs index b8fc3ee..e1b6b83 100644 --- a/src/statement.rs +++ b/src/statement.rs @@ -521,6 +521,30 @@ impl Statement<'_> { Ok(self.stmt.bind_parameter_index(name)) } + /// Return the SQL parameter name given its (one-based) index (the inverse of + /// [`Statement::parameter_index`]). + /// + /// ```rust,no_run + /// # use rusqlite::{Connection, Result}; + /// fn example(conn: &Connection) -> Result<()> { + /// let stmt = conn.prepare("SELECT * FROM test WHERE name = :example")?; + /// let index = stmt.parameter_name(1); + /// assert_eq!(index, Some(":example")); + /// Ok(()) + /// } + /// ``` + /// + /// # Failure + /// + /// Will return `None` if the column index is out of bounds or if the parameter + /// is positional. + #[inline] + pub fn parameter_name(&self, index: usize) -> Option<&'_ str> { + self.stmt.bind_parameter_name(index as i32).map(|name| { + str::from_utf8(name.to_bytes()).expect("Invalid UTF-8 sequence in parameter name") + }) + } + #[inline] pub(crate) fn bind_parameters

(&mut self, params: P) -> Result<()> where @@ -1334,6 +1358,17 @@ mod test { Ok(()) } + #[test] + fn test_parameter_name() -> Result<()> { + let db = Connection::open_in_memory()?; + db.execute_batch("CREATE TABLE test (name TEXT, value INTEGER)")?; + let stmt = db.prepare("INSERT INTO test (name, value) VALUES (:name, ?3)")?; + assert_eq!(stmt.parameter_name(0), None); + assert_eq!(stmt.parameter_name(1), Some(":name")); + assert_eq!(stmt.parameter_name(2), None); + Ok(()) + } + #[test] fn test_empty_stmt() -> Result<()> { let conn = Connection::open_in_memory()?;