Files
reverse-engineering-anything/src/sqlite/SqliteDatabaseWorker.ts
T
Dery Ferdika 89fea8130a fix(sqlite): report result-column capacity refusals as capacity (#6327)
A projection wider than SQLite's native result-column limit failed with the
generic "too many columns in result set" SQL error. The inspector could not
attribute that error to a generated column, so the worker reported "format"
and the parent blamed the caller's path as invalid_format even though the
selected database was readable.

Classify the refusal from SQLite's own column limit for the private
connection, carry the selected and engine counts through the worker reply,
and project it as a capacity resource constraint. The database stays
readable, no partial rows are returned, and the recovery names the column
counts and splitting the projection across calls.
2026-10-23 23:42:20 +09:00

77 lines
2.4 KiB
TypeScript

import { readFile, writeFile } from "node:fs/promises";
import { z } from "zod";
import { inspectSqliteDatabaseInputSchema } from "../domain/sqlite/sqliteDatabase.js";
import { inspectSqliteDatabaseSnapshot } from "./SqliteDatabaseInspection.js";
import {
SQLITE_DATABASE_LIMITS,
SqliteColumnEvaluationFailure,
SqliteColumnLimitFailure,
SqliteInspectionFailure,
sqlitePrimaryResultCode,
} from "./SqliteDatabaseLimits.js";
const requestSchema = z.strictObject({
snapshot_path: z.string(),
reply_path: z.string(),
input: inspectSqliteDatabaseInputSchema,
});
const main = async (): Promise<void> => {
const requestPath = process.argv[2];
if (requestPath === undefined)
throw new Error("Owned SQLite worker request path missing.");
const request = requestSchema.parse(
JSON.parse(await readFile(requestPath, "utf8")),
);
let reply: unknown;
try {
reply = {
ok: true,
inspection: inspectSqliteDatabaseSnapshot(
request.snapshot_path,
request.input,
),
};
} catch (cause: unknown) {
const code = sqlitePrimaryResultCode(cause);
const message = cause instanceof Error ? cause.message : String(cause);
reply =
cause instanceof SqliteColumnEvaluationFailure
? {
ok: false,
reason: cause.reason,
message,
readable_columns: cause.readableColumns,
}
: cause instanceof SqliteColumnLimitFailure
? {
ok: false,
reason: cause.reason,
message,
selected_columns: cause.selectedColumns,
engine_column_limit: cause.engineColumnLimit,
}
: {
ok: false,
reason:
cause instanceof SqliteInspectionFailure
? cause.reason
: code === 7
? "memory"
: code === 18
? "output-limit"
: "format",
message,
};
}
let encoded = JSON.stringify(reply);
if (Buffer.byteLength(encoded) > SQLITE_DATABASE_LIMITS.outputBytes)
encoded = JSON.stringify({
ok: false,
reason: "output-limit",
message:
"Complete SQLite evidence exceeds the 16 MiB JSON reply budget; no partial success was returned.",
});
await writeFile(request.reply_path, encoded, { flag: "wx", mode: 0o600 });
};
await main();