diff --git a/bindings/rust/src/lib.rs b/bindings/rust/src/lib.rs index d173204c1..fdc0810a4 100644 --- a/bindings/rust/src/lib.rs +++ b/bindings/rust/src/lib.rs @@ -33,6 +33,7 @@ //! ``` pub mod params; +pub mod statement; pub mod value; pub use value::Value; @@ -40,8 +41,8 @@ pub use value::Value; pub use params::params_from_iter; use crate::params::*; +use crate::statement::Statement; use std::fmt::Debug; -use std::num::NonZero; use std::sync::{Arc, Mutex}; #[derive(Debug, thiserror::Error)] @@ -62,7 +63,7 @@ impl From for Error { pub(crate) type BoxError = Box; -pub type Result = std::result::Result; +pub(crate) type Result = std::result::Result; /// A builder for `Database`. pub struct Builder { @@ -213,119 +214,6 @@ impl Debug for Connection { } } -/// A prepared statement. -pub struct Statement { - inner: Arc>, -} - -impl Clone for Statement { - fn clone(&self) -> Self { - Self { - inner: Arc::clone(&self.inner), - } - } -} - -unsafe impl Send for Statement {} -unsafe impl Sync for Statement {} - -impl Statement { - /// Query the database with this prepared statement. - pub async fn query(&mut self, params: impl IntoParams) -> Result { - let params = params.into_params()?; - match params { - params::Params::None => (), - params::Params::Positional(values) => { - for (i, value) in values.into_iter().enumerate() { - let mut stmt = self.inner.lock().unwrap(); - stmt.bind_at(NonZero::new(i + 1).unwrap(), value.into()); - } - } - params::Params::Named(values) => { - for (name, value) in values.into_iter() { - let mut stmt = self.inner.lock().unwrap(); - let i = stmt.parameters().index(name).unwrap(); - stmt.bind_at(i, value.into()); - } - } - } - #[allow(clippy::arc_with_non_send_sync)] - let rows = Rows { - inner: Arc::clone(&self.inner), - }; - Ok(rows) - } - - /// Execute this prepared statement. - pub async fn execute(&mut self, params: impl IntoParams) -> Result { - { - // Reset the statement before executing - self.inner.lock().unwrap().reset(); - } - let params = params.into_params()?; - match params { - params::Params::None => (), - params::Params::Positional(values) => { - for (i, value) in values.into_iter().enumerate() { - let mut stmt = self.inner.lock().unwrap(); - stmt.bind_at(NonZero::new(i + 1).unwrap(), value.into()); - } - } - params::Params::Named(values) => { - for (name, value) in values.into_iter() { - let mut stmt = self.inner.lock().unwrap(); - let i = stmt.parameters().index(name).unwrap(); - stmt.bind_at(i, value.into()); - } - } - } - loop { - let mut stmt = self.inner.lock().unwrap(); - match stmt.step() { - Ok(turso_core::StepResult::Row) => { - // unexpected row during execution, error out. - return Ok(2); - } - Ok(turso_core::StepResult::Done) => { - return Ok(0); - } - Ok(turso_core::StepResult::IO) => { - let _ = stmt.run_once(); - //return Ok(1); - } - Ok(turso_core::StepResult::Busy) => { - return Ok(4); - } - Ok(turso_core::StepResult::Interrupt) => { - return Ok(3); - } - Err(err) => { - return Err(err.into()); - } - } - } - } - - /// Returns columns of the result of this prepared statement. - pub fn columns(&self) -> Vec { - let stmt = self.inner.lock().unwrap(); - - let n = stmt.num_columns(); - - let mut cols = Vec::with_capacity(n); - - for i in 0..n { - let name = stmt.get_column_name(i).into_owned(); - cols.push(Column { - name, - decl_type: None, // TODO - }); - } - - cols - } -} - /// Column information. pub struct Column { name: String, diff --git a/bindings/rust/src/statement.rs b/bindings/rust/src/statement.rs new file mode 100644 index 000000000..5a0a8fca2 --- /dev/null +++ b/bindings/rust/src/statement.rs @@ -0,0 +1,122 @@ +use std::{ + num::NonZero, + sync::{Arc, Mutex}, +}; + +use crate::{ + params::{self, IntoParams}, + Column, Rows, +}; + +/// A prepared statement. +pub struct Statement { + pub(crate) inner: Arc>, +} + +impl Clone for Statement { + fn clone(&self) -> Self { + Self { + inner: Arc::clone(&self.inner), + } + } +} + +unsafe impl Send for Statement {} +unsafe impl Sync for Statement {} + +impl Statement { + /// Query the database with this prepared statement. + pub async fn query(&mut self, params: impl IntoParams) -> crate::Result { + let params = params.into_params()?; + match params { + params::Params::None => (), + params::Params::Positional(values) => { + for (i, value) in values.into_iter().enumerate() { + let mut stmt = self.inner.lock().unwrap(); + stmt.bind_at(NonZero::new(i + 1).unwrap(), value.into()); + } + } + params::Params::Named(values) => { + for (name, value) in values.into_iter() { + let mut stmt = self.inner.lock().unwrap(); + let i = stmt.parameters().index(name).unwrap(); + stmt.bind_at(i, value.into()); + } + } + } + #[allow(clippy::arc_with_non_send_sync)] + let rows = Rows { + inner: Arc::clone(&self.inner), + }; + Ok(rows) + } + + /// Execute this prepared statement. + pub async fn execute(&mut self, params: impl IntoParams) -> crate::Result { + { + // Reset the statement before executing + self.inner.lock().unwrap().reset(); + } + let params = params.into_params()?; + match params { + params::Params::None => (), + params::Params::Positional(values) => { + for (i, value) in values.into_iter().enumerate() { + let mut stmt = self.inner.lock().unwrap(); + stmt.bind_at(NonZero::new(i + 1).unwrap(), value.into()); + } + } + params::Params::Named(values) => { + for (name, value) in values.into_iter() { + let mut stmt = self.inner.lock().unwrap(); + let i = stmt.parameters().index(name).unwrap(); + stmt.bind_at(i, value.into()); + } + } + } + loop { + let mut stmt = self.inner.lock().unwrap(); + match stmt.step() { + Ok(turso_core::StepResult::Row) => { + // unexpected row during execution, error out. + return Ok(2); + } + Ok(turso_core::StepResult::Done) => { + return Ok(0); + } + Ok(turso_core::StepResult::IO) => { + let _ = stmt.run_once(); + //return Ok(1); + } + Ok(turso_core::StepResult::Busy) => { + return Ok(4); + } + Ok(turso_core::StepResult::Interrupt) => { + return Ok(3); + } + Err(err) => { + return Err(err.into()); + } + } + } + } + + /// Returns columns of the result of this prepared statement. + pub fn columns(&self) -> Vec { + let stmt = self.inner.lock().unwrap(); + + let n = stmt.num_columns(); + + let mut cols = Vec::with_capacity(n); + + for i in 0..n { + let name = stmt.get_column_name(i).into_owned(); + cols.push(Column { + name, + decl_type: None, // TODO + }); + } + + cols + } +}