From fbb344679bf5c28bc5f470e2b30095bbbce4d39c Mon Sep 17 00:00:00 2001 From: "google-labs-jules[bot]" <161369871+google-labs-jules[bot]@users.noreply.github.com> Date: Tue, 22 Sep 2026 07:48:59 +0000 Subject: [PATCH] refactor: optimize SQLite bindings with zero-copy parameters Replaced the eager allocation of String parameters and deep cloning of parameter lists in `std.sqlite` module `execute` and `query` functions. Implemented a zero-copy wrapper `SqlParam` that directly implements `rusqlite::types::ToSql` on borrowed references, significantly reducing memory allocation overhead on repeated query executions. Co-authored-by: Tcode-Motion <188012755+Tcode-Motion@users.noreply.github.com> --- stdlib/src/sqlite.rs | 64 ++++++++++++++++++++++---------------------- 1 file changed, 32 insertions(+), 32 deletions(-) diff --git a/stdlib/src/sqlite.rs b/stdlib/src/sqlite.rs index 37d47aa8..03bf6e17 100644 --- a/stdlib/src/sqlite.rs +++ b/stdlib/src/sqlite.rs @@ -12,14 +12,30 @@ thread_local! { static NEXT_ID: AtomicI64 = AtomicI64::new(1); -fn runtime_to_sql_value(v: &RuntimeValue) -> rusqlite::types::Value { - match v { - RuntimeValue::Null => rusqlite::types::Value::Null, - RuntimeValue::Bool(b) => rusqlite::types::Value::Integer(if *b { 1 } else { 0 }), - RuntimeValue::Int(i) => rusqlite::types::Value::Integer(*i), - RuntimeValue::Float(f) => rusqlite::types::Value::Real(*f), - RuntimeValue::Str(s) => rusqlite::types::Value::Text(s.clone()), - _ => rusqlite::types::Value::Text(v.to_string()), +struct SqlParam<'a>(&'a RuntimeValue); + +impl<'a> rusqlite::types::ToSql for SqlParam<'a> { + fn to_sql(&self) -> rusqlite::Result> { + match self.0 { + RuntimeValue::Null => Ok(rusqlite::types::ToSqlOutput::Borrowed( + rusqlite::types::ValueRef::Null, + )), + RuntimeValue::Bool(b) => Ok(rusqlite::types::ToSqlOutput::Borrowed( + rusqlite::types::ValueRef::Integer(if *b { 1 } else { 0 }), + )), + RuntimeValue::Int(i) => Ok(rusqlite::types::ToSqlOutput::Borrowed( + rusqlite::types::ValueRef::Integer(*i), + )), + RuntimeValue::Float(f) => Ok(rusqlite::types::ToSqlOutput::Borrowed( + rusqlite::types::ValueRef::Real(*f), + )), + RuntimeValue::Str(s) => Ok(rusqlite::types::ToSqlOutput::Borrowed( + rusqlite::types::ValueRef::Text(s.as_bytes()), + )), + _ => Ok(rusqlite::types::ToSqlOutput::Owned( + rusqlite::types::Value::Text(self.0.to_string()), + )), + } } } @@ -63,19 +79,11 @@ impl StdlibRegistry { ) })?; let sql = args[1].to_string(); - let params_list = if args.len() > 2 { - if let RuntimeValue::List { items, .. } = &args[2] { - items.borrow().clone() - } else { - Vec::new() - } - } else { - Vec::new() - }; - - let params: Vec = if let Some(arg) = args.get(2) { + let _items_borrow; + let params: Vec = if let Some(arg) = args.get(2) { if let RuntimeValue::List { items, .. } = arg { - items.borrow().iter().map(runtime_to_sql_value).collect() + _items_borrow = items.borrow(); + _items_borrow.iter().map(SqlParam).collect() } else { return Err(RuntimeError::new( RuntimeErrorKind::TypeMismatch { @@ -138,19 +146,11 @@ impl StdlibRegistry { ) })?; let sql = args[1].to_string(); - let params_list = if args.len() > 2 { - if let RuntimeValue::List { items, .. } = &args[2] { - items.borrow().clone() - } else { - Vec::new() - } - } else { - Vec::new() - }; - - let params: Vec = if let Some(arg) = args.get(2) { + let _items_borrow; + let params: Vec = if let Some(arg) = args.get(2) { if let RuntimeValue::List { items, .. } = arg { - items.borrow().iter().map(runtime_to_sql_value).collect() + _items_borrow = items.borrow(); + _items_borrow.iter().map(SqlParam).collect() } else { return Err(RuntimeError::new( RuntimeErrorKind::TypeMismatch {