From 572d3bd4ce030f62ab66ac52e14fb0fa2a06569c Mon Sep 17 00:00:00 2001 From: Diego Reis Date: Thu, 31 Jul 2025 16:08:06 -0300 Subject: [PATCH] Simplify Rust API verbosity by implementing Row.get() and Statement.query_row() --- bindings/rust/src/lib.rs | 15 +++++++++ bindings/rust/src/rows.rs | 8 +++++ bindings/rust/src/transaction.rs | 52 ++++++++++++-------------------- 3 files changed, 42 insertions(+), 33 deletions(-) diff --git a/bindings/rust/src/lib.rs b/bindings/rust/src/lib.rs index 8bc17478d..df54907f6 100644 --- a/bindings/rust/src/lib.rs +++ b/bindings/rust/src/lib.rs @@ -61,6 +61,10 @@ pub enum Error { SqlExecutionFailure(String), #[error("WAL operation error: `{0}`")] WalOperationError(String), + #[error("Query returned no rows")] + QueryReturnedNoRows, + #[error("Conversion failure: `{0}`")] + ConversionFailure(String), } impl From for Error { @@ -422,6 +426,17 @@ impl Statement { let mut stmt = self.inner.lock().unwrap(); stmt.reset(); } + + /// Execute a query that returns the first [`Row`]. + /// + /// # Errors + /// + /// - Returns `QueryReturnedNoRows` if no rows were returned. + pub async fn query_row(&mut self, params: impl IntoParams) -> Result { + let mut rows = self.query(params).await?; + + rows.next().await?.ok_or(Error::QueryReturnedNoRows) + } } /// Column information. diff --git a/bindings/rust/src/rows.rs b/bindings/rust/src/rows.rs index c85a7548d..9102baaf3 100644 --- a/bindings/rust/src/rows.rs +++ b/bindings/rust/src/rows.rs @@ -79,6 +79,14 @@ impl Row { } } + pub fn get(&self, idx: usize) -> Result + where + T: FromValue, + { + let val = &self.values[idx]; + T::from_sql(val.clone()).map_err(|err| Error::ConversionFailure(err.to_string())) + } + pub fn column_count(&self) -> usize { self.values.len() } diff --git a/bindings/rust/src/transaction.rs b/bindings/rust/src/transaction.rs index 78925d7c7..b68cc1fab 100644 --- a/bindings/rust/src/transaction.rs +++ b/bindings/rust/src/transaction.rs @@ -344,17 +344,13 @@ mod test { } { let tx = conn.transaction().await?; - let mut result = tx.query("SELECT SUM(x) FROM foo", ()).await?; - assert_eq!( - 2, - *result - .next() - .await? - .unwrap() - .get_value(0)? - .as_integer() - .unwrap() - ); + let result = tx + .prepare("SELECT SUM(x) FROM foo") + .await? + .query_row(()) + .await?; + + assert_eq!(2, result.get::(0)?); tx.finish().await?; } Ok(()) @@ -390,17 +386,12 @@ mod test { tx.commit().await?; } - let mut result = conn.query("SELECT SUM(x) FROM foo", ()).await?; - assert_eq!( - 2, - *result - .next() - .await? - .unwrap() - .get_value(0)? - .as_integer() - .unwrap() - ); + let result = conn + .prepare("SELECT SUM(x) FROM foo") + .await? + .query_row(()) + .await?; + assert_eq!(2, result.get::(0)?); Ok(()) } @@ -425,17 +416,12 @@ mod test { tx.commit().await?; } { - let mut result = conn.query("SELECT SUM(x) FROM foo", ()).await?; - assert_eq!( - 6, - *result - .next() - .await? - .unwrap() - .get_value(0)? - .as_integer() - .unwrap() - ); + let result = conn + .prepare("SELECT SUM(x) FROM foo") + .await? + .query_row(()) + .await?; + assert_eq!(6, result.get::(0)?); } Ok(()) }