@dbsp/adapter-pgsql 5.0.0 → 6.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -2
- package/dist/chunk-NXGMFZ4E.js +57170 -0
- package/dist/chunk-NXGMFZ4E.js.map +1 -0
- package/dist/index.d.ts +181 -1245
- package/dist/index.js +798 -37125
- package/dist/index.js.map +1 -1
- package/dist/internal.d.ts +144 -5
- package/dist/internal.js +37 -1
- package/dist/outcome-protocol-Dw5DYhnA.d.ts +2727 -0
- package/package.json +3 -3
- package/dist/chunk-KZ3NLIZ5.js +0 -13043
- package/dist/chunk-KZ3NLIZ5.js.map +0 -1
- package/dist/outcome-protocol-CACJDzli.d.ts +0 -1088
|
@@ -0,0 +1,2727 @@
|
|
|
1
|
+
import * as _dbsp_types from '@dbsp/types';
|
|
2
|
+
import { DialectCapabilities, IndexIR, ModelIR, DbCasing, NormalizedManagedStep, DeclarableResourceAddress, TableIR, CatalogueIdentity, SequenceIR, LedgerPayload, ResourceAddress, LedgerAddress, HierarchyIR, PhysicalNameInventory, Adapter, AdapterLogger, AdapterCapabilities, ConnectionAvailability, PlanReport, CompiledNqlQuery, CompileOptions, CompiledQuery, CompileResultWithIncludes, SubqueryIncludeInfo, ExpressionIntent, InsertIntent, InsertFromIntent, UpdateIntent, BatchUpdateIntent, DeleteIntent, UpsertIntent, UpsertFromIntent, RecursivePlanReport, CteQueryIntent, SetOperationIntent, DumpMeta, Dump, AdapterStreamOptions, PinnedConnectionOptions, TransactionOptions, LedgerHome, DurableIntentRecord, TransitionRunAuthorization, TransitionRunJournal, ProvenPlanShape, LedgerReservationRow, LedgerIdentity, LedgerChainMember, LedgerMarkerState, DeclarationSet, ReinitializePreflightReport, OutcomeClaimPlan, DestructiveDecision, LedgerEventKind, OutcomeVacancy, OutcomeProtocolRefusal, ClaimBundleStatement, ControllerIdentity, AdmittedOutcomeClaim, ClaimToken, OutcomeIndeterminateRecoveryEvidence, OutcomeRecoveryEffect, OutcomeRecoveryClassification, ScopedApprovalSet, OutcomeRecoveryReadBack, OutcomeClaimAdmission } from '@dbsp/types';
|
|
3
|
+
import { Pool, PoolClient } from 'pg';
|
|
4
|
+
import { IndexInfo, TruncateOptions, VacuumOptions, AlterColumnOptions, CreateIndexOptions, DropIndexOptions, TransitionRunPersister, ValidatedManagedStepManifest } from '@dbsp/core';
|
|
5
|
+
import { AdmittedDestructiveOutcomeClaim, DurablyLoadedRun } from '@dbsp/core/internal';
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Default primary key column name used as convention fallback
|
|
9
|
+
* when schema metadata doesn't provide an explicit PK.
|
|
10
|
+
*
|
|
11
|
+
* Consumers (handlers, compiler) must NOT use this directly —
|
|
12
|
+
* they use `requiredColumn()` to throw on missing data.
|
|
13
|
+
* Only convention mappers (extractors, introspection) should reference this.
|
|
14
|
+
*/
|
|
15
|
+
declare const DEFAULT_PK_COLUMN = "id";
|
|
16
|
+
/**
|
|
17
|
+
* Derive a foreign key column name from a table name and the PK column it references.
|
|
18
|
+
*
|
|
19
|
+
* Convention: `${singularTableName}_${pkColumnName}`
|
|
20
|
+
* e.g. (authors, id) → author_id, (categories, id) → category_id
|
|
21
|
+
*
|
|
22
|
+
* Consumers should use `deriveFkColumnName` from CompilerContext or options
|
|
23
|
+
* for configurable behavior.
|
|
24
|
+
*/
|
|
25
|
+
type FkColumnDerivation = (tableName: string, pkColumnName: string) => string;
|
|
26
|
+
declare const defaultFkDerivation: FkColumnDerivation;
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* NamingPlugin - Identifier transformation between model and database naming conventions
|
|
30
|
+
*
|
|
31
|
+
* Inspired by Kysely's CamelCasePlugin architecture.
|
|
32
|
+
* The plugin transforms identifiers bidirectionally:
|
|
33
|
+
* - toDatabase: model name (camelCase) → database name (snake_case)
|
|
34
|
+
* - toModel: database name (snake_case) → model name (camelCase)
|
|
35
|
+
*/
|
|
36
|
+
/**
|
|
37
|
+
* Interface for naming convention transformation plugins
|
|
38
|
+
*/
|
|
39
|
+
interface NamingPlugin {
|
|
40
|
+
/**
|
|
41
|
+
* Transform a model identifier to database format
|
|
42
|
+
* Example: "createdAt" → "created_at"
|
|
43
|
+
*/
|
|
44
|
+
toDatabase(identifier: string): string;
|
|
45
|
+
/**
|
|
46
|
+
* Transform a database identifier to model format
|
|
47
|
+
* Example: "created_at" → "createdAt"
|
|
48
|
+
*/
|
|
49
|
+
toModel(identifier: string): string;
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Identity plugin - no transformation
|
|
53
|
+
* Use this when model and database naming conventions match
|
|
54
|
+
*/
|
|
55
|
+
declare class IdentityNamingPlugin implements NamingPlugin {
|
|
56
|
+
toDatabase(identifier: string): string;
|
|
57
|
+
toModel(identifier: string): string;
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* CamelCase ↔ snake_case transformation plugin
|
|
61
|
+
*
|
|
62
|
+
* Follows the same logic as Kysely's CamelCasePlugin:
|
|
63
|
+
* - Handles consecutive uppercase letters (e.g., "parseJSON" → "parse_json")
|
|
64
|
+
* - Handles numbers (e.g., "field1Name" → "field1_name")
|
|
65
|
+
* - Preserves leading underscores
|
|
66
|
+
*/
|
|
67
|
+
declare class CamelCaseNamingPlugin implements NamingPlugin {
|
|
68
|
+
/**
|
|
69
|
+
* camelCase → snake_case
|
|
70
|
+
*/
|
|
71
|
+
toDatabase(identifier: string): string;
|
|
72
|
+
/**
|
|
73
|
+
* snake_case → camelCase
|
|
74
|
+
*/
|
|
75
|
+
toModel(identifier: string): string;
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* Singleton instances for convenience
|
|
79
|
+
*/
|
|
80
|
+
declare const identityNaming: IdentityNamingPlugin;
|
|
81
|
+
declare const camelCaseNaming: CamelCaseNamingPlugin;
|
|
82
|
+
/**
|
|
83
|
+
* Get a naming plugin by DbCasing (intuitive semantics).
|
|
84
|
+
* - `'snake_case'`: DB uses snake_case → CamelCaseNamingPlugin (transforms to camelCase)
|
|
85
|
+
* - `'camelCase'`: DB uses camelCase → IdentityNamingPlugin (no transform)
|
|
86
|
+
* - `'preserve'`: No transformation → IdentityNamingPlugin
|
|
87
|
+
*/
|
|
88
|
+
declare function getNamingPluginForDbCasing(casing: 'snake_case' | 'camelCase' | 'preserve'): NamingPlugin;
|
|
89
|
+
|
|
90
|
+
type IndexRenderKey = {
|
|
91
|
+
readonly column?: string | undefined;
|
|
92
|
+
readonly expression?: string | undefined;
|
|
93
|
+
readonly opclass?: string | undefined;
|
|
94
|
+
};
|
|
95
|
+
type IndexRenderSpec = {
|
|
96
|
+
readonly name: string;
|
|
97
|
+
readonly table: string;
|
|
98
|
+
readonly schema?: string | undefined;
|
|
99
|
+
readonly unique: boolean;
|
|
100
|
+
readonly method?: string | undefined;
|
|
101
|
+
readonly keys: readonly IndexRenderKey[];
|
|
102
|
+
readonly include?: readonly string[] | undefined;
|
|
103
|
+
readonly nullsNotDistinct?: boolean | undefined;
|
|
104
|
+
readonly with?: Readonly<Record<string, unknown>> | undefined;
|
|
105
|
+
readonly where?: string | undefined;
|
|
106
|
+
/** The in-process index value that owns a deparsed `where` predicate. */
|
|
107
|
+
readonly whereSource?: IndexIR | undefined;
|
|
108
|
+
readonly concurrently?: boolean | undefined;
|
|
109
|
+
readonly ifNotExists?: boolean | undefined;
|
|
110
|
+
};
|
|
111
|
+
type IndexCapabilityContext = {
|
|
112
|
+
readonly caps: DialectCapabilities;
|
|
113
|
+
readonly targetVersion?: string | undefined;
|
|
114
|
+
};
|
|
115
|
+
type IndexFeature = 'INCLUDE' | 'PARTIAL INDEX' | 'EXPRESSION INDEX' | 'INDEX METHOD' | 'OPCLASS' | 'NULLS NOT DISTINCT';
|
|
116
|
+
declare class IndexFeatureUnsupportedError extends Error {
|
|
117
|
+
readonly indexName: string;
|
|
118
|
+
readonly unsupportedFeatures: readonly IndexFeature[];
|
|
119
|
+
constructor(indexName: string, unsupportedFeatures: readonly IndexFeature[], message: string);
|
|
120
|
+
}
|
|
121
|
+
declare class AutoIncrementTransitionUnsupportedError extends Error {
|
|
122
|
+
readonly table: string;
|
|
123
|
+
readonly column: string;
|
|
124
|
+
readonly direction: 'enable' | 'disable' | 'retype' | 'unknown';
|
|
125
|
+
constructor(table: string, column: string, direction: 'enable' | 'disable' | 'retype' | 'unknown');
|
|
126
|
+
}
|
|
127
|
+
declare function assertCreateIndexSupported(spec: IndexRenderSpec, ctx?: IndexCapabilityContext): void;
|
|
128
|
+
declare function assertCreateIndexesSupported(specs: readonly IndexRenderSpec[], ctx?: IndexCapabilityContext): void;
|
|
129
|
+
declare function renderCreateIndex(spec: IndexRenderSpec, ctx?: IndexCapabilityContext): string;
|
|
130
|
+
|
|
131
|
+
/**
|
|
132
|
+
* DDL Generator - Generates PostgreSQL DDL statements from ModelIR
|
|
133
|
+
*
|
|
134
|
+
* Generates SQL strings directly for better compatibility and control.
|
|
135
|
+
* Two-pass strategy handles circular FK dependencies.
|
|
136
|
+
*
|
|
137
|
+
* @module ddl/ddl-generator
|
|
138
|
+
*/
|
|
139
|
+
|
|
140
|
+
interface GenerateDDLOptions$1 {
|
|
141
|
+
/** Include DROP TABLE IF EXISTS statements before CREATE TABLE */
|
|
142
|
+
readonly includeDropStatements?: boolean;
|
|
143
|
+
/**
|
|
144
|
+
* Database schema name (e.g., 'public', 'tenant_123').
|
|
145
|
+
* Required when emitted DDL would otherwise mix non-default target-scoped
|
|
146
|
+
* custom types/enums with unqualified table SQL.
|
|
147
|
+
*/
|
|
148
|
+
readonly schemaName?: string;
|
|
149
|
+
/**
|
|
150
|
+
* Automatically create indexes on foreign key columns.
|
|
151
|
+
* FK columns are frequently used in JOINs, so indexing is a best practice.
|
|
152
|
+
* @default true
|
|
153
|
+
*/
|
|
154
|
+
readonly fkAutoIndex?: boolean;
|
|
155
|
+
/** Naming plugin for logical-model callers. Physical models omit this option. */
|
|
156
|
+
readonly naming?: NamingPlugin;
|
|
157
|
+
/** Dialect capabilities — unsupported index features throw during DDL generation */
|
|
158
|
+
readonly dialectCapabilities?: DialectCapabilities;
|
|
159
|
+
}
|
|
160
|
+
/**
|
|
161
|
+
* Generate DDL statements from a ModelIR schema.
|
|
162
|
+
*
|
|
163
|
+
* Uses a two-pass approach to handle circular FK dependencies:
|
|
164
|
+
* 1. CREATE TABLE (without FK constraints)
|
|
165
|
+
* 2. ALTER TABLE ADD CONSTRAINT for foreign keys
|
|
166
|
+
* 3. CREATE INDEX (explicit + auto-generated for FKs)
|
|
167
|
+
*
|
|
168
|
+
* @param schema - The ModelIR schema to generate DDL from
|
|
169
|
+
* @param options - Optional configuration
|
|
170
|
+
* @returns Array of DDL statements in dependency order
|
|
171
|
+
*/
|
|
172
|
+
declare function generateDDL$1(schema: ModelIR, options?: GenerateDDLOptions$1): string[];
|
|
173
|
+
declare function generateCreateIndex(tableName: string, idx: IndexIR, schemaName: string | undefined, context?: IndexCapabilityContext, ifNotExists?: boolean): string;
|
|
174
|
+
/**
|
|
175
|
+
* Returns whether the PostgreSQL DDL generator can emit this IndexIR.
|
|
176
|
+
*
|
|
177
|
+
* Keep this as the single representability predicate for generated schema
|
|
178
|
+
* omission and destructive-drop classification: both sides must agree on the
|
|
179
|
+
* exact validation surface used by generateCreateIndex().
|
|
180
|
+
*/
|
|
181
|
+
declare function canGenerateCreateIndex(tableName: string, idx: IndexIR, schemaName?: string | undefined): boolean;
|
|
182
|
+
|
|
183
|
+
/**
|
|
184
|
+
* Schema Comparison Engine (DDL-PROV Block 1)
|
|
185
|
+
*
|
|
186
|
+
* Compares two ModelIRs (schema definition vs database state)
|
|
187
|
+
* and produces a structured diff of changes needed.
|
|
188
|
+
*
|
|
189
|
+
* @module schema-diff
|
|
190
|
+
*/
|
|
191
|
+
|
|
192
|
+
type ChangeKind = 'create_table' | 'drop_table' | 'readdress_table' | 'add_column' | 'drop_column' | 'alter_column_type' | 'alter_column_nullable' | 'alter_column_default' | 'alter_column_unique' | 'alter_column_auto_increment' | 'add_primary_key' | 'drop_primary_key' | 'add_foreign_key' | 'drop_foreign_key' | 'alter_foreign_key' | 'validate_constraint' | 'create_index' | 'drop_index' | 'add_check_constraint' | 'drop_check_constraint' | 'create_enum' | 'alter_enum_add_value' | 'drop_enum' | 'alter_column_collation' | 'alter_column_identity' | 'add_comment' | 'drop_comment' | 'create_extension' | 'drop_extension' | 'create_sequence' | 'alter_sequence' | 'drop_sequence' | 'enable_rls' | 'disable_rls' | 'create_policy' | 'drop_policy';
|
|
193
|
+
interface SchemaChange {
|
|
194
|
+
readonly kind: ChangeKind;
|
|
195
|
+
readonly table: string;
|
|
196
|
+
readonly column?: string;
|
|
197
|
+
readonly destructive: boolean;
|
|
198
|
+
readonly details: string;
|
|
199
|
+
/** Additional metadata for SQL generation */
|
|
200
|
+
readonly meta?: Readonly<Record<string, unknown>>;
|
|
201
|
+
}
|
|
202
|
+
interface DiffSummary {
|
|
203
|
+
readonly tables: {
|
|
204
|
+
readonly added: number;
|
|
205
|
+
readonly dropped: number;
|
|
206
|
+
};
|
|
207
|
+
readonly columns: {
|
|
208
|
+
readonly added: number;
|
|
209
|
+
readonly dropped: number;
|
|
210
|
+
readonly altered: number;
|
|
211
|
+
};
|
|
212
|
+
readonly indexes: {
|
|
213
|
+
readonly added: number;
|
|
214
|
+
readonly dropped: number;
|
|
215
|
+
};
|
|
216
|
+
readonly constraints: {
|
|
217
|
+
readonly added: number;
|
|
218
|
+
readonly dropped: number;
|
|
219
|
+
readonly altered: number;
|
|
220
|
+
};
|
|
221
|
+
}
|
|
222
|
+
interface SchemaDiff {
|
|
223
|
+
readonly changes: readonly SchemaChange[];
|
|
224
|
+
readonly hasDestructive: boolean;
|
|
225
|
+
readonly summary: DiffSummary;
|
|
226
|
+
}
|
|
227
|
+
interface CompareSchemataOptions$1 {
|
|
228
|
+
/** Internal compatibility metadata; public physical-model comparison owns schema. */
|
|
229
|
+
readonly schema?: string;
|
|
230
|
+
/** Internal callers must already pass physical names; this value is ignored. */
|
|
231
|
+
dbCasing?: DbCasing;
|
|
232
|
+
/** Authored standalone-sequence names retained by the physical-model boundary. */
|
|
233
|
+
readonly declaredSequenceNames?: ReadonlyMap<string, string>;
|
|
234
|
+
/** Dialect capabilities — comparisons for unsupported features will be skipped */
|
|
235
|
+
readonly dialectCapabilities?: DialectCapabilities;
|
|
236
|
+
/**
|
|
237
|
+
* When `true`, extensions present in the live DB but absent from the model
|
|
238
|
+
* schema are silently ignored — no `drop_extension` change is emitted for them.
|
|
239
|
+
* Only extensions explicitly declared in the model are managed (created if missing).
|
|
240
|
+
*
|
|
241
|
+
* Use this when the database image pre-installs extensions that the application
|
|
242
|
+
* schema does not own (e.g. pgvector, pg_search bundled in a custom Postgres image).
|
|
243
|
+
* Default: `false` (full-sync behaviour — unmanaged DB extensions produce a
|
|
244
|
+
* `drop_extension` entry).
|
|
245
|
+
*/
|
|
246
|
+
readonly ignoreUnmanagedExtensions?: boolean;
|
|
247
|
+
/**
|
|
248
|
+
* Strict compile-only mode for callers that require convergence guarantees.
|
|
249
|
+
*
|
|
250
|
+
* `compareSchemata()` is intentionally pure and cannot ask PostgreSQL to
|
|
251
|
+
* canonicalise raw-SQL expression surfaces. By default it keeps the historic
|
|
252
|
+
* best-effort verbatim comparison for column defaults, CHECK expressions,
|
|
253
|
+
* partial-index predicates, and index expressions. Set this flag to throw when either model
|
|
254
|
+
* contains one of those surfaces so a caller cannot accidentally rely on a
|
|
255
|
+
* compile-only diff for a convergence-sensitive check.
|
|
256
|
+
*
|
|
257
|
+
* Live PostgreSQL callers should use `comparePgsqlDatabaseSchema()`, which
|
|
258
|
+
* canonicalises CHECK constraint expressions, column defaults, and partial-index predicates before calling this function.
|
|
259
|
+
* Under that live mode, each side is canonicalised independently; rejected
|
|
260
|
+
* predicates refuse the migration and infrastructure fallback uses both raw
|
|
261
|
+
* models. This does not prove
|
|
262
|
+
* that the resulting migration is executable.
|
|
263
|
+
* Index expressions are not canonicalised by the live helper and are rejected
|
|
264
|
+
* there when this strict flag is set.
|
|
265
|
+
*/
|
|
266
|
+
readonly requireExpressionCanonicalization?: boolean;
|
|
267
|
+
}
|
|
268
|
+
declare class ExpressionCanonicalizationUnavailableError extends Error {
|
|
269
|
+
readonly surfaces: readonly string[];
|
|
270
|
+
constructor(surfaces: readonly string[]);
|
|
271
|
+
}
|
|
272
|
+
type ReferencedKeyKind = 'unique_index' | 'primary_key' | 'column_unique';
|
|
273
|
+
interface ReferencedKeyRemovalConflict {
|
|
274
|
+
readonly keyKind: ReferencedKeyKind;
|
|
275
|
+
readonly table: string;
|
|
276
|
+
readonly keyColumns: readonly string[];
|
|
277
|
+
readonly keyName?: string;
|
|
278
|
+
readonly referencingTable: string;
|
|
279
|
+
readonly foreignKeyColumns: readonly string[];
|
|
280
|
+
}
|
|
281
|
+
/**
|
|
282
|
+
* Refusal raised when executable UP SQL would remove a key a foreign key may
|
|
283
|
+
* depend on. Only foreign keys visible in the compared model are detected, so
|
|
284
|
+
* a single-schema comparison cannot see a foreign key whose source table is in
|
|
285
|
+
* another schema. A hand-built `SchemaDiff` without the comparison annotation
|
|
286
|
+
* is not covered.
|
|
287
|
+
*/
|
|
288
|
+
declare class ReferencedKeyRemovalError extends Error {
|
|
289
|
+
readonly conflicts: readonly ReferencedKeyRemovalConflict[];
|
|
290
|
+
constructor(conflicts: readonly ReferencedKeyRemovalConflict[]);
|
|
291
|
+
}
|
|
292
|
+
/**
|
|
293
|
+
* Compare two ModelIRs and produce a structured diff.
|
|
294
|
+
*
|
|
295
|
+
* @param schema - The desired schema (from definition)
|
|
296
|
+
* @param db - The current database state (from introspection)
|
|
297
|
+
* @param options - Optional comparison settings (e.g. dbCasing)
|
|
298
|
+
* @returns SchemaDiff with all changes needed to bring DB in sync with schema
|
|
299
|
+
*/
|
|
300
|
+
declare function compareSchemata$1(schema: ModelIR, db: ModelIR, options?: CompareSchemataOptions$1): SchemaDiff;
|
|
301
|
+
/** Collect comparison annotations from the changes an executable path selected. */
|
|
302
|
+
declare function collectReferencedKeyRemovalConflicts(changes: readonly SchemaChange[]): readonly ReferencedKeyRemovalConflict[];
|
|
303
|
+
|
|
304
|
+
type Address = DeclarableResourceAddress & {
|
|
305
|
+
readonly scope: 'schema' | 'database';
|
|
306
|
+
};
|
|
307
|
+
type GeneratedConstraintPostcondition = {
|
|
308
|
+
readonly type: 'p' | 'u';
|
|
309
|
+
readonly columns: readonly string[];
|
|
310
|
+
readonly deferrable: boolean;
|
|
311
|
+
readonly initiallyDeferred: boolean;
|
|
312
|
+
readonly enforced: boolean;
|
|
313
|
+
} | {
|
|
314
|
+
readonly type: 'f';
|
|
315
|
+
readonly columns: readonly string[];
|
|
316
|
+
readonly references: {
|
|
317
|
+
readonly schema: string;
|
|
318
|
+
readonly table: string;
|
|
319
|
+
readonly columns: readonly string[];
|
|
320
|
+
};
|
|
321
|
+
readonly onDelete: GeneratedForeignKeyAction;
|
|
322
|
+
readonly onUpdate: GeneratedForeignKeyAction;
|
|
323
|
+
readonly deferrable: boolean;
|
|
324
|
+
readonly initiallyDeferred: boolean;
|
|
325
|
+
readonly enforced: boolean;
|
|
326
|
+
readonly notValid: boolean;
|
|
327
|
+
} | {
|
|
328
|
+
readonly type: 'c';
|
|
329
|
+
/** The ModelIR CHECK expression, never a rendered constraint definition. */
|
|
330
|
+
readonly expression: string;
|
|
331
|
+
readonly notValid: boolean;
|
|
332
|
+
};
|
|
333
|
+
/** The semantic FK actions PostgreSQL can represent in pg_constraint. */
|
|
334
|
+
type GeneratedForeignKeyAction = 'NO ACTION' | 'RESTRICT' | 'CASCADE' | 'SET NULL' | 'SET DEFAULT';
|
|
335
|
+
type GeneratedIndexPostcondition = {
|
|
336
|
+
/** The identity is persisted separately from the rendered CREATE INDEX SQL. */
|
|
337
|
+
readonly schema: string;
|
|
338
|
+
readonly table: string;
|
|
339
|
+
readonly name: string;
|
|
340
|
+
/** PostgreSQL exposes an omitted method as btree; make that expectation explicit. */
|
|
341
|
+
readonly method: string;
|
|
342
|
+
readonly unique: boolean;
|
|
343
|
+
readonly valid: true;
|
|
344
|
+
readonly ready: true;
|
|
345
|
+
readonly live: true;
|
|
346
|
+
readonly columns: readonly string[];
|
|
347
|
+
readonly expressions?: readonly string[];
|
|
348
|
+
readonly include?: readonly string[];
|
|
349
|
+
readonly nullsNotDistinct: boolean;
|
|
350
|
+
readonly opclass?: Readonly<Record<string, string>>;
|
|
351
|
+
readonly with?: Readonly<Record<string, string>>;
|
|
352
|
+
readonly where?: string;
|
|
353
|
+
};
|
|
354
|
+
/** A canonical SQL fact, never an unversioned deparse string. */
|
|
355
|
+
type CanonicalSqlFact = {
|
|
356
|
+
readonly canonicalFormVersion: 1;
|
|
357
|
+
readonly sql: string;
|
|
358
|
+
};
|
|
359
|
+
/**
|
|
360
|
+
* The default, identity, and expression facts are one discriminated state.
|
|
361
|
+
* In particular, an identity cannot also claim an authored/default sequence
|
|
362
|
+
* expression, and a missing default cannot carry an expression.
|
|
363
|
+
*/
|
|
364
|
+
type GeneratedColumnDefaultState = {
|
|
365
|
+
readonly defaultKind: 'none';
|
|
366
|
+
readonly hasDefault: false;
|
|
367
|
+
readonly identity: null;
|
|
368
|
+
readonly defaultExpression?: never;
|
|
369
|
+
} | {
|
|
370
|
+
readonly defaultKind: 'authored';
|
|
371
|
+
readonly hasDefault: true;
|
|
372
|
+
readonly identity: null;
|
|
373
|
+
readonly defaultExpression: CanonicalSqlFact;
|
|
374
|
+
} | {
|
|
375
|
+
readonly defaultKind: 'generated-sequence';
|
|
376
|
+
readonly hasDefault: true;
|
|
377
|
+
readonly identity: null;
|
|
378
|
+
readonly defaultExpression?: never;
|
|
379
|
+
} | {
|
|
380
|
+
readonly defaultKind: 'identity';
|
|
381
|
+
readonly hasDefault: false;
|
|
382
|
+
readonly identity: 'always' | 'byDefault';
|
|
383
|
+
readonly defaultExpression?: never;
|
|
384
|
+
};
|
|
385
|
+
type GeneratedColumnDeclaration = {
|
|
386
|
+
readonly type?: string;
|
|
387
|
+
readonly nullable?: boolean;
|
|
388
|
+
/** null means no COLLATE clause was authored; it is not an effective default. */
|
|
389
|
+
readonly authoredCollation?: string | null;
|
|
390
|
+
readonly default?: GeneratedColumnDefaultState;
|
|
391
|
+
};
|
|
392
|
+
type GeneratedTableColumnDeclaration = GeneratedColumnDeclaration & {
|
|
393
|
+
/** A table-shape member name, not the table target binding. */
|
|
394
|
+
readonly name: string;
|
|
395
|
+
};
|
|
396
|
+
type GeneratedIndexDeclaration = Omit<GeneratedIndexPostcondition, 'schema' | 'table' | 'name' | 'expressions' | 'where'> & {
|
|
397
|
+
readonly expressions?: readonly CanonicalSqlFact[];
|
|
398
|
+
readonly where?: CanonicalSqlFact;
|
|
399
|
+
};
|
|
400
|
+
type GeneratedConstraintDeclaration = Extract<GeneratedConstraintPostcondition, {
|
|
401
|
+
readonly type: 'p' | 'u';
|
|
402
|
+
}> | Extract<GeneratedConstraintPostcondition, {
|
|
403
|
+
readonly type: 'f';
|
|
404
|
+
}>;
|
|
405
|
+
/** Table names live only in TargetBinding; columns describe table structure. */
|
|
406
|
+
type V3TableDeclaration = {
|
|
407
|
+
readonly kind: 'table';
|
|
408
|
+
readonly columns: readonly GeneratedTableColumnDeclaration[];
|
|
409
|
+
};
|
|
410
|
+
/** Column names live only in TargetBinding; this is the column's shape. */
|
|
411
|
+
type V3ColumnDeclaration = {
|
|
412
|
+
readonly kind: 'column';
|
|
413
|
+
readonly column: GeneratedColumnDeclaration;
|
|
414
|
+
};
|
|
415
|
+
/** Constraint names live only in TargetBinding; this is a non-CHECK constraint fact. */
|
|
416
|
+
type V3ConstraintDeclaration = {
|
|
417
|
+
readonly kind: 'constraint';
|
|
418
|
+
readonly constraint: GeneratedConstraintDeclaration;
|
|
419
|
+
};
|
|
420
|
+
/** CHECK names live only in TargetBinding; expression is canonical and versioned. */
|
|
421
|
+
type V3CheckDeclaration = {
|
|
422
|
+
readonly kind: 'check';
|
|
423
|
+
readonly check: {
|
|
424
|
+
readonly expression: CanonicalSqlFact;
|
|
425
|
+
readonly notValid: boolean;
|
|
426
|
+
};
|
|
427
|
+
};
|
|
428
|
+
/** Index schema, table, and name live only in TargetBinding; options are structured facts. */
|
|
429
|
+
type V3IndexDeclaration = {
|
|
430
|
+
readonly kind: 'index';
|
|
431
|
+
readonly index: GeneratedIndexDeclaration;
|
|
432
|
+
};
|
|
433
|
+
/** Enum names live only in TargetBinding; labels are the declaration. */
|
|
434
|
+
type V3EnumDeclaration = {
|
|
435
|
+
readonly kind: 'enum';
|
|
436
|
+
readonly labels: readonly string[];
|
|
437
|
+
};
|
|
438
|
+
/** Sequence names live only in TargetBinding; options are the declaration. */
|
|
439
|
+
type V3SequenceDeclaration = {
|
|
440
|
+
readonly kind: 'sequence';
|
|
441
|
+
readonly startValue?: string;
|
|
442
|
+
readonly incrementBy?: string;
|
|
443
|
+
readonly minValue?: string;
|
|
444
|
+
readonly maxValue?: string;
|
|
445
|
+
readonly cycle?: boolean;
|
|
446
|
+
};
|
|
447
|
+
/** Extension names live only in TargetBinding; requested version is the declaration. */
|
|
448
|
+
type V3ExtensionDeclaration = {
|
|
449
|
+
readonly kind: 'extension';
|
|
450
|
+
readonly version?: string;
|
|
451
|
+
};
|
|
452
|
+
/** Address-free v3 declaration variants. */
|
|
453
|
+
type GeneratedPostconditionDeclarationV3 = {
|
|
454
|
+
readonly canonicalFormVersion: 1;
|
|
455
|
+
} & (V3TableDeclaration | V3ColumnDeclaration | V3ConstraintDeclaration | V3CheckDeclaration | V3IndexDeclaration | V3EnumDeclaration | V3SequenceDeclaration | V3ExtensionDeclaration | {
|
|
456
|
+
readonly kind: 'absent';
|
|
457
|
+
});
|
|
458
|
+
/**
|
|
459
|
+
* The separate binding selects the surrounding managed step's canonical
|
|
460
|
+
* address. It is versioned independently so later verifiers can resolve it
|
|
461
|
+
* without teaching any declaration variant about physical addresses.
|
|
462
|
+
*/
|
|
463
|
+
type TargetBinding = {
|
|
464
|
+
readonly bindingVersion: 1;
|
|
465
|
+
readonly bindingKind: 'managed-step-address';
|
|
466
|
+
};
|
|
467
|
+
/** Version 3 carries an address-free declaration and a separately decoded binding. */
|
|
468
|
+
type GeneratedPostconditionV3 = {
|
|
469
|
+
readonly postconditionVersion: 3;
|
|
470
|
+
/** v3 kind lives only in the address-free declaration, never beside the binding. */
|
|
471
|
+
readonly kind?: never;
|
|
472
|
+
readonly declaration: GeneratedPostconditionDeclarationV3;
|
|
473
|
+
readonly targetBinding: TargetBinding;
|
|
474
|
+
};
|
|
475
|
+
/** Only v3 is a decodable generated postcondition. Older values replan. */
|
|
476
|
+
type GeneratedPostcondition = GeneratedPostconditionV3;
|
|
477
|
+
/** The version tag is part of the digest domain, never an implicit convention. */
|
|
478
|
+
declare function generatedPostconditionDigest(value: {
|
|
479
|
+
readonly postconditionVersion: number;
|
|
480
|
+
}): string;
|
|
481
|
+
declare function generatedPostconditionForChange(input: {
|
|
482
|
+
readonly change: SchemaChange;
|
|
483
|
+
readonly schema: string;
|
|
484
|
+
}): _dbsp_types.LedgerPayload | undefined;
|
|
485
|
+
/**
|
|
486
|
+
* The only change-kind boundary between diagnostic schema diffing and managed
|
|
487
|
+
* execution. Keep it at manifest construction: diagnostic-only controls must
|
|
488
|
+
* never acquire an address, claim, reservation, or DDL bundle.
|
|
489
|
+
*/
|
|
490
|
+
declare function assertDeclarableChangeKind(kind: ChangeKind): asserts kind is Exclude<ChangeKind, 'enable_rls' | 'disable_rls' | 'create_policy' | 'drop_policy' | 'add_comment' | 'drop_comment' | 'alter_column_auto_increment'>;
|
|
491
|
+
/**
|
|
492
|
+
* PostgreSQL's total ChangeKind-to-address producer. The mapping is run at
|
|
493
|
+
* plan time, so no executable generator step can later fall through to a
|
|
494
|
+
* permissive "no managed address" branch.
|
|
495
|
+
*/
|
|
496
|
+
declare function createPgsqlGeneratedManagedStep(input: {
|
|
497
|
+
readonly change: SchemaChange;
|
|
498
|
+
readonly database: string;
|
|
499
|
+
readonly schema: string;
|
|
500
|
+
readonly stepKey: string;
|
|
501
|
+
readonly order: number;
|
|
502
|
+
readonly dependencyOrder?: readonly string[];
|
|
503
|
+
readonly statements: readonly string[];
|
|
504
|
+
}): NormalizedManagedStep;
|
|
505
|
+
/**
|
|
506
|
+
* The live differ is the shape comparator. Persist the exact authored table
|
|
507
|
+
* shape, rather than a boolean that could later be reinterpreted.
|
|
508
|
+
*/
|
|
509
|
+
declare function pgsqlDeclaredAdoptionDeclaration(table: TableIR): LedgerPayload;
|
|
510
|
+
/**
|
|
511
|
+
* Create the persisted, token-gated declaration that admits an already-live
|
|
512
|
+
* table into the managed ledger. It intentionally mirrors the historical
|
|
513
|
+
* generator lifecycle material so CLI plans retain their byte representation.
|
|
514
|
+
*/
|
|
515
|
+
declare function createPgsqlDeclaredAdoptionStep(input: {
|
|
516
|
+
readonly address: Address;
|
|
517
|
+
readonly table: TableIR;
|
|
518
|
+
readonly stepKey: string;
|
|
519
|
+
readonly order: number;
|
|
520
|
+
readonly catalogueIdentity: CatalogueIdentity;
|
|
521
|
+
}): NormalizedManagedStep;
|
|
522
|
+
declare function pgsqlDeclaredSequenceAdoptionDeclaration(sequence: SequenceIR): LedgerPayload;
|
|
523
|
+
/** Creates the token-gated adoption claim for a physical standalone sequence. */
|
|
524
|
+
declare function createPgsqlDeclaredSequenceAdoptionStep(input: {
|
|
525
|
+
readonly address: Address;
|
|
526
|
+
readonly sequence: SequenceIR;
|
|
527
|
+
readonly stepKey: string;
|
|
528
|
+
readonly order: number;
|
|
529
|
+
readonly catalogueIdentity: CatalogueIdentity;
|
|
530
|
+
}): NormalizedManagedStep;
|
|
531
|
+
|
|
532
|
+
type GeneratedPostconditionQuery = {
|
|
533
|
+
query(sql: string, params?: readonly unknown[]): Promise<{
|
|
534
|
+
readonly rows: readonly Record<string, unknown>[];
|
|
535
|
+
}>;
|
|
536
|
+
};
|
|
537
|
+
declare const generatedPostconditionSessionBrand: unique symbol;
|
|
538
|
+
/** An adapter-minted, exclusive PostgreSQL session for rollback-only proof. */
|
|
539
|
+
type GeneratedPostconditionSession = GeneratedPostconditionQuery & {
|
|
540
|
+
readonly [generatedPostconditionSessionBrand]: true;
|
|
541
|
+
};
|
|
542
|
+
/** A retained session capability was used after its owning bracket ended. */
|
|
543
|
+
declare class GeneratedPostconditionSessionDeactivatedError extends Error {
|
|
544
|
+
constructor();
|
|
545
|
+
}
|
|
546
|
+
/** A caller attempted to overlap rollback-only proofs on one capability. */
|
|
547
|
+
declare class GeneratedPostconditionProofInFlightError extends Error {
|
|
548
|
+
constructor();
|
|
549
|
+
}
|
|
550
|
+
/** A session bracket completed while rollback-only proof work was still running. */
|
|
551
|
+
declare class GeneratedPostconditionWorkInFlightError extends Error {
|
|
552
|
+
constructor();
|
|
553
|
+
}
|
|
554
|
+
/**
|
|
555
|
+
* Public verifier checkout bracket. Scratch-backed proofs require the active
|
|
556
|
+
* role to hold database TEMP privilege; callers must preflight that capability
|
|
557
|
+
* before applying managed DDL whose postcondition needs scratch staging.
|
|
558
|
+
*/
|
|
559
|
+
declare function withGeneratedPostconditionSession<T>(executor: {
|
|
560
|
+
connect(): Promise<GeneratedPostconditionQuery & {
|
|
561
|
+
release(error?: unknown): void | Promise<void>;
|
|
562
|
+
}>;
|
|
563
|
+
}, work: (session: GeneratedPostconditionSession) => Promise<T>, lockTimeoutMs?: number): Promise<T>;
|
|
564
|
+
type ResolvableGeneratedPostconditionKind = 'table' | 'column' | 'constraint';
|
|
565
|
+
type GeneratedPostconditionBindingKind = ResolvableGeneratedPostconditionKind | 'index' | 'enum' | 'sequence' | 'extension';
|
|
566
|
+
type GeneratedPostconditionSchemaBindingKind = Exclude<GeneratedPostconditionBindingKind, 'extension'>;
|
|
567
|
+
type GeneratedPostconditionTableChildKind = 'column' | 'index' | 'constraint';
|
|
568
|
+
/** The canonical schema-scoped table parent of a managed table child. */
|
|
569
|
+
type GeneratedPostconditionTableParent = {
|
|
570
|
+
readonly scope: 'schema';
|
|
571
|
+
readonly engine: string;
|
|
572
|
+
readonly database: string;
|
|
573
|
+
readonly schema: string;
|
|
574
|
+
readonly kind: 'table';
|
|
575
|
+
readonly name: string;
|
|
576
|
+
readonly parent?: never;
|
|
577
|
+
readonly catalogueIdentity?: never;
|
|
578
|
+
readonly qualifiedBy?: never;
|
|
579
|
+
};
|
|
580
|
+
type GeneratedPostconditionSchemaRootAddress<K extends Exclude<GeneratedPostconditionSchemaBindingKind, GeneratedPostconditionTableChildKind>> = Omit<ResourceAddress, 'engine' | 'schema' | 'parent' | 'kind'> & {
|
|
581
|
+
readonly engine: string;
|
|
582
|
+
readonly scope: 'schema';
|
|
583
|
+
readonly schema: string;
|
|
584
|
+
readonly parent?: never;
|
|
585
|
+
readonly kind: K;
|
|
586
|
+
};
|
|
587
|
+
type GeneratedPostconditionTableChildAddress<K extends GeneratedPostconditionTableChildKind> = Omit<ResourceAddress, 'engine' | 'schema' | 'parent' | 'kind'> & {
|
|
588
|
+
readonly engine: string;
|
|
589
|
+
readonly scope: 'schema';
|
|
590
|
+
readonly schema: string;
|
|
591
|
+
readonly parent: GeneratedPostconditionTableParent;
|
|
592
|
+
readonly kind: K;
|
|
593
|
+
};
|
|
594
|
+
type GeneratedPostconditionExtensionAddress = Omit<ResourceAddress, 'engine' | 'schema' | 'parent' | 'kind'> & {
|
|
595
|
+
readonly engine: string;
|
|
596
|
+
readonly scope: 'database';
|
|
597
|
+
readonly schema?: never;
|
|
598
|
+
readonly parent?: never;
|
|
599
|
+
readonly kind: 'extension';
|
|
600
|
+
};
|
|
601
|
+
/** The complete topology selected by a v3 managed-step binding. */
|
|
602
|
+
type GeneratedPostconditionBindingAddress = GeneratedPostconditionSchemaRootAddress<'table' | 'enum' | 'sequence'> | GeneratedPostconditionTableChildAddress<GeneratedPostconditionTableChildKind> | GeneratedPostconditionExtensionAddress;
|
|
603
|
+
declare class GeneratedPostconditionBindingResolutionError extends Error {
|
|
604
|
+
readonly sought: string;
|
|
605
|
+
readonly found: string;
|
|
606
|
+
constructor(input: {
|
|
607
|
+
readonly sought: string;
|
|
608
|
+
readonly found: string;
|
|
609
|
+
}, options?: ErrorOptions);
|
|
610
|
+
}
|
|
611
|
+
/**
|
|
612
|
+
* Narrows a ledger address into the complete topology that a v3 verifier can
|
|
613
|
+
* bind. Ledger addresses are intentionally broader, so this boundary must
|
|
614
|
+
* reject malformed persisted input before it reaches any verifier dispatch.
|
|
615
|
+
*/
|
|
616
|
+
declare function toGeneratedPostconditionBindingAddress(address: LedgerAddress): GeneratedPostconditionBindingAddress;
|
|
617
|
+
type IndexProjection = {
|
|
618
|
+
readonly schema: string;
|
|
619
|
+
readonly table: string;
|
|
620
|
+
readonly name: string;
|
|
621
|
+
readonly method: string;
|
|
622
|
+
readonly unique: boolean;
|
|
623
|
+
readonly valid: boolean;
|
|
624
|
+
readonly ready: boolean;
|
|
625
|
+
readonly live: boolean;
|
|
626
|
+
readonly nullsNotDistinct: boolean;
|
|
627
|
+
readonly primary: boolean;
|
|
628
|
+
readonly exclusion: boolean;
|
|
629
|
+
readonly immediate: boolean;
|
|
630
|
+
readonly constraintOwned: boolean;
|
|
631
|
+
readonly keyColumns: readonly (string | null)[];
|
|
632
|
+
readonly keyDefinitions: readonly string[];
|
|
633
|
+
readonly includeColumns: readonly string[];
|
|
634
|
+
readonly opclasses: readonly string[];
|
|
635
|
+
readonly keyOptions: readonly string[];
|
|
636
|
+
readonly reloptions: readonly string[];
|
|
637
|
+
readonly predicate: string | null;
|
|
638
|
+
};
|
|
639
|
+
type CheckProjection = {
|
|
640
|
+
readonly expression: string;
|
|
641
|
+
readonly validated: boolean;
|
|
642
|
+
readonly noInherit: boolean;
|
|
643
|
+
readonly enforced: boolean;
|
|
644
|
+
readonly isLocal: boolean;
|
|
645
|
+
readonly inheritanceCount: number;
|
|
646
|
+
readonly parentId: number;
|
|
647
|
+
};
|
|
648
|
+
type TableColumnProjection = {
|
|
649
|
+
readonly name: string;
|
|
650
|
+
readonly type: string;
|
|
651
|
+
readonly nullable: boolean;
|
|
652
|
+
readonly default: string | undefined;
|
|
653
|
+
/** Ownership and canonical nextval shape read in the same catalogue snapshot. */
|
|
654
|
+
readonly generatedSequenceDefault: boolean;
|
|
655
|
+
readonly collation: string | null;
|
|
656
|
+
readonly identity: 'always' | 'byDefault' | null;
|
|
657
|
+
};
|
|
658
|
+
type TableProjection = {
|
|
659
|
+
readonly columns: readonly TableColumnProjection[];
|
|
660
|
+
};
|
|
661
|
+
type GeneratedColumnProjection = Omit<TableColumnProjection, 'name'>;
|
|
662
|
+
declare class GeneratedPostconditionReplanRequiredError extends Error {
|
|
663
|
+
readonly code = "REPLAN_REQUIRED";
|
|
664
|
+
readonly diagnostic: Readonly<{
|
|
665
|
+
versionSeen: unknown;
|
|
666
|
+
stepIdentity: string | undefined;
|
|
667
|
+
structuralPath: string | undefined;
|
|
668
|
+
}>;
|
|
669
|
+
readonly structuralPath: string | undefined;
|
|
670
|
+
constructor(message: string, versionSeen?: unknown, stepIdentity?: string | undefined, options?: ErrorOptions, structuralPath?: string | undefined);
|
|
671
|
+
}
|
|
672
|
+
/**
|
|
673
|
+
* Decode exactly one postcondition interpretation per version: only v3 is
|
|
674
|
+
* accepted. v1/v2 and every other value are named REPLAN_REQUIRED outcomes.
|
|
675
|
+
*/
|
|
676
|
+
declare function decodeGeneratedPostcondition(value: unknown, stepIdentity?: string): GeneratedPostcondition;
|
|
677
|
+
/**
|
|
678
|
+
* The persisted digest is bound to the versioned wire value before decoding.
|
|
679
|
+
* A digest minted for one version cannot authenticate another version body.
|
|
680
|
+
*/
|
|
681
|
+
declare function decodeGeneratedPostconditionPayload(payload: {
|
|
682
|
+
readonly value: unknown;
|
|
683
|
+
readonly digest: string;
|
|
684
|
+
}, stepIdentity?: string): GeneratedPostcondition;
|
|
685
|
+
/** Refuse structural lookalikes before any proof or catalogue read. */
|
|
686
|
+
declare function assertGeneratedPostconditionSession(value: unknown): GeneratedPostconditionSession;
|
|
687
|
+
type GeneratedPostconditionCatalogueIdentity = NonNullable<ResourceAddress['catalogueIdentity']>;
|
|
688
|
+
/** Resolves the v3 table binding, then delegates its shared structural proof. */
|
|
689
|
+
declare function verifyGeneratedTablePostcondition(input: {
|
|
690
|
+
readonly session: GeneratedPostconditionSession;
|
|
691
|
+
readonly postcondition: unknown;
|
|
692
|
+
readonly address: GeneratedPostconditionBindingAddress;
|
|
693
|
+
}): Promise<{
|
|
694
|
+
readonly kind: 'table';
|
|
695
|
+
readonly projection: TableProjection;
|
|
696
|
+
readonly catalogueIdentity: GeneratedPostconditionCatalogueIdentity;
|
|
697
|
+
}>;
|
|
698
|
+
/** Resolves the v3 column binding, then delegates its shared structural proof. */
|
|
699
|
+
declare function verifyGeneratedColumnPostcondition(input: {
|
|
700
|
+
readonly session: GeneratedPostconditionSession;
|
|
701
|
+
readonly postcondition: unknown;
|
|
702
|
+
readonly address: GeneratedPostconditionBindingAddress;
|
|
703
|
+
}): Promise<{
|
|
704
|
+
readonly kind: 'column';
|
|
705
|
+
readonly projection: GeneratedColumnProjection;
|
|
706
|
+
readonly catalogueIdentity: GeneratedPostconditionCatalogueIdentity;
|
|
707
|
+
}>;
|
|
708
|
+
/** Resolves the v3 index binding, then delegates its shared structural proof. */
|
|
709
|
+
declare function verifyGeneratedIndexPostcondition(input: {
|
|
710
|
+
readonly session: GeneratedPostconditionSession;
|
|
711
|
+
readonly postcondition: unknown;
|
|
712
|
+
readonly address: GeneratedPostconditionBindingAddress;
|
|
713
|
+
}): Promise<{
|
|
714
|
+
readonly kind: 'index';
|
|
715
|
+
readonly projection: IndexProjection;
|
|
716
|
+
readonly catalogueIdentity: GeneratedPostconditionCatalogueIdentity;
|
|
717
|
+
}>;
|
|
718
|
+
/** Resolves the v3 CHECK binding, then delegates its shared structural proof. */
|
|
719
|
+
declare function verifyGeneratedCheckPostcondition(input: {
|
|
720
|
+
readonly session: GeneratedPostconditionSession;
|
|
721
|
+
readonly postcondition: unknown;
|
|
722
|
+
readonly address: GeneratedPostconditionBindingAddress;
|
|
723
|
+
}): Promise<{
|
|
724
|
+
readonly kind: 'constraint';
|
|
725
|
+
readonly projection: CheckProjection;
|
|
726
|
+
readonly catalogueIdentity: GeneratedPostconditionCatalogueIdentity;
|
|
727
|
+
}>;
|
|
728
|
+
/**
|
|
729
|
+
* Binds the deliberately non-structural v3 kinds under the same rollback-only
|
|
730
|
+
* proof bracket as structural verifiers. The declaration kind is the binding
|
|
731
|
+
* expectation, so a sequence slot can never observe an enum declaration (or
|
|
732
|
+
* vice versa) merely because the address happens to resolve.
|
|
733
|
+
*/
|
|
734
|
+
declare function verifyGeneratedIdentityPostcondition(input: {
|
|
735
|
+
readonly session: GeneratedPostconditionSession;
|
|
736
|
+
readonly postcondition: unknown;
|
|
737
|
+
readonly address: GeneratedPostconditionBindingAddress;
|
|
738
|
+
readonly kind: 'constraint' | 'enum' | 'sequence' | 'extension';
|
|
739
|
+
}): Promise<{
|
|
740
|
+
readonly kind: 'constraint' | 'enum' | 'sequence' | 'extension';
|
|
741
|
+
readonly identity: Readonly<{
|
|
742
|
+
readonly relationOid: string;
|
|
743
|
+
readonly objectOid?: string;
|
|
744
|
+
}>;
|
|
745
|
+
readonly catalogueIdentity: GeneratedPostconditionCatalogueIdentity;
|
|
746
|
+
}>;
|
|
747
|
+
|
|
748
|
+
/**
|
|
749
|
+
* PostgreSQL Schema Introspection (ADAPTER-006)
|
|
750
|
+
*
|
|
751
|
+
* Queries information_schema/pg_catalog to build ModelIR
|
|
752
|
+
* from an existing database. Supports:
|
|
753
|
+
* - Table/column/PK discovery
|
|
754
|
+
* - FK → bidirectional relation inference
|
|
755
|
+
* - Hierarchy detection (adjacency + edge-table)
|
|
756
|
+
* - Include/exclude filtering
|
|
757
|
+
*
|
|
758
|
+
* @module introspection
|
|
759
|
+
*/
|
|
760
|
+
|
|
761
|
+
/** The minimum every schema-level operation needs: which schema. */
|
|
762
|
+
interface SchemaScopeOptions {
|
|
763
|
+
/** Schema name to operate on (default: 'public') */
|
|
764
|
+
readonly schema?: string;
|
|
765
|
+
}
|
|
766
|
+
/**
|
|
767
|
+
* Introspection additionally chooses WHICH TABLES to read. It is a read-only
|
|
768
|
+
* path, so narrowing it is safe — that is why the table filters live here and
|
|
769
|
+
* nowhere else.
|
|
770
|
+
*/
|
|
771
|
+
interface IntrospectionOptions extends SchemaScopeOptions {
|
|
772
|
+
/** Tables to exclude (glob patterns: * matches any chars) */
|
|
773
|
+
readonly exclude?: readonly string[];
|
|
774
|
+
/** Tables to include (default: all). Applied before exclude. */
|
|
775
|
+
readonly include?: readonly string[];
|
|
776
|
+
}
|
|
777
|
+
/** Hierarchy pattern detected during introspection */
|
|
778
|
+
/**
|
|
779
|
+
* Hierarchy pattern detected during introspection.
|
|
780
|
+
* Alias of {@link HierarchyIR} from \@dbsp/types — kept here for
|
|
781
|
+
* public-API backwards compatibility (re-exported from \@dbsp/adapter-pgsql).
|
|
782
|
+
*/
|
|
783
|
+
type DetectedHierarchy = HierarchyIR;
|
|
784
|
+
/** Extended ModelIR with hierarchy metadata */
|
|
785
|
+
interface IntrospectedModelIR extends ModelIR {
|
|
786
|
+
readonly hierarchies: readonly DetectedHierarchy[];
|
|
787
|
+
readonly introspectedAt: Date;
|
|
788
|
+
readonly warnings: readonly string[];
|
|
789
|
+
}
|
|
790
|
+
/**
|
|
791
|
+
* Introspect a database through a pool.
|
|
792
|
+
*
|
|
793
|
+
* This does NOT accept a checked-out `PoolClient`, and that is deliberate. A
|
|
794
|
+
* client may be sitting inside a transaction that belongs to its owner, and a
|
|
795
|
+
* catalog query that fails there aborts *their* transaction. Protecting that
|
|
796
|
+
* needs a savepoint, and knowing whether to take one needs the caller to say
|
|
797
|
+
* whose transaction it is — which is what `PgsqlAdapter`'s `borrowedClient`
|
|
798
|
+
* declaration is for. Guessing it from the object's shape is the exact defect
|
|
799
|
+
* this adapter was rewritten to remove.
|
|
800
|
+
*
|
|
801
|
+
* Saying so in a comment is not enough: `CatalogQueryExecutor` is structural, so
|
|
802
|
+
* a `PoolClient` — which has a `query()` — satisfies it, and the prose would have
|
|
803
|
+
* been the only thing standing in the way. It is branded instead, and only the
|
|
804
|
+
* adapter's own protected executor carries the brand. A client cannot be passed
|
|
805
|
+
* here at all.
|
|
806
|
+
*
|
|
807
|
+
* So: hold a client, use `new PgsqlAdapter(client, { borrowedClient: true })`
|
|
808
|
+
* and call `.introspect()` on it.
|
|
809
|
+
*/
|
|
810
|
+
declare function introspect(pool: Pool, options?: IntrospectionOptions): Promise<IntrospectedModelIR>;
|
|
811
|
+
|
|
812
|
+
type PgPhysicalModelInput = {
|
|
813
|
+
readonly mode: 'logical';
|
|
814
|
+
readonly model: ModelIR;
|
|
815
|
+
readonly schema: string;
|
|
816
|
+
readonly dbCasing?: DbCasing;
|
|
817
|
+
readonly naming?: NamingPlugin;
|
|
818
|
+
readonly fkAutoIndex?: boolean;
|
|
819
|
+
} | {
|
|
820
|
+
readonly mode: 'physical';
|
|
821
|
+
readonly model: ModelIR;
|
|
822
|
+
readonly schema: string;
|
|
823
|
+
readonly fkAutoIndex?: boolean;
|
|
824
|
+
};
|
|
825
|
+
type PgPhysicalNamespace = 'pg_class' | 'pg_type' | 'column' | 'constraint' | 'policy';
|
|
826
|
+
interface PgPhysicalNameClaim {
|
|
827
|
+
readonly namespace: PgPhysicalNamespace;
|
|
828
|
+
readonly schema: string;
|
|
829
|
+
readonly table?: string;
|
|
830
|
+
readonly physicalName: string;
|
|
831
|
+
readonly logicalOrigin: string;
|
|
832
|
+
}
|
|
833
|
+
interface PgPhysicalNameCollision {
|
|
834
|
+
readonly namespace: PgPhysicalNamespace;
|
|
835
|
+
readonly schema: string;
|
|
836
|
+
readonly table?: string;
|
|
837
|
+
readonly physicalName: string;
|
|
838
|
+
readonly first: PgPhysicalNameClaim;
|
|
839
|
+
readonly second: PgPhysicalNameClaim;
|
|
840
|
+
}
|
|
841
|
+
declare class PgPhysicalNameCollisionError extends Error {
|
|
842
|
+
readonly collision: PgPhysicalNameCollision;
|
|
843
|
+
constructor(collision: PgPhysicalNameCollision);
|
|
844
|
+
get namespace(): PgPhysicalNamespace;
|
|
845
|
+
get schema(): string;
|
|
846
|
+
get table(): string | undefined;
|
|
847
|
+
get physicalName(): string;
|
|
848
|
+
get first(): PgPhysicalNameClaim;
|
|
849
|
+
get second(): PgPhysicalNameClaim;
|
|
850
|
+
}
|
|
851
|
+
/** Refusal raised before a physical model starts inspecting its input model. */
|
|
852
|
+
declare class PgPhysicalModelInputError extends Error {
|
|
853
|
+
readonly reason: 'schema' | 'mode-options';
|
|
854
|
+
constructor(reason: 'schema' | 'mode-options');
|
|
855
|
+
}
|
|
856
|
+
interface PgPhysicalModel {
|
|
857
|
+
readonly mode: 'logical' | 'physical';
|
|
858
|
+
readonly schema: string;
|
|
859
|
+
readonly fkAutoIndex: boolean;
|
|
860
|
+
readonly model: ModelIR;
|
|
861
|
+
readonly inventory: PhysicalNameInventory;
|
|
862
|
+
readonly claims: readonly PgPhysicalNameClaim[];
|
|
863
|
+
}
|
|
864
|
+
/** Builds the sole PostgreSQL physical spelling of one model without rendering SQL. */
|
|
865
|
+
declare function createPgPhysicalModel(input: PgPhysicalModelInput): PgPhysicalModel;
|
|
866
|
+
|
|
867
|
+
type PgsqlTransactionTimeoutParameter = 'lock_timeout' | 'statement_timeout';
|
|
868
|
+
|
|
869
|
+
/**
|
|
870
|
+
* PgsqlAdapter - Implements the Adapter interface for PostgreSQL using native pg driver.
|
|
871
|
+
*
|
|
872
|
+
* This adapter wraps a pg Pool instance and provides the unified
|
|
873
|
+
* adapter interface for the db-semantic-planner ORM.
|
|
874
|
+
*
|
|
875
|
+
* @module pgsql-adapter
|
|
876
|
+
*/
|
|
877
|
+
|
|
878
|
+
declare const rollbackOnlyPgsqlScopeBrand: unique symbol;
|
|
879
|
+
/** A scope minted by withScratchScope and guaranteed to roll back on success. */
|
|
880
|
+
type RollbackOnlyPgsqlScope<DB = unknown> = PgsqlAdapter<DB> & {
|
|
881
|
+
readonly [rollbackOnlyPgsqlScopeBrand]: typeof rollbackOnlyPgsqlScopeBrand;
|
|
882
|
+
};
|
|
883
|
+
type PgAdvisoryLockKey = bigint | {
|
|
884
|
+
readonly classId: number;
|
|
885
|
+
readonly objId: number;
|
|
886
|
+
};
|
|
887
|
+
type PgAdvisoryLockResult<T> = {
|
|
888
|
+
readonly acquired: true;
|
|
889
|
+
readonly value: T;
|
|
890
|
+
} | {
|
|
891
|
+
readonly acquired: false;
|
|
892
|
+
};
|
|
893
|
+
declare class PgsqlRawSqlTransactionControlError extends Error {
|
|
894
|
+
readonly dbspRawSqlTransactionControl = true;
|
|
895
|
+
constructor(cause: unknown);
|
|
896
|
+
}
|
|
897
|
+
declare class PgsqlTransactionAbortedCommitError extends Error {
|
|
898
|
+
readonly dbspTransactionAbortedCommit = true;
|
|
899
|
+
constructor(cause: unknown);
|
|
900
|
+
}
|
|
901
|
+
declare class PgsqlTransactionAbortedError extends Error {
|
|
902
|
+
readonly dbspTransactionAborted = true;
|
|
903
|
+
constructor(cause: unknown);
|
|
904
|
+
}
|
|
905
|
+
/**
|
|
906
|
+
* Raised when a pool-owned top-level transaction is aborted through
|
|
907
|
+
* `TransactionOptions.signal`. If the signal aborts while `pool.connect()` is
|
|
908
|
+
* still pending, dbsp honors it only after a client is acquired.
|
|
909
|
+
*/
|
|
910
|
+
declare class PgsqlTransactionAbortSignalError extends Error {
|
|
911
|
+
readonly dbspTransactionAbortSignal = true;
|
|
912
|
+
constructor();
|
|
913
|
+
}
|
|
914
|
+
declare class PgsqlPinnedConnectionAbortSignalError extends Error {
|
|
915
|
+
readonly dbspPinnedConnectionAbortSignal = true;
|
|
916
|
+
constructor();
|
|
917
|
+
}
|
|
918
|
+
declare class PgsqlTransactionOptionsError extends Error {
|
|
919
|
+
readonly dbspTransactionOptions = true;
|
|
920
|
+
constructor(message: string);
|
|
921
|
+
}
|
|
922
|
+
declare class PgsqlAdvisoryLockOptionsError extends Error {
|
|
923
|
+
readonly dbspAdvisoryLockOptions = true;
|
|
924
|
+
constructor(message: string);
|
|
925
|
+
}
|
|
926
|
+
/**
|
|
927
|
+
* Raised when a statement inside a dbsp-managed transaction fails with a SQLSTATE
|
|
928
|
+
* that matches a timeout the caller configured for that transaction: `55P03`
|
|
929
|
+
* (`lock_not_available`) when `lockTimeoutMs` was set, or `57014` (`query_canceled`)
|
|
930
|
+
* when `statementTimeoutMs` was set. The original PostgreSQL error is preserved as
|
|
931
|
+
* `cause`.
|
|
932
|
+
*
|
|
933
|
+
* Classification is by SQLSTATE only. PostgreSQL assigns these codes to the OUTCOME,
|
|
934
|
+
* not the cause: `55P03` is also raised by `FOR UPDATE NOWAIT`, and `57014` is also
|
|
935
|
+
* raised by an external cancel (e.g. `pg_cancel_backend`). There is no locale-stable
|
|
936
|
+
* structured field that separates the timeout from the other cause, so the message
|
|
937
|
+
* text is deliberately NOT parsed. dbsp never emits `NOWAIT` itself, so a `55P03`
|
|
938
|
+
* here is the configured `lock_timeout` unless the caller's own raw SQL used
|
|
939
|
+
* `NOWAIT`; a `57014` is the configured `statement_timeout` unless the backend was
|
|
940
|
+
* cancelled from outside. Inspect `cause` when that distinction matters.
|
|
941
|
+
*/
|
|
942
|
+
declare class PgsqlTransactionTimeoutError extends Error {
|
|
943
|
+
readonly timeout: PgsqlTransactionTimeoutParameter;
|
|
944
|
+
readonly dbspTransactionTimeout = true;
|
|
945
|
+
constructor(cause: unknown, timeout: PgsqlTransactionTimeoutParameter);
|
|
946
|
+
}
|
|
947
|
+
/**
|
|
948
|
+
* Raised when the single safe unnamed replay after a prepared-statement
|
|
949
|
+
* infrastructure failure also fails. `message` is always the safe constant
|
|
950
|
+
* `Prepared statement recovery replay failed.`; `cause` is the replay error;
|
|
951
|
+
* `infrastructureError` is the original infrastructure error; and
|
|
952
|
+
* `admissionFingerprint` identifies the admitted statement. DBSP-authored
|
|
953
|
+
* messages carry no parameter values; preserved upstream errors, including the
|
|
954
|
+
* standard Error `cause`, are unsanitized.
|
|
955
|
+
*/
|
|
956
|
+
declare class PgsqlPreparedStatementReplayError extends Error {
|
|
957
|
+
readonly admissionFingerprint: string;
|
|
958
|
+
readonly infrastructureError: unknown;
|
|
959
|
+
readonly dbspPreparedStatementReplay = true;
|
|
960
|
+
readonly originalInfrastructureError: unknown;
|
|
961
|
+
readonly originalError: unknown;
|
|
962
|
+
constructor(admissionFingerprint: string, infrastructureError: unknown, cause: unknown);
|
|
963
|
+
}
|
|
964
|
+
/**
|
|
965
|
+
* Options for PgsqlAdapter.
|
|
966
|
+
*/
|
|
967
|
+
interface PgsqlPreparedStatementsOptions {
|
|
968
|
+
/** Maximum distinct compiled statements admitted per executor (default: 500). */
|
|
969
|
+
readonly maxStatements?: number;
|
|
970
|
+
}
|
|
971
|
+
interface PgsqlAdapterOptions {
|
|
972
|
+
/** Schema name for multi-tenant queries */
|
|
973
|
+
readonly schemaName?: string;
|
|
974
|
+
/**
|
|
975
|
+
* DB column casing convention (intuitive semantics).
|
|
976
|
+
* - `'snake_case'`: DB columns are snake_case → transform to camelCase for JS
|
|
977
|
+
* - `'camelCase'`: DB columns are camelCase → no transformation
|
|
978
|
+
* - `'preserve'`: No transformation
|
|
979
|
+
*/
|
|
980
|
+
readonly dbCasing?: DbCasing;
|
|
981
|
+
/** Optional model for WHERE compilation */
|
|
982
|
+
readonly model?: ModelIR;
|
|
983
|
+
/** Optional logger for debug/error messages */
|
|
984
|
+
readonly logger?: AdapterLogger;
|
|
985
|
+
/** Default primary key column name for convention fallbacks (default: 'id') */
|
|
986
|
+
readonly defaultPkColumnName?: string;
|
|
987
|
+
/** Convention for deriving FK column names: (tableName, pkName) => fkColumnName */
|
|
988
|
+
readonly deriveFkColumnName?: FkColumnDerivation;
|
|
989
|
+
/**
|
|
990
|
+
* Opt in to node-postgres named prepared statements for compiled queries with
|
|
991
|
+
* parameters. `true` uses the default statement cap; an object overrides it.
|
|
992
|
+
*/
|
|
993
|
+
readonly preparedStatements?: boolean | PgsqlPreparedStatementsOptions;
|
|
994
|
+
}
|
|
995
|
+
interface PgsqlPoolAdapterOptionsBase extends PgsqlAdapterOptions {
|
|
996
|
+
readonly borrowedClient?: false;
|
|
997
|
+
}
|
|
998
|
+
type PgsqlPoolAdapterOptions = (PgsqlPoolAdapterOptionsBase & {
|
|
999
|
+
readonly replayInvalidatedPlans?: false | undefined;
|
|
1000
|
+
}) | (Omit<PgsqlPoolAdapterOptionsBase, 'preparedStatements'> & {
|
|
1001
|
+
readonly preparedStatements: true | PgsqlPreparedStatementsOptions;
|
|
1002
|
+
/**
|
|
1003
|
+
* Enable one unnamed replay after `0A000`/`RevalidateCachedQuery` only when
|
|
1004
|
+
* you assert that your statements do not invoke functions performing
|
|
1005
|
+
* effectful work before nested prepared-statement operations. This requires
|
|
1006
|
+
* `preparedStatements: true` (or a prepared-statements options object).
|
|
1007
|
+
*
|
|
1008
|
+
* Replay snapshots JSON-like values (finite numbers, strings, booleans,
|
|
1009
|
+
* `null`, arrays, plain or null-prototype objects) and clean `Date`/`Buffer`
|
|
1010
|
+
* instances. It excludes non-finite numbers, `undefined`, `bigint`, functions,
|
|
1011
|
+
* proxies, cycles, sparse arrays, accessors, symbol-valued
|
|
1012
|
+
* parameters, symbol keys on plain objects, exotic prototypes, custom built-ins,
|
|
1013
|
+
* and values with their own node-postgres
|
|
1014
|
+
* `toPostgres` behavior.
|
|
1015
|
+
* Serialization-irrelevant symbol metadata on arrays and Buffers is ignored.
|
|
1016
|
+
* The detached snapshot covers later mutations to the supplied value graph,
|
|
1017
|
+
* not built-in prototypes, timezone state, or node-postgres serialization
|
|
1018
|
+
* configuration; a process-global `toPostgres` or `toJSON` installed while
|
|
1019
|
+
* the call is in flight is outside the guarantee. Each capture or replay copy
|
|
1020
|
+
* is independently limited to 64 Ki visited values, 16 MiB of UTF-8 strings,
|
|
1021
|
+
* and 16 MiB of Buffer data. An ineligible or over-budget value still receives
|
|
1022
|
+
* the initial named submission, but disables transparent replay.
|
|
1023
|
+
* These budgets bound copied nodes and payload bytes; enumerating a plain
|
|
1024
|
+
* object's existing property table is proportional to the caller's own object.
|
|
1025
|
+
*
|
|
1026
|
+
* Replay needs the adapter-owned serialized physical client available from a
|
|
1027
|
+
* pool; it is therefore not supported by borrowed or compile-only adapters.
|
|
1028
|
+
*/
|
|
1029
|
+
readonly replayInvalidatedPlans: true;
|
|
1030
|
+
});
|
|
1031
|
+
interface PgsqlBorrowedClientAdapterOptions extends PgsqlAdapterOptions {
|
|
1032
|
+
/** Replay is only available to a pool-owned pinned scope. */
|
|
1033
|
+
readonly replayInvalidatedPlans?: never;
|
|
1034
|
+
/** This connection belongs to the caller. dbsp never releases it. */
|
|
1035
|
+
readonly borrowedClient: true;
|
|
1036
|
+
/**
|
|
1037
|
+
* Let dbsp run transactions on your connection, through a savepoint.
|
|
1038
|
+
*
|
|
1039
|
+
* When your connection is already inside a transaction, dbsp creates a
|
|
1040
|
+
* savepoint and rolls back dbsp's changes after that savepoint if the callback
|
|
1041
|
+
* fails. `RELEASE SAVEPOINT` does not commit; it merges the work into your
|
|
1042
|
+
* surrounding transaction, so a callback that succeeded is still undone if you
|
|
1043
|
+
* later roll back. Deferred constraints or triggers can still make your outer
|
|
1044
|
+
* `COMMIT` fail after dbsp has returned. `SET LOCAL` changes inside the callback
|
|
1045
|
+
* remain in effect for the rest of your transaction after the savepoint is
|
|
1046
|
+
* released. `ON COMMIT DROP` and `ON COMMIT DELETE ROWS` fire at your transaction
|
|
1047
|
+
* boundary, not at the savepoint. Sequences are not transactional:
|
|
1048
|
+
* `nextval`/`setval` are not reclaimed by a savepoint rollback. Session-level
|
|
1049
|
+
* advisory locks ignore rollback; transaction-level advisory locks taken by a
|
|
1050
|
+
* successful callback last until your transaction ends.
|
|
1051
|
+
*
|
|
1052
|
+
* Transaction control through raw SQL inside a scope dbsp is managing is
|
|
1053
|
+
* unsupported. `COMMIT`, `ROLLBACK`, and `PREPARE TRANSACTION` end the
|
|
1054
|
+
* transaction dbsp is working inside; dbsp detects that and fails loudly, but
|
|
1055
|
+
* the data is already whatever your statement made it. Raw savepoint control
|
|
1056
|
+
* (`SAVEPOINT`, `RELEASE SAVEPOINT`, `ROLLBACK TO SAVEPOINT`) can alter the
|
|
1057
|
+
* savepoint stack before dbsp sees the command tag; dbsp poisons the scope, but
|
|
1058
|
+
* it cannot make that command un-run. Manage your transaction outside dbsp's
|
|
1059
|
+
* calls.
|
|
1060
|
+
*/
|
|
1061
|
+
readonly managedTransactions?: true;
|
|
1062
|
+
}
|
|
1063
|
+
/** Options for a connectionless adapter, which cannot own replay serialization. */
|
|
1064
|
+
interface PgsqlCompileOnlyAdapterOptions extends PgsqlAdapterOptions {
|
|
1065
|
+
readonly replayInvalidatedPlans?: never;
|
|
1066
|
+
}
|
|
1067
|
+
/**
|
|
1068
|
+
* Adapter implementation for PostgreSQL using native pg driver.
|
|
1069
|
+
*
|
|
1070
|
+
* @typeParam DB - Database schema type
|
|
1071
|
+
*
|
|
1072
|
+
* @example
|
|
1073
|
+
* ```typescript
|
|
1074
|
+
* import { Pool } from 'pg';
|
|
1075
|
+
* import { createPgsqlAdapter } from '@dbsp/adapter-pgsql';
|
|
1076
|
+
*
|
|
1077
|
+
* const pool = new Pool({ connectionString: process.env.DATABASE_URL });
|
|
1078
|
+
* const adapter = createPgsqlAdapter(pool);
|
|
1079
|
+
* const orm = createOrm({ model, adapter });
|
|
1080
|
+
* ```
|
|
1081
|
+
*/
|
|
1082
|
+
declare class PgsqlAdapter<DB = unknown> implements Adapter<DB> {
|
|
1083
|
+
private readonly pool;
|
|
1084
|
+
private readonly client;
|
|
1085
|
+
private readonly borrowedClient;
|
|
1086
|
+
private readonly managedTransactions;
|
|
1087
|
+
private readonly adapterManagedTransaction;
|
|
1088
|
+
private readonly adapterManagedPinnedConnection;
|
|
1089
|
+
private readonly rollbackOnlyScope;
|
|
1090
|
+
private readonly scopeToken;
|
|
1091
|
+
private readonly scopeState;
|
|
1092
|
+
private readonly schemaName;
|
|
1093
|
+
private readonly _dbCasing;
|
|
1094
|
+
private readonly naming;
|
|
1095
|
+
private readonly model;
|
|
1096
|
+
private readonly logger;
|
|
1097
|
+
private readonly replayInvalidatedPlans;
|
|
1098
|
+
private readonly preparedStatements;
|
|
1099
|
+
private readonly preparedStatementRegistry;
|
|
1100
|
+
private readonly _capabilities;
|
|
1101
|
+
private readonly defaultPk;
|
|
1102
|
+
private readonly deriveFk;
|
|
1103
|
+
/**
|
|
1104
|
+
* Create a new PgsqlAdapter.
|
|
1105
|
+
*
|
|
1106
|
+
* Ownership of the connection is **declared**, never inferred. Handing over a
|
|
1107
|
+
* `PoolClient` means nothing on its own — it says the object has a `release()`
|
|
1108
|
+
* method, not that a transaction is open or that the caller owns the lifecycle.
|
|
1109
|
+
* Pass `borrowedClient: true` to say so.
|
|
1110
|
+
*
|
|
1111
|
+
* @param pool - a pg.Pool, a caller-owned pg.PoolClient (with `borrowedClient: true`),
|
|
1112
|
+
* or nothing at all for compile-only mode
|
|
1113
|
+
* @param options - configuration; declares connection ownership
|
|
1114
|
+
*/
|
|
1115
|
+
constructor(pool: Pool, options?: PgsqlPoolAdapterOptions);
|
|
1116
|
+
constructor(client: PoolClient, options: PgsqlBorrowedClientAdapterOptions);
|
|
1117
|
+
constructor(pool?: undefined, options?: PgsqlCompileOnlyAdapterOptions);
|
|
1118
|
+
/**
|
|
1119
|
+
* Shared compilation dependencies — built lazily from adapter fields.
|
|
1120
|
+
* Passed to compiler sub-modules instead of `this`.
|
|
1121
|
+
*/
|
|
1122
|
+
/**
|
|
1123
|
+
* Return a new PgsqlAdapterOptions that merges current config with overrides.
|
|
1124
|
+
* Ensures that all configuration fields (logger, defaultPkColumnName,
|
|
1125
|
+
* deriveFkColumnName, etc.) are propagated to scoped/transactional adapters.
|
|
1126
|
+
*/
|
|
1127
|
+
private cloneOptions;
|
|
1128
|
+
private buildCompileDeps;
|
|
1129
|
+
private requireNqlCompileModel;
|
|
1130
|
+
private assertNqlBindingNamesDisjointFromTables;
|
|
1131
|
+
private compileNqlMutation;
|
|
1132
|
+
private compileNqlBundleLeafEnvelope;
|
|
1133
|
+
private compileNqlBundle;
|
|
1134
|
+
/**
|
|
1135
|
+
* Returns the pool/client executor, or refuses a connectionless adapter.
|
|
1136
|
+
*/
|
|
1137
|
+
private requireConnection;
|
|
1138
|
+
/** Adapter capabilities for feature detection */
|
|
1139
|
+
get capabilities(): AdapterCapabilities;
|
|
1140
|
+
/** Per-instance connection state, distinct from PostgreSQL capabilities. */
|
|
1141
|
+
get connectionAvailability(): ConnectionAvailability;
|
|
1142
|
+
/** Side-effect-free execution availability for core feature detection. */
|
|
1143
|
+
executionAvailable(): boolean;
|
|
1144
|
+
/** PostgreSQL dialect capabilities for planner strategy selection */
|
|
1145
|
+
get dialectCapabilities(): DialectCapabilities;
|
|
1146
|
+
/**
|
|
1147
|
+
* DB column casing convention used by this adapter.
|
|
1148
|
+
*/
|
|
1149
|
+
get dbCasing(): DbCasing;
|
|
1150
|
+
/**
|
|
1151
|
+
* Get the underlying pg Pool or borrowed PoolClient instance.
|
|
1152
|
+
*
|
|
1153
|
+
* Exposing raw access from a pool-owned dbsp-managed scope permanently taints that
|
|
1154
|
+
* physical client: external callers can queue commands outside dbsp's statement
|
|
1155
|
+
* lock, so replay is disabled and dbsp destroys the client at scope release.
|
|
1156
|
+
* Expect pool churn; session state on that exposed connection does not survive the
|
|
1157
|
+
* release. A borrowed client remains caller-owned: dbsp never releases it, and the
|
|
1158
|
+
* caller decides its fate after raw exposure.
|
|
1159
|
+
*/
|
|
1160
|
+
getPoolInstance(): Pool | PoolClient;
|
|
1161
|
+
/**
|
|
1162
|
+
* Compile a plan to executable SQL.
|
|
1163
|
+
*
|
|
1164
|
+
* When passed a direct `CompiledNqlQuery`, the adapter trusts that the bundle
|
|
1165
|
+
* has already been semantically validated by the NQL compiler. This method
|
|
1166
|
+
* still performs adapter-owned SQL safety checks for emitted binding names
|
|
1167
|
+
* before CTE emission.
|
|
1168
|
+
*/
|
|
1169
|
+
compile<T = unknown>(plan: PlanReport | CompiledNqlQuery, options?: CompileOptions): CompiledQuery<T>;
|
|
1170
|
+
/**
|
|
1171
|
+
* Compile a plan with includes, returning subquery include metadata (DX-033).
|
|
1172
|
+
*/
|
|
1173
|
+
compileWithIncludes<T = unknown>(plan: PlanReport, options?: CompileOptions): CompileResultWithIncludes<T>;
|
|
1174
|
+
/**
|
|
1175
|
+
* Compile a subquery include query for given parent IDs (DX-033).
|
|
1176
|
+
* Generates: SELECT * FROM targetTable WHERE foreignKey IN ($1, $2, ...)
|
|
1177
|
+
*
|
|
1178
|
+
* @param info - Subquery include metadata
|
|
1179
|
+
* @param parentIds - Parent record IDs to fetch related records for
|
|
1180
|
+
* @param options - Compile options
|
|
1181
|
+
* @returns Compiled query for fetching related records
|
|
1182
|
+
*/
|
|
1183
|
+
compileSubqueryInclude(info: SubqueryIncludeInfo, parentIds: readonly unknown[], options?: CompileOptions): CompiledQuery;
|
|
1184
|
+
/**
|
|
1185
|
+
* Compile a FROM-less SELECT expression to SQL.
|
|
1186
|
+
*
|
|
1187
|
+
* Produces: SELECT <expr>
|
|
1188
|
+
* Example: SELECT nextval('my_seq')
|
|
1189
|
+
*
|
|
1190
|
+
* @param expr - ExpressionIntent to evaluate
|
|
1191
|
+
* @returns Compiled SQL and parameters
|
|
1192
|
+
*/
|
|
1193
|
+
compileSelectExpression<T = unknown>(expr: ExpressionIntent): CompiledQuery<T>;
|
|
1194
|
+
/**
|
|
1195
|
+
* Compile an insert intent to executable SQL.
|
|
1196
|
+
*
|
|
1197
|
+
* Strategy switch (per CompileOptions):
|
|
1198
|
+
* - rows <= batchThreshold (default 50): VALUES ($1,$2),($3,$4),...
|
|
1199
|
+
* - rows > batchThreshold OR batchThreshold === 0: SELECT unnest($1::type[]),...
|
|
1200
|
+
*/
|
|
1201
|
+
compileInsert(intent: InsertIntent, options?: CompileOptions): CompiledQuery;
|
|
1202
|
+
/**
|
|
1203
|
+
* Compile an insert-from intent to executable SQL (NQL-ALIGN).
|
|
1204
|
+
* INSERT INTO target (cols) SELECT cols FROM source WHERE ... LIMIT ... RETURNING ...
|
|
1205
|
+
*/
|
|
1206
|
+
compileInsertFrom(intent: InsertFromIntent, options?: CompileOptions): CompiledQuery;
|
|
1207
|
+
/**
|
|
1208
|
+
* Compile an update intent to executable SQL.
|
|
1209
|
+
*/
|
|
1210
|
+
compileUpdate(intent: UpdateIntent, options?: CompileOptions): CompiledQuery;
|
|
1211
|
+
/**
|
|
1212
|
+
* Compile a batch update intent to executable SQL using unnest FROM strategy (BATCH-001).
|
|
1213
|
+
*
|
|
1214
|
+
* Generates:
|
|
1215
|
+
* UPDATE "table" SET "update_col" = t."update_col" [, "scalar_col" = $N]
|
|
1216
|
+
* FROM unnest(CAST($1 AS type[]), CAST($2 AS type[])) AS t("match_col", "update_col")
|
|
1217
|
+
* WHERE "table"."match_col" = t."match_col"
|
|
1218
|
+
* [RETURNING ...]
|
|
1219
|
+
*/
|
|
1220
|
+
compileBatchUpdate(intent: BatchUpdateIntent, options?: CompileOptions): CompiledQuery;
|
|
1221
|
+
/**
|
|
1222
|
+
* Compile a delete intent to executable SQL.
|
|
1223
|
+
*/
|
|
1224
|
+
compileDelete(intent: DeleteIntent, options?: CompileOptions): CompiledQuery;
|
|
1225
|
+
/**
|
|
1226
|
+
* Compile an upsert intent to executable SQL (DX-026).
|
|
1227
|
+
*/
|
|
1228
|
+
compileUpsert(intent: UpsertIntent, options?: CompileOptions): CompiledQuery;
|
|
1229
|
+
/**
|
|
1230
|
+
* Compile an upsert-from intent to executable SQL (NQL-BIND).
|
|
1231
|
+
* INSERT INTO target SELECT ... FROM source ON CONFLICT (cols) DO UPDATE SET ...
|
|
1232
|
+
*/
|
|
1233
|
+
compileUpsertFrom(intent: UpsertFromIntent, options?: CompileOptions): CompiledQuery;
|
|
1234
|
+
/**
|
|
1235
|
+
* Compile a recursive CTE plan to executable SQL.
|
|
1236
|
+
* Supports adjacency-list and edge-table traversal modes.
|
|
1237
|
+
*/
|
|
1238
|
+
compileRecursive<T = unknown>(report: RecursivePlanReport, model: ModelIR, options?: CompileOptions): CompiledQuery<T>;
|
|
1239
|
+
/**
|
|
1240
|
+
* Compile a CTE query backed by unnest() arrays (BATCH-001 Block 5).
|
|
1241
|
+
*
|
|
1242
|
+
* Strategy: compile CTE nodes to SQL fragments, compile outer query
|
|
1243
|
+
* independently (parameters starting at $1), then renumber outer params
|
|
1244
|
+
* to start after CTE params and prepend WITH clause.
|
|
1245
|
+
*/
|
|
1246
|
+
compileCteQuery<T = unknown>(intent: CteQueryIntent, options?: CompileOptions): CompiledQuery<T>;
|
|
1247
|
+
/**
|
|
1248
|
+
* Compile a set operation (UNION / INTERSECT / EXCEPT) to SQL.
|
|
1249
|
+
*/
|
|
1250
|
+
compileSetOperation<T = unknown>(intent: SetOperationIntent, model: ModelIR, options?: CompileOptions): CompiledQuery<T>;
|
|
1251
|
+
private compileSetOperationWithBindings;
|
|
1252
|
+
/**
|
|
1253
|
+
* Create a dump for observability.
|
|
1254
|
+
*/
|
|
1255
|
+
createDump(plan: PlanReport, query: CompiledQuery, meta?: DumpMeta): Dump;
|
|
1256
|
+
/**
|
|
1257
|
+
* Execute a query and return all results.
|
|
1258
|
+
* Results are transformed to use model naming convention (e.g., snake_case → camelCase)
|
|
1259
|
+
*/
|
|
1260
|
+
execute<T>(query: CompiledQuery<T>): Promise<T[]>;
|
|
1261
|
+
/**
|
|
1262
|
+
* Execute a query and return rows plus PostgreSQL result metadata.
|
|
1263
|
+
* Results are transformed to use model naming convention (e.g., snake_case → camelCase)
|
|
1264
|
+
*/
|
|
1265
|
+
executeWithMeta(query: CompiledQuery): Promise<{
|
|
1266
|
+
readonly rows: readonly unknown[];
|
|
1267
|
+
readonly rowCount: number;
|
|
1268
|
+
readonly command?: string;
|
|
1269
|
+
}>;
|
|
1270
|
+
/**
|
|
1271
|
+
* Transform result rows from database naming to model naming convention.
|
|
1272
|
+
* For CamelCaseNamingPlugin: price_cents → priceCents
|
|
1273
|
+
*/
|
|
1274
|
+
private transformResultRows;
|
|
1275
|
+
/**
|
|
1276
|
+
* Execute a query and return the first result or null.
|
|
1277
|
+
*/
|
|
1278
|
+
executeOne<T>(query: CompiledQuery<T>): Promise<T | null>;
|
|
1279
|
+
/**
|
|
1280
|
+
* Execute a query and return the first result or throw.
|
|
1281
|
+
*/
|
|
1282
|
+
executeOneOrThrow<T>(query: CompiledQuery<T>): Promise<T>;
|
|
1283
|
+
/**
|
|
1284
|
+
* Stream query results as an async iterable iterator.
|
|
1285
|
+
* Uses PostgreSQL cursors for efficient streaming.
|
|
1286
|
+
*
|
|
1287
|
+
* Note: The cursor must be used within a transaction. If not already
|
|
1288
|
+
* in a transaction, this method wraps the streaming in one.
|
|
1289
|
+
*
|
|
1290
|
+
* @param query - Compiled query to stream
|
|
1291
|
+
* @param options - Stream options (chunkSize)
|
|
1292
|
+
* @returns AsyncIterableIterator that yields rows one by one
|
|
1293
|
+
*/
|
|
1294
|
+
stream<T>(query: CompiledQuery<T>, options?: AdapterStreamOptions): AsyncIterableIterator<T>;
|
|
1295
|
+
/** Stream raw SQL directly using the same cursor machinery as stream(). */
|
|
1296
|
+
streamRaw<T = unknown>(sql: string, parameters?: readonly unknown[], options?: AdapterStreamOptions): AsyncIterableIterator<T>;
|
|
1297
|
+
private streamCursor;
|
|
1298
|
+
/**
|
|
1299
|
+
* Internal: Stream with an existing client using cursors.
|
|
1300
|
+
*/
|
|
1301
|
+
private streamWithClient;
|
|
1302
|
+
private streamWithManagedClient;
|
|
1303
|
+
private streamWithManagedClientSavepointScope;
|
|
1304
|
+
private streamWithClientTransaction;
|
|
1305
|
+
/**
|
|
1306
|
+
* Introspect the database schema and return a ModelIR.
|
|
1307
|
+
*
|
|
1308
|
+
* @param options - Optional introspection options (schema, include/exclude filters)
|
|
1309
|
+
* @returns IntrospectedModelIR with tables, relations, and hierarchy metadata
|
|
1310
|
+
*
|
|
1311
|
+
* @example
|
|
1312
|
+
* ```typescript
|
|
1313
|
+
* const model = await adapter.introspect();
|
|
1314
|
+
* const model = await adapter.introspect({ schema: 'tenant_1' });
|
|
1315
|
+
* const model = await adapter.introspect({ exclude: ['_prisma*'] });
|
|
1316
|
+
* ```
|
|
1317
|
+
*/
|
|
1318
|
+
introspect(options?: IntrospectionOptions): Promise<IntrospectedModelIR>;
|
|
1319
|
+
/**
|
|
1320
|
+
* Acquire an exclusive session-level PostgreSQL advisory lock for the callback.
|
|
1321
|
+
*
|
|
1322
|
+
* The lock, callback, and unlock run on one `withPinnedConnection()` adapter.
|
|
1323
|
+
* dbsp performs one PostgreSQL acquire and one matching unlock per call. It
|
|
1324
|
+
* does not track reentrant depth in v1; PostgreSQL's session-level stacking
|
|
1325
|
+
* still applies when callers deliberately nest on the same pinned adapter.
|
|
1326
|
+
*/
|
|
1327
|
+
withAdvisoryLock<T>(key: PgAdvisoryLockKey, fn: (locked: Adapter<DB>) => Promise<T>): Promise<T>;
|
|
1328
|
+
withAdvisoryLock<T>(key: PgAdvisoryLockKey, fn: (locked: Adapter<DB>) => Promise<T>, options: {
|
|
1329
|
+
readonly wait?: 'block';
|
|
1330
|
+
readonly signal?: AbortSignal;
|
|
1331
|
+
}): Promise<T>;
|
|
1332
|
+
withAdvisoryLock<T>(key: PgAdvisoryLockKey, fn: (locked: Adapter<DB>) => Promise<T>, options: {
|
|
1333
|
+
readonly wait: 'try';
|
|
1334
|
+
readonly signal?: AbortSignal;
|
|
1335
|
+
}): Promise<PgAdvisoryLockResult<T>>;
|
|
1336
|
+
withAdvisoryLock<T>(key: PgAdvisoryLockKey, fn: (locked: Adapter<DB>) => Promise<T>, options?: {
|
|
1337
|
+
readonly wait?: 'block' | 'try';
|
|
1338
|
+
readonly signal?: AbortSignal;
|
|
1339
|
+
}): Promise<T | PgAdvisoryLockResult<T>>;
|
|
1340
|
+
private unlockAdvisoryLock;
|
|
1341
|
+
withPinnedConnection<T>(fn: (adapter: Adapter<DB>) => Promise<T>, options?: PinnedConnectionOptions): Promise<T>;
|
|
1342
|
+
private pinnedConnectionReleaseReason;
|
|
1343
|
+
private pinnedConnectionWithClient;
|
|
1344
|
+
/**
|
|
1345
|
+
* Execute a callback within a database transaction.
|
|
1346
|
+
*
|
|
1347
|
+
* ## What this guarantees
|
|
1348
|
+
*
|
|
1349
|
+
* The callback's work commits together or not at all; a statement issued inside
|
|
1350
|
+
* the transaction never executes after its boundary, even if you forget to
|
|
1351
|
+
* `await` it; a nested `transaction()` is a real savepoint; and the connection
|
|
1352
|
+
* never goes back to the pool with a transaction still open on it.
|
|
1353
|
+
*
|
|
1354
|
+
* ## What it cannot guarantee, and you should know before you reach for raw SQL
|
|
1355
|
+
*
|
|
1356
|
+
* **Raw SQL that ends the transaction ends it.** `COMMIT`, `ROLLBACK` and
|
|
1357
|
+
* `PREPARE TRANSACTION` issued through `executeRaw` — or through several commands
|
|
1358
|
+
* in one call — reach PostgreSQL and take effect *before* dbsp is told what they
|
|
1359
|
+
* were: the command tag arrives after the statement has run. dbsp detects it, kills
|
|
1360
|
+
* the scope so nothing else escapes, and throws — but **it cannot un-run what your
|
|
1361
|
+
* statement already did**, and `transaction()` rejecting does not mean nothing was
|
|
1362
|
+
* committed.
|
|
1363
|
+
*
|
|
1364
|
+
* The same holds for session state raw SQL creates: a sequence that advanced stays
|
|
1365
|
+
* advanced, an advisory lock stays held, a `PREPARE` or a `SET` you issued survives
|
|
1366
|
+
* on a pooled connection. dbsp cleans up only what dbsp created.
|
|
1367
|
+
*
|
|
1368
|
+
* This is the contract of an escape hatch, not an oversight — see #327. If you need
|
|
1369
|
+
* transaction control, own the transaction: take a client, `BEGIN` on it yourself,
|
|
1370
|
+
* and hand dbsp a `borrowedClient` **without** `managedTransactions`. dbsp will then
|
|
1371
|
+
* contain its own statements inside *your* transaction instead of the other way round.
|
|
1372
|
+
*/
|
|
1373
|
+
transaction<T>(fn: (adapter: Adapter<DB>) => Promise<T>, options?: TransactionOptions): Promise<T>;
|
|
1374
|
+
/**
|
|
1375
|
+
* Execute scratch PostgreSQL work in a scope that always rolls back on success.
|
|
1376
|
+
*
|
|
1377
|
+
* This is intentionally PostgreSQL-adapter-specific. It is used for catalog
|
|
1378
|
+
* shaped scratch DDL such as expression canonicalisation, where the caller
|
|
1379
|
+
* needs PostgreSQL's rendering but must not keep the scratch objects. This
|
|
1380
|
+
* scope has exactly one successful exit: rollback. In a caller transaction,
|
|
1381
|
+
* only this outer savepoint is retained after rollback; nested work releases
|
|
1382
|
+
* normally, so a large canonicalisation run cannot retain one subtransaction
|
|
1383
|
+
* per expression.
|
|
1384
|
+
* Rollback here is cleanup of dbsp-created work, not a sandbox for arbitrary
|
|
1385
|
+
* session effects.
|
|
1386
|
+
*/
|
|
1387
|
+
withScratchScope<T>(fn: (adapter: RollbackOnlyPgsqlScope<DB>) => Promise<T>): Promise<T>;
|
|
1388
|
+
private createManagedClientAdapter;
|
|
1389
|
+
private createPinnedConnectionAdapter;
|
|
1390
|
+
private createChildTransactionObserver;
|
|
1391
|
+
private observeChildTransaction;
|
|
1392
|
+
private markChildTransactionObserved;
|
|
1393
|
+
private refreshScopeChildrenFailure;
|
|
1394
|
+
private transactionWithManagedClient;
|
|
1395
|
+
private transactionWithManagedClientSavepointScope;
|
|
1396
|
+
private applyTransactionTimeouts;
|
|
1397
|
+
private captureAndApplySavepointTimeouts;
|
|
1398
|
+
private restoreSavepointTimeouts;
|
|
1399
|
+
private transactionWithClientTransaction;
|
|
1400
|
+
private releaseClient;
|
|
1401
|
+
private rollbackAndReleaseSavepoint;
|
|
1402
|
+
private rollbackSavepoint;
|
|
1403
|
+
private releaseSavepoint;
|
|
1404
|
+
private rollbackTransactionIfOpen;
|
|
1405
|
+
private classifyTransactionStateError;
|
|
1406
|
+
private probeTransactionState;
|
|
1407
|
+
private classifySavepointReleaseFailure;
|
|
1408
|
+
private rollbackSavepointAfterReleaseFailure;
|
|
1409
|
+
private enterTransactionScope;
|
|
1410
|
+
private enterPinnedConnectionScope;
|
|
1411
|
+
private enterSavepointScope;
|
|
1412
|
+
private pushClientScope;
|
|
1413
|
+
private currentClientScope;
|
|
1414
|
+
private managedScopeEndedMessage;
|
|
1415
|
+
private assertCanUseClient;
|
|
1416
|
+
private assertUsableScopeAncestors;
|
|
1417
|
+
private findClientScope;
|
|
1418
|
+
private assertScopeNotPoisoned;
|
|
1419
|
+
private throwIfScopePoisoned;
|
|
1420
|
+
private scopePoisonOutranksError;
|
|
1421
|
+
private poisonScopeState;
|
|
1422
|
+
private poisonClientScope;
|
|
1423
|
+
private poisonClientScopeStack;
|
|
1424
|
+
private runWithScopeStatementLock;
|
|
1425
|
+
private closeScope;
|
|
1426
|
+
private closeScopeAndAssertChildren;
|
|
1427
|
+
private drainScopeStatements;
|
|
1428
|
+
private drainScopeChildren;
|
|
1429
|
+
private assertScopeChildrenSettled;
|
|
1430
|
+
private drainScopeWork;
|
|
1431
|
+
private executeScopeBoundaryStatement;
|
|
1432
|
+
private assertCommitSucceeded;
|
|
1433
|
+
/**
|
|
1434
|
+
* Create a schema-scoped adapter for multi-tenant queries.
|
|
1435
|
+
*/
|
|
1436
|
+
withSchema(schemaName: string): Adapter<DB>;
|
|
1437
|
+
/**
|
|
1438
|
+
* Execute raw SQL directly.
|
|
1439
|
+
*
|
|
1440
|
+
* ⚠️ WARNING: Use parameter placeholders ($1, $2, etc.) for all values.
|
|
1441
|
+
*
|
|
1442
|
+
* Transaction control through raw SQL inside a scope dbsp is managing is
|
|
1443
|
+
* unsupported. `COMMIT`, `ROLLBACK`, and `PREPARE TRANSACTION` end the
|
|
1444
|
+
* transaction dbsp is working inside; dbsp detects that and fails loudly, but
|
|
1445
|
+
* the data is already whatever your statement made it. Raw savepoint control
|
|
1446
|
+
* (`SAVEPOINT`, `RELEASE SAVEPOINT`, `ROLLBACK TO SAVEPOINT`) can alter the
|
|
1447
|
+
* savepoint stack before dbsp sees the command tag; dbsp poisons the scope, but
|
|
1448
|
+
* it cannot make that command un-run. Manage your transaction outside dbsp's
|
|
1449
|
+
* calls.
|
|
1450
|
+
*/
|
|
1451
|
+
executeRaw<T = unknown>(sql: string, parameters?: readonly unknown[]): Promise<T[]>;
|
|
1452
|
+
/**
|
|
1453
|
+
* Generate DDL statements from the PostgreSQL physical model.
|
|
1454
|
+
*
|
|
1455
|
+
* Uses PostgreSQL AST nodes and pgsql-deparser for consistent SQL generation.
|
|
1456
|
+
* Names are already physical: they were mapped once when the model was built
|
|
1457
|
+
* with `createPgPhysicalModel`, and this method maps none again.
|
|
1458
|
+
*
|
|
1459
|
+
* @param physical - The physical model to generate DDL from; its schema and
|
|
1460
|
+
* `fkAutoIndex` apply
|
|
1461
|
+
* @param overrideOptions - Optional rendering overrides (e.g., includeDropStatements)
|
|
1462
|
+
* @returns Array of DDL statements in dependency order
|
|
1463
|
+
*/
|
|
1464
|
+
generateDDL(physical: PgPhysicalModel, overrideOptions?: GenerateDDLOptions): string[];
|
|
1465
|
+
/**
|
|
1466
|
+
* Execute a DDL statement directly (e.g. TRUNCATE, VACUUM, ALTER TABLE, CREATE INDEX).
|
|
1467
|
+
*
|
|
1468
|
+
* @throws Error if called on a compile-only adapter (no pool)
|
|
1469
|
+
* @since DDL-TABLE-001
|
|
1470
|
+
*/
|
|
1471
|
+
executeDDL(sql: string): Promise<void>;
|
|
1472
|
+
/**
|
|
1473
|
+
* Whether a transaction is open on this adapter's connection.
|
|
1474
|
+
* This is true for dbsp-managed scopes and for borrowed pg clients whose
|
|
1475
|
+
* ReadyForQuery status says the caller has an open transaction.
|
|
1476
|
+
*
|
|
1477
|
+
* @since DDL-TABLE-001
|
|
1478
|
+
*/
|
|
1479
|
+
get inTransaction(): boolean;
|
|
1480
|
+
private adapterManagedScopeIsLive;
|
|
1481
|
+
private shouldProtectBorrowedClientTransaction;
|
|
1482
|
+
/**
|
|
1483
|
+
* An idle ReadyForQuery status says nothing about commands another owner has
|
|
1484
|
+
* already queued on a PoolClient. Only a dbsp-created pinned scope both owns
|
|
1485
|
+
* the checked-out physical client and holds its statement lock across the
|
|
1486
|
+
* failed named execution and any unnamed replay.
|
|
1487
|
+
*/
|
|
1488
|
+
private ownsSerializedClientForPreparedStatementReplay;
|
|
1489
|
+
private executeQueryProtectingOpenTransaction;
|
|
1490
|
+
private executeConnectionStatement;
|
|
1491
|
+
private executeConnectionStatementUnlocked;
|
|
1492
|
+
private executeConnectionStatementInSavepoint;
|
|
1493
|
+
private issueConnectionQuery;
|
|
1494
|
+
private assertNoMultiCommandRawCall;
|
|
1495
|
+
private assertNoTransactionControlCommand;
|
|
1496
|
+
private assertPrepareDidNotEndTransaction;
|
|
1497
|
+
/**
|
|
1498
|
+
* Resolve the explicit schema for a catalog read: an explicit argument, else
|
|
1499
|
+
* the adapter's configured schema, else `undefined` (resolve in-query). NOT a
|
|
1500
|
+
* hard-coded 'public' — an unresolved schema is handled by the SQL, which
|
|
1501
|
+
* finds the table's schema search_path-aware, in the SAME session, so a
|
|
1502
|
+
* non-public search_path and a pooled connection both stay correct.
|
|
1503
|
+
*/
|
|
1504
|
+
private explicitSchema;
|
|
1505
|
+
/**
|
|
1506
|
+
* List all indexes on a table by querying pg_indexes.
|
|
1507
|
+
*
|
|
1508
|
+
* @param table - Table name
|
|
1509
|
+
* @param schema - Schema name (defaults to the search_path-resolved schema)
|
|
1510
|
+
*/
|
|
1511
|
+
listIndexes(table: string, schema?: string, options?: {
|
|
1512
|
+
namePattern?: string;
|
|
1513
|
+
}): Promise<IndexInfo[]>;
|
|
1514
|
+
/**
|
|
1515
|
+
* Check whether an index with the given name exists on a table.
|
|
1516
|
+
*
|
|
1517
|
+
* @param name - Index name
|
|
1518
|
+
* @param table - Table name
|
|
1519
|
+
* @param schema - Schema name (defaults to the search_path-resolved schema)
|
|
1520
|
+
*/
|
|
1521
|
+
indexExists(name: string, table: string, schema?: string): Promise<boolean>;
|
|
1522
|
+
/**
|
|
1523
|
+
* Return the total storage size of a table in bytes (includes indexes and TOAST).
|
|
1524
|
+
*
|
|
1525
|
+
* The table name is a SQL identifier — it is double-quoted, not parameterized,
|
|
1526
|
+
* because PostgreSQL does not allow parameterized table names in FROM clauses.
|
|
1527
|
+
* With no known schema the table is left unqualified so ::regclass resolves it
|
|
1528
|
+
* through search_path (the same table an unqualified reference would hit).
|
|
1529
|
+
*
|
|
1530
|
+
* @param table - Table name
|
|
1531
|
+
* @param schema - Schema name (defaults to the search_path-resolved schema)
|
|
1532
|
+
*/
|
|
1533
|
+
storageSize(table: string, schema?: string): Promise<number>;
|
|
1534
|
+
/**
|
|
1535
|
+
* Generate SQL for TRUNCATE TABLE.
|
|
1536
|
+
* Implements TableDDLGeneratorAdapter.generateTruncate.
|
|
1537
|
+
*/
|
|
1538
|
+
generateTruncate(table: string, schemaName: string, options?: TruncateOptions): string;
|
|
1539
|
+
/**
|
|
1540
|
+
* Generate SQL for VACUUM.
|
|
1541
|
+
* Implements TableDDLGeneratorAdapter.generateVacuum.
|
|
1542
|
+
*/
|
|
1543
|
+
generateVacuum(table: string, schemaName: string, options?: VacuumOptions): string;
|
|
1544
|
+
/**
|
|
1545
|
+
* Generate SQL for ALTER TABLE ... ALTER COLUMN.
|
|
1546
|
+
* Implements TableDDLGeneratorAdapter.generateAlterColumn.
|
|
1547
|
+
*/
|
|
1548
|
+
generateAlterColumn(table: string, schemaName: string, column: string, options: AlterColumnOptions): string;
|
|
1549
|
+
/**
|
|
1550
|
+
* Generate SQL for CREATE INDEX.
|
|
1551
|
+
* Implements TableDDLGeneratorAdapter.generateCreateIndex.
|
|
1552
|
+
*/
|
|
1553
|
+
generateCreateIndex(table: string, schemaName: string, options: CreateIndexOptions): string;
|
|
1554
|
+
/**
|
|
1555
|
+
* Generate SQL for DROP INDEX.
|
|
1556
|
+
* Implements TableDDLGeneratorAdapter.generateDropIndex.
|
|
1557
|
+
*/
|
|
1558
|
+
generateDropIndex(name: string, schemaName: string, options?: DropIndexOptions): string;
|
|
1559
|
+
/**
|
|
1560
|
+
* Validate an identifier (table name, column name, schema name).
|
|
1561
|
+
*/
|
|
1562
|
+
validateIdentifier(value: string, type: string): void;
|
|
1563
|
+
}
|
|
1564
|
+
/**
|
|
1565
|
+
* Create a PgsqlAdapter from a pg Pool instance.
|
|
1566
|
+
*
|
|
1567
|
+
* @param pool - pg Pool instance
|
|
1568
|
+
* @param options - Optional configuration
|
|
1569
|
+
* @returns A new PgsqlAdapter instance
|
|
1570
|
+
*
|
|
1571
|
+
* @example
|
|
1572
|
+
* ```typescript
|
|
1573
|
+
* import { Pool } from 'pg';
|
|
1574
|
+
* import { createPgsqlAdapter } from '@dbsp/adapter-pgsql';
|
|
1575
|
+
*
|
|
1576
|
+
* const pool = new Pool({ connectionString: process.env.DATABASE_URL });
|
|
1577
|
+
* const adapter = createPgsqlAdapter(pool);
|
|
1578
|
+
*
|
|
1579
|
+
* // With naming convention
|
|
1580
|
+
* const adapter = createPgsqlAdapter(pool, { dbCasing: 'snake_case' });
|
|
1581
|
+
* ```
|
|
1582
|
+
*/
|
|
1583
|
+
declare function createPgsqlAdapter<DB = unknown>(pool: Pool, options?: PgsqlPoolAdapterOptions): PgsqlAdapter<DB>;
|
|
1584
|
+
declare function createPgsqlAdapter<DB = unknown>(client: PoolClient, options: PgsqlBorrowedClientAdapterOptions): PgsqlAdapter<DB>;
|
|
1585
|
+
/**
|
|
1586
|
+
* Creates a connectionless PgsqlAdapter for SQL generation without a database connection.
|
|
1587
|
+
*
|
|
1588
|
+
* All compilation methods (compile, compileInsert, etc.), createDump(), and generateDDL()
|
|
1589
|
+
* work normally. The adapter has the full PgsqlAdapter surface; database operations refuse
|
|
1590
|
+
* at runtime until it is constructed with a connection via createPgsqlAdapter(pool).
|
|
1591
|
+
*
|
|
1592
|
+
* @example
|
|
1593
|
+
* ```typescript
|
|
1594
|
+
* import { createPgsqlCompileOnlyAdapter } from '@dbsp/adapter-pgsql';
|
|
1595
|
+
* import { createOrm } from '@dbsp/core';
|
|
1596
|
+
*
|
|
1597
|
+
* const adapter = createPgsqlCompileOnlyAdapter();
|
|
1598
|
+
* const orm = createOrm({ model, adapter });
|
|
1599
|
+
* const dump = await orm.select('users').dump();
|
|
1600
|
+
* console.log(dump.sql);
|
|
1601
|
+
* ```
|
|
1602
|
+
*/
|
|
1603
|
+
declare function createPgsqlCompileOnlyAdapter<DB = unknown>(options?: PgsqlCompileOnlyAdapterOptions): PgsqlAdapter<DB>;
|
|
1604
|
+
|
|
1605
|
+
interface CheckConstraintCanonicalizationWarning {
|
|
1606
|
+
readonly table: string;
|
|
1607
|
+
readonly kind: 'check_constraint';
|
|
1608
|
+
readonly name: string;
|
|
1609
|
+
readonly constraint: string;
|
|
1610
|
+
readonly message: string;
|
|
1611
|
+
readonly cause: unknown;
|
|
1612
|
+
}
|
|
1613
|
+
interface ColumnDefaultCanonicalizationWarning {
|
|
1614
|
+
readonly table: string;
|
|
1615
|
+
readonly kind: 'column_default';
|
|
1616
|
+
readonly name: string;
|
|
1617
|
+
readonly message: string;
|
|
1618
|
+
readonly cause: unknown;
|
|
1619
|
+
readonly outcome?: 'unavailable' | 'rejected' | 'refused';
|
|
1620
|
+
/** Whether this warning represents a raw fallback or absent counterpart. */
|
|
1621
|
+
readonly comparison: 'raw' | 'unpaired';
|
|
1622
|
+
/** Present when the default could not be paired with the opposite model side. */
|
|
1623
|
+
readonly side?: 'desired' | 'database';
|
|
1624
|
+
}
|
|
1625
|
+
interface IndexPredicateCanonicalizationWarning {
|
|
1626
|
+
readonly table: string;
|
|
1627
|
+
readonly kind: 'index_predicate';
|
|
1628
|
+
readonly name: string;
|
|
1629
|
+
readonly message: string;
|
|
1630
|
+
readonly cause: unknown;
|
|
1631
|
+
readonly outcome: 'unavailable' | 'rejected' | 'refused';
|
|
1632
|
+
/** Predicate fallback always compares both complete models raw. */
|
|
1633
|
+
readonly comparison: 'raw';
|
|
1634
|
+
readonly side?: 'desired' | 'database';
|
|
1635
|
+
}
|
|
1636
|
+
type ExpressionCanonicalizationWarning = CheckConstraintCanonicalizationWarning | ColumnDefaultCanonicalizationWarning | IndexPredicateCanonicalizationWarning;
|
|
1637
|
+
interface CanonicalizeCheckConstraintsOptions {
|
|
1638
|
+
/** Database schema that owns the target tables and target-scoped enum types. */
|
|
1639
|
+
readonly schemaName?: string;
|
|
1640
|
+
/** Called when PostgreSQL CHECK canonicalisation fails and raw comparison is used. */
|
|
1641
|
+
readonly onWarning?: (warning: CheckConstraintCanonicalizationWarning) => void;
|
|
1642
|
+
/** Throw instead of falling back to raw comparison when canonicalisation fails. */
|
|
1643
|
+
readonly requireCanonicalization?: boolean;
|
|
1644
|
+
/** Skip CHECK scratch work when the caller's dialect does not support CHECK DDL. */
|
|
1645
|
+
readonly canonicalizeCheckConstraints?: boolean;
|
|
1646
|
+
/** Capabilities used to generate the migration this scope is staging for. */
|
|
1647
|
+
readonly dialectCapabilities?: DialectCapabilities;
|
|
1648
|
+
}
|
|
1649
|
+
/** The comparison result for one CHECK owned by an application assertion. */
|
|
1650
|
+
type OwnedCheckState = 'healthy' | 'absent' | 'unrenderable' | 'definition-mismatch' | 'unvalidated';
|
|
1651
|
+
declare class CheckConstraintCanonicalizationError extends Error {
|
|
1652
|
+
readonly table: string;
|
|
1653
|
+
readonly constraints: readonly string[];
|
|
1654
|
+
readonly cause: unknown;
|
|
1655
|
+
constructor(table: string, constraints: readonly string[], cause: unknown);
|
|
1656
|
+
}
|
|
1657
|
+
declare class ColumnDefaultCanonicalizationError extends Error {
|
|
1658
|
+
readonly table: string;
|
|
1659
|
+
readonly column: string;
|
|
1660
|
+
readonly cause: unknown;
|
|
1661
|
+
constructor(table: string, column: string, cause: unknown);
|
|
1662
|
+
}
|
|
1663
|
+
/**
|
|
1664
|
+
* Canonicalise PostgreSQL CHECK constraint expressions in a desired model.
|
|
1665
|
+
*/
|
|
1666
|
+
declare function canonicalizeCheckConstraints(adapter: RollbackOnlyPgsqlScope, desired: ModelIR, dbModel: ModelIR, options?: CanonicalizeCheckConstraintsOptions): Promise<ModelIR>;
|
|
1667
|
+
|
|
1668
|
+
interface ComparePgsqlDatabaseSchemaOptions$1 extends CompareSchemataOptions$1, SchemaScopeOptions {
|
|
1669
|
+
/**
|
|
1670
|
+
* Whether to canonicalise PostgreSQL CHECK constraint expressions, column defaults, and predicates on column-keyed
|
|
1671
|
+
* partial indexes before comparing. Defaults to `true`. Expression-keyed
|
|
1672
|
+
* partial-index predicates are reported as unavailable. Set to `false` only for compatibility with
|
|
1673
|
+
* legacy raw-string live diffs.
|
|
1674
|
+
*
|
|
1675
|
+
* Live canonicalisation creates temporary scratch tables inside an adapter
|
|
1676
|
+
* scratch scope whose successful cleanup is rollback. The database role needs
|
|
1677
|
+
* permission to create temporary tables and use the scratch column types. If
|
|
1678
|
+
* PostgreSQL refuses that scratch DDL, non-strict mode warns and falls back to
|
|
1679
|
+
* best-effort raw string comparison for the affected expression surfaces.
|
|
1680
|
+
*/
|
|
1681
|
+
readonly canonicalizeExpressions?: boolean;
|
|
1682
|
+
/**
|
|
1683
|
+
* Receives live expression canonicalisation warnings. Defaults to the core logger.
|
|
1684
|
+
*/
|
|
1685
|
+
readonly onWarning?: (message: string) => void;
|
|
1686
|
+
/** Receives the identity-bearing canonicalisation warning before its string form. */
|
|
1687
|
+
readonly onExpressionCanonicalizationWarning?: (warning: ExpressionCanonicalizationWarning) => void;
|
|
1688
|
+
/**
|
|
1689
|
+
* Diff that the caller just applied before this live re-diff. Used only when
|
|
1690
|
+
* expression surfaces are compared by raw text to fail loudly if the exact same
|
|
1691
|
+
* expression-surface drift appears again after re-introspection.
|
|
1692
|
+
*/
|
|
1693
|
+
readonly previouslyAppliedDiff?: SchemaDiff;
|
|
1694
|
+
/** Internal physical-to-authored sequence provenance for legacy-name refusal. */
|
|
1695
|
+
readonly declaredSequenceNames?: ReadonlyMap<string, string>;
|
|
1696
|
+
}
|
|
1697
|
+
/**
|
|
1698
|
+
* Compare the declared shape of an adopted table against its live PostgreSQL
|
|
1699
|
+
* counterpart. The supplied model is deliberately declaration-scoped: the whole
|
|
1700
|
+
* schema is introspected, so an adopted table's foreign keys to any table are
|
|
1701
|
+
* seen, and the comparison then keeps only the declared physical tables (with
|
|
1702
|
+
* the relations between them), so drift on other tables is not reported.
|
|
1703
|
+
*/
|
|
1704
|
+
interface ComparePgsqlDeclaredAdoptionSchemaInput {
|
|
1705
|
+
readonly executor: PgsqlAdoptionComparisonExecutor;
|
|
1706
|
+
readonly model: ModelIR;
|
|
1707
|
+
readonly schema: string;
|
|
1708
|
+
readonly dbCasing: DbCasing;
|
|
1709
|
+
/**
|
|
1710
|
+
* Already-physicalized naming authority for `model`. Callers that own a
|
|
1711
|
+
* snapshot pass it here so comparison never re-applies logical naming.
|
|
1712
|
+
*/
|
|
1713
|
+
readonly physical?: PgPhysicalModel;
|
|
1714
|
+
/** Physical [table, index] JSON keys whose drop drift is unmanaged. */
|
|
1715
|
+
readonly externalIndexMask?: ReadonlySet<string>;
|
|
1716
|
+
/** Physical [table, surface] JSON keys maintained by application assertions. */
|
|
1717
|
+
readonly ownershipMask?: PgsqlDeclaredAdoptionOwnershipMask;
|
|
1718
|
+
/** Internal physical-to-authored sequence provenance for legacy-name refusal. */
|
|
1719
|
+
readonly declaredSequenceNames?: ReadonlyMap<string, string>;
|
|
1720
|
+
}
|
|
1721
|
+
/** Internal converge-only declaration mask; public database comparison is unchanged. */
|
|
1722
|
+
interface PgsqlDeclaredAdoptionOwnershipMask {
|
|
1723
|
+
readonly checks: ReadonlySet<string>;
|
|
1724
|
+
readonly columnTypes: ReadonlySet<string>;
|
|
1725
|
+
readonly indexes: ReadonlySet<string>;
|
|
1726
|
+
}
|
|
1727
|
+
/** Minimal pool surface retained so callers can keep their executor opaque. */
|
|
1728
|
+
interface PgsqlAdoptionComparisonExecutor {
|
|
1729
|
+
query(sql: string, parameters?: readonly unknown[]): Promise<{
|
|
1730
|
+
readonly rows: readonly Record<string, unknown>[];
|
|
1731
|
+
}>;
|
|
1732
|
+
}
|
|
1733
|
+
/** Builds the declaration-scoped model used by every adoption shape check. */
|
|
1734
|
+
declare function modelForDeclaredAdoption(table: TableIR): ModelIR;
|
|
1735
|
+
/**
|
|
1736
|
+
* PostgreSQL-aware comparison used to admit a declared table adoption. A
|
|
1737
|
+
* claimed session remains pinned by constructing a borrowed, transaction-aware
|
|
1738
|
+
* adapter from that exact executor.
|
|
1739
|
+
*/
|
|
1740
|
+
declare function comparePgsqlDeclaredAdoptionSchema(input: ComparePgsqlDeclaredAdoptionSchemaInput): Promise<SchemaDiff>;
|
|
1741
|
+
type NonConvergentSchemaDiffSurface = {
|
|
1742
|
+
readonly kind: 'check_constraint';
|
|
1743
|
+
readonly table: string;
|
|
1744
|
+
readonly constraint: string;
|
|
1745
|
+
} | {
|
|
1746
|
+
readonly kind: 'column_default';
|
|
1747
|
+
readonly table: string;
|
|
1748
|
+
readonly column: string;
|
|
1749
|
+
};
|
|
1750
|
+
declare class NonConvergentSchemaDiffError extends Error {
|
|
1751
|
+
readonly surface: NonConvergentSchemaDiffSurface;
|
|
1752
|
+
readonly desiredExpressionHash: string;
|
|
1753
|
+
readonly databaseExpressionHash: string;
|
|
1754
|
+
constructor(surface: NonConvergentSchemaDiffSurface, desiredExpressionHash: string, databaseExpressionHash: string);
|
|
1755
|
+
}
|
|
1756
|
+
/** An enum value this diff adds, reported as a candidate cause — never asserted. */
|
|
1757
|
+
interface AddedEnumValue {
|
|
1758
|
+
readonly enumName: string;
|
|
1759
|
+
readonly value: string;
|
|
1760
|
+
}
|
|
1761
|
+
declare class CheckConstraintNewEnumValueError extends Error {
|
|
1762
|
+
readonly table: string;
|
|
1763
|
+
readonly constraint: string;
|
|
1764
|
+
readonly addedEnumValues: readonly AddedEnumValue[];
|
|
1765
|
+
constructor(table: string, constraint: string, addedEnumValues: readonly AddedEnumValue[]);
|
|
1766
|
+
}
|
|
1767
|
+
/** A raw partial-index predicate and added enum values cannot share one migration. */
|
|
1768
|
+
declare class PartialIndexPredicateNewEnumValueError extends Error {
|
|
1769
|
+
readonly addedEnumValues: readonly AddedEnumValue[];
|
|
1770
|
+
constructor(addedEnumValues: readonly AddedEnumValue[]);
|
|
1771
|
+
}
|
|
1772
|
+
/** #454: Predicate canonicalization is not implemented for indexes with expression keys. */
|
|
1773
|
+
declare class ExpressionKeyedIndexPredicateCanonicalizationUnsupportedError extends Error {
|
|
1774
|
+
readonly predicates: readonly {
|
|
1775
|
+
readonly side: 'desired' | 'database';
|
|
1776
|
+
readonly table: string;
|
|
1777
|
+
readonly index: string;
|
|
1778
|
+
}[];
|
|
1779
|
+
constructor(predicates: readonly {
|
|
1780
|
+
readonly side: 'desired' | 'database';
|
|
1781
|
+
readonly table: string;
|
|
1782
|
+
readonly index: string;
|
|
1783
|
+
}[]);
|
|
1784
|
+
}
|
|
1785
|
+
/**
|
|
1786
|
+
* A raw partial-index predicate cannot be proven to converge after PostgreSQL
|
|
1787
|
+
* deparses it, so emitting its CREATE statement is unsafe.
|
|
1788
|
+
*/
|
|
1789
|
+
declare class RawIndexPredicateFallbackError extends Error {
|
|
1790
|
+
constructor(cause?: unknown);
|
|
1791
|
+
}
|
|
1792
|
+
declare class IndexPredicateCanonicalizationError extends Error {
|
|
1793
|
+
readonly rejectedPredicates: readonly {
|
|
1794
|
+
readonly side: 'desired' | 'database';
|
|
1795
|
+
readonly table: string;
|
|
1796
|
+
readonly index: string;
|
|
1797
|
+
readonly reason?: unknown;
|
|
1798
|
+
}[];
|
|
1799
|
+
/**
|
|
1800
|
+
* Enum values added by this migration are diagnostic candidates only. They
|
|
1801
|
+
* are collected from the schema diff, never matched to a rejected index.
|
|
1802
|
+
*/
|
|
1803
|
+
readonly addedEnumValues: readonly AddedEnumValue[];
|
|
1804
|
+
constructor(rejectedPredicates: readonly {
|
|
1805
|
+
readonly side: 'desired' | 'database';
|
|
1806
|
+
readonly table: string;
|
|
1807
|
+
readonly index: string;
|
|
1808
|
+
readonly reason?: unknown;
|
|
1809
|
+
}[],
|
|
1810
|
+
/**
|
|
1811
|
+
* Enum values added by this migration are diagnostic candidates only. They
|
|
1812
|
+
* are collected from the schema diff, never matched to a rejected index.
|
|
1813
|
+
*/
|
|
1814
|
+
addedEnumValues?: readonly AddedEnumValue[]);
|
|
1815
|
+
}
|
|
1816
|
+
/**
|
|
1817
|
+
* Live PostgreSQL schema diff: introspect, canonicalise desired CHECK
|
|
1818
|
+
* constraint expressions, column defaults, and predicates on column-keyed
|
|
1819
|
+
* partial indexes through PostgreSQL, then call the pure synchronous
|
|
1820
|
+
* schema comparator.
|
|
1821
|
+
*
|
|
1822
|
+
* If CHECK canonicalisation falls back while the same diff adds a plausibly
|
|
1823
|
+
* referenced enum value, the diff is refused. dbsp currently applies each
|
|
1824
|
+
* migration in one transaction, and PostgreSQL forbids using a newly added enum
|
|
1825
|
+
* value in that same transaction; emitting the CHECK would produce a migration
|
|
1826
|
+
* that cannot run. Apply the enum addition by itself first, then add or update
|
|
1827
|
+
* the CHECK constraint in a later migration.
|
|
1828
|
+
*
|
|
1829
|
+
* Index expressions are intentionally not canonicalised here; partial-index
|
|
1830
|
+
* predicates on expression-keyed indexes are reported as unavailable and are
|
|
1831
|
+
* therefore rejected by strict mode. They need their own key-shape substrate.
|
|
1832
|
+
*/
|
|
1833
|
+
declare function comparePgsqlDatabaseSchema$1(adapter: PgsqlAdapter, desired: ModelIR, options?: ComparePgsqlDatabaseSchemaOptions$1): Promise<SchemaDiff>;
|
|
1834
|
+
declare function assertNoRepeatedExpressionSurfaceDrift(previouslyAppliedDiff: SchemaDiff, currentDiff: SchemaDiff, rawExpressionSurfaces?: ReadonlySet<string>): void;
|
|
1835
|
+
|
|
1836
|
+
/**
|
|
1837
|
+
* Migration SQL Generator (DDL-PROV Block 1)
|
|
1838
|
+
*
|
|
1839
|
+
* Generates ordered SQL statements from a SchemaDiff.
|
|
1840
|
+
* Statements are topologically sorted: DROP constraints → DROP objects → CREATE objects → ADD constraints.
|
|
1841
|
+
*
|
|
1842
|
+
* @module migration-sql
|
|
1843
|
+
*/
|
|
1844
|
+
|
|
1845
|
+
interface MigrationSQLOptions$1 {
|
|
1846
|
+
/**
|
|
1847
|
+
* Schema namespace (default: none — unqualified).
|
|
1848
|
+
* Required when emitted migration SQL would otherwise mix non-default
|
|
1849
|
+
* target-scoped custom types/enums with unqualified table SQL.
|
|
1850
|
+
*/
|
|
1851
|
+
readonly schemaName?: string;
|
|
1852
|
+
/** Whether to include destructive changes (drops) */
|
|
1853
|
+
readonly includeDestructive?: boolean;
|
|
1854
|
+
/** Automatically create indexes on FK columns for new tables (default: true) */
|
|
1855
|
+
readonly fkAutoIndex?: boolean;
|
|
1856
|
+
/**
|
|
1857
|
+
* Declared model whose FK-index coverage controls automatic index emission.
|
|
1858
|
+
* This lets callers mask generated DDL surfaces without changing the
|
|
1859
|
+
* declaration-level decision to emit an automatic FK index.
|
|
1860
|
+
*/
|
|
1861
|
+
readonly fkAutoIndexCoverage?: ModelIR;
|
|
1862
|
+
/** Dialect capabilities — unsupported index features throw during migration SQL generation */
|
|
1863
|
+
readonly dialectCapabilities?: DialectCapabilities;
|
|
1864
|
+
}
|
|
1865
|
+
/**
|
|
1866
|
+
* Generate ordered SQL statements from a SchemaDiff.
|
|
1867
|
+
*
|
|
1868
|
+
* Topological order:
|
|
1869
|
+
* 0. DROP FK/CHECK constraints (must drop before referenced tables)
|
|
1870
|
+
* 1. DROP indexes
|
|
1871
|
+
* 2. DROP columns
|
|
1872
|
+
* 3. DROP primary keys
|
|
1873
|
+
* 4. DROP tables, DROP ENUMs
|
|
1874
|
+
* 5. CREATE ENUMs (must exist before tables that use them)
|
|
1875
|
+
* 6. CREATE tables
|
|
1876
|
+
* 7. ADD columns
|
|
1877
|
+
* 8. ALTER columns (type, nullable, default)
|
|
1878
|
+
* 9. ADD primary keys / column UNIQUE constraints
|
|
1879
|
+
* 10. ADD FK constraints (must add after referenced tables exist)
|
|
1880
|
+
* 11. ALTER FK (drop + re-add)
|
|
1881
|
+
* 12. CREATE indexes
|
|
1882
|
+
* 13. ADD CHECK constraints
|
|
1883
|
+
* 14. ALTER ENUM ADD VALUE (must be last — has transaction visibility caveats in PG)
|
|
1884
|
+
* 15. COMMENT ON TABLE / COLUMN (very last)
|
|
1885
|
+
*/
|
|
1886
|
+
declare function generateMigrationSQL$1(diff: SchemaDiff, options?: MigrationSQLOptions$1): readonly string[];
|
|
1887
|
+
/**
|
|
1888
|
+
* Generate ordered DOWN SQL statements from a SchemaDiff.
|
|
1889
|
+
*
|
|
1890
|
+
* Reverses the topological order used in UP migrations:
|
|
1891
|
+
* phases run in descending order (18, 17, ..., 0).
|
|
1892
|
+
*
|
|
1893
|
+
* Irreversible drops with missing or unmanaged metadata produce SQL WARNING
|
|
1894
|
+
* comments instead of reconstructing the dropped object.
|
|
1895
|
+
*/
|
|
1896
|
+
declare function generateDownSQL$1(diff: SchemaDiff, options?: MigrationSQLOptions$1): readonly string[];
|
|
1897
|
+
|
|
1898
|
+
/** Public physical-model DDL facade. The rendering engines remain ModelIR-only. */
|
|
1899
|
+
|
|
1900
|
+
interface GenerateDDLOptions extends Omit<GenerateDDLOptions$1, 'schemaName' | 'naming' | 'fkAutoIndex'> {
|
|
1901
|
+
}
|
|
1902
|
+
interface CompareSchemataOptions extends Omit<CompareSchemataOptions$1, 'schema' | 'dbCasing' | 'declaredSequenceNames'> {
|
|
1903
|
+
}
|
|
1904
|
+
interface ComparePgsqlDatabaseSchemaOptions extends Omit<ComparePgsqlDatabaseSchemaOptions$1, 'schema' | 'dbCasing' | 'declaredSequenceNames'> {
|
|
1905
|
+
}
|
|
1906
|
+
interface MigrationSQLOptions extends Omit<MigrationSQLOptions$1, 'schemaName' | 'fkAutoIndex' | 'fkAutoIndexCoverage'> {
|
|
1907
|
+
}
|
|
1908
|
+
interface PgSchemaDiff extends SchemaDiff {
|
|
1909
|
+
readonly physical: Pick<PgPhysicalModel, 'schema' | 'fkAutoIndex'>;
|
|
1910
|
+
}
|
|
1911
|
+
declare function generateDDL(physical: PgPhysicalModel, options?: GenerateDDLOptions): string[];
|
|
1912
|
+
declare function compareSchemata(desired: PgPhysicalModel, database: PgPhysicalModel, options?: CompareSchemataOptions): PgSchemaDiff;
|
|
1913
|
+
declare function comparePgsqlDatabaseSchema(adapter: PgsqlAdapter, desired: PgPhysicalModel, options?: ComparePgsqlDatabaseSchemaOptions): Promise<PgSchemaDiff>;
|
|
1914
|
+
declare function generateMigrationSQL(diff: PgSchemaDiff, options?: MigrationSQLOptions): readonly string[];
|
|
1915
|
+
declare function generateDownSQL(diff: PgSchemaDiff, options?: MigrationSQLOptions): readonly string[];
|
|
1916
|
+
|
|
1917
|
+
/** The intentionally narrow query facade passed to application callbacks. */
|
|
1918
|
+
interface PgApplicationStepTx {
|
|
1919
|
+
query<Row extends Record<string, unknown> = Record<string, unknown>>(text: string, values?: readonly unknown[]): Promise<{
|
|
1920
|
+
readonly rows: readonly Row[];
|
|
1921
|
+
}>;
|
|
1922
|
+
}
|
|
1923
|
+
interface PgConvergeApplicationStepBase {
|
|
1924
|
+
readonly id: string;
|
|
1925
|
+
readonly digest: string;
|
|
1926
|
+
readonly scope?: 'schema';
|
|
1927
|
+
readonly phase: 'before-generated-ddl' | 'after-generated-ddl';
|
|
1928
|
+
readonly lockTimeoutMs?: number;
|
|
1929
|
+
readonly statementTimeoutMs?: number;
|
|
1930
|
+
}
|
|
1931
|
+
interface PgConvergeOnceStep extends PgConvergeApplicationStepBase {
|
|
1932
|
+
readonly kind: 'once';
|
|
1933
|
+
readonly apply: (tx: PgApplicationStepTx) => Promise<void> | void;
|
|
1934
|
+
}
|
|
1935
|
+
interface PgConvergeAssertOwnership {
|
|
1936
|
+
readonly checks?: readonly {
|
|
1937
|
+
readonly table: string;
|
|
1938
|
+
readonly name: string;
|
|
1939
|
+
}[];
|
|
1940
|
+
readonly columnTypes?: readonly {
|
|
1941
|
+
readonly table: string;
|
|
1942
|
+
readonly column: string;
|
|
1943
|
+
}[];
|
|
1944
|
+
readonly indexes?: readonly {
|
|
1945
|
+
readonly table: string;
|
|
1946
|
+
readonly name: string;
|
|
1947
|
+
}[];
|
|
1948
|
+
}
|
|
1949
|
+
type PgOwnedCheckState = OwnedCheckState;
|
|
1950
|
+
interface PgApplicationStepOwnedState {
|
|
1951
|
+
readonly checks: readonly {
|
|
1952
|
+
readonly table: string;
|
|
1953
|
+
readonly name: string;
|
|
1954
|
+
readonly physicalTable: string;
|
|
1955
|
+
readonly physicalName: string;
|
|
1956
|
+
readonly state: PgOwnedCheckState;
|
|
1957
|
+
}[];
|
|
1958
|
+
}
|
|
1959
|
+
interface PgConvergeAssertStep extends PgConvergeApplicationStepBase {
|
|
1960
|
+
readonly kind: 'assert';
|
|
1961
|
+
/** Declaration surfaces maintained by this assertion rather than converge. */
|
|
1962
|
+
readonly owns?: PgConvergeAssertOwnership;
|
|
1963
|
+
readonly inspect: (tx: PgApplicationStepTx, owned: PgApplicationStepOwnedState) => Promise<'healthy' | 'unhealthy'> | 'healthy' | 'unhealthy';
|
|
1964
|
+
readonly apply: (tx: PgApplicationStepTx, owned: PgApplicationStepOwnedState) => Promise<void> | void;
|
|
1965
|
+
}
|
|
1966
|
+
type PgConvergeApplicationStep = PgConvergeOnceStep | PgConvergeAssertStep;
|
|
1967
|
+
|
|
1968
|
+
type PgConvergeRefusal = 'invalid-options' | 'unsupported-change' | 'unmanaged-object' | 'unmanaged-parent' | 'concurrent-drift' | 'ledger-absent' | 'incompatible-ledger' | 'unsupported-server' | 'busy' | 'recovery-required' | 'database-read-only' | 'execution-refused' | 'adoption-refused' | 'application-step-changed' | 'application-step-failed' | 'initialization-refused';
|
|
1969
|
+
interface PgConvergeInitializationFailure {
|
|
1970
|
+
readonly home: LedgerHome;
|
|
1971
|
+
readonly code: string;
|
|
1972
|
+
readonly step: string;
|
|
1973
|
+
readonly detail: string;
|
|
1974
|
+
}
|
|
1975
|
+
type PgConvergeRefusalChange = Pick<SchemaChange, 'kind' | 'table' | 'column' | 'details'> & {
|
|
1976
|
+
/**
|
|
1977
|
+
* Present for create_index and drop_index when the index has a name: always
|
|
1978
|
+
* for a live index and for a logical-mode physical model, which names every
|
|
1979
|
+
* index; a physical-mode snapshot passes its own names through as given.
|
|
1980
|
+
*/
|
|
1981
|
+
readonly index?: string;
|
|
1982
|
+
};
|
|
1983
|
+
/**
|
|
1984
|
+
* Unsupported-change, ledger and ownership refusals occur before converge commits
|
|
1985
|
+
* managed DDL. An execution refusal may follow a rolled-back transactional DDL
|
|
1986
|
+
* attempt, and comparison may use rollback-only scratch DDL.
|
|
1987
|
+
*/
|
|
1988
|
+
declare class PgConvergeRefusalError extends Error {
|
|
1989
|
+
readonly refusal: PgConvergeRefusal;
|
|
1990
|
+
readonly changes: readonly PgConvergeRefusalChange[];
|
|
1991
|
+
readonly detail?: string | undefined;
|
|
1992
|
+
readonly runIds?: readonly string[] | undefined;
|
|
1993
|
+
readonly executionIds?: readonly string[] | undefined;
|
|
1994
|
+
readonly busyRunIds?: readonly string[] | undefined;
|
|
1995
|
+
readonly initialization?: PgConvergeInitializationFailure | undefined;
|
|
1996
|
+
constructor(refusal: PgConvergeRefusal, changes: readonly PgConvergeRefusalChange[], detail?: string | undefined, runIds?: readonly string[] | undefined, executionIds?: readonly string[] | undefined, busyRunIds?: readonly string[] | undefined, initialization?: PgConvergeInitializationFailure | undefined, options?: ErrorOptions);
|
|
1997
|
+
}
|
|
1998
|
+
type PgConvergeResult = {
|
|
1999
|
+
readonly kind: 'no-drift';
|
|
2000
|
+
readonly applied: readonly string[];
|
|
2001
|
+
} | {
|
|
2002
|
+
readonly kind: 'applied';
|
|
2003
|
+
readonly applied: readonly string[];
|
|
2004
|
+
} | {
|
|
2005
|
+
readonly kind: 'partially-applied';
|
|
2006
|
+
readonly completedStepKeys: readonly string[];
|
|
2007
|
+
readonly notStartedStepKeys: readonly string[];
|
|
2008
|
+
readonly detail: string;
|
|
2009
|
+
} | {
|
|
2010
|
+
readonly kind: 'transport-ambiguous';
|
|
2011
|
+
readonly detail: string;
|
|
2012
|
+
};
|
|
2013
|
+
type PgConvergePlannedStep = {
|
|
2014
|
+
readonly stepKey: string;
|
|
2015
|
+
readonly order: number;
|
|
2016
|
+
readonly dependencyOrder: readonly string[];
|
|
2017
|
+
readonly address: NonNullable<NormalizedManagedStep['address']>;
|
|
2018
|
+
readonly kind: SchemaChange['kind'];
|
|
2019
|
+
readonly table: string;
|
|
2020
|
+
readonly column?: string;
|
|
2021
|
+
readonly details: string;
|
|
2022
|
+
} | {
|
|
2023
|
+
readonly stepKey: string;
|
|
2024
|
+
readonly order: number;
|
|
2025
|
+
readonly dependencyOrder: readonly string[];
|
|
2026
|
+
readonly address: NonNullable<NormalizedManagedStep['address']>;
|
|
2027
|
+
readonly kind: 'adopt_table' | 'adopt_sequence';
|
|
2028
|
+
} | {
|
|
2029
|
+
readonly kind: 'application-step';
|
|
2030
|
+
readonly id: string;
|
|
2031
|
+
readonly step: 'once';
|
|
2032
|
+
readonly inspected?: never;
|
|
2033
|
+
readonly stepKey?: never;
|
|
2034
|
+
readonly order?: never;
|
|
2035
|
+
readonly dependencyOrder?: never;
|
|
2036
|
+
readonly address?: never;
|
|
2037
|
+
} | {
|
|
2038
|
+
readonly kind: 'application-step';
|
|
2039
|
+
readonly id: string;
|
|
2040
|
+
readonly step: 'assert';
|
|
2041
|
+
readonly inspected: boolean;
|
|
2042
|
+
readonly stepKey?: never;
|
|
2043
|
+
readonly order?: never;
|
|
2044
|
+
readonly dependencyOrder?: never;
|
|
2045
|
+
readonly address?: never;
|
|
2046
|
+
};
|
|
2047
|
+
type PgConvergeCheckResult = {
|
|
2048
|
+
readonly kind: 'no-drift';
|
|
2049
|
+
} | {
|
|
2050
|
+
readonly kind: 'would-apply';
|
|
2051
|
+
readonly planDigest: string;
|
|
2052
|
+
readonly steps: readonly PgConvergePlannedStep[];
|
|
2053
|
+
};
|
|
2054
|
+
interface ConvergePgBaseOptions {
|
|
2055
|
+
readonly schema?: string;
|
|
2056
|
+
readonly dbCasing?: DbCasing;
|
|
2057
|
+
/** Internal physical-model rendering choice; public callers cannot override it. */
|
|
2058
|
+
readonly fkAutoIndex?: boolean;
|
|
2059
|
+
/** Internal physical-to-authored sequence provenance for legacy-name refusal. */
|
|
2060
|
+
readonly declaredSequenceNames?: ReadonlyMap<string, string>;
|
|
2061
|
+
/**
|
|
2062
|
+
* In apply mode, create a ledger for an absent schema ledger. `pristine`
|
|
2063
|
+
* refuses declared live tables or standalone sequences; `adopt-existing`
|
|
2064
|
+
* also adopts matching declared relations on every converge call. The schema
|
|
2065
|
+
* itself must already exist. Defaults to `never`.
|
|
2066
|
+
*/
|
|
2067
|
+
readonly initialize?: 'never' | 'pristine' | 'adopt-existing';
|
|
2068
|
+
/**
|
|
2069
|
+
* Exact physical PostgreSQL index names that converge must leave alone on
|
|
2070
|
+
* declared model tables. Each table name uses the model's naming, while the
|
|
2071
|
+
* index name is used verbatim. Entries are validated before connecting: they
|
|
2072
|
+
* must be distinct, name declared tables, and must not equal the name of an
|
|
2073
|
+
* index listed in any declared table's `indexes`. Converge never drops a
|
|
2074
|
+
* live index named here. It does not check these names against the other
|
|
2075
|
+
* relations the model creates (tables, sequences, primary-key or UNIQUE
|
|
2076
|
+
* constraint indexes); PostgreSQL rejects such a collision when the step
|
|
2077
|
+
* runs, and converge reports it as that step's failure.
|
|
2078
|
+
*/
|
|
2079
|
+
readonly externalIndexes?: readonly {
|
|
2080
|
+
readonly table: string;
|
|
2081
|
+
readonly name: string;
|
|
2082
|
+
}[];
|
|
2083
|
+
/**
|
|
2084
|
+
* Transactional application-owned schema work. Recorded runs append
|
|
2085
|
+
* `application-step:<id>` to `applied`, after generated change kinds.
|
|
2086
|
+
* The transaction facade rejects leading transaction-control keywords; it is
|
|
2087
|
+
* a correctness guard, not a security boundary for code in this process.
|
|
2088
|
+
*/
|
|
2089
|
+
readonly steps?: readonly PgConvergeApplicationStep[];
|
|
2090
|
+
}
|
|
2091
|
+
interface ConvergePgOptions extends ConvergePgBaseOptions {
|
|
2092
|
+
readonly mode?: 'apply';
|
|
2093
|
+
}
|
|
2094
|
+
interface ConvergePgCheckOptions extends ConvergePgBaseOptions {
|
|
2095
|
+
readonly mode: 'check';
|
|
2096
|
+
}
|
|
2097
|
+
/**
|
|
2098
|
+
* Converges only startup-safe PostgreSQL additions: it creates tables and
|
|
2099
|
+
* sequences, adds nullable columns without defaults and NOT NULL columns with
|
|
2100
|
+
* boolean, finite-number, or non-function-like string literal defaults of a
|
|
2101
|
+
* a PostgreSQL built-in base type or an enum to managed tables, and creates
|
|
2102
|
+
* indexes, CHECK constraints, and foreign keys when their table parents are
|
|
2103
|
+
* created by this same run (for foreign keys, both tables).
|
|
2104
|
+
* Other defaulted original database types are refused.
|
|
2105
|
+
*
|
|
2106
|
+
* Adding a column still takes an ACCESS EXCLUSIVE lock on its table, bounded by
|
|
2107
|
+
* the executor's five-second lock_timeout and held through read-back and the
|
|
2108
|
+
* ledger terminal. A no-rewrite default is therefore not non-blocking.
|
|
2109
|
+
*
|
|
2110
|
+
* Converge mutates only declared additions whose target and existing parent pass
|
|
2111
|
+
* managed admission. It compares the declared tables, sequences, and enums'
|
|
2112
|
+
* structural shape; it does not audit the provenance of an exact-matching child
|
|
2113
|
+
* already present on a managed table.
|
|
2114
|
+
* An assert may own declared CHECKs, column types, and named indexes; those
|
|
2115
|
+
* surfaces are excluded from comparison and generated DDL. Its read-only
|
|
2116
|
+
* `inspect` receives canonical owned-CHECK state, while its callback is
|
|
2117
|
+
* responsible for maintaining them. `externalIndexes` accepts exact physical
|
|
2118
|
+
* index names on logical model tables;
|
|
2119
|
+
* entries are validated before the ledger lock or any query, and converge
|
|
2120
|
+
* never drops a matching live index. A name that collides with another
|
|
2121
|
+
* relation the model creates fails when that step runs.
|
|
2122
|
+
* Before comparison, converge refuses while its target ledger home has a live
|
|
2123
|
+
* reservation: wait for a run that is still executing, reconcile a run whose
|
|
2124
|
+
* lock is free with reconcilePgTransitionRun or `dbsp reconcile --db
|
|
2125
|
+
* <database> <run-id>`, have the ledger owner resolve an unmapped reservation
|
|
2126
|
+
* and the journal owner one whose journal attribution cannot be read, then call
|
|
2127
|
+
* converge again.
|
|
2128
|
+
* Application steps run on the converge session: session-level effects such as
|
|
2129
|
+
* `SET` without `LOCAL`, `SET ROLE`, `LISTEN`, `PREPARE`, temporary tables and
|
|
2130
|
+
* session advisory locks are not part of a step and can affect the rest of the
|
|
2131
|
+
* call. Steps should use `SET LOCAL`.
|
|
2132
|
+
* A declared table with `adopt: true` is taken into management when it exists,
|
|
2133
|
+
* the ledger projects its address as unknown (the only state an adoption claim
|
|
2134
|
+
* opens from), and it matches the declaration exactly after `externalIndexes`
|
|
2135
|
+
* and application ownership masking. A mismatch found while planning refuses
|
|
2136
|
+
* `adoption-refused` before anything is written. A table that changes while
|
|
2137
|
+
* its adoption runs is refused under its claim and the ledger records that
|
|
2138
|
+
* refused adoption; tables adopted earlier in the same call stay adopted.
|
|
2139
|
+
* Tables a run creates and every change on those tables commit together or not
|
|
2140
|
+
* at all. A sequence created by the same run commits on its own and can remain
|
|
2141
|
+
* after a failure. After a transport-ambiguous outcome, the next call observes
|
|
2142
|
+
* whichever state PostgreSQL holds. Converge runs are not journaled. Check mode
|
|
2143
|
+
* returns a point-in-time plan without executing it; it is not a guarantee that
|
|
2144
|
+
* a later apply will succeed, because other sessions can change the database
|
|
2145
|
+
* and execution-time ledger physical-shape integrity, claim-time adoption
|
|
2146
|
+
* re-verification, vacancy, and lock-timeout checks are not reproduced.
|
|
2147
|
+
* `initialize` defaults to `never`. `pristine` creates an absent ledger only
|
|
2148
|
+
* when declared tables and standalone sequences are absent, while
|
|
2149
|
+
* `adopt-existing` creates an absent ledger and adopts matching declared
|
|
2150
|
+
* relations on every call. The target schema must already exist. Application
|
|
2151
|
+
* steps run with `search_path` set to the target schema, `pg_temp`, then the
|
|
2152
|
+
* connection's entries, so `current_schema()` is the target. Lookup goes through
|
|
2153
|
+
* `pg_catalog` first unless those entries name it explicitly, then the target,
|
|
2154
|
+
* `pg_temp` and those entries.
|
|
2155
|
+
*/
|
|
2156
|
+
declare function convergePg(pool: Pool, model: ModelIR, options?: ConvergePgOptions): Promise<PgConvergeResult>;
|
|
2157
|
+
declare function convergePg(pool: Pool, model: ModelIR, options: ConvergePgCheckOptions): Promise<PgConvergeCheckResult>;
|
|
2158
|
+
|
|
2159
|
+
type QueryResultLike = {
|
|
2160
|
+
readonly rows: readonly Record<string, unknown>[];
|
|
2161
|
+
};
|
|
2162
|
+
type TransitionJournalQueryable = {
|
|
2163
|
+
query(sql: string, params?: readonly unknown[]): Promise<QueryResultLike>;
|
|
2164
|
+
};
|
|
2165
|
+
/** A copied plan row is not authority for a differently named run. */
|
|
2166
|
+
declare class TransitionRunIdentityMismatchError extends Error {
|
|
2167
|
+
constructor();
|
|
2168
|
+
}
|
|
2169
|
+
declare function renderCreateDbspMetaSchemaSql(): string;
|
|
2170
|
+
declare function renderCreateTransitionRunTableSql(exclusive?: boolean): string;
|
|
2171
|
+
declare function renderCreateTransitionJournalTableSql(exclusive?: boolean): string;
|
|
2172
|
+
declare function renderCreateTransitionRunPlanTableSql(exclusive?: boolean): string;
|
|
2173
|
+
declare function renderCreateTransitionAuthorizationTableSql(exclusive?: boolean): string;
|
|
2174
|
+
declare function ensureTransitionJournal(executor: TransitionJournalQueryable): Promise<void>;
|
|
2175
|
+
declare function createPgTransitionRunPersister(executor: TransitionJournalQueryable): TransitionRunPersister;
|
|
2176
|
+
declare function appendIntentJournal(executor: TransitionJournalQueryable, record: DurableIntentRecord): Promise<void>;
|
|
2177
|
+
/** Append-only run approval, intentionally separate from step attempts. */
|
|
2178
|
+
declare function appendTransitionAuthorization(executor: TransitionJournalQueryable, record: TransitionRunAuthorization): Promise<void>;
|
|
2179
|
+
declare function readTransitionJournal(executor: TransitionJournalQueryable, runId: string, options?: {
|
|
2180
|
+
readonly ensure?: boolean;
|
|
2181
|
+
}): Promise<TransitionRunJournal & {
|
|
2182
|
+
readonly plan: ProvenPlanShape;
|
|
2183
|
+
}>;
|
|
2184
|
+
|
|
2185
|
+
interface PgCatalogueIdentityQueryable {
|
|
2186
|
+
query(sql: string, params?: readonly unknown[]): Promise<{
|
|
2187
|
+
readonly rows: readonly Record<string, unknown>[];
|
|
2188
|
+
}>;
|
|
2189
|
+
}
|
|
2190
|
+
/**
|
|
2191
|
+
* Re-read the PostgreSQL catalogue identity for one managed address. The
|
|
2192
|
+
* adapter deliberately returns absence as undefined; callers decide whether an
|
|
2193
|
+
* absent object is legal for the lifecycle state they are admitting.
|
|
2194
|
+
*/
|
|
2195
|
+
declare function readPgCatalogueIdentity(executor: PgCatalogueIdentityQueryable, address: ResourceAddress): Promise<ResourceAddress | undefined>;
|
|
2196
|
+
|
|
2197
|
+
declare const PG_LEDGER_SHAPE_VERSION = 1;
|
|
2198
|
+
declare const ledgerShapeAllowanceBrand: unique symbol;
|
|
2199
|
+
/**
|
|
2200
|
+
* An in-process allowance for one non-ledger trigger observed immediately
|
|
2201
|
+
* after trusted harness setup. Its contents are deliberately not structural:
|
|
2202
|
+
* only the internal factory can register a value in the WeakSet below.
|
|
2203
|
+
*/
|
|
2204
|
+
interface PgLedgerShapeAllowance {
|
|
2205
|
+
readonly [ledgerShapeAllowanceBrand]: 'dbsp-ledger-shape-allowance';
|
|
2206
|
+
}
|
|
2207
|
+
type PgLedgerPhysicalShapeOutcome = {
|
|
2208
|
+
readonly kind: 'verified';
|
|
2209
|
+
} | {
|
|
2210
|
+
readonly kind: 'shape-wrong';
|
|
2211
|
+
readonly artefact: string;
|
|
2212
|
+
} | {
|
|
2213
|
+
readonly kind: 'unverifiable';
|
|
2214
|
+
readonly cause: string;
|
|
2215
|
+
} | {
|
|
2216
|
+
readonly kind: 'unsupported-major';
|
|
2217
|
+
readonly major: number | undefined;
|
|
2218
|
+
} | {
|
|
2219
|
+
readonly kind: 'validator-abi-failure';
|
|
2220
|
+
readonly sqlstate: string;
|
|
2221
|
+
};
|
|
2222
|
+
/**
|
|
2223
|
+
* Read-only admission of an existing ledger. A fixture is deliberately a
|
|
2224
|
+
* prerequisite: deparse text is not portable across PostgreSQL majors.
|
|
2225
|
+
*/
|
|
2226
|
+
declare function classifyPgLedgerPhysicalShape(executor: TransitionJournalQueryable, target: PgLedgerTarget, allowance?: PgLedgerShapeAllowance): Promise<PgLedgerPhysicalShapeOutcome>;
|
|
2227
|
+
/**
|
|
2228
|
+
* Throwing compatibility façade. Existing mutating callers intentionally keep
|
|
2229
|
+
* their historical contract; outcome-aware consumers use `classify…`.
|
|
2230
|
+
*/
|
|
2231
|
+
declare function validatePgLedgerPhysicalShape(executor: TransitionJournalQueryable, target: PgLedgerTarget, allowance?: PgLedgerShapeAllowance): Promise<void>;
|
|
2232
|
+
/**
|
|
2233
|
+
* Mint a one-request allowance for one exact live trigger. This is exported
|
|
2234
|
+
* only from the adapter's `/internal` surface: consumers cannot forge the
|
|
2235
|
+
* WeakMap registration or serialize it into an ordinary recovery request.
|
|
2236
|
+
*/
|
|
2237
|
+
declare function createPgLedgerShapeAllowance(executor: TransitionJournalQueryable, target: PgLedgerTarget, triggerName: string): Promise<PgLedgerShapeAllowance>;
|
|
2238
|
+
declare class PgLedgerStorageUnsupportedError extends Error {
|
|
2239
|
+
constructor(observed: unknown);
|
|
2240
|
+
}
|
|
2241
|
+
declare const pgOrderedLedgerLocksBrand: unique symbol;
|
|
2242
|
+
/** Proof returned only after this transaction acquired every home in order. */
|
|
2243
|
+
interface PgOrderedLedgerLocks {
|
|
2244
|
+
readonly homes: readonly PgLedgerTarget[];
|
|
2245
|
+
readonly [pgOrderedLedgerLocksBrand]: 'dbsp-pg-ordered-ledger-locks';
|
|
2246
|
+
}
|
|
2247
|
+
type PgLedgerLockResult = {
|
|
2248
|
+
readonly kind: 'acquired';
|
|
2249
|
+
readonly proof: PgOrderedLedgerLocks;
|
|
2250
|
+
} | {
|
|
2251
|
+
readonly kind: 'busy';
|
|
2252
|
+
readonly ledger: LedgerHome;
|
|
2253
|
+
} | {
|
|
2254
|
+
readonly kind: 'refused';
|
|
2255
|
+
readonly ledger: LedgerHome;
|
|
2256
|
+
readonly error: unknown;
|
|
2257
|
+
};
|
|
2258
|
+
type PgLedgerTarget = LedgerHome;
|
|
2259
|
+
/** Read only reservations explicitly linked to one durable execution/run. */
|
|
2260
|
+
declare function readPgLedgerReservationsForExecution(executor: TransitionJournalQueryable, target: PgLedgerTarget, executionId: string): Promise<readonly LedgerReservationRow[]>;
|
|
2261
|
+
/**
|
|
2262
|
+
* A re-address pair can cross ledger homes. Discover every existing reservation
|
|
2263
|
+
* table before reading the pair so recovery cannot accidentally treat one side
|
|
2264
|
+
* of a cross-schema closure as the entire operation.
|
|
2265
|
+
*/
|
|
2266
|
+
type PgLedgerReservationCandidateOutcome = {
|
|
2267
|
+
readonly target: PgLedgerTarget;
|
|
2268
|
+
readonly kind: 'verified';
|
|
2269
|
+
} | {
|
|
2270
|
+
readonly target: PgLedgerTarget;
|
|
2271
|
+
readonly kind: 'not-ledger-shape';
|
|
2272
|
+
} | {
|
|
2273
|
+
readonly target: PgLedgerTarget;
|
|
2274
|
+
readonly kind: 'unverifiable';
|
|
2275
|
+
readonly cause: string;
|
|
2276
|
+
};
|
|
2277
|
+
type PgLedgerReservationsForPair = readonly LedgerReservationRow[] & {
|
|
2278
|
+
readonly candidates: readonly PgLedgerReservationCandidateOutcome[];
|
|
2279
|
+
};
|
|
2280
|
+
declare function readPgLedgerReservationsForPair(executor: TransitionJournalQueryable, pairId: string): Promise<PgLedgerReservationsForPair>;
|
|
2281
|
+
type LedgerWriteMember = Omit<LedgerChainMember, 'controller' | 'recordedAt'>;
|
|
2282
|
+
declare function renderCreateLedgerEventTableSql(target: PgLedgerTarget): string;
|
|
2283
|
+
declare function renderCreateLedgerTerminalMemberIndexSql(target: PgLedgerTarget): string;
|
|
2284
|
+
declare function renderCreateLedgerReservationTableSql(target: PgLedgerTarget): string;
|
|
2285
|
+
declare function renderCreateLedgerIdentityTableSql(target: PgLedgerTarget): string;
|
|
2286
|
+
declare function renderCreateLedgerMarkerTableSql(target: PgLedgerTarget): string;
|
|
2287
|
+
declare function renderCreateLedgerImmutabilityFunctionSql(target: PgLedgerTarget): string;
|
|
2288
|
+
declare function renderCreateLedgerImmutabilityTriggerSql(target: PgLedgerTarget): string;
|
|
2289
|
+
/** Proves the PG 15 requirement before emitting a NULLS NOT DISTINCT table. */
|
|
2290
|
+
declare function ensurePgLedgerStorageVersion(executor: TransitionJournalQueryable): Promise<void>;
|
|
2291
|
+
declare function ensurePgLedger(executor: TransitionJournalQueryable, target: PgLedgerTarget, options?: {
|
|
2292
|
+
readonly writeMarker?: boolean;
|
|
2293
|
+
}): Promise<void>;
|
|
2294
|
+
declare function ensureDbspMetaLedger(executor: TransitionJournalQueryable, options?: {
|
|
2295
|
+
readonly writeMarker?: boolean;
|
|
2296
|
+
}): Promise<void>;
|
|
2297
|
+
/** Records lineage once; a mismatching identity is an admission concern of unit 5. */
|
|
2298
|
+
declare function recordPgLedgerIdentity(executor: TransitionJournalQueryable, target: PgLedgerTarget, identity: LedgerIdentity): Promise<void>;
|
|
2299
|
+
declare function appendPgLedgerProgress(executor: TransitionJournalQueryable, target: PgLedgerTarget, member: LedgerWriteMember): Promise<void>;
|
|
2300
|
+
/**
|
|
2301
|
+
* Appends the root claim and every reservation in one PostgreSQL statement.
|
|
2302
|
+
* Callers can include this statement in a larger DDL transaction, but cannot
|
|
2303
|
+
* accidentally split this claim's append from its durable reservation rows.
|
|
2304
|
+
*/
|
|
2305
|
+
declare function appendPgLedgerClaim(executor: TransitionJournalQueryable, target: PgLedgerTarget, member: LedgerWriteMember, reservations: readonly LedgerReservationRow[], reservationRootClaimId?: string): Promise<void>;
|
|
2306
|
+
/**
|
|
2307
|
+
* Appends an entire destructive closure as one ledger group. The caller owns
|
|
2308
|
+
* the surrounding locked transaction; consequently a failed member insert
|
|
2309
|
+
* rolls back the root, every member and every reservation together.
|
|
2310
|
+
*/
|
|
2311
|
+
declare function appendPgLedgerClaimGroup(executor: TransitionJournalQueryable, root: LedgerWriteMember, members: readonly LedgerWriteMember[], reservations: readonly LedgerReservationRow[]): Promise<void>;
|
|
2312
|
+
/** Resolves every closure terminal in the caller's one locked transaction. */
|
|
2313
|
+
declare function appendPgLedgerResolutionGroup(executor: TransitionJournalQueryable, rootClaimId: string, members: readonly LedgerWriteMember[], reservations: readonly Pick<LedgerReservationRow, 'address'>[]): Promise<void>;
|
|
2314
|
+
/**
|
|
2315
|
+
* Appends a terminal member and releases the reservations owned by this
|
|
2316
|
+
* append atomically. A group-owned contained member has an intentionally
|
|
2317
|
+
* empty closure because its group's root append already released it.
|
|
2318
|
+
*/
|
|
2319
|
+
declare function appendPgLedgerResolution(executor: TransitionJournalQueryable, target: PgLedgerTarget, member: LedgerWriteMember, rootClaimId: string, reservations: readonly Pick<LedgerReservationRow, 'address'>[]): Promise<void>;
|
|
2320
|
+
/**
|
|
2321
|
+
* `released` has no claim spelling in the closed event grammar. It is the
|
|
2322
|
+
* deliberate atomic managed-to-unknown transition, so it must not invent an
|
|
2323
|
+
* empty reservation closure merely to reuse ordinary claim resolution.
|
|
2324
|
+
*/
|
|
2325
|
+
declare function appendPgLedgerRelease(executor: TransitionJournalQueryable, target: PgLedgerTarget, member: LedgerWriteMember): Promise<void>;
|
|
2326
|
+
/**
|
|
2327
|
+
* Transaction-scoped, non-waiting locks for one effects closure. The ordering
|
|
2328
|
+
* is dbsp_meta first and then schema name, so opposing closures cannot deadlock.
|
|
2329
|
+
*/
|
|
2330
|
+
declare function acquirePgLedgerLocks(executor: TransitionJournalQueryable, homes: readonly LedgerHome[]): Promise<PgLedgerLockResult>;
|
|
2331
|
+
|
|
2332
|
+
type ReinitializePreflightCheckpoint = 'archive' | 'create' | 'grants' | 'journal-create' | 'marker' | 'output';
|
|
2333
|
+
/** Test-only callers can observe real engine progress without changing production flow. */
|
|
2334
|
+
type ReinitializePreflightObserver = (checkpoint: ReinitializePreflightCheckpoint, ledger?: LedgerHome) => Promise<void>;
|
|
2335
|
+
interface PgReinitializePreflightClient extends TransitionJournalQueryable {
|
|
2336
|
+
release?(error?: unknown): void;
|
|
2337
|
+
}
|
|
2338
|
+
interface PgReinitializePreflightPool {
|
|
2339
|
+
connect(): Promise<PgReinitializePreflightClient>;
|
|
2340
|
+
}
|
|
2341
|
+
interface PgReinitializePreflightOptions {
|
|
2342
|
+
readonly pool: PgReinitializePreflightPool;
|
|
2343
|
+
/** Schema names only. `dbsp_meta` is always added as the database ledger. */
|
|
2344
|
+
readonly schemas: readonly string[];
|
|
2345
|
+
readonly declarations: DeclarationSet;
|
|
2346
|
+
readonly writeAdoptionFile: (report: ReinitializePreflightReport) => Promise<void>;
|
|
2347
|
+
readonly observer?: ReinitializePreflightObserver;
|
|
2348
|
+
}
|
|
2349
|
+
/**
|
|
2350
|
+
* Read exactly one ledger shape marker without creating or repairing anything.
|
|
2351
|
+
* Ordinary command surfaces use this to refuse a non-current mutating scope;
|
|
2352
|
+
* inspect deliberately reports the returned value instead.
|
|
2353
|
+
*/
|
|
2354
|
+
declare function readPgLedgerMarker(executor: TransitionJournalQueryable, home: LedgerHome): Promise<LedgerMarkerState>;
|
|
2355
|
+
/**
|
|
2356
|
+
* Ordinary mutating commands consume this read-only admission result. It
|
|
2357
|
+
* intentionally delegates equality to the preflight's recorded-vs-live
|
|
2358
|
+
* comparison, keeping that pair as the only ledger lineage comparison.
|
|
2359
|
+
*/
|
|
2360
|
+
type PgLedgerScopeCurrency = {
|
|
2361
|
+
readonly kind: 'absent';
|
|
2362
|
+
readonly marker: LedgerMarkerState;
|
|
2363
|
+
} | {
|
|
2364
|
+
readonly kind: 'current';
|
|
2365
|
+
readonly marker: LedgerMarkerState;
|
|
2366
|
+
} | {
|
|
2367
|
+
readonly kind: 'not-current';
|
|
2368
|
+
readonly marker: LedgerMarkerState;
|
|
2369
|
+
readonly reason: 'marker' | 'lineage';
|
|
2370
|
+
};
|
|
2371
|
+
declare function readPgLedgerScopeCurrency(executor: TransitionJournalQueryable, home: LedgerHome): Promise<PgLedgerScopeCurrency>;
|
|
2372
|
+
/**
|
|
2373
|
+
* Pair recovery reads only homes already selected by the durable run. A
|
|
2374
|
+
* same-named user table in another schema is never discovery evidence for a
|
|
2375
|
+
* pair; callers must first establish the finite candidate homes from reviewed
|
|
2376
|
+
* material and then each home is admitted here.
|
|
2377
|
+
*/
|
|
2378
|
+
declare function readVerifiedPgLedgerReservationsForPair(executor: TransitionJournalQueryable, pairId: string, homes: readonly LedgerHome[]): Promise<readonly _dbsp_types.LedgerReservationRow[]>;
|
|
2379
|
+
/**
|
|
2380
|
+
* Runs the separately privileged reinitialize-preflight. It never invokes a
|
|
2381
|
+
* ledger append primitive: the only durable writes are additive structure,
|
|
2382
|
+
* archived structure, identity, grants, marker, and the caller-owned output.
|
|
2383
|
+
*/
|
|
2384
|
+
declare function runPgReinitializePreflight(options: PgReinitializePreflightOptions): Promise<ReinitializePreflightReport>;
|
|
2385
|
+
|
|
2386
|
+
declare const pgLockedRunBrand: unique symbol;
|
|
2387
|
+
/**
|
|
2388
|
+
* A run identity that was loaded while the caller owns its run lock. This is
|
|
2389
|
+
* deliberately not a structural `{ runId, planDigest }`: callers cannot bind
|
|
2390
|
+
* the digest check to two independently supplied strings.
|
|
2391
|
+
*/
|
|
2392
|
+
interface PgLockedRun {
|
|
2393
|
+
readonly runId: string;
|
|
2394
|
+
readonly planDigest: string;
|
|
2395
|
+
readonly [pgLockedRunBrand]: 'dbsp-pg-locked-journal-run';
|
|
2396
|
+
}
|
|
2397
|
+
/**
|
|
2398
|
+
* Adapter-only bridge from the journal-load/run-lock boundary. Keep this
|
|
2399
|
+
* beside the admitted facade; ordinary callers receive a `PgLockedRun`, never
|
|
2400
|
+
* manufacture one from string fields.
|
|
2401
|
+
*/
|
|
2402
|
+
declare function lockPgJournalRun(run: DurablyLoadedRun): PgLockedRun;
|
|
2403
|
+
/** A COMMIT write may have reached PostgreSQL even when its acknowledgement did not. */
|
|
2404
|
+
declare class PgCommitAcknowledgementAmbiguousError extends Error {
|
|
2405
|
+
constructor(cause: unknown);
|
|
2406
|
+
}
|
|
2407
|
+
/**
|
|
2408
|
+
* Test-only observation points on the admitted path. Production callers do
|
|
2409
|
+
* not supply an observer, so the helper is inert: it performs no IPC, I/O, or
|
|
2410
|
+
* scheduling work in an ordinary run.
|
|
2411
|
+
*/
|
|
2412
|
+
type PgOutcomeCheckpoint = 'post-lock-integrity-before-append' | 'commit-acknowledged' | 'ddl-completed-before-read-back';
|
|
2413
|
+
type PgOutcomeCheckpointObserver = (checkpoint: PgOutcomeCheckpoint) => Promise<void> | void;
|
|
2414
|
+
interface PgOutcomeClaimRequest {
|
|
2415
|
+
readonly plan: OutcomeClaimPlan;
|
|
2416
|
+
readonly reservations: readonly LedgerReservationRow[];
|
|
2417
|
+
readonly lockTimeoutMs?: number;
|
|
2418
|
+
/** Destructive authority is evaluated under these same ledger locks. */
|
|
2419
|
+
readonly destructiveDecision?: (executor: TransitionJournalQueryable, plan: OutcomeClaimPlan) => Promise<DestructiveDecision>;
|
|
2420
|
+
/** Optional E2E observer; absent in all production command paths. */
|
|
2421
|
+
readonly observer?: PgOutcomeCheckpointObserver;
|
|
2422
|
+
}
|
|
2423
|
+
/** One root claim plus its token-free destructive-closure members. */
|
|
2424
|
+
interface PgOutcomeClaimGroupRequest extends PgOutcomeClaimRequest {
|
|
2425
|
+
readonly members: readonly Omit<PgOutcomeClaimRequest, 'destructiveDecision'>[];
|
|
2426
|
+
}
|
|
2427
|
+
interface PgOutcomeClaimGroupAdmission {
|
|
2428
|
+
readonly root: OutcomeClaimAdmission;
|
|
2429
|
+
readonly members: readonly OutcomeClaimAdmission[];
|
|
2430
|
+
}
|
|
2431
|
+
interface PgOutcomeClaimGroupResolution {
|
|
2432
|
+
readonly rootClaimId: string;
|
|
2433
|
+
readonly members: readonly {
|
|
2434
|
+
readonly target: PgLedgerTarget;
|
|
2435
|
+
readonly member: Omit<LedgerChainMember, 'controller' | 'recordedAt'>;
|
|
2436
|
+
}[];
|
|
2437
|
+
readonly reservations: readonly Pick<LedgerReservationRow, 'address'>[];
|
|
2438
|
+
readonly lockTimeoutMs?: number;
|
|
2439
|
+
/** Durable run witness carried from destructive admission to its terminal. */
|
|
2440
|
+
readonly runtimeIntegrityRun?: PgLockedRun;
|
|
2441
|
+
/** Optional E2E observer for this terminal-appending transaction. */
|
|
2442
|
+
readonly observer?: PgOutcomeCheckpointObserver;
|
|
2443
|
+
}
|
|
2444
|
+
interface PgOutcomeResolution {
|
|
2445
|
+
readonly eventId: string;
|
|
2446
|
+
readonly eventKind: Exclude<LedgerEventKind, 'intent' | 'retire-intent' | 'readdress-intent' | 'adopt-intent' | 'executing'>;
|
|
2447
|
+
readonly observed?: LedgerChainMember['observed'];
|
|
2448
|
+
/** Required by the ledger writer when this resolution is `refused`. */
|
|
2449
|
+
readonly refusal?: LedgerChainMember['refusal'];
|
|
2450
|
+
}
|
|
2451
|
+
interface PgOutcomeExecutionRequest {
|
|
2452
|
+
readonly token: ClaimToken;
|
|
2453
|
+
readonly claim: AdmittedOutcomeClaim;
|
|
2454
|
+
readonly statements: readonly ClaimBundleStatement[];
|
|
2455
|
+
}
|
|
2456
|
+
/**
|
|
2457
|
+
* The first admitted-operation shape. Later waves add single and paired
|
|
2458
|
+
* operation variants without reopening the facade's authority boundary.
|
|
2459
|
+
*/
|
|
2460
|
+
interface PgSingleAdmittedOperation {
|
|
2461
|
+
readonly kind: 'single-outcome';
|
|
2462
|
+
readonly request: PgOutcomeTransactionalRequest | PgOutcomeNonTransactionalRequest;
|
|
2463
|
+
}
|
|
2464
|
+
/**
|
|
2465
|
+
* The three generated payload roles are intentionally disjoint at the type
|
|
2466
|
+
* boundary. Their runtime serialization remains the ledger's `{ value,
|
|
2467
|
+
* digest }` pair; the discriminant prevents a generic identity observation
|
|
2468
|
+
* from being wired into a declaration or a structural-proof slot.
|
|
2469
|
+
*/
|
|
2470
|
+
type GeneratedDeclarationPayload = LedgerPayload & {
|
|
2471
|
+
readonly payloadKind: 'generated-declaration';
|
|
2472
|
+
};
|
|
2473
|
+
type GeneratedIdentityObservation = LedgerPayload & {
|
|
2474
|
+
readonly payloadKind: 'generated-identity-observation';
|
|
2475
|
+
};
|
|
2476
|
+
type GeneratedStructuralObservation = LedgerPayload & {
|
|
2477
|
+
readonly payloadKind: 'generated-structural-observation';
|
|
2478
|
+
};
|
|
2479
|
+
/**
|
|
2480
|
+
* Readdress keeps its catalogue closure discovery in readdress.ts, while this
|
|
2481
|
+
* facade owns the only claim/permit/DDL/terminal path for the resulting pair.
|
|
2482
|
+
*/
|
|
2483
|
+
interface PgPairedReaddressOperation {
|
|
2484
|
+
readonly kind: 'paired-readdress';
|
|
2485
|
+
readonly request: {
|
|
2486
|
+
readonly pairId: string;
|
|
2487
|
+
readonly executionId: string;
|
|
2488
|
+
readonly members: readonly {
|
|
2489
|
+
readonly source: LedgerAddress;
|
|
2490
|
+
readonly target: LedgerAddress;
|
|
2491
|
+
readonly sourceClaimId: string;
|
|
2492
|
+
readonly targetClaimId: string;
|
|
2493
|
+
readonly sourceDeclared?: LedgerPayload;
|
|
2494
|
+
readonly targetDeclared: GeneratedDeclarationPayload;
|
|
2495
|
+
readonly targetObserved: GeneratedIdentityObservation;
|
|
2496
|
+
/**
|
|
2497
|
+
* Optional structural proof for a typed table declaration. The paired
|
|
2498
|
+
* protocol invokes it after DDL on its pinned transaction session, so
|
|
2499
|
+
* the observed ledger fact is the catalogue projection it just read.
|
|
2500
|
+
*/
|
|
2501
|
+
readonly postDdlReadBack?: (executor: GeneratedPostconditionSession) => Promise<GeneratedStructuralObservation>;
|
|
2502
|
+
/** Verifies a physical relationship that identity alone cannot prove. */
|
|
2503
|
+
readonly postDdlVerify?: (executor: TransitionJournalQueryable) => Promise<void>;
|
|
2504
|
+
}[];
|
|
2505
|
+
readonly reservations: readonly LedgerReservationRow[];
|
|
2506
|
+
readonly statements: readonly ClaimBundleStatement[];
|
|
2507
|
+
/** Digest-covered root material for this paired request; it is never empty. */
|
|
2508
|
+
readonly manifestPlan: OutcomeClaimPlan;
|
|
2509
|
+
/** Re-read closure, source controller/identity and target vacancy under lock. */
|
|
2510
|
+
readonly verifyLiveAdmission: (executor: TransitionJournalQueryable, currentController: ControllerIdentity) => Promise<OutcomeProtocolRefusal | readonly {
|
|
2511
|
+
readonly source: LedgerAddress;
|
|
2512
|
+
readonly target: LedgerAddress;
|
|
2513
|
+
readonly catalogueIdentity: NonNullable<NonNullable<Awaited<ReturnType<typeof readPgCatalogueIdentity>>>['catalogueIdentity']>;
|
|
2514
|
+
}[]>;
|
|
2515
|
+
readonly lockTimeoutMs?: number;
|
|
2516
|
+
/** Optional E2E observer; absent in normal execution. */
|
|
2517
|
+
readonly observer?: PgOutcomeCheckpointObserver;
|
|
2518
|
+
};
|
|
2519
|
+
}
|
|
2520
|
+
interface PgDestructiveAdmittedOperation {
|
|
2521
|
+
readonly kind: 'destructive-outcome';
|
|
2522
|
+
readonly request: PgOutcomeClaimGroupRequest;
|
|
2523
|
+
readonly readBackAndResolve: (executor: TransitionJournalQueryable, claim: AdmittedDestructiveOutcomeClaim) => Promise<PgOutcomeClaimGroupResolution>;
|
|
2524
|
+
}
|
|
2525
|
+
type PgAdmittedOperation = PgSingleAdmittedOperation | PgPairedReaddressOperation | PgDestructiveAdmittedOperation;
|
|
2526
|
+
type PgAdmittedOperationResult = PgOutcomeResult | PgDestructiveOutcomeResult | {
|
|
2527
|
+
readonly kind: 'executed-paired-readdress';
|
|
2528
|
+
readonly pairId: string;
|
|
2529
|
+
} | {
|
|
2530
|
+
readonly kind: 'outcome-transport-ambiguous';
|
|
2531
|
+
readonly reason: string;
|
|
2532
|
+
} | {
|
|
2533
|
+
readonly kind: 'outcome-recovery-required';
|
|
2534
|
+
readonly claimId: string;
|
|
2535
|
+
readonly reason: string;
|
|
2536
|
+
};
|
|
2537
|
+
type PgDestructiveOutcomeResult = {
|
|
2538
|
+
readonly kind: 'executed-destructive-outcome';
|
|
2539
|
+
}
|
|
2540
|
+
/**
|
|
2541
|
+
* SQL was admitted and may have run, but its operation-owned read-back could
|
|
2542
|
+
* not establish a terminal fact. Keep the durable claim open for reconcile;
|
|
2543
|
+
* in particular, never turn this post-executing state into `refused`.
|
|
2544
|
+
*/
|
|
2545
|
+
| {
|
|
2546
|
+
readonly kind: 'outcome-protocol-pending';
|
|
2547
|
+
readonly reason: string;
|
|
2548
|
+
} | OutcomeProtocolRefusal | {
|
|
2549
|
+
readonly kind: 'outcome-transport-ambiguous';
|
|
2550
|
+
readonly reason: string;
|
|
2551
|
+
} | {
|
|
2552
|
+
readonly kind: 'outcome-recovery-required';
|
|
2553
|
+
readonly claimId: string;
|
|
2554
|
+
readonly reason: string;
|
|
2555
|
+
};
|
|
2556
|
+
/**
|
|
2557
|
+
* Internal compatibility bridge. Callers must bring the durable run and scoped
|
|
2558
|
+
* approvals that the façade consumes; this bridge never invents either.
|
|
2559
|
+
*/
|
|
2560
|
+
declare function executePgDestructiveOutcome(executor: TransitionJournalQueryable, input: {
|
|
2561
|
+
readonly run: PgLockedRun;
|
|
2562
|
+
readonly approval: ScopedApprovalSet;
|
|
2563
|
+
readonly request: PgOutcomeClaimGroupRequest;
|
|
2564
|
+
readonly readBackAndResolve: (executor: TransitionJournalQueryable, claim: AdmittedDestructiveOutcomeClaim) => Promise<PgOutcomeClaimGroupResolution>;
|
|
2565
|
+
}): Promise<PgDestructiveOutcomeResult>;
|
|
2566
|
+
/** Keeps terminal appends and reservation release behind the managed facade. */
|
|
2567
|
+
declare function resolvePgDestructiveOutcome(executor: TransitionJournalQueryable, request: PgOutcomeClaimGroupResolution): Promise<undefined | OutcomeProtocolRefusal>;
|
|
2568
|
+
interface PgOutcomeTransactionalRequest extends PgOutcomeClaimRequest {
|
|
2569
|
+
readonly resolution: PgOutcomeResolution;
|
|
2570
|
+
/** Core has already opened the segment transaction; never nest BEGIN. */
|
|
2571
|
+
readonly transactionOpen?: boolean;
|
|
2572
|
+
/**
|
|
2573
|
+
* Operation-owned terminal read-back; generic catalogue identity is not
|
|
2574
|
+
* evidence. It receives the admitted session so transactional DDL is read
|
|
2575
|
+
* before its terminal ledger fact commits.
|
|
2576
|
+
*/
|
|
2577
|
+
readonly readBack?: (executor: GeneratedPostconditionSession) => Promise<LedgerPayload>;
|
|
2578
|
+
/** Required for creations; the reader runs after the claim and before SQL. */
|
|
2579
|
+
readonly vacancy?: (executor: TransitionJournalQueryable, plan: OutcomeClaimPlan) => Promise<OutcomeVacancy>;
|
|
2580
|
+
/** Re-check operation-specific live facts after the claim/reservation opens. */
|
|
2581
|
+
readonly verifyLiveAdmission?: (executor: TransitionJournalQueryable, plan: OutcomeClaimPlan) => Promise<OutcomeProtocolRefusal | undefined>;
|
|
2582
|
+
/** Record the post-DDL catalogue identity on a present terminal member. */
|
|
2583
|
+
readonly recordCatalogueIdentity?: boolean;
|
|
2584
|
+
}
|
|
2585
|
+
interface PgOutcomeNonTransactionalRequest extends PgOutcomeTransactionalRequest {
|
|
2586
|
+
readonly executingEventId: string;
|
|
2587
|
+
/** Observable acknowledgement point after executing has committed, before SQL. */
|
|
2588
|
+
readonly onExecutingCommitted?: () => Promise<void> | void;
|
|
2589
|
+
}
|
|
2590
|
+
/** Builds the canonical read-back payload once catalogue presence is proven. */
|
|
2591
|
+
type PgOutcomeReadBackFactory = (executor: GeneratedPostconditionSession, address: LedgerAddress, catalogueIdentity: NonNullable<Awaited<ReturnType<typeof readPgCatalogueIdentity>>>['catalogueIdentity']) => Promise<LedgerPayload>;
|
|
2592
|
+
/**
|
|
2593
|
+
* A postcondition read owned by the operation itself. Catalogue identity is
|
|
2594
|
+
* still retained when present for the ledger, but effect classification comes
|
|
2595
|
+
* from the operation's value-level observation rather than object presence.
|
|
2596
|
+
*/
|
|
2597
|
+
type PgOutcomeOperationReadBackFactory = (executor: TransitionJournalQueryable, address: LedgerAddress, catalogueIdentity: NonNullable<Awaited<ReturnType<typeof readPgCatalogueIdentity>>>['catalogueIdentity'] | undefined) => Promise<{
|
|
2598
|
+
readonly observed: LedgerPayload;
|
|
2599
|
+
readonly effect: OutcomeRecoveryEffect;
|
|
2600
|
+
}>;
|
|
2601
|
+
interface PgOutcomeRecoveryRequest {
|
|
2602
|
+
readonly address: LedgerAddress;
|
|
2603
|
+
readonly reservations: readonly Pick<LedgerReservationRow, 'address'>[];
|
|
2604
|
+
readonly resolutionEventId: string;
|
|
2605
|
+
readonly acceptedExternalDdlExclusion: boolean;
|
|
2606
|
+
/** Durable claim-bound evidence re-matched by reconcile under the run lock. */
|
|
2607
|
+
readonly indeterminateEvidence?: OutcomeIndeterminateRecoveryEvidence;
|
|
2608
|
+
readonly resolveIndeterminate?: boolean;
|
|
2609
|
+
readonly readBack: PgOutcomeReadBackFactory;
|
|
2610
|
+
readonly operationReadBack?: PgOutcomeOperationReadBackFactory;
|
|
2611
|
+
readonly lockTimeoutMs?: number;
|
|
2612
|
+
/** Internal-only, in-memory allowance for one harness-installed trigger. */
|
|
2613
|
+
readonly ledgerShapeAllowance?: PgLedgerShapeAllowance;
|
|
2614
|
+
/** Optional E2E observer for recovery's committing transaction. */
|
|
2615
|
+
readonly observer?: PgOutcomeCheckpointObserver;
|
|
2616
|
+
}
|
|
2617
|
+
type PgOutcomeResolutionAppendResult = {
|
|
2618
|
+
readonly kind: 'appended-outcome-resolution';
|
|
2619
|
+
} | {
|
|
2620
|
+
readonly kind: 'already-appended-outcome-resolution';
|
|
2621
|
+
} | {
|
|
2622
|
+
readonly kind: 'malformed-outcome-resolution';
|
|
2623
|
+
readonly reason: string;
|
|
2624
|
+
};
|
|
2625
|
+
type PgOutcomeRecoveryResult = Exclude<OutcomeRecoveryClassification, {
|
|
2626
|
+
readonly kind: 'outcome-recovery-append';
|
|
2627
|
+
}> | {
|
|
2628
|
+
readonly kind: 'outcome-recovery-appended';
|
|
2629
|
+
readonly classification: Extract<OutcomeRecoveryClassification, {
|
|
2630
|
+
readonly kind: 'outcome-recovery-append';
|
|
2631
|
+
}>;
|
|
2632
|
+
readonly append: Exclude<PgOutcomeResolutionAppendResult, {
|
|
2633
|
+
readonly kind: 'malformed-outcome-resolution';
|
|
2634
|
+
}>;
|
|
2635
|
+
} | {
|
|
2636
|
+
readonly kind: 'outcome-transport-ambiguous';
|
|
2637
|
+
readonly reason: string;
|
|
2638
|
+
} | OutcomeProtocolRefusal;
|
|
2639
|
+
type PgOutcomeResult = {
|
|
2640
|
+
readonly kind: 'executed-outcome-claim';
|
|
2641
|
+
readonly claim: AdmittedOutcomeClaim;
|
|
2642
|
+
} | OutcomeProtocolRefusal | {
|
|
2643
|
+
readonly kind: 'outcome-transport-ambiguous';
|
|
2644
|
+
readonly reason: string;
|
|
2645
|
+
} | {
|
|
2646
|
+
readonly kind: 'outcome-recovery-required';
|
|
2647
|
+
readonly claimId: string;
|
|
2648
|
+
readonly reason: string;
|
|
2649
|
+
};
|
|
2650
|
+
type PgPairedReaddressRecoveryDecision = {
|
|
2651
|
+
readonly kind: 'refused';
|
|
2652
|
+
readonly reason: string;
|
|
2653
|
+
} | {
|
|
2654
|
+
readonly kind: 'pending';
|
|
2655
|
+
readonly reason: string;
|
|
2656
|
+
} | {
|
|
2657
|
+
readonly kind: 'indeterminate';
|
|
2658
|
+
readonly reason: string;
|
|
2659
|
+
} | {
|
|
2660
|
+
readonly kind: 'outcome-transport-ambiguous';
|
|
2661
|
+
readonly reason: string;
|
|
2662
|
+
};
|
|
2663
|
+
/**
|
|
2664
|
+
* Recovery owns its reservation set: it re-reads every durable pair row,
|
|
2665
|
+
* checks currency under the same locks, and appends only under a minted paired
|
|
2666
|
+
* permit. A caller's selected rows are evidence to compare, never authority.
|
|
2667
|
+
*/
|
|
2668
|
+
declare function recoverPgAdmittedReaddressPair(executor: TransitionJournalQueryable, request: {
|
|
2669
|
+
readonly pairId: string;
|
|
2670
|
+
readonly executionId: string;
|
|
2671
|
+
readonly reservations: readonly LedgerReservationRow[];
|
|
2672
|
+
readonly assess: (executor: TransitionJournalQueryable, reservations: readonly LedgerReservationRow[]) => Promise<PgPairedReaddressRecoveryDecision>;
|
|
2673
|
+
readonly observer?: PgOutcomeCheckpointObserver;
|
|
2674
|
+
}): Promise<PgPairedReaddressRecoveryDecision>;
|
|
2675
|
+
type RuntimeIntegritySeams = {
|
|
2676
|
+
readonly validateShape: typeof validatePgLedgerPhysicalShape;
|
|
2677
|
+
readonly readCurrency: typeof readPgLedgerScopeCurrency;
|
|
2678
|
+
};
|
|
2679
|
+
/**
|
|
2680
|
+
* The façade's runtime gate: validate the physical ledger and its marker /
|
|
2681
|
+
* lineage currency on the same pinned execution session before it admits DDL.
|
|
2682
|
+
* Callers must still take the ledger locks before claiming; this check avoids a
|
|
2683
|
+
* preflight-only trust decision without widening the ledger DDL grammar.
|
|
2684
|
+
*/
|
|
2685
|
+
declare function validatePgLedgerRuntimeIntegrity(executor: TransitionJournalQueryable, homes: readonly PgLedgerTarget[], run?: PgLockedRun, seams?: RuntimeIntegritySeams): Promise<OutcomeProtocolRefusal | undefined>;
|
|
2686
|
+
/**
|
|
2687
|
+
* Appends a resolution once, or treats an already-written equal payload as a
|
|
2688
|
+
* successful retry. A different child cannot be written by PostgreSQL's
|
|
2689
|
+
* one-child constraint and is reported as a fail-closed malformed outcome.
|
|
2690
|
+
*/
|
|
2691
|
+
declare function appendPgOutcomeResolution(executor: TransitionJournalQueryable, target: PgLedgerTarget, member: Omit<LedgerChainMember, 'controller' | 'recordedAt'>, rootClaimId: string, reservations: readonly Pick<LedgerReservationRow, 'address'>[]): Promise<PgOutcomeResolutionAppendResult>;
|
|
2692
|
+
/**
|
|
2693
|
+
* Standalone PostgreSQL catalogue read-back. This intentionally does not
|
|
2694
|
+
* issue LOCK TABLE: callers may supply a Pool, and protocol atomicity belongs
|
|
2695
|
+
* to the transaction-bound recovery and observed-resolution paths.
|
|
2696
|
+
*/
|
|
2697
|
+
declare function readPgOutcomeRecoveryReadBack(executor: TransitionJournalQueryable, address: LedgerAddress, readBack: PgOutcomeReadBackFactory, operationReadBack?: PgOutcomeOperationReadBackFactory, lockTimeoutMs?: number): Promise<OutcomeRecoveryReadBack>;
|
|
2698
|
+
/** Opens a claim on one connection when supplied a PostgreSQL pool. */
|
|
2699
|
+
declare function openPgOutcomeClaim(executor: TransitionJournalQueryable, request: PgOutcomeClaimRequest, run?: PgLockedRun): Promise<OutcomeClaimAdmission>;
|
|
2700
|
+
/**
|
|
2701
|
+
* Opens a root and all closure claims under globally ordered ledger locks in
|
|
2702
|
+
* one transaction. No child is ever durable before its root group commits.
|
|
2703
|
+
*/
|
|
2704
|
+
declare function openPgOutcomeClaimGroup(executor: TransitionJournalQueryable, request: PgOutcomeClaimGroupRequest, run?: PgLockedRun): Promise<PgOutcomeClaimGroupAdmission>;
|
|
2705
|
+
/** Resolves every member terminal atomically under the same ordered locks. */
|
|
2706
|
+
declare function resolvePgOutcomeClaimGroup(executor: TransitionJournalQueryable, request: PgOutcomeClaimGroupResolution): Promise<undefined | OutcomeProtocolRefusal>;
|
|
2707
|
+
/**
|
|
2708
|
+
* The public PostgreSQL admitted-execution boundary. It is intentionally not
|
|
2709
|
+
* used by legacy paths yet: later dispatches bind their persisted runs and
|
|
2710
|
+
* operation shapes here without changing this authority surface.
|
|
2711
|
+
*/
|
|
2712
|
+
declare function executePgAdmittedOperation(session: TransitionJournalQueryable, input: {
|
|
2713
|
+
readonly run: PgLockedRun;
|
|
2714
|
+
readonly operation: PgAdmittedOperation;
|
|
2715
|
+
readonly approval: ScopedApprovalSet;
|
|
2716
|
+
/** Branded proof that the operation came from the normalized manifest. */
|
|
2717
|
+
readonly manifest?: ValidatedManagedStepManifest;
|
|
2718
|
+
/** Recomputed from the durable plan while the caller owns its run lock. */
|
|
2719
|
+
readonly recomputedPlanDigest?: string;
|
|
2720
|
+
}): Promise<PgAdmittedOperationResult>;
|
|
2721
|
+
/**
|
|
2722
|
+
* Reads an address's chain and live catalogue in one locked transaction before
|
|
2723
|
+
* appending the core classifier's instruction. It never calls the DDL sink.
|
|
2724
|
+
*/
|
|
2725
|
+
declare function recoverPgOutcomeClaim(executor: TransitionJournalQueryable, request: PgOutcomeRecoveryRequest): Promise<PgOutcomeRecoveryResult>;
|
|
2726
|
+
|
|
2727
|
+
export { type PgAdvisoryLockResult as $, type AddedEnumValue as A, GeneratedPostconditionReplanRequiredError as B, type ChangeKind as C, DEFAULT_PK_COLUMN as D, ExpressionCanonicalizationUnavailableError as E, type FkColumnDerivation as F, type GeneratedPostconditionSession as G, GeneratedPostconditionSessionDeactivatedError as H, GeneratedPostconditionWorkInFlightError as I, IdentityNamingPlugin as J, type IndexCapabilityContext as K, IndexFeatureUnsupportedError as L, IndexPredicateCanonicalizationError as M, type NamingPlugin as N, type IndexRenderSpec as O, type PgLockedRun as P, type IntrospectedModelIR as Q, type IntrospectionOptions as R, type MigrationSQLOptions as S, type TransitionJournalQueryable as T, NonConvergentSchemaDiffError as U, type NonConvergentSchemaDiffSurface as V, PG_LEDGER_SHAPE_VERSION as W, PartialIndexPredicateNewEnumValueError as X, type PgAdmittedOperation as Y, type PgAdmittedOperationResult as Z, type PgAdvisoryLockKey as _, type PgOutcomeCheckpointObserver as a, assertCreateIndexesSupported as a$, type PgApplicationStepOwnedState as a0, type PgApplicationStepTx as a1, type PgCatalogueIdentityQueryable as a2, type PgConvergeApplicationStep as a3, type PgConvergeAssertStep as a4, type PgConvergeInitializationFailure as a5, type PgConvergeOnceStep as a6, type PgConvergePlannedStep as a7, type PgConvergeRefusal as a8, type PgConvergeRefusalChange as a9, type PgsqlAdapterOptions as aA, PgsqlAdvisoryLockOptionsError as aB, type PgsqlBorrowedClientAdapterOptions as aC, type PgsqlCompileOnlyAdapterOptions as aD, PgsqlPinnedConnectionAbortSignalError as aE, type PgsqlPoolAdapterOptions as aF, PgsqlPreparedStatementReplayError as aG, type PgsqlPreparedStatementsOptions as aH, PgsqlRawSqlTransactionControlError as aI, PgsqlTransactionAbortSignalError as aJ, PgsqlTransactionAbortedCommitError as aK, PgsqlTransactionAbortedError as aL, PgsqlTransactionOptionsError as aM, PgsqlTransactionTimeoutError as aN, RawIndexPredicateFallbackError as aO, type ReferencedKeyKind as aP, type ReferencedKeyRemovalConflict as aQ, ReferencedKeyRemovalError as aR, type RollbackOnlyPgsqlScope as aS, type SchemaChange as aT, type SchemaDiff as aU, type SchemaScopeOptions as aV, TransitionRunIdentityMismatchError as aW, acquirePgLedgerLocks as aX, appendIntentJournal as aY, appendTransitionAuthorization as aZ, assertCreateIndexSupported as a_, PgConvergeRefusalError as aa, type PgLedgerLockResult as ab, PgLedgerStorageUnsupportedError as ac, type PgLedgerTarget as ad, type PgOutcomeCheckpoint as ae, type PgOutcomeClaimRequest as af, type PgOutcomeExecutionRequest as ag, type PgOutcomeNonTransactionalRequest as ah, type PgOutcomeReadBackFactory as ai, type PgOutcomeRecoveryRequest as aj, type PgOutcomeRecoveryResult as ak, type PgOutcomeResolution as al, type PgOutcomeResolutionAppendResult as am, type PgOutcomeResult as an, type PgOutcomeTransactionalRequest as ao, type PgOwnedCheckState as ap, type PgPhysicalModelInput as aq, PgPhysicalModelInputError as ar, type PgPhysicalNameClaim as as, type PgPhysicalNameCollision as at, PgPhysicalNameCollisionError as au, type PgPhysicalNamespace as av, type PgReinitializePreflightOptions as aw, type PgReinitializePreflightPool as ax, type PgSchemaDiff as ay, PgsqlAdapter as az, type ConvergePgOptions as b, type ComparePgsqlDeclaredAdoptionSchemaInput as b$, assertDeclarableChangeKind as b0, assertGeneratedPostconditionSession as b1, assertNoRepeatedExpressionSurfaceDrift as b2, camelCaseNaming as b3, canGenerateCreateIndex as b4, canonicalizeCheckConstraints as b5, comparePgsqlDatabaseSchema as b6, compareSchemata as b7, createPgPhysicalModel as b8, createPgTransitionRunPersister as b9, recordPgLedgerIdentity as bA, renderCreateDbspMetaSchemaSql as bB, renderCreateIndex as bC, renderCreateLedgerEventTableSql as bD, renderCreateLedgerIdentityTableSql as bE, renderCreateLedgerImmutabilityFunctionSql as bF, renderCreateLedgerImmutabilityTriggerSql as bG, renderCreateLedgerMarkerTableSql as bH, renderCreateLedgerReservationTableSql as bI, renderCreateLedgerTerminalMemberIndexSql as bJ, renderCreateTransitionAuthorizationTableSql as bK, renderCreateTransitionJournalTableSql as bL, renderCreateTransitionRunPlanTableSql as bM, renderCreateTransitionRunTableSql as bN, runPgReinitializePreflight as bO, toGeneratedPostconditionBindingAddress as bP, validatePgLedgerRuntimeIntegrity as bQ, verifyGeneratedCheckPostcondition as bR, verifyGeneratedColumnPostcondition as bS, verifyGeneratedIdentityPostcondition as bT, verifyGeneratedIndexPostcondition as bU, verifyGeneratedTablePostcondition as bV, withGeneratedPostconditionSession as bW, type PgOrderedLedgerLocks as bX, type PgLedgerShapeAllowance as bY, type PgLedgerPhysicalShapeOutcome as bZ, type ComparePgsqlDatabaseSchemaOptions$1 as b_, createPgsqlAdapter as ba, createPgsqlCompileOnlyAdapter as bb, createPgsqlGeneratedManagedStep as bc, decodeGeneratedPostcondition as bd, decodeGeneratedPostconditionPayload as be, defaultFkDerivation as bf, ensureDbspMetaLedger as bg, ensurePgLedger as bh, ensurePgLedgerStorageVersion as bi, ensureTransitionJournal as bj, executePgAdmittedOperation as bk, generateCreateIndex as bl, generateDDL as bm, generateDownSQL as bn, generateMigrationSQL as bo, generatedPostconditionDigest as bp, generatedPostconditionForChange as bq, getNamingPluginForDbCasing as br, identityNaming as bs, introspect as bt, readPgCatalogueIdentity as bu, readPgLedgerMarker as bv, readPgLedgerReservationsForExecution as bw, readPgLedgerScopeCurrency as bx, readPgOutcomeRecoveryReadBack as by, readVerifiedPgLedgerReservationsForPair as bz, type PgPhysicalModel as c, type CompareSchemataOptions$1 as c0, type ConvergePgBaseOptions as c1, type ConvergePgCheckOptions as c2, type GenerateDDLOptions$1 as c3, type MigrationSQLOptions$1 as c4, PgCommitAcknowledgementAmbiguousError as c5, type PgsqlAdoptionComparisonExecutor as c6, appendPgLedgerClaim as c7, appendPgLedgerClaimGroup as c8, appendPgLedgerProgress as c9, resolvePgDestructiveOutcome as cA, resolvePgOutcomeClaimGroup as cB, appendPgLedgerRelease as ca, appendPgLedgerResolution as cb, appendPgLedgerResolutionGroup as cc, appendPgOutcomeResolution as cd, classifyPgLedgerPhysicalShape as ce, collectReferencedKeyRemovalConflicts as cf, comparePgsqlDatabaseSchema$1 as cg, comparePgsqlDeclaredAdoptionSchema as ch, compareSchemata$1 as ci, convergePg as cj, createPgLedgerShapeAllowance as ck, createPgsqlDeclaredAdoptionStep as cl, createPgsqlDeclaredSequenceAdoptionStep as cm, executePgDestructiveOutcome as cn, generateDDL$1 as co, generateDownSQL$1 as cp, generateMigrationSQL$1 as cq, lockPgJournalRun as cr, modelForDeclaredAdoption as cs, openPgOutcomeClaim as ct, openPgOutcomeClaimGroup as cu, pgsqlDeclaredAdoptionDeclaration as cv, pgsqlDeclaredSequenceAdoptionDeclaration as cw, readPgLedgerReservationsForPair as cx, recoverPgAdmittedReaddressPair as cy, recoverPgOutcomeClaim as cz, type PgConvergeResult as d, type PgConvergeCheckResult as e, type PgLedgerScopeCurrency as f, AutoIncrementTransitionUnsupportedError as g, CamelCaseNamingPlugin as h, type CanonicalizeCheckConstraintsOptions as i, CheckConstraintCanonicalizationError as j, type CheckConstraintCanonicalizationWarning as k, CheckConstraintNewEnumValueError as l, ColumnDefaultCanonicalizationError as m, type ColumnDefaultCanonicalizationWarning as n, type ComparePgsqlDatabaseSchemaOptions as o, type CompareSchemataOptions as p, type DetectedHierarchy as q, readTransitionJournal as r, type DiffSummary as s, type ExpressionCanonicalizationWarning as t, ExpressionKeyedIndexPredicateCanonicalizationUnsupportedError as u, type GenerateDDLOptions as v, type GeneratedPostcondition as w, type GeneratedPostconditionBindingAddress as x, GeneratedPostconditionBindingResolutionError as y, GeneratedPostconditionProofInFlightError as z };
|