uql-orm 0.24.6 → 0.25.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 +9 -8
- package/dist/cockroachdb/crdbQuerierPool.d.ts +1 -1
- package/dist/cockroachdb/crdbQuerierPool.js +5 -4
- package/dist/dialect/abstractSqlDialect.d.ts +78 -27
- package/dist/dialect/abstractSqlDialect.js +194 -130
- package/dist/dialect/hydrateColumn.d.ts +16 -0
- package/dist/dialect/hydrateColumn.js +66 -0
- package/dist/dialect/jsonSql.d.ts +24 -0
- package/dist/dialect/jsonSql.js +39 -0
- package/dist/dialect/mysqlLikeSqlDialect.d.ts +5 -0
- package/dist/dialect/mysqlLikeSqlDialect.js +10 -1
- package/dist/dialect/pgLikeSqlDialect.d.ts +3 -7
- package/dist/dialect/pgLikeSqlDialect.js +2 -14
- package/dist/dialect/vectorCast.d.ts +15 -0
- package/dist/dialect/vectorCast.js +58 -0
- package/dist/entity/metadata/definition.d.ts +0 -1
- package/dist/entity/metadata/definition.js +1 -1
- package/dist/maria/mariaDialect.d.ts +3 -2
- package/dist/maria/mariaDialect.js +3 -18
- package/dist/maria/mariadbQuerierPool.js +6 -1
- package/dist/migrate/builder/migrationBuilder.d.ts +12 -16
- package/dist/migrate/builder/migrationBuilder.js +24 -59
- package/dist/migrate/builder/tableBuilder.js +0 -12
- package/dist/migrate/cli.d.ts +0 -1
- package/dist/migrate/cli.js +1 -1
- package/dist/migrate/codegen/entityCodeGenerator.js +0 -3
- package/dist/migrate/drift/driftDetector.js +17 -15
- package/dist/migrate/generator/mongoSchemaGenerator.d.ts +9 -1
- package/dist/migrate/generator/mongoSchemaGenerator.js +18 -0
- package/dist/migrate/introspection/abstractSqlSchemaIntrospector.d.ts +8 -2
- package/dist/migrate/introspection/abstractSqlSchemaIntrospector.js +10 -9
- package/dist/migrate/introspection/mysqlIntrospector.d.ts +0 -3
- package/dist/migrate/introspection/mysqlIntrospector.js +0 -9
- package/dist/migrate/introspection/postgresIntrospector.d.ts +0 -3
- package/dist/migrate/introspection/postgresIntrospector.js +0 -12
- package/dist/migrate/introspection/sqliteIntrospector.d.ts +1 -0
- package/dist/migrate/introspection/sqliteIntrospector.js +1 -9
- package/dist/migrate/migrator.d.ts +17 -0
- package/dist/migrate/migrator.js +51 -50
- package/dist/migrate/schemaGenerator.d.ts +19 -8
- package/dist/migrate/schemaGenerator.js +48 -17
- package/dist/neon/neonQuerierPool.d.ts +1 -1
- package/dist/neon/neonQuerierPool.js +6 -4
- package/dist/postgres/abstractPgQuerierPool.d.ts +6 -0
- package/dist/postgres/abstractPgQuerierPool.js +3 -0
- package/dist/postgres/pgNumericTypes.d.ts +41 -0
- package/dist/postgres/pgNumericTypes.js +35 -0
- package/dist/postgres/pgQuerierPool.d.ts +1 -1
- package/dist/postgres/pgQuerierPool.js +5 -4
- package/dist/querier/abstractSqlQuerier.d.ts +9 -2
- package/dist/querier/abstractSqlQuerier.js +34 -25
- package/dist/schema/canonicalType.js +2 -12
- package/dist/schema/schemaAST.js +0 -24
- package/dist/schema/schemaASTBuilder.d.ts +1 -1
- package/dist/schema/schemaASTBuilder.js +4 -5
- package/dist/sqlite/nodeSqliteQuerierPool.js +1 -0
- package/dist/sqlite/sqliteQuerierPool.d.ts +5 -0
- package/dist/sqlite/sqliteQuerierPool.js +7 -0
- package/dist/turso/tursoLocalQuerierPool.js +1 -0
- package/dist/type/entity.d.ts +16 -2
- package/dist/type/migration.d.ts +30 -9
- package/dist/type/queryAggregate.d.ts +3 -0
- package/dist/util/field.util.d.ts +4 -0
- package/dist/util/field.util.js +12 -0
- package/dist/util/sqlLiteral.js +18 -15
- package/package.json +6 -6
package/README.md
CHANGED
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
|
|
10
10
|
<h3>The smartest TypeScript ORM</h3>
|
|
11
11
|
|
|
12
|
-
<p>Type-safe to the leaf, serializable queries, no codegen, <a href="https://uql-orm.dev/benchmark">extremely fast</a>, and
|
|
12
|
+
<p>Type-safe to the leaf, serializable queries, no codegen, <a href="https://uql-orm.dev/benchmark">extremely fast</a>, and one API across every SQL database, MongoDB, and every runtime.</p>
|
|
13
13
|
|
|
14
14
|
<p>
|
|
15
15
|
<a href="https://uql-orm.dev"><b>Website</b></a> ·
|
|
@@ -37,7 +37,7 @@ and no compiler flag to turn on ([setup](https://uql-orm.dev/getting-started)),
|
|
|
37
37
|
[imperative API](https://uql-orm.dev/entities/imperative) skips decorators altogether.
|
|
38
38
|
|
|
39
39
|
```ts
|
|
40
|
-
await
|
|
40
|
+
await pool.findMany(User, {
|
|
41
41
|
$select: { id: true, email: true },
|
|
42
42
|
$populate: { posts: { $select: { title: true } } },
|
|
43
43
|
$where: { email: { $endsWith: '@uql-orm.dev' } },
|
|
@@ -50,12 +50,13 @@ from the browser to the server. The same object runs on every supported database
|
|
|
50
50
|
|
|
51
51
|
## Why UQL?
|
|
52
52
|
|
|
53
|
-
- **The fastest.** Wins [all 8 categories](https://uql-orm.dev/benchmark) of our
|
|
54
|
-
- **Light.** Zero runtime dependencies,
|
|
55
|
-
- **Queries are data, not method chains.** Plain JSON in, typed rows out. There's no DSL to learn and nothing to compile.
|
|
56
|
-
- **Type-safe to the leaf.** Operators are gated per field type, and JSON/JSONB dot-paths resolve each path's value type, so `
|
|
57
|
-
- **No codegen.** Entities are TypeScript classes, so your code *is* the schema.
|
|
58
|
-
- **One API everywhere.** PostgreSQL, CockroachDB, MySQL, MariaDB, SQLite, Turso,
|
|
53
|
+
- **The fastest.** Wins [all 8 categories](https://uql-orm.dev/benchmark) of our open-source [benchmark](https://github.com/rogerpadilla/ts-orm-benchmark), beating even query builders like Knex and Kysely: ~2.4× faster than the runner-up on average, reaching over 4.6M ops/s on simple SELECTs.
|
|
54
|
+
- **Light.** Zero runtime dependencies, 305 kB on the wire, every dialect included. See [what we deleted to get there](https://uql-orm.dev/blog/zero-dependencies).
|
|
55
|
+
- **Queries are data (JSON), not method chains.** Plain JSON in, typed rows out. There's no DSL to learn and nothing to compile.
|
|
56
|
+
- **Type-safe to the leaf.** Every key is autocompleted and checked against your entity, down to the fields of a populated relation. Operators are gated per field type, and [JSON/JSONB](https://uql-orm.dev/querying/json) dot-paths resolve each path's value type, so `$like` on a numeric column, or a typo'd path, is a compile error instead of a runtime surprise.
|
|
57
|
+
- **No codegen, no build step.** Entities are TypeScript classes, so your code *is* the schema. There's no `.prisma` file to regenerate and no generated client to keep in sync.
|
|
58
|
+
- **One API everywhere.** PostgreSQL, CockroachDB, MySQL, MariaDB, SQLite, Turso, libSQL, Neon, Cloudflare D1, Bun's native SQL, and even MongoDB!
|
|
59
|
+
- **Runs on every runtime.** Node 24+, Bun, Deno, [Cloudflare Workers](https://uql-orm.dev/cloudflare-d1), [AWS Lambda and Vercel](https://uql-orm.dev/serverless), and [the browser](https://uql-orm.dev/browser). ESM-only with no native binaries on the `fetch`-based drivers, so an edge bundle needs no special build.
|
|
59
60
|
- **The hard things are built in.** [Semantic and vector search](https://uql-orm.dev/ai-semantic-search), [non-bypassable multi-tenant filters](https://uql-orm.dev/multi-tenancy), [entity-first migrations](https://uql-orm.dev/migrations), [soft-delete with restore](https://uql-orm.dev/entities/soft-delete), [streaming](https://uql-orm.dev/querying/streaming), and [a REST API from your entities](https://uql-orm.dev/http).
|
|
60
61
|
|
|
61
62
|
## Get started
|
|
@@ -9,5 +9,5 @@ import { CrdbQuerier } from './crdbQuerier.js';
|
|
|
9
9
|
export declare class CrdbQuerierPool extends AbstractPgQuerierPool<PoolClient, CrdbQuerier, CockroachDialect> {
|
|
10
10
|
readonly pool: Pool;
|
|
11
11
|
constructor(opts: PoolConfig, extra?: ExtraOptions);
|
|
12
|
-
|
|
12
|
+
protected buildQuerier(connect: () => Promise<PoolClient>): CrdbQuerier;
|
|
13
13
|
}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
import { Pool } from 'pg';
|
|
1
|
+
import { Pool, types } from 'pg';
|
|
2
2
|
import { AbstractPgQuerierPool } from '../postgres/abstractPgQuerierPool.js';
|
|
3
|
+
import { numericTypes } from '../postgres/pgNumericTypes.js';
|
|
3
4
|
import { CockroachDialect } from './cockroachDialect.js';
|
|
4
5
|
import { CrdbQuerier } from './crdbQuerier.js';
|
|
5
6
|
/**
|
|
@@ -7,9 +8,9 @@ import { CrdbQuerier } from './crdbQuerier.js';
|
|
|
7
8
|
*/
|
|
8
9
|
export class CrdbQuerierPool extends AbstractPgQuerierPool {
|
|
9
10
|
constructor(opts, extra) {
|
|
10
|
-
super(new CockroachDialect({ namingStrategy: extra?.namingStrategy }), new Pool({ keepAlive: true, ...opts }), extra);
|
|
11
|
+
super(new CockroachDialect({ namingStrategy: extra?.namingStrategy }), new Pool({ keepAlive: true, types: numericTypes(types), ...opts }), extra);
|
|
11
12
|
}
|
|
12
|
-
|
|
13
|
-
return new CrdbQuerier(
|
|
13
|
+
buildQuerier(connect) {
|
|
14
|
+
return new CrdbQuerier(connect, this.dialect, this.extra);
|
|
14
15
|
}
|
|
15
16
|
}
|
|
@@ -1,7 +1,11 @@
|
|
|
1
1
|
import { type EntityMeta, type FieldKey, type FieldOptions, type IsolationLevel, type JsonColumnType, type JsonUpdateOp, type Query, type QueryAggMap, type QueryAggregate, type QueryComparisonOptions, type QueryConflictPaths, type QueryContext, type QueryDialect, type QueryExclude, type QueryGroupMap, type QueryHavingMap, type QueryOptions, type QueryPager, type QueryPopulate, QueryRaw, type QueryRawFnOptions, type QuerySearch, type QuerySelect, type QuerySelectOptions, type QuerySelectValue, type QuerySizeComparisonOps, type QuerySortMap, type QueryTextSearchOptions, type QueryWhere, type QueryWhereArray, type QueryWhereFieldOperatorMap, type QueryWhereMap, type QueryWhereOptions, type RelationMeta, type SqlDialectName, type SqlQueryDialect, type Type, type UpdatePayload } from '../type/index.js';
|
|
2
|
+
import type { HydrateKind } from './hydrateColumn.js';
|
|
2
3
|
import { IndexSqlDialect } from './indexSqlDialect.js';
|
|
3
4
|
/** How a column's values are bound: see {@link AbstractSqlDialect.persistKind}. */
|
|
4
5
|
type PersistKind = 'plain' | 'json' | 'vector';
|
|
6
|
+
/** One entry of {@link AbstractSqlDialect.hydratableFields}: a field key and how it decodes. */
|
|
7
|
+
type HydratableField = readonly [string, HydrateKind];
|
|
8
|
+
export type { HydrateKind };
|
|
5
9
|
export declare abstract class AbstractSqlDialect extends IndexSqlDialect implements QueryDialect, SqlQueryDialect {
|
|
6
10
|
abstract readonly dialectName: SqlDialectName;
|
|
7
11
|
abstract readonly escapeIdChar: '"' | '`';
|
|
@@ -99,6 +103,20 @@ export declare abstract class AbstractSqlDialect extends IndexSqlDialect impleme
|
|
|
99
103
|
protected resolveOperandField<E>(ctx: QueryContext, entity: Type<E>, key: string, opts: QueryOptions): string | undefined;
|
|
100
104
|
private appendFieldSql;
|
|
101
105
|
compareFieldOperator<E, K extends keyof QueryWhereFieldOperatorMap<E>>(ctx: QueryContext, entity: Type<E>, key: FieldKey<E>, op: K, val: QueryWhereFieldOperatorMap<E>[K], opts?: QueryOptions): void;
|
|
106
|
+
/**
|
|
107
|
+
* Render `<operand> <op> <value>` for every operator that needs nothing but its left-hand SQL, and
|
|
108
|
+
* report whether `op` was one of them.
|
|
109
|
+
*
|
|
110
|
+
* One implementation for three callers that each had their own: a WHERE column, a HAVING aggregate
|
|
111
|
+
* expression, and a `$size` count (which passes no operand, since its expression is already in the
|
|
112
|
+
* context). They previously disagreed - HAVING carried a second comparison-operator map and threw
|
|
113
|
+
* `unsupported HAVING operator` on the `$like` that `QueryHavingMap` accepts, and neither of the
|
|
114
|
+
* other two turned `$eq: null` into `IS NULL` the way the WHERE path does.
|
|
115
|
+
*
|
|
116
|
+
* The operators kept out are the ones that need more than an operand: `$not` recurses through the
|
|
117
|
+
* entity, and `$all`/`$size`/`$elemMatch` address a JSON document.
|
|
118
|
+
*/
|
|
119
|
+
protected appendOperatorCondition(ctx: QueryContext, operand: string | undefined, op: string, val: unknown): boolean;
|
|
102
120
|
private appendLikeOp;
|
|
103
121
|
private appendEqNe;
|
|
104
122
|
private appendInNin;
|
|
@@ -116,19 +134,6 @@ export declare abstract class AbstractSqlDialect extends IndexSqlDialect impleme
|
|
|
116
134
|
* {@link jsonCompareMode} for why each mode exists.
|
|
117
135
|
*/
|
|
118
136
|
protected jsonComparand(jsonField: string, value: unknown): string;
|
|
119
|
-
/**
|
|
120
|
-
* How a JSON scalar has to be compared against `value` (or, for `$in`/`$nin`, against every element
|
|
121
|
-
* of it). Extracting a JSON value yields *text*, which loses the type, so each operand type is
|
|
122
|
-
* compared in the representation every engine agrees on:
|
|
123
|
-
* - `numeric` - cast the accessor. Keeps `1` equal to a stored `1.0`, which strict JSON equality
|
|
124
|
-
* would not, and satisfies drivers that send typed parameters (`text = integer` otherwise).
|
|
125
|
-
* - `json` - compare the JSON value against a JSON-encoded parameter. No cast recovers a boolean
|
|
126
|
-
* portably: PostgreSQL raises `text = boolean` and MySQL matches `'true'` against `1`.
|
|
127
|
-
* - `text` - compare as extracted, which is also what the string operators need.
|
|
128
|
-
*
|
|
129
|
-
* Mixed operand types fall back to `text`, since one comparison cannot be two shapes at once.
|
|
130
|
-
*/
|
|
131
|
-
protected jsonCompareMode(value: unknown): 'json' | 'numeric' | 'text';
|
|
132
137
|
/** `$all`: the JSON array at `jsonField` contains every value (also serves element containment). */
|
|
133
138
|
protected abstract jsonAll(ctx: QueryContext, jsonField: string, value: unknown): string;
|
|
134
139
|
/** `$size`: the length of the JSON array at `jsonField`, compared against `value`. */
|
|
@@ -171,17 +176,6 @@ export declare abstract class AbstractSqlDialect extends IndexSqlDialect impleme
|
|
|
171
176
|
* - otherwise - per-field conditions over the exploded objects.
|
|
172
177
|
*/
|
|
173
178
|
protected jsonElemMatch(ctx: QueryContext, jsonField: string, match: Record<string, unknown>): string;
|
|
174
|
-
/**
|
|
175
|
-
* Whether the operator reads the JSON *value* instead of its text form. The array operators always
|
|
176
|
-
* do. Equality joins them for boolean operands, because extracting JSON as text loses the type in
|
|
177
|
-
* a way no cast recovers portably: PostgreSQL raises `operator does not exist: text = boolean`,
|
|
178
|
-
* MySQL compares `'true'` to `1` and silently matches nothing, and SQLite's `json_extract` yields
|
|
179
|
-
* `1`. Comparing the JSON value against a JSON-encoded parameter is exact on every dialect.
|
|
180
|
-
*
|
|
181
|
-
* Numbers stay on the text accessor with a numeric cast ({@link jsonComparand}), which keeps
|
|
182
|
-
* `1` equal to `1.0` - JSON equality would not.
|
|
183
|
-
*/
|
|
184
|
-
protected isJsonbOp(op: string, value?: unknown): boolean;
|
|
185
179
|
/**
|
|
186
180
|
* A JSON-encoded bound parameter, cast to the dialect's JSON type. Only the positional-placeholder
|
|
187
181
|
* dialects use this - PostgreSQL binds JSON through {@link PgLikeSqlDialect.jsonScalarParam} instead.
|
|
@@ -204,7 +198,6 @@ export declare abstract class AbstractSqlDialect extends IndexSqlDialect impleme
|
|
|
204
198
|
private static readonly SORT_DIRECTION_MAP;
|
|
205
199
|
private resolveSortDirection;
|
|
206
200
|
/** Scalar comparison operators shared by `HAVING` conditions and `$size` comparisons. */
|
|
207
|
-
private static readonly comparisonOpMap;
|
|
208
201
|
protected havingCondition(ctx: QueryContext, expr: string, condition: QueryHavingMap[string]): void;
|
|
209
202
|
find<E>(ctx: QueryContext, entity: Type<E>, q?: Query<E>, opts?: QueryOptions): void;
|
|
210
203
|
insert<E>(ctx: QueryContext, entity: Type<E>, payload: E | E[], opts?: QueryOptions): void;
|
|
@@ -232,6 +225,15 @@ export declare abstract class AbstractSqlDialect extends IndexSqlDialect impleme
|
|
|
232
225
|
* bind into the main context and skip the second one.
|
|
233
226
|
*/
|
|
234
227
|
upsert<E>(ctx: QueryContext, entity: Type<E>, conflictPaths: QueryConflictPaths<E>, payload: E | E[], extraReturning?: string): void;
|
|
228
|
+
/**
|
|
229
|
+
* Whether the upsert's update assignments can bind straight into the statement's own context.
|
|
230
|
+
*
|
|
231
|
+
* They cannot on a `?`-placeholder dialect: the assignments are built before the insert but read
|
|
232
|
+
* after it, so their values have to be pushed afterwards to land in the right positional order.
|
|
233
|
+
* A `$n` placeholder carries its own index, so there is nothing to reorder - but it also cannot use
|
|
234
|
+
* the scratch context, whose numbering would restart at `$1` and collide with the insert's.
|
|
235
|
+
*/
|
|
236
|
+
protected readonly upsertUpdateBindsInPlace: boolean;
|
|
235
237
|
/** How an `ON CONFLICT` assignment reads the row that was being inserted. */
|
|
236
238
|
protected readonly upsertExcluded: (columnName: string) => string;
|
|
237
239
|
protected getUpsertUpdateAssignments<E>(ctx: QueryContext, meta: EntityMeta<E>, conflictPaths: QueryConflictPaths<E>, payload: E | E[], callback?: (columnName: string) => string): string;
|
|
@@ -251,6 +253,49 @@ export declare abstract class AbstractSqlDialect extends IndexSqlDialect impleme
|
|
|
251
253
|
* `isJsonType` and `isVectorFieldType` 120 times to get the same six answers.
|
|
252
254
|
*/
|
|
253
255
|
protected persistKind(field: FieldOptions | undefined): PersistKind;
|
|
256
|
+
/**
|
|
257
|
+
* Which of an entity's columns need decoding on READ, and how: the inverse of {@link persistKind},
|
|
258
|
+
* cached per entity for the same reason it classifies per column. A 1000-row read of a 10-field
|
|
259
|
+
* entity otherwise asks `isJsonType` (which lowercases a string on every call) 10,000 times to get
|
|
260
|
+
* the same ten answers. Most entities land here for their numeric columns alone, where the per-row
|
|
261
|
+
* cost is one `typeof` against a value the driver usually decoded already.
|
|
262
|
+
*
|
|
263
|
+
* Dialect-aware exactly like {@link supportedVectorType}, because it has to be: a `sparsevec` field
|
|
264
|
+
* is written as a plain dense vector everywhere but Postgres, so reading it back by the field's own
|
|
265
|
+
* declared cast would look for a sparse literal that was never stored.
|
|
266
|
+
*
|
|
267
|
+
* A type lands here rather than at the driver when the wire type alone cannot decide it, and only
|
|
268
|
+
* the declaration can: `Boolean` is 0/1 in a SQLite INTEGER and a MySQL `TINYINT(1)`, both
|
|
269
|
+
* indistinguishable from a genuine small integer; a decimal is text from pg *and* mysql2, and only
|
|
270
|
+
* the field says it was meant as a number; and `type: BigInt` shares BIGINT with `type: Number`, so
|
|
271
|
+
* the wire decode has to be undone for it. All are no-ops where the driver already decoded.
|
|
272
|
+
*
|
|
273
|
+
* Classified through the same `isNumericType`/`isBooleanType`/`isJsonType` the rest of the library
|
|
274
|
+
* uses, not against the constructors: `type` accepts a string logical type for every one of these
|
|
275
|
+
* (`@Field({ type: 'decimal' })`), and matching `=== Number` alone left those reading back as text.
|
|
276
|
+
*/
|
|
277
|
+
hydratableFields<E>(entity: Type<E>): readonly HydratableField[];
|
|
278
|
+
/**
|
|
279
|
+
* The same classification for an aggregate row. Not cached, because these columns are a shape of the
|
|
280
|
+
* query rather than of the entity, and it is computed once per call either way.
|
|
281
|
+
*
|
|
282
|
+
* Mirrors `QueryAggregateFnResult`, which is the contract callers already compile against:
|
|
283
|
+
* `$count`/`$sum`/`$avg` are a number whatever they aggregate, while `$min`/`$max` and every
|
|
284
|
+
* `$group` column keep the aggregated field's own type, so they decode as that field would. Without
|
|
285
|
+
* it a `$sum` over a BIGINT column came back as `'500'` from a result type that says `number`, since
|
|
286
|
+
* Postgres widens that sum to NUMERIC and no driver can know it was meant as a JS number.
|
|
287
|
+
*/
|
|
288
|
+
hydratableAggregates<E, G extends QueryGroupMap<E>, A extends QueryAggMap<E>>(entity: Type<E>, q: QueryAggregate<E, G, A>): readonly HydratableField[];
|
|
289
|
+
/**
|
|
290
|
+
* The mirror of {@link persistKind}: what one column decodes as, or nothing if it needs no decode.
|
|
291
|
+
*
|
|
292
|
+
* Ordered for correctness, not for speed - this runs once per entity, cached, never per row. The
|
|
293
|
+
* one order that is load-bearing is `BigInt` before {@link isNumericType}, which answers true for
|
|
294
|
+
* `BigInt` as well as `Number`: swap them and every `type: BigInt` property silently decodes to a
|
|
295
|
+
* JS number again.
|
|
296
|
+
*/
|
|
297
|
+
protected hydrateKind(field: FieldOptions | undefined): HydrateKind | undefined;
|
|
298
|
+
private readonly hydratable;
|
|
254
299
|
/** The one type dispatch for a persisted value, over a column kind decided by the caller. */
|
|
255
300
|
private writePersistableValue;
|
|
256
301
|
protected appendJsonValue(ctx: QueryContext, value: unknown, _type: JsonColumnType): void;
|
|
@@ -348,8 +393,15 @@ export declare abstract class AbstractSqlDialect extends IndexSqlDialect impleme
|
|
|
348
393
|
* @param sizeExprFn - function that appends the size expression to ctx (e.g. `jsonb_array_length("col")`)
|
|
349
394
|
*/
|
|
350
395
|
protected buildSizeComparison(ctx: QueryContext, sizeExprFn: () => void, sizeVal: number | QuerySizeComparisonOps): void;
|
|
396
|
+
/** The runtime half of {@link QuerySizeComparisonOps}: what a count can sensibly be compared with. */
|
|
397
|
+
private static readonly SIZE_COMPARE_OPS;
|
|
351
398
|
/**
|
|
352
|
-
* Append a single size comparison operator and value
|
|
399
|
+
* Append a single size comparison operator and value. No operand: the count expression is already
|
|
400
|
+
* in the context, so this contributes only the ` <op> <value>` tail.
|
|
401
|
+
*
|
|
402
|
+
* Gated on {@link SIZE_COMPARE_OPS} rather than on whatever the shared renderer accepts, because
|
|
403
|
+
* that renderer also knows `$like`, `$regex` and `$in`, none of which mean anything against a
|
|
404
|
+
* count. `$size: { $like: 5 }` has to stay the error it always was.
|
|
353
405
|
*/
|
|
354
406
|
private appendSizeOp;
|
|
355
407
|
/** ANSI-style single-quote escaping. MySQL-family dialects override this for backslash escaping. */
|
|
@@ -371,4 +423,3 @@ export declare abstract class AbstractSqlDialect extends IndexSqlDialect impleme
|
|
|
371
423
|
protected numericCast(expr: string): string;
|
|
372
424
|
toString(): string;
|
|
373
425
|
}
|
|
374
|
-
export {};
|