uql-orm 0.24.5 → 0.24.7
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 -28
- package/dist/dialect/abstractSqlDialect.js +196 -147
- 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/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 +8 -0
- package/dist/migrate/migrator.js +19 -29
- package/dist/migrate/schemaGenerator.js +0 -12
- package/dist/mongo/mongoDialect.d.ts +7 -0
- package/dist/mongo/mongoDialect.js +37 -1
- package/dist/mongo/mongodbQuerier.js +8 -3
- 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/abstractQuerier.d.ts +0 -3
- package/dist/querier/abstractQuerier.js +10 -9
- package/dist/querier/abstractSqlQuerier.d.ts +9 -2
- package/dist/querier/abstractSqlQuerier.js +31 -24
- package/dist/schema/canonicalType.js +2 -12
- package/dist/schema/schemaAST.js +0 -24
- package/dist/schema/schemaASTBuilder.js +0 -3
- package/dist/type/query.d.ts +2 -0
- 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 +5 -5
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, 288 kB on the wire, every dialect included.
|
|
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, 288 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: '"' | '`';
|
|
@@ -79,7 +83,6 @@ export declare abstract class AbstractSqlDialect extends IndexSqlDialect impleme
|
|
|
79
83
|
protected renderWhere<E>(ctx: QueryContext, entity: Type<E>, where?: QueryWhere<E>, opts?: QueryWhereOptions): void;
|
|
80
84
|
compare<E>(ctx: QueryContext, entity: Type<E>, key: string, val: unknown, opts?: QueryComparisonOptions): void;
|
|
81
85
|
protected compareLogicalOperator<E>(ctx: QueryContext, entity: Type<E>, key: '$and' | '$or' | '$not' | '$nor', val: QueryWhereArray<E>, opts: QueryComparisonOptions): void;
|
|
82
|
-
/** Simple comparison operators: `getComparisonKey → op → addValue`. */
|
|
83
86
|
/** Memoizes {@link escapedColumnName}; see there for why it is per dialect instance. */
|
|
84
87
|
private readonly escapedColumns;
|
|
85
88
|
private static readonly NEGATE_OP_MAP;
|
|
@@ -100,6 +103,20 @@ export declare abstract class AbstractSqlDialect extends IndexSqlDialect impleme
|
|
|
100
103
|
protected resolveOperandField<E>(ctx: QueryContext, entity: Type<E>, key: string, opts: QueryOptions): string | undefined;
|
|
101
104
|
private appendFieldSql;
|
|
102
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;
|
|
103
120
|
private appendLikeOp;
|
|
104
121
|
private appendEqNe;
|
|
105
122
|
private appendInNin;
|
|
@@ -117,19 +134,6 @@ export declare abstract class AbstractSqlDialect extends IndexSqlDialect impleme
|
|
|
117
134
|
* {@link jsonCompareMode} for why each mode exists.
|
|
118
135
|
*/
|
|
119
136
|
protected jsonComparand(jsonField: string, value: unknown): string;
|
|
120
|
-
/**
|
|
121
|
-
* How a JSON scalar has to be compared against `value` (or, for `$in`/`$nin`, against every element
|
|
122
|
-
* of it). Extracting a JSON value yields *text*, which loses the type, so each operand type is
|
|
123
|
-
* compared in the representation every engine agrees on:
|
|
124
|
-
* - `numeric` - cast the accessor. Keeps `1` equal to a stored `1.0`, which strict JSON equality
|
|
125
|
-
* would not, and satisfies drivers that send typed parameters (`text = integer` otherwise).
|
|
126
|
-
* - `json` - compare the JSON value against a JSON-encoded parameter. No cast recovers a boolean
|
|
127
|
-
* portably: PostgreSQL raises `text = boolean` and MySQL matches `'true'` against `1`.
|
|
128
|
-
* - `text` - compare as extracted, which is also what the string operators need.
|
|
129
|
-
*
|
|
130
|
-
* Mixed operand types fall back to `text`, since one comparison cannot be two shapes at once.
|
|
131
|
-
*/
|
|
132
|
-
protected jsonCompareMode(value: unknown): 'json' | 'numeric' | 'text';
|
|
133
137
|
/** `$all`: the JSON array at `jsonField` contains every value (also serves element containment). */
|
|
134
138
|
protected abstract jsonAll(ctx: QueryContext, jsonField: string, value: unknown): string;
|
|
135
139
|
/** `$size`: the length of the JSON array at `jsonField`, compared against `value`. */
|
|
@@ -172,17 +176,6 @@ export declare abstract class AbstractSqlDialect extends IndexSqlDialect impleme
|
|
|
172
176
|
* - otherwise - per-field conditions over the exploded objects.
|
|
173
177
|
*/
|
|
174
178
|
protected jsonElemMatch(ctx: QueryContext, jsonField: string, match: Record<string, unknown>): string;
|
|
175
|
-
/**
|
|
176
|
-
* Whether the operator reads the JSON *value* instead of its text form. The array operators always
|
|
177
|
-
* do. Equality joins them for boolean operands, because extracting JSON as text loses the type in
|
|
178
|
-
* a way no cast recovers portably: PostgreSQL raises `operator does not exist: text = boolean`,
|
|
179
|
-
* MySQL compares `'true'` to `1` and silently matches nothing, and SQLite's `json_extract` yields
|
|
180
|
-
* `1`. Comparing the JSON value against a JSON-encoded parameter is exact on every dialect.
|
|
181
|
-
*
|
|
182
|
-
* Numbers stay on the text accessor with a numeric cast ({@link jsonComparand}), which keeps
|
|
183
|
-
* `1` equal to `1.0` - JSON equality would not.
|
|
184
|
-
*/
|
|
185
|
-
protected isJsonbOp(op: string, value?: unknown): boolean;
|
|
186
179
|
/**
|
|
187
180
|
* A JSON-encoded bound parameter, cast to the dialect's JSON type. Only the positional-placeholder
|
|
188
181
|
* dialects use this - PostgreSQL binds JSON through {@link PgLikeSqlDialect.jsonScalarParam} instead.
|
|
@@ -205,7 +198,6 @@ export declare abstract class AbstractSqlDialect extends IndexSqlDialect impleme
|
|
|
205
198
|
private static readonly SORT_DIRECTION_MAP;
|
|
206
199
|
private resolveSortDirection;
|
|
207
200
|
/** Scalar comparison operators shared by `HAVING` conditions and `$size` comparisons. */
|
|
208
|
-
private static readonly comparisonOpMap;
|
|
209
201
|
protected havingCondition(ctx: QueryContext, expr: string, condition: QueryHavingMap[string]): void;
|
|
210
202
|
find<E>(ctx: QueryContext, entity: Type<E>, q?: Query<E>, opts?: QueryOptions): void;
|
|
211
203
|
insert<E>(ctx: QueryContext, entity: Type<E>, payload: E | E[], opts?: QueryOptions): void;
|
|
@@ -233,6 +225,15 @@ export declare abstract class AbstractSqlDialect extends IndexSqlDialect impleme
|
|
|
233
225
|
* bind into the main context and skip the second one.
|
|
234
226
|
*/
|
|
235
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;
|
|
236
237
|
/** How an `ON CONFLICT` assignment reads the row that was being inserted. */
|
|
237
238
|
protected readonly upsertExcluded: (columnName: string) => string;
|
|
238
239
|
protected getUpsertUpdateAssignments<E>(ctx: QueryContext, meta: EntityMeta<E>, conflictPaths: QueryConflictPaths<E>, payload: E | E[], callback?: (columnName: string) => string): string;
|
|
@@ -252,6 +253,49 @@ export declare abstract class AbstractSqlDialect extends IndexSqlDialect impleme
|
|
|
252
253
|
* `isJsonType` and `isVectorFieldType` 120 times to get the same six answers.
|
|
253
254
|
*/
|
|
254
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;
|
|
255
299
|
/** The one type dispatch for a persisted value, over a column kind decided by the caller. */
|
|
256
300
|
private writePersistableValue;
|
|
257
301
|
protected appendJsonValue(ctx: QueryContext, value: unknown, _type: JsonColumnType): void;
|
|
@@ -349,8 +393,15 @@ export declare abstract class AbstractSqlDialect extends IndexSqlDialect impleme
|
|
|
349
393
|
* @param sizeExprFn - function that appends the size expression to ctx (e.g. `jsonb_array_length("col")`)
|
|
350
394
|
*/
|
|
351
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;
|
|
352
398
|
/**
|
|
353
|
-
* 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.
|
|
354
405
|
*/
|
|
355
406
|
private appendSizeOp;
|
|
356
407
|
/** ANSI-style single-quote escaping. MySQL-family dialects override this for backslash escaping. */
|
|
@@ -372,4 +423,3 @@ export declare abstract class AbstractSqlDialect extends IndexSqlDialect impleme
|
|
|
372
423
|
protected numericCast(expr: string): string;
|
|
373
424
|
toString(): string;
|
|
374
425
|
}
|
|
375
|
-
export {};
|