@prisma-next/adapter-postgres 0.5.0-dev.60 → 0.5.0-dev.61

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.
@@ -22,7 +22,6 @@ import {
22
22
  type ParamRef,
23
23
  type ProjectionItem,
24
24
  type SelectAst,
25
- type Codec as SqlCodec,
26
25
  type SubqueryExpr,
27
26
  type UpdateAst,
28
27
  } from '@prisma-next/sql-relational-core/ast';
@@ -30,21 +29,11 @@ import { escapeLiteral, quoteIdentifier } from '@prisma-next/target-postgres/sql
30
29
  import type { PostgresContract } from './types';
31
30
 
32
31
  /**
33
- * Postgres native types whose unknown-OID parameter inference is reliable in
34
- * arbitrary expression positions. Parameters bound to a codec whose
35
- * `meta.db.sql.postgres.nativeType` falls in this set are emitted as plain
36
- * `$N`; everything else (including `json`, `jsonb`, extension types like
37
- * `vector`, and unknown user types) is emitted as `$N::<nativeType>` so the
38
- * planner picks an unambiguous overload.
32
+ * Postgres native types whose unknown-OID parameter inference is reliable in arbitrary expression positions. Parameters bound to a codec whose `meta.db.sql.postgres.nativeType` falls in this set are emitted as plain `$N`; everything else (including `json`, `jsonb`, extension types like `vector`, and unknown user types) is emitted as `$N::<nativeType>` so the planner picks an unambiguous overload.
39
33
  *
40
- * `json` / `jsonb` are intentionally excluded despite being Postgres builtins:
41
- * their operator overloads make context inference unreliable in expression
42
- * positions (e.g. `$1 -> 'key'` is ambiguous between the two).
34
+ * `json` / `jsonb` are intentionally excluded despite being Postgres builtins: their operator overloads make context inference unreliable in expression positions (e.g. `$1 -> 'key'` is ambiguous between the two).
43
35
  *
44
- * Spellings match the on-disk `meta.db.sql.postgres.nativeType` values in
45
- * `@prisma-next/target-postgres`'s codec definitions, not the `udt_name`
46
- * abbreviations that ADR 205 used as illustrative shorthand. The lookup-based
47
- * cast policy compares against these strings directly.
36
+ * 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.
48
37
  */
49
38
  const POSTGRES_INFERRABLE_NATIVE_TYPES: ReadonlySet<string> = new Set([
50
39
  // Numeric
@@ -80,12 +69,7 @@ function renderTypedParam(
80
69
  if (codecId === undefined) {
81
70
  return `$${index}`;
82
71
  }
83
- // SQL codecs extend the framework `Codec` base with an optional
84
- // `meta: CodecMeta`; the framework `CodecLookup.get` returns the base type,
85
- // so we narrow to `SqlCodec` to read `meta`. Every codec actually
86
- // registered into a SQL codec lookup conforms to `SqlCodec`.
87
- const codec = codecLookup.get(codecId) as SqlCodec | undefined;
88
- if (codec === undefined) {
72
+ if (codecLookup.get(codecId) === undefined) {
89
73
  throw new Error(
90
74
  `Postgres lowering: ParamRef carries codecId "${codecId}" but the ` +
91
75
  'assembled codec lookup has no entry for it. This usually indicates ' +
@@ -95,18 +79,24 @@ function renderTypedParam(
95
79
  "if it's a builtin.",
96
80
  );
97
81
  }
98
- const nativeType = codec.meta?.db?.sql?.postgres?.nativeType;
99
- if (nativeType !== undefined && !POSTGRES_INFERRABLE_NATIVE_TYPES.has(nativeType)) {
82
+ // The framework `CodecLookup.metaFor` returns the family-agnostic `CodecMeta` whose `db` is `Record<string, unknown>`. The SQL family populates a narrower shape with `db.sql.<dialect>.nativeType: string`; navigate that path defensively and string-check the leaf.
83
+ const meta = codecLookup.metaFor(codecId);
84
+ const dbRecord = meta?.db;
85
+ const sqlBlock = isRecord(dbRecord) ? dbRecord['sql'] : undefined;
86
+ const dialectBlock = isRecord(sqlBlock) ? sqlBlock['postgres'] : undefined;
87
+ const nativeType = isRecord(dialectBlock) ? dialectBlock['nativeType'] : undefined;
88
+ if (typeof nativeType === 'string' && !POSTGRES_INFERRABLE_NATIVE_TYPES.has(nativeType)) {
100
89
  return `$${index}::${nativeType}`;
101
90
  }
102
91
  return `$${index}`;
103
92
  }
104
93
 
94
+ function isRecord(value: unknown): value is Record<string, unknown> {
95
+ return typeof value === 'object' && value !== null;
96
+ }
97
+
105
98
  /**
106
- * Per-render carrier threaded through every helper. Bundles the param-index
107
- * map (for `$N` numbering) and the assembled-stack `codecLookup` (for
108
- * cast policy at the `renderTypedParam` chokepoint). Carrying both on a
109
- * single value keeps helper signatures stable.
99
+ * Per-render carrier threaded through every helper. Bundles the param-index map (for `$N` numbering) and the assembled-stack `codecLookup` (for cast policy at the `renderTypedParam` chokepoint). Carrying both on a single value keeps helper signatures stable.
110
100
  */
111
101
  interface ParamIndexMap {
112
102
  readonly indexMap: Map<ParamRef, number>;
@@ -116,9 +106,7 @@ interface ParamIndexMap {
116
106
  /**
117
107
  * Render a SQL query AST to a Postgres-flavored `{ sql, params }` payload.
118
108
  *
119
- * Shared between the runtime (`PostgresAdapterImpl.lower`) and control
120
- * (`PostgresControlAdapter.lower`) entrypoints so emit-time and run-time
121
- * paths produce byte-identical output for the same AST.
109
+ * Shared between the runtime (`PostgresAdapterImpl.lower`) and control (`PostgresControlAdapter.lower`) entrypoints so emit-time and run-time paths produce byte-identical output for the same AST.
122
110
  */
123
111
  export function renderLoweredSql(
124
112
  ast: AnyQueryAst,
@@ -309,15 +297,9 @@ function renderNullCheck(
309
297
  }
310
298
 
311
299
  /**
312
- * Atomic expression kinds whose rendered SQL is already self-delimited
313
- * (a column reference, parameter, literal, function call, aggregate, etc.)
314
- * and therefore does not need surrounding parentheses when used as the
315
- * left operand of a postfix predicate like `IS NULL` or `IS NOT NULL`,
316
- * or as either operand of a binary infix operator.
300
+ * Atomic expression kinds whose rendered SQL is already self-delimited (a column reference, parameter, literal, function call, aggregate, etc.) and therefore does not need surrounding parentheses when used as the left operand of a postfix predicate like `IS NULL` or `IS NOT NULL`, or as either operand of a binary infix operator.
317
301
  *
318
- * Anything not in this set is treated as composite (binary, AND/OR/NOT,
319
- * EXISTS, nested IS NULL, subqueries, operation templates) and gets
320
- * wrapped to preserve grouping.
302
+ * Anything not in this set is treated as composite (binary, AND/OR/NOT, EXISTS, nested IS NULL, subqueries, operation templates) and gets wrapped to preserve grouping.
321
303
  */
322
304
  function isAtomicExpressionKind(kind: AnyExpression['kind']): boolean {
323
305
  switch (kind) {
@@ -571,12 +553,7 @@ function renderOperation(
571
553
  return renderExpr(arg, contract, pim);
572
554
  });
573
555
 
574
- // Resolve `{{self}}` and `{{argN}}` from the original template in a single
575
- // pass. Doing this with sequential `String.prototype.replace` calls is
576
- // unsafe: a substituted fragment can itself contain text that matches a
577
- // later token (e.g. an arg literal containing the substring `{{arg1}}`),
578
- // and the next iteration would corrupt it. A single regex callback never
579
- // re-scans already-substituted output.
556
+ // Resolve `{{self}}` and `{{argN}}` from the original template in a single pass. Doing this with sequential `String.prototype.replace` calls is unsafe: a substituted fragment can itself contain text that matches a later token (e.g. an arg literal containing the substring `{{arg1}}`), and the next iteration would corrupt it. A single regex callback never re-scans already-substituted output.
580
557
  return expr.lowering.template.replace(
581
558
  /\{\{self\}\}|\{\{arg(\d+)\}\}/g,
582
559
  (token, argIndex: string | undefined) => {
@@ -1,11 +1,10 @@
1
1
  /**
2
2
  * Column type descriptors for Postgres adapter.
3
3
  *
4
- * These descriptors provide both codecId and nativeType for use in contract authoring.
5
- * They are derived from the same source of truth as codec definitions and manifests.
4
+ * These descriptors provide both codecId and nativeType for use in contract authoring. They are derived from the same source of truth as codec definitions and manifests.
6
5
  */
7
6
 
8
- import type { ColumnTypeDescriptor } from '@prisma-next/contract-authoring';
7
+ import type { ColumnTypeDescriptor } from '@prisma-next/framework-components/codec';
9
8
  import type { StorageTypeInstance } from '@prisma-next/sql-contract/types';
10
9
  import {
11
10
  PG_BIT_CODEC_ID,
@@ -152,10 +151,7 @@ export function varbitColumn(length: number): ColumnTypeDescriptor & {
152
151
  /**
153
152
  * Postgres `bytea` column descriptor — variable-length binary string.
154
153
  *
155
- * Round-trips as `Uint8Array` on the JS side. The pg wire-protocol text
156
- * encoding (`\x` followed by hex-encoded bytes, canonical for Postgres ≥ 9.0)
157
- * and binary encoding are both handled by the underlying driver; the codec
158
- * only normalizes the JS-side representation to a plain `Uint8Array` view.
154
+ * Round-trips as `Uint8Array` on the JS side. The pg wire-protocol text encoding (`\x` followed by hex-encoded bytes, canonical for Postgres ≥ 9.0) and binary encoding are both handled by the underlying driver; the codec only normalizes the JS-side representation to a plain `Uint8Array` view.
159
155
  */
160
156
  export const byteaColumn = {
161
157
  codecId: PG_BYTEA_CODEC_ID,
@@ -175,11 +171,7 @@ export function intervalColumn(precision?: number): ColumnTypeDescriptor & {
175
171
  /**
176
172
  * Postgres `json` column descriptor — untyped raw JSON.
177
173
  *
178
- * For schema-typed JSON columns, use the per-library extension package
179
- * (`@prisma-next/extension-arktype-json` ships `arktypeJson(schema)` for
180
- * arktype). The schema-accepting `json(schema)` / `jsonb(schema)`
181
- * overloads previously shipped from this module retired in Phase C of
182
- * the codec-registry-unification project — see spec § AC-7.
174
+ * For schema-typed JSON columns, use the per-library extension package (`@prisma-next/extension-arktype-json` ships `arktypeJson(schema)` for arktype). The schema-accepting `json(schema)` / `jsonb(schema)` overloads previously shipped from this module retired in Phase C of the codec-registry-unification project — see spec § AC-7.
183
175
  */
184
176
  export const jsonColumn = {
185
177
  codecId: PG_JSON_CODEC_ID,
@@ -187,8 +179,7 @@ export const jsonColumn = {
187
179
  } as const satisfies ColumnTypeDescriptor;
188
180
 
189
181
  /**
190
- * Postgres `jsonb` column descriptor — untyped raw JSONB. Same retirement
191
- * note as {@link jsonColumn}.
182
+ * Postgres `jsonb` column descriptor — untyped raw JSONB. Same retirement note as {@link jsonColumn}.
192
183
  */
193
184
  export const jsonbColumn = {
194
185
  codecId: PG_JSONB_CODEC_ID,
@@ -4,13 +4,9 @@ import { extractCodecLookup } from '@prisma-next/framework-components/control';
4
4
  import type { RuntimeAdapterInstance } from '@prisma-next/framework-components/execution';
5
5
  import { builtinGeneratorIds } from '@prisma-next/ids';
6
6
  import { generateId } from '@prisma-next/ids/runtime';
7
- import type { Adapter, AnyQueryAst, CodecRegistry } from '@prisma-next/sql-relational-core/ast';
8
- import { createCodecRegistry } from '@prisma-next/sql-relational-core/ast';
9
- import type {
10
- RuntimeParameterizedCodecDescriptor,
11
- SqlRuntimeAdapterDescriptor,
12
- } from '@prisma-next/sql-runtime';
13
- import { codecDefinitions } from '@prisma-next/target-postgres/codecs';
7
+ import type { Adapter, AnyQueryAst } from '@prisma-next/sql-relational-core/ast';
8
+ import type { SqlRuntimeAdapterDescriptor } from '@prisma-next/sql-runtime';
9
+ import { postgresCodecRegistry } from '@prisma-next/target-postgres/codecs';
14
10
  import { createPostgresAdapter } from '../core/adapter';
15
11
  import { postgresAdapterDescriptorMeta, postgresQueryOperations } from '../core/descriptor-meta';
16
12
  import type { PostgresContract, PostgresLoweredStatement } from '../core/types';
@@ -19,14 +15,6 @@ export interface SqlRuntimeAdapter
19
15
  extends RuntimeAdapterInstance<'sql', 'postgres'>,
20
16
  Adapter<AnyQueryAst, PostgresContract, PostgresLoweredStatement> {}
21
17
 
22
- function createPostgresCodecRegistry(): CodecRegistry {
23
- const registry = createCodecRegistry();
24
- for (const definition of Object.values(codecDefinitions)) {
25
- registry.register(definition.codec);
26
- }
27
- return registry;
28
- }
29
-
30
18
  function createPostgresMutationDefaultGenerators() {
31
19
  return [
32
20
  ...builtinGeneratorIds.map((id) => ({
@@ -41,34 +29,15 @@ function createPostgresMutationDefaultGenerators() {
41
29
  ];
42
30
  }
43
31
 
44
- /**
45
- * Phase C of codec-registry-unification: the postgres adapter retains
46
- * only static raw-JSON / raw-JSONB column descriptors. Schema-typed JSON
47
- * columns ship from per-library extension packages now —
48
- * `@prisma-next/extension-arktype-json` for arktype, future zod / valibot
49
- * extensions when each lands. The previously-shipped
50
- * `parameterizedCodecDescriptors` for `pg/json@1` / `pg/jsonb@1` retired
51
- * with the schema-typed surface; the unified descriptor map auto-lifts
52
- * the raw json/jsonb codecs from `codecs:` via the synthesis bridge for
53
- * codec-id-keyed metadata reads.
54
- */
55
- const parameterizedCodecDescriptors: ReadonlyArray<RuntimeParameterizedCodecDescriptor> = [];
56
-
57
32
  const postgresRuntimeAdapterDescriptor: SqlRuntimeAdapterDescriptor<'postgres', SqlRuntimeAdapter> =
58
33
  {
59
34
  ...postgresAdapterDescriptorMeta,
60
- codecs: createPostgresCodecRegistry,
61
- parameterizedCodecs: () => parameterizedCodecDescriptors,
35
+ codecs: () => Array.from(postgresCodecRegistry.values()),
62
36
  queryOperations: () => postgresQueryOperations(),
63
37
  mutationDefaultGenerators: createPostgresMutationDefaultGenerators,
64
38
  create(stack): SqlRuntimeAdapter {
65
- // The runtime `ExecutionStack` does not (yet) carry a pre-assembled
66
- // `codecLookup` field the way the control `ControlStack` does, so we
67
- // derive an equivalent lookup here from the stack's component metadata
68
- // (target + adapter + extension packs) using the same assembly helper
69
- // that `createControlStack` uses. This keeps the renderer fed with the
70
- // same codec set on both planes — including extension-contributed
71
- // codecs like `pg/vector@1` from `@prisma-next/extension-pgvector`.
39
+ // The runtime `ExecutionStack` does not (yet) carry a pre-assembled `codecLookup` field the way the control `ControlStack` does, so we derive an equivalent lookup here from the stack's component metadata (target + adapter + extension packs) using the same assembly helper that `createControlStack` uses. This keeps the renderer fed with the same codec set on both planes — including extension-contributed codecs like
40
+ // `pg/vector@1` from `@prisma-next/extension-pgvector`.
72
41
  const codecLookup = extractCodecLookup([
73
42
  stack.target,
74
43
  stack.adapter,
@@ -1 +0,0 @@
1
- {"version":3,"file":"adapter-_L4wXA4O.mjs","names":["parameterizedCodecs: ReadonlyArray<CodecParamsDescriptor>"],"sources":["../src/core/adapter.ts"],"sourcesContent":["import type { CodecLookup } from '@prisma-next/framework-components/codec';\nimport {\n type Adapter,\n type AdapterProfile,\n type AnyQueryAst,\n type CodecParamsDescriptor,\n createCodecRegistry,\n type LowererContext,\n} from '@prisma-next/sql-relational-core/ast';\nimport { parseContractMarkerRow } from '@prisma-next/sql-runtime';\nimport { codecDefinitions } from '@prisma-next/target-postgres/codecs';\nimport { ifDefined } from '@prisma-next/utils/defined';\nimport { createPostgresBuiltinCodecLookup } from './codec-lookup';\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 },\n sql: {\n enums: true,\n returning: true,\n defaultInInsert: true,\n },\n});\n\ntype AdapterCodec = (typeof codecDefinitions)[keyof typeof codecDefinitions]['codec'];\ntype ParameterizedCodec = AdapterCodec & {\n readonly paramsSchema: NonNullable<AdapterCodec['paramsSchema']>;\n};\n\nconst parameterizedCodecs: ReadonlyArray<CodecParamsDescriptor> = Object.values(codecDefinitions)\n .map((definition) => definition.codec)\n .filter((codec): codec is ParameterizedCodec => codec.paramsSchema !== undefined)\n .map((codec) =>\n Object.freeze({\n codecId: codec.id,\n paramsSchema: codec.paramsSchema,\n ...ifDefined('init', codec.init),\n }),\n );\n\nclass PostgresAdapterImpl\n implements Adapter<AnyQueryAst, PostgresContract, PostgresLoweredStatement>\n{\n // These fields make the adapter instance structurally compatible with\n // 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 codecRegistry = (() => {\n const registry = createCodecRegistry();\n for (const definition of Object.values(codecDefinitions)) {\n registry.register(definition.codec);\n }\n return registry;\n })();\n private readonly codecLookup: CodecLookup;\n\n constructor(options?: PostgresAdapterOptions) {\n this.codecLookup = options?.codecLookup ?? createPostgresBuiltinCodecLookup();\n this.profile = Object.freeze({\n id: options?.profileId ?? 'postgres/default@1',\n target: 'postgres',\n capabilities: defaultCapabilities,\n codecs: () => this.codecRegistry,\n readMarkerStatement: () => ({\n sql: 'select core_hash, profile_hash, contract_json, canonical_version, updated_at, app_tag, meta, invariants from prisma_contract.marker where id = $1',\n params: [1],\n }),\n // Postgres' driver hydrates `text[]` columns as native JS arrays, so\n // the row is already in the shape the shared parser expects.\n parseMarkerRow: (row: unknown) => parseContractMarkerRow(row),\n });\n }\n\n parameterizedCodecs(): ReadonlyArray<CodecParamsDescriptor> {\n return parameterizedCodecs;\n }\n\n lower(ast: AnyQueryAst, context: LowererContext<PostgresContract>): PostgresLoweredStatement {\n return renderLoweredSql(ast, context.contract, this.codecLookup);\n }\n}\n\nexport function createPostgresAdapter(options?: PostgresAdapterOptions) {\n return Object.freeze(new PostgresAdapterImpl(options));\n}\n"],"mappings":";;;;;;;AAgBA,MAAM,sBAAsB,OAAO,OAAO;CACxC,UAAU;EACR,SAAS;EACT,OAAO;EACP,SAAS;EACT,SAAS;EACT,WAAW;EACZ;CACD,KAAK;EACH,OAAO;EACP,WAAW;EACX,iBAAiB;EAClB;CACF,CAAC;AAOF,MAAMA,sBAA4D,OAAO,OAAO,iBAAiB,CAC9F,KAAK,eAAe,WAAW,MAAM,CACrC,QAAQ,UAAuC,MAAM,iBAAiB,OAAU,CAChF,KAAK,UACJ,OAAO,OAAO;CACZ,SAAS,MAAM;CACf,cAAc,MAAM;CACpB,GAAG,UAAU,QAAQ,MAAM,KAAK;CACjC,CAAC,CACH;AAEH,IAAM,sBAAN,MAEA;CAGE,AAAS,WAAW;CACpB,AAAS,WAAW;CAEpB,AAAS;CACT,AAAiB,uBAAuB;EACtC,MAAM,WAAW,qBAAqB;AACtC,OAAK,MAAM,cAAc,OAAO,OAAO,iBAAiB,CACtD,UAAS,SAAS,WAAW,MAAM;AAErC,SAAO;KACL;CACJ,AAAiB;CAEjB,YAAY,SAAkC;AAC5C,OAAK,cAAc,SAAS,eAAe,kCAAkC;AAC7E,OAAK,UAAU,OAAO,OAAO;GAC3B,IAAI,SAAS,aAAa;GAC1B,QAAQ;GACR,cAAc;GACd,cAAc,KAAK;GACnB,4BAA4B;IAC1B,KAAK;IACL,QAAQ,CAAC,EAAE;IACZ;GAGD,iBAAiB,QAAiB,uBAAuB,IAAI;GAC9D,CAAC;;CAGJ,sBAA4D;AAC1D,SAAO;;CAGT,MAAM,KAAkB,SAAqE;AAC3F,SAAO,iBAAiB,KAAK,QAAQ,UAAU,KAAK,YAAY;;;AAIpE,SAAgB,sBAAsB,SAAkC;AACtE,QAAO,OAAO,OAAO,IAAI,oBAAoB,QAAQ,CAAC"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"sql-renderer-DLwYpnxz.mjs","names":["POSTGRES_INFERRABLE_NATIVE_TYPES: ReadonlySet<string>","params: unknown[]","pim: ParamIndexMap","sql: string","right: string","orderedColumns: string[]","value: string"],"sources":["../src/core/codec-lookup.ts","../src/core/sql-renderer.ts"],"sourcesContent":["import type { Codec, CodecLookup } from '@prisma-next/framework-components/codec';\nimport { codecDefinitions } from '@prisma-next/target-postgres/codecs';\n\n/**\n * Build a {@link CodecLookup} populated with the Postgres-builtin codec\n * definitions only.\n *\n * This is the default lookup used by `createPostgresAdapter()` and\n * `new PostgresControlAdapter()` when called without a stack-derived lookup\n * (e.g. from tests, or one-off scripts that don't compose a full stack).\n *\n * Extension codecs (e.g. `pg/vector@1` from `@prisma-next/extension-pgvector`)\n * are intentionally NOT included here: a bare adapter cannot see extensions.\n * Stack-composed paths (`SqlControlAdapterDescriptor.create(stack)` /\n * `SqlRuntimeAdapterDescriptor.create(stack)`) supply the broader,\n * extension-inclusive lookup at construction time.\n */\nexport function createPostgresBuiltinCodecLookup(): CodecLookup {\n const byId = new Map<string, Codec>();\n for (const definition of Object.values(codecDefinitions)) {\n byId.set(definition.codec.id, definition.codec);\n }\n return { get: (id) => byId.get(id) };\n}\n","import type { CodecLookup } from '@prisma-next/framework-components/codec';\nimport {\n type AggregateExpr,\n type AnyExpression,\n type AnyFromSource,\n type AnyQueryAst,\n type BinaryExpr,\n type ColumnRef,\n collectOrderedParamRefs,\n type DeleteAst,\n type InsertAst,\n type InsertValue,\n type JoinAst,\n type JoinOnExpr,\n type JsonArrayAggExpr,\n type JsonObjectExpr,\n type ListExpression,\n LiteralExpr,\n type NullCheckExpr,\n type OperationExpr,\n type OrderByItem,\n type ParamRef,\n type ProjectionItem,\n type SelectAst,\n type Codec as SqlCodec,\n type SubqueryExpr,\n type UpdateAst,\n} from '@prisma-next/sql-relational-core/ast';\nimport { escapeLiteral, quoteIdentifier } from '@prisma-next/target-postgres/sql-utils';\nimport type { PostgresContract } from './types';\n\n/**\n * Postgres native types whose unknown-OID parameter inference is reliable in\n * arbitrary expression positions. Parameters bound to a codec whose\n * `meta.db.sql.postgres.nativeType` falls in this set are emitted as plain\n * `$N`; everything else (including `json`, `jsonb`, extension types like\n * `vector`, and unknown user types) is emitted as `$N::<nativeType>` so the\n * planner picks an unambiguous overload.\n *\n * `json` / `jsonb` are intentionally excluded despite being Postgres builtins:\n * their operator overloads make context inference unreliable in expression\n * positions (e.g. `$1 -> 'key'` is ambiguous between the two).\n *\n * Spellings match the on-disk `meta.db.sql.postgres.nativeType` values in\n * `@prisma-next/target-postgres`'s codec definitions, not the `udt_name`\n * abbreviations that ADR 205 used as illustrative shorthand. The lookup-based\n * cast policy compares against these strings directly.\n */\nconst POSTGRES_INFERRABLE_NATIVE_TYPES: ReadonlySet<string> = new Set([\n // Numeric\n 'integer',\n 'smallint',\n 'bigint',\n 'real',\n 'double precision',\n 'numeric',\n // Boolean\n 'boolean',\n // Strings\n 'text',\n 'character',\n 'character varying',\n // Temporal\n 'timestamp',\n 'timestamp without time zone',\n 'timestamp with time zone',\n 'time',\n 'timetz',\n 'interval',\n // Bit strings\n 'bit',\n 'bit varying',\n]);\n\nfunction renderTypedParam(\n index: number,\n codecId: string | undefined,\n codecLookup: CodecLookup,\n): string {\n if (codecId === undefined) {\n return `$${index}`;\n }\n // SQL codecs extend the framework `Codec` base with an optional\n // `meta: CodecMeta`; the framework `CodecLookup.get` returns the base type,\n // so we narrow to `SqlCodec` to read `meta`. Every codec actually\n // registered into a SQL codec lookup conforms to `SqlCodec`.\n const codec = codecLookup.get(codecId) as SqlCodec | undefined;\n if (codec === undefined) {\n throw new Error(\n `Postgres lowering: ParamRef carries codecId \"${codecId}\" but the ` +\n 'assembled codec lookup has no entry for it. This usually indicates ' +\n 'a missing extension pack in the runtime stack — register the pack ' +\n 'that contributes this codec (e.g. `extensionPacks: [pgvectorRuntime]`), ' +\n 'or use the codec directly from `@prisma-next/target-postgres/codecs` ' +\n \"if it's a builtin.\",\n );\n }\n const nativeType = codec.meta?.db?.sql?.postgres?.nativeType;\n if (nativeType !== undefined && !POSTGRES_INFERRABLE_NATIVE_TYPES.has(nativeType)) {\n return `$${index}::${nativeType}`;\n }\n return `$${index}`;\n}\n\n/**\n * Per-render carrier threaded through every helper. Bundles the param-index\n * map (for `$N` numbering) and the assembled-stack `codecLookup` (for\n * cast policy at the `renderTypedParam` chokepoint). Carrying both on a\n * single value keeps helper signatures stable.\n */\ninterface ParamIndexMap {\n readonly indexMap: Map<ParamRef, number>;\n readonly codecLookup: CodecLookup;\n}\n\n/**\n * Render a SQL query AST to a Postgres-flavored `{ sql, params }` payload.\n *\n * Shared between the runtime (`PostgresAdapterImpl.lower`) and control\n * (`PostgresControlAdapter.lower`) entrypoints so emit-time and run-time\n * paths produce byte-identical output for the same AST.\n */\nexport function renderLoweredSql(\n ast: AnyQueryAst,\n contract: PostgresContract,\n codecLookup: CodecLookup,\n): { readonly sql: string; readonly params: readonly unknown[] } {\n const orderedRefs = collectOrderedParamRefs(ast);\n const indexMap = new Map<ParamRef, number>();\n const params: unknown[] = orderedRefs.map((ref, i) => {\n indexMap.set(ref, i + 1);\n return ref.value;\n });\n const pim: ParamIndexMap = { indexMap, codecLookup };\n\n const node = ast;\n let sql: string;\n switch (node.kind) {\n case 'select':\n sql = renderSelect(node, contract, pim);\n break;\n case 'insert':\n sql = renderInsert(node, contract, pim);\n break;\n case 'update':\n sql = renderUpdate(node, contract, pim);\n break;\n case 'delete':\n sql = renderDelete(node, contract, pim);\n break;\n // v8 ignore next 4\n default:\n throw new Error(\n `Unsupported AST node kind: ${(node satisfies never as { kind: string }).kind}`,\n );\n }\n\n return Object.freeze({ sql, params: Object.freeze(params) });\n}\n\nfunction renderSelect(ast: SelectAst, contract: PostgresContract, pim: ParamIndexMap): string {\n const selectClause = `SELECT ${renderDistinctPrefix(ast.distinct, ast.distinctOn, contract, pim)}${renderProjection(\n ast.projection,\n contract,\n pim,\n )}`;\n const fromClause = `FROM ${renderSource(ast.from, contract, pim)}`;\n\n const joinsClause = ast.joins?.length\n ? ast.joins.map((join) => renderJoin(join, contract, pim)).join(' ')\n : '';\n\n const whereClause = ast.where ? `WHERE ${renderWhere(ast.where, contract, pim)}` : '';\n const groupByClause = ast.groupBy?.length\n ? `GROUP BY ${ast.groupBy.map((expr) => renderExpr(expr, contract, pim)).join(', ')}`\n : '';\n const havingClause = ast.having ? `HAVING ${renderWhere(ast.having, contract, pim)}` : '';\n const orderClause = ast.orderBy?.length\n ? `ORDER BY ${ast.orderBy\n .map((order) => {\n const expr = renderExpr(order.expr, contract, pim);\n return `${expr} ${order.dir.toUpperCase()}`;\n })\n .join(', ')}`\n : '';\n const limitClause = typeof ast.limit === 'number' ? `LIMIT ${ast.limit}` : '';\n const offsetClause = typeof ast.offset === 'number' ? `OFFSET ${ast.offset}` : '';\n\n const clauses = [\n selectClause,\n fromClause,\n joinsClause,\n whereClause,\n groupByClause,\n havingClause,\n orderClause,\n limitClause,\n offsetClause,\n ]\n .filter((part) => part.length > 0)\n .join(' ');\n return clauses.trim();\n}\n\nfunction renderProjection(\n projection: ReadonlyArray<ProjectionItem>,\n contract: PostgresContract,\n pim: ParamIndexMap,\n): string {\n return projection\n .map((item) => {\n const alias = quoteIdentifier(item.alias);\n if (item.expr.kind === 'literal') {\n return `${renderLiteral(item.expr)} AS ${alias}`;\n }\n return `${renderExpr(item.expr, contract, pim)} AS ${alias}`;\n })\n .join(', ');\n}\n\nfunction renderReturning(\n items: ReadonlyArray<ProjectionItem>,\n contract: PostgresContract,\n pim: ParamIndexMap,\n): string {\n return items\n .map((item) => {\n if (item.expr.kind === 'column-ref') {\n const rendered = renderColumn(item.expr);\n return item.expr.column === item.alias\n ? rendered\n : `${rendered} AS ${quoteIdentifier(item.alias)}`;\n }\n if (item.expr.kind === 'literal') {\n return `${renderLiteral(item.expr)} AS ${quoteIdentifier(item.alias)}`;\n }\n return `${renderExpr(item.expr, contract, pim)} AS ${quoteIdentifier(item.alias)}`;\n })\n .join(', ');\n}\n\nfunction renderDistinctPrefix(\n distinct: true | undefined,\n distinctOn: ReadonlyArray<AnyExpression> | undefined,\n contract: PostgresContract,\n pim: ParamIndexMap,\n): string {\n if (distinctOn && distinctOn.length > 0) {\n const rendered = distinctOn.map((expr) => renderExpr(expr, contract, pim)).join(', ');\n return `DISTINCT ON (${rendered}) `;\n }\n if (distinct) {\n return 'DISTINCT ';\n }\n return '';\n}\n\nfunction renderSource(\n source: AnyFromSource,\n contract: PostgresContract,\n pim: ParamIndexMap,\n): string {\n const node = source;\n switch (node.kind) {\n case 'table-source': {\n const table = quoteIdentifier(node.name);\n if (!node.alias) {\n return table;\n }\n return `${table} AS ${quoteIdentifier(node.alias)}`;\n }\n case 'derived-table-source':\n return `(${renderSelect(node.query, contract, pim)}) AS ${quoteIdentifier(node.alias)}`;\n // v8 ignore next 4\n default:\n throw new Error(\n `Unsupported source node kind: ${(node satisfies never as { kind: string }).kind}`,\n );\n }\n}\n\nfunction assertScalarSubquery(query: SelectAst): void {\n if (query.projection.length !== 1) {\n throw new Error('Subquery expressions must project exactly one column');\n }\n}\n\nfunction renderSubqueryExpr(\n expr: SubqueryExpr,\n contract: PostgresContract,\n pim: ParamIndexMap,\n): string {\n assertScalarSubquery(expr.query);\n return `(${renderSelect(expr.query, contract, pim)})`;\n}\n\nfunction renderWhere(expr: AnyExpression, contract: PostgresContract, pim: ParamIndexMap): string {\n return renderExpr(expr, contract, pim);\n}\n\nfunction renderNullCheck(\n expr: NullCheckExpr,\n contract: PostgresContract,\n pim: ParamIndexMap,\n): string {\n const rendered = renderExpr(expr.expr, contract, pim);\n const renderedExpr = isAtomicExpressionKind(expr.expr.kind) ? rendered : `(${rendered})`;\n return expr.isNull ? `${renderedExpr} IS NULL` : `${renderedExpr} IS NOT NULL`;\n}\n\n/**\n * Atomic expression kinds whose rendered SQL is already self-delimited\n * (a column reference, parameter, literal, function call, aggregate, etc.)\n * and therefore does not need surrounding parentheses when used as the\n * left operand of a postfix predicate like `IS NULL` or `IS NOT NULL`,\n * or as either operand of a binary infix operator.\n *\n * Anything not in this set is treated as composite (binary, AND/OR/NOT,\n * EXISTS, nested IS NULL, subqueries, operation templates) and gets\n * wrapped to preserve grouping.\n */\nfunction isAtomicExpressionKind(kind: AnyExpression['kind']): boolean {\n switch (kind) {\n case 'column-ref':\n case 'identifier-ref':\n case 'param-ref':\n case 'literal':\n case 'aggregate':\n case 'json-object':\n case 'json-array-agg':\n case 'list':\n return true;\n case 'subquery':\n case 'operation':\n case 'binary':\n case 'and':\n case 'or':\n case 'exists':\n case 'null-check':\n case 'not':\n return false;\n }\n}\n\nfunction renderBinary(expr: BinaryExpr, contract: PostgresContract, pim: ParamIndexMap): string {\n if (expr.right.kind === 'list' && expr.right.values.length === 0) {\n if (expr.op === 'in') {\n return 'FALSE';\n }\n if (expr.op === 'notIn') {\n return 'TRUE';\n }\n }\n\n const leftExpr = expr.left;\n const left = renderExpr(leftExpr, contract, pim);\n const leftRendered =\n leftExpr.kind === 'operation' || leftExpr.kind === 'subquery' ? `(${left})` : left;\n\n const rightNode = expr.right;\n let right: string;\n switch (rightNode.kind) {\n case 'list':\n right = renderListLiteral(rightNode, contract, pim);\n break;\n case 'literal':\n right = renderLiteral(rightNode);\n break;\n case 'column-ref':\n right = renderColumn(rightNode);\n break;\n case 'param-ref':\n right = renderParamRef(rightNode, pim);\n break;\n default:\n right = renderExpr(rightNode, contract, pim);\n break;\n }\n\n const operatorMap: Record<BinaryExpr['op'], string> = {\n eq: '=',\n neq: '!=',\n gt: '>',\n lt: '<',\n gte: '>=',\n lte: '<=',\n like: 'LIKE',\n in: 'IN',\n notIn: 'NOT IN',\n };\n\n return `${leftRendered} ${operatorMap[expr.op]} ${right}`;\n}\n\nfunction renderListLiteral(\n expr: ListExpression,\n contract: PostgresContract,\n pim: ParamIndexMap,\n): string {\n if (expr.values.length === 0) {\n return '(NULL)';\n }\n const values = expr.values\n .map((v) => {\n if (v.kind === 'param-ref') return renderParamRef(v, pim);\n if (v.kind === 'literal') return renderLiteral(v);\n return renderExpr(v, contract, pim);\n })\n .join(', ');\n return `(${values})`;\n}\n\nfunction renderColumn(ref: ColumnRef): string {\n if (ref.table === 'excluded') {\n return `excluded.${quoteIdentifier(ref.column)}`;\n }\n return `${quoteIdentifier(ref.table)}.${quoteIdentifier(ref.column)}`;\n}\n\nfunction renderAggregateExpr(\n expr: AggregateExpr,\n contract: PostgresContract,\n pim: ParamIndexMap,\n): string {\n const fn = expr.fn.toUpperCase();\n if (!expr.expr) {\n return `${fn}(*)`;\n }\n return `${fn}(${renderExpr(expr.expr, contract, pim)})`;\n}\n\nfunction renderJsonObjectExpr(\n expr: JsonObjectExpr,\n contract: PostgresContract,\n pim: ParamIndexMap,\n): string {\n const args = expr.entries\n .flatMap((entry): [string, string] => {\n const key = `'${escapeLiteral(entry.key)}'`;\n if (entry.value.kind === 'literal') {\n return [key, renderLiteral(entry.value)];\n }\n return [key, renderExpr(entry.value, contract, pim)];\n })\n .join(', ');\n return `json_build_object(${args})`;\n}\n\nfunction renderOrderByItems(\n items: ReadonlyArray<OrderByItem>,\n contract: PostgresContract,\n pim: ParamIndexMap,\n): string {\n return items\n .map((item) => `${renderExpr(item.expr, contract, pim)} ${item.dir.toUpperCase()}`)\n .join(', ');\n}\n\nfunction renderJsonArrayAggExpr(\n expr: JsonArrayAggExpr,\n contract: PostgresContract,\n pim: ParamIndexMap,\n): string {\n const aggregateOrderBy =\n expr.orderBy && expr.orderBy.length > 0\n ? ` ORDER BY ${renderOrderByItems(expr.orderBy, contract, pim)}`\n : '';\n const aggregated = `json_agg(${renderExpr(expr.expr, contract, pim)}${aggregateOrderBy})`;\n if (expr.onEmpty === 'emptyArray') {\n return `coalesce(${aggregated}, json_build_array())`;\n }\n return aggregated;\n}\n\nfunction renderExpr(expr: AnyExpression, contract: PostgresContract, pim: ParamIndexMap): string {\n const node = expr;\n switch (node.kind) {\n case 'column-ref':\n return renderColumn(node);\n case 'identifier-ref':\n return quoteIdentifier(node.name);\n case 'operation':\n return renderOperation(node, contract, pim);\n case 'subquery':\n return renderSubqueryExpr(node, contract, pim);\n case 'aggregate':\n return renderAggregateExpr(node, contract, pim);\n case 'json-object':\n return renderJsonObjectExpr(node, contract, pim);\n case 'json-array-agg':\n return renderJsonArrayAggExpr(node, contract, pim);\n case 'binary':\n return renderBinary(node, contract, pim);\n case 'and':\n if (node.exprs.length === 0) {\n return 'TRUE';\n }\n return `(${node.exprs.map((part) => renderExpr(part, contract, pim)).join(' AND ')})`;\n case 'or':\n if (node.exprs.length === 0) {\n return 'FALSE';\n }\n return `(${node.exprs.map((part) => renderExpr(part, contract, pim)).join(' OR ')})`;\n case 'exists': {\n const notKeyword = node.notExists ? 'NOT ' : '';\n const subquery = renderSelect(node.subquery, contract, pim);\n return `${notKeyword}EXISTS (${subquery})`;\n }\n case 'null-check':\n return renderNullCheck(node, contract, pim);\n case 'not':\n return `NOT (${renderExpr(node.expr, contract, pim)})`;\n case 'param-ref':\n return renderParamRef(node, pim);\n case 'literal':\n return renderLiteral(node);\n case 'list':\n return renderListLiteral(node, contract, pim);\n // v8 ignore next 4\n default:\n throw new Error(\n `Unsupported expression node kind: ${(node satisfies never as { kind: string }).kind}`,\n );\n }\n}\n\nfunction renderParamRef(ref: ParamRef, pim: ParamIndexMap): string {\n const index = pim.indexMap.get(ref);\n if (index === undefined) {\n throw new Error('ParamRef not found in index map');\n }\n return renderTypedParam(index, ref.codecId, pim.codecLookup);\n}\n\nfunction renderLiteral(expr: LiteralExpr): string {\n if (typeof expr.value === 'string') {\n return `'${escapeLiteral(expr.value)}'`;\n }\n if (typeof expr.value === 'number' || typeof expr.value === 'boolean') {\n return String(expr.value);\n }\n if (typeof expr.value === 'bigint') {\n return String(expr.value);\n }\n if (expr.value === null) {\n return 'NULL';\n }\n if (expr.value === undefined) {\n return 'NULL';\n }\n if (expr.value instanceof Date) {\n return `'${escapeLiteral(expr.value.toISOString())}'`;\n }\n if (Array.isArray(expr.value)) {\n return `ARRAY[${expr.value.map((v: unknown) => renderLiteral(new LiteralExpr(v))).join(', ')}]`;\n }\n const json = JSON.stringify(expr.value);\n if (json === undefined) {\n return 'NULL';\n }\n return `'${escapeLiteral(json)}'`;\n}\n\nfunction renderOperation(\n expr: OperationExpr,\n contract: PostgresContract,\n pim: ParamIndexMap,\n): string {\n const self = renderExpr(expr.self, contract, pim);\n const args = expr.args.map((arg) => {\n return renderExpr(arg, contract, pim);\n });\n\n // Resolve `{{self}}` and `{{argN}}` from the original template in a single\n // pass. Doing this with sequential `String.prototype.replace` calls is\n // unsafe: a substituted fragment can itself contain text that matches a\n // later token (e.g. an arg literal containing the substring `{{arg1}}`),\n // and the next iteration would corrupt it. A single regex callback never\n // re-scans already-substituted output.\n return expr.lowering.template.replace(\n /\\{\\{self\\}\\}|\\{\\{arg(\\d+)\\}\\}/g,\n (token, argIndex: string | undefined) => {\n if (token === '{{self}}') {\n return self;\n }\n const arg = args[Number(argIndex)];\n if (arg === undefined) {\n throw new Error(\n `Operation lowering template for \"${expr.method}\" referenced missing argument {{arg${argIndex}}}; template has ${args.length} arg(s)`,\n );\n }\n return arg;\n },\n );\n}\n\nfunction renderJoin(join: JoinAst, contract: PostgresContract, pim: ParamIndexMap): string {\n const joinType = join.joinType.toUpperCase();\n const lateral = join.lateral ? 'LATERAL ' : '';\n const source = renderSource(join.source, contract, pim);\n const onClause = renderJoinOn(join.on, contract, pim);\n return `${joinType} JOIN ${lateral}${source} ON ${onClause}`;\n}\n\nfunction renderJoinOn(on: JoinOnExpr, contract: PostgresContract, pim: ParamIndexMap): string {\n if (on.kind === 'eq-col-join-on') {\n const left = renderColumn(on.left);\n const right = renderColumn(on.right);\n return `${left} = ${right}`;\n }\n return renderWhere(on, contract, pim);\n}\n\nfunction getInsertColumnOrder(\n rows: ReadonlyArray<Record<string, InsertValue>>,\n contract: PostgresContract,\n tableName: string,\n): string[] {\n const orderedColumns: string[] = [];\n const seenColumns = new Set<string>();\n\n for (const row of rows) {\n for (const column of Object.keys(row)) {\n if (seenColumns.has(column)) {\n continue;\n }\n seenColumns.add(column);\n orderedColumns.push(column);\n }\n }\n\n if (orderedColumns.length > 0) {\n return orderedColumns;\n }\n\n const table = contract.storage.tables[tableName];\n if (!table) {\n throw new Error(`INSERT target table not found in contract storage: ${tableName}`);\n }\n return Object.keys(table.columns);\n}\n\nfunction renderInsertValue(value: InsertValue | undefined, pim: ParamIndexMap): string {\n if (!value || value.kind === 'default-value') {\n return 'DEFAULT';\n }\n\n switch (value.kind) {\n case 'param-ref':\n return renderParamRef(value, pim);\n case 'column-ref':\n return renderColumn(value);\n // v8 ignore next 4\n default:\n throw new Error(\n `Unsupported value node in INSERT: ${(value satisfies never as { kind: string }).kind}`,\n );\n }\n}\n\nfunction renderInsert(ast: InsertAst, contract: PostgresContract, pim: ParamIndexMap): string {\n const table = quoteIdentifier(ast.table.name);\n const rows = ast.rows;\n if (rows.length === 0) {\n throw new Error('INSERT requires at least one row');\n }\n const hasExplicitValues = rows.some((row) => Object.keys(row).length > 0);\n const insertClause = (() => {\n if (!hasExplicitValues) {\n if (rows.length === 1) {\n return `INSERT INTO ${table} DEFAULT VALUES`;\n }\n\n const defaultColumns = getInsertColumnOrder(rows, contract, ast.table.name);\n if (defaultColumns.length === 0) {\n return `INSERT INTO ${table} VALUES ${rows.map(() => '()').join(', ')}`;\n }\n\n const quotedColumns = defaultColumns.map((column) => quoteIdentifier(column));\n const defaultRow = `(${defaultColumns.map(() => 'DEFAULT').join(', ')})`;\n return `INSERT INTO ${table} (${quotedColumns.join(', ')}) VALUES ${rows\n .map(() => defaultRow)\n .join(', ')}`;\n }\n\n const columnOrder = getInsertColumnOrder(rows, contract, ast.table.name);\n const columns = columnOrder.map((column) => quoteIdentifier(column));\n const values = rows\n .map((row) => {\n const renderedRow = columnOrder.map((column) => renderInsertValue(row[column], pim));\n return `(${renderedRow.join(', ')})`;\n })\n .join(', ');\n\n return `INSERT INTO ${table} (${columns.join(', ')}) VALUES ${values}`;\n })();\n const onConflictClause = ast.onConflict\n ? (() => {\n const conflictColumns = ast.onConflict.columns.map((col) => quoteIdentifier(col.column));\n if (conflictColumns.length === 0) {\n throw new Error('INSERT onConflict requires at least one conflict column');\n }\n\n const action = ast.onConflict.action;\n switch (action.kind) {\n case 'do-nothing':\n return ` ON CONFLICT (${conflictColumns.join(', ')}) DO NOTHING`;\n case 'do-update-set': {\n const updateEntries = Object.entries(action.set);\n if (updateEntries.length === 0) {\n throw new Error('INSERT onConflict do-update-set requires at least one assignment');\n }\n const updates = updateEntries.map(([colName, value]) => {\n const target = quoteIdentifier(colName);\n if (value.kind === 'param-ref') {\n return `${target} = ${renderParamRef(value, pim)}`;\n }\n return `${target} = ${renderColumn(value)}`;\n });\n return ` ON CONFLICT (${conflictColumns.join(', ')}) DO UPDATE SET ${updates.join(', ')}`;\n }\n // v8 ignore next 4\n default:\n throw new Error(\n `Unsupported onConflict action: ${(action satisfies never as { kind: string }).kind}`,\n );\n }\n })()\n : '';\n const returningClause = ast.returning?.length\n ? ` RETURNING ${renderReturning(ast.returning, contract, pim)}`\n : '';\n\n return `${insertClause}${onConflictClause}${returningClause}`;\n}\n\nfunction renderUpdate(ast: UpdateAst, contract: PostgresContract, pim: ParamIndexMap): string {\n const table = quoteIdentifier(ast.table.name);\n const setEntries = Object.entries(ast.set);\n if (setEntries.length === 0) {\n throw new Error('UPDATE requires at least one SET assignment');\n }\n const setClauses = setEntries.map(([col, val]) => {\n const column = quoteIdentifier(col);\n let value: string;\n switch (val.kind) {\n case 'param-ref':\n value = renderParamRef(val, pim);\n break;\n case 'column-ref':\n value = renderColumn(val);\n break;\n // v8 ignore next 4\n default:\n throw new Error(\n `Unsupported value node in UPDATE: ${(val satisfies never as { kind: string }).kind}`,\n );\n }\n return `${column} = ${value}`;\n });\n\n const whereClause = ast.where ? ` WHERE ${renderWhere(ast.where, contract, pim)}` : '';\n const returningClause = ast.returning?.length\n ? ` RETURNING ${renderReturning(ast.returning, contract, pim)}`\n : '';\n\n return `UPDATE ${table} SET ${setClauses.join(', ')}${whereClause}${returningClause}`;\n}\n\nfunction renderDelete(ast: DeleteAst, contract: PostgresContract, pim: ParamIndexMap): string {\n const table = quoteIdentifier(ast.table.name);\n const whereClause = ast.where ? ` WHERE ${renderWhere(ast.where, contract, pim)}` : '';\n const returningClause = ast.returning?.length\n ? ` RETURNING ${renderReturning(ast.returning, contract, pim)}`\n : '';\n\n return `DELETE FROM ${table}${whereClause}${returningClause}`;\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;AAiBA,SAAgB,mCAAgD;CAC9D,MAAM,uBAAO,IAAI,KAAoB;AACrC,MAAK,MAAM,cAAc,OAAO,OAAO,iBAAiB,CACtD,MAAK,IAAI,WAAW,MAAM,IAAI,WAAW,MAAM;AAEjD,QAAO,EAAE,MAAM,OAAO,KAAK,IAAI,GAAG,EAAE;;;;;;;;;;;;;;;;;;;;;;AC0BtC,MAAMA,mCAAwD,IAAI,IAAI;CAEpE;CACA;CACA;CACA;CACA;CACA;CAEA;CAEA;CACA;CACA;CAEA;CACA;CACA;CACA;CACA;CACA;CAEA;CACA;CACD,CAAC;AAEF,SAAS,iBACP,OACA,SACA,aACQ;AACR,KAAI,YAAY,OACd,QAAO,IAAI;CAMb,MAAM,QAAQ,YAAY,IAAI,QAAQ;AACtC,KAAI,UAAU,OACZ,OAAM,IAAI,MACR,gDAAgD,QAAQ,oTAMzD;CAEH,MAAM,aAAa,MAAM,MAAM,IAAI,KAAK,UAAU;AAClD,KAAI,eAAe,UAAa,CAAC,iCAAiC,IAAI,WAAW,CAC/E,QAAO,IAAI,MAAM,IAAI;AAEvB,QAAO,IAAI;;;;;;;;;AAqBb,SAAgB,iBACd,KACA,UACA,aAC+D;CAC/D,MAAM,cAAc,wBAAwB,IAAI;CAChD,MAAM,2BAAW,IAAI,KAAuB;CAC5C,MAAMC,SAAoB,YAAY,KAAK,KAAK,MAAM;AACpD,WAAS,IAAI,KAAK,IAAI,EAAE;AACxB,SAAO,IAAI;GACX;CACF,MAAMC,MAAqB;EAAE;EAAU;EAAa;CAEpD,MAAM,OAAO;CACb,IAAIC;AACJ,SAAQ,KAAK,MAAb;EACE,KAAK;AACH,SAAM,aAAa,MAAM,UAAU,IAAI;AACvC;EACF,KAAK;AACH,SAAM,aAAa,MAAM,UAAU,IAAI;AACvC;EACF,KAAK;AACH,SAAM,aAAa,MAAM,UAAU,IAAI;AACvC;EACF,KAAK;AACH,SAAM,aAAa,MAAM,UAAU,IAAI;AACvC;EAEF,QACE,OAAM,IAAI,MACR,8BAA+B,KAA0C,OAC1E;;AAGL,QAAO,OAAO,OAAO;EAAE;EAAK,QAAQ,OAAO,OAAO,OAAO;EAAE,CAAC;;AAG9D,SAAS,aAAa,KAAgB,UAA4B,KAA4B;AAyC5F,QAbgB;EA3BK,UAAU,qBAAqB,IAAI,UAAU,IAAI,YAAY,UAAU,IAAI,GAAG,iBACjG,IAAI,YACJ,UACA,IACD;EACkB,QAAQ,aAAa,IAAI,MAAM,UAAU,IAAI;EAE5C,IAAI,OAAO,SAC3B,IAAI,MAAM,KAAK,SAAS,WAAW,MAAM,UAAU,IAAI,CAAC,CAAC,KAAK,IAAI,GAClE;EAEgB,IAAI,QAAQ,SAAS,YAAY,IAAI,OAAO,UAAU,IAAI,KAAK;EAC7D,IAAI,SAAS,SAC/B,YAAY,IAAI,QAAQ,KAAK,SAAS,WAAW,MAAM,UAAU,IAAI,CAAC,CAAC,KAAK,KAAK,KACjF;EACiB,IAAI,SAAS,UAAU,YAAY,IAAI,QAAQ,UAAU,IAAI,KAAK;EACnE,IAAI,SAAS,SAC7B,YAAY,IAAI,QACb,KAAK,UAAU;AAEd,UAAO,GADM,WAAW,MAAM,MAAM,UAAU,IAAI,CACnC,GAAG,MAAM,IAAI,aAAa;IACzC,CACD,KAAK,KAAK,KACb;EACgB,OAAO,IAAI,UAAU,WAAW,SAAS,IAAI,UAAU;EACtD,OAAO,IAAI,WAAW,WAAW,UAAU,IAAI,WAAW;EAY9E,CACE,QAAQ,SAAS,KAAK,SAAS,EAAE,CACjC,KAAK,IAAI,CACG,MAAM;;AAGvB,SAAS,iBACP,YACA,UACA,KACQ;AACR,QAAO,WACJ,KAAK,SAAS;EACb,MAAM,QAAQ,gBAAgB,KAAK,MAAM;AACzC,MAAI,KAAK,KAAK,SAAS,UACrB,QAAO,GAAG,cAAc,KAAK,KAAK,CAAC,MAAM;AAE3C,SAAO,GAAG,WAAW,KAAK,MAAM,UAAU,IAAI,CAAC,MAAM;GACrD,CACD,KAAK,KAAK;;AAGf,SAAS,gBACP,OACA,UACA,KACQ;AACR,QAAO,MACJ,KAAK,SAAS;AACb,MAAI,KAAK,KAAK,SAAS,cAAc;GACnC,MAAM,WAAW,aAAa,KAAK,KAAK;AACxC,UAAO,KAAK,KAAK,WAAW,KAAK,QAC7B,WACA,GAAG,SAAS,MAAM,gBAAgB,KAAK,MAAM;;AAEnD,MAAI,KAAK,KAAK,SAAS,UACrB,QAAO,GAAG,cAAc,KAAK,KAAK,CAAC,MAAM,gBAAgB,KAAK,MAAM;AAEtE,SAAO,GAAG,WAAW,KAAK,MAAM,UAAU,IAAI,CAAC,MAAM,gBAAgB,KAAK,MAAM;GAChF,CACD,KAAK,KAAK;;AAGf,SAAS,qBACP,UACA,YACA,UACA,KACQ;AACR,KAAI,cAAc,WAAW,SAAS,EAEpC,QAAO,gBADU,WAAW,KAAK,SAAS,WAAW,MAAM,UAAU,IAAI,CAAC,CAAC,KAAK,KAAK,CACrD;AAElC,KAAI,SACF,QAAO;AAET,QAAO;;AAGT,SAAS,aACP,QACA,UACA,KACQ;CACR,MAAM,OAAO;AACb,SAAQ,KAAK,MAAb;EACE,KAAK,gBAAgB;GACnB,MAAM,QAAQ,gBAAgB,KAAK,KAAK;AACxC,OAAI,CAAC,KAAK,MACR,QAAO;AAET,UAAO,GAAG,MAAM,MAAM,gBAAgB,KAAK,MAAM;;EAEnD,KAAK,uBACH,QAAO,IAAI,aAAa,KAAK,OAAO,UAAU,IAAI,CAAC,OAAO,gBAAgB,KAAK,MAAM;EAEvF,QACE,OAAM,IAAI,MACR,iCAAkC,KAA0C,OAC7E;;;AAIP,SAAS,qBAAqB,OAAwB;AACpD,KAAI,MAAM,WAAW,WAAW,EAC9B,OAAM,IAAI,MAAM,uDAAuD;;AAI3E,SAAS,mBACP,MACA,UACA,KACQ;AACR,sBAAqB,KAAK,MAAM;AAChC,QAAO,IAAI,aAAa,KAAK,OAAO,UAAU,IAAI,CAAC;;AAGrD,SAAS,YAAY,MAAqB,UAA4B,KAA4B;AAChG,QAAO,WAAW,MAAM,UAAU,IAAI;;AAGxC,SAAS,gBACP,MACA,UACA,KACQ;CACR,MAAM,WAAW,WAAW,KAAK,MAAM,UAAU,IAAI;CACrD,MAAM,eAAe,uBAAuB,KAAK,KAAK,KAAK,GAAG,WAAW,IAAI,SAAS;AACtF,QAAO,KAAK,SAAS,GAAG,aAAa,YAAY,GAAG,aAAa;;;;;;;;;;;;;AAcnE,SAAS,uBAAuB,MAAsC;AACpE,SAAQ,MAAR;EACE,KAAK;EACL,KAAK;EACL,KAAK;EACL,KAAK;EACL,KAAK;EACL,KAAK;EACL,KAAK;EACL,KAAK,OACH,QAAO;EACT,KAAK;EACL,KAAK;EACL,KAAK;EACL,KAAK;EACL,KAAK;EACL,KAAK;EACL,KAAK;EACL,KAAK,MACH,QAAO;;;AAIb,SAAS,aAAa,MAAkB,UAA4B,KAA4B;AAC9F,KAAI,KAAK,MAAM,SAAS,UAAU,KAAK,MAAM,OAAO,WAAW,GAAG;AAChE,MAAI,KAAK,OAAO,KACd,QAAO;AAET,MAAI,KAAK,OAAO,QACd,QAAO;;CAIX,MAAM,WAAW,KAAK;CACtB,MAAM,OAAO,WAAW,UAAU,UAAU,IAAI;CAChD,MAAM,eACJ,SAAS,SAAS,eAAe,SAAS,SAAS,aAAa,IAAI,KAAK,KAAK;CAEhF,MAAM,YAAY,KAAK;CACvB,IAAIC;AACJ,SAAQ,UAAU,MAAlB;EACE,KAAK;AACH,WAAQ,kBAAkB,WAAW,UAAU,IAAI;AACnD;EACF,KAAK;AACH,WAAQ,cAAc,UAAU;AAChC;EACF,KAAK;AACH,WAAQ,aAAa,UAAU;AAC/B;EACF,KAAK;AACH,WAAQ,eAAe,WAAW,IAAI;AACtC;EACF;AACE,WAAQ,WAAW,WAAW,UAAU,IAAI;AAC5C;;AAeJ,QAAO,GAAG,aAAa,GAZ+B;EACpD,IAAI;EACJ,KAAK;EACL,IAAI;EACJ,IAAI;EACJ,KAAK;EACL,KAAK;EACL,MAAM;EACN,IAAI;EACJ,OAAO;EACR,CAEqC,KAAK,IAAI,GAAG;;AAGpD,SAAS,kBACP,MACA,UACA,KACQ;AACR,KAAI,KAAK,OAAO,WAAW,EACzB,QAAO;AAST,QAAO,IAPQ,KAAK,OACjB,KAAK,MAAM;AACV,MAAI,EAAE,SAAS,YAAa,QAAO,eAAe,GAAG,IAAI;AACzD,MAAI,EAAE,SAAS,UAAW,QAAO,cAAc,EAAE;AACjD,SAAO,WAAW,GAAG,UAAU,IAAI;GACnC,CACD,KAAK,KAAK,CACK;;AAGpB,SAAS,aAAa,KAAwB;AAC5C,KAAI,IAAI,UAAU,WAChB,QAAO,YAAY,gBAAgB,IAAI,OAAO;AAEhD,QAAO,GAAG,gBAAgB,IAAI,MAAM,CAAC,GAAG,gBAAgB,IAAI,OAAO;;AAGrE,SAAS,oBACP,MACA,UACA,KACQ;CACR,MAAM,KAAK,KAAK,GAAG,aAAa;AAChC,KAAI,CAAC,KAAK,KACR,QAAO,GAAG,GAAG;AAEf,QAAO,GAAG,GAAG,GAAG,WAAW,KAAK,MAAM,UAAU,IAAI,CAAC;;AAGvD,SAAS,qBACP,MACA,UACA,KACQ;AAUR,QAAO,qBATM,KAAK,QACf,SAAS,UAA4B;EACpC,MAAM,MAAM,IAAI,cAAc,MAAM,IAAI,CAAC;AACzC,MAAI,MAAM,MAAM,SAAS,UACvB,QAAO,CAAC,KAAK,cAAc,MAAM,MAAM,CAAC;AAE1C,SAAO,CAAC,KAAK,WAAW,MAAM,OAAO,UAAU,IAAI,CAAC;GACpD,CACD,KAAK,KAAK,CACoB;;AAGnC,SAAS,mBACP,OACA,UACA,KACQ;AACR,QAAO,MACJ,KAAK,SAAS,GAAG,WAAW,KAAK,MAAM,UAAU,IAAI,CAAC,GAAG,KAAK,IAAI,aAAa,GAAG,CAClF,KAAK,KAAK;;AAGf,SAAS,uBACP,MACA,UACA,KACQ;CACR,MAAM,mBACJ,KAAK,WAAW,KAAK,QAAQ,SAAS,IAClC,aAAa,mBAAmB,KAAK,SAAS,UAAU,IAAI,KAC5D;CACN,MAAM,aAAa,YAAY,WAAW,KAAK,MAAM,UAAU,IAAI,GAAG,iBAAiB;AACvF,KAAI,KAAK,YAAY,aACnB,QAAO,YAAY,WAAW;AAEhC,QAAO;;AAGT,SAAS,WAAW,MAAqB,UAA4B,KAA4B;CAC/F,MAAM,OAAO;AACb,SAAQ,KAAK,MAAb;EACE,KAAK,aACH,QAAO,aAAa,KAAK;EAC3B,KAAK,iBACH,QAAO,gBAAgB,KAAK,KAAK;EACnC,KAAK,YACH,QAAO,gBAAgB,MAAM,UAAU,IAAI;EAC7C,KAAK,WACH,QAAO,mBAAmB,MAAM,UAAU,IAAI;EAChD,KAAK,YACH,QAAO,oBAAoB,MAAM,UAAU,IAAI;EACjD,KAAK,cACH,QAAO,qBAAqB,MAAM,UAAU,IAAI;EAClD,KAAK,iBACH,QAAO,uBAAuB,MAAM,UAAU,IAAI;EACpD,KAAK,SACH,QAAO,aAAa,MAAM,UAAU,IAAI;EAC1C,KAAK;AACH,OAAI,KAAK,MAAM,WAAW,EACxB,QAAO;AAET,UAAO,IAAI,KAAK,MAAM,KAAK,SAAS,WAAW,MAAM,UAAU,IAAI,CAAC,CAAC,KAAK,QAAQ,CAAC;EACrF,KAAK;AACH,OAAI,KAAK,MAAM,WAAW,EACxB,QAAO;AAET,UAAO,IAAI,KAAK,MAAM,KAAK,SAAS,WAAW,MAAM,UAAU,IAAI,CAAC,CAAC,KAAK,OAAO,CAAC;EACpF,KAAK,SAGH,QAAO,GAFY,KAAK,YAAY,SAAS,GAExB,UADJ,aAAa,KAAK,UAAU,UAAU,IAAI,CACnB;EAE1C,KAAK,aACH,QAAO,gBAAgB,MAAM,UAAU,IAAI;EAC7C,KAAK,MACH,QAAO,QAAQ,WAAW,KAAK,MAAM,UAAU,IAAI,CAAC;EACtD,KAAK,YACH,QAAO,eAAe,MAAM,IAAI;EAClC,KAAK,UACH,QAAO,cAAc,KAAK;EAC5B,KAAK,OACH,QAAO,kBAAkB,MAAM,UAAU,IAAI;EAE/C,QACE,OAAM,IAAI,MACR,qCAAsC,KAA0C,OACjF;;;AAIP,SAAS,eAAe,KAAe,KAA4B;CACjE,MAAM,QAAQ,IAAI,SAAS,IAAI,IAAI;AACnC,KAAI,UAAU,OACZ,OAAM,IAAI,MAAM,kCAAkC;AAEpD,QAAO,iBAAiB,OAAO,IAAI,SAAS,IAAI,YAAY;;AAG9D,SAAS,cAAc,MAA2B;AAChD,KAAI,OAAO,KAAK,UAAU,SACxB,QAAO,IAAI,cAAc,KAAK,MAAM,CAAC;AAEvC,KAAI,OAAO,KAAK,UAAU,YAAY,OAAO,KAAK,UAAU,UAC1D,QAAO,OAAO,KAAK,MAAM;AAE3B,KAAI,OAAO,KAAK,UAAU,SACxB,QAAO,OAAO,KAAK,MAAM;AAE3B,KAAI,KAAK,UAAU,KACjB,QAAO;AAET,KAAI,KAAK,UAAU,OACjB,QAAO;AAET,KAAI,KAAK,iBAAiB,KACxB,QAAO,IAAI,cAAc,KAAK,MAAM,aAAa,CAAC,CAAC;AAErD,KAAI,MAAM,QAAQ,KAAK,MAAM,CAC3B,QAAO,SAAS,KAAK,MAAM,KAAK,MAAe,cAAc,IAAI,YAAY,EAAE,CAAC,CAAC,CAAC,KAAK,KAAK,CAAC;CAE/F,MAAM,OAAO,KAAK,UAAU,KAAK,MAAM;AACvC,KAAI,SAAS,OACX,QAAO;AAET,QAAO,IAAI,cAAc,KAAK,CAAC;;AAGjC,SAAS,gBACP,MACA,UACA,KACQ;CACR,MAAM,OAAO,WAAW,KAAK,MAAM,UAAU,IAAI;CACjD,MAAM,OAAO,KAAK,KAAK,KAAK,QAAQ;AAClC,SAAO,WAAW,KAAK,UAAU,IAAI;GACrC;AAQF,QAAO,KAAK,SAAS,SAAS,QAC5B,mCACC,OAAO,aAAiC;AACvC,MAAI,UAAU,WACZ,QAAO;EAET,MAAM,MAAM,KAAK,OAAO,SAAS;AACjC,MAAI,QAAQ,OACV,OAAM,IAAI,MACR,oCAAoC,KAAK,OAAO,qCAAqC,SAAS,mBAAmB,KAAK,OAAO,SAC9H;AAEH,SAAO;GAEV;;AAGH,SAAS,WAAW,MAAe,UAA4B,KAA4B;AAKzF,QAAO,GAJU,KAAK,SAAS,aAAa,CAIzB,QAHH,KAAK,UAAU,aAAa,KAC7B,aAAa,KAAK,QAAQ,UAAU,IAAI,CAEX,MAD3B,aAAa,KAAK,IAAI,UAAU,IAAI;;AAIvD,SAAS,aAAa,IAAgB,UAA4B,KAA4B;AAC5F,KAAI,GAAG,SAAS,iBAGd,QAAO,GAFM,aAAa,GAAG,KAAK,CAEnB,KADD,aAAa,GAAG,MAAM;AAGtC,QAAO,YAAY,IAAI,UAAU,IAAI;;AAGvC,SAAS,qBACP,MACA,UACA,WACU;CACV,MAAMC,iBAA2B,EAAE;CACnC,MAAM,8BAAc,IAAI,KAAa;AAErC,MAAK,MAAM,OAAO,KAChB,MAAK,MAAM,UAAU,OAAO,KAAK,IAAI,EAAE;AACrC,MAAI,YAAY,IAAI,OAAO,CACzB;AAEF,cAAY,IAAI,OAAO;AACvB,iBAAe,KAAK,OAAO;;AAI/B,KAAI,eAAe,SAAS,EAC1B,QAAO;CAGT,MAAM,QAAQ,SAAS,QAAQ,OAAO;AACtC,KAAI,CAAC,MACH,OAAM,IAAI,MAAM,sDAAsD,YAAY;AAEpF,QAAO,OAAO,KAAK,MAAM,QAAQ;;AAGnC,SAAS,kBAAkB,OAAgC,KAA4B;AACrF,KAAI,CAAC,SAAS,MAAM,SAAS,gBAC3B,QAAO;AAGT,SAAQ,MAAM,MAAd;EACE,KAAK,YACH,QAAO,eAAe,OAAO,IAAI;EACnC,KAAK,aACH,QAAO,aAAa,MAAM;EAE5B,QACE,OAAM,IAAI,MACR,qCAAsC,MAA2C,OAClF;;;AAIP,SAAS,aAAa,KAAgB,UAA4B,KAA4B;CAC5F,MAAM,QAAQ,gBAAgB,IAAI,MAAM,KAAK;CAC7C,MAAM,OAAO,IAAI;AACjB,KAAI,KAAK,WAAW,EAClB,OAAM,IAAI,MAAM,mCAAmC;CAErD,MAAM,oBAAoB,KAAK,MAAM,QAAQ,OAAO,KAAK,IAAI,CAAC,SAAS,EAAE;AAmEzE,QAAO,UAlEqB;AAC1B,MAAI,CAAC,mBAAmB;AACtB,OAAI,KAAK,WAAW,EAClB,QAAO,eAAe,MAAM;GAG9B,MAAM,iBAAiB,qBAAqB,MAAM,UAAU,IAAI,MAAM,KAAK;AAC3E,OAAI,eAAe,WAAW,EAC5B,QAAO,eAAe,MAAM,UAAU,KAAK,UAAU,KAAK,CAAC,KAAK,KAAK;GAGvE,MAAM,gBAAgB,eAAe,KAAK,WAAW,gBAAgB,OAAO,CAAC;GAC7E,MAAM,aAAa,IAAI,eAAe,UAAU,UAAU,CAAC,KAAK,KAAK,CAAC;AACtE,UAAO,eAAe,MAAM,IAAI,cAAc,KAAK,KAAK,CAAC,WAAW,KACjE,UAAU,WAAW,CACrB,KAAK,KAAK;;EAGf,MAAM,cAAc,qBAAqB,MAAM,UAAU,IAAI,MAAM,KAAK;EACxE,MAAM,UAAU,YAAY,KAAK,WAAW,gBAAgB,OAAO,CAAC;EACpE,MAAM,SAAS,KACZ,KAAK,QAAQ;AAEZ,UAAO,IADa,YAAY,KAAK,WAAW,kBAAkB,IAAI,SAAS,IAAI,CAAC,CAC7D,KAAK,KAAK,CAAC;IAClC,CACD,KAAK,KAAK;AAEb,SAAO,eAAe,MAAM,IAAI,QAAQ,KAAK,KAAK,CAAC,WAAW;KAC5D,GACqB,IAAI,oBAClB;EACL,MAAM,kBAAkB,IAAI,WAAW,QAAQ,KAAK,QAAQ,gBAAgB,IAAI,OAAO,CAAC;AACxF,MAAI,gBAAgB,WAAW,EAC7B,OAAM,IAAI,MAAM,0DAA0D;EAG5E,MAAM,SAAS,IAAI,WAAW;AAC9B,UAAQ,OAAO,MAAf;GACE,KAAK,aACH,QAAO,iBAAiB,gBAAgB,KAAK,KAAK,CAAC;GACrD,KAAK,iBAAiB;IACpB,MAAM,gBAAgB,OAAO,QAAQ,OAAO,IAAI;AAChD,QAAI,cAAc,WAAW,EAC3B,OAAM,IAAI,MAAM,mEAAmE;IAErF,MAAM,UAAU,cAAc,KAAK,CAAC,SAAS,WAAW;KACtD,MAAM,SAAS,gBAAgB,QAAQ;AACvC,SAAI,MAAM,SAAS,YACjB,QAAO,GAAG,OAAO,KAAK,eAAe,OAAO,IAAI;AAElD,YAAO,GAAG,OAAO,KAAK,aAAa,MAAM;MACzC;AACF,WAAO,iBAAiB,gBAAgB,KAAK,KAAK,CAAC,kBAAkB,QAAQ,KAAK,KAAK;;GAGzF,QACE,OAAM,IAAI,MACR,kCAAmC,OAA4C,OAChF;;KAEH,GACJ,KACoB,IAAI,WAAW,SACnC,cAAc,gBAAgB,IAAI,WAAW,UAAU,IAAI,KAC3D;;AAKN,SAAS,aAAa,KAAgB,UAA4B,KAA4B;CAC5F,MAAM,QAAQ,gBAAgB,IAAI,MAAM,KAAK;CAC7C,MAAM,aAAa,OAAO,QAAQ,IAAI,IAAI;AAC1C,KAAI,WAAW,WAAW,EACxB,OAAM,IAAI,MAAM,8CAA8C;CAEhE,MAAM,aAAa,WAAW,KAAK,CAAC,KAAK,SAAS;EAChD,MAAM,SAAS,gBAAgB,IAAI;EACnC,IAAIC;AACJ,UAAQ,IAAI,MAAZ;GACE,KAAK;AACH,YAAQ,eAAe,KAAK,IAAI;AAChC;GACF,KAAK;AACH,YAAQ,aAAa,IAAI;AACzB;GAEF,QACE,OAAM,IAAI,MACR,qCAAsC,IAAyC,OAChF;;AAEL,SAAO,GAAG,OAAO,KAAK;GACtB;CAEF,MAAM,cAAc,IAAI,QAAQ,UAAU,YAAY,IAAI,OAAO,UAAU,IAAI,KAAK;CACpF,MAAM,kBAAkB,IAAI,WAAW,SACnC,cAAc,gBAAgB,IAAI,WAAW,UAAU,IAAI,KAC3D;AAEJ,QAAO,UAAU,MAAM,OAAO,WAAW,KAAK,KAAK,GAAG,cAAc;;AAGtE,SAAS,aAAa,KAAgB,UAA4B,KAA4B;AAO5F,QAAO,eANO,gBAAgB,IAAI,MAAM,KAAK,GACzB,IAAI,QAAQ,UAAU,YAAY,IAAI,OAAO,UAAU,IAAI,KAAK,KAC5D,IAAI,WAAW,SACnC,cAAc,gBAAgB,IAAI,WAAW,UAAU,IAAI,KAC3D"}