turbine-orm 0.51.0 → 0.52.0
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 +33 -5
- package/dist/cjs/cli/studio-ui.generated.js +1 -1
- package/dist/cjs/client.d.ts +106 -2
- package/dist/cjs/client.js +111 -5
- package/dist/cjs/dialect.d.ts +33 -0
- package/dist/cjs/dialect.js +14 -0
- package/dist/cjs/engine-config.d.ts +49 -0
- package/dist/cjs/engine-config.js +19 -0
- package/dist/cjs/index-advisor.js +0 -0
- package/dist/cjs/index.d.ts +1 -1
- package/dist/cjs/index.js +3 -2
- package/dist/cjs/mssql.d.ts +8 -3
- package/dist/cjs/mssql.js +22 -3
- package/dist/cjs/mysql.d.ts +7 -3
- package/dist/cjs/mysql.js +20 -3
- package/dist/cjs/nested-write.d.ts +31 -0
- package/dist/cjs/nested-write.js +80 -2
- package/dist/cjs/powdb-introspect.d.ts +10 -1
- package/dist/cjs/powdb-introspect.js +10 -1
- package/dist/cjs/powdb.d.ts +116 -6
- package/dist/cjs/powdb.js +169 -10
- package/dist/cjs/powql.d.ts +161 -1
- package/dist/cjs/powql.js +299 -19
- package/dist/cjs/prisma-compat.d.ts +54 -8
- package/dist/cjs/prisma-compat.js +136 -20
- package/dist/cjs/query/batched-loader.d.ts +7 -0
- package/dist/cjs/query/batched-loader.js +97 -15
- package/dist/cjs/query/builder.d.ts +131 -5
- package/dist/cjs/query/builder.js +223 -19
- package/dist/cjs/query/compound-unique.js +0 -0
- package/dist/cjs/query/index.d.ts +1 -1
- package/dist/cjs/query/index.js +2 -1
- package/dist/cjs/query/warn-registry.d.ts +10 -0
- package/dist/cjs/query/warn-registry.js +10 -0
- package/dist/cjs/query/writes.js +115 -7
- package/dist/cjs/sqlite.d.ts +10 -4
- package/dist/cjs/sqlite.js +18 -4
- package/dist/cli/studio-ui.generated.js +1 -1
- package/dist/client.d.ts +106 -2
- package/dist/client.js +111 -5
- package/dist/dialect.d.ts +33 -0
- package/dist/dialect.js +14 -0
- package/dist/engine-config.d.ts +49 -0
- package/dist/engine-config.js +18 -0
- package/dist/index-advisor.js +0 -0
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/dist/mssql.d.ts +8 -3
- package/dist/mssql.js +22 -3
- package/dist/mysql.d.ts +7 -3
- package/dist/mysql.js +20 -3
- package/dist/nested-write.d.ts +31 -0
- package/dist/nested-write.js +79 -2
- package/dist/powdb-introspect.d.ts +10 -1
- package/dist/powdb-introspect.js +10 -1
- package/dist/powdb.d.ts +116 -6
- package/dist/powdb.js +167 -9
- package/dist/powql.d.ts +161 -1
- package/dist/powql.js +299 -19
- package/dist/prisma-compat.d.ts +54 -8
- package/dist/prisma-compat.js +136 -20
- package/dist/query/batched-loader.d.ts +7 -0
- package/dist/query/batched-loader.js +98 -16
- package/dist/query/builder.d.ts +131 -5
- package/dist/query/builder.js +222 -18
- package/dist/query/compound-unique.js +0 -0
- package/dist/query/index.d.ts +1 -1
- package/dist/query/index.js +1 -1
- package/dist/query/warn-registry.d.ts +10 -0
- package/dist/query/warn-registry.js +10 -0
- package/dist/query/writes.js +116 -8
- package/dist/sqlite.d.ts +10 -4
- package/dist/sqlite.js +19 -5
- package/package.json +3 -3
package/dist/cjs/powql.d.ts
CHANGED
|
@@ -38,6 +38,18 @@ import { type PowdbPool } from './powdb.js';
|
|
|
38
38
|
import type { MiddlewareFn, QueryInterfaceOptions } from './query/index.js';
|
|
39
39
|
import type { AggregateArgs, AggregateResult, CountArgs, CreateArgs, CreateManyArgs, DeleteArgs, DeleteManyArgs, FindManyArgs, FindUniqueArgs, GroupByArgs, UpdateArgs, UpdateManyArgs, UpsertArgs } from './query/types.js';
|
|
40
40
|
import { type SchemaMetadata } from './schema.js';
|
|
41
|
+
/**
|
|
42
|
+
* Max values one `in` / `notIn` on a PowDB-native `datetime` column may carry.
|
|
43
|
+
*
|
|
44
|
+
* Such a list is never sent as a list: it is expanded into an equality chain
|
|
45
|
+
* (see {@link PowqlInterface.buildDatetimeInList}), and PowQL spends one level
|
|
46
|
+
* of its 64-level nesting budget per chain term. Measured on the 0.20.0 addon:
|
|
47
|
+
* 63 terms parse at the top level, 61 one level deep, whatever else the
|
|
48
|
+
* predicate contains. 32 leaves room for the surrounding filter, and is also the
|
|
49
|
+
* key-chunk size the relation loaders use for a datetime correlation column, so
|
|
50
|
+
* a loader can never build a chain the engine will reject.
|
|
51
|
+
*/
|
|
52
|
+
export declare const MAX_POWQL_DATETIME_TERMS = 32;
|
|
41
53
|
/**
|
|
42
54
|
* The PowQL query interface. Constructed by `turbinePowDB` via the
|
|
43
55
|
* `queryInterfaceFactory` seam and cast to `QueryInterface<object>` so
|
|
@@ -95,6 +107,25 @@ export declare class PowqlInterface<T extends object = Record<string, unknown>>
|
|
|
95
107
|
* default so a hand-built test pool never crashes the version gates.
|
|
96
108
|
*/
|
|
97
109
|
private get capabilities();
|
|
110
|
+
/**
|
|
111
|
+
* The `limit` a query actually emits: the explicit `limit`, Prisma's `take`
|
|
112
|
+
* alias, then the client-level `defaultLimit`. Shared by {@link buildFind} and
|
|
113
|
+
* the {@link findMany} zero short-circuit so the two can never disagree about
|
|
114
|
+
* which limit is in force.
|
|
115
|
+
*/
|
|
116
|
+
private effectiveLimit;
|
|
117
|
+
/**
|
|
118
|
+
* Reject a negative `limit` / `offset` before it reaches the engine. PowDB
|
|
119
|
+
* casts both with `as usize` at execution, so below engine 0.20 a negative
|
|
120
|
+
* limit wrapped to `usize::MAX` and silently returned EVERY row, the opposite
|
|
121
|
+
* of what the caller asked for; 0.20 refuses it. Validating client-side makes
|
|
122
|
+
* the refusal identical on every engine version and names the argument.
|
|
123
|
+
*
|
|
124
|
+
* `limit: 0` is legal and means "no rows" (SQL `LIMIT 0`). It is not emitted:
|
|
125
|
+
* callers short-circuit it, because PowDB's projection fast path returned ONE
|
|
126
|
+
* row for `limit 0` below 0.20.
|
|
127
|
+
*/
|
|
128
|
+
private assertPagination;
|
|
98
129
|
/** A predicate that is always false, the empty-`in` / contradiction sentinel. */
|
|
99
130
|
private alwaysFalse;
|
|
100
131
|
/**
|
|
@@ -109,6 +140,37 @@ export declare class PowqlInterface<T extends object = Record<string, unknown>>
|
|
|
109
140
|
* throws, so an unresolved relation filter can never leak into a join.
|
|
110
141
|
*/
|
|
111
142
|
private buildWhere;
|
|
143
|
+
/**
|
|
144
|
+
* Gate a predicate on a PowDB-native `datetime` column. Turbine binds a JS
|
|
145
|
+
* `Date` as an integer count of microseconds, and PowDB writes a timestamp
|
|
146
|
+
* literal as a plain integer, so every such predicate is a `DateTime` vs `Int`
|
|
147
|
+
* comparison. Below engine 0.20 that pairing was unhandled and fell back to
|
|
148
|
+
* comparing TYPE TAGS, so `>` matched every non-null row, `=` and `<` matched
|
|
149
|
+
* none, and the answer additionally changed with the column's access path
|
|
150
|
+
* (indexed vs scanned). 0.20 compares microseconds and every binary operator
|
|
151
|
+
* (`=`, `!=`, `<`, `<=`, `>`, `>=`) is correct.
|
|
152
|
+
*
|
|
153
|
+
* ONE gate covers the whole family, whatever spelling the caller used. `in` /
|
|
154
|
+
* `not in` are included because their still-broken LIST form is never emitted:
|
|
155
|
+
* {@link buildInList} expands a datetime list into the equality chain the
|
|
156
|
+
* engine does answer correctly, which is the same binary comparison this flag
|
|
157
|
+
* governs. So on >= 0.20 every path is served (direct predicates, relation
|
|
158
|
+
* filters, the batched loaders, nested projections, native joins, and the
|
|
159
|
+
* findUnique / update / delete / upsert by-key paths), and below 0.20 every
|
|
160
|
+
* path that compares against a literal is refused with one message, which
|
|
161
|
+
* names the read paths that do not.
|
|
162
|
+
*
|
|
163
|
+
* `is null` / `is not null` are never gated: they compare no literal and are
|
|
164
|
+
* correct on every version. Ordering, grouping and `min`/`max` are likewise
|
|
165
|
+
* unaffected (they compare datetimes against each other, never against an int),
|
|
166
|
+
* as are nested-projection and join correlations, which are column-to-column.
|
|
167
|
+
*
|
|
168
|
+
* Only PowDB's native `datetime` type is affected. Turbine's own DDL emits
|
|
169
|
+
* `int` epoch micros for a `Date` column, so a Turbine-provisioned database
|
|
170
|
+
* never reaches this: the exposed shape is a table created outside Turbine and
|
|
171
|
+
* read through `introspectPowdbDatabase`, or hand-written metadata.
|
|
172
|
+
*/
|
|
173
|
+
private assertDatetimePredicateSupported;
|
|
112
174
|
/** Build a single `field: value | operator` condition. */
|
|
113
175
|
private buildFieldCondition;
|
|
114
176
|
/**
|
|
@@ -153,8 +215,60 @@ export declare class PowqlInterface<T extends object = Record<string, unknown>>
|
|
|
153
215
|
private bind;
|
|
154
216
|
/** Bind a LIKE pattern (already escaped), lowercasing for insensitive mode. */
|
|
155
217
|
private bindLike;
|
|
156
|
-
/**
|
|
218
|
+
/**
|
|
219
|
+
* `lhs [not] in ($1, $2, …)`, empty list collapses to a constant.
|
|
220
|
+
*
|
|
221
|
+
* A PowDB-native `datetime` column takes the expanded form instead (see
|
|
222
|
+
* {@link buildDatetimeInList}): its `in` list is still broken upstream at 0.20.
|
|
223
|
+
*/
|
|
157
224
|
private buildInList;
|
|
225
|
+
/**
|
|
226
|
+
* `in` / `not in` on a PowDB-native `datetime` column, expanded into the
|
|
227
|
+
* equality chain the engine answers correctly:
|
|
228
|
+
*
|
|
229
|
+
* `in` → `(.ts = $1 or .ts = $2 …)`
|
|
230
|
+
* `notIn` → `(.ts != $1 and .ts != $2 … and .ts is not null)`
|
|
231
|
+
*
|
|
232
|
+
* PowQL's LIST form compares a datetime column against integer timestamp
|
|
233
|
+
* literals by TYPE TAG as of engine 0.20 (the 0.20 timestamp fix covered the
|
|
234
|
+
* binary operators only): measured on the 0.20.0 addon, `filter .ts in
|
|
235
|
+
* (<micros>, …)` matches nothing and `not in` matches everything, while the
|
|
236
|
+
* identical lists against an `int` control column answer correctly. The
|
|
237
|
+
* expanded chain uses the operators 0.20 DID fix, so it answers correctly and
|
|
238
|
+
* matches the int control exactly.
|
|
239
|
+
*
|
|
240
|
+
* This is what keeps the relation family coherent: relation filters and the
|
|
241
|
+
* batched loaders both compile to a key `in` list, so without the rewrite the
|
|
242
|
+
* same relation was refused through one strategy and served through another
|
|
243
|
+
* (nested projections and joins correlate column to column and never emit a
|
|
244
|
+
* list at all).
|
|
245
|
+
*
|
|
246
|
+
* The cost is the chain's width. PowQL bounds the SHAPE of the predicate tree,
|
|
247
|
+
* and a flat `or` / `and` chain spends one level per term against the same
|
|
248
|
+
* 64-level budget as nested parens (measured on 0.20: 63 terms at the top
|
|
249
|
+
* level, 61 one level deep), so the expansion is capped at
|
|
250
|
+
* {@link MAX_POWQL_DATETIME_TERMS} with headroom for whatever predicate it
|
|
251
|
+
* sits inside. The loaders chunk their key lists to that cap, so only a
|
|
252
|
+
* caller-written list (or a relation filter matching very many distinct
|
|
253
|
+
* timestamps) can exceed it, and that raises a typed E017 saying so rather
|
|
254
|
+
* than an engine parse failure.
|
|
255
|
+
*/
|
|
256
|
+
private buildDatetimeInList;
|
|
257
|
+
/**
|
|
258
|
+
* A literal `ref in (…)` clause for the hand-built key lists the relation
|
|
259
|
+
* loaders emit (they bypass {@link buildWhere}). Routes a PowDB-native
|
|
260
|
+
* `datetime` key column through the same equality-chain expansion the
|
|
261
|
+
* where-builder uses, so a datetime junction / correlation key behaves
|
|
262
|
+
* identically however the statement was assembled.
|
|
263
|
+
*/
|
|
264
|
+
private inClause;
|
|
265
|
+
/**
|
|
266
|
+
* Key-chunk size for a relation loader. A PowDB-native `datetime` correlation
|
|
267
|
+
* column's `in` list is expanded into an equality chain, which PowQL's nesting
|
|
268
|
+
* budget bounds, so those keys chunk at {@link MAX_POWQL_DATETIME_TERMS}
|
|
269
|
+
* (more, smaller round-trips) instead of {@link MAX_RELATION_KEYS}.
|
|
270
|
+
*/
|
|
271
|
+
private keyChunkSize;
|
|
158
272
|
/**
|
|
159
273
|
* Pre-resolve every relation filter (`some`/`none`/`every`) in a where clause
|
|
160
274
|
* into a plain scalar `in`/`notIn` condition on the **local key**, by running
|
|
@@ -421,6 +535,10 @@ export declare class PowqlInterface<T extends object = Record<string, unknown>>
|
|
|
421
535
|
* - m2m (the block takes exactly one child table; the junction-order
|
|
422
536
|
* stitch has no nested equivalent), and composite relation keys;
|
|
423
537
|
* - a to-one relation carrying `limit`/`offset` (the loaders' semantics);
|
|
538
|
+
* - a relation `limit` of exactly 0 (a nested block would emit `limit 0`,
|
|
539
|
+
* which PowDB's projection fast path answered with ONE row below engine
|
|
540
|
+
* 0.20; the loader path resolves it client-side and is correct on every
|
|
541
|
+
* version). A NEGATIVE relation limit is refused outright, not fallen back;
|
|
424
542
|
* - `distinct` inside the relation options (no nested grammar for it);
|
|
425
543
|
* - a projected child column whose tsType is `bigint` or `Uint8Array`
|
|
426
544
|
* (values ride a JSON array, which cannot carry them losslessly);
|
|
@@ -520,6 +638,27 @@ export declare class PowqlInterface<T extends object = Record<string, unknown>>
|
|
|
520
638
|
*/
|
|
521
639
|
private get qt();
|
|
522
640
|
create(args: CreateArgs<T>): Promise<T>;
|
|
641
|
+
/**
|
|
642
|
+
* Refuse a `createMany` whose rows do not all name the SAME fields.
|
|
643
|
+
*
|
|
644
|
+
* PowQL could express it: a multi-row insert carries one `{ col := … }` tuple
|
|
645
|
+
* per row, each with its own column list, so a ragged call inserts every
|
|
646
|
+
* value. The SQL engines cannot, their single statement takes its column list
|
|
647
|
+
* from the first row, so a field only a later row names is dropped and a field
|
|
648
|
+
* only the first row names is written as NULL over that column's default. They
|
|
649
|
+
* refuse it (ValidationError, query/writes.ts), and PowDB matching that
|
|
650
|
+
* refusal is what makes the call portable: a shape accepted here and rejected
|
|
651
|
+
* by every other engine turns a PowDB-to-Postgres move into a hard error found
|
|
652
|
+
* in production rather than at the first run.
|
|
653
|
+
*
|
|
654
|
+
* Runs AFTER `applyPkDefault`, on the rows as they will actually be written:
|
|
655
|
+
* a defaulted string PK is filled in on every row, so `[{}, { name }]` is
|
|
656
|
+
* refused for the missing `name`, not for the PK the client supplied itself.
|
|
657
|
+
* Rows that all name the same fields (the overwhelmingly common shape,
|
|
658
|
+
* including N rows of pure defaults) cost one `Object.keys` pass and emit
|
|
659
|
+
* byte-identical PowQL.
|
|
660
|
+
*/
|
|
661
|
+
private assertUniformCreateManyRows;
|
|
523
662
|
createMany(args: CreateManyArgs<T>): Promise<T[]>;
|
|
524
663
|
update(args: UpdateArgs<T>): Promise<T>;
|
|
525
664
|
updateMany(args: UpdateManyArgs<T>): Promise<{
|
|
@@ -547,6 +686,27 @@ export declare class PowqlInterface<T extends object = Record<string, unknown>>
|
|
|
547
686
|
*/
|
|
548
687
|
private upsertComposite;
|
|
549
688
|
count(args?: CountArgs<T>): Promise<number>;
|
|
689
|
+
/**
|
|
690
|
+
* Gate ONE field of a per-field `_count`.
|
|
691
|
+
*
|
|
692
|
+
* `_count: { col: true }` compiles to `count(T { .col })`, which counts
|
|
693
|
+
* NON-NULL values of the column (SQL's `COUNT(col)`) only from engine 0.20 on.
|
|
694
|
+
* Below 0.20 both PowDB frontends ignored the projection and returned the ROW
|
|
695
|
+
* count.
|
|
696
|
+
*
|
|
697
|
+
* That divergence only EXISTS on a nullable column: where the column is NOT
|
|
698
|
+
* NULL the row count and the non-null count are the same number, so the
|
|
699
|
+
* pre-0.20 answer was already the right one and the query keeps working. The
|
|
700
|
+
* gate is therefore per-column, not per-call: refusing the whole feature would
|
|
701
|
+
* take a correct, working call away from every user on the engine line Turbine
|
|
702
|
+
* shipped against and hand them nothing.
|
|
703
|
+
*
|
|
704
|
+
* Nullability comes from the column metadata (`introspectPowdbDatabase` reads
|
|
705
|
+
* PowDB's `required` modifier; `defineSchema` declares it). Metadata that
|
|
706
|
+
* claims NOT NULL for a column the live catalog lets be null would count rows
|
|
707
|
+
* instead of values below 0.20, the same drift any stale-metadata query has.
|
|
708
|
+
*/
|
|
709
|
+
private assertProjectedCountSupported;
|
|
550
710
|
aggregate(args: AggregateArgs<T>): Promise<AggregateResult<T>>;
|
|
551
711
|
groupBy(args: GroupByArgs<T>): Promise<Record<string, unknown>[]>;
|
|
552
712
|
/** Validate a JSON-path target (group key / aggregate target): non-empty array of keys/indexes. */
|