import { createSchemaCacheTable, schemaKeyToCacheTableName, } from "../state/cache/create-schema-cache-table.js";
import { getStateCacheTables } from "../state/cache/schema.js";
import { listAvailableCacheSchemas } from "../state/cache/schema-resolver.js";
export function createExplainQuery(args) {
    const preprocess = args.engine.preprocessQuery;
    return ({ sql, parameters }) => {
        const result = preprocess({
            sql,
            parameters,
            // sideEffects removed false,
        });
        ensureCacheTablesForSql(args.engine, result.sql);
        const trimmed = result.sql.trimStart();
        const needsWrapper = trimmed.startsWith("(");
        // Wrap the rewritten SQL in a trivial CTE only when we end up with a bare derived table.
        // SQLite refuses to EXPLAIN `(…) AS alias`, but regular INSERT/UPDATE/SELECT statements
        // should be explained as-is.
        const explainTarget = needsWrapper
            ? `WITH __lix_explain_target AS (${result.sql}) SELECT * FROM __lix_explain_target`
            : result.sql;
        const explainRows = args.engine.sqlite.exec({
            sql: `EXPLAIN QUERY PLAN ${explainTarget}`,
            bind: result.parameters,
            returnValue: "resultRows",
            rowMode: "object",
            columnNames: [],
        });
        const wasRewritten = result.sql !== sql;
        return {
            originalSql: sql,
            parameters,
            rewrittenSql: wasRewritten ? result.sql : undefined,
            plan: explainRows,
        };
    };
}
function ensureCacheTablesForSql(engine, sql) {
    const matches = sql.matchAll(/lix_internal_state_cache_([A-Za-z0-9_]+)/g);
    const tableCache = getStateCacheTables({ engine });
    const availableSchemas = listAvailableCacheSchemas({ engine });
    const tableToSchema = new Map();
    for (const [schemaKey, definition] of availableSchemas.entries()) {
        const tableName = schemaKeyToCacheTableName(schemaKey);
        tableToSchema.set(tableName, definition);
    }
    for (const match of matches) {
        const tableName = match[0];
        if (!tableName)
            continue;
        if (tableCache.has(tableName))
            continue;
        const schemaDefinition = tableToSchema.get(tableName);
        if (!schemaDefinition) {
            continue;
        }
        const created = createSchemaCacheTable({
            engine,
            schema: schemaDefinition,
        });
        tableCache.add(created);
        if (created !== tableName) {
            tableCache.add(tableName);
        }
    }
}
//# sourceMappingURL=explain-query.js.map