mirror of
https://github.com/openclaw/openclaw.git
synced 2026-10-26 10:13:27 +08:00
Read the SQLite version with the NUL round-trip row, preserving synchronous boot admission and failure diagnostics. Reduce each successful capability probe from four statements to three.
71 lines
2.6 KiB
JavaScript
71 lines
2.6 KiB
JavaScript
/**
|
|
* @typedef {import("./node-sqlite-capabilities.d.mts").SqliteCapabilities} SqliteCapabilities
|
|
* @typedef {import("./node-sqlite-capabilities.d.mts").SqliteCapabilityDatabase} SqliteCapabilityDatabase
|
|
* @typedef {import("./node-sqlite-capabilities.d.mts").SqliteCapabilityDatabaseConstructor} SqliteCapabilityDatabaseConstructor
|
|
*/
|
|
|
|
/**
|
|
* @param {SqliteCapabilityDatabaseConstructor} DatabaseSync
|
|
* @returns {SqliteCapabilities}
|
|
*/
|
|
export function probeSqlite(DatabaseSync) {
|
|
/** @type {SqliteCapabilities} */
|
|
const result = { available: false, version: null, text: false, blob: false, json: false };
|
|
/** @type {SqliteCapabilityDatabase | undefined} */
|
|
let database;
|
|
try {
|
|
database = new DatabaseSync(":memory:");
|
|
result.available = true;
|
|
const text = "a\u0000b\u0000";
|
|
const bytes = Buffer.from(text, "utf8");
|
|
const json = JSON.stringify({ value: text });
|
|
database.exec("CREATE TABLE probe (text_value TEXT, blob_value BLOB, json_value TEXT)");
|
|
database.prepare("INSERT INTO probe VALUES (?, ?, ?)").run(text, bytes, json);
|
|
const row = database
|
|
.prepare("SELECT sqlite_version() AS version, text_value, blob_value, json_value FROM probe")
|
|
.get();
|
|
result.version = typeof row?.version === "string" ? row.version : null;
|
|
result.text =
|
|
typeof row?.text_value === "string" &&
|
|
row.text_value.length === text.length &&
|
|
Buffer.from(row.text_value, "utf8").equals(bytes);
|
|
result.blob =
|
|
row?.blob_value instanceof Uint8Array && Buffer.from(row.blob_value).equals(bytes);
|
|
result.json = row?.json_value === json && JSON.parse(row.json_value).value === text;
|
|
} catch (error) {
|
|
let failure = error;
|
|
if (database && result.version === null) {
|
|
try {
|
|
const version = database.prepare("SELECT sqlite_version() AS version").get()?.version;
|
|
result.version = typeof version === "string" ? version : null;
|
|
} catch (versionError) {
|
|
failure = versionError;
|
|
}
|
|
}
|
|
result.error = failure instanceof Error ? failure.message : String(failure);
|
|
} finally {
|
|
database?.close();
|
|
}
|
|
return result;
|
|
}
|
|
|
|
/** @param {string} value */
|
|
export function isSqliteWalResetSafeVersion(value) {
|
|
const match = /^(\d+)\.(\d+)\.(\d+)$/u.exec(value.trim());
|
|
if (!match) {
|
|
return false;
|
|
}
|
|
const [major, minor, patch] = match.slice(1).map(Number);
|
|
if (![major, minor, patch].every(Number.isSafeInteger)) {
|
|
return false;
|
|
}
|
|
return (
|
|
major > 3 ||
|
|
(major === 3 &&
|
|
(minor > 51 ||
|
|
(minor === 51 && patch >= 3) ||
|
|
(minor === 50 && patch >= 7) ||
|
|
(minor === 44 && patch >= 6)))
|
|
);
|
|
}
|