From c2832d70a16b045833439e16d159113bb5344ca9 Mon Sep 17 00:00:00 2001 From: Divy Srivastava Date: Tue, 4 Feb 2025 17:38:41 +0530 Subject: [PATCH] fix(ext/sqlite): add `sourceSQL` and `expandedSQL` getters (#27921) --- ext/node/ops/sqlite/mod.rs | 3 +++ ext/node/ops/sqlite/statement.rs | 34 ++++++++++++++++++++++++++++++++ tests/unit_node/sqlite_test.ts | 3 +++ 3 files changed, 40 insertions(+) diff --git a/ext/node/ops/sqlite/mod.rs b/ext/node/ops/sqlite/mod.rs index cc65eaff9b7841..c53f244cc70c2c 100644 --- a/ext/node/ops/sqlite/mod.rs +++ b/ext/node/ops/sqlite/mod.rs @@ -42,6 +42,9 @@ pub enum SqliteError { #[class(generic)] #[error("Invalid constructor")] InvalidConstructor, + #[class(generic)] + #[error("Expanded SQL text would exceed configured limits")] + InvalidExpandedSql, #[class(range)] #[error("The value of column {0} is too large to be represented as a JavaScript number: {1}")] NumberTooLarge(i32, i64), diff --git a/ext/node/ops/sqlite/statement.rs b/ext/node/ops/sqlite/statement.rs index 1fa8ade59903de..60f2610a0eb9c8 100644 --- a/ext/node/ops/sqlite/statement.rs +++ b/ext/node/ops/sqlite/statement.rs @@ -373,4 +373,38 @@ impl StatementSync { fn set_read_big_ints(&self, enabled: bool) { self.use_big_ints.set(enabled); } + + #[getter] + #[rename("sourceSQL")] + #[string] + fn source_sql(&self) -> String { + // SAFETY: `self.inner` is a valid pointer to a sqlite3_stmt + // as it lives as long as the StatementSync instance. + unsafe { + let raw = ffi::sqlite3_sql(self.inner); + std::ffi::CStr::from_ptr(raw as _) + .to_string_lossy() + .into_owned() + } + } + + #[getter] + #[rename("expandedSQL")] + #[string] + fn expanded_sql(&self) -> Result { + // SAFETY: `self.inner` is a valid pointer to a sqlite3_stmt + // as it lives as long as the StatementSync instance. + unsafe { + let raw = ffi::sqlite3_expanded_sql(self.inner); + if raw.is_null() { + return Err(SqliteError::InvalidExpandedSql); + } + let sql = std::ffi::CStr::from_ptr(raw as _) + .to_string_lossy() + .into_owned(); + ffi::sqlite3_free(raw as _); + + Ok(sql) + } + } } diff --git a/tests/unit_node/sqlite_test.ts b/tests/unit_node/sqlite_test.ts index ca485099430b3a..9377d6d34eb3ca 100644 --- a/tests/unit_node/sqlite_test.ts +++ b/tests/unit_node/sqlite_test.ts @@ -72,6 +72,9 @@ Deno.test("[node/sqlite] StatementSync read bigints are supported", () => { stmt.setReadBigInts(true); assertEquals(stmt.get(), { key: 1n, __proto__: null }); + + assertEquals(stmt.sourceSQL, "SELECT * FROM data"); + assertEquals(stmt.expandedSQL, "SELECT * FROM data"); }); Deno.test("[node/sqlite] StatementSync integer too large", () => {