From 60b78b3566d10dd7055fa7ff0e0da970307c34c6 Mon Sep 17 00:00:00 2001 From: Diego Reis Date: Sun, 25 May 2025 15:56:28 -0300 Subject: [PATCH] bind/js: Partially implements pragma Some pragmas may return more than one value, which would break the current logic. So this cause should be handled in the future --- .../__test__/better-sqlite3.spec.mjs | 6 ++ bindings/javascript/__test__/limbo.spec.mjs | 6 ++ bindings/javascript/src/lib.rs | 57 ++++++++++++++++--- bindings/javascript/wrapper.js | 10 +++- 4 files changed, 70 insertions(+), 9 deletions(-) diff --git a/bindings/javascript/__test__/better-sqlite3.spec.mjs b/bindings/javascript/__test__/better-sqlite3.spec.mjs index aefe0aa92..94f3570dd 100644 --- a/bindings/javascript/__test__/better-sqlite3.spec.mjs +++ b/bindings/javascript/__test__/better-sqlite3.spec.mjs @@ -52,6 +52,12 @@ test("Empty prepared statement should throw", async (t) => { ); }); +test("Test pragma", async (t) => { + const [db] = await connect(":memory:"); + t.deepEqual(typeof db.pragma("cache_size")[0].cache_size, "number"); + t.deepEqual(typeof db.pragma("cache_size", { simple: true }), "number"); +}); + const connect = async (path) => { const db = new Database(path); return [db]; diff --git a/bindings/javascript/__test__/limbo.spec.mjs b/bindings/javascript/__test__/limbo.spec.mjs index c4c4c6a78..73e5412ba 100644 --- a/bindings/javascript/__test__/limbo.spec.mjs +++ b/bindings/javascript/__test__/limbo.spec.mjs @@ -65,6 +65,12 @@ test("Empty prepared statement should throw", async (t) => { ); }); +test("Test pragma", async (t) => { + const [db] = await connect(":memory:"); + t.deepEqual(typeof db.pragma("cache_size")[0].cache_size, "number"); + t.deepEqual(typeof db.pragma("cache_size", { simple: true }), "number"); +}); + const connect = async (path) => { const db = new Database(path); return [db]; diff --git a/bindings/javascript/src/lib.rs b/bindings/javascript/src/lib.rs index 6cb3eab2f..a06d6500d 100644 --- a/bindings/javascript/src/lib.rs +++ b/bindings/javascript/src/lib.rs @@ -83,11 +83,6 @@ impl Database { Ok(Statement::new(RefCell::new(stmt), self.clone(), sql)) } - #[napi] - pub fn pragma(&self) { - todo!() - } - #[napi] pub fn backup(&self) { todo!() @@ -128,6 +123,46 @@ impl Database { self.conn.close().map_err(into_napi_error)?; Ok(()) } + + // We assume that every pragma only returns one result, which isn't + // true. + #[napi] + pub fn pragma(&self, env: Env, pragma: String, simple: bool) -> napi::Result { + let stmt = self.prepare(pragma.clone())?; + let mut stmt = stmt.inner.borrow_mut(); + let pragma_name = pragma + .split("PRAGMA") + .filter(|s| !s.trim().is_empty()) + .next() + .map(str::trim) + .unwrap(); + let mut results = env.create_empty_array()?; + + let step = stmt.step().map_err(into_napi_error)?; + match step { + limbo_core::StepResult::Row => { + let row = stmt.row().unwrap(); + let mut obj = env.create_object()?; + for (_, value) in row.get_values().enumerate() { + let js_value = to_js_value(&env, value)?; + + if simple { + return Ok(js_value); + } + + obj.set_named_property(&pragma_name, js_value)?; + } + + results.set_element(0, obj)?; + Ok(results.into_unknown()) + } + limbo_core::StepResult::Done => Ok(env.get_undefined()?.into_unknown()), + limbo_core::StepResult::IO => todo!(), + limbo_core::StepResult::Interrupt | limbo_core::StepResult::Busy => Err( + napi::Error::new(napi::Status::GenericFailure, format!("{:?}", step)), + ), + } + } } // TODO: Add the (parent) 'database' property @@ -142,6 +177,8 @@ pub struct Statement { // pub busy: bool, #[napi(writable = false)] pub source: String, + + toggle: bool, database: Database, inner: Rc>, } @@ -153,6 +190,7 @@ impl Statement { inner: Rc::new(inner), database, source, + toggle: false, } } @@ -278,9 +316,14 @@ impl Statement { } #[napi] - pub fn pluck() { - todo!() + pub fn pluck(&mut self, toggle: Option) { + if let Some(false) = toggle { + self.toggle = false; + } + + self.toggle = true; } + #[napi] pub fn expand() { todo!() diff --git a/bindings/javascript/wrapper.js b/bindings/javascript/wrapper.js index f9584835f..22492bd63 100644 --- a/bindings/javascript/wrapper.js +++ b/bindings/javascript/wrapper.js @@ -77,13 +77,19 @@ class Database { pragma(source, options) { if (options == null) options = {}; + if (typeof source !== "string") throw new TypeError("Expected first argument to be a string"); + if (typeof options !== "object") throw new TypeError("Expected second argument to be an options object"); + const simple = options["simple"]; - const stmt = this.prepare(`PRAGMA ${source}`, this, true); - return simple ? stmt.pluck().get() : stmt.all(); + const pragma = `PRAGMA ${source}`; + + return simple + ? this.db.pragma(pragma, true) + : this.db.pragma(pragma, false); } backup(filename, options) {