turbine-orm 0.50.0 → 0.51.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 +66 -66
- package/dist/adapters/cockroachdb.d.ts +5 -5
- package/dist/adapters/cockroachdb.js +10 -10
- package/dist/adapters/index.d.ts +5 -5
- package/dist/adapters/index.js +7 -7
- package/dist/adapters/yugabytedb.d.ts +7 -7
- package/dist/adapters/yugabytedb.js +10 -10
- package/dist/cjs/adapters/cockroachdb.d.ts +5 -5
- package/dist/cjs/adapters/cockroachdb.js +10 -10
- package/dist/cjs/adapters/index.d.ts +5 -5
- package/dist/cjs/adapters/index.js +7 -7
- package/dist/cjs/adapters/yugabytedb.d.ts +7 -7
- package/dist/cjs/adapters/yugabytedb.js +10 -10
- package/dist/cjs/cli/config.d.ts +13 -2
- package/dist/cjs/cli/config.js +3 -2
- package/dist/cjs/cli/destructive.d.ts +1 -1
- package/dist/cjs/cli/destructive.js +1 -1
- package/dist/cjs/cli/index.d.ts +10 -10
- package/dist/cjs/cli/index.js +49 -45
- package/dist/cjs/cli/loader.d.ts +7 -7
- package/dist/cjs/cli/loader.js +9 -9
- package/dist/cjs/cli/mcp.js +4 -4
- package/dist/cjs/cli/migrate.d.ts +5 -5
- package/dist/cjs/cli/migrate.js +11 -11
- package/dist/cjs/cli/studio-ui.generated.js +1 -1
- package/dist/cjs/cli/ui.d.ts +2 -2
- package/dist/cjs/cli/ui.js +2 -2
- package/dist/cjs/client.d.ts +49 -38
- package/dist/cjs/client.js +57 -56
- package/dist/cjs/dialect.d.ts +62 -18
- package/dist/cjs/dialect.js +40 -2
- package/dist/cjs/errors.d.ts +5 -5
- package/dist/cjs/errors.js +11 -11
- package/dist/cjs/generate.d.ts +6 -6
- package/dist/cjs/generate.js +31 -29
- package/dist/cjs/index-advisor.d.ts +5 -5
- package/dist/cjs/index-advisor.js +0 -0
- package/dist/cjs/index.d.ts +1 -1
- package/dist/cjs/index.js +7 -7
- package/dist/cjs/introspect.d.ts +35 -9
- package/dist/cjs/introspect.js +83 -32
- package/dist/cjs/mssql.d.ts +11 -11
- package/dist/cjs/mssql.js +64 -29
- package/dist/cjs/mysql.d.ts +8 -8
- package/dist/cjs/mysql.js +61 -23
- package/dist/cjs/nested-write.d.ts +21 -2
- package/dist/cjs/nested-write.js +51 -14
- package/dist/cjs/optional-peer-import.cjs +7 -7
- package/dist/cjs/optional-peer-import.d.cts +7 -7
- package/dist/cjs/pipeline-submittable.d.ts +2 -2
- package/dist/cjs/pipeline-submittable.js +6 -6
- package/dist/cjs/pipeline.d.ts +1 -1
- package/dist/cjs/pipeline.js +4 -4
- package/dist/cjs/powdb-introspect.d.ts +1 -1
- package/dist/cjs/powdb-introspect.js +1 -1
- package/dist/cjs/powdb.d.ts +28 -28
- package/dist/cjs/powdb.js +66 -66
- package/dist/cjs/powql.d.ts +27 -27
- package/dist/cjs/powql.js +73 -52
- package/dist/cjs/query/aggregates.d.ts +1 -1
- package/dist/cjs/query/aggregates.js +5 -5
- package/dist/cjs/query/batched-loader.d.ts +11 -11
- package/dist/cjs/query/batched-loader.js +24 -24
- package/dist/cjs/query/builder.d.ts +39 -21
- package/dist/cjs/query/builder.js +99 -57
- package/dist/cjs/query/compound-unique.d.ts +1 -1
- package/dist/cjs/query/compound-unique.js +0 -0
- package/dist/cjs/query/deferred.d.ts +12 -6
- package/dist/cjs/query/deferred.js +1 -1
- package/dist/cjs/query/filters.d.ts +31 -11
- package/dist/cjs/query/filters.js +67 -14
- package/dist/cjs/query/index.d.ts +1 -1
- package/dist/cjs/query/index.js +1 -1
- package/dist/cjs/query/relations.d.ts +9 -9
- package/dist/cjs/query/relations.js +164 -57
- package/dist/cjs/query/types.d.ts +86 -35
- package/dist/cjs/query/types.js +1 -1
- package/dist/cjs/query/utils.d.ts +27 -10
- package/dist/cjs/query/utils.js +86 -14
- package/dist/cjs/query/where.d.ts +47 -28
- package/dist/cjs/query/where.js +130 -31
- package/dist/cjs/query/writes.d.ts +24 -5
- package/dist/cjs/query/writes.js +102 -13
- package/dist/cjs/realtime.d.ts +7 -7
- package/dist/cjs/realtime.js +9 -9
- package/dist/cjs/schema-builder.d.ts +18 -7
- package/dist/cjs/schema-builder.js +17 -10
- package/dist/cjs/schema-metadata.d.ts +3 -3
- package/dist/cjs/schema-metadata.js +9 -9
- package/dist/cjs/schema-sql.d.ts +9 -9
- package/dist/cjs/schema-sql.js +20 -20
- package/dist/cjs/schema.d.ts +19 -9
- package/dist/cjs/schema.js +6 -6
- package/dist/cjs/serverless.d.ts +15 -15
- package/dist/cjs/serverless.js +16 -16
- package/dist/cjs/sqlite.d.ts +8 -8
- package/dist/cjs/sqlite.js +53 -22
- package/dist/cjs/typed-sql.d.ts +4 -4
- package/dist/cjs/typed-sql.js +5 -5
- package/dist/cli/config.d.ts +13 -2
- package/dist/cli/config.js +3 -2
- package/dist/cli/destructive.d.ts +1 -1
- package/dist/cli/destructive.js +1 -1
- package/dist/cli/index.d.ts +10 -10
- package/dist/cli/index.js +49 -45
- package/dist/cli/loader.d.ts +7 -7
- package/dist/cli/loader.js +9 -9
- package/dist/cli/mcp.js +4 -4
- package/dist/cli/migrate.d.ts +5 -5
- package/dist/cli/migrate.js +11 -11
- package/dist/cli/studio-ui.generated.js +1 -1
- package/dist/cli/ui.d.ts +2 -2
- package/dist/cli/ui.js +2 -2
- package/dist/client.d.ts +49 -38
- package/dist/client.js +57 -56
- package/dist/dialect.d.ts +62 -18
- package/dist/dialect.js +40 -2
- package/dist/errors.d.ts +5 -5
- package/dist/errors.js +11 -11
- package/dist/generate.d.ts +6 -6
- package/dist/generate.js +31 -29
- package/dist/index-advisor.d.ts +5 -5
- package/dist/index-advisor.js +0 -0
- package/dist/index.d.ts +1 -1
- package/dist/index.js +7 -7
- package/dist/introspect.d.ts +35 -9
- package/dist/introspect.js +82 -32
- package/dist/mssql.d.ts +11 -11
- package/dist/mssql.js +64 -29
- package/dist/mysql.d.ts +8 -8
- package/dist/mysql.js +61 -23
- package/dist/nested-write.d.ts +21 -2
- package/dist/nested-write.js +51 -14
- package/dist/optional-peer-import.cjs +7 -7
- package/dist/optional-peer-import.d.cts +7 -7
- package/dist/pipeline-submittable.d.ts +2 -2
- package/dist/pipeline-submittable.js +6 -6
- package/dist/pipeline.d.ts +1 -1
- package/dist/pipeline.js +4 -4
- package/dist/powdb-introspect.d.ts +1 -1
- package/dist/powdb-introspect.js +1 -1
- package/dist/powdb.d.ts +28 -28
- package/dist/powdb.js +66 -66
- package/dist/powql.d.ts +27 -27
- package/dist/powql.js +73 -52
- package/dist/query/aggregates.d.ts +1 -1
- package/dist/query/aggregates.js +5 -5
- package/dist/query/batched-loader.d.ts +11 -11
- package/dist/query/batched-loader.js +24 -24
- package/dist/query/builder.d.ts +39 -21
- package/dist/query/builder.js +100 -58
- package/dist/query/compound-unique.d.ts +1 -1
- package/dist/query/compound-unique.js +0 -0
- package/dist/query/deferred.d.ts +12 -6
- package/dist/query/deferred.js +1 -1
- package/dist/query/filters.d.ts +31 -11
- package/dist/query/filters.js +66 -13
- package/dist/query/index.d.ts +1 -1
- package/dist/query/index.js +1 -1
- package/dist/query/relations.d.ts +9 -9
- package/dist/query/relations.js +165 -58
- package/dist/query/types.d.ts +86 -35
- package/dist/query/types.js +1 -1
- package/dist/query/utils.d.ts +27 -10
- package/dist/query/utils.js +84 -14
- package/dist/query/where.d.ts +47 -28
- package/dist/query/where.js +129 -32
- package/dist/query/writes.d.ts +24 -5
- package/dist/query/writes.js +101 -13
- package/dist/realtime.d.ts +7 -7
- package/dist/realtime.js +9 -9
- package/dist/schema-builder.d.ts +18 -7
- package/dist/schema-builder.js +17 -10
- package/dist/schema-metadata.d.ts +3 -3
- package/dist/schema-metadata.js +9 -9
- package/dist/schema-sql.d.ts +9 -9
- package/dist/schema-sql.js +20 -20
- package/dist/schema.d.ts +19 -9
- package/dist/schema.js +6 -6
- package/dist/serverless.d.ts +15 -15
- package/dist/serverless.js +16 -16
- package/dist/sqlite.d.ts +8 -8
- package/dist/sqlite.js +53 -22
- package/dist/typed-sql.d.ts +4 -4
- package/dist/typed-sql.js +5 -5
- package/package.json +2 -2
package/dist/query/filters.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* turbine-orm
|
|
2
|
+
* turbine-orm, Where-filter type guards and shape helpers
|
|
3
3
|
*
|
|
4
4
|
* Pure detection / fingerprint utilities used by the query builder's WHERE
|
|
5
5
|
* compiler. Kept out of builder.ts so the class file stays about SQL assembly
|
|
@@ -10,7 +10,7 @@ import type { ArrayFilter, ColumnRef, JsonFilter, JsonPathOrderBy, OrderBySpec,
|
|
|
10
10
|
export declare function isWhereOperator(value: unknown): value is WhereOperator;
|
|
11
11
|
/**
|
|
12
12
|
* True for a *plain object literal* that reached an equality fallthrough
|
|
13
|
-
* without matching any known filter shape
|
|
13
|
+
* without matching any known filter shape, the misspelled-operator case.
|
|
14
14
|
* Class instances (Buffer for bytea, Decimal wrappers, ...) are legitimate
|
|
15
15
|
* bind values and return false, as do arrays and Dates.
|
|
16
16
|
*/
|
|
@@ -31,7 +31,7 @@ export declare function isColumnRef(value: unknown): value is ColumnRef;
|
|
|
31
31
|
/**
|
|
32
32
|
* Fingerprint the SHAPE of a where-operator object. Null-valued `equals` /
|
|
33
33
|
* `not` compile to parameterless `IS NULL` / `IS NOT NULL` (different SQL, no
|
|
34
|
-
* param pushed), so null-ness is part of the shape
|
|
34
|
+
* param pushed), so null-ness is part of the shape, without it a cache entry
|
|
35
35
|
* warmed by `{ not: 5 }` would serve `{ not: null }` with a desynced param list.
|
|
36
36
|
*
|
|
37
37
|
* Column references ({@link ColumnRef}) compile the referenced column into the
|
|
@@ -44,7 +44,7 @@ export declare function fingerprintOperatorShape(value: WhereOperator): string;
|
|
|
44
44
|
/**
|
|
45
45
|
* Guard for the value of an `equals` operator reaching the plain-equality
|
|
46
46
|
* operator path. A plain object literal can only legitimately be an equality
|
|
47
|
-
* value on a json/jsonb column
|
|
47
|
+
* value on a json/jsonb column, and those route to the JSONB filter branch
|
|
48
48
|
* BEFORE the operator branch, so any plain object that reaches here is a
|
|
49
49
|
* mistake (e.g. `{ equals: { foo: 1 } }` on a text column). Shared by the
|
|
50
50
|
* SQL-build path and the cache-hit param-collect path so a warmed cache can
|
|
@@ -56,16 +56,21 @@ export declare function assertBindableEqualsOperand(value: unknown, column: stri
|
|
|
56
56
|
* cache fingerprint. The SQL-build and cache-hit param-collect paths MUST
|
|
57
57
|
* enumerate object keys in this exact order: fingerprints sort keys, so two
|
|
58
58
|
* where clauses with the same fields in different insertion order share one
|
|
59
|
-
* cache entry
|
|
59
|
+
* cache entry, if build/collect iterated insertion order, the cached SQL's
|
|
60
60
|
* `$N` placeholders would bind the wrong values (cross-tenant-leak class).
|
|
61
61
|
* Array order (OR/AND members) is positional and is never sorted.
|
|
62
62
|
*/
|
|
63
63
|
export declare function sortedKeys(obj: Record<string, unknown>): string[];
|
|
64
64
|
/** {@link sortedKeys}, but yielding `[key, value]` pairs. */
|
|
65
65
|
export declare function sortedEntries<V>(obj: Record<string, V>): [string, V][];
|
|
66
|
-
/** Known atomic-update operator keys
|
|
66
|
+
/** Known atomic-update operator keys, used to detect operator objects vs plain JSON values */
|
|
67
67
|
export declare const UPDATE_OPERATOR_KEYS: Set<string>;
|
|
68
|
-
/**
|
|
68
|
+
/**
|
|
69
|
+
* Known JSONB operator keys. `stringContains` / `stringStartsWith` /
|
|
70
|
+
* `stringEndsWith` are appended below, once {@link JSON_STRING_OPERATORS} is
|
|
71
|
+
* declared: they have no `WhereOperator` counterpart, so their presence is an
|
|
72
|
+
* unambiguous JSON-filter signal.
|
|
73
|
+
*/
|
|
69
74
|
export declare const JSONB_OPERATOR_KEYS: Set<string>;
|
|
70
75
|
/**
|
|
71
76
|
* JSON range comparison operators → SQL comparison tokens, in the FIXED order
|
|
@@ -77,16 +82,31 @@ export declare const JSONB_OPERATOR_KEYS: Set<string>;
|
|
|
77
82
|
* and they always require `path`.
|
|
78
83
|
*/
|
|
79
84
|
export declare const JSON_RANGE_OPERATORS: Record<'gt' | 'gte' | 'lt' | 'lte', string>;
|
|
85
|
+
/**
|
|
86
|
+
* JSON substring operators → the LIKE pattern each one builds around its
|
|
87
|
+
* escaped operand, in the FIXED order the build and collect paths iterate
|
|
88
|
+
* them. These compare the TEXT at `path` (which every one of them requires),
|
|
89
|
+
* so they are the JSON counterpart of the scalar `contains` / `startsWith` /
|
|
90
|
+
* `endsWith` operators rather than of jsonb containment.
|
|
91
|
+
*
|
|
92
|
+
* They are deliberately NOT named `contains` / `startsWith` / `endsWith`:
|
|
93
|
+
* `contains` on a JSON column already means whole-document containment
|
|
94
|
+
* (`@>`), and silently changing that would break every existing caller.
|
|
95
|
+
*/
|
|
96
|
+
export declare const JSON_STRING_OPERATORS: Record<'stringContains' | 'stringStartsWith' | 'stringEndsWith', (escaped: string) => string>;
|
|
97
|
+
export declare const JSON_FILTER_KEYS: ReadonlySet<string>;
|
|
80
98
|
/**
|
|
81
99
|
* Value-invariant shape fingerprint for a {@link JsonFilter}. Range operators
|
|
82
100
|
* are annotated with the comparison value's kind (`#n` numeric / `#s` string)
|
|
83
|
-
* because a numeric comparison compiles to a `::numeric` cast
|
|
84
|
-
* SQL text than the text comparison
|
|
85
|
-
* SQL entry.
|
|
101
|
+
* because a numeric comparison compiles to a `::numeric` cast, a different
|
|
102
|
+
* SQL text than the text comparison, so the two must never share a cached
|
|
103
|
+
* SQL entry. `mode` is part of the shape for the same reason: it selects
|
|
104
|
+
* between `LIKE` and the dialect's case-insensitive form, which is different
|
|
105
|
+
* SQL text.
|
|
86
106
|
*/
|
|
87
107
|
export declare function fingerprintJsonFilterShape(filter: JsonFilter): string;
|
|
88
108
|
/**
|
|
89
|
-
* JSONB operator keys that are *unique* to {@link JsonFilter}
|
|
109
|
+
* JSONB operator keys that are *unique* to {@link JsonFilter}, they cannot
|
|
90
110
|
* appear in any other where-filter shape, so the presence of one of these is
|
|
91
111
|
* an unambiguous signal that the user meant a JSON filter. Used by the
|
|
92
112
|
* strict-validation path so that `{ contains: 'foo' }` (which is also a valid
|
package/dist/query/filters.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* turbine-orm
|
|
2
|
+
* turbine-orm, Where-filter type guards and shape helpers
|
|
3
3
|
*
|
|
4
4
|
* Pure detection / fingerprint utilities used by the query builder's WHERE
|
|
5
5
|
* compiler. Kept out of builder.ts so the class file stays about SQL assembly
|
|
@@ -24,7 +24,7 @@ export function isWhereOperator(value) {
|
|
|
24
24
|
}
|
|
25
25
|
/**
|
|
26
26
|
* True for a *plain object literal* that reached an equality fallthrough
|
|
27
|
-
* without matching any known filter shape
|
|
27
|
+
* without matching any known filter shape, the misspelled-operator case.
|
|
28
28
|
* Class instances (Buffer for bytea, Decimal wrappers, ...) are legitimate
|
|
29
29
|
* bind values and return false, as do arrays and Dates.
|
|
30
30
|
*/
|
|
@@ -57,7 +57,7 @@ export function isColumnRef(value) {
|
|
|
57
57
|
/**
|
|
58
58
|
* Fingerprint the SHAPE of a where-operator object. Null-valued `equals` /
|
|
59
59
|
* `not` compile to parameterless `IS NULL` / `IS NOT NULL` (different SQL, no
|
|
60
|
-
* param pushed), so null-ness is part of the shape
|
|
60
|
+
* param pushed), so null-ness is part of the shape, without it a cache entry
|
|
61
61
|
* warmed by `{ not: 5 }` would serve `{ not: null }` with a desynced param list.
|
|
62
62
|
*
|
|
63
63
|
* Column references ({@link ColumnRef}) compile the referenced column into the
|
|
@@ -85,7 +85,7 @@ export function fingerprintOperatorShape(value) {
|
|
|
85
85
|
/**
|
|
86
86
|
* Guard for the value of an `equals` operator reaching the plain-equality
|
|
87
87
|
* operator path. A plain object literal can only legitimately be an equality
|
|
88
|
-
* value on a json/jsonb column
|
|
88
|
+
* value on a json/jsonb column, and those route to the JSONB filter branch
|
|
89
89
|
* BEFORE the operator branch, so any plain object that reaches here is a
|
|
90
90
|
* mistake (e.g. `{ equals: { foo: 1 } }` on a text column). Shared by the
|
|
91
91
|
* SQL-build path and the cache-hit param-collect path so a warmed cache can
|
|
@@ -103,7 +103,7 @@ export function assertBindableEqualsOperand(value, column) {
|
|
|
103
103
|
* cache fingerprint. The SQL-build and cache-hit param-collect paths MUST
|
|
104
104
|
* enumerate object keys in this exact order: fingerprints sort keys, so two
|
|
105
105
|
* where clauses with the same fields in different insertion order share one
|
|
106
|
-
* cache entry
|
|
106
|
+
* cache entry, if build/collect iterated insertion order, the cached SQL's
|
|
107
107
|
* `$N` placeholders would bind the wrong values (cross-tenant-leak class).
|
|
108
108
|
* Array order (OR/AND members) is positional and is never sorted.
|
|
109
109
|
*/
|
|
@@ -117,9 +117,14 @@ export function sortedEntries(obj) {
|
|
|
117
117
|
// ---------------------------------------------------------------------------
|
|
118
118
|
// Atomic-update / JSONB / Array / text-search / vector key sets
|
|
119
119
|
// ---------------------------------------------------------------------------
|
|
120
|
-
/** Known atomic-update operator keys
|
|
120
|
+
/** Known atomic-update operator keys, used to detect operator objects vs plain JSON values */
|
|
121
121
|
export const UPDATE_OPERATOR_KEYS = new Set(['set', 'increment', 'decrement', 'multiply', 'divide']);
|
|
122
|
-
/**
|
|
122
|
+
/**
|
|
123
|
+
* Known JSONB operator keys. `stringContains` / `stringStartsWith` /
|
|
124
|
+
* `stringEndsWith` are appended below, once {@link JSON_STRING_OPERATORS} is
|
|
125
|
+
* declared: they have no `WhereOperator` counterpart, so their presence is an
|
|
126
|
+
* unambiguous JSON-filter signal.
|
|
127
|
+
*/
|
|
123
128
|
export const JSONB_OPERATOR_KEYS = new Set(['path', 'equals', 'contains', 'hasKey']);
|
|
124
129
|
/**
|
|
125
130
|
* JSON range comparison operators → SQL comparison tokens, in the FIXED order
|
|
@@ -136,23 +141,71 @@ export const JSON_RANGE_OPERATORS = {
|
|
|
136
141
|
lt: '<',
|
|
137
142
|
lte: '<=',
|
|
138
143
|
};
|
|
144
|
+
/**
|
|
145
|
+
* JSON substring operators → the LIKE pattern each one builds around its
|
|
146
|
+
* escaped operand, in the FIXED order the build and collect paths iterate
|
|
147
|
+
* them. These compare the TEXT at `path` (which every one of them requires),
|
|
148
|
+
* so they are the JSON counterpart of the scalar `contains` / `startsWith` /
|
|
149
|
+
* `endsWith` operators rather than of jsonb containment.
|
|
150
|
+
*
|
|
151
|
+
* They are deliberately NOT named `contains` / `startsWith` / `endsWith`:
|
|
152
|
+
* `contains` on a JSON column already means whole-document containment
|
|
153
|
+
* (`@>`), and silently changing that would break every existing caller.
|
|
154
|
+
*/
|
|
155
|
+
export const JSON_STRING_OPERATORS = {
|
|
156
|
+
stringContains: (escaped) => `%${escaped}%`,
|
|
157
|
+
stringStartsWith: (escaped) => `${escaped}%`,
|
|
158
|
+
stringEndsWith: (escaped) => `%${escaped}`,
|
|
159
|
+
};
|
|
160
|
+
/**
|
|
161
|
+
* Every key a {@link JsonFilter} may carry. Used by the strict-key check so an
|
|
162
|
+
* unrecognized operator is REFUSED rather than dropped.
|
|
163
|
+
*
|
|
164
|
+
* This existed as tribal knowledge spread across `buildJsonFilterClauses` and
|
|
165
|
+
* `collectJsonFilterParams`: each simply ignored what it did not recognize, so
|
|
166
|
+
* `{ path: ['title'], string_contains: 'x' }` (the Prisma spelling) compiled to
|
|
167
|
+
* no predicate at all and returned every row of the table. The scalar operator
|
|
168
|
+
* path has always thrown on an unknown key; this set is what lets the JSON path
|
|
169
|
+
* behave the same way.
|
|
170
|
+
*/
|
|
171
|
+
for (const k of Object.keys(JSON_STRING_OPERATORS))
|
|
172
|
+
JSONB_OPERATOR_KEYS.add(k);
|
|
173
|
+
export const JSON_FILTER_KEYS = new Set([
|
|
174
|
+
'path',
|
|
175
|
+
'equals',
|
|
176
|
+
'contains',
|
|
177
|
+
'hasKey',
|
|
178
|
+
'mode',
|
|
179
|
+
...Object.keys(JSON_RANGE_OPERATORS),
|
|
180
|
+
...Object.keys(JSON_STRING_OPERATORS),
|
|
181
|
+
]);
|
|
139
182
|
/**
|
|
140
183
|
* Value-invariant shape fingerprint for a {@link JsonFilter}. Range operators
|
|
141
184
|
* are annotated with the comparison value's kind (`#n` numeric / `#s` string)
|
|
142
|
-
* because a numeric comparison compiles to a `::numeric` cast
|
|
143
|
-
* SQL text than the text comparison
|
|
144
|
-
* SQL entry.
|
|
185
|
+
* because a numeric comparison compiles to a `::numeric` cast, a different
|
|
186
|
+
* SQL text than the text comparison, so the two must never share a cached
|
|
187
|
+
* SQL entry. `mode` is part of the shape for the same reason: it selects
|
|
188
|
+
* between `LIKE` and the dialect's case-insensitive form, which is different
|
|
189
|
+
* SQL text.
|
|
145
190
|
*/
|
|
146
191
|
export function fingerprintJsonFilterShape(filter) {
|
|
147
192
|
const obj = filter;
|
|
148
193
|
const parts = Object.keys(obj)
|
|
149
194
|
.filter((k) => obj[k] !== undefined)
|
|
150
195
|
.sort()
|
|
151
|
-
.map((k) =>
|
|
196
|
+
.map((k) => {
|
|
197
|
+
if (k in JSON_RANGE_OPERATORS)
|
|
198
|
+
return `${k}#${typeof obj[k] === 'number' ? 'n' : 's'}`;
|
|
199
|
+
// `mode` carries its VALUE, not just its presence: 'insensitive' and any
|
|
200
|
+
// other spelling select different SQL, so they must not share an entry.
|
|
201
|
+
if (k === 'mode')
|
|
202
|
+
return `mode#${String(obj[k])}`;
|
|
203
|
+
return k;
|
|
204
|
+
});
|
|
152
205
|
return `json(${parts.join(',')})`;
|
|
153
206
|
}
|
|
154
207
|
/**
|
|
155
|
-
* JSONB operator keys that are *unique* to {@link JsonFilter}
|
|
208
|
+
* JSONB operator keys that are *unique* to {@link JsonFilter}, they cannot
|
|
156
209
|
* appear in any other where-filter shape, so the presence of one of these is
|
|
157
210
|
* an unambiguous signal that the user meant a JSON filter. Used by the
|
|
158
211
|
* strict-validation path so that `{ contains: 'foo' }` (which is also a valid
|
|
@@ -160,7 +213,7 @@ export function fingerprintJsonFilterShape(filter) {
|
|
|
160
213
|
* set: on non-JSON columns it is a plain equality operator (`WhereOperator`),
|
|
161
214
|
* so it must fall through instead of throwing.
|
|
162
215
|
*/
|
|
163
|
-
export const JSONB_UNIQUE_KEYS = new Set(['path', 'hasKey']);
|
|
216
|
+
export const JSONB_UNIQUE_KEYS = new Set(['path', 'hasKey', ...Object.keys(JSON_STRING_OPERATORS)]);
|
|
164
217
|
/** Check if a value is a JSONB filter object */
|
|
165
218
|
export function isJsonFilter(value) {
|
|
166
219
|
if (value === null ||
|
package/dist/query/index.d.ts
CHANGED
package/dist/query/index.js
CHANGED
|
@@ -21,11 +21,11 @@ import type { BuilderCtx } from './where.js';
|
|
|
21
21
|
* generation (see {@link buildRelationShape}) and consumed by the
|
|
22
22
|
* transform to map key-less positional arrays back to keyed objects.
|
|
23
23
|
*
|
|
24
|
-
* - `keys
|
|
24
|
+
* - `keys`, camelCase field names in emitted array position, INCLUDING nested
|
|
25
25
|
* relation slots (a nested relation occupies one more position after the
|
|
26
26
|
* scalar columns, in `sortedEntries(with)` order).
|
|
27
|
-
* - `nested
|
|
28
|
-
* - `cardinality
|
|
27
|
+
* - `nested`, sub-shape for each key in `keys` that is itself a relation slot.
|
|
28
|
+
* - `cardinality`, `'one'` (belongsTo/hasOne, a single positional array or
|
|
29
29
|
* null) vs `'many'` (an array of positional arrays).
|
|
30
30
|
*/
|
|
31
31
|
export interface RelationShape {
|
|
@@ -58,7 +58,7 @@ export declare function collectRelationSubqueryParams(qi: BuilderCtx, relDef: Re
|
|
|
58
58
|
* Value-shape fingerprint for a single orderBy entry, so two queries whose
|
|
59
59
|
* ORDER BY differs only in nulls placement, vector metric, or relation-count
|
|
60
60
|
* vs relation-column never collide on one cached SQL string. Captures the
|
|
61
|
-
* SQL-shaping bits (direction, nulls, metric, relation keys)
|
|
61
|
+
* SQL-shaping bits (direction, nulls, metric, relation keys), never values.
|
|
62
62
|
*/
|
|
63
63
|
export declare function orderByEntryFingerprint(qi: BuilderCtx, d: unknown, targetTable?: string): string;
|
|
64
64
|
export declare function buildOrderBy(qi: BuilderCtx, orderBy: OrderByClause, params?: unknown[], lateralSink?: string[]): string;
|
|
@@ -70,7 +70,7 @@ export declare function buildOrderBy(qi: BuilderCtx, orderBy: OrderByClause, par
|
|
|
70
70
|
export declare function isRelationOrderByValue(_qi: BuilderCtx, value: unknown): boolean;
|
|
71
71
|
/**
|
|
72
72
|
* Render the ` NULLS FIRST` / ` NULLS LAST` suffix for a column ordering.
|
|
73
|
-
* Only PostgreSQL and SQLite support the `NULLS FIRST/LAST` grammar
|
|
73
|
+
* Only PostgreSQL and SQLite support the `NULLS FIRST/LAST` grammar, on any
|
|
74
74
|
* other engine a caller asking for explicit nulls placement gets a clear
|
|
75
75
|
* {@link UnsupportedFeatureError} (E017) instead of broken SQL.
|
|
76
76
|
*/
|
|
@@ -225,7 +225,7 @@ export declare function collectManyToManyTargetGlobalFilter(qi: BuilderCtx, relD
|
|
|
225
225
|
/**
|
|
226
226
|
* Param-collect mirror of {@link buildRelationCountExpr}'s global-filter
|
|
227
227
|
* params (hasMany direct filter, or manyToMany EXISTS-on-target). Only pushes
|
|
228
|
-
* when a filter applies
|
|
228
|
+
* when a filter applies, no-op otherwise.
|
|
229
229
|
*/
|
|
230
230
|
export declare function collectRelationCountParams(qi: BuilderCtx, relDef: RelationDef, params: unknown[]): void;
|
|
231
231
|
export declare function getCamelDateFields(qi: BuilderCtx, table: string, meta: TableMetadata): Set<string>;
|
|
@@ -277,7 +277,7 @@ export declare function makeNestedParser(qi: BuilderCtx, withClause: WithClause,
|
|
|
277
277
|
/**
|
|
278
278
|
* Return a shallow copy of a top-level row with each relation column decoded
|
|
279
279
|
* from its positional array(s) into the object representation. Only relation
|
|
280
|
-
* columns are positional
|
|
280
|
+
* columns are positional, base scalar columns stay object-keyed, so the
|
|
281
281
|
* result is exactly what the object encoding would have handed parseNestedRow.
|
|
282
282
|
*/
|
|
283
283
|
export declare function decodePositionalRelations(qi: BuilderCtx, row: Record<string, unknown>, shapes: Record<string, RelationShape>): Record<string, unknown>;
|
|
@@ -319,7 +319,7 @@ export interface FlattenNode {
|
|
|
319
319
|
alias: string;
|
|
320
320
|
/** Alias of the real target table inside the derived table (`f0s`). */
|
|
321
321
|
srcAlias: string;
|
|
322
|
-
/** Target-side correlation columns (provably unique
|
|
322
|
+
/** Target-side correlation columns (provably unique, see {@link provableUniqueTargetKey}). */
|
|
323
323
|
keyColumns: string[];
|
|
324
324
|
/**
|
|
325
325
|
* Match discriminator. A top-level node projects the constant `1` (its
|
|
@@ -394,7 +394,7 @@ export declare function provableUniqueTargetKey(relDef: RelationDef, targetMeta:
|
|
|
394
394
|
* it emits today, down to the cache key).
|
|
395
395
|
*
|
|
396
396
|
* The plan is a pure function of the schema, the `with` clause shape and
|
|
397
|
-
* `includePii
|
|
397
|
+
* `includePii`, never of any bound value, so the build path, the cache-hit
|
|
398
398
|
* param-collect path and the row assembler can each recompute it and agree.
|
|
399
399
|
*/
|
|
400
400
|
export declare function planFlattenWith(qi: BuilderCtx, table: string, withClause: WithClause, includePii?: boolean): FlattenPlan | null;
|