@prisma-next/sql-relational-core 0.13.0-dev.4 → 0.13.0-dev.40
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/{ddl-types-D3vlEjMA.d.mts → ddl-types-BVO002FS.d.mts} +6 -2
- package/dist/ddl-types-BVO002FS.d.mts.map +1 -0
- package/dist/{ddl-types-X9_XHUl0.mjs → ddl-types-DAox2c8w.mjs} +4 -1
- package/dist/ddl-types-DAox2c8w.mjs.map +1 -0
- package/dist/{errors-CPLfzKkw.d.mts → errors-BbatEYjA.d.mts} +2 -2
- package/dist/{errors-CPLfzKkw.d.mts.map → errors-BbatEYjA.d.mts.map} +1 -1
- package/dist/exports/ast.d.mts +11 -3
- package/dist/exports/ast.d.mts.map +1 -1
- package/dist/exports/ast.mjs +3 -3
- package/dist/exports/codec-descriptor-registry.d.mts.map +1 -1
- package/dist/exports/codec-descriptor-registry.mjs +2 -13
- package/dist/exports/codec-descriptor-registry.mjs.map +1 -1
- package/dist/exports/contract-free.d.mts +60 -3
- package/dist/exports/contract-free.d.mts.map +1 -1
- package/dist/exports/contract-free.mjs +123 -3
- package/dist/exports/contract-free.mjs.map +1 -1
- package/dist/exports/errors.d.mts +1 -1
- package/dist/exports/expression.d.mts +1 -1
- package/dist/exports/expression.mjs +1 -1
- package/dist/exports/middleware.d.mts +1 -1
- package/dist/exports/plan.d.mts +2 -2
- package/dist/exports/types.d.mts +3 -3
- package/dist/index.d.mts +9 -9
- package/dist/index.mjs +3 -3
- package/dist/{middleware-BXSFukKU.d.mts → middleware-Dyyo4IP1.d.mts} +2 -2
- package/dist/{middleware-BXSFukKU.d.mts.map → middleware-Dyyo4IP1.d.mts.map} +1 -1
- package/dist/{plan-DObuWSWi.d.mts → plan-DUjdGLY3.d.mts} +2 -2
- package/dist/{plan-DObuWSWi.d.mts.map → plan-DUjdGLY3.d.mts.map} +1 -1
- package/dist/{sql-execution-plan-JwVeAzXt.d.mts → sql-execution-plan-DjMEAjKK.d.mts} +2 -2
- package/dist/{sql-execution-plan-JwVeAzXt.d.mts.map → sql-execution-plan-DjMEAjKK.d.mts.map} +1 -1
- package/dist/types-BQ_zfC-S.d.mts +233 -0
- package/dist/types-BQ_zfC-S.d.mts.map +1 -0
- package/dist/{types-LGikJRYV.d.mts → types-CUHnDsdV.d.mts} +3 -3
- package/dist/{types-LGikJRYV.d.mts.map → types-CUHnDsdV.d.mts.map} +1 -1
- package/dist/{types-BbGUx5Bi.d.mts → types-DQrmgP8Y.d.mts} +17 -5
- package/dist/{types-BbGUx5Bi.d.mts.map → types-DQrmgP8Y.d.mts.map} +1 -1
- package/dist/{types-D72v8s92.mjs → types-lJUc6cY-.mjs} +78 -18
- package/dist/types-lJUc6cY-.mjs.map +1 -0
- package/package.json +11 -11
- package/src/ast/ddl-types.ts +5 -0
- package/src/ast/driver-types.ts +8 -0
- package/src/ast/types.ts +98 -19
- package/src/codec-ref-for-column.ts +2 -35
- package/src/contract-free/column.ts +2 -0
- package/src/contract-free/dml.ts +5 -0
- package/src/contract-free/table.ts +191 -1
- package/src/exports/contract-free.ts +5 -0
- package/src/types.ts +134 -22
- package/dist/ddl-types-D3vlEjMA.d.mts.map +0 -1
- package/dist/ddl-types-X9_XHUl0.mjs.map +0 -1
- package/dist/types-CQVke4QO.d.mts +0 -181
- package/dist/types-CQVke4QO.d.mts.map +0 -1
- package/dist/types-D72v8s92.mjs.map +0 -1
package/src/ast/ddl-types.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import type { ColumnDefaultLiteralInputValue } from '@prisma-next/contract/types';
|
|
2
2
|
import { isColumnDefaultLiteralInputValue } from '@prisma-next/contract/types';
|
|
3
3
|
import type { ReferentialAction } from '@prisma-next/sql-contract/types';
|
|
4
|
+
import type { CodecRef } from './codec-types';
|
|
4
5
|
import type { AnyParamRef } from './types';
|
|
5
6
|
|
|
6
7
|
/**
|
|
@@ -71,6 +72,8 @@ export class DdlColumn {
|
|
|
71
72
|
readonly notNull?: boolean | undefined;
|
|
72
73
|
readonly primaryKey?: boolean | undefined;
|
|
73
74
|
readonly default?: AnyDdlColumnDefault | undefined;
|
|
75
|
+
/** Codec identity for this column. When present, the DDL walker resolves the codec via `codecLookup.get(codecRef.codecId)` and calls `codec.encode(default.value, {})` to obtain the wire value before inlining the literal default into the DDL string. When absent, literal defaults follow RawSqlLiteral wire-scalar semantics (string / number / boolean / bigint / null / Uint8Array / Date inlined directly). */
|
|
76
|
+
readonly codecRef?: CodecRef | undefined;
|
|
74
77
|
|
|
75
78
|
constructor(options: {
|
|
76
79
|
readonly name: string;
|
|
@@ -78,12 +81,14 @@ export class DdlColumn {
|
|
|
78
81
|
readonly notNull?: boolean;
|
|
79
82
|
readonly primaryKey?: boolean;
|
|
80
83
|
readonly default?: AnyDdlColumnDefault;
|
|
84
|
+
readonly codecRef?: CodecRef;
|
|
81
85
|
}) {
|
|
82
86
|
this.name = options.name;
|
|
83
87
|
this.type = options.type;
|
|
84
88
|
this.notNull = options.notNull;
|
|
85
89
|
this.primaryKey = options.primaryKey;
|
|
86
90
|
this.default = options.default;
|
|
91
|
+
this.codecRef = options.codecRef;
|
|
87
92
|
Object.freeze(this);
|
|
88
93
|
}
|
|
89
94
|
}
|
package/src/ast/driver-types.ts
CHANGED
|
@@ -1,3 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A fully lowered SQL statement ready for a driver to execute: SQL text plus
|
|
3
|
+
* driver-ready (codec-encoded) parameter values. The output of the control
|
|
4
|
+
* adapter's `lowerToExecuteRequest`, handed to a driver via `SqlQueryable.query`
|
|
5
|
+
* or `execute`. Inline-substituted positions (e.g. DDL `DEFAULT`
|
|
6
|
+
* clauses) carry no param; `params` holds the wire values for the `$N`/`?`
|
|
7
|
+
* positions, in order.
|
|
8
|
+
*/
|
|
1
9
|
export interface SqlExecuteRequest {
|
|
2
10
|
readonly sql: string;
|
|
3
11
|
readonly params?: readonly unknown[];
|
package/src/ast/types.ts
CHANGED
|
@@ -378,6 +378,35 @@ export class DerivedTableSource extends FromSource {
|
|
|
378
378
|
}
|
|
379
379
|
}
|
|
380
380
|
|
|
381
|
+
export class FunctionSource extends FromSource {
|
|
382
|
+
readonly kind = 'function-source' as const;
|
|
383
|
+
readonly fn: string;
|
|
384
|
+
readonly args: ReadonlyArray<AnyExpression>;
|
|
385
|
+
readonly alias: string | undefined;
|
|
386
|
+
|
|
387
|
+
protected constructor(fn: string, args: ReadonlyArray<AnyExpression>, alias?: string) {
|
|
388
|
+
super();
|
|
389
|
+
this.fn = fn;
|
|
390
|
+
this.args = frozenArrayCopy(args);
|
|
391
|
+
this.alias = alias;
|
|
392
|
+
this.freeze();
|
|
393
|
+
}
|
|
394
|
+
|
|
395
|
+
static of(fn: string, args: ReadonlyArray<AnyExpression>, alias?: string): FunctionSource {
|
|
396
|
+
return new FunctionSource(fn, args, alias);
|
|
397
|
+
}
|
|
398
|
+
|
|
399
|
+
override rewrite(rewriter: AstRewriter): AnyFromSource {
|
|
400
|
+
const rewrittenArgs = this.args.map((arg) => rewriteComparable(arg, rewriter));
|
|
401
|
+
if (rewrittenArgs.every((arg, i) => arg === this.args[i])) return this;
|
|
402
|
+
return new FunctionSource(this.fn, rewrittenArgs, this.alias);
|
|
403
|
+
}
|
|
404
|
+
|
|
405
|
+
override toFromSource(): AnyFromSource {
|
|
406
|
+
return this;
|
|
407
|
+
}
|
|
408
|
+
}
|
|
409
|
+
|
|
381
410
|
export class ColumnRef extends Expression {
|
|
382
411
|
readonly kind = 'column-ref' as const;
|
|
383
412
|
readonly table: string;
|
|
@@ -1299,7 +1328,7 @@ export class ProjectionItem extends AstNode {
|
|
|
1299
1328
|
export type LimitOffsetValue = number | AnyExpression;
|
|
1300
1329
|
|
|
1301
1330
|
export interface SelectAstOptions {
|
|
1302
|
-
readonly from
|
|
1331
|
+
readonly from?: AnyFromSource;
|
|
1303
1332
|
readonly joins: ReadonlyArray<JoinAst> | undefined;
|
|
1304
1333
|
readonly projection: ReadonlyArray<ProjectionItem>;
|
|
1305
1334
|
readonly where: AnyExpression | undefined;
|
|
@@ -1315,7 +1344,7 @@ export interface SelectAstOptions {
|
|
|
1315
1344
|
|
|
1316
1345
|
export class SelectAst extends QueryAst {
|
|
1317
1346
|
readonly kind = 'select' as const;
|
|
1318
|
-
readonly from: AnyFromSource;
|
|
1347
|
+
readonly from: AnyFromSource | undefined;
|
|
1319
1348
|
readonly joins: ReadonlyArray<JoinAst> | undefined;
|
|
1320
1349
|
readonly projection: ReadonlyArray<ProjectionItem>;
|
|
1321
1350
|
readonly where: AnyExpression | undefined;
|
|
@@ -1368,79 +1397,113 @@ export class SelectAst extends QueryAst {
|
|
|
1368
1397
|
});
|
|
1369
1398
|
}
|
|
1370
1399
|
|
|
1400
|
+
static noFrom(): SelectAst {
|
|
1401
|
+
return new SelectAst({
|
|
1402
|
+
joins: undefined,
|
|
1403
|
+
projection: [],
|
|
1404
|
+
where: undefined,
|
|
1405
|
+
orderBy: undefined,
|
|
1406
|
+
distinct: undefined,
|
|
1407
|
+
distinctOn: undefined,
|
|
1408
|
+
groupBy: undefined,
|
|
1409
|
+
having: undefined,
|
|
1410
|
+
limit: undefined,
|
|
1411
|
+
offset: undefined,
|
|
1412
|
+
selectAllIntent: undefined,
|
|
1413
|
+
});
|
|
1414
|
+
}
|
|
1415
|
+
|
|
1416
|
+
private toOptions(): SelectAstOptions {
|
|
1417
|
+
return {
|
|
1418
|
+
...(this.from !== undefined ? { from: this.from } : {}),
|
|
1419
|
+
joins: this.joins,
|
|
1420
|
+
projection: this.projection,
|
|
1421
|
+
where: this.where,
|
|
1422
|
+
orderBy: this.orderBy,
|
|
1423
|
+
distinct: this.distinct,
|
|
1424
|
+
distinctOn: this.distinctOn,
|
|
1425
|
+
groupBy: this.groupBy,
|
|
1426
|
+
having: this.having,
|
|
1427
|
+
limit: this.limit,
|
|
1428
|
+
offset: this.offset,
|
|
1429
|
+
selectAllIntent: this.selectAllIntent,
|
|
1430
|
+
};
|
|
1431
|
+
}
|
|
1432
|
+
|
|
1371
1433
|
withFrom(from: AnyFromSource): SelectAst {
|
|
1372
|
-
return new SelectAst({ ...this, from });
|
|
1434
|
+
return new SelectAst({ ...this.toOptions(), from });
|
|
1373
1435
|
}
|
|
1374
1436
|
|
|
1375
1437
|
withJoins(joins: ReadonlyArray<JoinAst>): SelectAst {
|
|
1376
1438
|
return new SelectAst({
|
|
1377
|
-
...this,
|
|
1439
|
+
...this.toOptions(),
|
|
1378
1440
|
joins: joins.length > 0 ? joins : undefined,
|
|
1379
1441
|
});
|
|
1380
1442
|
}
|
|
1381
1443
|
|
|
1382
1444
|
withProjection(projection: ReadonlyArray<ProjectionItem>): SelectAst {
|
|
1383
|
-
return new SelectAst({ ...this, projection });
|
|
1445
|
+
return new SelectAst({ ...this.toOptions(), projection });
|
|
1384
1446
|
}
|
|
1385
1447
|
|
|
1386
1448
|
addProjection(alias: string, expr: ProjectionExpr): SelectAst {
|
|
1387
1449
|
return new SelectAst({
|
|
1388
|
-
...this,
|
|
1450
|
+
...this.toOptions(),
|
|
1389
1451
|
projection: [...this.projection, new ProjectionItem(alias, expr)],
|
|
1390
1452
|
});
|
|
1391
1453
|
}
|
|
1392
1454
|
|
|
1393
1455
|
withWhere(where: AnyExpression | undefined): SelectAst {
|
|
1394
|
-
return new SelectAst({ ...this, where });
|
|
1456
|
+
return new SelectAst({ ...this.toOptions(), where });
|
|
1395
1457
|
}
|
|
1396
1458
|
|
|
1397
1459
|
withOrderBy(orderBy: ReadonlyArray<OrderByItem>): SelectAst {
|
|
1398
1460
|
return new SelectAst({
|
|
1399
|
-
...this,
|
|
1461
|
+
...this.toOptions(),
|
|
1400
1462
|
orderBy: orderBy.length > 0 ? orderBy : undefined,
|
|
1401
1463
|
});
|
|
1402
1464
|
}
|
|
1403
1465
|
|
|
1404
1466
|
withDistinct(enabled = true): SelectAst {
|
|
1405
1467
|
return new SelectAst({
|
|
1406
|
-
...this,
|
|
1468
|
+
...this.toOptions(),
|
|
1407
1469
|
distinct: enabled ? true : undefined,
|
|
1408
1470
|
});
|
|
1409
1471
|
}
|
|
1410
1472
|
|
|
1411
1473
|
withDistinctOn(distinctOn: ReadonlyArray<AnyExpression>): SelectAst {
|
|
1412
1474
|
return new SelectAst({
|
|
1413
|
-
...this,
|
|
1475
|
+
...this.toOptions(),
|
|
1414
1476
|
distinctOn: distinctOn.length > 0 ? distinctOn : undefined,
|
|
1415
1477
|
});
|
|
1416
1478
|
}
|
|
1417
1479
|
|
|
1418
1480
|
withGroupBy(groupBy: ReadonlyArray<AnyExpression>): SelectAst {
|
|
1419
1481
|
return new SelectAst({
|
|
1420
|
-
...this,
|
|
1482
|
+
...this.toOptions(),
|
|
1421
1483
|
groupBy: groupBy.length > 0 ? groupBy : undefined,
|
|
1422
1484
|
});
|
|
1423
1485
|
}
|
|
1424
1486
|
|
|
1425
1487
|
withHaving(having: AnyExpression | undefined): SelectAst {
|
|
1426
|
-
return new SelectAst({ ...this, having });
|
|
1488
|
+
return new SelectAst({ ...this.toOptions(), having });
|
|
1427
1489
|
}
|
|
1428
1490
|
|
|
1429
1491
|
withLimit(limit: LimitOffsetValue | undefined): SelectAst {
|
|
1430
|
-
return new SelectAst({ ...this, limit });
|
|
1492
|
+
return new SelectAst({ ...this.toOptions(), limit });
|
|
1431
1493
|
}
|
|
1432
1494
|
|
|
1433
1495
|
withOffset(offset: LimitOffsetValue | undefined): SelectAst {
|
|
1434
|
-
return new SelectAst({ ...this, offset });
|
|
1496
|
+
return new SelectAst({ ...this.toOptions(), offset });
|
|
1435
1497
|
}
|
|
1436
1498
|
|
|
1437
1499
|
withSelectAllIntent(selectAllIntent: { readonly table?: string } | undefined): SelectAst {
|
|
1438
|
-
return new SelectAst({ ...this, selectAllIntent });
|
|
1500
|
+
return new SelectAst({ ...this.toOptions(), selectAllIntent });
|
|
1439
1501
|
}
|
|
1440
1502
|
|
|
1441
1503
|
rewrite(rewriter: AstRewriter): SelectAst {
|
|
1504
|
+
const rewrittenFrom = this.from?.rewrite(rewriter);
|
|
1442
1505
|
const rewritten = new SelectAst({
|
|
1443
|
-
from:
|
|
1506
|
+
...(rewrittenFrom !== undefined ? { from: rewrittenFrom } : {}),
|
|
1444
1507
|
joins: this.joins?.map((join) => join.rewrite(rewriter)),
|
|
1445
1508
|
projection: this.projection.map(
|
|
1446
1509
|
(projection) =>
|
|
@@ -1474,8 +1537,12 @@ export class SelectAst extends QueryAst {
|
|
|
1474
1537
|
refs.push(...columns);
|
|
1475
1538
|
};
|
|
1476
1539
|
|
|
1477
|
-
if (this.from
|
|
1540
|
+
if (this.from?.kind === 'derived-table-source') {
|
|
1478
1541
|
pushRefs(this.from.query.collectColumnRefs());
|
|
1542
|
+
} else if (this.from?.kind === 'function-source') {
|
|
1543
|
+
for (const arg of this.from.args) {
|
|
1544
|
+
pushRefs(arg.collectColumnRefs());
|
|
1545
|
+
}
|
|
1479
1546
|
}
|
|
1480
1547
|
|
|
1481
1548
|
for (const projection of this.projection) {
|
|
@@ -1502,6 +1569,10 @@ export class SelectAst extends QueryAst {
|
|
|
1502
1569
|
for (const join of this.joins ?? []) {
|
|
1503
1570
|
if (join.source.kind === 'derived-table-source') {
|
|
1504
1571
|
pushRefs(join.source.query.collectColumnRefs());
|
|
1572
|
+
} else if (join.source.kind === 'function-source') {
|
|
1573
|
+
for (const arg of join.source.args) {
|
|
1574
|
+
pushRefs(arg.collectColumnRefs());
|
|
1575
|
+
}
|
|
1505
1576
|
}
|
|
1506
1577
|
if (join.on.kind === 'eq-col-join-on') {
|
|
1507
1578
|
refs.push(join.on.left, join.on.right);
|
|
@@ -1525,8 +1596,12 @@ export class SelectAst extends QueryAst {
|
|
|
1525
1596
|
refs.push(...params);
|
|
1526
1597
|
};
|
|
1527
1598
|
|
|
1528
|
-
if (this.from
|
|
1599
|
+
if (this.from?.kind === 'derived-table-source') {
|
|
1529
1600
|
pushRefs(this.from.query.collectParamRefs());
|
|
1601
|
+
} else if (this.from?.kind === 'function-source') {
|
|
1602
|
+
for (const arg of this.from.args) {
|
|
1603
|
+
pushRefs(arg.collectParamRefs());
|
|
1604
|
+
}
|
|
1530
1605
|
}
|
|
1531
1606
|
|
|
1532
1607
|
for (const projection of this.projection) {
|
|
@@ -1553,6 +1628,10 @@ export class SelectAst extends QueryAst {
|
|
|
1553
1628
|
for (const join of this.joins ?? []) {
|
|
1554
1629
|
if (join.source.kind === 'derived-table-source') {
|
|
1555
1630
|
pushRefs(join.source.query.collectParamRefs());
|
|
1631
|
+
} else if (join.source.kind === 'function-source') {
|
|
1632
|
+
for (const arg of join.source.args) {
|
|
1633
|
+
pushRefs(arg.collectParamRefs());
|
|
1634
|
+
}
|
|
1556
1635
|
}
|
|
1557
1636
|
if (!(join.on.kind === 'eq-col-join-on')) {
|
|
1558
1637
|
pushRefs(join.on.collectParamRefs());
|
|
@@ -1899,7 +1978,7 @@ export class RawSqlExpr extends QueryAst {
|
|
|
1899
1978
|
}
|
|
1900
1979
|
|
|
1901
1980
|
export type AnyQueryAst = SelectAst | InsertAst | UpdateAst | DeleteAst | RawSqlExpr;
|
|
1902
|
-
export type AnyFromSource = TableSource | DerivedTableSource;
|
|
1981
|
+
export type AnyFromSource = TableSource | DerivedTableSource | FunctionSource;
|
|
1903
1982
|
export type AnyExpression =
|
|
1904
1983
|
| ColumnRef
|
|
1905
1984
|
| IdentifierRef
|
|
@@ -1,11 +1,7 @@
|
|
|
1
1
|
import type { JsonValue } from '@prisma-next/contract/types';
|
|
2
2
|
import type { CodecRef } from '@prisma-next/framework-components/codec';
|
|
3
3
|
import { resolveStorageTable } from '@prisma-next/sql-contract/resolve-storage-table';
|
|
4
|
-
import {
|
|
5
|
-
isPostgresEnumStorageEntry,
|
|
6
|
-
isStorageTypeInstance,
|
|
7
|
-
type SqlStorage,
|
|
8
|
-
} from '@prisma-next/sql-contract/types';
|
|
4
|
+
import { isStorageTypeInstance, type SqlStorage } from '@prisma-next/sql-contract/types';
|
|
9
5
|
|
|
10
6
|
/**
|
|
11
7
|
* Derive the canonical {@link CodecRef} for a `(table, column)` pair against a {@link SqlStorage}. This is the build-time path every column-bound `ParamRef` / `ProjectionItem` uses to stamp its `codec` slot before the AST is handed to the runtime — the runtime resolver then materialises a memoised {@link import('@prisma-next/sql-relational-core/ast').Codec} for the same `CodecRef` via `forCodecRef`.
|
|
@@ -34,38 +30,9 @@ export function codecRefForStorageColumn(
|
|
|
34
30
|
const columnDef = tableDef.columns[columnName];
|
|
35
31
|
if (!columnDef) return undefined;
|
|
36
32
|
if (columnDef.typeRef !== undefined) {
|
|
37
|
-
|
|
38
|
-
if (!instance) {
|
|
39
|
-
for (const ns of Object.values(storage.namespaces)) {
|
|
40
|
-
const typeSlot = (ns.entries as { type?: Record<string, unknown> }).type;
|
|
41
|
-
const nsEntry = typeSlot?.[columnDef.typeRef];
|
|
42
|
-
if (nsEntry !== undefined) {
|
|
43
|
-
instance = nsEntry;
|
|
44
|
-
break;
|
|
45
|
-
}
|
|
46
|
-
}
|
|
47
|
-
}
|
|
33
|
+
const instance = storage.types?.[columnDef.typeRef];
|
|
48
34
|
if (!instance) return undefined;
|
|
49
|
-
if (isPostgresEnumStorageEntry(instance)) {
|
|
50
|
-
// Canonical path: the entry is a live `PostgresEnumType` IR
|
|
51
|
-
// instance reached through the per-target serializer's
|
|
52
|
-
// hydration. Raw JSON envelopes carrying `kind: 'postgres-enum'`
|
|
53
|
-
// never reach this site — `SqlStorage.normaliseTypeEntry`
|
|
54
|
-
// rejects them upstream (F09). Read `codecId` and `values` off
|
|
55
|
-
// the structural shape (enumerable own properties on the live
|
|
56
|
-
// instance) so the dispatch stays layered against the family
|
|
57
|
-
// alphabet rather than a target-specific class import.
|
|
58
|
-
return {
|
|
59
|
-
codecId: instance.codecId,
|
|
60
|
-
typeParams: { values: instance.values } as unknown as JsonValue,
|
|
61
|
-
};
|
|
62
|
-
}
|
|
63
35
|
if (isStorageTypeInstance(instance)) {
|
|
64
|
-
// Empty-state canonicalization: a `StorageTypeInstance` with absent
|
|
65
|
-
// (or empty) `typeParams` produces a `CodecRef` with no `typeParams`
|
|
66
|
-
// field. Equivalent to the non-parameterized-column branch below.
|
|
67
|
-
// Carrying `{}` here would break content-keyed memoisation and trip
|
|
68
|
-
// the runtime validator against non-parameterized codec descriptors.
|
|
69
36
|
const instanceParams = instance.typeParams;
|
|
70
37
|
const hasParamKeys = instanceParams !== undefined && Object.keys(instanceParams).length > 0;
|
|
71
38
|
return hasParamKeys
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { ColumnDefaultLiteralInputValue } from '@prisma-next/contract/types';
|
|
2
2
|
import type { ReferentialAction } from '@prisma-next/sql-contract/types';
|
|
3
|
+
import type { CodecRef } from '../ast/codec-types';
|
|
3
4
|
import type { AnyDdlColumnDefault } from '../ast/ddl-types';
|
|
4
5
|
import {
|
|
5
6
|
DdlColumn,
|
|
@@ -14,6 +15,7 @@ export interface DdlColumnOptions {
|
|
|
14
15
|
readonly notNull?: boolean;
|
|
15
16
|
readonly primaryKey?: boolean;
|
|
16
17
|
readonly default?: AnyDdlColumnDefault;
|
|
18
|
+
readonly codecRef?: CodecRef;
|
|
17
19
|
}
|
|
18
20
|
|
|
19
21
|
export function lit(value: ColumnDefaultLiteralInputValue): LiteralColumnDefault {
|
package/src/contract-free/dml.ts
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
export {
|
|
2
2
|
CfConflictClause,
|
|
3
3
|
CfExpr,
|
|
4
|
+
CfExprSelectQuery,
|
|
5
|
+
type CfFnOptions,
|
|
4
6
|
CfInsertQuery,
|
|
5
7
|
CfSelectQuery,
|
|
6
8
|
CfUpdateQuery,
|
|
@@ -9,7 +11,10 @@ export {
|
|
|
9
11
|
type ColumnDescriptor,
|
|
10
12
|
type ColumnProxy,
|
|
11
13
|
type ColumnSchema,
|
|
14
|
+
cfExpr,
|
|
15
|
+
cfTable,
|
|
12
16
|
type ExcludedProxy,
|
|
17
|
+
exprSelect,
|
|
13
18
|
type TableHandle,
|
|
14
19
|
type TableInsertRow,
|
|
15
20
|
type TableSetValues,
|
|
@@ -1,19 +1,28 @@
|
|
|
1
|
+
import type { ParamSpec } from '@prisma-next/operations';
|
|
1
2
|
import { blindCast } from '@prisma-next/utils/casts';
|
|
2
3
|
import {
|
|
4
|
+
AggregateExpr,
|
|
3
5
|
AndExpr,
|
|
4
6
|
type AnyExpression,
|
|
7
|
+
type AnyFromSource,
|
|
5
8
|
BinaryExpr,
|
|
6
9
|
ColumnRef,
|
|
10
|
+
ExistsExpr,
|
|
11
|
+
IdentifierRef,
|
|
7
12
|
InsertAst,
|
|
8
13
|
InsertOnConflict,
|
|
9
14
|
type InsertValue,
|
|
15
|
+
JoinAst,
|
|
16
|
+
LiteralExpr,
|
|
10
17
|
NullCheckExpr,
|
|
18
|
+
OperationExpr,
|
|
11
19
|
OrderByItem,
|
|
12
20
|
OrExpr,
|
|
13
21
|
ParamRef,
|
|
14
22
|
ProjectionItem,
|
|
23
|
+
RawExpr,
|
|
15
24
|
SelectAst,
|
|
16
|
-
|
|
25
|
+
TableSource,
|
|
17
26
|
UpdateAst,
|
|
18
27
|
} from '../ast/types';
|
|
19
28
|
|
|
@@ -43,6 +52,187 @@ export class CfExpr {
|
|
|
43
52
|
not(): CfExpr {
|
|
44
53
|
return new CfExpr(this.ast.not());
|
|
45
54
|
}
|
|
55
|
+
|
|
56
|
+
isNull(): CfExpr {
|
|
57
|
+
return new CfExpr(NullCheckExpr.isNull(this.ast));
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
isNotNull(): CfExpr {
|
|
61
|
+
return new CfExpr(NullCheckExpr.isNotNull(this.ast));
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
eqLit(value: number | string | boolean): CfExpr {
|
|
65
|
+
return new CfExpr(BinaryExpr.eq(this.ast, LiteralExpr.of(value)));
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
gtLit(value: number | string | boolean): CfExpr {
|
|
69
|
+
return new CfExpr(BinaryExpr.gt(this.ast, LiteralExpr.of(value)));
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
eqParam(value: unknown, codecId: string): CfExpr {
|
|
73
|
+
return new CfExpr(BinaryExpr.eq(this.ast, ParamRef.of(value, { codec: { codecId } })));
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
eqExpr(other: CfExpr): CfExpr {
|
|
77
|
+
return new CfExpr(BinaryExpr.eq(this.ast, other.ast));
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
export interface CfFnOptions {
|
|
82
|
+
readonly method: string;
|
|
83
|
+
readonly template: string;
|
|
84
|
+
readonly self: CfExpr;
|
|
85
|
+
readonly args?: ReadonlyArray<CfExpr>;
|
|
86
|
+
readonly returns: ParamSpec;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
export const cfExpr = {
|
|
90
|
+
countStar(): CfExpr {
|
|
91
|
+
return new CfExpr(AggregateExpr.count());
|
|
92
|
+
},
|
|
93
|
+
lit(value: number | string | boolean): CfExpr {
|
|
94
|
+
return new CfExpr(LiteralExpr.of(value));
|
|
95
|
+
},
|
|
96
|
+
identifierRef(name: string): CfExpr {
|
|
97
|
+
return new CfExpr(IdentifierRef.of(name));
|
|
98
|
+
},
|
|
99
|
+
param(value: unknown, codecId: string): CfExpr {
|
|
100
|
+
return new CfExpr(ParamRef.of(value, { codec: { codecId } }));
|
|
101
|
+
},
|
|
102
|
+
/**
|
|
103
|
+
* Catalog function call lowered via a `'function'`-strategy template
|
|
104
|
+
* (e.g. `to_regclass({{self}})`). Owns the `OperationExpr` assembly so
|
|
105
|
+
* target packages only supply vocabulary: template, codec'd operands,
|
|
106
|
+
* and return spec.
|
|
107
|
+
*/
|
|
108
|
+
fn(options: CfFnOptions): CfExpr {
|
|
109
|
+
return new CfExpr(
|
|
110
|
+
new OperationExpr({
|
|
111
|
+
method: options.method,
|
|
112
|
+
self: options.self.ast,
|
|
113
|
+
args: options.args?.map((arg) => arg.ast),
|
|
114
|
+
returns: options.returns,
|
|
115
|
+
lowering: {
|
|
116
|
+
targetFamily: 'sql',
|
|
117
|
+
strategy: 'function',
|
|
118
|
+
template: options.template,
|
|
119
|
+
},
|
|
120
|
+
}),
|
|
121
|
+
);
|
|
122
|
+
},
|
|
123
|
+
columnRef(qualifier: string, name: string): CfExpr {
|
|
124
|
+
return new CfExpr(ColumnRef.of(qualifier, name));
|
|
125
|
+
},
|
|
126
|
+
allOf(exprs: ReadonlyArray<CfExpr>): CfExpr {
|
|
127
|
+
return new CfExpr(AndExpr.of(exprs.map((expr) => expr.ast)));
|
|
128
|
+
},
|
|
129
|
+
/**
|
|
130
|
+
* Opaque DB-side SQL expression (e.g. `current_schema()`) carried as a
|
|
131
|
+
* `RawExpr`. For zero-operand catalog functions where a `'function'`
|
|
132
|
+
* lowering template has nothing to substitute.
|
|
133
|
+
*/
|
|
134
|
+
raw(sql: string, returns: ParamSpec): CfExpr {
|
|
135
|
+
return new CfExpr(new RawExpr({ parts: [sql], returns }));
|
|
136
|
+
},
|
|
137
|
+
exists(query: CfExprSelectQuery): CfExpr {
|
|
138
|
+
return new CfExpr(ExistsExpr.exists(query.build()));
|
|
139
|
+
},
|
|
140
|
+
notExists(query: CfExprSelectQuery): CfExpr {
|
|
141
|
+
return new CfExpr(ExistsExpr.notExists(query.build()));
|
|
142
|
+
},
|
|
143
|
+
};
|
|
144
|
+
|
|
145
|
+
/** Aliased table source for catalog queries (no namespace coordinate). */
|
|
146
|
+
export function cfTable(name: string, alias?: string): TableSource {
|
|
147
|
+
return TableSource.named(name, alias);
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
export class CfExprSelectQuery {
|
|
151
|
+
constructor(
|
|
152
|
+
private readonly src: AnyFromSource | undefined,
|
|
153
|
+
private readonly projectionItems: ReadonlyArray<ProjectionItem>,
|
|
154
|
+
private readonly whereExpr: CfExpr | undefined,
|
|
155
|
+
private readonly joinItems: ReadonlyArray<JoinAst> = [],
|
|
156
|
+
private readonly limitValue: number | undefined = undefined,
|
|
157
|
+
) {}
|
|
158
|
+
|
|
159
|
+
from(source: AnyFromSource): CfExprSelectQuery {
|
|
160
|
+
return new CfExprSelectQuery(
|
|
161
|
+
source,
|
|
162
|
+
this.projectionItems,
|
|
163
|
+
this.whereExpr,
|
|
164
|
+
this.joinItems,
|
|
165
|
+
this.limitValue,
|
|
166
|
+
);
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
join(source: AnyFromSource, on: CfExpr): CfExprSelectQuery {
|
|
170
|
+
return new CfExprSelectQuery(
|
|
171
|
+
this.src,
|
|
172
|
+
this.projectionItems,
|
|
173
|
+
this.whereExpr,
|
|
174
|
+
[...this.joinItems, JoinAst.inner(source, on.ast)],
|
|
175
|
+
this.limitValue,
|
|
176
|
+
);
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
leftJoin(source: AnyFromSource, on: CfExpr): CfExprSelectQuery {
|
|
180
|
+
return new CfExprSelectQuery(
|
|
181
|
+
this.src,
|
|
182
|
+
this.projectionItems,
|
|
183
|
+
this.whereExpr,
|
|
184
|
+
[...this.joinItems, JoinAst.left(source, on.ast)],
|
|
185
|
+
this.limitValue,
|
|
186
|
+
);
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
project(alias: string, expr: CfExpr): CfExprSelectQuery {
|
|
190
|
+
return new CfExprSelectQuery(
|
|
191
|
+
this.src,
|
|
192
|
+
[...this.projectionItems, ProjectionItem.of(alias, expr.ast)],
|
|
193
|
+
this.whereExpr,
|
|
194
|
+
this.joinItems,
|
|
195
|
+
this.limitValue,
|
|
196
|
+
);
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
where(expr: CfExpr): CfExprSelectQuery {
|
|
200
|
+
return new CfExprSelectQuery(
|
|
201
|
+
this.src,
|
|
202
|
+
this.projectionItems,
|
|
203
|
+
expr,
|
|
204
|
+
this.joinItems,
|
|
205
|
+
this.limitValue,
|
|
206
|
+
);
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
limit(value: number): CfExprSelectQuery {
|
|
210
|
+
return new CfExprSelectQuery(
|
|
211
|
+
this.src,
|
|
212
|
+
this.projectionItems,
|
|
213
|
+
this.whereExpr,
|
|
214
|
+
this.joinItems,
|
|
215
|
+
value,
|
|
216
|
+
);
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
build(): SelectAst {
|
|
220
|
+
if (this.joinItems.length > 0 && this.src === undefined) {
|
|
221
|
+
throw new Error('CfExprSelectQuery: cannot add a JOIN without a FROM clause');
|
|
222
|
+
}
|
|
223
|
+
const base =
|
|
224
|
+
this.src !== undefined
|
|
225
|
+
? SelectAst.from(this.src).withProjection(this.projectionItems)
|
|
226
|
+
: SelectAst.noFrom().withProjection(this.projectionItems);
|
|
227
|
+
const withJoins = this.joinItems.length > 0 ? base.withJoins(this.joinItems) : base;
|
|
228
|
+
const withWhere =
|
|
229
|
+
this.whereExpr !== undefined ? withJoins.withWhere(this.whereExpr.ast) : withJoins;
|
|
230
|
+
return this.limitValue !== undefined ? withWhere.withLimit(this.limitValue) : withWhere;
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
export function exprSelect(): CfExprSelectQuery {
|
|
235
|
+
return new CfExprSelectQuery(undefined, [], undefined);
|
|
46
236
|
}
|
|
47
237
|
|
|
48
238
|
/**
|
|
@@ -10,6 +10,8 @@ export {
|
|
|
10
10
|
export {
|
|
11
11
|
CfConflictClause,
|
|
12
12
|
CfExpr,
|
|
13
|
+
CfExprSelectQuery,
|
|
14
|
+
type CfFnOptions,
|
|
13
15
|
CfInsertQuery,
|
|
14
16
|
CfSelectQuery,
|
|
15
17
|
CfUpdateQuery,
|
|
@@ -18,7 +20,10 @@ export {
|
|
|
18
20
|
type ColumnDescriptor,
|
|
19
21
|
type ColumnProxy,
|
|
20
22
|
type ColumnSchema,
|
|
23
|
+
cfExpr,
|
|
24
|
+
cfTable,
|
|
21
25
|
type ExcludedProxy,
|
|
26
|
+
exprSelect,
|
|
22
27
|
type TableHandle,
|
|
23
28
|
type TableInsertRow,
|
|
24
29
|
type TableSetValues,
|