var __knownSymbol = (name, symbol) => (symbol = Symbol[name]) ? symbol : Symbol.for("Symbol." + name);
var __typeError = (msg) => {
  throw TypeError(msg);
};
var __using = (stack, value, async) => {
  if (value != null) {
    if (typeof value !== "object" && typeof value !== "function") __typeError("Object expected");
    var dispose, inner;
    if (async) dispose = value[__knownSymbol("asyncDispose")];
    if (dispose === void 0) {
      dispose = value[__knownSymbol("dispose")];
      if (async) inner = dispose;
    }
    if (typeof dispose !== "function") __typeError("Object not disposable");
    if (inner) dispose = function() {
      try {
        inner.call(this);
      } catch (e) {
        return Promise.reject(e);
      }
    };
    stack.push([async, dispose, value]);
  } else if (async) {
    stack.push([async]);
  }
  return value;
};
var __callDispose = (stack, error, hasError) => {
  var E = typeof SuppressedError === "function" ? SuppressedError : function(e, s, m, _) {
    return _ = Error(m), _.name = "SuppressedError", _.error = e, _.suppressed = s, _;
  };
  var fail = (e) => error = hasError ? new E(e, error, "An error was suppressed during disposal") : (hasError = true, e);
  var next = (it) => {
    while (it = stack.pop()) {
      try {
        var result = it[1] && it[1].call(it[2]);
        if (it[0]) return Promise.resolve(result).then(next, (e) => (fail(e), next()));
      } catch (e) {
        fail(e);
      }
    }
    if (hasError) throw error;
  };
  return next();
};
import { Debug } from "../../../zql/src/builder/debug-delegate.js";
import { MemoryStorage } from "../../../zql/src/ivm/memory-storage.js";
import { serializePlanDebugEvents, AccumulatorDebugger } from "../../../zql/src/planner/planner-debug.js";
import { Database } from "../../../zqlite/src/db.js";
import { explainQueries } from "../../../zqlite/src/explain-queries.js";
import { createSQLiteCostModel } from "../../../zqlite/src/sqlite-cost-model.js";
import { TableSource } from "../../../zqlite/src/table-source.js";
import { computeZqlSpecs, mustGetTableSpec } from "../db/lite-tables.js";
import { runAst } from "./run-ast.js";
import { TimeSliceTimer } from "./view-syncer/view-syncer.js";
const TIME_SLICE_LAP_THRESHOLD_MS = 200;
async function analyzeQuery(lc, config, clientSchema, ast, syncedRows = true, vendedRows = false, permissions, auth, joinPlans = false) {
  var _stack = [];
  try {
    const db = __using(_stack, new Database(lc, config.replica.file));
    const fullTables = /* @__PURE__ */ new Map();
    const tableSpecs = /* @__PURE__ */ new Map();
    const tables = /* @__PURE__ */ new Map();
    computeZqlSpecs(
      lc,
      db,
      { includeBackfillingColumns: false },
      tableSpecs,
      fullTables
    );
    const planDebugger = joinPlans ? new AccumulatorDebugger() : void 0;
    const costModel = joinPlans ? createSQLiteCostModel(db, tableSpecs) : void 0;
    const timer = await new TimeSliceTimer(lc).start();
    const shouldYield = () => timer.elapsedLap() > TIME_SLICE_LAP_THRESHOLD_MS;
    const yieldProcess = () => timer.yieldProcess();
    const result = await runAst(
      lc,
      clientSchema,
      ast,
      true,
      {
        applyPermissions: permissions !== void 0,
        syncedRows,
        vendedRows,
        auth,
        permissions,
        costModel,
        planDebugger,
        host: {
          debug: new Debug(),
          getSource(tableName) {
            let source = tables.get(tableName);
            if (source) {
              return source;
            }
            const tableSpec = mustGetTableSpec(tableSpecs, tableName);
            const { primaryKey } = tableSpec.tableSpec;
            source = new TableSource(
              lc,
              config.log,
              db,
              tableName,
              tableSpec.zqlSpec,
              primaryKey,
              shouldYield
            );
            tables.set(tableName, source);
            return source;
          },
          createStorage() {
            return new MemoryStorage();
          },
          decorateSourceInput: (input) => input,
          decorateInput: (input) => input,
          addEdge() {
          },
          decorateFilterInput: (input) => input
        }
      },
      yieldProcess
    );
    result.sqlitePlans = explainQueries(result.readRowCountsByQuery ?? {}, db);
    if (planDebugger) {
      result.joinPlans = serializePlanDebugEvents(planDebugger.events);
    }
    return result;
  } catch (_) {
    var _error = _, _hasError = true;
  } finally {
    __callDispose(_stack, _error, _hasError);
  }
}
export {
  analyzeQuery
};
//# sourceMappingURL=analyze.js.map
