@prisma-next/adapter-postgres 0.14.0 → 0.15.0-dev.1
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/{adapter-CwkcdpM_.mjs → adapter-CssyjkaR.mjs} +4 -3
- package/dist/adapter-CssyjkaR.mjs.map +1 -0
- package/dist/adapter.d.mts +1 -1
- package/dist/adapter.d.mts.map +1 -1
- package/dist/adapter.mjs +1 -1
- package/dist/{control-adapter-Dspz5uKp.mjs → control-adapter-w2BFxQ--.mjs} +312 -63
- package/dist/control-adapter-w2BFxQ--.mjs.map +1 -0
- package/dist/control.d.mts +23 -12
- package/dist/control.d.mts.map +1 -1
- package/dist/control.mjs +46 -107
- package/dist/control.mjs.map +1 -1
- package/dist/{descriptor-meta-DOgMfoqm.mjs → descriptor-meta-jMtx881n.mjs} +12 -4
- package/dist/descriptor-meta-jMtx881n.mjs.map +1 -0
- package/dist/runtime.d.mts +1 -1
- package/dist/runtime.mjs +2 -2
- package/dist/runtime.mjs.map +1 -1
- package/dist/{types-KXRwRZU8.d.mts → types-DkGeLfUp.d.mts} +3 -6
- package/dist/types-DkGeLfUp.d.mts.map +1 -0
- package/dist/types.d.mts +1 -1
- package/package.json +26 -25
- package/src/core/adapter.ts +1 -0
- package/src/core/codec-lookup.ts +2 -1
- package/src/core/control-adapter.ts +481 -92
- package/src/core/control-mutation-defaults.ts +61 -190
- package/src/core/descriptor-meta.ts +4 -0
- package/src/core/marker-ledger.ts +15 -0
- package/src/core/sql-renderer.ts +32 -6
- package/src/core/types.ts +2 -3
- package/src/exports/runtime.ts +2 -5
- package/dist/adapter-CwkcdpM_.mjs.map +0 -1
- package/dist/control-adapter-Dspz5uKp.mjs.map +0 -1
- package/dist/descriptor-meta-DOgMfoqm.mjs.map +0 -1
- package/dist/types-KXRwRZU8.d.mts.map +0 -1
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { n as renderLoweredSql, r as createPostgresBuiltinCodecLookup, t as PostgresControlAdapter } from "./control-adapter-
|
|
1
|
+
import { n as renderLoweredSql, r as createPostgresBuiltinCodecLookup, t as PostgresControlAdapter } from "./control-adapter-w2BFxQ--.mjs";
|
|
2
2
|
import { APP_SPACE_ID } from "@prisma-next/framework-components/control";
|
|
3
3
|
import { isDdlNode } from "@prisma-next/sql-relational-core/ast";
|
|
4
4
|
//#region src/core/adapter.ts
|
|
@@ -15,7 +15,8 @@ const defaultCapabilities = Object.freeze({
|
|
|
15
15
|
enums: true,
|
|
16
16
|
returning: true,
|
|
17
17
|
defaultInInsert: true,
|
|
18
|
-
lateral: true
|
|
18
|
+
lateral: true,
|
|
19
|
+
scalarList: true
|
|
19
20
|
}
|
|
20
21
|
});
|
|
21
22
|
var PostgresAdapterImpl = class {
|
|
@@ -62,4 +63,4 @@ function createPostgresAdapter(options) {
|
|
|
62
63
|
//#endregion
|
|
63
64
|
export { postgresRawCodecInferer as n, createPostgresAdapter as t };
|
|
64
65
|
|
|
65
|
-
//# sourceMappingURL=adapter-
|
|
66
|
+
//# sourceMappingURL=adapter-CssyjkaR.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"adapter-CssyjkaR.mjs","names":[],"sources":["../src/core/adapter.ts"],"sourcesContent":["import type { CodecRegistry } from '@prisma-next/framework-components/codec';\nimport { APP_SPACE_ID } from '@prisma-next/framework-components/control';\nimport type {\n Adapter,\n AdapterProfile,\n AnyQueryAst,\n LowererContext,\n RawSqlLiteral,\n SqlQueryable,\n} from '@prisma-next/sql-relational-core/ast';\nimport { isDdlNode } from '@prisma-next/sql-relational-core/ast';\nimport type { RawCodecInferer } from '@prisma-next/sql-relational-core/expression';\nimport type { PostgresDdlNode } from '@prisma-next/target-postgres/ddl';\nimport { createPostgresBuiltinCodecLookup } from './codec-lookup';\nimport { PostgresControlAdapter } from './control-adapter';\nimport { renderLoweredSql } from './sql-renderer';\nimport type { PostgresAdapterOptions, PostgresContract, PostgresLoweredStatement } from './types';\n\nconst defaultCapabilities = Object.freeze({\n postgres: {\n orderBy: true,\n limit: true,\n lateral: true,\n jsonAgg: true,\n returning: true,\n distinctOn: true,\n },\n sql: {\n enums: true,\n returning: true,\n defaultInInsert: true,\n lateral: true,\n scalarList: true,\n },\n});\n\nclass PostgresAdapterImpl\n implements Adapter<AnyQueryAst, PostgresContract, PostgresLoweredStatement>\n{\n // These fields make the adapter instance structurally compatible with RuntimeAdapterInstance<'sql', 'postgres'> without introducing a runtime-plane dependency.\n readonly familyId = 'sql' as const;\n readonly targetId = 'postgres' as const;\n\n readonly profile: AdapterProfile<'postgres'>;\n private readonly codecLookup: CodecRegistry;\n\n constructor(options?: PostgresAdapterOptions) {\n this.codecLookup = options?.codecLookup ?? createPostgresBuiltinCodecLookup();\n const controlAdapter = new PostgresControlAdapter(this.codecLookup);\n this.profile = Object.freeze({\n id: options?.profileId ?? 'postgres/default@1',\n target: 'postgres',\n capabilities: defaultCapabilities,\n readMarker: (queryable: SqlQueryable) =>\n controlAdapter.readMarkerDiscriminated(\n {\n familyId: 'sql',\n targetId: 'postgres',\n query: async <Row = Record<string, unknown>>(\n sql: string,\n params?: readonly unknown[],\n ) => {\n const result = await queryable.query<Row>(sql, params);\n return { rows: [...result.rows] };\n },\n close: async () => {},\n },\n APP_SPACE_ID,\n ),\n });\n }\n\n lower(\n ast: AnyQueryAst | PostgresDdlNode,\n context: LowererContext<PostgresContract>,\n ): PostgresLoweredStatement {\n if (isDdlNode(ast)) {\n throw new Error(\n 'lower() does not lower DDL on the runtime adapter — DDL lowering is a control-plane concern handled by the control adapter.',\n );\n }\n return renderLoweredSql(ast, context.contract, this.codecLookup);\n }\n}\n\n/** Codec-id lookup for bare-literal interpolations used by `fns.raw` on a postgres client. Contributed as the descriptor's static `rawCodecInferer` slot. */\nexport const postgresRawCodecInferer: RawCodecInferer = {\n inferCodec(value: RawSqlLiteral): string {\n switch (typeof value) {\n case 'number':\n return Number.isSafeInteger(value) && value % 1 === 0 ? 'pg/int4' : 'pg/float8';\n case 'bigint':\n return 'pg/int8';\n case 'string':\n return 'pg/text';\n case 'boolean':\n return 'pg/bool';\n case 'object':\n if (value instanceof Uint8Array) return 'pg/bytea';\n }\n throw new Error(\n 'unsupported JS value type for raw-SQL interpolation: wrap this value in `param(...)` with an explicit codec',\n );\n },\n};\n\nexport function createPostgresAdapter(options?: PostgresAdapterOptions) {\n return Object.freeze(new PostgresAdapterImpl(options));\n}\n"],"mappings":";;;;AAkBA,MAAM,sBAAsB,OAAO,OAAO;CACxC,UAAU;EACR,SAAS;EACT,OAAO;EACP,SAAS;EACT,SAAS;EACT,WAAW;EACX,YAAY;CACd;CACA,KAAK;EACH,OAAO;EACP,WAAW;EACX,iBAAiB;EACjB,SAAS;EACT,YAAY;CACd;AACF,CAAC;AAED,IAAM,sBAAN,MAEA;CAEE,WAAoB;CACpB,WAAoB;CAEpB;CACA;CAEA,YAAY,SAAkC;EAC5C,KAAK,cAAc,SAAS,eAAe,iCAAiC;EAC5E,MAAM,iBAAiB,IAAI,uBAAuB,KAAK,WAAW;EAClE,KAAK,UAAU,OAAO,OAAO;GAC3B,IAAI,SAAS,aAAa;GAC1B,QAAQ;GACR,cAAc;GACd,aAAa,cACX,eAAe,wBACb;IACE,UAAU;IACV,UAAU;IACV,OAAO,OACL,KACA,WACG;KAEH,OAAO,EAAE,MAAM,CAAC,IAAG,MADE,UAAU,MAAW,KAAK,MAAM,EAAA,CAC3B,IAAI,EAAE;IAClC;IACA,OAAO,YAAY,CAAC;GACtB,GACA,YACF;EACJ,CAAC;CACH;CAEA,MACE,KACA,SAC0B;EAC1B,IAAI,UAAU,GAAG,GACf,MAAM,IAAI,MACR,6HACF;EAEF,OAAO,iBAAiB,KAAK,QAAQ,UAAU,KAAK,WAAW;CACjE;AACF;;AAGA,MAAa,0BAA2C,EACtD,WAAW,OAA8B;CACvC,QAAQ,OAAO,OAAf;EACE,KAAK,UACH,OAAO,OAAO,cAAc,KAAK,KAAK,QAAQ,MAAM,IAAI,YAAY;EACtE,KAAK,UACH,OAAO;EACT,KAAK,UACH,OAAO;EACT,KAAK,WACH,OAAO;EACT,KAAK,UACH,IAAI,iBAAiB,YAAY,OAAO;CAC5C;CACA,MAAM,IAAI,MACR,6GACF;AACF,EACF;AAEA,SAAgB,sBAAsB,SAAkC;CACtE,OAAO,OAAO,OAAO,IAAI,oBAAoB,OAAO,CAAC;AACvD"}
|
package/dist/adapter.d.mts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { c as PostgresContract, l as PostgresLoweredStatement, s as PostgresAdapterOptions } from "./types-
|
|
1
|
+
import { c as PostgresContract, l as PostgresLoweredStatement, s as PostgresAdapterOptions } from "./types-DkGeLfUp.mjs";
|
|
2
2
|
import { Adapter, AdapterProfile, AnyQueryAst, LowererContext } from "@prisma-next/sql-relational-core/ast";
|
|
3
3
|
import { RawCodecInferer } from "@prisma-next/sql-relational-core/expression";
|
|
4
4
|
import { PostgresDdlNode } from "@prisma-next/target-postgres/ddl";
|
package/dist/adapter.d.mts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"adapter.d.mts","names":[],"sources":["../src/core/adapter.ts"],"mappings":";;;;;;
|
|
1
|
+
{"version":3,"file":"adapter.d.mts","names":[],"sources":["../src/core/adapter.ts"],"mappings":";;;;;;cAoCM,mBAAA,YACO,OAAA,CAAQ,WAAA,EAAa,gBAAA,EAAkB,wBAAA;EAAA,SAGzC,QAAA;EAAA,SACA,QAAA;EAAA,SAEA,OAAA,EAAS,cAAA;EAAA,iBACD,WAAA;cAEL,OAAA,GAAU,sBAAA;EA0BtB,KAAA,CACE,GAAA,EAAK,WAAA,GAAc,eAAA,EACnB,OAAA,EAAS,cAAA,CAAe,gBAAA,IACvB,wBAAA;AAAA;;cAWQ,uBAAA,EAAyB,eAkBrC;AAAA,iBAEe,qBAAA,CAAsB,OAAA,GAAU,sBAAA,GAAsB,QAAA,CAAA,mBAAA"}
|
package/dist/adapter.mjs
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { n as postgresRawCodecInferer, t as createPostgresAdapter } from "./adapter-
|
|
1
|
+
import { n as postgresRawCodecInferer, t as createPostgresAdapter } from "./adapter-CssyjkaR.mjs";
|
|
2
2
|
export { createPostgresAdapter, postgresRawCodecInferer };
|
|
@@ -8,7 +8,9 @@ import { REFERENTIAL_ACTION_SQL } from "@prisma-next/sql-contract/referential-ac
|
|
|
8
8
|
import { buildControlTableBootstrapQueries, buildSignMarkerBootstrapQueries, int4, int8, jsonb, pgTable, text, textArray, timestamptz } from "@prisma-next/target-postgres/contract-free";
|
|
9
9
|
import { parsePostgresDefault } from "@prisma-next/target-postgres/default-normalizer";
|
|
10
10
|
import { normalizeSchemaNativeType } from "@prisma-next/target-postgres/native-type-normalizer";
|
|
11
|
+
import { parseRlsPolicyWireName } from "@prisma-next/target-postgres/rls-canonicalize";
|
|
11
12
|
import { escapeLiteral, quoteIdentifier } from "@prisma-next/target-postgres/sql-utils";
|
|
13
|
+
import { PostgresDatabaseSchemaNode, PostgresNamespaceSchemaNode, PostgresNativeEnumSchemaNode, PostgresPolicySchemaNode, PostgresRoleSchemaNode, PostgresTableSchemaNode } from "@prisma-next/target-postgres/types";
|
|
12
14
|
import { blindCast } from "@prisma-next/utils/casts";
|
|
13
15
|
import { ifDefined } from "@prisma-next/utils/defined";
|
|
14
16
|
import { createAstCodecRegistry, deriveParamMetadata, encodeParamsWithMetadata } from "@prisma-next/sql-runtime";
|
|
@@ -76,6 +78,20 @@ const ledger = pgTable({
|
|
|
76
78
|
operations: jsonb()
|
|
77
79
|
});
|
|
78
80
|
/**
|
|
81
|
+
* Content-addressed contract store: one row per distinct contract, keyed
|
|
82
|
+
* by its storage hash. The ledger's `origin_core_hash` /
|
|
83
|
+
* `destination_core_hash` resolve here by hash equality, so both
|
|
84
|
+
* endpoints of every edge are direct lookups and a contract revisited by
|
|
85
|
+
* a rollback cycle is stored exactly once (upsert DO NOTHING).
|
|
86
|
+
*/
|
|
87
|
+
const ledgerContract = pgTable({
|
|
88
|
+
name: "contract",
|
|
89
|
+
schema: "prisma_contract"
|
|
90
|
+
}, {
|
|
91
|
+
core_hash: text(),
|
|
92
|
+
contract_json: jsonb()
|
|
93
|
+
});
|
|
94
|
+
/**
|
|
79
95
|
* Read-side handle covering every column of `prisma_contract.ledger`,
|
|
80
96
|
* including the DB-generated `id` (for ORDER BY) and `created_at`.
|
|
81
97
|
*/
|
|
@@ -107,7 +123,7 @@ const NOW = new RawExpr({
|
|
|
107
123
|
}
|
|
108
124
|
});
|
|
109
125
|
function mergeInvariants(current, incoming) {
|
|
110
|
-
return [
|
|
126
|
+
return [.../* @__PURE__ */ new Set([...current, ...incoming])].sort();
|
|
111
127
|
}
|
|
112
128
|
async function execute(lower, driver, query) {
|
|
113
129
|
const lowered = lower(query);
|
|
@@ -123,7 +139,7 @@ async function execute(lower, driver, query) {
|
|
|
123
139
|
*
|
|
124
140
|
* Spellings match the on-disk `meta.db.sql.postgres.nativeType` values in `@prisma-next/target-postgres`'s codec definitions, not the `udt_name` abbreviations that ADR 205 used as illustrative shorthand. The lookup-based cast policy compares against these strings directly.
|
|
125
141
|
*/
|
|
126
|
-
const POSTGRES_INFERRABLE_NATIVE_TYPES = new Set([
|
|
142
|
+
const POSTGRES_INFERRABLE_NATIVE_TYPES = /* @__PURE__ */ new Set([
|
|
127
143
|
"integer",
|
|
128
144
|
"smallint",
|
|
129
145
|
"bigint",
|
|
@@ -143,15 +159,19 @@ const POSTGRES_INFERRABLE_NATIVE_TYPES = new Set([
|
|
|
143
159
|
"bit",
|
|
144
160
|
"bit varying"
|
|
145
161
|
]);
|
|
146
|
-
function renderTypedParam(index, codecId, codecLookup) {
|
|
162
|
+
function renderTypedParam(index, codecId, codecLookup, many, typeParams) {
|
|
147
163
|
if (codecId === void 0) return `$${index}`;
|
|
148
|
-
const meta = codecLookup.metaFor(codecId);
|
|
164
|
+
const meta = codecLookup.metaFor(codecId, typeParams);
|
|
149
165
|
if (!(codecLookup.get(codecId) !== void 0 || meta !== void 0 || codecLookup.targetTypesFor(codecId) !== void 0)) throw new Error(`Postgres lowering: ParamRef carries codecId "${codecId}" but the assembled codec lookup has no entry for it. This usually indicates a missing extension pack in the runtime stack — register the pack that contributes this codec (e.g. \`extensionPacks: [pgvectorRuntime]\`), or use the codec directly from \`@prisma-next/target-postgres/codecs\` if it's a builtin.`);
|
|
150
166
|
const dbRecord = meta?.db;
|
|
151
167
|
const sqlBlock = isRecord(dbRecord) ? dbRecord["sql"] : void 0;
|
|
152
168
|
const dialectBlock = isRecord(sqlBlock) ? sqlBlock["postgres"] : void 0;
|
|
153
169
|
const nativeType = isRecord(dialectBlock) ? dialectBlock["nativeType"] : void 0;
|
|
154
|
-
if (typeof nativeType === "string"
|
|
170
|
+
if (typeof nativeType === "string") {
|
|
171
|
+
const arraySuffix = many ? "[]" : "";
|
|
172
|
+
if (!POSTGRES_INFERRABLE_NATIVE_TYPES.has(nativeType)) return `$${index}::${nativeType}${arraySuffix}`;
|
|
173
|
+
if (many) return `$${index}::${nativeType}${arraySuffix}`;
|
|
174
|
+
}
|
|
155
175
|
return `$${index}`;
|
|
156
176
|
}
|
|
157
177
|
function isRecord(value) {
|
|
@@ -497,12 +517,12 @@ function renderExpr(expr, contract, pim) {
|
|
|
497
517
|
function renderParamRef(ref, pim) {
|
|
498
518
|
const index = pim.indexMap.get(ref);
|
|
499
519
|
if (index === void 0) throw new Error("ParamRef not found in index map");
|
|
500
|
-
if (ref.kind === "prepared-param-ref") return renderTypedParam(index, ref.codec.codecId, pim.codecLookup);
|
|
520
|
+
if (ref.kind === "prepared-param-ref") return renderTypedParam(index, ref.codec.codecId, pim.codecLookup, ref.codec.many, ref.codec.typeParams);
|
|
501
521
|
if (ref.codec === void 0) throw runtimeError("RUNTIME.PARAM_REF_MISSING_CODEC", "Postgres renderer: ParamRef reached lowering without a bound CodecRef. Every column-bound ParamRef must carry a codec under the AST-bound codec contract. This usually indicates a builder path that constructed a ParamRef without threading the column codec.", {
|
|
502
522
|
paramIndex: index,
|
|
503
523
|
...ifDefined("name", ref.name)
|
|
504
524
|
});
|
|
505
|
-
return renderTypedParam(index, ref.codec.codecId, pim.codecLookup);
|
|
525
|
+
return renderTypedParam(index, ref.codec.codecId, pim.codecLookup, ref.codec.many, ref.codec.typeParams);
|
|
506
526
|
}
|
|
507
527
|
function renderLiteral(expr) {
|
|
508
528
|
if (typeof expr.value === "string") return `'${escapeLiteral(expr.value)}'`;
|
|
@@ -824,11 +844,20 @@ var PostgresControlAdapter = class {
|
|
|
824
844
|
}).where(marker.space.eq(space).and(marker.core_hash.eq(expectedFrom))).returning(marker.space).build())).length > 0;
|
|
825
845
|
}
|
|
826
846
|
/**
|
|
827
|
-
* Appends a ledger entry for `space`.
|
|
847
|
+
* Appends a ledger entry for `space`. When the edge carries a
|
|
848
|
+
* destination contract snapshot, the content-addressed
|
|
849
|
+
* `prisma_contract.contract` store is populated first (keyed by the
|
|
850
|
+
* destination hash, DO NOTHING on revisit) so a reader never sees a
|
|
851
|
+
* ledger row whose stored destination contract is missing. See the
|
|
828
852
|
* `SqlControlAdapter.writeLedgerEntry` contract.
|
|
829
853
|
*/
|
|
830
854
|
async writeLedgerEntry(driver, space, entry) {
|
|
831
|
-
|
|
855
|
+
const lower = (query) => this.lower(query, { contract: void 0 });
|
|
856
|
+
if (entry.destinationContractJson !== void 0) await execute(lower, driver, ledgerContract.upsert({
|
|
857
|
+
core_hash: entry.to,
|
|
858
|
+
contract_json: entry.destinationContractJson
|
|
859
|
+
}).onConflict(ledgerContract.core_hash).doNothing().build());
|
|
860
|
+
await execute(lower, driver, ledger.insert({
|
|
832
861
|
space,
|
|
833
862
|
migration_name: entry.migrationName,
|
|
834
863
|
migration_hash: entry.migrationHash,
|
|
@@ -887,20 +916,34 @@ var PostgresControlAdapter = class {
|
|
|
887
916
|
*/
|
|
888
917
|
async introspect(driver, contract, schema = "public") {
|
|
889
918
|
const declaredNamespaces = extractContractNamespaceIds(contract);
|
|
890
|
-
const
|
|
891
|
-
const
|
|
892
|
-
|
|
893
|
-
const
|
|
894
|
-
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
|
|
902
|
-
|
|
903
|
-
};
|
|
919
|
+
const resolvedSchemas = declaredNamespaces.length > 0 ? await this.resolveNamespaceSchemas(driver, declaredNamespaces) : [schema];
|
|
920
|
+
const namespaces = {};
|
|
921
|
+
let pgVersion = "unknown";
|
|
922
|
+
for (const resolved of resolvedSchemas) {
|
|
923
|
+
const { namespace, pgVersion: version } = await this.introspectSchema(driver, resolved);
|
|
924
|
+
namespaces[resolved] = namespace;
|
|
925
|
+
pgVersion = version;
|
|
926
|
+
}
|
|
927
|
+
return new PostgresDatabaseSchemaNode({
|
|
928
|
+
namespaces,
|
|
929
|
+
roles: await this.introspectRoles(driver),
|
|
930
|
+
existingSchemas: await this.listExistingSchemas(driver),
|
|
931
|
+
pgVersion
|
|
932
|
+
});
|
|
933
|
+
}
|
|
934
|
+
/**
|
|
935
|
+
* Reads cluster-scoped database roles. Roles are not schema-qualified, so
|
|
936
|
+
* this is queried once for the whole database rather than per namespace.
|
|
937
|
+
*/
|
|
938
|
+
async introspectRoles(driver) {
|
|
939
|
+
return (await driver.query(`SELECT rolname
|
|
940
|
+
FROM pg_catalog.pg_roles
|
|
941
|
+
WHERE rolname NOT LIKE 'pg_%'
|
|
942
|
+
AND rolname != 'postgres'
|
|
943
|
+
ORDER BY rolname`)).rows.map((row) => new PostgresRoleSchemaNode({
|
|
944
|
+
name: row.rolname,
|
|
945
|
+
namespaceId: UNBOUND_NAMESPACE_ID
|
|
946
|
+
}));
|
|
904
947
|
}
|
|
905
948
|
/**
|
|
906
949
|
* Lists every non-system schema present in the connected database.
|
|
@@ -919,36 +962,24 @@ var PostgresControlAdapter = class {
|
|
|
919
962
|
ORDER BY nspname`)).rows.map((row) => row.nspname);
|
|
920
963
|
}
|
|
921
964
|
/**
|
|
922
|
-
*
|
|
923
|
-
* the connection's `current_schema()
|
|
924
|
-
*
|
|
925
|
-
*
|
|
926
|
-
*
|
|
965
|
+
* Resolves the declared namespace ids to their live DDL schema names,
|
|
966
|
+
* mapping `UNBOUND_NAMESPACE_ID` to the connection's `current_schema()`
|
|
967
|
+
* and de-duplicating. The caller introspects one namespace node per
|
|
968
|
+
* resolved schema — there is no flat cross-schema merge, so two schemas
|
|
969
|
+
* holding a same-named table no longer collide.
|
|
927
970
|
*/
|
|
928
|
-
async
|
|
971
|
+
async resolveNamespaceSchemas(driver, namespaceIds) {
|
|
929
972
|
const resolvedSchemas = [];
|
|
930
973
|
for (const id of namespaceIds) if (id === UNBOUND_NAMESPACE_ID) {
|
|
931
974
|
const { rows } = await driver.query("SELECT current_schema() AS current_schema");
|
|
932
975
|
resolvedSchemas.push(rows[0]?.current_schema ?? "public");
|
|
933
976
|
} else resolvedSchemas.push(id);
|
|
934
|
-
|
|
935
|
-
const perSchema = [];
|
|
936
|
-
for (const schema of uniqueSchemas) perSchema.push(await this.introspectSchema(driver, schema));
|
|
937
|
-
const mergedTables = {};
|
|
938
|
-
for (const ir of perSchema) for (const [tableName, table] of Object.entries(ir.tables)) mergedTables[tableName] = table;
|
|
939
|
-
const firstAnnotations = perSchema[0]?.annotations;
|
|
940
|
-
const firstPg = blindCast(firstAnnotations?.["pg"]) ?? {};
|
|
941
|
-
return {
|
|
942
|
-
tables: mergedTables,
|
|
943
|
-
...ifDefined("annotations", {
|
|
944
|
-
...firstAnnotations,
|
|
945
|
-
pg: { ...firstPg }
|
|
946
|
-
})
|
|
947
|
-
};
|
|
977
|
+
return Array.from(new Set(resolvedSchemas));
|
|
948
978
|
}
|
|
949
979
|
/**
|
|
950
|
-
* Introspects a single Postgres schema and returns
|
|
951
|
-
*
|
|
980
|
+
* Introspects a single Postgres schema and returns the namespace node for
|
|
981
|
+
* that schema (its tables, their policies, and its native enum type names),
|
|
982
|
+
* alongside the cluster-scoped Postgres version. Used by `introspect` as
|
|
952
983
|
* the per-namespace walk.
|
|
953
984
|
*/
|
|
954
985
|
async introspectSchema(driver, schema) {
|
|
@@ -1091,7 +1122,7 @@ var PostgresControlAdapter = class {
|
|
|
1091
1122
|
}
|
|
1092
1123
|
constraints.add(row.constraint_name);
|
|
1093
1124
|
}
|
|
1094
|
-
const
|
|
1125
|
+
const tableInputs = {};
|
|
1095
1126
|
for (const tableRow of tablesResult.rows) {
|
|
1096
1127
|
const tableName = tableRow.table_name;
|
|
1097
1128
|
const columns = {};
|
|
@@ -1105,11 +1136,18 @@ var PostgresControlAdapter = class {
|
|
|
1105
1136
|
else if (colRow.numeric_precision) nativeType = `${colRow.data_type}(${colRow.numeric_precision})`;
|
|
1106
1137
|
else nativeType = colRow.data_type;
|
|
1107
1138
|
else nativeType = colRow.udt_name || colRow.data_type;
|
|
1139
|
+
const many = nativeType.endsWith("[]") ? true : void 0;
|
|
1140
|
+
if (many) nativeType = normalizeSchemaNativeType(nativeType.slice(0, -2));
|
|
1141
|
+
const resolvedNativeType = `${normalizeSchemaNativeType(nativeType)}${many ? "[]" : ""}`;
|
|
1142
|
+
const rawDefault = colRow.column_default ?? void 0;
|
|
1108
1143
|
columns[colRow.column_name] = {
|
|
1109
1144
|
name: colRow.column_name,
|
|
1110
1145
|
nativeType,
|
|
1111
1146
|
nullable: colRow.is_nullable === "YES",
|
|
1112
|
-
...ifDefined("default",
|
|
1147
|
+
...ifDefined("default", rawDefault),
|
|
1148
|
+
...ifDefined("many", many),
|
|
1149
|
+
resolvedNativeType,
|
|
1150
|
+
...ifDefined("resolvedDefault", rawDefault !== void 0 ? parsePostgresDefault(rawDefault, resolvedNativeType) : void 0)
|
|
1113
1151
|
};
|
|
1114
1152
|
}
|
|
1115
1153
|
const pkRows = [...pksByTable.get(tableName) ?? []];
|
|
@@ -1159,8 +1197,12 @@ var PostgresControlAdapter = class {
|
|
|
1159
1197
|
name: uq.name
|
|
1160
1198
|
}));
|
|
1161
1199
|
const indexesMap = /* @__PURE__ */ new Map();
|
|
1200
|
+
const indexNamesWithExpressionKey = /* @__PURE__ */ new Set();
|
|
1162
1201
|
for (const idxRow of indexesByTable.get(tableName) ?? []) {
|
|
1163
|
-
if (!idxRow.attname)
|
|
1202
|
+
if (!idxRow.attname) {
|
|
1203
|
+
indexNamesWithExpressionKey.add(idxRow.indexname);
|
|
1204
|
+
continue;
|
|
1205
|
+
}
|
|
1164
1206
|
const existing = indexesMap.get(idxRow.indexname);
|
|
1165
1207
|
if (existing) existing.columns.push(idxRow.attname);
|
|
1166
1208
|
else {
|
|
@@ -1175,7 +1217,14 @@ var PostgresControlAdapter = class {
|
|
|
1175
1217
|
});
|
|
1176
1218
|
}
|
|
1177
1219
|
}
|
|
1178
|
-
const
|
|
1220
|
+
const survivingIndexes = Array.from(indexesMap.values()).filter((idx) => !indexNamesWithExpressionKey.has(idx.name));
|
|
1221
|
+
const bestByColumnTuple = /* @__PURE__ */ new Map();
|
|
1222
|
+
for (const idx of survivingIndexes) {
|
|
1223
|
+
const tupleKey = idx.columns.join(",");
|
|
1224
|
+
const existing = bestByColumnTuple.get(tupleKey);
|
|
1225
|
+
if (!existing || idx.unique && !existing.unique || idx.unique === existing.unique && idx.name < existing.name) bestByColumnTuple.set(tupleKey, idx);
|
|
1226
|
+
}
|
|
1227
|
+
const indexes = Array.from(bestByColumnTuple.values()).map((idx) => ({
|
|
1179
1228
|
columns: Object.freeze([...idx.columns]),
|
|
1180
1229
|
name: idx.name,
|
|
1181
1230
|
unique: idx.unique,
|
|
@@ -1191,7 +1240,7 @@ var PostgresControlAdapter = class {
|
|
|
1191
1240
|
permittedValues: parsed.permittedValues
|
|
1192
1241
|
});
|
|
1193
1242
|
}
|
|
1194
|
-
|
|
1243
|
+
tableInputs[tableName] = {
|
|
1195
1244
|
name: tableName,
|
|
1196
1245
|
columns,
|
|
1197
1246
|
...ifDefined("primaryKey", primaryKey),
|
|
@@ -1201,19 +1250,63 @@ var PostgresControlAdapter = class {
|
|
|
1201
1250
|
...ifDefined("checks", checksForTable.length > 0 ? checksForTable : void 0)
|
|
1202
1251
|
};
|
|
1203
1252
|
}
|
|
1204
|
-
const
|
|
1253
|
+
const enums = (await driver.query(`SELECT t.typname, array_agg(e.enumlabel ORDER BY e.enumsortorder) AS enumvalues
|
|
1205
1254
|
FROM pg_catalog.pg_type t
|
|
1206
1255
|
JOIN pg_catalog.pg_namespace n ON n.oid = t.typnamespace
|
|
1256
|
+
JOIN pg_catalog.pg_enum e ON e.enumtypid = t.oid
|
|
1207
1257
|
WHERE t.typtype = 'e'
|
|
1208
1258
|
AND n.nspname = $1
|
|
1209
|
-
|
|
1259
|
+
GROUP BY t.typname
|
|
1260
|
+
ORDER BY t.typname`, [schema])).rows.map((r) => new PostgresNativeEnumSchemaNode({
|
|
1261
|
+
typeName: r.typname,
|
|
1262
|
+
namespaceId: schema,
|
|
1263
|
+
members: parsePgNameArray(r.enumvalues)
|
|
1264
|
+
}));
|
|
1265
|
+
const policiesResult = await driver.query(`SELECT schemaname, tablename, policyname, cmd, roles, qual, with_check, permissive
|
|
1266
|
+
FROM pg_catalog.pg_policies
|
|
1267
|
+
WHERE schemaname = $1
|
|
1268
|
+
ORDER BY tablename, policyname`, [schema]);
|
|
1269
|
+
const policiesByTable = /* @__PURE__ */ new Map();
|
|
1270
|
+
for (const row of policiesResult.rows) {
|
|
1271
|
+
const operation = mapPgCmd(row.cmd);
|
|
1272
|
+
const policyRoles = [...new Set(parsePgNameArray(row.roles).map((r) => r.toLowerCase()))].sort();
|
|
1273
|
+
const permissive = row.permissive.toUpperCase() === "PERMISSIVE";
|
|
1274
|
+
const prefix = parseRlsPolicyWireName(row.policyname)?.prefix ?? row.policyname;
|
|
1275
|
+
const policy = new PostgresPolicySchemaNode({
|
|
1276
|
+
name: row.policyname,
|
|
1277
|
+
prefix,
|
|
1278
|
+
tableName: row.tablename,
|
|
1279
|
+
namespaceId: row.schemaname,
|
|
1280
|
+
operation,
|
|
1281
|
+
roles: policyRoles,
|
|
1282
|
+
...row.qual !== null ? { using: row.qual } : {},
|
|
1283
|
+
...row.with_check !== null ? { withCheck: row.with_check } : {},
|
|
1284
|
+
permissive
|
|
1285
|
+
});
|
|
1286
|
+
const list = policiesByTable.get(row.tablename) ?? [];
|
|
1287
|
+
list.push(policy);
|
|
1288
|
+
policiesByTable.set(row.tablename, list);
|
|
1289
|
+
}
|
|
1290
|
+
const rlsEnabledResult = await driver.query(`SELECT c.relname AS tablename, c.relrowsecurity AS rls_enabled
|
|
1291
|
+
FROM pg_catalog.pg_class c
|
|
1292
|
+
JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace
|
|
1293
|
+
WHERE n.nspname = $1
|
|
1294
|
+
AND c.relkind IN ('r', 'p')
|
|
1295
|
+
ORDER BY c.relname`, [schema]);
|
|
1296
|
+
const rlsEnabledByTable = new Map(rlsEnabledResult.rows.map((row) => [row.tablename, row.rls_enabled]));
|
|
1297
|
+
const tables = {};
|
|
1298
|
+
for (const [tableName, input] of Object.entries(tableInputs)) tables[tableName] = new PostgresTableSchemaNode({
|
|
1299
|
+
...input,
|
|
1300
|
+
policies: policiesByTable.get(tableName) ?? [],
|
|
1301
|
+
rlsEnabled: rlsEnabledByTable.get(tableName) ?? false
|
|
1302
|
+
});
|
|
1210
1303
|
return {
|
|
1211
|
-
|
|
1212
|
-
|
|
1213
|
-
|
|
1214
|
-
|
|
1215
|
-
|
|
1216
|
-
|
|
1304
|
+
namespace: new PostgresNamespaceSchemaNode({
|
|
1305
|
+
schemaName: schema,
|
|
1306
|
+
tables,
|
|
1307
|
+
nativeEnums: enums
|
|
1308
|
+
}),
|
|
1309
|
+
pgVersion: await this.getPostgresVersion(driver)
|
|
1217
1310
|
};
|
|
1218
1311
|
}
|
|
1219
1312
|
/**
|
|
@@ -1224,6 +1317,86 @@ var PostgresControlAdapter = class {
|
|
|
1224
1317
|
}
|
|
1225
1318
|
};
|
|
1226
1319
|
/**
|
|
1320
|
+
* Normalises a `name[]` column value from `pg_policies.roles`.
|
|
1321
|
+
*
|
|
1322
|
+
* The `pg` client's type-parser registry handles `text[]` (OID 1009) but not
|
|
1323
|
+
* `name[]` (OID 1003). When the parser is absent the raw Postgres text-array
|
|
1324
|
+
* literal (`{role1,role2}`) is returned as a string instead of a JS array.
|
|
1325
|
+
* This function accepts either form and returns a plain string array.
|
|
1326
|
+
*
|
|
1327
|
+
* The string branch honors Postgres array-literal quoting: an element
|
|
1328
|
+
* containing a comma, quote, backslash, brace, or significant whitespace is
|
|
1329
|
+
* emitted double-quoted with `\"` / `\\` escapes, and unquoted elements are
|
|
1330
|
+
* whitespace-trimmed — so a label like `in progress` or `say "hi"` parses to
|
|
1331
|
+
* its true value instead of being split or kept escaped.
|
|
1332
|
+
*/
|
|
1333
|
+
function parsePgNameArray(value) {
|
|
1334
|
+
if (Array.isArray(value)) return value.map(String);
|
|
1335
|
+
if (typeof value !== "string") return [];
|
|
1336
|
+
const trimmed = value.trim();
|
|
1337
|
+
if (!trimmed.startsWith("{") || !trimmed.endsWith("}")) return [];
|
|
1338
|
+
const inner = trimmed.slice(1, -1);
|
|
1339
|
+
if (inner === "") return [];
|
|
1340
|
+
const elements = [];
|
|
1341
|
+
let current = "";
|
|
1342
|
+
let inQuotes = false;
|
|
1343
|
+
let wasQuoted = false;
|
|
1344
|
+
const pushCurrent = () => {
|
|
1345
|
+
elements.push(wasQuoted ? current : current.trim());
|
|
1346
|
+
current = "";
|
|
1347
|
+
wasQuoted = false;
|
|
1348
|
+
};
|
|
1349
|
+
let i = 0;
|
|
1350
|
+
while (i < inner.length) {
|
|
1351
|
+
const char = inner.charAt(i);
|
|
1352
|
+
if (inQuotes) {
|
|
1353
|
+
if (char === "\\") {
|
|
1354
|
+
current += inner[i + 1] ?? "";
|
|
1355
|
+
i += 2;
|
|
1356
|
+
continue;
|
|
1357
|
+
}
|
|
1358
|
+
if (char === "\"") {
|
|
1359
|
+
inQuotes = false;
|
|
1360
|
+
i++;
|
|
1361
|
+
continue;
|
|
1362
|
+
}
|
|
1363
|
+
current += char;
|
|
1364
|
+
i++;
|
|
1365
|
+
continue;
|
|
1366
|
+
}
|
|
1367
|
+
if (char === "\"") {
|
|
1368
|
+
inQuotes = true;
|
|
1369
|
+
wasQuoted = true;
|
|
1370
|
+
i++;
|
|
1371
|
+
continue;
|
|
1372
|
+
}
|
|
1373
|
+
if (char === ",") {
|
|
1374
|
+
pushCurrent();
|
|
1375
|
+
i++;
|
|
1376
|
+
continue;
|
|
1377
|
+
}
|
|
1378
|
+
current += char;
|
|
1379
|
+
i++;
|
|
1380
|
+
}
|
|
1381
|
+
if (inQuotes) return [];
|
|
1382
|
+
pushCurrent();
|
|
1383
|
+
return elements;
|
|
1384
|
+
}
|
|
1385
|
+
/**
|
|
1386
|
+
* Maps `pg_policies.cmd` text values to the `RlsPolicyOperation` union.
|
|
1387
|
+
* The `pg_policies` view renders the internal command code as an uppercase
|
|
1388
|
+
* English keyword; this function lowercases to match the IR type.
|
|
1389
|
+
*/
|
|
1390
|
+
function mapPgCmd(cmd) {
|
|
1391
|
+
switch (cmd.toUpperCase()) {
|
|
1392
|
+
case "SELECT": return "select";
|
|
1393
|
+
case "INSERT": return "insert";
|
|
1394
|
+
case "UPDATE": return "update";
|
|
1395
|
+
case "DELETE": return "delete";
|
|
1396
|
+
default: return "all";
|
|
1397
|
+
}
|
|
1398
|
+
}
|
|
1399
|
+
/**
|
|
1227
1400
|
* Extracts the namespace coordinate ids declared on a contract's storage,
|
|
1228
1401
|
* or returns an empty array when no contract (or no storage / namespaces)
|
|
1229
1402
|
* is present. Used by `PostgresControlAdapter.introspect` to decide
|
|
@@ -1238,6 +1411,7 @@ function extractContractNamespaceIds(contract) {
|
|
|
1238
1411
|
return Object.keys(namespaces);
|
|
1239
1412
|
}
|
|
1240
1413
|
function normalizeFormattedType(formattedType, dataType, udtName) {
|
|
1414
|
+
if (formattedType.endsWith("[]")) return `${normalizeFormattedType(formattedType.slice(0, -2), dataType, udtName)}[]`;
|
|
1241
1415
|
if (formattedType === "integer") return "int4";
|
|
1242
1416
|
if (formattedType === "smallint") return "int2";
|
|
1243
1417
|
if (formattedType === "bigint") return "int8";
|
|
@@ -1383,6 +1557,16 @@ function extractQuotedLiterals(listBody) {
|
|
|
1383
1557
|
function pgIsTextLikeNativeType(nativeType) {
|
|
1384
1558
|
return nativeType === "text" || nativeType === "varchar" || nativeType.startsWith("varchar(") || nativeType === "character varying" || nativeType.startsWith("character varying(") || nativeType === "char" || nativeType.startsWith("char(") || nativeType === "character" || nativeType.startsWith("character(");
|
|
1385
1559
|
}
|
|
1560
|
+
function pgRenderArrayElement(el) {
|
|
1561
|
+
if (el === null) return "NULL";
|
|
1562
|
+
if (typeof el === "number" || typeof el === "boolean") return String(el);
|
|
1563
|
+
if (typeof el === "string") return `'${escapeLiteral(el)}'`;
|
|
1564
|
+
return `'${escapeLiteral(JSON.stringify(el))}'`;
|
|
1565
|
+
}
|
|
1566
|
+
function pgRenderArrayLiteral(elements) {
|
|
1567
|
+
if (elements.length === 0) return "'{}'";
|
|
1568
|
+
return `ARRAY[${elements.map(pgRenderArrayElement).join(", ")}]`;
|
|
1569
|
+
}
|
|
1386
1570
|
function pgInlineLiteral(wire, nativeType) {
|
|
1387
1571
|
if (wire === null) return "NULL";
|
|
1388
1572
|
if (typeof wire === "boolean") return wire ? "true" : "false";
|
|
@@ -1401,6 +1585,7 @@ function pgInlineLiteral(wire, nativeType) {
|
|
|
1401
1585
|
return pgIsTextLikeNativeType(nativeType) ? quoted : `${quoted}::${nativeType}`;
|
|
1402
1586
|
}
|
|
1403
1587
|
if (wire instanceof Uint8Array) return `'\\x${Array.from(wire).map((b) => b.toString(16).padStart(2, "0")).join("")}'::${nativeType}`;
|
|
1588
|
+
if (Array.isArray(wire) && nativeType.endsWith("[]")) return pgRenderArrayLiteral(wire);
|
|
1404
1589
|
if (typeof wire === "object") return `${`'${escapeLiteral(JSON.stringify(wire))}'`}::${nativeType}`;
|
|
1405
1590
|
throw new Error(`pgRenderDdlExecuteRequest: unexpected wire type "${typeof wire}" for native type "${nativeType}"`);
|
|
1406
1591
|
}
|
|
@@ -1438,6 +1623,7 @@ function pgRenderDdlConstraint(constraint) {
|
|
|
1438
1623
|
if (constraint.name !== void 0) sql = `CONSTRAINT ${quoteIdentifier(constraint.name)} ${sql}`;
|
|
1439
1624
|
return sql;
|
|
1440
1625
|
}
|
|
1626
|
+
if (constraint.kind === "check-expression") return `CONSTRAINT ${quoteIdentifier(constraint.name)} CHECK (${constraint.expression})`;
|
|
1441
1627
|
const cols = constraint.columns.map(quoteIdentifier).join(", ");
|
|
1442
1628
|
if (constraint.name !== void 0) return `CONSTRAINT ${quoteIdentifier(constraint.name)} UNIQUE (${cols})`;
|
|
1443
1629
|
return `UNIQUE (${cols})`;
|
|
@@ -1458,24 +1644,87 @@ function pgRenderCreateSchema(node) {
|
|
|
1458
1644
|
params: []
|
|
1459
1645
|
};
|
|
1460
1646
|
}
|
|
1647
|
+
function pgRenderCreateType(node) {
|
|
1648
|
+
return {
|
|
1649
|
+
sql: `CREATE TYPE ${node.schema ? `${quoteIdentifier(node.schema)}.${quoteIdentifier(node.name)}` : quoteIdentifier(node.name)} AS ENUM (${node.values.map((value) => `'${escapeLiteral(value)}'`).join(", ")})`,
|
|
1650
|
+
params: []
|
|
1651
|
+
};
|
|
1652
|
+
}
|
|
1653
|
+
function pgRenderDropType(node) {
|
|
1654
|
+
return {
|
|
1655
|
+
sql: `DROP TYPE ${node.schema ? `${quoteIdentifier(node.schema)}.${quoteIdentifier(node.name)}` : quoteIdentifier(node.name)}`,
|
|
1656
|
+
params: []
|
|
1657
|
+
};
|
|
1658
|
+
}
|
|
1461
1659
|
async function pgRenderAlterTable(node, codecLookup) {
|
|
1462
1660
|
const tableRef = node.schema ? `${quoteIdentifier(node.schema)}.${quoteIdentifier(node.table)}` : quoteIdentifier(node.table);
|
|
1463
|
-
const actionVisitor = {
|
|
1464
|
-
|
|
1465
|
-
|
|
1661
|
+
const actionVisitor = {
|
|
1662
|
+
async addColumn(action) {
|
|
1663
|
+
return `ADD COLUMN ${await pgRenderDdlColumn(action.column, codecLookup)}`;
|
|
1664
|
+
},
|
|
1665
|
+
dropDefault(action) {
|
|
1666
|
+
return Promise.resolve(`ALTER COLUMN ${quoteIdentifier(action.columnName)} DROP DEFAULT`);
|
|
1667
|
+
}
|
|
1668
|
+
};
|
|
1466
1669
|
return {
|
|
1467
1670
|
sql: `ALTER TABLE ${tableRef} ${(await Promise.all(node.actions.map((a) => a.accept(actionVisitor)))).join(", ")}`,
|
|
1468
1671
|
params: []
|
|
1469
1672
|
};
|
|
1470
1673
|
}
|
|
1674
|
+
const POLICY_OPERATION_SQL = {
|
|
1675
|
+
select: "SELECT",
|
|
1676
|
+
insert: "INSERT",
|
|
1677
|
+
update: "UPDATE",
|
|
1678
|
+
delete: "DELETE",
|
|
1679
|
+
all: "ALL"
|
|
1680
|
+
};
|
|
1681
|
+
function pgRenderCreatePolicy(node) {
|
|
1682
|
+
const tableRef = `${quoteIdentifier(node.schema)}.${quoteIdentifier(node.table)}`;
|
|
1683
|
+
const permissiveness = node.permissive ? "PERMISSIVE" : "RESTRICTIVE";
|
|
1684
|
+
const command = POLICY_OPERATION_SQL[node.operation];
|
|
1685
|
+
const roles = node.roles.length === 0 ? "PUBLIC" : node.roles.join(", ");
|
|
1686
|
+
let sql = `CREATE POLICY ${quoteIdentifier(node.name)} ON ${tableRef} AS ${permissiveness} FOR ${command} TO ${roles}`;
|
|
1687
|
+
if (node.using !== void 0) sql += ` USING (${node.using})`;
|
|
1688
|
+
if (node.withCheck !== void 0) sql += ` WITH CHECK (${node.withCheck})`;
|
|
1689
|
+
return {
|
|
1690
|
+
sql,
|
|
1691
|
+
params: []
|
|
1692
|
+
};
|
|
1693
|
+
}
|
|
1694
|
+
function pgRenderDropPolicy(node) {
|
|
1695
|
+
const tableRef = `${quoteIdentifier(node.schema)}.${quoteIdentifier(node.table)}`;
|
|
1696
|
+
return {
|
|
1697
|
+
sql: `DROP POLICY ${quoteIdentifier(node.name)} ON ${tableRef}`,
|
|
1698
|
+
params: []
|
|
1699
|
+
};
|
|
1700
|
+
}
|
|
1701
|
+
function pgRenderAlterPolicyRename(node) {
|
|
1702
|
+
const tableRef = `${quoteIdentifier(node.schema)}.${quoteIdentifier(node.table)}`;
|
|
1703
|
+
return {
|
|
1704
|
+
sql: `ALTER POLICY ${quoteIdentifier(node.name)} ON ${tableRef} RENAME TO ${quoteIdentifier(node.newName)}`,
|
|
1705
|
+
params: []
|
|
1706
|
+
};
|
|
1707
|
+
}
|
|
1708
|
+
function pgRenderDisableRowLevelSecurity(node) {
|
|
1709
|
+
return {
|
|
1710
|
+
sql: `ALTER TABLE ${`${quoteIdentifier(node.schema)}.${quoteIdentifier(node.table)}`} DISABLE ROW LEVEL SECURITY`,
|
|
1711
|
+
params: []
|
|
1712
|
+
};
|
|
1713
|
+
}
|
|
1471
1714
|
async function pgRenderDdlExecuteRequest(ast, codecLookup) {
|
|
1472
1715
|
return ast.accept({
|
|
1473
1716
|
createTable: (node) => pgRenderCreateTable(node, codecLookup),
|
|
1474
1717
|
createSchema: (node) => Promise.resolve(pgRenderCreateSchema(node)),
|
|
1475
|
-
|
|
1718
|
+
createType: (node) => Promise.resolve(pgRenderCreateType(node)),
|
|
1719
|
+
dropType: (node) => Promise.resolve(pgRenderDropType(node)),
|
|
1720
|
+
alterTable: (node) => pgRenderAlterTable(node, codecLookup),
|
|
1721
|
+
createPolicy: (node) => Promise.resolve(pgRenderCreatePolicy(node)),
|
|
1722
|
+
dropPolicy: (node) => Promise.resolve(pgRenderDropPolicy(node)),
|
|
1723
|
+
alterPolicyRename: (node) => Promise.resolve(pgRenderAlterPolicyRename(node)),
|
|
1724
|
+
disableRowLevelSecurity: (node) => Promise.resolve(pgRenderDisableRowLevelSecurity(node))
|
|
1476
1725
|
});
|
|
1477
1726
|
}
|
|
1478
1727
|
//#endregion
|
|
1479
1728
|
export { renderLoweredSql as n, createPostgresBuiltinCodecLookup as r, PostgresControlAdapter as t };
|
|
1480
1729
|
|
|
1481
|
-
//# sourceMappingURL=control-adapter-
|
|
1730
|
+
//# sourceMappingURL=control-adapter-w2BFxQ--.mjs.map
|