bind/js: Add bind method

This commit is contained in:
Diego Reis
2025-05-26 16:04:54 -03:00
parent bce4ac45db
commit 799f4149c5
4 changed files with 79 additions and 10 deletions

View File

@@ -58,6 +58,25 @@ test("Test pragma", async (t) => {
t.deepEqual(typeof db.pragma("cache_size", { simple: true }), "number");
});
test("Test bind()", async (t) => {
const [db] = await connect(":memory:");
db.prepare("CREATE TABLE users (name TEXT, age INTEGER)").run();
db.prepare("INSERT INTO users (name, age) VALUES (?, ?)").run("Alice", 42);
let stmt = db.prepare("SELECT * FROM users WHERE name = ?").bind("Alice");
for (const row of stmt.iterate()) {
t.truthy(row.name);
t.true(typeof row.age === "number");
}
t.throws(
() => {
db.bind("Bob");
},
{ instanceOf: Error },
);
});
const connect = async (path) => {
const db = new Database(path);
return [db];

View File

@@ -1,5 +1,4 @@
import test from "ava";
import fs from "fs";
import { Database } from "../wrapper.js";
@@ -72,6 +71,25 @@ test("Test pragma", async (t) => {
t.true(typeof db.pragma("cache_size", { simple: true }) === "number");
});
test("Test bind()", async (t) => {
const [db] = await connect(":memory:");
db.prepare("CREATE TABLE users (name TEXT, age INTEGER)").run();
db.prepare("INSERT INTO users (name, age) VALUES (?, ?)").run("Alice", 42);
let stmt = db.prepare("SELECT * FROM users WHERE name = ?").bind("Alice");
for (const row of stmt.iterate()) {
t.truthy(row.name);
t.true(typeof row.age === "number");
}
t.throws(
() => {
db.bind("Bob");
},
{ instanceOf: Error },
);
});
const connect = async (path) => {
const db = new Database(path);
return [db];

View File

@@ -170,8 +170,8 @@ impl Database {
}
}
// TODO: Add the (parent) 'database' property
#[napi]
#[derive(Clone)]
pub struct Statement {
// TODO: implement each property when core supports it
// #[napi(able = false)]
@@ -183,8 +183,9 @@ pub struct Statement {
#[napi(writable = false)]
pub source: String,
toggle: bool,
database: Database,
pluck: bool,
binded: bool,
inner: Rc<RefCell<limbo_core::Statement>>,
}
@@ -195,7 +196,8 @@ impl Statement {
inner: Rc::new(inner),
database,
source,
toggle: false,
pluck: false,
binded: false,
}
}
@@ -321,29 +323,49 @@ impl Statement {
}
#[napi]
pub fn pluck(&mut self, toggle: Option<bool>) {
if let Some(false) = toggle {
self.toggle = false;
pub fn pluck(&mut self, pluck: Option<bool>) {
if let Some(false) = pluck {
self.pluck = false;
}
self.toggle = true;
self.pluck = true;
}
#[napi]
pub fn expand() {
todo!()
}
#[napi]
pub fn raw() {
todo!()
}
#[napi]
pub fn columns() {
todo!()
}
#[napi]
pub fn bind() {
todo!()
pub fn bind(&mut self, args: Option<Vec<JsUnknown>>) -> napi::Result<Self> {
let mut stmt = self.inner.borrow_mut();
stmt.reset();
if self.binded {
return Err(napi::Error::new(
napi::Status::InvalidArg,
"This statement already has bound parameters",
));
}
if let Some(args) = args {
for (i, elem) in args.into_iter().enumerate() {
let value = from_js_value(elem)?;
stmt.bind_at(NonZeroUsize::new(i + 1).unwrap(), value);
}
}
self.binded = true;
Ok(self.clone())
}
}

View File

@@ -224,6 +224,16 @@ class Statement {
columns() {
return this.stmt.columns();
}
/**
* Binds the given parameters to the statement _permanently_
*
* @param bindParameters - The bind parameters for binding the statement.
* @returns this - Statement with binded parameters
*/
bind(...bindParameters) {
return this.stmt.bind(bindParameters.flat());
}
}
module.exports.Database = Database;