import type { IndexBloatOptions, JobMatchStrategy, ManagedIndex, ManagedFunction } from './types.ts';
import type { ExpectedColumns, ExpectedConstraints } from './drifter.ts';
export interface SqlQuery {
    text: string;
    values: unknown[];
}
export declare const PG_ERROR: {
    divisionByZero: string;
};
export declare const DEFAULT_SCHEMA = "pgboss";
export declare const MIGRATE_RACE_MESSAGE = "division by zero";
export declare const CREATE_RACE_MESSAGE = "already exists";
export declare const SINGLE_QUOTE_REGEX: RegExp;
export declare const JOB_STATES: Readonly<{
    created: "created";
    retry: "retry";
    active: "active";
    completed: "completed";
    cancelled: "cancelled";
    failed: "failed";
}>;
export declare const QUEUE_POLICIES: Readonly<{
    standard: "standard";
    short: "short";
    singleton: "singleton";
    stately: "stately";
    exclusive: "exclusive";
    key_strict_fifo: "key_strict_fifo";
}>;
/**
 * How the expression in a schedule row is read: a cron expression, or an RFC 5545 recurrence rule.
 *
 * Stored on the row rather than derived from the expression on every pass, so the format is decided
 * once, by whoever writes the schedule, and every reader agrees with that decision. A row written
 * straight into the table with SQL has to name its own kind; the column defaults to cron, which is
 * what every schedule written before rules existed is.
 */
export declare const SCHEDULE_KINDS: Readonly<{
    readonly cron: "cron";
    readonly rrule: "rrule";
}>;
/** The kind column's domain, for the CHECK on the table and the migration that adds it. */
export declare const SCHEDULE_KIND_CHECK: string;
/**
 * What a schedule does about occurrences that came due while no cron pass ran.
 *
 * A pass sends what the last minute holds, so nothing outside that window is sent at all: a
 * deployment that was down, or between deploys, for an hour never sends the occurrences that hour
 * held. `skip` is that behavior, and stays the default, since a job appearing on the first pass
 * after a deploy for work whose moment has passed is a surprise nobody asked for.
 *
 * `once` sends a single job however many occurrences were missed, which is what a schedule whose
 * job reads the current state of the world wants: a nightly report that missed three nights is one
 * report, not three. One job needs no occurrence identity to be worth running, which is what a
 * policy sending a job per missed occurrence would need and has no way to carry: the forwarded job
 * gets the schedule's `data` and nothing else, so a handler could not tell which hour of an outage
 * each of twelve identical jobs was for.
 *
 * Part of the options blob rather than a column of its own: the pass reads every schedule row
 * anyway, and nothing queries the table by policy.
 */
export declare const SCHEDULE_MISSED_POLICIES: Readonly<{
    readonly skip: "skip";
    readonly once: "once";
}>;
export declare const BASE_JOB_TABLE = "job";
export declare const COMMON_JOB_TABLE = "job_common";
interface CreateOptions {
    createSchema?: boolean;
    noTablePartitioning?: boolean;
    noDeferrableConstraints?: boolean;
    noAdvisoryLocks?: boolean;
    noCoveringIndexes?: boolean;
    inlineTableIndexes?: boolean;
}
export declare const SERVER_VERSION = "SELECT version() AS version";
export declare function inlineIntoCreateTable(createTable: string, statements: string[]): string;
export declare function create(schema: string, version: number, options?: CreateOptions): string;
export declare const CLOCK_FUNCTION_BODY = "SELECT pg_catalog.now();";
export declare const CLOCK_OVERRIDE_SETTING = "pgboss.test_clock";
export declare function clockTable(schema: string): string;
export declare function clockOverrideBody(schema: string): string;
export declare function enableClockOverride(): string;
export declare function disableClockOverride(): string;
export declare function getClockFunctionSource(schema: string): string;
export declare function clockFunctionIsOverridden(source: string | null | undefined): boolean;
export declare function restoreClockFunction(schema: string): string;
export declare function createClockFunction(schema: string, options?: {
    replace?: boolean;
    body?: string;
}): string;
export declare function createTableWarning(schema: string): string;
export declare function createIndexWarning(schema: string): string;
export declare function createTableJobDependency(schema: string): string;
export declare function createIndexJobDependencyParent(schema: string): string;
export declare function jobTableFormatFunction(schema: string): string;
export declare function createQueue(schema: string, name: string, options: unknown, noAdvisoryLocks?: boolean): string;
export declare function notifyChannelSql(schema: string): string;
export declare function notifyQueue(schema: string, name: string): string;
export declare function deleteQueue(schema: string, name: string, noAdvisoryLocks?: boolean): string;
export declare function trySetQueueMonitorTime(schema: string, queues: string[], seconds: number): SqlQuery;
export declare function setMonitorBackoff(schema: string, elapsedSeconds: number): SqlQuery;
export declare function trySetQueueDeletionTime(schema: string, queues: string[], seconds: number): SqlQuery;
export declare function trySetCronTime(schema: string, seconds: number): string;
export declare function trySetBamTime(schema: string, seconds: number): string;
export declare function trySetFlowTime(schema: string, seconds: number): string;
export declare function trySetReindexTime(schema: string, seconds: number): string;
export declare function updateQueue(schema: string): string;
export declare function getQueues(schema: string, names?: string[]): SqlQuery;
export declare function deleteJobsById(schema: string, table: string): string;
export declare function deleteQueuedJobs(schema: string, table: string): string;
export declare function deleteStoredJobs(schema: string, table: string): string;
export declare function truncateTable(schema: string, table: string): string;
export declare function deleteAllJobs(schema: string, table: string): string;
export declare function getSchedules(schema: string): string;
export declare function getSchedulesByQueue(schema: string): string;
export declare function getSchedulesByQueueAndKey(schema: string): string;
export declare function setScheduleLastJobIds(schema: string): string;
/**
 * Relabels the kind of one or more schedules, as the cron pass does when a row's stored kind
 * disagrees with the expression beside it.
 *
 * `updated_on` is deliberately untouched: it tracks edits to the definition, and a relabel is the
 * pass agreeing with what the row already said, not a change to what the schedule does.
 *
 * Matched on the expression as well as the primary key, so a schedule() upsert landing between the
 * pass's read and this write keeps the kind it was stored with instead of being stamped with the
 * previous expression's. A row that misses the update because it changed underneath is relabelled
 * by the next pass if it still needs it.
 */
export declare function setScheduleKinds(schema: string): string;
export declare function schedule(schema: string): string;
export declare function unschedule(schema: string): string;
export declare function subscribe(schema: string): string;
export declare function unsubscribe(schema: string): string;
export declare function getQueuesForEvent(schema: string): string;
export declare function getTime(schema: string): string;
export declare function insertWarning(schema: string): string;
export declare function getWarnings(schema: string): string;
export declare function getWarningsCount(schema: string): string;
export declare function deleteOldWarnings(schema: string, days: number): string;
export declare function createTableQueueStats(schema: string, noPartitioning?: boolean): string;
export declare function createIndexQueueStats(schema: string, noCoveringIndex?: boolean): string;
export declare function ensureQueueStatsPartitions(schema: string): string;
export declare function dropOldQueueStatsPartitions(schema: string, days: number): string;
export declare function deleteOldQueueStats(schema: string, days: number): string;
export declare function insertQueueStats(schema: string, queues: string[], noAdvisoryLocks?: boolean): string;
export declare function getQueueStatsCache(schema: string): string;
export declare function getQueueStatsHistory(schema: string): string;
export declare function getQueueStatsHistoryBucketed(schema: string, aggregate: 'max' | 'min' | 'avg', mode: 'bucket' | 'auto'): string;
export declare function getVersion(schema: string): string;
export declare function setVersion(schema: string, version: number): string;
export declare function versionTableExists(schema: string): string;
export declare function getSchemaCaseVariants(schema: string): string;
export declare function getPartitionedQueueTables(schema: string): string;
export declare function insertVersion(schema: string, version: number): string;
interface GroupConcurrencyConfig {
    default: number;
    tiers?: Record<string, number>;
}
interface FetchJobOptions {
    schema: string;
    table: string;
    name: string;
    policy: string | undefined;
    limit: number;
    includeMetadata?: boolean;
    priority?: boolean;
    orderByCreatedOn?: boolean;
    ignoreStartAfter?: boolean;
    ignoreSingletons: string[] | null;
    ignoreGroups?: string[] | null;
    groupConcurrency?: number | GroupConcurrencyConfig;
    minPriority?: number;
    maxPriority?: number;
}
/**
 * Builds the fetch query for claiming jobs from the queue.
 *
 * With SKIP LOCKED (noSkipLocked=false, the default), uses SELECT FOR UPDATE SKIP
 * LOCKED, which lets multiple workers efficiently fetch different jobs simultaneously.
 *
 * With noSkipLocked=true, omits FOR UPDATE SKIP LOCKED and adds an additional state
 * check in the WHERE clause. This pattern works better with distributed databases like
 * CockroachDB where SKIP LOCKED has performance issues and can unexpectedly skip
 * unlocked rows.
 *
 * Trade-off when noSkipLocked is set: under high contention, workers may receive fewer
 * jobs per fetch as concurrent updates to the same rows will result in some workers
 * getting empty results. This is acceptable for job queues where processing time
 * exceeds fetch time.
 */
export declare function fetchNextJob(options: FetchJobOptions, noSkipLocked?: boolean): SqlQuery;
export declare function completeJobs(schema: string, table: string, includeQueued?: boolean): string;
export declare function completeJobsWithOutputs(schema: string, table: string): string;
export declare function completeJobsWithOutputsDistributed(schema: string, table: string): string;
export declare function cancelJobs(schema: string, table: string): string;
export declare function resumeJobs(schema: string, table: string): string;
export declare function restoreJobs(schema: string, table: string): string;
interface InsertJobsOptions {
    table: string;
    name: string;
    returnId?: boolean;
    notify?: boolean;
    slots?: boolean;
}
export declare function insertJobs(schema: string, { table, name, returnId, notify, slots }: InsertJobsOptions): string;
export declare function insertFlowJobs(schema: string, { table, name }: {
    table: string;
    name: string;
}, jobs: unknown[]): string;
export declare function failJobsById(schema: string, table: string): string;
export declare function failJobsByTimeout(schema: string, table: string, queues: string[], noAdvisoryLocks?: boolean): string;
export declare function failJobsByHeartbeat(schema: string, table: string, queues: string[], noAdvisoryLocks?: boolean): string;
export declare function touchJobs(schema: string, table: string): string;
export declare function failJobsByIdWithOutputs(schema: string, table: string): string;
export declare function deadLetterJobsByIdWithOutputs(schema: string, table: string): string;
export declare function selectJobsToFailById(schema: string, table: string): SqlQuery;
export declare function deleteJobsToFail(schema: string, table: string): SqlQuery;
export declare function selectJobsToFailByTimeout(schema: string, table: string, queues: string[]): SqlQuery;
export declare function selectJobsToFailByHeartbeat(schema: string, table: string, queues: string[]): SqlQuery;
export declare function deleteJobsByIds(schema: string, table: string): SqlQuery;
export declare function completeJobsDistributed(schema: string, table: string, includeQueued?: boolean): string;
export declare function decrementDependents(schema: string): string;
export declare const FLOW_BATCH_SIZE = 1000;
export declare function resolveFlowJobs(schema: string, table: string, names: string[]): SqlQuery;
export declare function selectBlockingParents(schema: string, table: string, names: string[], noSkipLocked?: boolean): SqlQuery;
export declare function clearBlocking(schema: string): string;
export declare function insertRetryJob(schema: string, table: string): string;
export declare function insertDeadLetterJob(schema: string): string;
export declare function redriveJobs(schema: string, table: string): string;
export declare function selectRedriveCandidates(schema: string, table: string): string;
export declare function insertRedrivenJobs(schema: string, table: string): string;
export declare function previewRedrive(schema: string, table: string): string;
export declare function deletion(schema: string, table: string, queues: string[], noAdvisoryLocks?: boolean): string;
export declare function retryJobs(schema: string, table: string): string;
export declare function updateJob(schema: string, table: string, name: string, by: 'id' | 'singletonKey', match: JobMatchStrategy, notify?: boolean): string;
export declare function getQueueStats(schema: string, table: string, queues: string[]): SqlQuery;
export declare const READY_HISTORY_SIZE = 60;
export declare function cacheQueueStats(schema: string, table: string, queues: string[], noAdvisoryLocks?: boolean): string;
export declare function refreshQueueStats(schema: string, table: string, name: string, options?: {
    noAdvisoryLocks?: boolean;
    firstCapture?: boolean;
}): string;
export declare function serializeArrayParam(values: string[]): string;
export declare function serializeJsonParam(value: unknown): string;
export declare function transaction(query: string | string[]): string;
export declare function locked(schema: string, query: string | string[], key?: string, noAdvisoryLocks?: boolean): string;
export declare function assertMigration(schema: string, version: number): string;
export declare function findJobs(schema: string, table: string, options: {
    queued: boolean;
    byKey: boolean;
    byData: boolean;
    byId: boolean;
}): string;
export declare function getJobById(schema: string, table: string): string;
export declare function insertDependencies(schema: string, deps?: unknown[]): string;
export declare function getDependencies(schema: string): string;
export declare function getDependents(schema: string): string;
export declare function cleanupDependencies(schema: string, table: string, queues: string[], noAdvisoryLocks?: boolean): string;
export declare function getBlockedKeys(schema: string, table: string): string;
export declare function getNextBamCommand(schema: string, { useLiveness }?: {
    useLiveness?: boolean;
}): string;
export declare function bamHealDrop(schema: string, command: string): string | null;
export declare function bamHealProbe(schema: string, command: string): string | null;
export declare function releaseBamCommand(schema: string, id: string, priorStatus: string, priorStartedOn: string | null, claimedStartedOn: string): string;
export declare function setBamCompleted(schema: string, id: string): string;
export declare function setBamFailed(schema: string, id: string, error: string): string;
export declare function getBamStatus(schema: string): string;
export declare function getBamEntries(schema: string): string;
export declare function jobCommonExists(schema: string): string;
export declare function getManagedQueuePartitions(schema: string): string;
export declare function getIncompleteBamCommands(schema: string): string;
export declare function bamCommandIndexName(command: string): string | null;
interface QueuePartition {
    table: string;
    policy?: string | null;
}
export declare const EXPECTED_JOB_STATES: readonly string[];
export declare function expectedManagedTables(schema: string, partitioned: boolean, partitions?: QueuePartition[]): string[];
export declare function expectedManagedColumns(schema: string, partitioned: boolean, partitions?: QueuePartition[]): ExpectedColumns[];
export declare function expectedManagedConstraints(schema: string, partitioned: boolean): ExpectedConstraints[];
export declare function expectedManagedFunctions(schema: string, partitioned: boolean, options?: {
    clockOverride?: boolean;
}): ManagedFunction[];
export declare function expectedManagedIndexes(schema: string, partitioned: boolean, partitions?: QueuePartition[]): ManagedIndex[];
export declare const REINDEX_DEFAULTS: {
    minPages: number;
    maxEntriesPerPage: number;
    minSizeRatio: number;
    maxIndexBytes: number;
};
/**
 * Bloated job indexes, by the pg_class density heuristic. Deliberately avoids pgstattuple: it is an
 * extension that may not be installed, and relpages/reltuples separates a bloated index from a
 * healthy one by three orders of magnitude on their own.
 *
 * PostgreSQL-only (including PGlite, where both the bloat and REINDEX CONCURRENTLY behave normally).
 * Callers must gate on noReindex. See the note in boss.ts #reindex.
 *
 * `owned` is returned rather than filtered on, so an installation whose role cannot reindex still
 * gets told what is bloated. Only leaf indexes (relkind 'i') are candidates. pg-boss creates
 * i1..i10 directly on each partition, and a partitioned index (relkind 'I') cannot be reindexed
 * except through its leaves anyway.
 *
 * Caveat: relpages/reltuples are refreshed by VACUUM/ANALYZE, so they go stale where autovacuum is
 * disabled for the table. That is acceptable. The entire failure mode assumes autovacuum runs.
 */
export declare function getBloatedIndexes(schema: string, tables?: string[], options?: IndexBloatOptions): string;
/**
 * Every owned leaf index on the job tables, ignoring the density gate. The target list for
 * `{ force: true }`.
 */
export declare function getJobIndexes(schema: string, tables?: string[]): string;
/**
 * Invalid `*_ccnew` stubs left behind by an interrupted REINDEX CONCURRENTLY. Postgres appends
 * `_ccnew`, then `_ccnew1`, `_ccnew2`, ... on collision. These must be dropped before a retry or
 * they accumulate, and they are dead weight that vacuum still walks. Mirrors bamHealDrop's role for
 * interrupted CREATE INDEX CONCURRENTLY.
 */
export declare function getReindexLeftovers(schema: string, tables?: string[], noIndexProgressView?: boolean, anyOwner?: boolean): string;
/**
 * The sources that can hold the MVCC horizon back, and the catalog each is read from. Split out so
 * an installation whose role cannot read one of them still gets an answer from the rest, and so the
 * warning can name which sources it could not check rather than implying a clean bill of health.
 *
 * `pg_stat_activity.backend_xmin` is readable by an unprivileged role (it is not one of the columns
 * restricted to the owning user), as are the other three views, so the degraded path is defensive
 * rather than expected. A managed provider may still revoke them.
 */
export declare const XMIN_HORIZON_SOURCES: {
    readonly backends: "SELECT max(age(backend_xmin)) FROM pg_catalog.pg_stat_activity WHERE backend_xmin IS NOT NULL AND (xact_start IS NULL OR xact_start < $1)";
    readonly slots: "SELECT max(age(xmin)) FROM pg_catalog.pg_replication_slots WHERE xmin IS NOT NULL";
    readonly slotsCatalog: "SELECT max(age(catalog_xmin)) FROM pg_catalog.pg_replication_slots WHERE catalog_xmin IS NOT NULL";
    readonly standbys: "SELECT max(age(backend_xmin)) FROM pg_catalog.pg_stat_replication WHERE backend_xmin IS NOT NULL";
    readonly prepared: "SELECT max(age(transaction)) FROM pg_catalog.pg_prepared_xacts";
};
export type XminHorizonSource = keyof typeof XMIN_HORIZON_SOURCES;
export declare const XMIN_HORIZON_QUERY_SOURCES: readonly XminHorizonSource[];
/**
 * How far behind the MVCC horizon is, per holder class, in **transactions**.
 *
 * `age()` measures transactions elapsed since the pinned xid, not wall time, which is the metric
 * that matters: dead tuples accumulate per transaction, so a horizon pinned across an idle night
 * costs nothing while the same age on a busy queue is a backlog of rows autovacuum cannot reclaim.
 * Measured directly. A REPEATABLE READ holder open on an idle database reports 0, and 2,000 after
 * 2,000 transactions with the same holder still open.
 *
 * Also returns the oldest in-transaction backend's wall-clock age, purely so the warning can say
 * how long as well as how far; nothing keys off it.
 */
export declare function getXminHorizon(lastVacuum: Date, sources?: readonly XminHorizonSource[]): SqlQuery;
/**
 * Dead-tuple accounting for pg-boss's own job tables, plus the autovacuum settings each table is
 * actually measured against.
 *
 * This is the direct measurement the `xmin_horizon` check is built on. `age(backend_xmin)` is only
 * a proxy for it, and a poor one: it counts cluster transactions, so a producer batching 500 jobs
 * per `insert()` moves it ~9x slower than one calling `send()` per job for identical garbage, and
 * any unrelated application sharing the database moves it for reasons that have nothing to do with
 * pg-boss at all. `n_dead_tup` is the harm itself.
 *
 * The budget comes from Postgres rather than from a pg-boss constant:
 * `autovacuum_vacuum_threshold + autovacuum_vacuum_scale_factor * n_live_tup` is the point the
 * server itself decides a table needs vacuuming. Per-table reloptions win over the cluster
 * settings, so an operator who has tuned a queue's table is measured against their own numbers.
 *
 * `lastVacuum` is the later of the autovacuum and manual timestamps: what matters is that a vacuum
 * ran, not who asked for it. GREATEST ignores NULLs, so it is NULL only when neither has ever run.
 * Returned as epoch milliseconds rather than timestamptz: pg-boss shares the caller's pool, and a
 * global pg-types parser (Temporal.Instant, say) returns values `new Date()` cannot coerce.
 * Its age is computed server-side rather than against the client clock, so the check does not
 * inherit the skew that `clock_skew` exists to report.
 *
 * PostgreSQL-only. Callers must gate on noMonitorVacuum - see the note in boss.ts #checkXminHorizon.
 */
export declare function getJobTableGarbage(schema: string, tables?: string[]): string;
export declare function reindexIndex(schema: string, name: string): string;
export declare function dropIndexConcurrently(schema: string, name: string): string;
/**
 * The statement list an operator runs by hand: every stale stub dropped first, then the rebuilds.
 *
 * Stubs are emitted whole rather than paired to the index they came from. Postgres does not append
 * `_ccnew`. It truncates the *base* so the result fits in 63 bytes, so `j<sha224>_i11` (61 chars)
 * leaves behind `j<sha224>__ccnew` with the `i11` gone, and a prefix match never fires on a
 * partitioned queue (every partition table name is `'j' || sha224(queue_name)`, 57 chars). Dropping
 * them unconditionally is also what the background pass does: an invalid stub is dead weight that
 * vacuum still walks, whichever index it came from.
 */
export declare function buildReindexCommands(schema: string, targets: {
    name: string;
}[], leftovers: {
    name: string;
}[]): string[];
export {};
//# sourceMappingURL=plans.d.ts.map