@prisma-next/adapter-postgres 0.12.0-dev.5 → 0.12.0-dev.50
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +13 -20
- package/dist/{adapter-H8BiuXdq.mjs → adapter-BI6bq3e0.mjs} +13 -13
- package/dist/adapter-BI6bq3e0.mjs.map +1 -0
- package/dist/adapter.d.mts +2 -1
- package/dist/adapter.d.mts.map +1 -1
- package/dist/adapter.mjs +1 -1
- package/dist/control-adapter-1Yv2bsSN.mjs +1357 -0
- package/dist/control-adapter-1Yv2bsSN.mjs.map +1 -0
- package/dist/control.d.mts +60 -10
- package/dist/control.d.mts.map +1 -1
- package/dist/control.mjs +3 -659
- package/dist/control.mjs.map +1 -1
- package/dist/runtime.d.mts +1 -1
- package/dist/runtime.mjs +1 -1
- package/package.json +22 -22
- package/src/core/adapter.ts +28 -25
- package/src/core/control-adapter.ts +380 -105
- package/src/core/ddl-renderer.ts +73 -0
- package/src/core/enum-control-hooks.ts +2 -2
- package/src/core/marker-ledger.ts +124 -0
- package/src/core/sql-renderer.ts +66 -23
- package/dist/adapter-H8BiuXdq.mjs.map +0 -1
- package/dist/sql-renderer-DlZhVI9B.mjs +0 -457
- package/dist/sql-renderer-DlZhVI9B.mjs.map +0 -1
package/README.md
CHANGED
|
@@ -20,7 +20,7 @@ Provide PostgreSQL-specific adapter implementation, codecs, and capabilities. En
|
|
|
20
20
|
|
|
21
21
|
- **Adapter Implementation**: Implement `Adapter` SPI for PostgreSQL
|
|
22
22
|
- Lower SQL ASTs to PostgreSQL dialect SQL
|
|
23
|
-
- Render
|
|
23
|
+
- Render JSON aggregation (`json_agg`, `json_build_object`) and scalar subqueries
|
|
24
24
|
- Advertise PostgreSQL capabilities (`lateral`, `jsonAgg`)
|
|
25
25
|
- Normalize PostgreSQL EXPLAIN output
|
|
26
26
|
- Map PostgreSQL errors to `RuntimeError` envelope
|
|
@@ -89,8 +89,8 @@ flowchart TD
|
|
|
89
89
|
**Adapter (`adapter.ts`)**
|
|
90
90
|
- Main adapter implementation
|
|
91
91
|
- Lowers SQL ASTs to PostgreSQL SQL
|
|
92
|
-
- Renders joins (INNER, LEFT, RIGHT, FULL) with ON conditions
|
|
93
|
-
- Renders
|
|
92
|
+
- Renders joins (INNER, LEFT, RIGHT, FULL, LATERAL) with ON conditions
|
|
93
|
+
- Renders JSON aggregation (`json_agg`, `json_build_object`) and scalar subqueries
|
|
94
94
|
- Renders DML operations (INSERT, UPDATE, DELETE) with RETURNING clauses
|
|
95
95
|
- Advertises PostgreSQL capabilities (`lateral`, `jsonAgg`, `returning`)
|
|
96
96
|
- Maps PostgreSQL errors to `RuntimeError`
|
|
@@ -191,8 +191,8 @@ The adapter declares the following PostgreSQL capabilities:
|
|
|
191
191
|
|
|
192
192
|
- **`orderBy: true`** - Supports ORDER BY clauses
|
|
193
193
|
- **`limit: true`** - Supports LIMIT clauses
|
|
194
|
-
- **`lateral: true`** - Supports LATERAL joins
|
|
195
|
-
- **`jsonAgg: true`** - Supports JSON aggregation functions (`json_agg`)
|
|
194
|
+
- **`lateral: true`** - Supports LATERAL joins
|
|
195
|
+
- **`jsonAgg: true`** - Supports JSON aggregation functions (`json_agg`)
|
|
196
196
|
- **`returning: true`** - Supports RETURNING clauses for DML operations (INSERT, UPDATE, DELETE)
|
|
197
197
|
- **`sql.enums: true`** - Supports contract-defined enum storage types
|
|
198
198
|
|
|
@@ -205,29 +205,22 @@ The capabilities on the descriptor must match the capabilities in code. If they
|
|
|
205
205
|
|
|
206
206
|
See `docs/reference/capabilities.md` and `docs/architecture docs/subsystems/5. Adapters & Targets.md` for details.
|
|
207
207
|
|
|
208
|
-
##
|
|
208
|
+
## JSON Aggregation
|
|
209
209
|
|
|
210
|
-
The
|
|
210
|
+
The renderer lowers JSON-aggregation AST nodes to PostgreSQL's `json_agg`:
|
|
211
211
|
|
|
212
|
-
|
|
213
|
-
-
|
|
214
|
-
-
|
|
215
|
-
- When both `ORDER BY` and `LIMIT` are present, wraps the query in an inner SELECT that projects individual columns with aliases, then uses `json_agg(row_to_json(sub.*))` on the result
|
|
216
|
-
- Uses different aliases for the table (`{alias}_lateral`) and column (`{alias}`) to avoid ambiguity
|
|
217
|
-
|
|
218
|
-
**Capabilities Required:**
|
|
219
|
-
- `lateral: true` - Enables LATERAL join support
|
|
220
|
-
- `jsonAgg: true` - Enables `json_agg` function support
|
|
212
|
+
- `json_agg(json_build_object(...))` aggregates a row set into a JSON array of objects
|
|
213
|
+
- A scalar subquery (`SubqueryExpr`) in the SELECT list correlates against the outer row through its WHERE clause
|
|
214
|
+
- When the subquery carries an inner `ORDER BY` and `LIMIT`, its rows are wrapped in an inner SELECT, then aggregated with `json_agg(row_to_json(sub.*))`
|
|
221
215
|
|
|
222
216
|
**Example SQL Output:**
|
|
223
217
|
```sql
|
|
224
|
-
SELECT "user"."id" AS "id",
|
|
225
|
-
FROM "user"
|
|
226
|
-
LEFT JOIN LATERAL (
|
|
218
|
+
SELECT "user"."id" AS "id", (
|
|
227
219
|
SELECT json_agg(json_build_object('id', "post"."id", 'title', "post"."title")) AS "posts"
|
|
228
220
|
FROM "post"
|
|
229
221
|
WHERE "user"."id" = "post"."userId"
|
|
230
|
-
) AS "
|
|
222
|
+
) AS "posts"
|
|
223
|
+
FROM "user"
|
|
231
224
|
```
|
|
232
225
|
|
|
233
226
|
## DML Operations with RETURNING
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { i as createPostgresBuiltinCodecLookup, n as renderLoweredSql, r as renderLoweredDdl, t as PostgresControlAdapter } from "./control-adapter-1Yv2bsSN.mjs";
|
|
2
2
|
import { APP_SPACE_ID } from "@prisma-next/framework-components/control";
|
|
3
|
-
import {
|
|
3
|
+
import { isDdlNode } from "@prisma-next/sql-relational-core/ast";
|
|
4
4
|
//#region src/core/adapter.ts
|
|
5
5
|
const defaultCapabilities = Object.freeze({
|
|
6
6
|
postgres: {
|
|
@@ -25,14 +25,23 @@ var PostgresAdapterImpl = class {
|
|
|
25
25
|
codecLookup;
|
|
26
26
|
constructor(options) {
|
|
27
27
|
this.codecLookup = options?.codecLookup ?? createPostgresBuiltinCodecLookup();
|
|
28
|
+
const controlAdapter = new PostgresControlAdapter(this.codecLookup);
|
|
28
29
|
this.profile = Object.freeze({
|
|
29
30
|
id: options?.profileId ?? "postgres/default@1",
|
|
30
31
|
target: "postgres",
|
|
31
32
|
capabilities: defaultCapabilities,
|
|
32
|
-
readMarker: (queryable) =>
|
|
33
|
+
readMarker: (queryable) => controlAdapter.readMarkerDiscriminated({
|
|
34
|
+
familyId: "sql",
|
|
35
|
+
targetId: "postgres",
|
|
36
|
+
query: async (sql, params) => {
|
|
37
|
+
return { rows: [...(await queryable.query(sql, params)).rows] };
|
|
38
|
+
},
|
|
39
|
+
close: async () => {}
|
|
40
|
+
}, APP_SPACE_ID)
|
|
33
41
|
});
|
|
34
42
|
}
|
|
35
43
|
lower(ast, context) {
|
|
44
|
+
if (isDdlNode(ast)) return renderLoweredDdl(ast);
|
|
36
45
|
return renderLoweredSql(ast, context.contract, this.codecLookup);
|
|
37
46
|
}
|
|
38
47
|
};
|
|
@@ -47,19 +56,10 @@ const postgresRawCodecInferer = { inferCodec(value) {
|
|
|
47
56
|
}
|
|
48
57
|
throw new Error("unsupported JS value type for raw-SQL interpolation: wrap this value in `param(...)` with an explicit codec");
|
|
49
58
|
} };
|
|
50
|
-
async function readPostgresMarker(queryable) {
|
|
51
|
-
if ((await queryable.query("select 1 from information_schema.tables where table_schema = $1 and table_name = $2", ["prisma_contract", "marker"])).rows.length === 0) return { kind: "no-table" };
|
|
52
|
-
const row = (await queryable.query("select core_hash, profile_hash, contract_json, canonical_version, updated_at, app_tag, meta, invariants from prisma_contract.marker where space = $1", [APP_SPACE_ID])).rows[0];
|
|
53
|
-
if (!row) return { kind: "absent" };
|
|
54
|
-
return {
|
|
55
|
-
kind: "present",
|
|
56
|
-
record: parseContractMarkerRow(row)
|
|
57
|
-
};
|
|
58
|
-
}
|
|
59
59
|
function createPostgresAdapter(options) {
|
|
60
60
|
return Object.freeze(new PostgresAdapterImpl(options));
|
|
61
61
|
}
|
|
62
62
|
//#endregion
|
|
63
63
|
export { postgresRawCodecInferer as n, createPostgresAdapter as t };
|
|
64
64
|
|
|
65
|
-
//# sourceMappingURL=adapter-
|
|
65
|
+
//# sourceMappingURL=adapter-BI6bq3e0.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"adapter-BI6bq3e0.mjs","names":[],"sources":["../src/core/adapter.ts"],"sourcesContent":["import type { CodecLookup } 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 { renderLoweredDdl } from './ddl-renderer';\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 },\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: CodecLookup;\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 return renderLoweredDdl(ast);\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":";;;;AAmBA,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;CACX;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,GAC3B,IAAI,EAAE;IAClC;IACA,OAAO,YAAY,CAAC;GACtB,GACA,YACF;EACJ,CAAC;CACH;CAEA,MACE,KACA,SAC0B;EAC1B,IAAI,UAAU,GAAG,GACf,OAAO,iBAAiB,GAAG;EAE7B,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,6 +1,7 @@
|
|
|
1
1
|
import { c as PostgresContract, l as PostgresLoweredStatement, s as PostgresAdapterOptions } from "./types-B1eiuBHQ.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
|
+
import { PostgresDdlNode } from "@prisma-next/target-postgres/ddl";
|
|
4
5
|
|
|
5
6
|
//#region src/core/adapter.d.ts
|
|
6
7
|
declare class PostgresAdapterImpl implements Adapter<AnyQueryAst, PostgresContract, PostgresLoweredStatement> {
|
|
@@ -9,7 +10,7 @@ declare class PostgresAdapterImpl implements Adapter<AnyQueryAst, PostgresContra
|
|
|
9
10
|
readonly profile: AdapterProfile<'postgres'>;
|
|
10
11
|
private readonly codecLookup;
|
|
11
12
|
constructor(options?: PostgresAdapterOptions);
|
|
12
|
-
lower(ast: AnyQueryAst, context: LowererContext<PostgresContract>): PostgresLoweredStatement;
|
|
13
|
+
lower(ast: AnyQueryAst | PostgresDdlNode, context: LowererContext<PostgresContract>): PostgresLoweredStatement;
|
|
13
14
|
}
|
|
14
15
|
/** Codec-id lookup for bare-literal interpolations used by `fns.raw` on a postgres client. Contributed as the descriptor's static `rawCodecInferer` slot. */
|
|
15
16
|
declare const postgresRawCodecInferer: RawCodecInferer;
|
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;;cASQ,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-BI6bq3e0.mjs";
|
|
2
2
|
export { createPostgresAdapter, postgresRawCodecInferer };
|