Skip to main content

sqlite_provider/
statement.rs

1use core::ptr::NonNull;
2
3use crate::error::Result;
4use crate::provider::{Sqlite3Api, StepResult, ValueType};
5use crate::row::Row;
6use crate::value::Value;
7use crate::Connection;
8
9/// Prepared statement wrapper.
10pub struct Statement<'c, 'p, P: Sqlite3Api> {
11    pub(crate) conn: &'c Connection<'p, P>,
12    pub(crate) stmt: NonNull<P::Stmt>,
13}
14
15impl<'c, 'p, P: Sqlite3Api> Statement<'c, 'p, P> {
16    pub(crate) fn new(conn: &'c Connection<'p, P>, stmt: NonNull<P::Stmt>) -> Self {
17        Self { conn, stmt }
18    }
19
20    /// Reset the statement.
21    pub fn reset(&mut self) -> Result<()> {
22        unsafe { self.conn.api.reset(self.stmt) }
23    }
24
25    /// Step the statement; returns `Some(Row)` while rows are available.
26    pub fn step(&mut self) -> Result<Option<Row<'_, 'c, 'p, P>>> {
27        match unsafe { self.conn.api.step(self.stmt)? } {
28            StepResult::Row => Ok(Some(Row::new(self))),
29            StepResult::Done => Ok(None),
30        }
31    }
32
33    /// Bind NULL at parameter `idx`.
34    pub fn bind_null(&mut self, idx: i32) -> Result<()> {
35        unsafe { self.conn.api.bind_null(self.stmt, idx) }
36    }
37
38    /// Bind integer at parameter `idx`.
39    pub fn bind_int64(&mut self, idx: i32, value: i64) -> Result<()> {
40        unsafe { self.conn.api.bind_int64(self.stmt, idx, value) }
41    }
42
43    /// Bind double at parameter `idx`.
44    pub fn bind_double(&mut self, idx: i32, value: f64) -> Result<()> {
45        unsafe { self.conn.api.bind_double(self.stmt, idx, value) }
46    }
47
48    /// Bind text at parameter `idx`.
49    pub fn bind_text(&mut self, idx: i32, value: &str) -> Result<()> {
50        unsafe { self.conn.api.bind_text(self.stmt, idx, value) }
51    }
52
53    /// Bind blob at parameter `idx`.
54    pub fn bind_blob(&mut self, idx: i32, value: &[u8]) -> Result<()> {
55        unsafe { self.conn.api.bind_blob(self.stmt, idx, value) }
56    }
57
58    /// Bind an owned value at parameter `idx`.
59    pub fn bind_value(&mut self, idx: i32, value: &Value) -> Result<()> {
60        match value {
61            Value::Null => self.bind_null(idx),
62            Value::Integer(v) => self.bind_int64(idx, *v),
63            Value::Float(v) => self.bind_double(idx, *v),
64            Value::Text(v) => self.bind_text(idx, v),
65            Value::Blob(v) => self.bind_blob(idx, v),
66        }
67    }
68
69    /// Number of columns in the result set.
70    pub fn column_count(&self) -> i32 {
71        unsafe { self.conn.api.column_count(self.stmt) }
72    }
73
74    /// Column type for the current row.
75    pub fn column_type(&self, col: i32) -> ValueType {
76        unsafe { self.conn.api.column_type(self.stmt, col) }
77    }
78
79    /// Expose the raw statement handle.
80    pub fn raw_handle(&self) -> NonNull<P::Stmt> {
81        self.stmt
82    }
83}
84
85impl<'c, 'p, P: Sqlite3Api> Drop for Statement<'c, 'p, P> {
86    fn drop(&mut self) {
87        let _ = unsafe { self.conn.api.finalize(self.stmt) };
88    }
89}