From e21982d159822ce3eba94a4b2a50779edeeea4d2 Mon Sep 17 00:00:00 2001 From: Divy Srivastava Date: Sun, 15 Dec 2024 12:02:03 +0530 Subject: [PATCH] perf --- ext/node/ops/sqlite/statement.rs | 43 ++++++++++++++++++++------------ 1 file changed, 27 insertions(+), 16 deletions(-) diff --git a/ext/node/ops/sqlite/statement.rs b/ext/node/ops/sqlite/statement.rs index 0a0e65e7d7..295ba77265 100644 --- a/ext/node/ops/sqlite/statement.rs +++ b/ext/node/ops/sqlite/statement.rs @@ -52,10 +52,14 @@ impl<'a> ColumnIterator<'a> { count, } } + + fn column_count(&self) -> usize { + self.count as usize + } } impl<'a> Iterator for ColumnIterator<'a> { - type Item = (i32, Cow<'a, str>); + type Item = (i32, &'a [u8]); fn next(&mut self) -> Option { if self.index >= self.count { @@ -103,11 +107,11 @@ impl StatementSync { unsafe { ffi::sqlite3_column_count(self.inner) } } - fn column_name(&self, index: i32) -> Cow { + fn column_name(&self, index: i32) -> &[u8] { // SAFETY: `self.inner` is a valid pointer to a sqlite3_stmt. unsafe { let name = ffi::sqlite3_column_name(self.inner, index); - std::ffi::CStr::from_ptr(name as _).to_string_lossy() + std::ffi::CStr::from_ptr(name as _).to_bytes() } } @@ -133,10 +137,10 @@ impl StatementSync { } ffi::SQLITE_TEXT => { let value = ffi::sqlite3_column_text(self.inner, index); - let value = std::ffi::CStr::from_ptr(value as _).to_string_lossy(); + let value = std::ffi::CStr::from_ptr(value as _); v8::String::new_from_utf8( scope, - value.as_bytes(), + value.to_bytes(), v8::NewStringType::Normal, ) .unwrap() @@ -167,21 +171,28 @@ impl StatementSync { return Ok(None); } - let result = v8::Object::new(scope); let iter = ColumnIterator::new(self); + let num_cols = iter.column_count(); + + let mut names = Vec::with_capacity(num_cols); + let mut values = Vec::with_capacity(num_cols); + for (index, name) in iter { let value = self.column_value(index, scope); - let name = v8::String::new_from_utf8( - scope, - name.as_bytes(), - v8::NewStringType::Normal, - ) - .unwrap() - .into(); - result.set(scope, name, value); + let name = + v8::String::new_from_utf8(scope, name, v8::NewStringType::Normal) + .unwrap() + .into(); + + names.push(name); + values.push(value); } + let null = v8::null(scope).into(); + let result = + v8::Object::with_prototype_and_properties(scope, null, &names, &values); + Ok(Some(result)) } @@ -271,6 +282,8 @@ impl StatementSync { scope: &mut v8::HandleScope<'a>, #[varargs] params: Option<&v8::FunctionCallbackArguments>, ) -> Result, SqliteError> { + self.reset(); + self.bind_params(scope, params)?; let entry = self.read_row(scope)?; @@ -278,8 +291,6 @@ impl StatementSync { .map(|r| r.into()) .unwrap_or_else(|| v8::undefined(scope).into()); - self.reset(); - Ok(result) }