@dbsp/adapter-pgsql 2.0.0 → 3.1.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/dist/index.d.ts CHANGED
@@ -1,7 +1,8 @@
1
- import { ExpressionRef, IndexInfo, TruncateOptions, VacuumOptions, AlterColumnOptions, CreateIndexOptions, DropIndexOptions, ModelIR as ModelIR$1 } from '@dbsp/core';
1
+ import * as _dbsp_core from '@dbsp/core';
2
+ import { IndexInfo, TruncateOptions, VacuumOptions, AlterColumnOptions, CreateIndexOptions, DropIndexOptions, ExpressionRef, ModelIR as ModelIR$1, ExecutionCoordinator, CapabilityDescriptor } from '@dbsp/core';
2
3
  export { normalizeSQL } from '@dbsp/core';
3
4
  import * as _dbsp_types from '@dbsp/types';
4
- import { DialectCapabilities, ModelIR, ColumnListInput, ParamIntent, JsonAggOrderByEntry, IndexIR, DbCasing, ColumnIR, HierarchyIR, MutationReturningItem, WhereIntent, Adapter, AdapterLogger, AdapterCapabilities, PlanReport, CompiledNqlQuery, CompileOptions, CompiledQuery, CompileResultWithIncludes, SubqueryIncludeInfo, ExpressionIntent, InsertIntent, InsertFromIntent, UpdateIntent, BatchUpdateIntent, DeleteIntent, UpsertIntent, UpsertFromIntent, RecursivePlanReport, CteQueryIntent, SetOperationIntent, DumpMeta, Dump, AdapterStreamOptions, CompileOnlyAdapter, QueryIntent } from '@dbsp/types';
5
+ import { DialectCapabilities, ModelIR, ColumnListInput, ParamIntent, JsonAggOrderByEntry, IndexIR, HierarchyIR, Adapter, DbCasing, AdapterLogger, AdapterCapabilities, PlanReport, CompiledNqlQuery, CompileOptions, CompiledQuery, CompileResultWithIncludes, SubqueryIncludeInfo, ExpressionIntent, InsertIntent, InsertFromIntent, UpdateIntent, BatchUpdateIntent, DeleteIntent, UpsertIntent, UpsertFromIntent, RecursivePlanReport, CteQueryIntent, SetOperationIntent, DumpMeta, Dump, AdapterStreamOptions, CompileOnlyAdapter, ColumnIR, MutationReturningItem, WhereIntent, OutputDescriptor, QueryIntent, OperationKindRef, SemanticArtifactRef, TransitionRunJournal, ObservationIssuer, ObservationContext, TypeRef, ExpressionValue, CollationRef, LogicalIdentity, PhysicalOperation, OperationEffectAssessment, EvidenceObservation, FingerprintManifest, DurableIntentRecord, IssuedObservation, ApplyGuard, AdvisoryObservation, TransactionalCompletionRecord, StepJournal, UnsafeNativeFragment, ResourceAddress, ExecutableAssertion, Assumption, TransitionRule, TransitionCompositionFact, TrustRoot, RequiredEnumLabelIR } from '@dbsp/types';
5
6
  import * as _pgsql_types from '@pgsql/types';
6
7
  import { Node, OnConflictClause, ParamRef } from '@pgsql/types';
7
8
  import { Pool, PoolClient } from 'pg';
@@ -727,6 +728,39 @@ declare class PlanCompiler {
727
728
  */
728
729
  declare function compilePlan(plan: SimplifiedPlanReport, options?: CompilerOptions): CompiledResult;
729
730
 
731
+ type IndexRenderKey = {
732
+ readonly column?: string | undefined;
733
+ readonly expression?: string | undefined;
734
+ readonly opclass?: string | undefined;
735
+ };
736
+ type IndexRenderSpec = {
737
+ readonly name: string;
738
+ readonly table: string;
739
+ readonly schema?: string | undefined;
740
+ readonly unique: boolean;
741
+ readonly method?: string | undefined;
742
+ readonly keys: readonly IndexRenderKey[];
743
+ readonly include?: readonly string[] | undefined;
744
+ readonly nullsNotDistinct?: boolean | undefined;
745
+ readonly with?: Readonly<Record<string, unknown>> | undefined;
746
+ readonly where?: string | undefined;
747
+ readonly concurrently?: boolean | undefined;
748
+ readonly ifNotExists?: boolean | undefined;
749
+ };
750
+ type IndexCapabilityContext = {
751
+ readonly caps: DialectCapabilities;
752
+ readonly targetVersion?: string | undefined;
753
+ };
754
+ type IndexFeature = 'INCLUDE' | 'PARTIAL INDEX' | 'EXPRESSION INDEX' | 'INDEX METHOD' | 'OPCLASS' | 'NULLS NOT DISTINCT';
755
+ declare class IndexFeatureUnsupportedError extends Error {
756
+ readonly indexName: string;
757
+ readonly unsupportedFeatures: readonly IndexFeature[];
758
+ constructor(indexName: string, unsupportedFeatures: readonly IndexFeature[], message: string);
759
+ }
760
+ declare function assertCreateIndexSupported(spec: IndexRenderSpec, ctx?: IndexCapabilityContext): void;
761
+ declare function assertCreateIndexesSupported(specs: readonly IndexRenderSpec[], ctx?: IndexCapabilityContext): void;
762
+ declare function renderCreateIndex(spec: IndexRenderSpec, ctx?: IndexCapabilityContext): string;
763
+
730
764
  /**
731
765
  * DDL Generator - Generates PostgreSQL DDL statements from ModelIR
732
766
  *
@@ -753,7 +787,7 @@ interface GenerateDDLOptions {
753
787
  readonly fkAutoIndex?: boolean;
754
788
  /** Naming plugin for identifier transformation */
755
789
  readonly naming?: NamingPlugin;
756
- /** Dialect capabilities — DDL passes for unsupported features will be skipped */
790
+ /** Dialect capabilities — unsupported index features throw during DDL generation */
757
791
  readonly dialectCapabilities?: DialectCapabilities;
758
792
  }
759
793
  /**
@@ -769,7 +803,7 @@ interface GenerateDDLOptions {
769
803
  * @returns Array of DDL statements in dependency order
770
804
  */
771
805
  declare function generateDDL(schema: ModelIR, options?: GenerateDDLOptions): string[];
772
- declare function generateCreateIndex(tableName: string, idx: IndexIR, schemaName: string | undefined, naming: NamingPlugin): string;
806
+ declare function generateCreateIndex(tableName: string, idx: IndexIR, schemaName: string | undefined, naming: NamingPlugin, context?: IndexCapabilityContext): string;
773
807
  /**
774
808
  * Returns whether the PostgreSQL DDL generator can emit this IndexIR.
775
809
  *
@@ -780,912 +814,168 @@ declare function generateCreateIndex(tableName: string, idx: IndexIR, schemaName
780
814
  declare function canGenerateCreateIndex(tableName: string, idx: IndexIR, schemaName?: string | undefined, naming?: NamingPlugin): boolean;
781
815
 
782
816
  /**
783
- * Schema Comparison Engine (DDL-PROV Block 1)
817
+ * PostgreSQL Schema Introspection (ADAPTER-006)
784
818
  *
785
- * Compares two ModelIRs (schema definition vs database state)
786
- * and produces a structured diff of changes needed.
819
+ * Queries information_schema/pg_catalog to build ModelIR
820
+ * from an existing database. Supports:
821
+ * - Table/column/PK discovery
822
+ * - FK → bidirectional relation inference
823
+ * - Hierarchy detection (adjacency + edge-table)
824
+ * - Include/exclude filtering
787
825
  *
788
- * @module schema-diff
826
+ * @module introspection
789
827
  */
790
828
 
791
- type ChangeKind = 'create_table' | 'drop_table' | 'add_column' | 'drop_column' | 'alter_column_type' | 'alter_column_nullable' | 'alter_column_default' | 'alter_column_unique' | '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';
792
- interface SchemaChange {
793
- readonly kind: ChangeKind;
794
- readonly table: string;
795
- readonly column?: string;
796
- readonly destructive: boolean;
797
- readonly details: string;
798
- /** Additional metadata for SQL generation */
799
- readonly meta?: Readonly<Record<string, unknown>>;
800
- }
801
- interface DiffSummary {
802
- readonly tables: {
803
- readonly added: number;
804
- readonly dropped: number;
805
- };
806
- readonly columns: {
807
- readonly added: number;
808
- readonly dropped: number;
809
- readonly altered: number;
810
- };
811
- readonly indexes: {
812
- readonly added: number;
813
- readonly dropped: number;
814
- };
815
- readonly constraints: {
816
- readonly added: number;
817
- readonly dropped: number;
818
- readonly altered: number;
819
- };
820
- }
821
- interface SchemaDiff {
822
- readonly changes: readonly SchemaChange[];
823
- readonly hasDestructive: boolean;
824
- readonly summary: DiffSummary;
825
- }
826
- interface CompareSchemataOptions {
827
- /**
828
- * Database naming convention.
829
- * When set, schema model names (camelCase) are converted to DB format
830
- * (e.g. snake_case) before comparison with the introspected model.
831
- */
832
- dbCasing?: DbCasing;
833
- /** Dialect capabilities — comparisons for unsupported features will be skipped */
834
- readonly dialectCapabilities?: DialectCapabilities;
835
- /**
836
- * When `true`, extensions present in the live DB but absent from the model
837
- * schema are silently ignored — no `drop_extension` change is emitted for them.
838
- * Only extensions explicitly declared in the model are managed (created if missing).
839
- *
840
- * Use this when the database image pre-installs extensions that the application
841
- * schema does not own (e.g. pgvector, pg_search bundled in a custom Postgres image).
842
- * Default: `false` (full-sync behaviour — unmanaged DB extensions produce a
843
- * `drop_extension` entry).
844
- */
845
- readonly ignoreUnmanagedExtensions?: boolean;
829
+ /** The minimum every schema-level operation needs: which schema. */
830
+ interface SchemaScopeOptions {
831
+ /** Schema name to operate on (default: 'public') */
832
+ readonly schema?: string;
846
833
  }
847
834
  /**
848
- * Compare two ModelIRs and produce a structured diff.
849
- *
850
- * @param schema - The desired schema (from definition)
851
- * @param db - The current database state (from introspection)
852
- * @param options - Optional comparison settings (e.g. dbCasing)
853
- * @returns SchemaDiff with all changes needed to bring DB in sync with schema
835
+ * Introspection additionally chooses WHICH TABLES to read. It is a read-only
836
+ * path, so narrowing it is safe — that is why the table filters live here and
837
+ * nowhere else.
854
838
  */
855
- declare function compareSchemata(schema: ModelIR, db: ModelIR, options?: CompareSchemataOptions): SchemaDiff;
856
-
839
+ interface IntrospectionOptions extends SchemaScopeOptions {
840
+ /** Tables to exclude (glob patterns: * matches any chars) */
841
+ readonly exclude?: readonly string[];
842
+ /** Tables to include (default: all). Applied before exclude. */
843
+ readonly include?: readonly string[];
844
+ }
845
+ /** Hierarchy pattern detected during introspection */
857
846
  /**
858
- * Migration SQL Generator (DDL-PROV Block 1)
859
- *
860
- * Generates ordered SQL statements from a SchemaDiff.
861
- * Statements are topologically sorted: DROP constraints → DROP objects → CREATE objects → ADD constraints.
862
- *
863
- * @module migration-sql
847
+ * Hierarchy pattern detected during introspection.
848
+ * Alias of {@link HierarchyIR} from \@dbsp/types — kept here for
849
+ * public-API backwards compatibility (re-exported from \@dbsp/adapter-pgsql).
864
850
  */
865
-
866
- interface MigrationSQLOptions {
867
- /**
868
- * Schema namespace (default: none — unqualified).
869
- * Required when emitted migration SQL would otherwise mix non-default
870
- * target-scoped custom types/enums with unqualified table SQL.
871
- */
872
- readonly schemaName?: string;
873
- /** Whether to include destructive changes (drops) */
874
- readonly includeDestructive?: boolean;
875
- /** Automatically create indexes on FK columns for new tables (default: true) */
876
- readonly fkAutoIndex?: boolean;
877
- /** Dialect capabilities — migration SQL for unsupported features will be filtered */
878
- readonly dialectCapabilities?: DialectCapabilities;
851
+ type DetectedHierarchy = HierarchyIR;
852
+ /** Extended ModelIR with hierarchy metadata */
853
+ interface IntrospectedModelIR extends ModelIR {
854
+ readonly hierarchies: readonly DetectedHierarchy[];
855
+ readonly introspectedAt: Date;
856
+ readonly warnings: readonly string[];
879
857
  }
880
858
  /**
881
- * Generate ordered SQL statements from a SchemaDiff.
859
+ * Introspect a database through a pool.
882
860
  *
883
- * Topological order:
884
- * 0. DROP FK/CHECK constraints (must drop before referenced tables)
885
- * 1. DROP indexes
886
- * 2. DROP columns
887
- * 3. DROP primary keys
888
- * 4. DROP tables, DROP ENUMs
889
- * 5. CREATE ENUMs (must exist before tables that use them)
890
- * 6. CREATE tables
891
- * 7. ADD columns
892
- * 8. ALTER columns (type, nullable, default)
893
- * 9. ADD primary keys / column UNIQUE constraints
894
- * 10. ADD FK constraints (must add after referenced tables exist)
895
- * 11. ALTER FK (drop + re-add)
896
- * 12. CREATE indexes
897
- * 13. ADD CHECK constraints
898
- * 14. ALTER ENUM ADD VALUE (must be last — has transaction visibility caveats in PG)
899
- * 15. COMMENT ON TABLE / COLUMN (very last)
900
- */
901
- declare function generateMigrationSQL(diff: SchemaDiff, options?: MigrationSQLOptions): readonly string[];
902
- /**
903
- * Generate ordered DOWN SQL statements from a SchemaDiff.
861
+ * This does NOT accept a checked-out `PoolClient`, and that is deliberate. A
862
+ * client may be sitting inside a transaction that belongs to its owner, and a
863
+ * catalog query that fails there aborts *their* transaction. Protecting that
864
+ * needs a savepoint, and knowing whether to take one needs the caller to say
865
+ * whose transaction it is — which is what `PgsqlAdapter`'s `borrowedClient`
866
+ * declaration is for. Guessing it from the object's shape is the exact defect
867
+ * this adapter was rewritten to remove.
904
868
  *
905
- * Reverses the topological order used in UP migrations:
906
- * phases run in descending order (11, 10, 9, ..., 0).
869
+ * Saying so in a comment is not enough: `CatalogQueryExecutor` is structural, so
870
+ * a `PoolClient` — which has a `query()` — satisfies it, and the prose would have
871
+ * been the only thing standing in the way. It is branded instead, and only the
872
+ * adapter's own protected executor carries the brand. A client cannot be passed
873
+ * here at all.
907
874
  *
908
- * Irreversible changes (drops that lose data) produce SQL WARNING comments.
875
+ * So: hold a client, use `new PgsqlAdapter(client, { borrowedClient: true })`
876
+ * and call `.introspect()` on it.
909
877
  */
910
- declare function generateDownSQL(diff: SchemaDiff, options?: MigrationSQLOptions): readonly string[];
878
+ declare function introspect(pool: Pool, options?: IntrospectionOptions): Promise<IntrospectedModelIR>;
911
879
 
912
880
  /**
913
- * Migration File Format v2 — UP + DOWN sections.
914
- *
915
- * File format:
916
- * -- dbsp:destructive: true|false
917
- * <UP statements>;
918
- * -- DOWN
919
- * <DOWN statements>;
881
+ * PgsqlAdapter - Implements the Adapter interface for PostgreSQL using native pg driver.
920
882
  *
921
- * The separator `-- DOWN` must be on its own line (SC-25).
883
+ * This adapter wraps a pg Pool instance and provides the unified
884
+ * adapter interface for the db-semantic-planner ORM.
922
885
  *
923
- * @module ddl/migration-file
886
+ * @module pgsql-adapter
924
887
  */
925
888
 
926
- /**
927
- * Result of parsing a migration file's UP/DOWN sections.
928
- */
929
- interface ParsedMigrationFile {
930
- readonly upStatements: readonly string[];
931
- readonly downStatements: readonly string[];
932
- readonly hasDown: boolean;
933
- readonly destructive?: boolean | undefined;
889
+ declare class PgsqlRawSqlTransactionControlError extends Error {
890
+ readonly dbspRawSqlTransactionControl = true;
891
+ constructor(cause: unknown);
934
892
  }
935
- /**
936
- * Generate a migration file content with UP and DOWN sections.
937
- */
938
- declare function generateMigrationFile(diff: SchemaDiff, options?: MigrationSQLOptions & {
939
- name?: string;
940
- }): string;
941
- /**
942
- * Parse a migration file into UP and DOWN sections.
943
- * Separator: `^\s*-- DOWN\s*$` (strict regex, own line only — SC-25)
944
- */
945
- declare function parseMigrationFile(content: string): ParsedMigrationFile;
946
- /**
947
- * Check if SQL statements contain destructive operations.
948
- * Destructive: DROP TABLE, DROP COLUMN, lossy ALTER COLUMN TYPE
949
- */
950
- declare function isDestructiveDown(downStatements: readonly string[]): boolean;
951
-
952
- /**
953
- * Migration Tracker — `_dbsp_migrations` table CRUD.
954
- *
955
- * Manages the tracking table that records which migrations
956
- * have been applied to a database.
957
- */
958
-
959
- interface MigrationRecord {
960
- /** Migration filename (e.g., "0001_create_users.sql") */
961
- readonly name: string;
962
- /** SHA-256 checksum of the migration file content */
963
- readonly checksum: string;
964
- /** When the migration was applied */
965
- readonly appliedAt: Date;
966
- /** Schema version at time of this migration */
967
- readonly schemaVersion: number;
968
- /** Whether this migration contains destructive changes */
969
- readonly destructive: boolean;
893
+ declare class PgsqlTransactionAbortedCommitError extends Error {
894
+ readonly dbspTransactionAbortedCommit = true;
895
+ constructor(cause: unknown);
896
+ }
897
+ declare class PgsqlTransactionAbortedError extends Error {
898
+ readonly dbspTransactionAborted = true;
899
+ constructor(cause: unknown);
970
900
  }
971
901
  /**
972
- * Execute a callback under an advisory lock using a dedicated client.
973
- * The lock is held for the duration of the callback.
974
- * The client is released (and lock freed) after the callback completes.
975
- */
976
- declare function withMigrationLock<T>(pool: Pool, fn: (client: PoolClient) => Promise<T>): Promise<T>;
977
- /**
978
- * Ensure the migrations tracking table exists.
979
- * Auto-migrates existing tables that lack `schema_version`/`destructive` columns,
980
- * and backfills `schema_version` by `applied_at` order for rows still at 0.
981
- */
982
- declare function ensureMigrationsTable(pool: Pool): Promise<void>;
983
- /**
984
- * Get all applied migrations, ordered by name.
902
+ * Options for PgsqlAdapter.
985
903
  */
986
- declare function getAppliedMigrations(pool: Pool): Promise<readonly MigrationRecord[]>;
904
+ interface PgsqlAdapterOptions {
905
+ /** Schema name for multi-tenant queries */
906
+ readonly schemaName?: string;
907
+ /**
908
+ * DB column casing convention (intuitive semantics).
909
+ * - `'snake_case'`: DB columns are snake_case → transform to camelCase for JS
910
+ * - `'camelCase'`: DB columns are camelCase → no transformation
911
+ * - `'preserve'`: No transformation
912
+ */
913
+ readonly dbCasing?: DbCasing;
914
+ /** Optional model for WHERE compilation */
915
+ readonly model?: ModelIR;
916
+ /** Optional logger for debug/error messages */
917
+ readonly logger?: AdapterLogger;
918
+ /** Default primary key column name for convention fallbacks (default: 'id') */
919
+ readonly defaultPkColumnName?: string;
920
+ /** Convention for deriving FK column names: (tableName, pkName) => fkColumnName */
921
+ readonly deriveFkColumnName?: FkColumnDerivation;
922
+ }
923
+ interface PgsqlPoolAdapterOptions extends PgsqlAdapterOptions {
924
+ readonly borrowedClient?: false;
925
+ }
926
+ interface PgsqlBorrowedClientAdapterOptions extends PgsqlAdapterOptions {
927
+ /** This connection belongs to the caller. dbsp never releases it. */
928
+ readonly borrowedClient: true;
929
+ /**
930
+ * Let dbsp run transactions on your connection, through a savepoint.
931
+ *
932
+ * When your connection is already inside a transaction, dbsp creates a
933
+ * savepoint and rolls back dbsp's changes after that savepoint if the callback
934
+ * fails. `RELEASE SAVEPOINT` does not commit; it merges the work into your
935
+ * surrounding transaction, so a callback that succeeded is still undone if you
936
+ * later roll back. Deferred constraints or triggers can still make your outer
937
+ * `COMMIT` fail after dbsp has returned. `SET LOCAL` changes inside the callback
938
+ * remain in effect for the rest of your transaction after the savepoint is
939
+ * released. `ON COMMIT DROP` and `ON COMMIT DELETE ROWS` fire at your transaction
940
+ * boundary, not at the savepoint. Sequences are not transactional:
941
+ * `nextval`/`setval` are not reclaimed by a savepoint rollback. Session-level
942
+ * advisory locks ignore rollback; transaction-level advisory locks taken by a
943
+ * successful callback last until your transaction ends.
944
+ *
945
+ * Transaction control through raw SQL inside a scope dbsp is managing is
946
+ * unsupported. `COMMIT`, `ROLLBACK`, and `PREPARE TRANSACTION` end the
947
+ * transaction dbsp is working inside; dbsp detects that and fails loudly, but
948
+ * the data is already whatever your statement made it. Raw savepoint control
949
+ * (`SAVEPOINT`, `RELEASE SAVEPOINT`, `ROLLBACK TO SAVEPOINT`) can alter the
950
+ * savepoint stack before dbsp sees the command tag; dbsp poisons the scope, but
951
+ * it cannot make that command un-run. Manage your transaction outside dbsp's
952
+ * calls.
953
+ */
954
+ readonly managedTransactions?: true;
955
+ }
987
956
  /**
988
- * Record a migration as applied.
989
- */
990
- declare function recordMigration(pool: Pool, name: string, checksum: string, schemaVersion: number, destructive: boolean): Promise<void>;
991
- /**
992
- * Check if a specific migration has been applied.
993
- */
994
- declare function isMigrationApplied(pool: Pool, name: string): Promise<boolean>;
995
- /**
996
- * Get the next schema version number (max + 1, or 1 if no migrations).
997
- */
998
- declare function getNextSchemaVersion(pool: Pool): Promise<number>;
999
- /**
1000
- * Remove a migration record (for rollback).
1001
- */
1002
- declare function removeMigrationRecord(pool: Pool, name: string): Promise<void>;
1003
-
1004
- /**
1005
- * Type Mapping - Maps ModelIR ColumnType to PostgreSQL data types
1006
- *
1007
- * Supports both manual schemas and introspected schemas (preserving originalDbType).
1008
- * Handles auto-increment via SERIAL/BIGSERIAL types.
1009
- *
1010
- * @module ddl/type-mapping
1011
- */
1012
-
1013
- /**
1014
- * Map ColumnType to PostgreSQL data type string.
1015
- *
1016
- * Uses originalDbType if available (from introspection), otherwise
1017
- * falls back to reasonable PostgreSQL defaults.
1018
- *
1019
- * @param col - Column definition from ModelIR
1020
- * @returns PostgreSQL type string (e.g., 'VARCHAR(255)', 'SERIAL', 'JSONB')
1021
- */
1022
- declare function mapColumnType(col: ColumnIR, targetSchema?: string): string;
1023
- /**
1024
- * Map OnDeleteAction to PostgreSQL syntax.
1025
- */
1026
- declare function mapOnDeleteAction(action?: string): string;
1027
-
1028
- /**
1029
- * EXPLAIN Statement Compiler
1030
- *
1031
- * Generates PostgreSQL EXPLAIN statements with various options.
1032
- * Supports:
1033
- * - ANALYZE (execute and show actual run times)
1034
- * - FORMAT (text, json, xml, yaml)
1035
- * - VERBOSE, COSTS, BUFFERS, TIMING, SETTINGS
1036
- */
1037
-
1038
- /**
1039
- * Output format for EXPLAIN results.
1040
- */
1041
- type ExplainFormat = 'text' | 'json' | 'xml' | 'yaml';
1042
- /**
1043
- * Options for EXPLAIN statement.
1044
- */
1045
- interface ExplainOptions {
1046
- /** Execute the query and show actual run times */
1047
- analyze?: boolean;
1048
- /** Show more detailed output */
1049
- verbose?: boolean;
1050
- /** Show cost estimates (default: true) */
1051
- costs?: boolean;
1052
- /** Show buffer usage (requires analyze) */
1053
- buffers?: boolean;
1054
- /** Show actual timing (requires analyze) */
1055
- timing?: boolean;
1056
- /** Show non-default settings */
1057
- settings?: boolean;
1058
- /** Output format */
1059
- format?: ExplainFormat;
1060
- }
1061
- /**
1062
- * Build an EXPLAIN statement wrapping a query.
1063
- *
1064
- * @param query - The query to explain (SelectStmt, InsertStmt, etc.)
1065
- * @param options - EXPLAIN options
1066
- * @returns ExplainStmt AST node
1067
- *
1068
- * @example
1069
- * ```typescript
1070
- * const selectAst = { SelectStmt: { ... } };
1071
- * const explainAst = buildExplain(selectAst, { analyze: true, format: 'json' });
1072
- * // Produces: EXPLAIN (ANALYZE, FORMAT JSON) SELECT ...
1073
- * ```
1074
- */
1075
- declare function buildExplain(query: Node, options?: ExplainOptions): Node;
1076
- /**
1077
- * Build EXPLAIN ANALYZE with JSON format (common pattern).
1078
- *
1079
- * @param query - The query to explain
1080
- * @returns ExplainStmt with ANALYZE and JSON format
1081
- */
1082
- declare function buildExplainAnalyzeJson(query: Node): Node;
1083
- /**
1084
- * Build simple EXPLAIN (plan only, no execution).
1085
- *
1086
- * @param query - The query to explain
1087
- * @returns ExplainStmt with default options
1088
- */
1089
- declare function buildExplainPlan(query: Node): Node;
1090
- /**
1091
- * Build verbose EXPLAIN with costs and buffers.
1092
- *
1093
- * @param query - The query to explain
1094
- * @returns ExplainStmt with verbose options
1095
- */
1096
- declare function buildExplainVerbose(query: Node): Node;
1097
- /**
1098
- * Parse EXPLAIN JSON output to get execution statistics.
1099
- *
1100
- * @param jsonOutput - The JSON string from EXPLAIN (ANALYZE, FORMAT JSON)
1101
- * @returns Parsed plan with execution statistics
1102
- */
1103
- declare function parseExplainJson(jsonOutput: string): ExplainPlan[];
1104
- /**
1105
- * Parsed EXPLAIN plan structure (simplified).
1106
- */
1107
- interface ExplainPlan {
1108
- Plan: {
1109
- 'Node Type': string;
1110
- 'Relation Name'?: string;
1111
- Alias?: string;
1112
- 'Startup Cost'?: number;
1113
- 'Total Cost'?: number;
1114
- 'Plan Rows'?: number;
1115
- 'Plan Width'?: number;
1116
- 'Actual Startup Time'?: number;
1117
- 'Actual Total Time'?: number;
1118
- 'Actual Rows'?: number;
1119
- 'Actual Loops'?: number;
1120
- Plans?: ExplainPlan['Plan'][];
1121
- };
1122
- 'Planning Time'?: number;
1123
- 'Execution Time'?: number;
1124
- Triggers?: unknown[];
1125
- }
1126
- /**
1127
- * Extract total execution time from EXPLAIN ANALYZE JSON output.
1128
- *
1129
- * @param plans - Parsed EXPLAIN plans
1130
- * @returns Total execution time in milliseconds
1131
- */
1132
- declare function getTotalExecutionTime(plans: ExplainPlan[]): number;
1133
- /**
1134
- * Extract row counts from EXPLAIN ANALYZE JSON output.
1135
- *
1136
- * @param plans - Parsed EXPLAIN plans
1137
- * @returns Object with estimated and actual row counts
1138
- */
1139
- declare function getRowEstimates(plans: ExplainPlan[]): {
1140
- estimated: number;
1141
- actual: number;
1142
- };
1143
-
1144
- /**
1145
- * ParadeDB Extension Wrappers
1146
- *
1147
- * Type-safe query builders for ParadeDB BM25 full-text search.
1148
- * All functions return ExpressionRef instances that can be used in:
1149
- * - SELECT: .column(score('id').as('score'))
1150
- * - WHERE: .where(bm25Search('symbols', query, { name: 3.0, doc: 1.0 }))
1151
- * - ORDER BY: .orderBy(score('id'), 'desc')
1152
- *
1153
- * @remarks
1154
- * ParadeDB functions accept both named and positional arguments.
1155
- * This module uses named args via namedArg() for parse(), which produces:
1156
- * paradedb.parse(field => 'field_name', query_string => $1)
1157
- * Named parameter syntax is supported via the NamedArgExpressionIntent (EXT-NAMED-PARAMS).
1158
- */
1159
-
1160
- /**
1161
- * BM25 relevance score for a row.
1162
- *
1163
- * Use in SELECT and ORDER BY to retrieve and sort by full-text relevance.
1164
- * Requires a BM25 index on the table.
1165
- *
1166
- * @param keyField - The key field of the BM25 index (typically the primary key, e.g. 'id')
1167
- * @returns ExpressionRef that compiles to: paradedb.score("keyField")
1168
- *
1169
- * @example
1170
- * orm.select('symbols').column(score('id').as('score')).orderBy(score('id'), 'desc')
1171
- * // → paradedb.score("id") AS "score"
1172
- */
1173
- declare function score(keyField: string): ExpressionRef;
1174
- /**
1175
- * Parse a single-field BM25 query expression.
1176
- *
1177
- * Compiles to: paradedb.parse(field => 'field_name', query_string => $N)
1178
- *
1179
- * @param field - Column name to search in (must be indexed in the BM25 index)
1180
- * @param query - Query string value (will be bound as a parameter)
1181
- * @returns ExpressionRef for use with boost() or booleanSearch()
1182
- *
1183
- * @example
1184
- * parse('name', 'hello world')
1185
- * // → paradedb.parse(field => 'name', query_string => $1)
1186
- */
1187
- declare function parse(field: string, query: ExpressionRef | unknown): ExpressionRef;
1188
- /**
1189
- * Apply a boost multiplier to a BM25 sub-expression.
1190
- *
1191
- * Compiles to: paradedb.boost(factor, expr)
1192
- *
1193
- * @param factor - Boost multiplier (e.g. 3.0 for 3x weight)
1194
- * @param expr - Expression to boost (typically a parse() call)
1195
- * @returns ExpressionRef for use with booleanSearch()
1196
- *
1197
- * @example
1198
- * boost(3.0, parse('name', 'hello'))
1199
- * // → paradedb.boost(3.0, paradedb.parse('name', $1))
1200
- */
1201
- declare function boost(factor: number, expr: ExpressionRef): ExpressionRef;
1202
- /**
1203
- * Combine multiple BM25 sub-expressions with boolean OR logic.
1204
- *
1205
- * Compiles to: paradedb.boolean(expr1, expr2, ...)
1206
- *
1207
- * @param exprs - One or more sub-expressions (typically boost() calls)
1208
- * @returns ExpressionRef for use on the right side of the @@@ operator
1209
- *
1210
- * @example
1211
- * booleanSearch([boost(3.0, parse('name', q)), boost(1.0, parse('doc', q))])
1212
- * // → paradedb.boolean(paradedb.boost(3.0, ...), paradedb.boost(1.0, ...))
1213
- */
1214
- /**
1215
- * Combine multiple BM25 sub-expressions with boolean OR logic.
1216
- *
1217
- * Compiles to: paradedb.boolean(should => ARRAY[expr1, expr2, ...])
1218
- *
1219
- * @param exprs - One or more sub-expressions (typically boost() calls)
1220
- * @returns ExpressionRef for use on the right side of the @@@ operator
1221
- *
1222
- * @example
1223
- * booleanSearch([boost(3.0, parse('name', q)), boost(1.0, parse('doc', q))])
1224
- * // → paradedb.boolean(should => ARRAY[paradedb.boost(3.0, ...), paradedb.boost(1.0, ...)])
1225
- */
1226
- declare function booleanSearch(exprs: ExpressionRef[]): ExpressionRef;
1227
- /**
1228
- * Full BM25 multi-field search with per-field boost weights.
1229
- *
1230
- * Produces: table @@@ paradedb.boolean(boost1, boost2, ...)
1231
- *
1232
- * Each field in `fieldBoosts` generates a `paradedb.boost(weight, paradedb.parse(field, $N))`
1233
- * sub-expression. The same query string is used for all fields (single parameter binding).
1234
- *
1235
- * @param table - Table alias for the left side of the @@@ operator
1236
- * @param query - Query string (bound as a single $N parameter, shared across all fields)
1237
- * @param fieldBoosts - Map of column name → boost weight
1238
- * @returns ExpressionRef for use in .where()
1239
- *
1240
- * @example
1241
- * bm25Search('s', searchTerm, {
1242
- * name_searchable: 3.0,
1243
- * name: 1.0,
1244
- * signature: 1.5,
1245
- * doc_searchable: 1.0,
1246
- * })
1247
- * // → s @@@ paradedb.boolean(
1248
- * // paradedb.boost(3.0, paradedb.parse('name_searchable', $1)),
1249
- * // paradedb.boost(1.0, paradedb.parse('name', $1)),
1250
- * // paradedb.boost(1.5, paradedb.parse('signature', $1)),
1251
- * // paradedb.boost(1.0, paradedb.parse('doc_searchable', $1))
1252
- * // )
1253
- *
1254
- * @remarks
1255
- * The query parameter is shared: all parse() calls reference the same $N slot.
1256
- * If you need different query strings per field, compose parse()/boost()/booleanSearch() manually.
1257
- *
1258
- * @remarks
1259
- * ParadeDB's boolean() function accepts both positional args and the named
1260
- * `should => ARRAY[...]` syntax. This wrapper uses positional args.
1261
- * Named parameter syntax is deferred to EXT-NAMED-PARAMS.
1262
- */
1263
- declare function bm25Search(table: string, query: unknown, fieldBoosts: Record<string, number>): ExpressionRef;
1264
-
1265
- /**
1266
- * PostgreSQL built-in function helpers.
1267
- *
1268
- * Thin wrappers around core expression primitives for common PostgreSQL functions.
1269
- * Same pattern as pgvector.ts and paradedb.ts.
1270
- */
1271
-
1272
- /**
1273
- * Generate a series of values: generate_series(start, stop[, step])
1274
- *
1275
- * Returns a set of values from start to stop (inclusive), with an optional step.
1276
- * Commonly used with CTE for batch operations.
1277
- *
1278
- * @example generateSeries(1, 100) → generate_series(1, 100)
1279
- * @example generateSeries(0, 50, 5) → generate_series(0, 50, 5)
1280
- */
1281
- declare function generateSeries(start: number, stop: number, step?: number): ExpressionRef;
1282
- /**
1283
- * Get next value from a sequence: nextval('sequence_name')
1284
- *
1285
- * @example nextval('order_id_seq') → nextval('order_id_seq')
1286
- */
1287
- declare function nextval(sequenceName: string): ExpressionRef;
1288
-
1289
- /**
1290
- * pgvector Extension Wrappers
1291
- *
1292
- * Type-safe query builders for pgvector distance operators.
1293
- * All functions return ExpressionRef instances that can be used in:
1294
- * - SELECT: .column(cosineDistance('vector', qv).as('score'))
1295
- * - WHERE: .where(cosineDistance('vector', qv).gte(0.5))
1296
- * - ORDER BY: .orderBy(rawDistance('vector', qv), 'asc')
1297
- */
1298
-
1299
- /**
1300
- * Cosine similarity: 1 - (col <=> vector)
1301
- *
1302
- * Score in [0, 1], higher = more similar.
1303
- * Use in SELECT to get a similarity score.
1304
- *
1305
- * @example
1306
- * orm.select('embeddings').column(cosineDistance('vector', qv).as('score'))
1307
- */
1308
- declare function cosineDistance(column: string, vector: number[]): ExpressionRef;
1309
- /**
1310
- * Raw cosine distance: col <=> vector
1311
- *
1312
- * Lower = closer. Index-friendly — use in ORDER BY for ANN search.
1313
- * Do NOT use in SELECT as a similarity score (lower = closer is counterintuitive).
1314
- *
1315
- * @example
1316
- * orm.select('embeddings').orderBy(rawDistance('vector', qv), 'asc')
1317
- */
1318
- declare function rawDistance(column: string, vector: number[]): ExpressionRef;
1319
- /**
1320
- * L2 (Euclidean) distance: col <-> vector
1321
- *
1322
- * @example
1323
- * orm.select('embeddings').orderBy(l2Distance('vector', qv), 'asc')
1324
- */
1325
- declare function l2Distance(column: string, vector: number[]): ExpressionRef;
1326
- /**
1327
- * Inner product distance: col <#> vector (negative inner product)
1328
- *
1329
- * For maximum inner product search: ORDER BY innerProduct('vector', qv) ASC.
1330
- *
1331
- * @example
1332
- * orm.select('embeddings').orderBy(innerProduct('vector', qv), 'asc')
1333
- */
1334
- declare function innerProduct(column: string, vector: number[]): ExpressionRef;
1335
- /**
1336
- * Get the number of dimensions of a vector column: vector_dims(col)
1337
- *
1338
- * Returns an integer — the dimension count of the stored vector.
1339
- * Useful for sanity-checking that embeddings match the expected model dimension.
1340
- *
1341
- * @example
1342
- * orm.from(embeddings).columns([vectorDims('vector').as('dim')]).first()
1343
- * // → SELECT vector_dims("t0"."vector") AS "dim" FROM "embeddings" AS "t0"
1344
- */
1345
- declare function vectorDims(column: string): ExpressionRef;
1346
-
1347
- /**
1348
- * PostgreSQL Schema Introspection (ADAPTER-006)
1349
- *
1350
- * Queries information_schema/pg_catalog to build ModelIR
1351
- * from an existing database. Supports:
1352
- * - Table/column/PK discovery
1353
- * - FK → bidirectional relation inference
1354
- * - Hierarchy detection (adjacency + edge-table)
1355
- * - Include/exclude filtering
1356
- *
1357
- * @module introspection
1358
- */
1359
-
1360
- /** Options for database introspection */
1361
- interface IntrospectionOptions {
1362
- /** Tables to exclude (glob patterns: * matches any chars) */
1363
- readonly exclude?: readonly string[];
1364
- /** Tables to include (default: all). Applied before exclude. */
1365
- readonly include?: readonly string[];
1366
- /** Schema name to introspect (default: 'public') */
1367
- readonly schema?: string;
1368
- }
1369
- /** Hierarchy pattern detected during introspection */
1370
- /**
1371
- * Hierarchy pattern detected during introspection.
1372
- * Alias of {@link HierarchyIR} from \@dbsp/types — kept here for
1373
- * public-API backwards compatibility (re-exported from \@dbsp/adapter-pgsql).
1374
- */
1375
- type DetectedHierarchy = HierarchyIR;
1376
- /** Extended ModelIR with hierarchy metadata */
1377
- interface IntrospectedModelIR extends ModelIR {
1378
- readonly hierarchies: readonly DetectedHierarchy[];
1379
- readonly introspectedAt: Date;
1380
- readonly warnings: readonly string[];
1381
- }
1382
- declare function introspect(pool: Pool, options?: IntrospectionOptions): Promise<IntrospectedModelIR>;
1383
-
1384
- /**
1385
- * Mutation Compiler
1386
- *
1387
- * Compiles INSERT, UPDATE, and DELETE statements from plan decisions.
1388
- * Supports:
1389
- * - INSERT with values/from subquery
1390
- * - INSERT with RETURNING
1391
- * - UPDATE with SET and WHERE
1392
- * - DELETE with WHERE
1393
- * - RETURNING clause for all mutations
1394
- */
1395
-
1396
- /**
1397
- * Configuration for INSERT compilation
1398
- */
1399
- interface InsertConfig {
1400
- /** Table to insert into */
1401
- table: string;
1402
- /** Columns to insert */
1403
- columns: string[];
1404
- /** Values for each column (array of rows) */
1405
- values: unknown[][];
1406
- /** Columns to return (RETURNING clause) */
1407
- returning?: string[];
1408
- /** Alias-aware RETURNING projection items */
1409
- returningItems?: readonly MutationReturningItem[];
1410
- /** Subquery for INSERT ... SELECT */
1411
- selectQuery?: Node;
1412
- /** Column database types for type-cast emission (e.g. range types) */
1413
- columnTypes?: Record<string, string>;
1414
- }
1415
- /**
1416
- * Configuration for UPDATE compilation
1417
- */
1418
- interface UpdateConfig {
1419
- /** Table to update */
1420
- table: string;
1421
- /** Column-value pairs to set */
1422
- set: {
1423
- column: string;
1424
- value: unknown;
1425
- }[];
1426
- /** WHERE conditions */
1427
- where?: Decision[];
1428
- /** Columns to return (RETURNING clause) */
1429
- returning?: string[];
1430
- /** Alias-aware RETURNING projection items */
1431
- returningItems?: readonly MutationReturningItem[];
1432
- /** Column database types for type-cast emission (e.g. range types) */
1433
- columnTypes?: Record<string, string>;
1434
- }
1435
- /**
1436
- * Configuration for DELETE compilation
1437
- */
1438
- interface DeleteConfig {
1439
- /** Table to delete from */
1440
- table: string;
1441
- /** WHERE conditions */
1442
- where?: Decision[];
1443
- /** Columns to return (RETURNING clause) */
1444
- returning?: string[];
1445
- /** Alias-aware RETURNING projection items */
1446
- returningItems?: readonly MutationReturningItem[];
1447
- }
1448
- /**
1449
- * Compile an INSERT statement from configuration.
1450
- */
1451
- declare function compileInsert(config: InsertConfig, ctx: CompilerContext, state: CompilerState): Node;
1452
- /**
1453
- * Compile an UPDATE statement from configuration.
1454
- */
1455
- declare function compileUpdate(config: UpdateConfig, ctx: CompilerContext, state: CompilerState): Node;
1456
- declare function compileDelete(config: DeleteConfig, ctx: CompilerContext, state: CompilerState): Node;
1457
- /**
1458
- * Compile a mutation decision to AST.
1459
- * Determines mutation type from decision.type and delegates.
1460
- */
1461
- declare function compileMutation(decision: Decision, ctx: CompilerContext, state: CompilerState): Node;
1462
-
1463
- /**
1464
- * Upsert (INSERT ... ON CONFLICT) Compiler
1465
- *
1466
- * Compiles UPSERT statements with ON CONFLICT handling.
1467
- * Supports:
1468
- * - ON CONFLICT DO NOTHING
1469
- * - ON CONFLICT DO UPDATE SET ...
1470
- * - Conflict target (columns or constraint name)
1471
- * - WHERE clause for conflict resolution
1472
- */
1473
-
1474
- /**
1475
- * Conflict resolution strategy
1476
- */
1477
- type ConflictAction = 'nothing' | 'update';
1478
- /**
1479
- * Conflict target specification
1480
- */
1481
- interface ConflictTarget {
1482
- /** Column names that form the unique constraint */
1483
- columns?: string[];
1484
- /** Named constraint */
1485
- constraint?: string;
1486
- /** WHERE clause for partial index */
1487
- where?: Decision[];
1488
- }
1489
- /**
1490
- * Configuration for UPSERT compilation
1491
- */
1492
- interface UpsertConfig {
1493
- /** Table to upsert into */
1494
- table: string;
1495
- /** Columns to insert */
1496
- columns: string[];
1497
- /** Values for each column (array of rows) */
1498
- values: unknown[][];
1499
- /** Conflict target (unique columns or constraint) */
1500
- conflictTarget: ConflictTarget;
1501
- /** What to do on conflict */
1502
- conflictAction: ConflictAction;
1503
- /** Columns to update on conflict (for 'update' action) */
1504
- updateColumns?: string[];
1505
- /** Optional WHERE clause for ON CONFLICT DO UPDATE */
1506
- actionWhere?: Decision[];
1507
- /** Optional direct WHERE intent for ON CONFLICT DO UPDATE */
1508
- actionWhereIntent?: WhereIntent;
1509
- /** Compile the direct action WHERE intent using the caller's WHERE compiler */
1510
- compileActionWhere?: (where: WhereIntent, state: CompilerState) => Node;
1511
- /** Use EXCLUDED.column for update values (default: true) */
1512
- useExcluded?: boolean;
1513
- /** Columns to return (RETURNING clause) */
1514
- returning?: string[];
1515
- /** Alias-aware RETURNING projection items */
1516
- returningItems?: readonly MutationReturningItem[];
1517
- /** Optional column type hints for unnest casting (schema-driven) */
1518
- columnTypes?: Record<string, string>;
1519
- /**
1520
- * Raw SQL expressions for specific update columns.
1521
- * These are injected verbatim into the ON CONFLICT DO UPDATE SET clause.
1522
- * Keys are logical column names (before naming plugin), values are raw SQL fragments.
1523
- *
1524
- * @warning SECURITY: fragments are inserted without parameterization.
1525
- * Only use with hardcoded expressions. Never with user input.
1526
- *
1527
- * @example { last_parsed: 'now()', count: 'excluded.count + 1' }
1528
- */
1529
- updateExpressions?: Record<string, string>;
1530
- }
1531
- /**
1532
- * Build ON CONFLICT clause for INSERT statement.
1533
- */
1534
- declare function buildOnConflictClause(config: UpsertConfig, ctx: CompilerContext, state: CompilerState): OnConflictClause;
1535
- /**
1536
- * Compile a complete UPSERT statement.
1537
- */
1538
- declare function compileUpsert(config: UpsertConfig, ctx: CompilerContext, state: CompilerState): Node;
1539
- /**
1540
- * Build EXCLUDED.column reference.
1541
- * EXCLUDED is a special table alias in ON CONFLICT ... DO UPDATE
1542
- * that refers to the row that would have been inserted.
1543
- */
1544
- declare function excludedRef(column: string, naming: {
1545
- toDatabase: (s: string) => string;
1546
- }): Node;
1547
- /**
1548
- * Build conditional update using COALESCE.
1549
- *
1550
- * Produces: COALESCE(EXCLUDED.col, table.col)
1551
- * This keeps existing value if new value is NULL.
1552
- */
1553
- declare function conditionalUpdate(column: string, table: string, ctx: CompilerContext): Node;
1554
-
1555
- /**
1556
- * @module naming
1557
- * Utilities for resolving database names to logical model names.
1558
- *
1559
- * The ModelIR.getTable() method expects logical (camelCase) names,
1560
- * but the adapter often works with database (snake_case) names.
1561
- * This module bridges that gap.
1562
- */
1563
-
1564
- /**
1565
- * Resolve a database table name to the corresponding logical model name.
1566
- *
1567
- * Converts the DB name using the naming convention, then looks it up in the model.
1568
- * Falls back to exact match if conversion doesn't find a match.
1569
- *
1570
- * @param model - The model IR to search in
1571
- * @param dbName - Database table name (e.g. "post_comments")
1572
- * @param convention - Naming convention used by the adapter
1573
- * @returns The logical table name if found, undefined otherwise
1574
- *
1575
- * @example
1576
- * ```typescript
1577
- * // With camelCase convention:
1578
- * resolveLogicalName(model, "post_comments", "camelCase") // → "postComments"
1579
- * resolveLogicalName(model, "posts", "camelCase") // → "posts"
1580
- * resolveLogicalName(model, "unknown", "camelCase") // → undefined
1581
- * ```
1582
- */
1583
- declare function resolveLogicalName(model: ModelIR, dbName: string, casing: DbCasing): string | undefined;
1584
-
1585
- /**
1586
- * ParamRef validation and helpers for PostgreSQL AST
1587
- *
1588
- * ParamRef nodes represent parameterized query placeholders ($1, $2, etc.)
1589
- * This module provides validation and creation helpers for safe AST construction.
1590
- */
1591
-
1592
- /**
1593
- * Validation result for ParamRef nodes
1594
- */
1595
- interface ParamRefValidationResult {
1596
- valid: boolean;
1597
- errors: string[];
1598
- }
1599
- /**
1600
- * Validates a ParamRef node
1601
- *
1602
- * Rules:
1603
- * - `number` must be a positive integer (1-based indexing)
1604
- * - `number` must not exceed reasonable bounds (e.g., 65535)
1605
- */
1606
- declare function validateParamRef(paramRef: ParamRef): ParamRefValidationResult;
1607
- /**
1608
- * Creates a validated ParamRef node
1609
- * @throws Error if validation fails
1610
- */
1611
- declare function createParamRef(number: number, location?: number): Node;
1612
- /**
1613
- * Creates a TypeCast node wrapping a ParamRef
1614
- * Example: $1::integer, $2::text[]
1615
- */
1616
- declare function createTypeCastParamRef(paramNumber: number, typeName: string, isArray?: boolean, location?: number): Node;
1617
- /**
1618
- * Creates an A_Expr node for equality comparison with ParamRef
1619
- * Example: col = $1
1620
- */
1621
- declare function createEqualityExpr(columnName: string, paramNumber: number, tableName?: string, location?: number): Node;
1622
- /**
1623
- * Creates a FuncCall node for ANY() with ParamRef
1624
- * Example: col = ANY($1) for array parameter matching
1625
- */
1626
- declare function createAnyExpr(columnName: string, paramNumber: number, tableName?: string, location?: number): Node;
1627
- /**
1628
- * Collects all ParamRef nodes from an AST, validating each
1629
- * Returns validation results for all found ParamRefs
1630
- */
1631
- declare function collectAndValidateParamRefs(node: unknown): {
1632
- paramRefs: Array<{
1633
- paramRef: ParamRef;
1634
- path: string;
1635
- }>;
1636
- validationResults: ParamRefValidationResult[];
1637
- allValid: boolean;
1638
- };
1639
-
1640
- /**
1641
- * PgsqlAdapter - Implements the Adapter interface for PostgreSQL using native pg driver.
1642
- *
1643
- * This adapter wraps a pg Pool instance and provides the unified
1644
- * adapter interface for the db-semantic-planner ORM.
1645
- *
1646
- * @module pgsql-adapter
1647
- */
1648
-
1649
- /**
1650
- * Options for PgsqlAdapter.
1651
- */
1652
- interface PgsqlAdapterOptions {
1653
- /** Schema name for multi-tenant queries */
1654
- readonly schemaName?: string;
1655
- /**
1656
- * DB column casing convention (intuitive semantics).
1657
- * - `'snake_case'`: DB columns are snake_case → transform to camelCase for JS
1658
- * - `'camelCase'`: DB columns are camelCase → no transformation
1659
- * - `'preserve'`: No transformation
1660
- */
1661
- readonly dbCasing?: DbCasing;
1662
- /** Optional model for WHERE compilation */
1663
- readonly model?: ModelIR;
1664
- /** Optional logger for debug/error messages */
1665
- readonly logger?: AdapterLogger;
1666
- /** Default primary key column name for convention fallbacks (default: 'id') */
1667
- readonly defaultPkColumnName?: string;
1668
- /** Convention for deriving FK column names: (tableName, pkName) => fkColumnName */
1669
- readonly deriveFkColumnName?: FkColumnDerivation;
1670
- }
1671
- /**
1672
- * Adapter implementation for PostgreSQL using native pg driver.
1673
- *
1674
- * @typeParam DB - Database schema type
1675
- *
1676
- * @example
1677
- * ```typescript
1678
- * import { Pool } from 'pg';
1679
- * import { createPgsqlAdapter } from '@dbsp/adapter-pgsql';
1680
- *
1681
- * const pool = new Pool({ connectionString: process.env.DATABASE_URL });
1682
- * const adapter = createPgsqlAdapter(pool);
1683
- * const orm = createOrm({ model, adapter });
1684
- * ```
957
+ * Adapter implementation for PostgreSQL using native pg driver.
958
+ *
959
+ * @typeParam DB - Database schema type
960
+ *
961
+ * @example
962
+ * ```typescript
963
+ * import { Pool } from 'pg';
964
+ * import { createPgsqlAdapter } from '@dbsp/adapter-pgsql';
965
+ *
966
+ * const pool = new Pool({ connectionString: process.env.DATABASE_URL });
967
+ * const adapter = createPgsqlAdapter(pool);
968
+ * const orm = createOrm({ model, adapter });
969
+ * ```
1685
970
  */
1686
971
  declare class PgsqlAdapter<DB = unknown> implements Adapter<DB> {
1687
972
  private readonly pool;
1688
973
  private readonly client;
974
+ private readonly borrowedClient;
975
+ private readonly managedTransactions;
976
+ private readonly adapterManagedTransaction;
977
+ private readonly scopeToken;
978
+ private readonly scopeState;
1689
979
  private readonly schemaName;
1690
980
  private readonly _dbCasing;
1691
981
  private readonly naming;
@@ -1697,10 +987,19 @@ declare class PgsqlAdapter<DB = unknown> implements Adapter<DB> {
1697
987
  /**
1698
988
  * Create a new PgsqlAdapter.
1699
989
  *
1700
- * @param pool - pg.Pool instance, PoolClient (transactions), or undefined (compile-only mode)
1701
- * @param options - Optional configuration
990
+ * Ownership of the connection is **declared**, never inferred. Handing over a
991
+ * `PoolClient` means nothing on its own — it says the object has a `release()`
992
+ * method, not that a transaction is open or that the caller owns the lifecycle.
993
+ * Pass `borrowedClient: true` to say so.
994
+ *
995
+ * @param pool - a pg.Pool, a caller-owned pg.PoolClient (with `borrowedClient: true`),
996
+ * or nothing at all for compile-only mode
997
+ * @param options - configuration; declares connection ownership
1702
998
  */
1703
- constructor(pool?: Pool | PoolClient | undefined, options?: PgsqlAdapterOptions);
999
+ constructor(pool?: Pool | undefined, options?: PgsqlPoolAdapterOptions);
1000
+ constructor(pool: Pool, options?: PgsqlPoolAdapterOptions);
1001
+ constructor(client: PoolClient, options: PgsqlBorrowedClientAdapterOptions);
1002
+ constructor(pool: undefined, options?: PgsqlAdapterOptions);
1704
1003
  /**
1705
1004
  * Shared compilation dependencies — built lazily from adapter fields.
1706
1005
  * Passed to compiler sub-modules instead of `this`.
@@ -1715,7 +1014,7 @@ declare class PgsqlAdapter<DB = unknown> implements Adapter<DB> {
1715
1014
  private requireNqlCompileModel;
1716
1015
  private assertNqlBindingNamesDisjointFromTables;
1717
1016
  private compileNqlMutation;
1718
- private compileNqlBundleLeaf;
1017
+ private compileNqlBundleLeafEnvelope;
1719
1018
  private compileNqlBundle;
1720
1019
  /**
1721
1020
  * Returns the pool/client executor, or throws if in compile-only mode.
@@ -1730,9 +1029,9 @@ declare class PgsqlAdapter<DB = unknown> implements Adapter<DB> {
1730
1029
  */
1731
1030
  get dbCasing(): DbCasing;
1732
1031
  /**
1733
- * Get the underlying pg Pool instance.
1032
+ * Get the underlying pg Pool or borrowed PoolClient instance.
1734
1033
  */
1735
- getPoolInstance(): Pool;
1034
+ getPoolInstance(): Pool | PoolClient;
1736
1035
  /**
1737
1036
  * Compile a plan to executable SQL.
1738
1037
  *
@@ -1765,7 +1064,7 @@ declare class PgsqlAdapter<DB = unknown> implements Adapter<DB> {
1765
1064
  * @param expr - ExpressionIntent to evaluate
1766
1065
  * @returns Compiled SQL and parameters
1767
1066
  */
1768
- compileSelectExpression(expr: ExpressionIntent): CompiledQuery;
1067
+ compileSelectExpression<T = unknown>(expr: ExpressionIntent): CompiledQuery<T>;
1769
1068
  /**
1770
1069
  * Compile an insert intent to executable SQL.
1771
1070
  *
@@ -1810,7 +1109,7 @@ declare class PgsqlAdapter<DB = unknown> implements Adapter<DB> {
1810
1109
  * Compile a recursive CTE plan to executable SQL.
1811
1110
  * Supports adjacency-list and edge-table traversal modes.
1812
1111
  */
1813
- compileRecursive(report: RecursivePlanReport, model: ModelIR, options?: CompileOptions): CompiledQuery;
1112
+ compileRecursive<T = unknown>(report: RecursivePlanReport, model: ModelIR, options?: CompileOptions): CompiledQuery<T>;
1814
1113
  /**
1815
1114
  * Compile a CTE query backed by unnest() arrays (BATCH-001 Block 5).
1816
1115
  *
@@ -1818,11 +1117,11 @@ declare class PgsqlAdapter<DB = unknown> implements Adapter<DB> {
1818
1117
  * independently (parameters starting at $1), then renumber outer params
1819
1118
  * to start after CTE params and prepend WITH clause.
1820
1119
  */
1821
- compileCteQuery(intent: CteQueryIntent, options?: CompileOptions): CompiledQuery;
1120
+ compileCteQuery<T = unknown>(intent: CteQueryIntent, options?: CompileOptions): CompiledQuery<T>;
1822
1121
  /**
1823
1122
  * Compile a set operation (UNION / INTERSECT / EXCEPT) to SQL.
1824
1123
  */
1825
- compileSetOperation(intent: SetOperationIntent, model: ModelIR, options?: CompileOptions): CompiledQuery;
1124
+ compileSetOperation<T = unknown>(intent: SetOperationIntent, model: ModelIR, options?: CompileOptions): CompiledQuery<T>;
1826
1125
  private compileSetOperationWithBindings;
1827
1126
  /**
1828
1127
  * Create a dump for observability.
@@ -1858,10 +1157,16 @@ declare class PgsqlAdapter<DB = unknown> implements Adapter<DB> {
1858
1157
  * @returns AsyncIterableIterator that yields rows one by one
1859
1158
  */
1860
1159
  stream<T>(query: CompiledQuery<T>, options?: AdapterStreamOptions): AsyncIterableIterator<T>;
1160
+ /** Stream raw SQL directly using the same cursor machinery as stream(). */
1161
+ streamRaw<T = unknown>(sql: string, parameters?: readonly unknown[], options?: AdapterStreamOptions): AsyncIterableIterator<T>;
1162
+ private streamCursor;
1861
1163
  /**
1862
1164
  * Internal: Stream with an existing client using cursors.
1863
1165
  */
1864
1166
  private streamWithClient;
1167
+ private streamWithManagedClient;
1168
+ private streamWithManagedClientSavepointScope;
1169
+ private streamWithClientTransaction;
1865
1170
  /**
1866
1171
  * Introspect the database schema and return a ModelIR.
1867
1172
  *
@@ -1878,8 +1183,83 @@ declare class PgsqlAdapter<DB = unknown> implements Adapter<DB> {
1878
1183
  introspect(options?: IntrospectionOptions): Promise<IntrospectedModelIR>;
1879
1184
  /**
1880
1185
  * Execute a callback within a database transaction.
1186
+ *
1187
+ * ## What this guarantees
1188
+ *
1189
+ * The callback's work commits together or not at all; a statement issued inside
1190
+ * the transaction never executes after its boundary, even if you forget to
1191
+ * `await` it; a nested `transaction()` is a real savepoint; and the connection
1192
+ * never goes back to the pool with a transaction still open on it.
1193
+ *
1194
+ * ## What it cannot guarantee, and you should know before you reach for raw SQL
1195
+ *
1196
+ * **Raw SQL that ends the transaction ends it.** `COMMIT`, `ROLLBACK` and
1197
+ * `PREPARE TRANSACTION` issued through `executeRaw` — or through several commands
1198
+ * in one call — reach PostgreSQL and take effect *before* dbsp is told what they
1199
+ * were: the command tag arrives after the statement has run. dbsp detects it, kills
1200
+ * the scope so nothing else escapes, and throws — but **it cannot un-run what your
1201
+ * statement already did**, and `transaction()` rejecting does not mean nothing was
1202
+ * committed.
1203
+ *
1204
+ * The same holds for session state raw SQL creates: a sequence that advanced stays
1205
+ * advanced, an advisory lock stays held, a `PREPARE` or a `SET` you issued survives
1206
+ * on a pooled connection. dbsp cleans up only what dbsp created.
1207
+ *
1208
+ * This is the contract of an escape hatch, not an oversight — see #327. If you need
1209
+ * transaction control, own the transaction: take a client, `BEGIN` on it yourself,
1210
+ * and hand dbsp a `borrowedClient` **without** `managedTransactions`. dbsp will then
1211
+ * contain its own statements inside *your* transaction instead of the other way round.
1881
1212
  */
1882
1213
  transaction<T>(fn: (adapter: Adapter<DB>) => Promise<T>): Promise<T>;
1214
+ /**
1215
+ * Execute scratch PostgreSQL work in a scope that always rolls back on success.
1216
+ *
1217
+ * This is intentionally PostgreSQL-adapter-specific. It is used for catalog
1218
+ * shaped scratch DDL such as CHECK expression canonicalisation, where the
1219
+ * caller needs PostgreSQL's rendering but must not keep the scratch objects.
1220
+ * Rollback here is cleanup of dbsp-created work, not a sandbox for arbitrary
1221
+ * session effects.
1222
+ */
1223
+ withScratchScope<T>(fn: (adapter: PgsqlAdapter<DB>) => Promise<T>): Promise<T>;
1224
+ private createManagedClientAdapter;
1225
+ private createChildTransactionObserver;
1226
+ private observeChildTransaction;
1227
+ private markChildTransactionObserved;
1228
+ private refreshScopeChildrenFailure;
1229
+ private transactionWithManagedClient;
1230
+ private transactionWithManagedClientSavepointScope;
1231
+ private transactionWithClientTransaction;
1232
+ private releaseClient;
1233
+ private rollbackAndReleaseSavepoint;
1234
+ private rollbackSavepoint;
1235
+ private releaseSavepoint;
1236
+ private rollbackTransactionIfOpen;
1237
+ private classifyTransactionStateError;
1238
+ private probeTransactionState;
1239
+ private classifySavepointReleaseFailure;
1240
+ private rollbackSavepointAfterReleaseFailure;
1241
+ private enterTransactionScope;
1242
+ private enterSavepointScope;
1243
+ private pushClientScope;
1244
+ private currentClientScope;
1245
+ private assertCanUseClient;
1246
+ private assertUsableScopeAncestors;
1247
+ private findClientScope;
1248
+ private assertScopeNotPoisoned;
1249
+ private throwIfScopePoisoned;
1250
+ private scopePoisonOutranksError;
1251
+ private poisonScopeState;
1252
+ private poisonClientScope;
1253
+ private poisonClientScopeStack;
1254
+ private runWithScopeStatementLock;
1255
+ private closeScope;
1256
+ private closeScopeAndAssertChildren;
1257
+ private drainScopeStatements;
1258
+ private drainScopeChildren;
1259
+ private assertScopeChildrenSettled;
1260
+ private drainScopeWork;
1261
+ private executeScopeBoundaryStatement;
1262
+ private assertCommitSucceeded;
1883
1263
  /**
1884
1264
  * Create a schema-scoped adapter for multi-tenant queries.
1885
1265
  */
@@ -1888,6 +1268,15 @@ declare class PgsqlAdapter<DB = unknown> implements Adapter<DB> {
1888
1268
  * Execute raw SQL directly.
1889
1269
  *
1890
1270
  * ⚠️ WARNING: Use parameter placeholders ($1, $2, etc.) for all values.
1271
+ *
1272
+ * Transaction control through raw SQL inside a scope dbsp is managing is
1273
+ * unsupported. `COMMIT`, `ROLLBACK`, and `PREPARE TRANSACTION` end the
1274
+ * transaction dbsp is working inside; dbsp detects that and fails loudly, but
1275
+ * the data is already whatever your statement made it. Raw savepoint control
1276
+ * (`SAVEPOINT`, `RELEASE SAVEPOINT`, `ROLLBACK TO SAVEPOINT`) can alter the
1277
+ * savepoint stack before dbsp sees the command tag; dbsp poisons the scope, but
1278
+ * it cannot make that command un-run. Manage your transaction outside dbsp's
1279
+ * calls.
1891
1280
  */
1892
1281
  executeRaw<T = unknown>(sql: string, parameters?: readonly unknown[]): Promise<T[]>;
1893
1282
  /**
@@ -1909,12 +1298,22 @@ declare class PgsqlAdapter<DB = unknown> implements Adapter<DB> {
1909
1298
  */
1910
1299
  executeDDL(sql: string): Promise<void>;
1911
1300
  /**
1912
- * Whether this adapter instance is scoped inside a transaction.
1913
- * Guards unsafe DDL operations (VACUUM, CREATE INDEX CONCURRENTLY).
1301
+ * Whether a transaction is open on this adapter's connection.
1302
+ * This is true for dbsp-managed scopes and for borrowed pg clients whose
1303
+ * ReadyForQuery status says the caller has an open transaction.
1914
1304
  *
1915
1305
  * @since DDL-TABLE-001
1916
1306
  */
1917
1307
  get inTransaction(): boolean;
1308
+ private adapterManagedScopeIsLive;
1309
+ private executeQueryProtectingOpenTransaction;
1310
+ private executeConnectionStatement;
1311
+ private executeConnectionStatementUnlocked;
1312
+ private executeConnectionStatementInSavepoint;
1313
+ private issueConnectionQuery;
1314
+ private assertNoMultiCommandRawCall;
1315
+ private assertNoTransactionControlCommand;
1316
+ private assertPrepareDidNotEndTransaction;
1918
1317
  /**
1919
1318
  * Resolve the explicit schema for a catalog read: an explicit argument, else
1920
1319
  * the adapter's configured schema, else `undefined` (resolve in-query). NOT a
@@ -1978,48 +1377,1008 @@ declare class PgsqlAdapter<DB = unknown> implements Adapter<DB> {
1978
1377
  */
1979
1378
  generateDropIndex(name: string, options?: DropIndexOptions): string;
1980
1379
  /**
1981
- * Validate an identifier (table name, column name, schema name).
1380
+ * Validate an identifier (table name, column name, schema name).
1381
+ */
1382
+ validateIdentifier(value: string, type: string): void;
1383
+ }
1384
+ /**
1385
+ * Create a PgsqlAdapter from a pg Pool instance.
1386
+ *
1387
+ * @param pool - pg Pool instance
1388
+ * @param options - Optional configuration
1389
+ * @returns A new PgsqlAdapter instance
1390
+ *
1391
+ * @example
1392
+ * ```typescript
1393
+ * import { Pool } from 'pg';
1394
+ * import { createPgsqlAdapter } from '@dbsp/adapter-pgsql';
1395
+ *
1396
+ * const pool = new Pool({ connectionString: process.env.DATABASE_URL });
1397
+ * const adapter = createPgsqlAdapter(pool);
1398
+ *
1399
+ * // With naming convention
1400
+ * const adapter = createPgsqlAdapter(pool, { dbCasing: 'snake_case' });
1401
+ * ```
1402
+ */
1403
+ declare function createPgsqlAdapter<DB = unknown>(pool: Pool, options?: PgsqlPoolAdapterOptions): PgsqlAdapter<DB>;
1404
+ declare function createPgsqlAdapter<DB = unknown>(client: PoolClient, options: PgsqlBorrowedClientAdapterOptions): PgsqlAdapter<DB>;
1405
+ /**
1406
+ * Creates a compile-only PgsqlAdapter for SQL generation without a database connection.
1407
+ *
1408
+ * All compilation methods (compile, compileInsert, etc.), createDump(), and generateDDL()
1409
+ * work normally. Execution methods (execute, stream, transaction, etc.) throw an error.
1410
+ *
1411
+ * @example
1412
+ * ```typescript
1413
+ * import { createPgsqlCompileOnlyAdapter } from '@dbsp/adapter-pgsql';
1414
+ * import { createOrm } from '@dbsp/core';
1415
+ *
1416
+ * const adapter = createPgsqlCompileOnlyAdapter();
1417
+ * const orm = createOrm({ model, adapter });
1418
+ * const dump = await orm.select('users').dump();
1419
+ * console.log(dump.sql);
1420
+ * ```
1421
+ */
1422
+ declare function createPgsqlCompileOnlyAdapter<DB = unknown>(options?: PgsqlAdapterOptions): CompileOnlyAdapter;
1423
+
1424
+ /**
1425
+ * Schema Comparison Engine (DDL-PROV Block 1)
1426
+ *
1427
+ * Compares two ModelIRs (schema definition vs database state)
1428
+ * and produces a structured diff of changes needed.
1429
+ *
1430
+ * @module schema-diff
1431
+ */
1432
+
1433
+ type ChangeKind = 'create_table' | 'drop_table' | 'add_column' | 'drop_column' | 'alter_column_type' | 'alter_column_nullable' | 'alter_column_default' | 'alter_column_unique' | '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';
1434
+ interface SchemaChange {
1435
+ readonly kind: ChangeKind;
1436
+ readonly table: string;
1437
+ readonly column?: string;
1438
+ readonly destructive: boolean;
1439
+ readonly details: string;
1440
+ /** Additional metadata for SQL generation */
1441
+ readonly meta?: Readonly<Record<string, unknown>>;
1442
+ }
1443
+ interface DiffSummary {
1444
+ readonly tables: {
1445
+ readonly added: number;
1446
+ readonly dropped: number;
1447
+ };
1448
+ readonly columns: {
1449
+ readonly added: number;
1450
+ readonly dropped: number;
1451
+ readonly altered: number;
1452
+ };
1453
+ readonly indexes: {
1454
+ readonly added: number;
1455
+ readonly dropped: number;
1456
+ };
1457
+ readonly constraints: {
1458
+ readonly added: number;
1459
+ readonly dropped: number;
1460
+ readonly altered: number;
1461
+ };
1462
+ }
1463
+ interface SchemaDiff {
1464
+ readonly changes: readonly SchemaChange[];
1465
+ readonly hasDestructive: boolean;
1466
+ readonly summary: DiffSummary;
1467
+ }
1468
+ interface CompareSchemataOptions {
1469
+ /**
1470
+ * Database naming convention.
1471
+ * When set, schema model names (camelCase) are converted to DB format
1472
+ * (e.g. snake_case) before comparison with the introspected model.
1473
+ */
1474
+ dbCasing?: DbCasing;
1475
+ /** Dialect capabilities — comparisons for unsupported features will be skipped */
1476
+ readonly dialectCapabilities?: DialectCapabilities;
1477
+ /**
1478
+ * When `true`, extensions present in the live DB but absent from the model
1479
+ * schema are silently ignored — no `drop_extension` change is emitted for them.
1480
+ * Only extensions explicitly declared in the model are managed (created if missing).
1481
+ *
1482
+ * Use this when the database image pre-installs extensions that the application
1483
+ * schema does not own (e.g. pgvector, pg_search bundled in a custom Postgres image).
1484
+ * Default: `false` (full-sync behaviour — unmanaged DB extensions produce a
1485
+ * `drop_extension` entry).
1486
+ */
1487
+ readonly ignoreUnmanagedExtensions?: boolean;
1488
+ /**
1489
+ * Strict compile-only mode for callers that require convergence guarantees.
1490
+ *
1491
+ * `compareSchemata()` is intentionally pure and cannot ask PostgreSQL to
1492
+ * canonicalise raw-SQL expression surfaces. By default it keeps the historic
1493
+ * best-effort raw string comparison for CHECK expressions, partial-index
1494
+ * predicates, and index expressions. Set this flag to throw when either model
1495
+ * contains one of those surfaces so a caller cannot accidentally rely on a
1496
+ * compile-only diff for a convergence-sensitive check.
1497
+ *
1498
+ * Live PostgreSQL callers should use `comparePgsqlDatabaseSchema()`, which
1499
+ * canonicalises CHECK constraint expressions before calling this function.
1500
+ * Partial-index predicates and index expressions are not canonicalised by the
1501
+ * live helper and are rejected there when this strict flag is set.
1502
+ */
1503
+ readonly requireExpressionCanonicalization?: boolean;
1504
+ }
1505
+ declare class ExpressionCanonicalizationUnavailableError extends Error {
1506
+ readonly surfaces: readonly string[];
1507
+ constructor(surfaces: readonly string[]);
1508
+ }
1509
+ /**
1510
+ * Compare two ModelIRs and produce a structured diff.
1511
+ *
1512
+ * @param schema - The desired schema (from definition)
1513
+ * @param db - The current database state (from introspection)
1514
+ * @param options - Optional comparison settings (e.g. dbCasing)
1515
+ * @returns SchemaDiff with all changes needed to bring DB in sync with schema
1516
+ */
1517
+ declare function compareSchemata(schema: ModelIR, db: ModelIR, options?: CompareSchemataOptions): SchemaDiff;
1518
+
1519
+ interface ComparePgsqlDatabaseSchemaOptions extends CompareSchemataOptions, SchemaScopeOptions {
1520
+ /**
1521
+ * Whether to canonicalise PostgreSQL CHECK constraint expressions before
1522
+ * comparing. Defaults to `true`. Set to `false` only for compatibility with
1523
+ * legacy raw-string live diffs.
1524
+ *
1525
+ * Live canonicalisation creates temporary scratch tables and missing desired
1526
+ * enum types inside an adapter scratch scope whose successful cleanup is
1527
+ * rollback. The database role needs permission to create temporary tables,
1528
+ * and enum-dependent checks may need permission to create the pending enum
1529
+ * type. If PostgreSQL refuses that scratch DDL, non-strict mode warns and
1530
+ * falls back to best-effort raw string comparison for the affected CHECK
1531
+ * constraints.
1532
+ */
1533
+ readonly canonicalizeExpressions?: boolean;
1534
+ /**
1535
+ * Receives live CHECK canonicalisation warnings. Defaults to console.warn.
1536
+ */
1537
+ readonly onWarning?: (message: string) => void;
1538
+ /**
1539
+ * Diff that the caller just applied before this live re-diff. Used only when
1540
+ * CHECK expressions are compared by raw text to fail loudly if the exact same
1541
+ * expression-surface drift appears again after re-introspection.
1542
+ */
1543
+ readonly previouslyAppliedDiff?: SchemaDiff;
1544
+ }
1545
+ declare class NonConvergentSchemaDiffError extends Error {
1546
+ readonly table: string;
1547
+ readonly constraint: string;
1548
+ readonly desiredExpression: string;
1549
+ readonly databaseExpression: string;
1550
+ constructor(table: string, constraint: string, desiredExpression: string, databaseExpression: string);
1551
+ }
1552
+ /** An enum value this diff adds, reported as a candidate cause — never asserted. */
1553
+ interface AddedEnumValue {
1554
+ readonly enumName: string;
1555
+ readonly value: string;
1556
+ }
1557
+ declare class CheckConstraintNewEnumValueError extends Error {
1558
+ readonly table: string;
1559
+ readonly constraint: string;
1560
+ readonly addedEnumValues: readonly AddedEnumValue[];
1561
+ constructor(table: string, constraint: string, addedEnumValues: readonly AddedEnumValue[]);
1562
+ }
1563
+ /**
1564
+ * Live PostgreSQL schema diff: introspect, canonicalise desired CHECK
1565
+ * constraint expressions through PostgreSQL, then call the pure synchronous
1566
+ * schema comparator.
1567
+ *
1568
+ * If CHECK canonicalisation falls back while the same diff adds a plausibly
1569
+ * referenced enum value, the diff is refused. dbsp currently applies each
1570
+ * migration in one transaction, and PostgreSQL forbids using a newly added enum
1571
+ * value in that same transaction; emitting the CHECK would produce a migration
1572
+ * that cannot run. Apply the enum addition by itself first, then add or update
1573
+ * the CHECK constraint in a later migration.
1574
+ *
1575
+ * Partial-index predicates and index expressions are intentionally not
1576
+ * canonicalised here; non-strict diffs compare them by raw string, and strict
1577
+ * diffs reject them.
1578
+ */
1579
+ declare function comparePgsqlDatabaseSchema(adapter: PgsqlAdapter, desired: ModelIR, options?: ComparePgsqlDatabaseSchemaOptions): Promise<SchemaDiff>;
1580
+ declare function assertNoRepeatedExpressionSurfaceDrift(previouslyAppliedDiff: SchemaDiff, currentDiff: SchemaDiff, rawCheckExpressionSurfaces?: ReadonlySet<string>): void;
1581
+
1582
+ /**
1583
+ * Migration SQL Generator (DDL-PROV Block 1)
1584
+ *
1585
+ * Generates ordered SQL statements from a SchemaDiff.
1586
+ * Statements are topologically sorted: DROP constraints → DROP objects → CREATE objects → ADD constraints.
1587
+ *
1588
+ * @module migration-sql
1589
+ */
1590
+
1591
+ interface MigrationSQLOptions {
1592
+ /**
1593
+ * Schema namespace (default: none — unqualified).
1594
+ * Required when emitted migration SQL would otherwise mix non-default
1595
+ * target-scoped custom types/enums with unqualified table SQL.
1596
+ */
1597
+ readonly schemaName?: string;
1598
+ /** Whether to include destructive changes (drops) */
1599
+ readonly includeDestructive?: boolean;
1600
+ /** Automatically create indexes on FK columns for new tables (default: true) */
1601
+ readonly fkAutoIndex?: boolean;
1602
+ /** Dialect capabilities — unsupported index features throw during migration SQL generation */
1603
+ readonly dialectCapabilities?: DialectCapabilities;
1604
+ }
1605
+ /**
1606
+ * Generate ordered SQL statements from a SchemaDiff.
1607
+ *
1608
+ * Topological order:
1609
+ * 0. DROP FK/CHECK constraints (must drop before referenced tables)
1610
+ * 1. DROP indexes
1611
+ * 2. DROP columns
1612
+ * 3. DROP primary keys
1613
+ * 4. DROP tables, DROP ENUMs
1614
+ * 5. CREATE ENUMs (must exist before tables that use them)
1615
+ * 6. CREATE tables
1616
+ * 7. ADD columns
1617
+ * 8. ALTER columns (type, nullable, default)
1618
+ * 9. ADD primary keys / column UNIQUE constraints
1619
+ * 10. ADD FK constraints (must add after referenced tables exist)
1620
+ * 11. ALTER FK (drop + re-add)
1621
+ * 12. CREATE indexes
1622
+ * 13. ADD CHECK constraints
1623
+ * 14. ALTER ENUM ADD VALUE (must be last — has transaction visibility caveats in PG)
1624
+ * 15. COMMENT ON TABLE / COLUMN (very last)
1625
+ */
1626
+ declare function generateMigrationSQL(diff: SchemaDiff, options?: MigrationSQLOptions): readonly string[];
1627
+ /**
1628
+ * Generate ordered DOWN SQL statements from a SchemaDiff.
1629
+ *
1630
+ * Reverses the topological order used in UP migrations:
1631
+ * phases run in descending order (11, 10, 9, ..., 0).
1632
+ *
1633
+ * Irreversible changes (drops that lose data) produce SQL WARNING comments.
1634
+ */
1635
+ declare function generateDownSQL(diff: SchemaDiff, options?: MigrationSQLOptions): readonly string[];
1636
+
1637
+ /**
1638
+ * Migration File Format v2 — UP + DOWN sections.
1639
+ *
1640
+ * File format:
1641
+ * -- dbsp:destructive: true|false
1642
+ * <UP statements>;
1643
+ * -- DOWN
1644
+ * <DOWN statements>;
1645
+ *
1646
+ * The separator `-- DOWN` must be on its own line (SC-25).
1647
+ *
1648
+ * @module ddl/migration-file
1649
+ */
1650
+
1651
+ /**
1652
+ * Result of parsing a migration file's UP/DOWN sections.
1653
+ */
1654
+ interface ParsedMigrationFile {
1655
+ readonly upStatements: readonly string[];
1656
+ readonly downStatements: readonly string[];
1657
+ readonly hasDown: boolean;
1658
+ readonly destructive?: boolean | undefined;
1659
+ }
1660
+ /**
1661
+ * Generate a migration file content with UP and DOWN sections.
1662
+ */
1663
+ declare function generateMigrationFile(diff: SchemaDiff, options?: MigrationSQLOptions & {
1664
+ name?: string;
1665
+ }): string;
1666
+ /**
1667
+ * Parse a migration file into UP and DOWN sections.
1668
+ * Separator: `^\s*-- DOWN\s*$` (strict regex, own line only — SC-25)
1669
+ */
1670
+ declare function parseMigrationFile(content: string): ParsedMigrationFile;
1671
+ /**
1672
+ * Check if SQL statements contain destructive operations.
1673
+ * Destructive: DROP TABLE, DROP COLUMN, lossy ALTER COLUMN TYPE
1674
+ */
1675
+ declare function isDestructiveDown(downStatements: readonly string[]): boolean;
1676
+
1677
+ /**
1678
+ * Migration Tracker — `_dbsp_migrations` table CRUD.
1679
+ *
1680
+ * Manages the tracking table that records which migrations
1681
+ * have been applied to a database.
1682
+ */
1683
+
1684
+ interface MigrationRecord {
1685
+ /** Migration filename (e.g., "0001_create_users.sql") */
1686
+ readonly name: string;
1687
+ /** SHA-256 checksum of the migration file content */
1688
+ readonly checksum: string;
1689
+ /** When the migration was applied */
1690
+ readonly appliedAt: Date;
1691
+ /** Schema version at time of this migration */
1692
+ readonly schemaVersion: number;
1693
+ /** Whether this migration contains destructive changes */
1694
+ readonly destructive: boolean;
1695
+ }
1696
+ /**
1697
+ * Execute a callback under an advisory lock using a dedicated client.
1698
+ * The lock is held for the duration of the callback.
1699
+ * The client is released (and lock freed) after the callback completes.
1700
+ */
1701
+ declare function withMigrationLock<T>(pool: Pool, fn: (client: PoolClient) => Promise<T>): Promise<T>;
1702
+ /**
1703
+ * Ensure the migrations tracking table exists.
1704
+ * Auto-migrates existing tables that lack `schema_version`/`destructive` columns,
1705
+ * and backfills `schema_version` by `applied_at` order for rows still at 0.
1706
+ */
1707
+ declare function ensureMigrationsTable(pool: Pool): Promise<void>;
1708
+ /**
1709
+ * Get all applied migrations, ordered by name.
1710
+ */
1711
+ declare function getAppliedMigrations(pool: Pool): Promise<readonly MigrationRecord[]>;
1712
+ /**
1713
+ * Record a migration as applied.
1714
+ */
1715
+ declare function recordMigration(pool: Pool, name: string, checksum: string, schemaVersion: number, destructive: boolean): Promise<void>;
1716
+ /**
1717
+ * Check if a specific migration has been applied.
1718
+ */
1719
+ declare function isMigrationApplied(pool: Pool, name: string): Promise<boolean>;
1720
+ /**
1721
+ * Get the next schema version number (max + 1, or 1 if no migrations).
1722
+ */
1723
+ declare function getNextSchemaVersion(pool: Pool): Promise<number>;
1724
+ /**
1725
+ * Remove a migration record (for rollback).
1726
+ */
1727
+ declare function removeMigrationRecord(pool: Pool, name: string): Promise<void>;
1728
+
1729
+ /**
1730
+ * Type Mapping - Maps ModelIR ColumnType to PostgreSQL data types
1731
+ *
1732
+ * Supports both manual schemas and introspected schemas (preserving originalDbType).
1733
+ * Handles auto-increment via SERIAL/BIGSERIAL types.
1734
+ *
1735
+ * @module ddl/type-mapping
1736
+ */
1737
+
1738
+ /**
1739
+ * Map ColumnType to PostgreSQL data type string.
1740
+ *
1741
+ * Uses originalDbType if available (from introspection), otherwise
1742
+ * falls back to reasonable PostgreSQL defaults.
1743
+ *
1744
+ * @param col - Column definition from ModelIR
1745
+ * @returns PostgreSQL type string (e.g., 'VARCHAR(255)', 'SERIAL', 'JSONB')
1746
+ */
1747
+ declare function mapColumnType(col: ColumnIR, targetSchema?: string): string;
1748
+ /**
1749
+ * Map OnDeleteAction to PostgreSQL syntax.
1750
+ */
1751
+ declare function mapOnDeleteAction(action?: string): string;
1752
+
1753
+ /**
1754
+ * EXPLAIN Statement Compiler
1755
+ *
1756
+ * Generates PostgreSQL EXPLAIN statements with various options.
1757
+ * Supports:
1758
+ * - ANALYZE (execute and show actual run times)
1759
+ * - FORMAT (text, json, xml, yaml)
1760
+ * - VERBOSE, COSTS, BUFFERS, TIMING, SETTINGS
1761
+ */
1762
+
1763
+ /**
1764
+ * Output format for EXPLAIN results.
1765
+ */
1766
+ type ExplainFormat = 'text' | 'json' | 'xml' | 'yaml';
1767
+ /**
1768
+ * Options for EXPLAIN statement.
1769
+ */
1770
+ interface ExplainOptions {
1771
+ /** Execute the query and show actual run times */
1772
+ analyze?: boolean;
1773
+ /** Show more detailed output */
1774
+ verbose?: boolean;
1775
+ /** Show cost estimates (default: true) */
1776
+ costs?: boolean;
1777
+ /** Show buffer usage (requires analyze) */
1778
+ buffers?: boolean;
1779
+ /** Show actual timing (requires analyze) */
1780
+ timing?: boolean;
1781
+ /** Show non-default settings */
1782
+ settings?: boolean;
1783
+ /** Output format */
1784
+ format?: ExplainFormat;
1785
+ }
1786
+ /**
1787
+ * Build an EXPLAIN statement wrapping a query.
1788
+ *
1789
+ * @param query - The query to explain (SelectStmt, InsertStmt, etc.)
1790
+ * @param options - EXPLAIN options
1791
+ * @returns ExplainStmt AST node
1792
+ *
1793
+ * @example
1794
+ * ```typescript
1795
+ * const selectAst = { SelectStmt: { ... } };
1796
+ * const explainAst = buildExplain(selectAst, { analyze: true, format: 'json' });
1797
+ * // Produces: EXPLAIN (ANALYZE, FORMAT JSON) SELECT ...
1798
+ * ```
1799
+ */
1800
+ declare function buildExplain(query: Node, options?: ExplainOptions): Node;
1801
+ /**
1802
+ * Build EXPLAIN ANALYZE with JSON format (common pattern).
1803
+ *
1804
+ * @param query - The query to explain
1805
+ * @returns ExplainStmt with ANALYZE and JSON format
1806
+ */
1807
+ declare function buildExplainAnalyzeJson(query: Node): Node;
1808
+ /**
1809
+ * Build simple EXPLAIN (plan only, no execution).
1810
+ *
1811
+ * @param query - The query to explain
1812
+ * @returns ExplainStmt with default options
1813
+ */
1814
+ declare function buildExplainPlan(query: Node): Node;
1815
+ /**
1816
+ * Build verbose EXPLAIN with costs and buffers.
1817
+ *
1818
+ * @param query - The query to explain
1819
+ * @returns ExplainStmt with verbose options
1820
+ */
1821
+ declare function buildExplainVerbose(query: Node): Node;
1822
+ /**
1823
+ * Parse EXPLAIN JSON output to get execution statistics.
1824
+ *
1825
+ * @param jsonOutput - The JSON string from EXPLAIN (ANALYZE, FORMAT JSON)
1826
+ * @returns Parsed plan with execution statistics
1827
+ */
1828
+ declare function parseExplainJson(jsonOutput: string): ExplainPlan[];
1829
+ /**
1830
+ * Parsed EXPLAIN plan structure (simplified).
1831
+ */
1832
+ interface ExplainPlan {
1833
+ Plan: {
1834
+ 'Node Type': string;
1835
+ 'Relation Name'?: string;
1836
+ Alias?: string;
1837
+ 'Startup Cost'?: number;
1838
+ 'Total Cost'?: number;
1839
+ 'Plan Rows'?: number;
1840
+ 'Plan Width'?: number;
1841
+ 'Actual Startup Time'?: number;
1842
+ 'Actual Total Time'?: number;
1843
+ 'Actual Rows'?: number;
1844
+ 'Actual Loops'?: number;
1845
+ Plans?: ExplainPlan['Plan'][];
1846
+ };
1847
+ 'Planning Time'?: number;
1848
+ 'Execution Time'?: number;
1849
+ Triggers?: unknown[];
1850
+ }
1851
+ /**
1852
+ * Extract total execution time from EXPLAIN ANALYZE JSON output.
1853
+ *
1854
+ * @param plans - Parsed EXPLAIN plans
1855
+ * @returns Total execution time in milliseconds
1856
+ */
1857
+ declare function getTotalExecutionTime(plans: ExplainPlan[]): number;
1858
+ /**
1859
+ * Extract row counts from EXPLAIN ANALYZE JSON output.
1860
+ *
1861
+ * @param plans - Parsed EXPLAIN plans
1862
+ * @returns Object with estimated and actual row counts
1863
+ */
1864
+ declare function getRowEstimates(plans: ExplainPlan[]): {
1865
+ estimated: number;
1866
+ actual: number;
1867
+ };
1868
+
1869
+ interface CheckConstraintCanonicalizationWarning {
1870
+ readonly table: string;
1871
+ readonly constraint: string;
1872
+ readonly message: string;
1873
+ readonly cause: unknown;
1874
+ }
1875
+ interface CanonicalizeCheckConstraintsOptions {
1876
+ /** Database schema that owns the target tables and target-scoped enum types. */
1877
+ readonly schemaName?: string;
1878
+ /** Naming convention used when matching desired table names to DB table names. */
1879
+ readonly dbCasing?: DbCasing;
1880
+ /** Called when PostgreSQL CHECK canonicalisation fails and raw comparison is used. */
1881
+ readonly onWarning?: (warning: CheckConstraintCanonicalizationWarning) => void;
1882
+ /** Throw instead of falling back to raw comparison when canonicalisation fails. */
1883
+ readonly requireCanonicalization?: boolean;
1884
+ }
1885
+ type PgsqlCanonicalizationScope = Pick<Adapter, 'executeRaw' | 'transaction'>;
1886
+ declare class CheckConstraintCanonicalizationError extends Error {
1887
+ readonly table: string;
1888
+ readonly constraints: readonly string[];
1889
+ readonly cause: unknown;
1890
+ constructor(table: string, constraints: readonly string[], cause: unknown);
1891
+ }
1892
+ /**
1893
+ * Canonicalise PostgreSQL CHECK constraint expressions in a desired model.
1894
+ *
1895
+ * CHECK constraints are canonicalised by creating a transaction-local temp table
1896
+ * with the desired table's column definitions (borrowing live database type
1897
+ * detail for existing columns when the desired model omits it), adding the
1898
+ * authored CHECK constraints to that temp table, and reading PostgreSQL's
1899
+ * `pg_get_constraintdef()` rendering. The caller must provide a rollback-only
1900
+ * scratch scope; that rollback is cleanup for dbsp-created scratch objects, not
1901
+ * a sandbox for arbitrary session effects.
1902
+ * Missing desired enum types are also created inside that scratch scope before
1903
+ * scratch tables.
1904
+ * Scratch columns include only names and types; defaults, identity, uniqueness,
1905
+ * nullability, and other table-shape clauses are deliberately omitted.
1906
+ *
1907
+ * The returned expression is the full `CHECK (...)` clause. Bare authored
1908
+ * predicates are accepted and become full CHECK clauses.
1909
+ *
1910
+ * PostgreSQL does not allow an enum value added by `ALTER TYPE ... ADD VALUE`
1911
+ * to be used in the same transaction that added it. Because dbsp currently
1912
+ * emits and applies each migration in one transaction, the live diff layer
1913
+ * deliberately refuses CHECK constraints that fall back while the same diff adds
1914
+ * a plausibly referenced enum value. Splitting that into multiple transaction
1915
+ * phases is a separate migration-runner feature.
1916
+ *
1917
+ * This does not canonicalise partial-index predicates or index expressions, so
1918
+ * those surfaces may still compare by raw text in non-strict diffs.
1919
+ */
1920
+ declare function canonicalizeCheckConstraints(adapter: PgsqlCanonicalizationScope, desired: ModelIR, dbModel: ModelIR, options?: CanonicalizeCheckConstraintsOptions): Promise<ModelIR>;
1921
+
1922
+ /**
1923
+ * ParadeDB Extension Wrappers
1924
+ *
1925
+ * Type-safe query builders for ParadeDB BM25 full-text search.
1926
+ * All functions return ExpressionRef instances that can be used in:
1927
+ * - SELECT: .column(score('id').as('score'))
1928
+ * - WHERE: .where(bm25Search('symbols', query, { name: 3.0, doc: 1.0 }))
1929
+ * - ORDER BY: .orderBy(score('id'), 'desc')
1930
+ *
1931
+ * @remarks
1932
+ * ParadeDB functions accept both named and positional arguments.
1933
+ * This module uses named args via namedArg() for parse(), which produces:
1934
+ * paradedb.parse(field => 'field_name', query_string => $1)
1935
+ * Named parameter syntax is supported via the NamedArgExpressionIntent (EXT-NAMED-PARAMS).
1936
+ */
1937
+
1938
+ /**
1939
+ * BM25 relevance score for a row.
1940
+ *
1941
+ * Use in SELECT and ORDER BY to retrieve and sort by full-text relevance.
1942
+ * Requires a BM25 index on the table.
1943
+ *
1944
+ * @param keyField - The key field of the BM25 index (typically the primary key, e.g. 'id')
1945
+ * @returns ExpressionRef that compiles to: paradedb.score("keyField")
1946
+ *
1947
+ * @example
1948
+ * orm.select('symbols').column(score('id').as('score')).orderBy(score('id'), 'desc')
1949
+ * // → paradedb.score("id") AS "score"
1950
+ */
1951
+ declare function score(keyField: string): ExpressionRef;
1952
+ /**
1953
+ * Parse a single-field BM25 query expression.
1954
+ *
1955
+ * Compiles to: paradedb.parse(field => 'field_name', query_string => $N)
1956
+ *
1957
+ * @param field - Column name to search in (must be indexed in the BM25 index)
1958
+ * @param query - Query string value (will be bound as a parameter)
1959
+ * @returns ExpressionRef for use with boost() or booleanSearch()
1960
+ *
1961
+ * @example
1962
+ * parse('name', 'hello world')
1963
+ * // → paradedb.parse(field => 'name', query_string => $1)
1964
+ */
1965
+ declare function parse(field: string, query: ExpressionRef | unknown): ExpressionRef;
1966
+ /**
1967
+ * Apply a boost multiplier to a BM25 sub-expression.
1968
+ *
1969
+ * Compiles to: paradedb.boost(factor, expr)
1970
+ *
1971
+ * @param factor - Boost multiplier (e.g. 3.0 for 3x weight)
1972
+ * @param expr - Expression to boost (typically a parse() call)
1973
+ * @returns ExpressionRef for use with booleanSearch()
1974
+ *
1975
+ * @example
1976
+ * boost(3.0, parse('name', 'hello'))
1977
+ * // → paradedb.boost(3.0, paradedb.parse('name', $1))
1978
+ */
1979
+ declare function boost(factor: number, expr: ExpressionRef): ExpressionRef;
1980
+ /**
1981
+ * Combine multiple BM25 sub-expressions with boolean OR logic.
1982
+ *
1983
+ * Compiles to: paradedb.boolean(expr1, expr2, ...)
1984
+ *
1985
+ * @param exprs - One or more sub-expressions (typically boost() calls)
1986
+ * @returns ExpressionRef for use on the right side of the @@@ operator
1987
+ *
1988
+ * @example
1989
+ * booleanSearch([boost(3.0, parse('name', q)), boost(1.0, parse('doc', q))])
1990
+ * // → paradedb.boolean(paradedb.boost(3.0, ...), paradedb.boost(1.0, ...))
1991
+ */
1992
+ /**
1993
+ * Combine multiple BM25 sub-expressions with boolean OR logic.
1994
+ *
1995
+ * Compiles to: paradedb.boolean(should => ARRAY[expr1, expr2, ...])
1996
+ *
1997
+ * @param exprs - One or more sub-expressions (typically boost() calls)
1998
+ * @returns ExpressionRef for use on the right side of the @@@ operator
1999
+ *
2000
+ * @example
2001
+ * booleanSearch([boost(3.0, parse('name', q)), boost(1.0, parse('doc', q))])
2002
+ * // → paradedb.boolean(should => ARRAY[paradedb.boost(3.0, ...), paradedb.boost(1.0, ...)])
2003
+ */
2004
+ declare function booleanSearch(exprs: ExpressionRef[]): ExpressionRef;
2005
+ /**
2006
+ * Full BM25 multi-field search with per-field boost weights.
2007
+ *
2008
+ * Produces: table @@@ paradedb.boolean(boost1, boost2, ...)
2009
+ *
2010
+ * Each field in `fieldBoosts` generates a `paradedb.boost(weight, paradedb.parse(field, $N))`
2011
+ * sub-expression. The same query string is used for all fields (single parameter binding).
2012
+ *
2013
+ * @param table - Table alias for the left side of the @@@ operator
2014
+ * @param query - Query string (bound as a single $N parameter, shared across all fields)
2015
+ * @param fieldBoosts - Map of column name → boost weight
2016
+ * @returns ExpressionRef for use in .where()
2017
+ *
2018
+ * @example
2019
+ * bm25Search('s', searchTerm, {
2020
+ * name_searchable: 3.0,
2021
+ * name: 1.0,
2022
+ * signature: 1.5,
2023
+ * doc_searchable: 1.0,
2024
+ * })
2025
+ * // → s @@@ paradedb.boolean(
2026
+ * // paradedb.boost(3.0, paradedb.parse('name_searchable', $1)),
2027
+ * // paradedb.boost(1.0, paradedb.parse('name', $1)),
2028
+ * // paradedb.boost(1.5, paradedb.parse('signature', $1)),
2029
+ * // paradedb.boost(1.0, paradedb.parse('doc_searchable', $1))
2030
+ * // )
2031
+ *
2032
+ * @remarks
2033
+ * The query parameter is shared: all parse() calls reference the same $N slot.
2034
+ * If you need different query strings per field, compose parse()/boost()/booleanSearch() manually.
2035
+ *
2036
+ * @remarks
2037
+ * ParadeDB's boolean() function accepts both positional args and the named
2038
+ * `should => ARRAY[...]` syntax. This wrapper uses positional args.
2039
+ * Named parameter syntax is deferred to EXT-NAMED-PARAMS.
2040
+ */
2041
+ declare function bm25Search(table: string, query: unknown, fieldBoosts: Record<string, number>): ExpressionRef;
2042
+
2043
+ /**
2044
+ * PostgreSQL built-in function helpers.
2045
+ *
2046
+ * Thin wrappers around core expression primitives for common PostgreSQL functions.
2047
+ * Same pattern as pgvector.ts and paradedb.ts.
2048
+ */
2049
+
2050
+ /**
2051
+ * Generate a series of values: generate_series(start, stop[, step])
2052
+ *
2053
+ * Returns a set of values from start to stop (inclusive), with an optional step.
2054
+ * Commonly used with CTE for batch operations.
2055
+ *
2056
+ * @example generateSeries(1, 100) → generate_series(1, 100)
2057
+ * @example generateSeries(0, 50, 5) → generate_series(0, 50, 5)
2058
+ */
2059
+ declare function generateSeries(start: number, stop: number, step?: number): ExpressionRef;
2060
+ /**
2061
+ * Get next value from a sequence: nextval('sequence_name')
2062
+ *
2063
+ * @example nextval('order_id_seq') → nextval('order_id_seq')
2064
+ */
2065
+ declare function nextval(sequenceName: string): ExpressionRef;
2066
+
2067
+ /**
2068
+ * pgvector Extension Wrappers
2069
+ *
2070
+ * Type-safe query builders for pgvector distance operators.
2071
+ * All functions return ExpressionRef instances that can be used in:
2072
+ * - SELECT: .column(cosineDistance('vector', qv).as('score'))
2073
+ * - WHERE: .where(cosineDistance('vector', qv).gte(0.5))
2074
+ * - ORDER BY: .orderBy(rawDistance('vector', qv), 'asc')
2075
+ */
2076
+
2077
+ /**
2078
+ * Cosine similarity: 1 - (col <=> vector)
2079
+ *
2080
+ * Score in [0, 1], higher = more similar.
2081
+ * Use in SELECT to get a similarity score.
2082
+ *
2083
+ * @example
2084
+ * orm.select('embeddings').column(cosineDistance('vector', qv).as('score'))
2085
+ */
2086
+ declare function cosineDistance(column: string, vector: number[]): ExpressionRef;
2087
+ /**
2088
+ * Raw cosine distance: col <=> vector
2089
+ *
2090
+ * Lower = closer. Index-friendly — use in ORDER BY for ANN search.
2091
+ * Do NOT use in SELECT as a similarity score (lower = closer is counterintuitive).
2092
+ *
2093
+ * @example
2094
+ * orm.select('embeddings').orderBy(rawDistance('vector', qv), 'asc')
2095
+ */
2096
+ declare function rawDistance(column: string, vector: number[]): ExpressionRef;
2097
+ /**
2098
+ * L2 (Euclidean) distance: col <-> vector
2099
+ *
2100
+ * @example
2101
+ * orm.select('embeddings').orderBy(l2Distance('vector', qv), 'asc')
2102
+ */
2103
+ declare function l2Distance(column: string, vector: number[]): ExpressionRef;
2104
+ /**
2105
+ * Inner product distance: col <#> vector (negative inner product)
2106
+ *
2107
+ * For maximum inner product search: ORDER BY innerProduct('vector', qv) ASC.
2108
+ *
2109
+ * @example
2110
+ * orm.select('embeddings').orderBy(innerProduct('vector', qv), 'asc')
2111
+ */
2112
+ declare function innerProduct(column: string, vector: number[]): ExpressionRef;
2113
+ /**
2114
+ * Get the number of dimensions of a vector column: vector_dims(col)
2115
+ *
2116
+ * Returns an integer — the dimension count of the stored vector.
2117
+ * Useful for sanity-checking that embeddings match the expected model dimension.
2118
+ *
2119
+ * @example
2120
+ * orm.from(embeddings).columns([vectorDims('vector').as('dim')]).first()
2121
+ * // → SELECT vector_dims("t0"."vector") AS "dim" FROM "embeddings" AS "t0"
2122
+ */
2123
+ declare function vectorDims(column: string): ExpressionRef;
2124
+
2125
+ /**
2126
+ * Mutation Compiler
2127
+ *
2128
+ * Compiles INSERT, UPDATE, and DELETE statements from plan decisions.
2129
+ * Supports:
2130
+ * - INSERT with values/from subquery
2131
+ * - INSERT with RETURNING
2132
+ * - UPDATE with SET and WHERE
2133
+ * - DELETE with WHERE
2134
+ * - RETURNING clause for all mutations
2135
+ */
2136
+
2137
+ /**
2138
+ * Configuration for INSERT compilation
2139
+ */
2140
+ interface InsertConfig {
2141
+ /** Table to insert into */
2142
+ table: string;
2143
+ /** Columns to insert */
2144
+ columns: string[];
2145
+ /** Values for each column (array of rows) */
2146
+ values: unknown[][];
2147
+ /** Columns to return (RETURNING clause) */
2148
+ returning?: string[];
2149
+ /** Alias-aware RETURNING projection items */
2150
+ returningItems?: readonly MutationReturningItem[];
2151
+ /** Subquery for INSERT ... SELECT */
2152
+ selectQuery?: Node;
2153
+ /** Column database types for type-cast emission (e.g. range types) */
2154
+ columnTypes?: Record<string, string>;
2155
+ }
2156
+ /**
2157
+ * Configuration for UPDATE compilation
2158
+ */
2159
+ interface UpdateConfig {
2160
+ /** Table to update */
2161
+ table: string;
2162
+ /** Column-value pairs to set */
2163
+ set: {
2164
+ column: string;
2165
+ value: unknown;
2166
+ }[];
2167
+ /** WHERE conditions */
2168
+ where?: Decision[];
2169
+ /** Columns to return (RETURNING clause) */
2170
+ returning?: string[];
2171
+ /** Alias-aware RETURNING projection items */
2172
+ returningItems?: readonly MutationReturningItem[];
2173
+ /** Column database types for type-cast emission (e.g. range types) */
2174
+ columnTypes?: Record<string, string>;
2175
+ }
2176
+ /**
2177
+ * Configuration for DELETE compilation
2178
+ */
2179
+ interface DeleteConfig {
2180
+ /** Table to delete from */
2181
+ table: string;
2182
+ /** WHERE conditions */
2183
+ where?: Decision[];
2184
+ /** Columns to return (RETURNING clause) */
2185
+ returning?: string[];
2186
+ /** Alias-aware RETURNING projection items */
2187
+ returningItems?: readonly MutationReturningItem[];
2188
+ }
2189
+ /**
2190
+ * Compile an INSERT statement from configuration.
2191
+ */
2192
+ declare function compileInsert(config: InsertConfig, ctx: CompilerContext, state: CompilerState): Node;
2193
+ /**
2194
+ * Compile an UPDATE statement from configuration.
2195
+ */
2196
+ declare function compileUpdate(config: UpdateConfig, ctx: CompilerContext, state: CompilerState): Node;
2197
+ declare function compileDelete(config: DeleteConfig, ctx: CompilerContext, state: CompilerState): Node;
2198
+ /**
2199
+ * Compile a mutation decision to AST.
2200
+ * Determines mutation type from decision.type and delegates.
2201
+ */
2202
+ declare function compileMutation(decision: Decision, ctx: CompilerContext, state: CompilerState): Node;
2203
+
2204
+ /**
2205
+ * Upsert (INSERT ... ON CONFLICT) Compiler
2206
+ *
2207
+ * Compiles UPSERT statements with ON CONFLICT handling.
2208
+ * Supports:
2209
+ * - ON CONFLICT DO NOTHING
2210
+ * - ON CONFLICT DO UPDATE SET ...
2211
+ * - Conflict target (columns or constraint name)
2212
+ * - WHERE clause for conflict resolution
2213
+ */
2214
+
2215
+ /**
2216
+ * Conflict resolution strategy
2217
+ */
2218
+ type ConflictAction = 'nothing' | 'update';
2219
+ /**
2220
+ * Conflict target specification
2221
+ */
2222
+ interface ConflictTarget {
2223
+ /** Column names that form the unique constraint */
2224
+ columns?: string[];
2225
+ /** Named constraint */
2226
+ constraint?: string;
2227
+ /** WHERE clause for partial index */
2228
+ where?: Decision[];
2229
+ }
2230
+ /**
2231
+ * Configuration for UPSERT compilation
2232
+ */
2233
+ interface UpsertConfig {
2234
+ /** Table to upsert into */
2235
+ table: string;
2236
+ /** Columns to insert */
2237
+ columns: string[];
2238
+ /** Values for each column (array of rows) */
2239
+ values: unknown[][];
2240
+ /** Conflict target (unique columns or constraint) */
2241
+ conflictTarget: ConflictTarget;
2242
+ /** What to do on conflict */
2243
+ conflictAction: ConflictAction;
2244
+ /** Columns to update on conflict (for 'update' action) */
2245
+ updateColumns?: string[];
2246
+ /** Optional WHERE clause for ON CONFLICT DO UPDATE */
2247
+ actionWhere?: Decision[];
2248
+ /** Optional direct WHERE intent for ON CONFLICT DO UPDATE */
2249
+ actionWhereIntent?: WhereIntent;
2250
+ /** Compile the direct action WHERE intent using the caller's WHERE compiler */
2251
+ compileActionWhere?: (where: WhereIntent, state: CompilerState) => Node;
2252
+ /** Use EXCLUDED.column for update values (default: true) */
2253
+ useExcluded?: boolean;
2254
+ /** Columns to return (RETURNING clause) */
2255
+ returning?: string[];
2256
+ /** Alias-aware RETURNING projection items */
2257
+ returningItems?: readonly MutationReturningItem[];
2258
+ /** Optional column type hints for unnest casting (schema-driven) */
2259
+ columnTypes?: Record<string, string>;
2260
+ /**
2261
+ * Raw SQL expressions for specific update columns.
2262
+ * These are injected verbatim into the ON CONFLICT DO UPDATE SET clause.
2263
+ * Keys are logical column names (before naming plugin), values are raw SQL fragments.
2264
+ *
2265
+ * @warning SECURITY: fragments are inserted without parameterization.
2266
+ * Only use with hardcoded expressions. Never with user input.
2267
+ *
2268
+ * @example { last_parsed: 'now()', count: 'excluded.count + 1' }
1982
2269
  */
1983
- validateIdentifier(value: string, type: string): void;
2270
+ updateExpressions?: Record<string, string>;
1984
2271
  }
1985
2272
  /**
1986
- * Create a PgsqlAdapter from a pg Pool instance.
1987
- *
1988
- * @param pool - pg Pool instance
1989
- * @param options - Optional configuration
1990
- * @returns A new PgsqlAdapter instance
1991
- *
1992
- * @example
1993
- * ```typescript
1994
- * import { Pool } from 'pg';
1995
- * import { createPgsqlAdapter } from '@dbsp/adapter-pgsql';
2273
+ * Build ON CONFLICT clause for INSERT statement.
2274
+ */
2275
+ declare function buildOnConflictClause(config: UpsertConfig, ctx: CompilerContext, state: CompilerState): OnConflictClause;
2276
+ /**
2277
+ * Compile a complete UPSERT statement.
2278
+ */
2279
+ declare function compileUpsert(config: UpsertConfig, ctx: CompilerContext, state: CompilerState): Node;
2280
+ /**
2281
+ * Build EXCLUDED.column reference.
2282
+ * EXCLUDED is a special table alias in ON CONFLICT ... DO UPDATE
2283
+ * that refers to the row that would have been inserted.
2284
+ */
2285
+ declare function excludedRef(column: string, naming: {
2286
+ toDatabase: (s: string) => string;
2287
+ }): Node;
2288
+ /**
2289
+ * Build conditional update using COALESCE.
1996
2290
  *
1997
- * const pool = new Pool({ connectionString: process.env.DATABASE_URL });
1998
- * const adapter = createPgsqlAdapter(pool);
2291
+ * Produces: COALESCE(EXCLUDED.col, table.col)
2292
+ * This keeps existing value if new value is NULL.
2293
+ */
2294
+ declare function conditionalUpdate(column: string, table: string, ctx: CompilerContext): Node;
2295
+
2296
+ /**
2297
+ * @module naming
2298
+ * Utilities for resolving database names to logical model names.
1999
2299
  *
2000
- * // With naming convention
2001
- * const adapter = createPgsqlAdapter(pool, { dbCasing: 'snake_case' });
2002
- * ```
2300
+ * The ModelIR.getTable() method expects logical (camelCase) names,
2301
+ * but the adapter often works with database (snake_case) names.
2302
+ * This module bridges that gap.
2003
2303
  */
2004
- declare function createPgsqlAdapter<DB = unknown>(pool: Pool, options?: PgsqlAdapterOptions): PgsqlAdapter<DB>;
2304
+
2005
2305
  /**
2006
- * Creates a compile-only PgsqlAdapter for SQL generation without a database connection.
2306
+ * Resolve a database table name to the corresponding logical model name.
2007
2307
  *
2008
- * All compilation methods (compile, compileInsert, etc.), createDump(), and generateDDL()
2009
- * work normally. Execution methods (execute, stream, transaction, etc.) throw an error.
2308
+ * Converts the DB name using the naming convention, then looks it up in the model.
2309
+ * Falls back to exact match if conversion doesn't find a match.
2310
+ *
2311
+ * @param model - The model IR to search in
2312
+ * @param dbName - Database table name (e.g. "post_comments")
2313
+ * @param convention - Naming convention used by the adapter
2314
+ * @returns The logical table name if found, undefined otherwise
2010
2315
  *
2011
2316
  * @example
2012
2317
  * ```typescript
2013
- * import { createPgsqlCompileOnlyAdapter } from '@dbsp/adapter-pgsql';
2014
- * import { createOrm } from '@dbsp/core';
2015
- *
2016
- * const adapter = createPgsqlCompileOnlyAdapter();
2017
- * const orm = createOrm({ model, adapter });
2018
- * const dump = await orm.select('users').dump();
2019
- * console.log(dump.sql);
2318
+ * // With camelCase convention:
2319
+ * resolveLogicalName(model, "post_comments", "camelCase") // → "postComments"
2320
+ * resolveLogicalName(model, "posts", "camelCase") // → "posts"
2321
+ * resolveLogicalName(model, "unknown", "camelCase") // → undefined
2020
2322
  * ```
2021
2323
  */
2022
- declare function createPgsqlCompileOnlyAdapter<DB = unknown>(options?: PgsqlAdapterOptions): CompileOnlyAdapter;
2324
+ declare function resolveLogicalName(model: ModelIR, dbName: string, casing: DbCasing): string | undefined;
2325
+
2326
+ /**
2327
+ * ParamRef validation and helpers for PostgreSQL AST
2328
+ *
2329
+ * ParamRef nodes represent parameterized query placeholders ($1, $2, etc.)
2330
+ * This module provides validation and creation helpers for safe AST construction.
2331
+ */
2332
+
2333
+ /**
2334
+ * Validation result for ParamRef nodes
2335
+ */
2336
+ interface ParamRefValidationResult {
2337
+ valid: boolean;
2338
+ errors: string[];
2339
+ }
2340
+ /**
2341
+ * Validates a ParamRef node
2342
+ *
2343
+ * Rules:
2344
+ * - `number` must be a positive integer (1-based indexing)
2345
+ * - `number` must not exceed reasonable bounds (e.g., 65535)
2346
+ */
2347
+ declare function validateParamRef(paramRef: ParamRef): ParamRefValidationResult;
2348
+ /**
2349
+ * Creates a validated ParamRef node
2350
+ * @throws Error if validation fails
2351
+ */
2352
+ declare function createParamRef(number: number, location?: number): Node;
2353
+ /**
2354
+ * Creates a TypeCast node wrapping a ParamRef
2355
+ * Example: $1::integer, $2::text[]
2356
+ */
2357
+ declare function createTypeCastParamRef(paramNumber: number, typeName: string, isArray?: boolean, location?: number): Node;
2358
+ /**
2359
+ * Creates an A_Expr node for equality comparison with ParamRef
2360
+ * Example: col = $1
2361
+ */
2362
+ declare function createEqualityExpr(columnName: string, paramNumber: number, tableName?: string, location?: number): Node;
2363
+ /**
2364
+ * Creates a FuncCall node for ANY() with ParamRef
2365
+ * Example: col = ANY($1) for array parameter matching
2366
+ */
2367
+ declare function createAnyExpr(columnName: string, paramNumber: number, tableName?: string, location?: number): Node;
2368
+ /**
2369
+ * Collects all ParamRef nodes from an AST, validating each
2370
+ * Returns validation results for all found ParamRefs
2371
+ */
2372
+ declare function collectAndValidateParamRefs(node: unknown): {
2373
+ paramRefs: Array<{
2374
+ paramRef: ParamRef;
2375
+ path: string;
2376
+ }>;
2377
+ validationResults: ParamRefValidationResult[];
2378
+ allValid: boolean;
2379
+ };
2380
+
2381
+ declare function derivePostgresqlCapabilitiesForVersion(version: string): DialectCapabilities;
2023
2382
 
2024
2383
  /**
2025
2384
  * Redact sensitive values in a query dump's `params` array before logging.
@@ -2051,6 +2410,28 @@ declare const DEFAULT_REDACTION_PATTERNS: ReadonlyArray<RegExp>;
2051
2410
  */
2052
2411
  declare function redactParams(params: readonly unknown[], config: RedactionConfig): readonly unknown[];
2053
2412
 
2413
+ declare const projectionEnvelopeBrand: unique symbol;
2414
+ type ProjectionEnvelope<T = unknown> = {
2415
+ readonly [projectionEnvelopeBrand]: true;
2416
+ readonly sql: string;
2417
+ readonly parameters: readonly unknown[];
2418
+ readonly ast?: Node;
2419
+ readonly projection: ProjectionState;
2420
+ readonly hydrationPlan?: PlanReport;
2421
+ readonly __resultType?: T;
2422
+ };
2423
+ type ProjectionState = {
2424
+ readonly kind: 'known';
2425
+ readonly outputs: ReadonlyMap<string, OutputProjection>;
2426
+ } | {
2427
+ readonly kind: 'dropped';
2428
+ readonly reason: ProjectionDropReason;
2429
+ readonly hadConvertibleSource: boolean;
2430
+ };
2431
+ type OutputProjection = OutputDescriptor;
2432
+
2433
+ type ProjectionDropReason = 'set-operation-positional-merge' | 'raw-recursive-cte-positional-merge' | 'unknown-raw-sql' | 'unsupported-source';
2434
+
2054
2435
  /**
2055
2436
  * Set operation compiler (UNION / INTERSECT / EXCEPT)
2056
2437
  *
@@ -2059,37 +2440,33 @@ declare function redactParams(params: readonly unknown[], config: RedactionConfi
2059
2440
  */
2060
2441
 
2061
2442
  /**
2062
- * Compiled SQL with positional parameters.
2443
+ * Compiled set-operation SQL with positional parameters.
2063
2444
  */
2064
- interface SetOperationResult {
2065
- readonly sql: string;
2066
- readonly parameters: readonly unknown[];
2067
- }
2445
+ type SetOperationResult<T = unknown> = CompiledQuery<T>;
2068
2446
  /**
2069
- * Function that compiles a single QueryIntent leaf to SQL + parameters.
2447
+ * Function that compiles a single QueryIntent leaf to a projection envelope, or
2448
+ * a compiled query that can be bridged into one.
2070
2449
  * Provided by the caller to decouple from adapter internals.
2071
2450
  */
2072
- type LeafCompileFn = (query: QueryIntent) => {
2073
- sql: string;
2074
- parameters: readonly unknown[];
2075
- };
2451
+ type LeafCompileResult = ProjectionEnvelope | CompiledQuery;
2452
+ type LeafCompileFn = (query: QueryIntent) => LeafCompileResult;
2076
2453
  /**
2077
2454
  * Recursively compile a SetOperationIntent to SQL with merged parameters.
2078
2455
  *
2079
- * Each leaf QueryIntent is compiled via `compileFn`. When merging left and
2080
- * right branches, the right side's `$N` placeholders are renumbered so they
2081
- * don't collide with the left side's parameters.
2456
+ * Each leaf QueryIntent is compiled via `compileFn` to a projection envelope.
2457
+ * When merging left and right branches, the right side's `$N` placeholders are
2458
+ * renumbered so they don't collide with the left side's parameters. The final
2459
+ * set operation drops positional projection provenance through the envelope so
2460
+ * `finalizeEnvelope` owns the set-operation `js` fail-loud behavior.
2082
2461
  *
2083
2462
  * @param intent - The set operation intent (recursive tree)
2084
- * @param compileFn - Compiles a single QueryIntent to SQL + params
2463
+ * @param compileFn - Compiles a single QueryIntent to an envelope-compatible result
2085
2464
  * @returns Combined SQL string and merged parameter array
2086
2465
  *
2087
2466
  * @example
2088
2467
  * ```typescript
2089
- * const result = compileSetOperation(setOpIntent, (query) => {
2090
- * const planReport = plan(query, model, { dialectCapabilities });
2091
- * return adapter.compile(planReport, { model });
2092
- * });
2468
+ * const compileFn = createLeafCompileFn(adapter, model, plan);
2469
+ * const result = compileSetOperation(setOpIntent, compileFn);
2093
2470
  * console.log(result.sql); // (SELECT ...) UNION (SELECT ...)
2094
2471
  * console.log(result.parameters); // [...leftParams, ...rightParams]
2095
2472
  * ```
@@ -2108,10 +2485,7 @@ declare function compileSetOperation(intent: SetOperationIntent, compileFn: Leaf
2108
2485
  declare function createLeafCompileFn(adapter: {
2109
2486
  compile(plan: PlanReport, options: CompileOptions & {
2110
2487
  model: ModelIR$1;
2111
- }): {
2112
- sql: string;
2113
- parameters: readonly unknown[];
2114
- };
2488
+ }): CompiledQuery;
2115
2489
  dialectCapabilities: DialectCapabilities;
2116
2490
  }, model: ModelIR$1, planFn: (intent: QueryIntent, model: ModelIR$1, options: {
2117
2491
  dialectCapabilities: DialectCapabilities;
@@ -2273,6 +2647,550 @@ declare function buildStreamingStatements(query: Node, config?: StreamConfig): {
2273
2647
  close: Node;
2274
2648
  };
2275
2649
 
2650
+ declare const PG_OPERATION_PACK_ARTIFACT: SemanticArtifactRef;
2651
+ declare const PG_RULE_PACK_ARTIFACT: SemanticArtifactRef;
2652
+ declare const PG_INTROSPECTION_ARTIFACT: SemanticArtifactRef;
2653
+ declare const ALTER_COLUMN_SET_NOT_NULL_OPERATION_KIND: OperationKindRef;
2654
+ declare const ALTER_TYPE_ADD_VALUE_OPERATION_KIND: OperationKindRef;
2655
+ declare const ATTACH_LOGICAL_IDENTITY_OPERATION_KIND: OperationKindRef;
2656
+ declare const MANUAL_SQL_OPERATION_KIND: OperationKindRef;
2657
+ declare const SET_NOT_NULL_RULE_ID = "postgresql.column.set-not-null";
2658
+ declare const ADD_CHECK_RULE_ID = "postgresql.table.add-check";
2659
+ declare const ENUM_ADD_VALUE_RULE_ID = "postgresql.enum.add-value";
2660
+ declare const LOGICAL_IDENTITY_ADOPTION_RULE_ID = "postgresql.logical-identity.adopt";
2661
+ declare const DBSP_META_SCHEMA = "dbsp_meta";
2662
+ declare const DBSP_TRANSITION_RUN_TABLE = "dbsp_transition_run";
2663
+ declare const DBSP_TRANSITION_JOURNAL_TABLE = "dbsp_transition_journal";
2664
+ declare const DBSP_LOGICAL_IDENTITY_TABLE = "dbsp_logical_identity";
2665
+ declare const COLUMN_EXISTS_OBSERVATION = "postgresql.column.exists";
2666
+ declare const ENUM_TYPE_EXISTS_OBSERVATION = "postgresql.enum-type.exists";
2667
+ declare const ENUM_LABEL_VISIBLE_OBSERVATION = "postgresql.enum-label.visible";
2668
+ declare const ALTER_AUTHORITY_OBSERVATION = "postgresql.table.alter-authority";
2669
+ declare const ENGINE_VERSION_OBSERVATION = "postgresql.engine.version-supported";
2670
+ declare const LOGICAL_IDENTITY_CARRIER_OBSERVATION = "postgresql.logical-identity.carrier-state";
2671
+ declare const NO_NULLS_GUARD = "NO_NULLS";
2672
+
2673
+ type QueryResultLike = {
2674
+ readonly rows: readonly Record<string, unknown>[];
2675
+ };
2676
+ type TransitionJournalQueryable = {
2677
+ query(sql: string, params?: readonly unknown[]): Promise<QueryResultLike>;
2678
+ };
2679
+ declare function renderCreateDbspMetaSchemaSql(): string;
2680
+ declare function renderCreateTransitionRunTableSql(): string;
2681
+ declare function renderCreateTransitionJournalTableSql(): string;
2682
+ declare function ensureTransitionJournal(executor: TransitionJournalQueryable): Promise<void>;
2683
+ declare function readTransitionJournal(executor: TransitionJournalQueryable, runId: string): Promise<TransitionRunJournal>;
2684
+
2685
+ type ObservationTarget = {
2686
+ readonly table: string;
2687
+ readonly column?: string;
2688
+ readonly constraint?: string;
2689
+ readonly index?: string;
2690
+ readonly schema?: string;
2691
+ };
2692
+ type EnumObservationTarget = {
2693
+ readonly type: string;
2694
+ readonly label?: string;
2695
+ readonly schema?: string;
2696
+ };
2697
+ declare function createPgObservationIssuer(): ObservationIssuer;
2698
+ declare function readPgObservationContext(target: unknown, schema?: string, observationTarget?: ObservationTarget | EnumObservationTarget): Promise<ObservationContext>;
2699
+
2700
+ interface SetNotNullColumnShapeExpectation {
2701
+ readonly kind: 'postgresql.set-not-null.column-shape.v1';
2702
+ readonly name: string;
2703
+ readonly nullability: {
2704
+ readonly from: true;
2705
+ readonly to: boolean;
2706
+ };
2707
+ readonly type: TypeRef;
2708
+ readonly default: ExpressionValue | null;
2709
+ readonly collation: CollationRef;
2710
+ readonly identity: 'always' | 'byDefault' | null;
2711
+ readonly generated: string | null;
2712
+ readonly autoIncrement: boolean;
2713
+ readonly unique: boolean;
2714
+ readonly uniqueConstraintName: string | null;
2715
+ readonly logicalIdentity?: LogicalIdentity | null;
2716
+ readonly comment: string | null;
2717
+ readonly target?: ColumnDefaultAttestationTarget;
2718
+ }
2719
+ interface ColumnDefaultAttestationTarget {
2720
+ readonly database?: string;
2721
+ readonly schema?: string;
2722
+ readonly table: string;
2723
+ readonly column: string;
2724
+ }
2725
+
2726
+ type AlterColumnSetNotNullPayload = {
2727
+ readonly table: string;
2728
+ readonly column: string;
2729
+ readonly schema?: string;
2730
+ readonly expectedColumnShape?: SetNotNullColumnShapeExpectation;
2731
+ };
2732
+ type TransitionExecutionClient$3 = {
2733
+ readonly opaqueClient: unknown;
2734
+ };
2735
+ declare function renderAlterColumnSetNotNullSql(payload: AlterColumnSetNotNullPayload, context: ObservationContext): string;
2736
+ declare function renderSetNotNullLockSql(payload: AlterColumnSetNotNullPayload, context: ObservationContext): string;
2737
+ declare function renderNoNullsCheckSql(payload: AlterColumnSetNotNullPayload, context: ObservationContext): string;
2738
+ declare function beforeAfterFingerprints$3(operation: PhysicalOperation, evidence: readonly EvidenceObservation[], context: ObservationContext): {
2739
+ expectedBefore: FingerprintManifest;
2740
+ expectedAfter: FingerprintManifest;
2741
+ };
2742
+ declare function createAlterColumnSetNotNullOperationRuntime(): {
2743
+ artifact: _dbsp_types.SemanticArtifactRef;
2744
+ supportsOperation(operation: PhysicalOperation): boolean;
2745
+ effectsOf(operation: PhysicalOperation, context: ObservationContext): OperationEffectAssessment;
2746
+ buildFingerprints: typeof beforeAfterFingerprints$3;
2747
+ checkout(target: unknown): Promise<TransitionExecutionClient$3>;
2748
+ release(client: TransitionExecutionClient$3, error?: unknown): void;
2749
+ writeIntentJournal(client: TransitionExecutionClient$3, record: DurableIntentRecord): Promise<void>;
2750
+ begin(client: TransitionExecutionClient$3): Promise<void>;
2751
+ setLockTimeout(client: TransitionExecutionClient$3, maxWaitMs: number): Promise<void>;
2752
+ acquireLocks(client: TransitionExecutionClient$3, operation: PhysicalOperation, _effects: OperationEffectAssessment, context: ObservationContext): Promise<void>;
2753
+ observeContext(client: TransitionExecutionClient$3, operation: PhysicalOperation, _proofContext: ObservationContext): Promise<ObservationContext>;
2754
+ observeOperation(client: TransitionExecutionClient$3, operation: PhysicalOperation, context: ObservationContext, _phase: "before" | "after", issuer: ObservationIssuer): Promise<{
2755
+ observations: IssuedObservation[];
2756
+ fingerprint: FingerprintManifest;
2757
+ }>;
2758
+ checkGuard(client: TransitionExecutionClient$3, operation: PhysicalOperation, guard: ApplyGuard, context: ObservationContext): Promise<{
2759
+ passed: boolean;
2760
+ observations: AdvisoryObservation[];
2761
+ recovery: readonly _dbsp_types.RecoveryArtefact[];
2762
+ }>;
2763
+ executeOperation(client: TransitionExecutionClient$3, operation: PhysicalOperation, context: ObservationContext, duringGuards?: readonly ApplyGuard[]): Promise<{
2764
+ kind: string;
2765
+ }>;
2766
+ writeCompletionJournal(client: TransitionExecutionClient$3, operation: PhysicalOperation, record: TransactionalCompletionRecord): Promise<void>;
2767
+ commit(client: TransitionExecutionClient$3): Promise<void>;
2768
+ rollback(client: TransitionExecutionClient$3): Promise<void>;
2769
+ writeObservedJournal(client: TransitionExecutionClient$3, journal: StepJournal): Promise<void>;
2770
+ isLockTimeout(error: unknown): boolean;
2771
+ };
2772
+
2773
+ type AlterTypeAddValuePayload = {
2774
+ readonly schema: string;
2775
+ readonly type: string;
2776
+ readonly label: string;
2777
+ readonly after?: string;
2778
+ readonly expectedBefore: readonly string[];
2779
+ readonly expectedAfter: readonly string[];
2780
+ };
2781
+ type TransitionExecutionClient$2 = {
2782
+ readonly opaqueClient: unknown;
2783
+ };
2784
+ declare function renderAlterTypeAddValueSql(payload: AlterTypeAddValuePayload, context: ObservationContext): string;
2785
+ declare function beforeAfterFingerprints$2(operation: PhysicalOperation, evidence: readonly EvidenceObservation[], context: ObservationContext): {
2786
+ expectedBefore: FingerprintManifest;
2787
+ expectedAfter: FingerprintManifest;
2788
+ };
2789
+ declare function createAlterTypeAddValueOperationRuntime(): {
2790
+ artifact: _dbsp_types.SemanticArtifactRef;
2791
+ operationKind: _dbsp_types.OperationKindRef;
2792
+ supportsOperation(operation: PhysicalOperation): boolean;
2793
+ effectsOf(operation: PhysicalOperation, context: ObservationContext): OperationEffectAssessment;
2794
+ buildFingerprints: typeof beforeAfterFingerprints$2;
2795
+ checkout(target: unknown): Promise<TransitionExecutionClient$2>;
2796
+ release(client: TransitionExecutionClient$2, error?: unknown): void;
2797
+ writeIntentJournal(client: TransitionExecutionClient$2, record: DurableIntentRecord): Promise<void>;
2798
+ begin(client: TransitionExecutionClient$2): Promise<void>;
2799
+ setLockTimeout(client: TransitionExecutionClient$2, maxWaitMs: number): Promise<void>;
2800
+ acquireLocks(client: TransitionExecutionClient$2, operation: PhysicalOperation): Promise<void>;
2801
+ observeContext(client: TransitionExecutionClient$2, operation: PhysicalOperation, _proofContext: ObservationContext): Promise<ObservationContext>;
2802
+ observeOperation(client: TransitionExecutionClient$2, operation: PhysicalOperation, context: ObservationContext, _phase: "before" | "after", issuer: ObservationIssuer): Promise<{
2803
+ observations: IssuedObservation[];
2804
+ fingerprint: FingerprintManifest;
2805
+ }>;
2806
+ checkGuard(client: TransitionExecutionClient$2, operation: PhysicalOperation, guard: ApplyGuard, context: ObservationContext): Promise<{
2807
+ passed: boolean;
2808
+ observations: EvidenceObservation[];
2809
+ recovery: readonly _dbsp_types.RecoveryArtefact[];
2810
+ }>;
2811
+ executeOperation(client: TransitionExecutionClient$2, operation: PhysicalOperation, context: ObservationContext, duringGuards?: readonly ApplyGuard[]): Promise<{
2812
+ kind: string;
2813
+ }>;
2814
+ writeCompletionJournal(client: TransitionExecutionClient$2, operation: PhysicalOperation, record: TransactionalCompletionRecord): Promise<void>;
2815
+ commit(client: TransitionExecutionClient$2): Promise<void>;
2816
+ rollback(client: TransitionExecutionClient$2): Promise<void>;
2817
+ writeObservedJournal(client: TransitionExecutionClient$2, journal: StepJournal): Promise<void>;
2818
+ isLockTimeout(error: unknown): boolean;
2819
+ };
2820
+
2821
+ type AttachLogicalIdentityPayload = {
2822
+ readonly schema: string;
2823
+ readonly table: string;
2824
+ readonly column?: string;
2825
+ readonly logicalId: string;
2826
+ readonly carrierKind: 'postgresql-side-table';
2827
+ readonly authenticated: false;
2828
+ };
2829
+ type TransitionExecutionClient$1 = {
2830
+ readonly opaqueClient: unknown;
2831
+ };
2832
+ declare function renderAttachLogicalIdentityLockSql(payload: AttachLogicalIdentityPayload): string;
2833
+ declare function renderCreateLogicalIdentitySideTableSql(_schema: string): string;
2834
+ declare function renderCreateLogicalIdentityIndexesSql(_schema: string): readonly string[];
2835
+ declare function renderInsertLogicalIdentitySql(_schema: string): string;
2836
+ declare function beforeAfterFingerprints$1(operation: PhysicalOperation, evidence: readonly EvidenceObservation[], context: ObservationContext): {
2837
+ expectedBefore: FingerprintManifest;
2838
+ expectedAfter: FingerprintManifest;
2839
+ };
2840
+ declare function createAttachLogicalIdentityOperationRuntime(): {
2841
+ artifact: _dbsp_types.SemanticArtifactRef;
2842
+ supportsOperation(operation: PhysicalOperation): boolean;
2843
+ effectsOf(operation: PhysicalOperation, context: ObservationContext): OperationEffectAssessment;
2844
+ buildFingerprints: typeof beforeAfterFingerprints$1;
2845
+ checkout(target: unknown): Promise<TransitionExecutionClient$1>;
2846
+ release(client: TransitionExecutionClient$1, error?: unknown): void;
2847
+ writeIntentJournal(client: TransitionExecutionClient$1, record: DurableIntentRecord): Promise<void>;
2848
+ begin(client: TransitionExecutionClient$1): Promise<void>;
2849
+ setLockTimeout(client: TransitionExecutionClient$1, maxWaitMs: number): Promise<void>;
2850
+ acquireLocks(client: TransitionExecutionClient$1, operation: PhysicalOperation): Promise<void>;
2851
+ observeContext(client: TransitionExecutionClient$1, operation: PhysicalOperation, _proofContext: ObservationContext): Promise<ObservationContext>;
2852
+ observeOperation(client: TransitionExecutionClient$1, operation: PhysicalOperation, context: ObservationContext, phase: "before" | "after", issuer: ObservationIssuer): Promise<{
2853
+ observations: IssuedObservation[];
2854
+ fingerprint: FingerprintManifest;
2855
+ }>;
2856
+ checkGuard(): Promise<{
2857
+ passed: boolean;
2858
+ observations: never[];
2859
+ recovery: never[];
2860
+ }>;
2861
+ executeOperation(client: TransitionExecutionClient$1, operation: PhysicalOperation): Promise<{
2862
+ kind: "completed";
2863
+ }>;
2864
+ writeCompletionJournal(client: TransitionExecutionClient$1, operation: PhysicalOperation, record: TransactionalCompletionRecord): Promise<void>;
2865
+ commit(client: TransitionExecutionClient$1): Promise<void>;
2866
+ rollback(client: TransitionExecutionClient$1): Promise<void>;
2867
+ writeObservedJournal(client: TransitionExecutionClient$1, journal: StepJournal): Promise<void>;
2868
+ isLockTimeout(error: unknown): boolean;
2869
+ };
2870
+
2871
+ type ManualSqlPayload = {
2872
+ readonly statement: UnsafeNativeFragment;
2873
+ readonly blastRadius: readonly ResourceAddress[];
2874
+ readonly preconditions: readonly ExecutableAssertion[];
2875
+ readonly postconditions: readonly ExecutableAssertion[];
2876
+ };
2877
+ type TransitionExecutionClient = {
2878
+ readonly opaqueClient: unknown;
2879
+ };
2880
+ declare function normalizeManualSqlPayload(payload: ManualSqlPayload, context: ObservationContext): ManualSqlPayload;
2881
+ declare function beforeAfterFingerprints(operation: PhysicalOperation, _evidence: readonly EvidenceObservation[], context: ObservationContext): {
2882
+ expectedBefore: FingerprintManifest;
2883
+ expectedAfter: FingerprintManifest;
2884
+ };
2885
+ declare function createManualSqlOperationRuntime(): {
2886
+ artifact: _dbsp_types.SemanticArtifactRef;
2887
+ operationKind: _dbsp_types.OperationKindRef;
2888
+ supportsOperation(operation: PhysicalOperation): boolean;
2889
+ effectsOf(operation: PhysicalOperation, context: ObservationContext): OperationEffectAssessment;
2890
+ buildFingerprints: typeof beforeAfterFingerprints;
2891
+ checkout(target: unknown): Promise<TransitionExecutionClient>;
2892
+ release(client: TransitionExecutionClient, error?: unknown): void;
2893
+ writeIntentJournal(client: TransitionExecutionClient, record: DurableIntentRecord): Promise<void>;
2894
+ begin(client: TransitionExecutionClient): Promise<void>;
2895
+ setLockTimeout(_client: TransitionExecutionClient, _maxWaitMs: number): Promise<void>;
2896
+ acquireLocks(): Promise<void>;
2897
+ observeContext(client: TransitionExecutionClient, _operation: PhysicalOperation, proofContext: ObservationContext): Promise<ObservationContext>;
2898
+ observeOperation(_client: TransitionExecutionClient, operation: PhysicalOperation, context: ObservationContext, phase: "before" | "after"): Promise<{
2899
+ observations: never[];
2900
+ fingerprint: FingerprintManifest;
2901
+ }>;
2902
+ checkGuard(): Promise<{
2903
+ passed: boolean;
2904
+ observations: never[];
2905
+ recovery: never[];
2906
+ }>;
2907
+ executeOperation(client: TransitionExecutionClient, operation: PhysicalOperation, context: ObservationContext): Promise<{
2908
+ kind: "completed";
2909
+ }>;
2910
+ writeCompletionJournal(client: TransitionExecutionClient, operation: PhysicalOperation, record: TransactionalCompletionRecord): Promise<void>;
2911
+ commit(client: TransitionExecutionClient): Promise<void>;
2912
+ rollback(client: TransitionExecutionClient): Promise<void>;
2913
+ writeObservedJournal(client: TransitionExecutionClient, journal: StepJournal): Promise<void>;
2914
+ isLockTimeout(error: unknown): boolean;
2915
+ };
2916
+
2917
+ interface SetNotNullMatch {
2918
+ readonly schema?: string;
2919
+ readonly database?: string;
2920
+ readonly table: string;
2921
+ readonly column: string;
2922
+ readonly expectedColumnShape: SetNotNullColumnShapeExpectation;
2923
+ readonly assumptions?: readonly Assumption[];
2924
+ }
2925
+ interface SetNotNullRuleOptions {
2926
+ readonly naming?: NamingPlugin;
2927
+ }
2928
+ declare function createSetNotNullRule(options?: SetNotNullRuleOptions): TransitionRule<SetNotNullMatch>;
2929
+
2930
+ interface EnumAddValueMatch {
2931
+ readonly schema?: string;
2932
+ readonly database?: string;
2933
+ readonly type: string;
2934
+ readonly label: string;
2935
+ readonly after?: string;
2936
+ readonly expectedBefore: readonly string[];
2937
+ readonly expectedAfter: readonly string[];
2938
+ readonly assumptions?: readonly Assumption[];
2939
+ }
2940
+ interface EnumAddValueRuleOptions {
2941
+ readonly naming?: NamingPlugin;
2942
+ }
2943
+ declare function satisfiesPgEnumLabelVisibleCompositionFact(fact: TransitionCompositionFact, current: ModelIR, _context: ObservationContext): boolean;
2944
+ declare function createEnumAddValueRule(options?: EnumAddValueRuleOptions): TransitionRule<EnumAddValueMatch>;
2945
+
2946
+ interface CreateUniqueIndexConcurrentlyMatch {
2947
+ readonly schema?: string;
2948
+ readonly database?: string;
2949
+ readonly table: string;
2950
+ readonly index: string;
2951
+ readonly columns: readonly string[];
2952
+ readonly assumptions?: readonly Assumption[];
2953
+ }
2954
+
2955
+ type IdentityAdoptionAsserter = Exclude<TrustRoot, {
2956
+ readonly kind: 'pack';
2957
+ }>;
2958
+ interface LogicalIdentityAdoptionMatch {
2959
+ readonly schema?: string;
2960
+ readonly database?: string;
2961
+ readonly table: string;
2962
+ readonly column?: string;
2963
+ readonly logicalId: string;
2964
+ readonly carrierKind: 'postgresql-side-table';
2965
+ readonly authenticated: false;
2966
+ readonly selectionBasis: string;
2967
+ }
2968
+ interface LogicalIdentityAdoptionRuleOptions {
2969
+ readonly naming?: NamingPlugin;
2970
+ readonly asserter?: IdentityAdoptionAsserter;
2971
+ readonly selectionBasis?: string;
2972
+ }
2973
+ declare function createLogicalIdentityAdoptionRule(options?: LogicalIdentityAdoptionRuleOptions): TransitionRule<LogicalIdentityAdoptionMatch>;
2974
+
2975
+ interface AddCheckMatch {
2976
+ readonly schema?: string;
2977
+ readonly database?: string;
2978
+ readonly table: string;
2979
+ readonly constraint: string;
2980
+ readonly expression: string;
2981
+ readonly requiresEnumLabels?: readonly RequiredEnumLabelIR[];
2982
+ readonly assumptions?: readonly Assumption[];
2983
+ }
2984
+
2985
+ interface PgTransitionPackOptions {
2986
+ readonly dbCasing?: DbCasing;
2987
+ readonly naming?: NamingPlugin;
2988
+ readonly identityAdoptionAsserter?: IdentityAdoptionAsserter;
2989
+ readonly identityAdoptionSelectionBasis?: string;
2990
+ }
2991
+ declare function createPgTransitionPack(options?: PgTransitionPackOptions): {
2992
+ rules: (_dbsp_types.TransitionRule<AddCheckMatch> | _dbsp_types.TransitionRule<LogicalIdentityAdoptionMatch> | _dbsp_types.TransitionRule<CreateUniqueIndexConcurrentlyMatch> | _dbsp_types.TransitionRule<EnumAddValueMatch> | _dbsp_types.TransitionRule<SetNotNullMatch>)[];
2993
+ operationSemantics: ({
2994
+ artifact: _dbsp_types.SemanticArtifactRef;
2995
+ supportsOperation(operation: _dbsp_types.PhysicalOperation): boolean;
2996
+ effectsOf(operation: _dbsp_types.PhysicalOperation, context: _dbsp_types.ObservationContext): _dbsp_types.OperationEffectAssessment;
2997
+ buildFingerprints: (operation: _dbsp_types.PhysicalOperation, evidence: readonly _dbsp_types.EvidenceObservation[], context: _dbsp_types.ObservationContext) => {
2998
+ expectedBefore: _dbsp_types.FingerprintManifest;
2999
+ expectedAfter: _dbsp_types.FingerprintManifest;
3000
+ };
3001
+ checkout(target: unknown): Promise<{
3002
+ readonly opaqueClient: unknown;
3003
+ }>;
3004
+ release(client: {
3005
+ readonly opaqueClient: unknown;
3006
+ }, error?: unknown): void;
3007
+ writeIntentJournal(client: {
3008
+ readonly opaqueClient: unknown;
3009
+ }, record: _dbsp_types.DurableIntentRecord): Promise<void>;
3010
+ begin(client: {
3011
+ readonly opaqueClient: unknown;
3012
+ }): Promise<void>;
3013
+ setLockTimeout(client: {
3014
+ readonly opaqueClient: unknown;
3015
+ }, maxWaitMs: number): Promise<void>;
3016
+ acquireLocks(client: {
3017
+ readonly opaqueClient: unknown;
3018
+ }, operation: _dbsp_types.PhysicalOperation, _effects: _dbsp_types.OperationEffectAssessment, context: _dbsp_types.ObservationContext): Promise<void>;
3019
+ observeContext(client: {
3020
+ readonly opaqueClient: unknown;
3021
+ }, operation: _dbsp_types.PhysicalOperation, _proofContext: _dbsp_types.ObservationContext): Promise<_dbsp_types.ObservationContext>;
3022
+ observeOperation(client: {
3023
+ readonly opaqueClient: unknown;
3024
+ }, operation: _dbsp_types.PhysicalOperation, context: _dbsp_types.ObservationContext, _phase: "before" | "after", issuer: _dbsp_types.ObservationIssuer): Promise<{
3025
+ observations: _dbsp_types.IssuedObservation[];
3026
+ fingerprint: _dbsp_types.FingerprintManifest;
3027
+ }>;
3028
+ checkGuard(client: {
3029
+ readonly opaqueClient: unknown;
3030
+ }, operation: _dbsp_types.PhysicalOperation, guard: _dbsp_types.ApplyGuard, context: _dbsp_types.ObservationContext): Promise<{
3031
+ passed: boolean;
3032
+ observations: _dbsp_types.AdvisoryObservation[];
3033
+ recovery: readonly _dbsp_types.RecoveryArtefact[];
3034
+ }>;
3035
+ executeOperation(client: {
3036
+ readonly opaqueClient: unknown;
3037
+ }, operation: _dbsp_types.PhysicalOperation, context: _dbsp_types.ObservationContext, duringGuards?: readonly _dbsp_types.ApplyGuard[]): Promise<{
3038
+ kind: string;
3039
+ }>;
3040
+ writeCompletionJournal(client: {
3041
+ readonly opaqueClient: unknown;
3042
+ }, operation: _dbsp_types.PhysicalOperation, record: _dbsp_types.TransactionalCompletionRecord): Promise<void>;
3043
+ commit(client: {
3044
+ readonly opaqueClient: unknown;
3045
+ }): Promise<void>;
3046
+ rollback(client: {
3047
+ readonly opaqueClient: unknown;
3048
+ }): Promise<void>;
3049
+ writeObservedJournal(client: {
3050
+ readonly opaqueClient: unknown;
3051
+ }, journal: _dbsp_types.StepJournal): Promise<void>;
3052
+ isLockTimeout(error: unknown): boolean;
3053
+ } | {
3054
+ artifact: _dbsp_types.SemanticArtifactRef;
3055
+ operationKind: _dbsp_types.OperationKindRef;
3056
+ supportsOperation(operation: _dbsp_types.PhysicalOperation): boolean;
3057
+ effectsOf(operation: _dbsp_types.PhysicalOperation, context: _dbsp_types.ObservationContext): _dbsp_types.OperationEffectAssessment;
3058
+ buildFingerprints: (operation: _dbsp_types.PhysicalOperation, evidence: readonly _dbsp_types.EvidenceObservation[], context: _dbsp_types.ObservationContext) => {
3059
+ expectedBefore: _dbsp_types.FingerprintManifest;
3060
+ expectedAfter: _dbsp_types.FingerprintManifest;
3061
+ };
3062
+ checkout(target: unknown): Promise<{
3063
+ readonly opaqueClient: unknown;
3064
+ }>;
3065
+ release(client: {
3066
+ readonly opaqueClient: unknown;
3067
+ }, error?: unknown): void;
3068
+ writeIntentJournal(client: {
3069
+ readonly opaqueClient: unknown;
3070
+ }, record: _dbsp_types.DurableIntentRecord): Promise<void>;
3071
+ begin(client: {
3072
+ readonly opaqueClient: unknown;
3073
+ }): Promise<void>;
3074
+ setLockTimeout(client: {
3075
+ readonly opaqueClient: unknown;
3076
+ }, maxWaitMs: number): Promise<void>;
3077
+ acquireLocks(client: {
3078
+ readonly opaqueClient: unknown;
3079
+ }, operation: _dbsp_types.PhysicalOperation): Promise<void>;
3080
+ observeContext(client: {
3081
+ readonly opaqueClient: unknown;
3082
+ }, operation: _dbsp_types.PhysicalOperation, _proofContext: _dbsp_types.ObservationContext): Promise<_dbsp_types.ObservationContext>;
3083
+ observeOperation(client: {
3084
+ readonly opaqueClient: unknown;
3085
+ }, operation: _dbsp_types.PhysicalOperation, context: _dbsp_types.ObservationContext, _phase: "before" | "after", issuer: _dbsp_types.ObservationIssuer): Promise<{
3086
+ observations: _dbsp_types.IssuedObservation[];
3087
+ fingerprint: _dbsp_types.FingerprintManifest;
3088
+ }>;
3089
+ checkGuard(client: {
3090
+ readonly opaqueClient: unknown;
3091
+ }, operation: _dbsp_types.PhysicalOperation, guard: _dbsp_types.ApplyGuard, context: _dbsp_types.ObservationContext): Promise<{
3092
+ passed: boolean;
3093
+ observations: _dbsp_types.EvidenceObservation[];
3094
+ recovery: readonly _dbsp_types.RecoveryArtefact[];
3095
+ }>;
3096
+ executeOperation(client: {
3097
+ readonly opaqueClient: unknown;
3098
+ }, operation: _dbsp_types.PhysicalOperation, context: _dbsp_types.ObservationContext, duringGuards?: readonly _dbsp_types.ApplyGuard[]): Promise<{
3099
+ kind: string;
3100
+ }>;
3101
+ writeCompletionJournal(client: {
3102
+ readonly opaqueClient: unknown;
3103
+ }, operation: _dbsp_types.PhysicalOperation, record: _dbsp_types.TransactionalCompletionRecord): Promise<void>;
3104
+ commit(client: {
3105
+ readonly opaqueClient: unknown;
3106
+ }): Promise<void>;
3107
+ rollback(client: {
3108
+ readonly opaqueClient: unknown;
3109
+ }): Promise<void>;
3110
+ writeObservedJournal(client: {
3111
+ readonly opaqueClient: unknown;
3112
+ }, journal: _dbsp_types.StepJournal): Promise<void>;
3113
+ isLockTimeout(error: unknown): boolean;
3114
+ } | {
3115
+ artifact: _dbsp_types.SemanticArtifactRef;
3116
+ operationKind: _dbsp_types.OperationKindRef;
3117
+ supportsOperation(operation: _dbsp_types.PhysicalOperation): boolean;
3118
+ effectsOf(operation: _dbsp_types.PhysicalOperation, context: _dbsp_types.ObservationContext): _dbsp_types.OperationEffectAssessment;
3119
+ buildFingerprints: (operation: _dbsp_types.PhysicalOperation, evidence: readonly _dbsp_types.EvidenceObservation[], context: _dbsp_types.ObservationContext) => {
3120
+ expectedBefore: _dbsp_types.FingerprintManifest;
3121
+ expectedAfter: _dbsp_types.FingerprintManifest;
3122
+ };
3123
+ checkout(target: unknown): Promise<{
3124
+ readonly opaqueClient: unknown;
3125
+ }>;
3126
+ release(client: {
3127
+ readonly opaqueClient: unknown;
3128
+ }, error?: unknown): void;
3129
+ writeIntentJournal(client: {
3130
+ readonly opaqueClient: unknown;
3131
+ }, record: _dbsp_types.DurableIntentRecord): Promise<void>;
3132
+ begin(_client: {
3133
+ readonly opaqueClient: unknown;
3134
+ }): Promise<never>;
3135
+ setLockTimeout(_client: {
3136
+ readonly opaqueClient: unknown;
3137
+ }, _maxWaitMs: number): Promise<void>;
3138
+ acquireLocks(): Promise<void>;
3139
+ observeContext(client: {
3140
+ readonly opaqueClient: unknown;
3141
+ }, operation: _dbsp_types.PhysicalOperation, _proofContext: _dbsp_types.ObservationContext): Promise<_dbsp_types.ObservationContext>;
3142
+ observeOperation(client: {
3143
+ readonly opaqueClient: unknown;
3144
+ }, operation: _dbsp_types.PhysicalOperation, context: _dbsp_types.ObservationContext, phase: "before" | "after", issuer: _dbsp_types.ObservationIssuer): Promise<{
3145
+ observations: _dbsp_types.IssuedObservation[];
3146
+ fingerprint: _dbsp_types.FingerprintManifest;
3147
+ }>;
3148
+ checkGuard(_client: {
3149
+ readonly opaqueClient: unknown;
3150
+ }, _operation: _dbsp_types.PhysicalOperation, guard: _dbsp_types.ApplyGuard): Promise<never>;
3151
+ executeOperation(client: {
3152
+ readonly opaqueClient: unknown;
3153
+ }, operation: _dbsp_types.PhysicalOperation, context: _dbsp_types.ObservationContext, duringGuards?: readonly _dbsp_types.ApplyGuard[], executionTracker?: _dbsp_core.NonRollbackableExecutionTracker): Promise<{
3154
+ kind: "partially-applied";
3155
+ recovery: _dbsp_types.RecoveryArtefact[];
3156
+ detail: string;
3157
+ } | {
3158
+ kind: string;
3159
+ guard?: never;
3160
+ recovery?: never;
3161
+ nonRollbackableFootprint?: never;
3162
+ } | {
3163
+ kind: string;
3164
+ guard: _dbsp_types.ApplyGuard;
3165
+ recovery: never[];
3166
+ nonRollbackableFootprint: string;
3167
+ }>;
3168
+ writeCompletionJournal(client: {
3169
+ readonly opaqueClient: unknown;
3170
+ }, operation: _dbsp_types.PhysicalOperation, record: _dbsp_types.TransactionalCompletionRecord): Promise<void>;
3171
+ commit(_client: {
3172
+ readonly opaqueClient: unknown;
3173
+ }): Promise<never>;
3174
+ rollback(_client: {
3175
+ readonly opaqueClient: unknown;
3176
+ }): Promise<never>;
3177
+ writeObservedJournal(client: {
3178
+ readonly opaqueClient: unknown;
3179
+ }, journal: _dbsp_types.StepJournal): Promise<void>;
3180
+ isLockTimeout(error: unknown): boolean;
3181
+ })[];
3182
+ issuer: _dbsp_types.ObservationIssuer;
3183
+ executionCoordinator: ExecutionCoordinator;
3184
+ transactionDomain: string;
3185
+ equivalence: _dbsp_types.EquivalenceCapability;
3186
+ capabilityDescriptors: readonly CapabilityDescriptor[];
3187
+ comparatorNameNormalizer: {
3188
+ normalizeCurrentIdentifier: (identifier: string) => string;
3189
+ };
3190
+ compositionFactKinds: string[];
3191
+ satisfiesCompositionFact: typeof satisfiesPgEnumLabelVisibleCompositionFact;
3192
+ };
3193
+
2276
3194
  /**
2277
3195
  * Identifier Validation for adapter-pgsql
2278
3196
  *
@@ -2342,4 +3260,4 @@ declare function sanitizeForDisplay(value: string): string;
2342
3260
  */
2343
3261
  declare function validateSqlExpression(sql: string, context: string): void;
2344
3262
 
2345
- export { type BatchValuesJoinDecision, CamelCaseNamingPlugin, type ChangeKind, type CompareSchemataOptions, type CompiledResult, type CompilerContext, type CompilerOptions, type CompilerState, type ConflictAction, type ConflictTarget, type CursorHoldOption, type CursorOptions, type CursorScrollOption, DEFAULT_PK_COLUMN, DEFAULT_REDACTION_PATTERNS, type Decision, type DeleteConfig, type DetectedHierarchy, type DiffSummary, type ExplainFormat, type ExplainOptions, type ExplainPlan, type ExpressionHandler, type FetchDirection, type FetchOptions, type FkColumnDerivation, type GenerateDDLOptions, IdentityNamingPlugin, type IncludeHandler, type IncludeResult, type InsertConfig, type IntrospectedModelIR, type IntrospectionOptions, InvalidIdentifierError, type JoinDecision, type LeafCompileFn, type MigrationRecord, type MigrationSQLOptions, type NamingPlugin, type ParamRefValidationResult, type ParsedMigrationFile, PgsqlAdapter, type PgsqlAdapterOptions, PlanCompiler, type PlanDecision, type PrecompiledJoinDecision, type RedactionConfig, type RedactionPattern, type SchemaChange, type SchemaDiff, type SetOperationResult, type SimplifiedPlanReport, type StreamConfig, type UpdateConfig, type UpsertConfig, type WhereDispatcher, type WhereHandler, bm25Search, booleanSearch, boost, buildCloseCursor, buildDeclareCursor, buildExplain, buildExplainAnalyzeJson, buildExplainPlan, buildExplainVerbose, buildFetch, buildFetchAll, buildFetchFirst, buildFetchForward, buildFetchNext, buildOnConflictClause, buildStreamingStatements, camelCaseNaming, canGenerateCreateIndex, collectAndValidateParamRefs, compareSchemata, compileDelete, compileInsert, compileMutation, compilePlan, compileSetOperation, compileUpdate, compileUpsert, conditionalUpdate, cosineDistance, createAnyExpr, createEqualityExpr, createLeafCompileFn, createParamRef, createPgsqlAdapter, createPgsqlCompileOnlyAdapter, createTypeCastParamRef, defaultFkDerivation, ensureMigrationsTable, excludedRef, generateCreateIndex, generateCursorName, generateDDL, generateDownSQL, generateMigrationFile, generateMigrationSQL, generateSeries, getAppliedMigrations, getNamingPluginForDbCasing, getNextSchemaVersion, getRowEstimates, getTotalExecutionTime, identityNaming, innerProduct, introspect, isBatchValuesJoinDecision, isDestructiveDown, isJoinDecision, isMigrationApplied, isPrecompiledJoinDecision, isReservedKeyword, l2Distance, mapColumnType, mapOnDeleteAction, nextval, parse, parseExplainJson, parseMigrationFile, rawDistance, recordMigration, redactParams, removeMigrationRecord, resolveLogicalName, sanitizeForDisplay, score, validateIdentifier, validateIdentifiers, validateParamRef, validateQualifiedIdentifier, validateSqlExpression, vectorDims, withMigrationLock };
3263
+ export { ADD_CHECK_RULE_ID, ALTER_AUTHORITY_OBSERVATION, ALTER_COLUMN_SET_NOT_NULL_OPERATION_KIND, ALTER_TYPE_ADD_VALUE_OPERATION_KIND, ATTACH_LOGICAL_IDENTITY_OPERATION_KIND, type AddedEnumValue, type AlterColumnSetNotNullPayload, type AlterTypeAddValuePayload, type AttachLogicalIdentityPayload, type BatchValuesJoinDecision, COLUMN_EXISTS_OBSERVATION, CamelCaseNamingPlugin, type CanonicalizeCheckConstraintsOptions, type ChangeKind, CheckConstraintCanonicalizationError, type CheckConstraintCanonicalizationWarning, CheckConstraintNewEnumValueError, type ComparePgsqlDatabaseSchemaOptions, type CompareSchemataOptions, type CompiledResult, type CompilerContext, type CompilerOptions, type CompilerState, type ConflictAction, type ConflictTarget, type CursorHoldOption, type CursorOptions, type CursorScrollOption, DBSP_LOGICAL_IDENTITY_TABLE, DBSP_META_SCHEMA, DBSP_TRANSITION_JOURNAL_TABLE, DBSP_TRANSITION_RUN_TABLE, DEFAULT_PK_COLUMN, DEFAULT_REDACTION_PATTERNS, type Decision, type DeleteConfig, type DetectedHierarchy, type DiffSummary, ENGINE_VERSION_OBSERVATION, ENUM_ADD_VALUE_RULE_ID, ENUM_LABEL_VISIBLE_OBSERVATION, ENUM_TYPE_EXISTS_OBSERVATION, type EnumAddValueMatch, type EnumAddValueRuleOptions, type ExplainFormat, type ExplainOptions, type ExplainPlan, ExpressionCanonicalizationUnavailableError, type ExpressionHandler, type FetchDirection, type FetchOptions, type FkColumnDerivation, type GenerateDDLOptions, type IdentityAdoptionAsserter, IdentityNamingPlugin, type IncludeHandler, type IncludeResult, type IndexCapabilityContext, IndexFeatureUnsupportedError, type IndexRenderSpec, type InsertConfig, type IntrospectedModelIR, type IntrospectionOptions, InvalidIdentifierError, type JoinDecision, LOGICAL_IDENTITY_ADOPTION_RULE_ID, LOGICAL_IDENTITY_CARRIER_OBSERVATION, type LeafCompileFn, type LogicalIdentityAdoptionMatch, type LogicalIdentityAdoptionRuleOptions, MANUAL_SQL_OPERATION_KIND, type ManualSqlPayload, type MigrationRecord, type MigrationSQLOptions, NO_NULLS_GUARD, type NamingPlugin, NonConvergentSchemaDiffError, PG_INTROSPECTION_ARTIFACT, PG_OPERATION_PACK_ARTIFACT, PG_RULE_PACK_ARTIFACT, type ParamRefValidationResult, type ParsedMigrationFile, type PgTransitionPackOptions, PgsqlAdapter, type PgsqlAdapterOptions, type PgsqlBorrowedClientAdapterOptions, type PgsqlPoolAdapterOptions, PgsqlRawSqlTransactionControlError, PgsqlTransactionAbortedCommitError, PgsqlTransactionAbortedError, PlanCompiler, type PlanDecision, type PrecompiledJoinDecision, type RedactionConfig, type RedactionPattern, SET_NOT_NULL_RULE_ID, type SchemaChange, type SchemaDiff, type SchemaScopeOptions, type SetNotNullMatch, type SetNotNullRuleOptions, type SetOperationResult, type SimplifiedPlanReport, type StreamConfig, type UpdateConfig, type UpsertConfig, type WhereDispatcher, type WhereHandler, assertCreateIndexSupported, assertCreateIndexesSupported, assertNoRepeatedExpressionSurfaceDrift, bm25Search, booleanSearch, boost, buildCloseCursor, buildDeclareCursor, buildExplain, buildExplainAnalyzeJson, buildExplainPlan, buildExplainVerbose, buildFetch, buildFetchAll, buildFetchFirst, buildFetchForward, buildFetchNext, buildOnConflictClause, buildStreamingStatements, camelCaseNaming, canGenerateCreateIndex, canonicalizeCheckConstraints, collectAndValidateParamRefs, comparePgsqlDatabaseSchema, compareSchemata, compileDelete, compileInsert, compileMutation, compilePlan, compileSetOperation, compileUpdate, compileUpsert, conditionalUpdate, cosineDistance, createAlterColumnSetNotNullOperationRuntime, createAlterTypeAddValueOperationRuntime, createAnyExpr, createAttachLogicalIdentityOperationRuntime, createEnumAddValueRule, createEqualityExpr, createLeafCompileFn, createLogicalIdentityAdoptionRule, createManualSqlOperationRuntime, createParamRef, createPgObservationIssuer, createPgTransitionPack, createPgsqlAdapter, createPgsqlCompileOnlyAdapter, createSetNotNullRule, createTypeCastParamRef, defaultFkDerivation, derivePostgresqlCapabilitiesForVersion, ensureMigrationsTable, ensureTransitionJournal, excludedRef, generateCreateIndex, generateCursorName, generateDDL, generateDownSQL, generateMigrationFile, generateMigrationSQL, generateSeries, getAppliedMigrations, getNamingPluginForDbCasing, getNextSchemaVersion, getRowEstimates, getTotalExecutionTime, identityNaming, innerProduct, introspect, isBatchValuesJoinDecision, isDestructiveDown, isJoinDecision, isMigrationApplied, isPrecompiledJoinDecision, isReservedKeyword, l2Distance, mapColumnType, mapOnDeleteAction, nextval, normalizeManualSqlPayload, parse, parseExplainJson, parseMigrationFile, rawDistance, readPgObservationContext, readTransitionJournal, recordMigration, redactParams, removeMigrationRecord, renderAlterColumnSetNotNullSql, renderAlterTypeAddValueSql, renderAttachLogicalIdentityLockSql, renderCreateDbspMetaSchemaSql, renderCreateIndex, renderCreateLogicalIdentityIndexesSql, renderCreateLogicalIdentitySideTableSql, renderCreateTransitionJournalTableSql, renderCreateTransitionRunTableSql, renderInsertLogicalIdentitySql, renderNoNullsCheckSql, renderSetNotNullLockSql, resolveLogicalName, sanitizeForDisplay, score, validateIdentifier, validateIdentifiers, validateParamRef, validateQualifiedIdentifier, validateSqlExpression, vectorDims, withMigrationLock };