mirror of
https://github.com/aljazceru/turso.git
synced 2026-01-05 09:14:24 +01:00
Merge 'bindings/javascript: Add Statement.iterate() method' from Diego Reis
I still didn't find a good way to implement variadic functions, we should have some sort of wrapper in JS layer but it didn't work so well for me so far. But once done it will be easily transferable to any function. It also should probably be async, but AFAIC napi doesn't have a straight way to implement async iterators. Closes #1515
This commit is contained in:
4
Cargo.lock
generated
4
Cargo.lock
generated
@@ -2205,9 +2205,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "napi-build"
|
||||
version = "2.1.6"
|
||||
version = "2.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e28acfa557c083f6e254a786e01ba253fc56f18ee000afcd4f79af735f73a6da"
|
||||
checksum = "03acbfa4f156a32188bfa09b86dc11a431b5725253fc1fc6f6df5bed273382c4"
|
||||
|
||||
[[package]]
|
||||
name = "napi-derive"
|
||||
|
||||
@@ -16,4 +16,4 @@ napi = { version = "2.16.17", default-features = false, features = ["napi4"] }
|
||||
napi-derive = { version = "2.16.13", default-features = false }
|
||||
|
||||
[build-dependencies]
|
||||
napi-build = "2.0.1"
|
||||
napi-build = "2.2.0"
|
||||
|
||||
@@ -7,7 +7,6 @@ test("Open in-memory database", async (t) => {
|
||||
t.is(db.memory, true);
|
||||
});
|
||||
|
||||
|
||||
test("Statement.get() returns data", async (t) => {
|
||||
const [db] = await connect(":memory:");
|
||||
const stmt = db.prepare("SELECT 1");
|
||||
@@ -31,11 +30,26 @@ test("Statement.run() returns correct result object", async (t) => {
|
||||
t.deepEqual(rows, { changes: 1, lastInsertRowid: 1 });
|
||||
});
|
||||
|
||||
test("Statment.iterate() should correctly return an iterable object", 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);
|
||||
db.prepare("INSERT INTO users (name, age) VALUES (?, ?)").run("Bob", 24);
|
||||
let rows = db.prepare("SELECT * FROM users").iterate();
|
||||
for (const row of rows) {
|
||||
t.truthy(row.name);
|
||||
t.true(typeof row.age === "number");
|
||||
}
|
||||
});
|
||||
|
||||
test("Empty prepared statement should throw", async (t) => {
|
||||
const [db] = await connect(":memory:");
|
||||
t.throws(() => {
|
||||
db.prepare("");
|
||||
}, { instanceOf: Error });
|
||||
const [db] = await connect(":memory:");
|
||||
t.throws(
|
||||
() => {
|
||||
db.prepare("");
|
||||
},
|
||||
{ instanceOf: Error },
|
||||
);
|
||||
});
|
||||
|
||||
const connect = async (path) => {
|
||||
|
||||
@@ -27,10 +27,22 @@ test("Statement.get() returns null when no data", async (t) => {
|
||||
// it should return a result object, not a row object
|
||||
test("Statement.run() returns correct result object", async (t) => {
|
||||
const [db] = await connect(":memory:");
|
||||
db.prepare("CREATE TABLE users (name TEXT)").run();
|
||||
db.prepare("INSERT INTO users (name) VALUES (?)").run(["Alice"]);
|
||||
db.prepare("CREATE TABLE users (name TEXT, age INTEGER)").run();
|
||||
db.prepare("INSERT INTO users (name, age) VALUES (?, ?)").run(["Alice", 42]);
|
||||
let rows = db.prepare("SELECT * FROM users").all();
|
||||
t.deepEqual(rows, [{ name: "Alice" }]);
|
||||
t.deepEqual(rows, [{ name: "Alice", age: 42 }]);
|
||||
});
|
||||
|
||||
test("Statment.iterate() should correctly return an iterable object", 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]);
|
||||
db.prepare("INSERT INTO users (name, age) VALUES (?, ?)").run(["Bob", 24]);
|
||||
let rows = db.prepare("SELECT * FROM users").iterate();
|
||||
for (const row of rows) {
|
||||
t.truthy(row.name);
|
||||
t.true(typeof row.age === "number");
|
||||
}
|
||||
});
|
||||
|
||||
test("Empty prepared statement should throw", async (t) => {
|
||||
|
||||
@@ -5,312 +5,325 @@
|
||||
/* auto-generated by NAPI-RS */
|
||||
|
||||
const { existsSync, readFileSync } = require('fs')
|
||||
const { join } = require('path')
|
||||
const { join } = require("path");
|
||||
|
||||
const { platform, arch } = process
|
||||
const { platform, arch } = process;
|
||||
|
||||
let nativeBinding = null
|
||||
let localFileExisted = false
|
||||
let loadError = null
|
||||
let nativeBinding = null;
|
||||
let localFileExisted = false;
|
||||
let loadError = null;
|
||||
|
||||
function isMusl() {
|
||||
// For Node 10
|
||||
if (!process.report || typeof process.report.getReport !== 'function') {
|
||||
if (!process.report || typeof process.report.getReport !== "function") {
|
||||
try {
|
||||
const lddPath = require('child_process').execSync('which ldd').toString().trim()
|
||||
return readFileSync(lddPath, 'utf8').includes('musl')
|
||||
const lddPath = require("child_process")
|
||||
.execSync("which ldd")
|
||||
.toString()
|
||||
.trim();
|
||||
return readFileSync(lddPath, "utf8").includes("musl");
|
||||
} catch (e) {
|
||||
return true
|
||||
return true;
|
||||
}
|
||||
} else {
|
||||
const { glibcVersionRuntime } = process.report.getReport().header
|
||||
return !glibcVersionRuntime
|
||||
const { glibcVersionRuntime } = process.report.getReport().header;
|
||||
return !glibcVersionRuntime;
|
||||
}
|
||||
}
|
||||
|
||||
switch (platform) {
|
||||
case 'android':
|
||||
case "android":
|
||||
switch (arch) {
|
||||
case 'arm64':
|
||||
localFileExisted = existsSync(join(__dirname, 'turso-limbo.android-arm64.node'))
|
||||
case "arm64":
|
||||
localFileExisted = existsSync(
|
||||
join(__dirname, "turso-limbo.android-arm64.node"),
|
||||
);
|
||||
try {
|
||||
if (localFileExisted) {
|
||||
nativeBinding = require('./turso-limbo.android-arm64.node')
|
||||
nativeBinding = require("./turso-limbo.android-arm64.node");
|
||||
} else {
|
||||
nativeBinding = require('@tursodatabase/limbo-android-arm64')
|
||||
nativeBinding = require("@tursodatabase/limbo-android-arm64");
|
||||
}
|
||||
} catch (e) {
|
||||
loadError = e
|
||||
loadError = e;
|
||||
}
|
||||
break
|
||||
case 'arm':
|
||||
localFileExisted = existsSync(join(__dirname, 'turso-limbo.android-arm-eabi.node'))
|
||||
break;
|
||||
case "arm":
|
||||
localFileExisted = existsSync(
|
||||
join(__dirname, "turso-limbo.android-arm-eabi.node"),
|
||||
);
|
||||
try {
|
||||
if (localFileExisted) {
|
||||
nativeBinding = require('./turso-limbo.android-arm-eabi.node')
|
||||
nativeBinding = require("./turso-limbo.android-arm-eabi.node");
|
||||
} else {
|
||||
nativeBinding = require('@tursodatabase/limbo-android-arm-eabi')
|
||||
nativeBinding = require("@tursodatabase/limbo-android-arm-eabi");
|
||||
}
|
||||
} catch (e) {
|
||||
loadError = e
|
||||
loadError = e;
|
||||
}
|
||||
break
|
||||
break;
|
||||
default:
|
||||
throw new Error(`Unsupported architecture on Android ${arch}`)
|
||||
throw new Error(`Unsupported architecture on Android ${arch}`);
|
||||
}
|
||||
break
|
||||
case 'win32':
|
||||
break;
|
||||
case "win32":
|
||||
switch (arch) {
|
||||
case 'x64':
|
||||
case "x64":
|
||||
localFileExisted = existsSync(
|
||||
join(__dirname, 'turso-limbo.win32-x64-msvc.node')
|
||||
)
|
||||
join(__dirname, "turso-limbo.win32-x64-msvc.node"),
|
||||
);
|
||||
try {
|
||||
if (localFileExisted) {
|
||||
nativeBinding = require('./turso-limbo.win32-x64-msvc.node')
|
||||
nativeBinding = require("./turso-limbo.win32-x64-msvc.node");
|
||||
} else {
|
||||
nativeBinding = require('@tursodatabase/limbo-win32-x64-msvc')
|
||||
nativeBinding = require("@tursodatabase/limbo-win32-x64-msvc");
|
||||
}
|
||||
} catch (e) {
|
||||
loadError = e
|
||||
loadError = e;
|
||||
}
|
||||
break
|
||||
case 'ia32':
|
||||
break;
|
||||
case "ia32":
|
||||
localFileExisted = existsSync(
|
||||
join(__dirname, 'turso-limbo.win32-ia32-msvc.node')
|
||||
)
|
||||
join(__dirname, "turso-limbo.win32-ia32-msvc.node"),
|
||||
);
|
||||
try {
|
||||
if (localFileExisted) {
|
||||
nativeBinding = require('./turso-limbo.win32-ia32-msvc.node')
|
||||
nativeBinding = require("./turso-limbo.win32-ia32-msvc.node");
|
||||
} else {
|
||||
nativeBinding = require('@tursodatabase/limbo-win32-ia32-msvc')
|
||||
nativeBinding = require("@tursodatabase/limbo-win32-ia32-msvc");
|
||||
}
|
||||
} catch (e) {
|
||||
loadError = e
|
||||
loadError = e;
|
||||
}
|
||||
break
|
||||
case 'arm64':
|
||||
break;
|
||||
case "arm64":
|
||||
localFileExisted = existsSync(
|
||||
join(__dirname, 'turso-limbo.win32-arm64-msvc.node')
|
||||
)
|
||||
join(__dirname, "turso-limbo.win32-arm64-msvc.node"),
|
||||
);
|
||||
try {
|
||||
if (localFileExisted) {
|
||||
nativeBinding = require('./turso-limbo.win32-arm64-msvc.node')
|
||||
nativeBinding = require("./turso-limbo.win32-arm64-msvc.node");
|
||||
} else {
|
||||
nativeBinding = require('@tursodatabase/limbo-win32-arm64-msvc')
|
||||
nativeBinding = require("@tursodatabase/limbo-win32-arm64-msvc");
|
||||
}
|
||||
} catch (e) {
|
||||
loadError = e
|
||||
loadError = e;
|
||||
}
|
||||
break
|
||||
break;
|
||||
default:
|
||||
throw new Error(`Unsupported architecture on Windows: ${arch}`)
|
||||
throw new Error(`Unsupported architecture on Windows: ${arch}`);
|
||||
}
|
||||
break
|
||||
case 'darwin':
|
||||
localFileExisted = existsSync(join(__dirname, 'turso-limbo.darwin-universal.node'))
|
||||
break;
|
||||
case "darwin":
|
||||
localFileExisted = existsSync(
|
||||
join(__dirname, "turso-limbo.darwin-universal.node"),
|
||||
);
|
||||
try {
|
||||
if (localFileExisted) {
|
||||
nativeBinding = require('./turso-limbo.darwin-universal.node')
|
||||
nativeBinding = require("./turso-limbo.darwin-universal.node");
|
||||
} else {
|
||||
nativeBinding = require('@tursodatabase/limbo-darwin-universal')
|
||||
nativeBinding = require("@tursodatabase/limbo-darwin-universal");
|
||||
}
|
||||
break
|
||||
break;
|
||||
} catch {}
|
||||
switch (arch) {
|
||||
case 'x64':
|
||||
localFileExisted = existsSync(join(__dirname, 'turso-limbo.darwin-x64.node'))
|
||||
try {
|
||||
if (localFileExisted) {
|
||||
nativeBinding = require('./turso-limbo.darwin-x64.node')
|
||||
} else {
|
||||
nativeBinding = require('@tursodatabase/limbo-darwin-x64')
|
||||
}
|
||||
} catch (e) {
|
||||
loadError = e
|
||||
}
|
||||
break
|
||||
case 'arm64':
|
||||
case "x64":
|
||||
localFileExisted = existsSync(
|
||||
join(__dirname, 'turso-limbo.darwin-arm64.node')
|
||||
)
|
||||
join(__dirname, "turso-limbo.darwin-x64.node"),
|
||||
);
|
||||
try {
|
||||
if (localFileExisted) {
|
||||
nativeBinding = require('./turso-limbo.darwin-arm64.node')
|
||||
nativeBinding = require("./turso-limbo.darwin-x64.node");
|
||||
} else {
|
||||
nativeBinding = require('@tursodatabase/limbo-darwin-arm64')
|
||||
nativeBinding = require("@tursodatabase/limbo-darwin-x64");
|
||||
}
|
||||
} catch (e) {
|
||||
loadError = e
|
||||
loadError = e;
|
||||
}
|
||||
break
|
||||
break;
|
||||
case "arm64":
|
||||
localFileExisted = existsSync(
|
||||
join(__dirname, "turso-limbo.darwin-arm64.node"),
|
||||
);
|
||||
try {
|
||||
if (localFileExisted) {
|
||||
nativeBinding = require("./turso-limbo.darwin-arm64.node");
|
||||
} else {
|
||||
nativeBinding = require("@tursodatabase/limbo-darwin-arm64");
|
||||
}
|
||||
} catch (e) {
|
||||
loadError = e;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
throw new Error(`Unsupported architecture on macOS: ${arch}`)
|
||||
throw new Error(`Unsupported architecture on macOS: ${arch}`);
|
||||
}
|
||||
break
|
||||
case 'freebsd':
|
||||
if (arch !== 'x64') {
|
||||
throw new Error(`Unsupported architecture on FreeBSD: ${arch}`)
|
||||
break;
|
||||
case "freebsd":
|
||||
if (arch !== "x64") {
|
||||
throw new Error(`Unsupported architecture on FreeBSD: ${arch}`);
|
||||
}
|
||||
localFileExisted = existsSync(join(__dirname, 'turso-limbo.freebsd-x64.node'))
|
||||
localFileExisted = existsSync(
|
||||
join(__dirname, "turso-limbo.freebsd-x64.node"),
|
||||
);
|
||||
try {
|
||||
if (localFileExisted) {
|
||||
nativeBinding = require('./turso-limbo.freebsd-x64.node')
|
||||
nativeBinding = require("./turso-limbo.freebsd-x64.node");
|
||||
} else {
|
||||
nativeBinding = require('@tursodatabase/limbo-freebsd-x64')
|
||||
nativeBinding = require("@tursodatabase/limbo-freebsd-x64");
|
||||
}
|
||||
} catch (e) {
|
||||
loadError = e
|
||||
loadError = e;
|
||||
}
|
||||
break
|
||||
case 'linux':
|
||||
break;
|
||||
case "linux":
|
||||
switch (arch) {
|
||||
case 'x64':
|
||||
case "x64":
|
||||
if (isMusl()) {
|
||||
localFileExisted = existsSync(
|
||||
join(__dirname, 'turso-limbo.linux-x64-musl.node')
|
||||
)
|
||||
join(__dirname, "turso-limbo.linux-x64-musl.node"),
|
||||
);
|
||||
try {
|
||||
if (localFileExisted) {
|
||||
nativeBinding = require('./turso-limbo.linux-x64-musl.node')
|
||||
nativeBinding = require("./turso-limbo.linux-x64-musl.node");
|
||||
} else {
|
||||
nativeBinding = require('@tursodatabase/limbo-linux-x64-musl')
|
||||
nativeBinding = require("@tursodatabase/limbo-linux-x64-musl");
|
||||
}
|
||||
} catch (e) {
|
||||
loadError = e
|
||||
loadError = e;
|
||||
}
|
||||
} else {
|
||||
localFileExisted = existsSync(
|
||||
join(__dirname, 'turso-limbo.linux-x64-gnu.node')
|
||||
)
|
||||
join(__dirname, "turso-limbo.linux-x64-gnu.node"),
|
||||
);
|
||||
try {
|
||||
if (localFileExisted) {
|
||||
nativeBinding = require('./turso-limbo.linux-x64-gnu.node')
|
||||
nativeBinding = require("./turso-limbo.linux-x64-gnu.node");
|
||||
} else {
|
||||
nativeBinding = require('@tursodatabase/limbo-linux-x64-gnu')
|
||||
nativeBinding = require("@tursodatabase/limbo-linux-x64-gnu");
|
||||
}
|
||||
} catch (e) {
|
||||
loadError = e
|
||||
loadError = e;
|
||||
}
|
||||
}
|
||||
break
|
||||
case 'arm64':
|
||||
break;
|
||||
case "arm64":
|
||||
if (isMusl()) {
|
||||
localFileExisted = existsSync(
|
||||
join(__dirname, 'turso-limbo.linux-arm64-musl.node')
|
||||
)
|
||||
join(__dirname, "turso-limbo.linux-arm64-musl.node"),
|
||||
);
|
||||
try {
|
||||
if (localFileExisted) {
|
||||
nativeBinding = require('./turso-limbo.linux-arm64-musl.node')
|
||||
nativeBinding = require("./turso-limbo.linux-arm64-musl.node");
|
||||
} else {
|
||||
nativeBinding = require('@tursodatabase/limbo-linux-arm64-musl')
|
||||
nativeBinding = require("@tursodatabase/limbo-linux-arm64-musl");
|
||||
}
|
||||
} catch (e) {
|
||||
loadError = e
|
||||
loadError = e;
|
||||
}
|
||||
} else {
|
||||
localFileExisted = existsSync(
|
||||
join(__dirname, 'turso-limbo.linux-arm64-gnu.node')
|
||||
)
|
||||
join(__dirname, "turso-limbo.linux-arm64-gnu.node"),
|
||||
);
|
||||
try {
|
||||
if (localFileExisted) {
|
||||
nativeBinding = require('./turso-limbo.linux-arm64-gnu.node')
|
||||
nativeBinding = require("./turso-limbo.linux-arm64-gnu.node");
|
||||
} else {
|
||||
nativeBinding = require('@tursodatabase/limbo-linux-arm64-gnu')
|
||||
nativeBinding = require("@tursodatabase/limbo-linux-arm64-gnu");
|
||||
}
|
||||
} catch (e) {
|
||||
loadError = e
|
||||
loadError = e;
|
||||
}
|
||||
}
|
||||
break
|
||||
case 'arm':
|
||||
break;
|
||||
case "arm":
|
||||
if (isMusl()) {
|
||||
localFileExisted = existsSync(
|
||||
join(__dirname, 'turso-limbo.linux-arm-musleabihf.node')
|
||||
)
|
||||
join(__dirname, "turso-limbo.linux-arm-musleabihf.node"),
|
||||
);
|
||||
try {
|
||||
if (localFileExisted) {
|
||||
nativeBinding = require('./turso-limbo.linux-arm-musleabihf.node')
|
||||
nativeBinding = require("./turso-limbo.linux-arm-musleabihf.node");
|
||||
} else {
|
||||
nativeBinding = require('@tursodatabase/limbo-linux-arm-musleabihf')
|
||||
nativeBinding = require("@tursodatabase/limbo-linux-arm-musleabihf");
|
||||
}
|
||||
} catch (e) {
|
||||
loadError = e
|
||||
loadError = e;
|
||||
}
|
||||
} else {
|
||||
localFileExisted = existsSync(
|
||||
join(__dirname, 'turso-limbo.linux-arm-gnueabihf.node')
|
||||
)
|
||||
join(__dirname, "turso-limbo.linux-arm-gnueabihf.node"),
|
||||
);
|
||||
try {
|
||||
if (localFileExisted) {
|
||||
nativeBinding = require('./turso-limbo.linux-arm-gnueabihf.node')
|
||||
nativeBinding = require("./turso-limbo.linux-arm-gnueabihf.node");
|
||||
} else {
|
||||
nativeBinding = require('@tursodatabase/limbo-linux-arm-gnueabihf')
|
||||
nativeBinding = require("@tursodatabase/limbo-linux-arm-gnueabihf");
|
||||
}
|
||||
} catch (e) {
|
||||
loadError = e
|
||||
loadError = e;
|
||||
}
|
||||
}
|
||||
break
|
||||
case 'riscv64':
|
||||
break;
|
||||
case "riscv64":
|
||||
if (isMusl()) {
|
||||
localFileExisted = existsSync(
|
||||
join(__dirname, 'turso-limbo.linux-riscv64-musl.node')
|
||||
)
|
||||
join(__dirname, "turso-limbo.linux-riscv64-musl.node"),
|
||||
);
|
||||
try {
|
||||
if (localFileExisted) {
|
||||
nativeBinding = require('./turso-limbo.linux-riscv64-musl.node')
|
||||
nativeBinding = require("./turso-limbo.linux-riscv64-musl.node");
|
||||
} else {
|
||||
nativeBinding = require('@tursodatabase/limbo-linux-riscv64-musl')
|
||||
nativeBinding = require("@tursodatabase/limbo-linux-riscv64-musl");
|
||||
}
|
||||
} catch (e) {
|
||||
loadError = e
|
||||
loadError = e;
|
||||
}
|
||||
} else {
|
||||
localFileExisted = existsSync(
|
||||
join(__dirname, 'turso-limbo.linux-riscv64-gnu.node')
|
||||
)
|
||||
join(__dirname, "turso-limbo.linux-riscv64-gnu.node"),
|
||||
);
|
||||
try {
|
||||
if (localFileExisted) {
|
||||
nativeBinding = require('./turso-limbo.linux-riscv64-gnu.node')
|
||||
nativeBinding = require("./turso-limbo.linux-riscv64-gnu.node");
|
||||
} else {
|
||||
nativeBinding = require('@tursodatabase/limbo-linux-riscv64-gnu')
|
||||
nativeBinding = require("@tursodatabase/limbo-linux-riscv64-gnu");
|
||||
}
|
||||
} catch (e) {
|
||||
loadError = e
|
||||
loadError = e;
|
||||
}
|
||||
}
|
||||
break
|
||||
case 's390x':
|
||||
break;
|
||||
case "s390x":
|
||||
localFileExisted = existsSync(
|
||||
join(__dirname, 'turso-limbo.linux-s390x-gnu.node')
|
||||
)
|
||||
join(__dirname, "turso-limbo.linux-s390x-gnu.node"),
|
||||
);
|
||||
try {
|
||||
if (localFileExisted) {
|
||||
nativeBinding = require('./turso-limbo.linux-s390x-gnu.node')
|
||||
nativeBinding = require("./turso-limbo.linux-s390x-gnu.node");
|
||||
} else {
|
||||
nativeBinding = require('@tursodatabase/limbo-linux-s390x-gnu')
|
||||
nativeBinding = require("@tursodatabase/limbo-linux-s390x-gnu");
|
||||
}
|
||||
} catch (e) {
|
||||
loadError = e
|
||||
loadError = e;
|
||||
}
|
||||
break
|
||||
break;
|
||||
default:
|
||||
throw new Error(`Unsupported architecture on Linux: ${arch}`)
|
||||
throw new Error(`Unsupported architecture on Linux: ${arch}`);
|
||||
}
|
||||
break
|
||||
break;
|
||||
default:
|
||||
throw new Error(`Unsupported OS: ${platform}, architecture: ${arch}`)
|
||||
throw new Error(`Unsupported OS: ${platform}, architecture: ${arch}`);
|
||||
}
|
||||
|
||||
if (!nativeBinding) {
|
||||
if (loadError) {
|
||||
throw loadError
|
||||
throw loadError;
|
||||
}
|
||||
throw new Error(`Failed to load native binding`)
|
||||
throw new Error(`Failed to load native binding`);
|
||||
}
|
||||
|
||||
const { Database, Statement } = nativeBinding
|
||||
const { Database, Statement } = nativeBinding;
|
||||
|
||||
module.exports.Database = Database
|
||||
module.exports.Statement = Statement
|
||||
module.exports.Database = Database;
|
||||
module.exports.Statement = Statement;
|
||||
|
||||
@@ -8,6 +8,8 @@ use std::sync::Arc;
|
||||
|
||||
use limbo_core::types::Text;
|
||||
use limbo_core::{maybe_init_database_file, LimboError};
|
||||
use napi::iterator::Generator;
|
||||
use napi::JsObject;
|
||||
use napi::{bindgen_prelude::ObjectFinalize, Env, JsUnknown};
|
||||
use napi_derive::napi;
|
||||
|
||||
@@ -136,20 +138,23 @@ impl Database {
|
||||
#[napi]
|
||||
pub struct Statement {
|
||||
// TODO: implement each property when core supports it
|
||||
// #[napi(writable = false)]
|
||||
// #[napi(able = false)]
|
||||
// pub reader: bool,
|
||||
// #[napi(writable = false)]
|
||||
// pub readonly: bool,
|
||||
// #[napi(writable = false)]
|
||||
// pub busy: bool,
|
||||
database: Database,
|
||||
inner: RefCell<limbo_core::Statement>,
|
||||
inner: Rc<RefCell<limbo_core::Statement>>,
|
||||
}
|
||||
|
||||
#[napi]
|
||||
impl Statement {
|
||||
pub fn new(inner: RefCell<limbo_core::Statement>, database: Database) -> Self {
|
||||
Self { inner, database }
|
||||
Self {
|
||||
inner: Rc::new(inner),
|
||||
database,
|
||||
}
|
||||
}
|
||||
|
||||
#[napi]
|
||||
@@ -194,8 +199,12 @@ impl Statement {
|
||||
}
|
||||
|
||||
#[napi]
|
||||
pub fn iterate() {
|
||||
todo!()
|
||||
pub fn iterate(&self, env: Env) -> IteratorStatement {
|
||||
IteratorStatement {
|
||||
stmt: Rc::clone(&self.inner),
|
||||
database: self.database.clone(),
|
||||
env,
|
||||
}
|
||||
}
|
||||
|
||||
#[napi]
|
||||
@@ -266,6 +275,46 @@ impl Statement {
|
||||
}
|
||||
}
|
||||
|
||||
#[napi(iterator)]
|
||||
pub struct IteratorStatement {
|
||||
stmt: Rc<RefCell<limbo_core::Statement>>,
|
||||
database: Database,
|
||||
env: Env,
|
||||
}
|
||||
|
||||
impl Generator for IteratorStatement {
|
||||
type Yield = JsObject;
|
||||
|
||||
type Next = ();
|
||||
|
||||
type Return = ();
|
||||
|
||||
fn next(&mut self, _: Option<Self::Next>) -> Option<Self::Yield> {
|
||||
let mut stmt = self.stmt.borrow_mut();
|
||||
|
||||
match stmt.step().ok()? {
|
||||
limbo_core::StepResult::Row => {
|
||||
let row = stmt.row().unwrap();
|
||||
let mut js_row = self.env.create_object().ok()?;
|
||||
|
||||
for (idx, value) in row.get_values().enumerate() {
|
||||
let key = stmt.get_column_name(idx);
|
||||
let js_value = to_js_value(&self.env, value);
|
||||
js_row.set_named_property(&key, js_value).ok()?;
|
||||
}
|
||||
|
||||
Some(js_row)
|
||||
}
|
||||
limbo_core::StepResult::Done => None,
|
||||
limbo_core::StepResult::IO => {
|
||||
self.database.io.run_once().ok()?;
|
||||
None // clearly it's incorrect it should return to user
|
||||
}
|
||||
limbo_core::StepResult::Interrupt | limbo_core::StepResult::Busy => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn to_js_value(env: &napi::Env, value: &limbo_core::Value) -> napi::Result<JsUnknown> {
|
||||
match value {
|
||||
limbo_core::Value::Null => Ok(env.get_null()?.into_unknown()),
|
||||
|
||||
Reference in New Issue
Block a user