@prisma-next/adapter-postgres 0.15.0-dev.13 → 0.15.0-dev.2

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.
@@ -7,7 +7,7 @@ import {
7
7
  import type { SqlControlAdapter } from '@prisma-next/family-sql/control-adapter';
8
8
  import { parseContractMarkerRow } from '@prisma-next/family-sql/verify';
9
9
  import type { CodecLookup, CodecRegistry } from '@prisma-next/framework-components/codec';
10
- import { APP_SPACE_ID, type SchemaNodeRef } from '@prisma-next/framework-components/control';
10
+ import { APP_SPACE_ID } from '@prisma-next/framework-components/control';
11
11
  import { UNBOUND_NAMESPACE_ID } from '@prisma-next/framework-components/ir';
12
12
  import { ledgerOriginFromStored } from '@prisma-next/migration-tools/ledger-origin';
13
13
  import { REFERENTIAL_ACTION_SQL } from '@prisma-next/sql-contract/referential-action-sql';
@@ -36,7 +36,6 @@ import type {
36
36
  SqlReferentialAction,
37
37
  SqlUniqueIRInput,
38
38
  } from '@prisma-next/sql-schema-ir/types';
39
- import { RelationalSchemaNodeKind } from '@prisma-next/sql-schema-ir/types';
40
39
  import {
41
40
  buildControlTableBootstrapQueries,
42
41
  buildSignMarkerBootstrapQueries,
@@ -67,7 +66,6 @@ import {
67
66
  PostgresNativeEnumSchemaNode,
68
67
  PostgresPolicySchemaNode,
69
68
  PostgresRoleSchemaNode,
70
- PostgresSchemaNodeKind,
71
69
  PostgresTableSchemaNode,
72
70
  } from '@prisma-next/target-postgres/types';
73
71
  import { blindCast } from '@prisma-next/utils/casts';
@@ -739,13 +737,7 @@ export class PostgresControlAdapter implements SqlControlAdapter<'postgres'> {
739
737
  ORDER BY c.table_name, c.ordinal_position`,
740
738
  [schema],
741
739
  );
742
- // Query all primary keys for all tables in schema. Reads pg_catalog, not
743
- // information_schema: `information_schema.table_constraints` hides
744
- // constraints on tables where the connecting role's only privilege is
745
- // SELECT (its filter grants visibility for INSERT/UPDATE/DELETE/TRUNCATE/
746
- // REFERENCES/TRIGGER — not SELECT), so a SELECT-only table introspects
747
- // with all its columns but zero constraints and verify reports every
748
- // declared constraint as missing. pg_catalog is not privilege-filtered.
740
+ // Query all primary keys for all tables in schema
749
741
  const pkResult = await driver.query<{
750
742
  table_name: string;
751
743
  constraint_name: string;
@@ -753,29 +745,24 @@ export class PostgresControlAdapter implements SqlControlAdapter<'postgres'> {
753
745
  ordinal_position: number;
754
746
  }>(
755
747
  `SELECT
756
- cl.relname AS table_name,
757
- con.conname AS constraint_name,
758
- a.attname AS column_name,
759
- k.ord AS ordinal_position
760
- FROM pg_catalog.pg_constraint con
761
- JOIN pg_catalog.pg_class cl ON cl.oid = con.conrelid
762
- JOIN pg_catalog.pg_namespace ns ON ns.oid = cl.relnamespace
763
- JOIN LATERAL unnest(con.conkey) WITH ORDINALITY AS k(attnum, ord) ON true
764
- JOIN pg_catalog.pg_attribute a
765
- ON a.attrelid = con.conrelid
766
- AND a.attnum = k.attnum
767
- WHERE ns.nspname = $1
768
- AND con.contype = 'p'
769
- ORDER BY cl.relname, k.ord`,
748
+ tc.table_name,
749
+ tc.constraint_name,
750
+ kcu.column_name,
751
+ kcu.ordinal_position
752
+ FROM information_schema.table_constraints tc
753
+ JOIN information_schema.key_column_usage kcu
754
+ ON tc.constraint_name = kcu.constraint_name
755
+ AND tc.table_schema = kcu.table_schema
756
+ AND tc.table_name = kcu.table_name
757
+ WHERE tc.table_schema = $1
758
+ AND tc.constraint_type = 'PRIMARY KEY'
759
+ ORDER BY tc.table_name, kcu.ordinal_position`,
770
760
  [schema],
771
761
  );
772
- // Query all foreign keys for all tables in schema, including referential
773
- // actions. Reads pg_catalog only (see the primary-key query above for why
774
- // information_schema is unusable here); `unnest(conkey) WITH ORDINALITY`
775
- // pairs source and referenced columns positionally, so composite FKs
776
- // round-trip in declared order. The referential-action CASEs mirror
777
- // pg_constraint's confdeltype/confupdtype encoding and produce the same
778
- // rule strings information_schema.referential_constraints reports.
762
+ // Query all foreign keys for all tables in schema, including referential actions.
763
+ // Uses pg_catalog for correct positional pairing of composite FK columns
764
+ // (information_schema.constraint_column_usage lacks ordinal_position,
765
+ // which causes Cartesian products for multi-column FKs).
779
766
  const fkResult = await driver.query<{
780
767
  table_name: string;
781
768
  constraint_name: string;
@@ -788,48 +775,41 @@ export class PostgresControlAdapter implements SqlControlAdapter<'postgres'> {
788
775
  update_rule: string;
789
776
  }>(
790
777
  `SELECT
791
- cl.relname AS table_name,
792
- con.conname AS constraint_name,
793
- a.attname AS column_name,
794
- k.ord AS ordinal_position,
778
+ tc.table_name,
779
+ tc.constraint_name,
780
+ kcu.column_name,
781
+ kcu.ordinal_position,
795
782
  ref_ns.nspname AS referenced_table_schema,
796
783
  ref_cl.relname AS referenced_table_name,
797
784
  ref_att.attname AS referenced_column_name,
798
- CASE con.confdeltype
799
- WHEN 'a' THEN 'NO ACTION'
800
- WHEN 'r' THEN 'RESTRICT'
801
- WHEN 'c' THEN 'CASCADE'
802
- WHEN 'n' THEN 'SET NULL'
803
- WHEN 'd' THEN 'SET DEFAULT'
804
- END AS delete_rule,
805
- CASE con.confupdtype
806
- WHEN 'a' THEN 'NO ACTION'
807
- WHEN 'r' THEN 'RESTRICT'
808
- WHEN 'c' THEN 'CASCADE'
809
- WHEN 'n' THEN 'SET NULL'
810
- WHEN 'd' THEN 'SET DEFAULT'
811
- END AS update_rule
812
- FROM pg_catalog.pg_constraint con
813
- JOIN pg_catalog.pg_class cl ON cl.oid = con.conrelid
814
- JOIN pg_catalog.pg_namespace ns ON ns.oid = cl.relnamespace
815
- JOIN LATERAL unnest(con.conkey) WITH ORDINALITY AS k(attnum, ord) ON true
816
- JOIN pg_catalog.pg_attribute a
817
- ON a.attrelid = con.conrelid
818
- AND a.attnum = k.attnum
785
+ rc.delete_rule,
786
+ rc.update_rule
787
+ FROM information_schema.table_constraints tc
788
+ JOIN information_schema.key_column_usage kcu
789
+ ON tc.constraint_name = kcu.constraint_name
790
+ AND tc.table_schema = kcu.table_schema
791
+ AND tc.table_name = kcu.table_name
792
+ JOIN pg_catalog.pg_constraint pgc
793
+ ON pgc.conname = tc.constraint_name
794
+ AND pgc.connamespace = (
795
+ SELECT oid FROM pg_catalog.pg_namespace WHERE nspname = tc.table_schema
796
+ )
819
797
  JOIN pg_catalog.pg_class ref_cl
820
- ON ref_cl.oid = con.confrelid
798
+ ON ref_cl.oid = pgc.confrelid
821
799
  JOIN pg_catalog.pg_namespace ref_ns
822
800
  ON ref_ns.oid = ref_cl.relnamespace
823
801
  JOIN pg_catalog.pg_attribute ref_att
824
- ON ref_att.attrelid = con.confrelid
825
- AND ref_att.attnum = con.confkey[k.ord]
826
- WHERE ns.nspname = $1
827
- AND con.contype = 'f'
828
- ORDER BY cl.relname, con.conname, k.ord`,
802
+ ON ref_att.attrelid = pgc.confrelid
803
+ AND ref_att.attnum = pgc.confkey[kcu.ordinal_position]
804
+ JOIN information_schema.referential_constraints rc
805
+ ON rc.constraint_name = tc.constraint_name
806
+ AND rc.constraint_schema = tc.table_schema
807
+ WHERE tc.table_schema = $1
808
+ AND tc.constraint_type = 'FOREIGN KEY'
809
+ ORDER BY tc.table_name, tc.constraint_name, kcu.ordinal_position`,
829
810
  [schema],
830
811
  );
831
- // Query all unique constraints for all tables in schema (excluding PKs).
832
- // Reads pg_catalog (see the primary-key query above).
812
+ // Query all unique constraints for all tables in schema (excluding PKs)
833
813
  const uniqueResult = await driver.query<{
834
814
  table_name: string;
835
815
  constraint_name: string;
@@ -837,20 +817,18 @@ export class PostgresControlAdapter implements SqlControlAdapter<'postgres'> {
837
817
  ordinal_position: number;
838
818
  }>(
839
819
  `SELECT
840
- cl.relname AS table_name,
841
- con.conname AS constraint_name,
842
- a.attname AS column_name,
843
- k.ord AS ordinal_position
844
- FROM pg_catalog.pg_constraint con
845
- JOIN pg_catalog.pg_class cl ON cl.oid = con.conrelid
846
- JOIN pg_catalog.pg_namespace ns ON ns.oid = cl.relnamespace
847
- JOIN LATERAL unnest(con.conkey) WITH ORDINALITY AS k(attnum, ord) ON true
848
- JOIN pg_catalog.pg_attribute a
849
- ON a.attrelid = con.conrelid
850
- AND a.attnum = k.attnum
851
- WHERE ns.nspname = $1
852
- AND con.contype = 'u'
853
- ORDER BY cl.relname, con.conname, k.ord`,
820
+ tc.table_name,
821
+ tc.constraint_name,
822
+ kcu.column_name,
823
+ kcu.ordinal_position
824
+ FROM information_schema.table_constraints tc
825
+ JOIN information_schema.key_column_usage kcu
826
+ ON tc.constraint_name = kcu.constraint_name
827
+ AND tc.table_schema = kcu.table_schema
828
+ AND tc.table_name = kcu.table_name
829
+ WHERE tc.table_schema = $1
830
+ AND tc.constraint_type = 'UNIQUE'
831
+ ORDER BY tc.table_name, tc.constraint_name, kcu.ordinal_position`,
854
832
  [schema],
855
833
  );
856
834
  // Query all indexes for all tables in schema (excluding constraints).
@@ -895,9 +873,10 @@ export class PostgresControlAdapter implements SqlControlAdapter<'postgres'> {
895
873
  WHERE i.schemaname = $1
896
874
  AND NOT EXISTS (
897
875
  SELECT 1
898
- FROM pg_catalog.pg_constraint con
899
- WHERE con.conindid = ic.oid
900
- AND con.contype IN ('p', 'u', 'x')
876
+ FROM information_schema.table_constraints tc
877
+ WHERE tc.table_schema = $1
878
+ AND tc.table_name = i.tablename
879
+ AND tc.constraint_name = i.indexname
901
880
  )
902
881
  ORDER BY i.tablename, i.indexname, k.ord`,
903
882
  [schema],
@@ -1033,7 +1012,6 @@ export class PostgresControlAdapter implements SqlControlAdapter<'postgres'> {
1033
1012
  ? {
1034
1013
  columns: primaryKeyColumns,
1035
1014
  ...(pkRows[0]?.constraint_name ? { name: pkRows[0].constraint_name } : {}),
1036
- dependsOn: postgresColumnDependsOn(schema, tableName, primaryKeyColumns),
1037
1015
  }
1038
1016
  : undefined;
1039
1017
 
@@ -1076,10 +1054,6 @@ export class PostgresControlAdapter implements SqlControlAdapter<'postgres'> {
1076
1054
  name: fk.name,
1077
1055
  ...ifDefined('onDelete', mapReferentialAction(fk.deleteRule)),
1078
1056
  ...ifDefined('onUpdate', mapReferentialAction(fk.updateRule)),
1079
- dependsOn: [
1080
- postgresTableDependsOn(fk.referencedSchema, fk.referencedTable),
1081
- ...postgresColumnDependsOn(schema, tableName, fk.columns),
1082
- ],
1083
1057
  }),
1084
1058
  );
1085
1059
 
@@ -1104,7 +1078,6 @@ export class PostgresControlAdapter implements SqlControlAdapter<'postgres'> {
1104
1078
  const uniques: readonly SqlUniqueIRInput[] = Array.from(uniquesMap.values()).map((uq) => ({
1105
1079
  columns: Object.freeze([...uq.columns]) as readonly string[],
1106
1080
  name: uq.name,
1107
- dependsOn: postgresColumnDependsOn(schema, tableName, uq.columns),
1108
1081
  }));
1109
1082
 
1110
1083
  // Process indexes
@@ -1186,7 +1159,6 @@ export class PostgresControlAdapter implements SqlControlAdapter<'postgres'> {
1186
1159
  unique: idx.unique,
1187
1160
  ...(idx.type !== undefined && { type: idx.type }),
1188
1161
  ...(idx.options !== undefined && { options: idx.options }),
1189
- dependsOn: postgresColumnDependsOn(schema, tableName, idx.columns),
1190
1162
  }),
1191
1163
  );
1192
1164
 
@@ -1269,10 +1241,6 @@ export class PostgresControlAdapter implements SqlControlAdapter<'postgres'> {
1269
1241
  ...(row.qual !== null ? { using: row.qual } : {}),
1270
1242
  ...(row.with_check !== null ? { withCheck: row.with_check } : {}),
1271
1243
  permissive,
1272
- dependsOn: [
1273
- postgresTableDependsOn(row.schemaname, row.tablename),
1274
- ...policyRoles.map(postgresRoleDependsOn),
1275
- ],
1276
1244
  });
1277
1245
  const list = policiesByTable.get(row.tablename) ?? [];
1278
1246
  list.push(policy);
@@ -1534,44 +1502,6 @@ function mapReferentialAction(rule: string): SqlReferentialAction | undefined {
1534
1502
  return mapped;
1535
1503
  }
1536
1504
 
1537
- /**
1538
- * A FK/policy dependency chain, mirroring the shape the expected-side
1539
- * derivation stamps (`contractToPostgresDatabaseSchemaNode`): the database
1540
- * root's fixed sentinel id, then the namespace, then the table.
1541
- */
1542
- function postgresTableDependsOn(namespaceId: string, tableName: string): SchemaNodeRef {
1543
- return [
1544
- { nodeKind: PostgresSchemaNodeKind.database, id: 'database' },
1545
- { nodeKind: PostgresSchemaNodeKind.namespace, id: namespaceId },
1546
- { nodeKind: PostgresSchemaNodeKind.table, id: tableName },
1547
- ];
1548
- }
1549
-
1550
- /** A policy's dependency chain onto one of the roles it grants to. */
1551
- function postgresRoleDependsOn(role: string): SchemaNodeRef {
1552
- return [
1553
- { nodeKind: PostgresSchemaNodeKind.database, id: 'database' },
1554
- { nodeKind: PostgresSchemaNodeKind.role, id: role },
1555
- ];
1556
- }
1557
-
1558
- /**
1559
- * The chains from a table-child object (foreign key, index, unique, primary
1560
- * key) to each of the own columns it is built on — the introspection-side
1561
- * mirror of `contractToPostgresDatabaseSchemaNode`'s `columnDependsOn`. An
1562
- * object is dropped before the columns it covers.
1563
- */
1564
- function postgresColumnDependsOn(
1565
- namespaceId: string,
1566
- tableName: string,
1567
- columns: readonly string[],
1568
- ): SchemaNodeRef[] {
1569
- return columns.map((column) => [
1570
- ...postgresTableDependsOn(namespaceId, tableName),
1571
- { nodeKind: RelationalSchemaNodeKind.column, id: `column:${column}` },
1572
- ]);
1573
- }
1574
-
1575
1505
  /**
1576
1506
  * Groups an array of objects by a specified key.
1577
1507
  * Returns a Map for O(1) lookup by group key.