uql-orm 0.51.0 → 0.53.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 +1 -1
- package/dist/browser/uql-browser.min.js +2 -2
- package/dist/browser/uql-browser.min.js.map +5 -5
- package/dist/bunSql/bunSql.util.d.ts +33 -10
- package/dist/bunSql/bunSql.util.js +57 -42
- package/dist/bunSql/bunSqlQuerier.d.ts +13 -8
- package/dist/bunSql/bunSqlQuerier.js +17 -8
- package/dist/bunSql/bunSqlQuerierPool.d.ts +10 -2
- package/dist/bunSql/bunSqlQuerierPool.js +38 -25
- package/dist/bunSql/index.d.ts +1 -3
- package/dist/bunSql/index.js +0 -3
- package/dist/dialect/abstractDialect.d.ts +5 -5
- package/dist/dialect/abstractDialect.js +7 -6
- package/dist/dialect/abstractSqlDialect.d.ts +59 -6
- package/dist/dialect/abstractSqlDialect.js +90 -32
- package/dist/dialect/aliases.d.ts +2 -0
- package/dist/dialect/aliases.js +2 -0
- package/dist/dialect/mergeSqlDialect.d.ts +45 -0
- package/dist/dialect/mergeSqlDialect.js +89 -0
- package/dist/dialect/mysqlLikeSqlDialect.d.ts +0 -1
- package/dist/dialect/mysqlLikeSqlDialect.js +3 -3
- package/dist/dialect/pgLikeSqlDialect.js +3 -2
- package/dist/dialect/vectorSqlDialect.js +2 -1
- package/dist/http/handler.js +3 -12
- package/dist/http/query.js +4 -1
- package/dist/migrate/builder/expressions.js +5 -0
- package/dist/migrate/ddl/index.d.ts +8 -0
- package/dist/migrate/ddl/index.js +11 -0
- package/dist/migrate/ddl/mssqlTableDdl.d.ts +23 -0
- package/dist/migrate/ddl/mssqlTableDdl.js +61 -0
- package/dist/migrate/ddl/tableDdl.d.ts +34 -0
- package/dist/migrate/ddl/tableDdl.js +71 -0
- package/dist/migrate/introspection/index.d.ts +2 -0
- package/dist/migrate/introspection/index.js +2 -0
- package/dist/migrate/introspection/mssqlIntrospector.d.ts +60 -0
- package/dist/migrate/introspection/mssqlIntrospector.js +205 -0
- package/dist/migrate/introspection/registry.d.ts +3 -0
- package/dist/migrate/introspection/registry.js +28 -0
- package/dist/migrate/migrator.js +2 -21
- package/dist/migrate/schemaGenerator.d.ts +8 -10
- package/dist/migrate/schemaGenerator.js +29 -74
- package/dist/mongo/mongoDialect.js +12 -14
- package/dist/mssql/index.d.ts +3 -0
- package/dist/mssql/index.js +3 -0
- package/dist/mssql/mssqlDialect.d.ts +155 -0
- package/dist/mssql/mssqlDialect.js +341 -0
- package/dist/mssql/mssqlQuerier.d.ts +23 -0
- package/dist/mssql/mssqlQuerier.js +137 -0
- package/dist/mssql/mssqlQuerierPool.d.ts +17 -0
- package/dist/mssql/mssqlQuerierPool.js +32 -0
- package/dist/mssql/mssqlWireTypes.d.ts +23 -0
- package/dist/mssql/mssqlWireTypes.js +44 -0
- package/dist/pglite/pgliteQuerier.d.ts +4 -2
- package/dist/pglite/pgliteQuerier.js +7 -2
- package/dist/postgres/pgCursorStream.d.ts +20 -0
- package/dist/postgres/pgCursorStream.js +49 -0
- package/dist/postgres/pgDialect.d.ts +1 -1
- package/dist/postgres/pgDialect.js +1 -1
- package/dist/postgres/postgresWireDriverCapabilities.d.ts +12 -10
- package/dist/postgres/postgresWireDriverCapabilities.js +12 -10
- package/dist/querier/abstractQuerier.js +13 -11
- package/dist/querier/abstractSqlQuerier.js +3 -3
- package/dist/schema/canonicalType.js +96 -113
- package/dist/sqlite/sqliteDialect.js +3 -2
- package/dist/type/dialect.d.ts +24 -5
- package/dist/type/migratorDialect.d.ts +1 -1
- package/dist/type/migratorDialect.js +1 -0
- package/dist/type/query.d.ts +1 -1
- package/dist/type/queryWhere.d.ts +7 -19
- package/dist/type/vector.d.ts +3 -1
- package/dist/util/dialect.util.d.ts +10 -7
- package/dist/util/dialect.util.js +16 -29
- package/dist/util/object.util.d.ts +2 -0
- package/dist/util/object.util.js +4 -0
- package/package.json +13 -3
- package/dist/bunSql/bunSqlCockroachDialect.d.ts +0 -12
- package/dist/bunSql/bunSqlCockroachDialect.js +0 -15
- package/dist/bunSql/bunSqlPostgresDialect.d.ts +0 -11
- package/dist/bunSql/bunSqlPostgresDialect.js +0 -14
- package/dist/bunSql/bunSqliteDialect.d.ts +0 -6
- package/dist/bunSql/bunSqliteDialect.js +0 -6
|
@@ -1,19 +1,28 @@
|
|
|
1
1
|
import { SQL } from 'bun';
|
|
2
|
+
import { CockroachDialect } from '../cockroachdb/cockroachDialect.js';
|
|
2
3
|
import { dialectOptionsFrom } from '../dialect/abstractDialect.js';
|
|
3
4
|
import { MariaDialect } from '../maria/mariaDialect.js';
|
|
4
5
|
import { MySqlDialect } from '../mysql/mysqlDialect.js';
|
|
6
|
+
import { PostgresDialect } from '../postgres/postgresDialect.js';
|
|
7
|
+
import { POSTGRES_WIRE_DRIVER_CAPABILITIES } from '../postgres/postgresWireDriverCapabilities.js';
|
|
5
8
|
import { AbstractSqlQuerierPool } from '../querier/index.js';
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
8
|
-
import { BunSqlPostgresDialect } from './bunSqlPostgresDialect.js';
|
|
9
|
+
import { SqliteDialect } from '../sqlite/sqliteDialect.js';
|
|
10
|
+
import { getAffectedRows, inferDialectName, normalizeBunOpts, normalizeRows, } from './bunSql.util.js';
|
|
9
11
|
import { BunSqlQuerier } from './bunSqlQuerier.js';
|
|
10
|
-
|
|
12
|
+
/**
|
|
13
|
+
* The dialect each engine `bun:sql` drives is given, and how this driver shapes its parameters.
|
|
14
|
+
*
|
|
15
|
+
* The engine dialects themselves, not `bun:sql` subclasses of them: what Bun changes is the binding,
|
|
16
|
+
* never the SQL, and a per-instance `driverCapabilities` is where the base class already takes that -
|
|
17
|
+
* so the Postgres and CockroachDB entries differ from `PgQuerierPool`'s only by naming the same
|
|
18
|
+
* constant. Total over {@link BunSqlDialectName}, so a new Bun adapter has to be answered here.
|
|
19
|
+
*/
|
|
11
20
|
const DialectMap = {
|
|
12
|
-
postgres:
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
21
|
+
postgres: [PostgresDialect, POSTGRES_WIRE_DRIVER_CAPABILITIES],
|
|
22
|
+
cockroachdb: [CockroachDialect, POSTGRES_WIRE_DRIVER_CAPABILITIES],
|
|
23
|
+
mysql: [MySqlDialect],
|
|
24
|
+
mariadb: [MariaDialect],
|
|
25
|
+
sqlite: [SqliteDialect],
|
|
17
26
|
};
|
|
18
27
|
export class BunSqlQuerierPool extends AbstractSqlQuerierPool {
|
|
19
28
|
config;
|
|
@@ -22,7 +31,8 @@ export class BunSqlQuerierPool extends AbstractSqlQuerierPool {
|
|
|
22
31
|
foreignKeysOn;
|
|
23
32
|
constructor(config, extra) {
|
|
24
33
|
const dialectName = inferDialectName(config);
|
|
25
|
-
|
|
34
|
+
const [Dialect, driverCapabilities] = DialectMap[dialectName];
|
|
35
|
+
super(new Dialect({ ...dialectOptionsFrom(extra), driverCapabilities }), extra);
|
|
26
36
|
this.config = config;
|
|
27
37
|
this.sqlDialectName = dialectName;
|
|
28
38
|
const opts = normalizeBunOpts(config, dialectName);
|
|
@@ -34,28 +44,31 @@ export class BunSqlQuerierPool extends AbstractSqlQuerierPool {
|
|
|
34
44
|
*/
|
|
35
45
|
get pool() {
|
|
36
46
|
return {
|
|
37
|
-
query: (text, values) => this.sql.unsafe(text, this.dialect.normalizeValues(values)).then((res) =>
|
|
38
|
-
rows
|
|
39
|
-
rowCount: getAffectedRows(res)
|
|
40
|
-
})
|
|
47
|
+
query: (text, values) => this.sql.unsafe(text, this.dialect.normalizeValues(values)).then((res) => {
|
|
48
|
+
const rows = normalizeRows(res);
|
|
49
|
+
return { rows, rowCount: getAffectedRows(res) ?? rows.length };
|
|
50
|
+
}),
|
|
41
51
|
on: () => {
|
|
42
52
|
/* no-op for event listeners */
|
|
43
53
|
},
|
|
44
54
|
};
|
|
45
55
|
}
|
|
46
56
|
async getQuerier() {
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
57
|
+
return new BunSqlQuerier(this.sql, this.dialect, () => this.acquire(), this.extra);
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* Bun's SQLite adapter does not support connection reservation (it's unpooled), and leaves
|
|
61
|
+
* `foreign_keys` off as `bun:sqlite` does, so without the pragma the constraints uql emits in its
|
|
62
|
+
* own DDL are decorative. One connection means one pragma, issued on the first acquisition, and a
|
|
63
|
+
* `release` that does nothing: the handle is the pool's, and outlives every querier over it.
|
|
64
|
+
*/
|
|
65
|
+
async acquire() {
|
|
66
|
+
if (this.sqlDialectName !== 'sqlite') {
|
|
56
67
|
return this.sql.reserve();
|
|
57
|
-
}
|
|
58
|
-
|
|
68
|
+
}
|
|
69
|
+
this.foreignKeysOn ??= this.sql.unsafe('PRAGMA foreign_keys = ON');
|
|
70
|
+
await this.foreignKeysOn;
|
|
71
|
+
return { unsafe: this.sql.unsafe.bind(this.sql), release: () => { } };
|
|
59
72
|
}
|
|
60
73
|
async end() {
|
|
61
74
|
await this.sql.close();
|
package/dist/bunSql/index.d.ts
CHANGED
|
@@ -1,5 +1,3 @@
|
|
|
1
|
-
export
|
|
2
|
-
export * from './bunSqlCockroachDialect.js';
|
|
3
|
-
export * from './bunSqlPostgresDialect.js';
|
|
1
|
+
export type { BunSqlConn, BunSqlDialectName, BunSqlResult } from './bunSql.util.js';
|
|
4
2
|
export * from './bunSqlQuerier.js';
|
|
5
3
|
export * from './bunSqlQuerierPool.js';
|
package/dist/bunSql/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { DialectFeatures, DialectName, EntityMeta, ExtraOptions, FieldOptions, InsertIdSource, NamingStrategy, QueryGroupOp, QueryOptions, QueryWhere, QueryWhereArray
|
|
1
|
+
import type { DialectFeatures, DialectName, EntityMeta, ExtraOptions, FieldOptions, InsertIdSource, NamingStrategy, QueryGroupOp, QueryOptions, QueryWhere, QueryWhereArray } from '../type/index.js';
|
|
2
2
|
/**
|
|
3
3
|
* Options for initializing a dialect.
|
|
4
4
|
*/
|
|
@@ -72,11 +72,11 @@ export declare abstract class AbstractDialect {
|
|
|
72
72
|
*/
|
|
73
73
|
columnOf<E>(meta: EntityMeta<E>, key: string): string;
|
|
74
74
|
/**
|
|
75
|
-
* A `$where`
|
|
76
|
-
*
|
|
77
|
-
*
|
|
75
|
+
* A `$where` with the entity's active filters merged in - the only way any dialect should enter a
|
|
76
|
+
* new query scope, so a scope cannot be rendered with its `security: true` filters skipped.
|
|
77
|
+
* Recursion within one scope renders the returned map directly instead.
|
|
78
78
|
*/
|
|
79
|
-
protected
|
|
79
|
+
protected scopedWhere<E>(meta: EntityMeta<E>, where?: QueryWhere<E>, opts?: QueryOptions): QueryWhere<E>;
|
|
80
80
|
/**
|
|
81
81
|
* How each clause-grouping operator renders: which operator joins its clauses, and whether the
|
|
82
82
|
* group is negated afterwards - so `$not` is `NOT (a AND b)` and `$nor` is `NOT (a OR b)`. SQL
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { applyFilters,
|
|
1
|
+
import { applyFilters, assertWhere } from '../util/dialect.util.js';
|
|
2
2
|
import { entityName } from '../util/index.js';
|
|
3
3
|
import { qualifyName } from '../util/sql.util.js';
|
|
4
4
|
/**
|
|
@@ -81,12 +81,13 @@ export class AbstractDialect {
|
|
|
81
81
|
return this.resolveColumnName(key, meta.fields[key]);
|
|
82
82
|
}
|
|
83
83
|
/**
|
|
84
|
-
* A `$where`
|
|
85
|
-
*
|
|
86
|
-
*
|
|
84
|
+
* A `$where` with the entity's active filters merged in - the only way any dialect should enter a
|
|
85
|
+
* new query scope, so a scope cannot be rendered with its `security: true` filters skipped.
|
|
86
|
+
* Recursion within one scope renders the returned map directly instead.
|
|
87
87
|
*/
|
|
88
|
-
|
|
89
|
-
|
|
88
|
+
scopedWhere(meta, where = {}, opts) {
|
|
89
|
+
assertWhere(meta, where);
|
|
90
|
+
return applyFilters(meta, where, opts);
|
|
90
91
|
}
|
|
91
92
|
/**
|
|
92
93
|
* How each clause-grouping operator renders: which operator joins its clauses, and whether the
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { type EntityMeta, type FieldKey, type FieldOptions, type IsolationLevel, type JsonColumnType, type JsonUpdateOp, type Query, type QueryAggMap, type QueryAggregate, type QueryBuildFn, type QueryComparisonOptions, type QueryConflictPaths, type QueryContext, type QueryDialect, type QueryExclude, type QueryFilter, type QueryGroupMap, type QueryGroupOp, type QueryHavingMap, type QueryOptions, type QueryPager, QueryRaw, type QueryRawFnOptions, type QuerySearch, type QuerySelectOptions, type QuerySelectValue, type QuerySizeComparisonOps, type QuerySortMap, type QueryTextSearchOptions, type QueryVectorNear, type QueryWhere, type QueryWhereArray, type QueryWhereFieldOperatorMap, type
|
|
1
|
+
import { type EntityData, type EntityMeta, type FieldKey, type FieldOptions, type IsolationLevel, type JsonColumnType, type JsonUpdateOp, type Query, type QueryAggMap, type QueryAggregate, type QueryBuildFn, type QueryComparisonOptions, type QueryConflictPaths, type QueryContext, type QueryDialect, type QueryExclude, type QueryFilter, type QueryGroupMap, type QueryGroupOp, type QueryHavingMap, type QueryOptions, type QueryPager, QueryRaw, type QueryRawFnOptions, type QuerySearch, type QuerySelectOptions, type QuerySelectValue, type QuerySizeComparisonOps, type QuerySortMap, type QueryTextSearchOptions, type QueryVectorNear, type QueryWhere, type QueryWhereArray, type QueryWhereFieldOperatorMap, type QueryWhereOptions, type RelationMeta, type SqlDialectName, type SqlQueryDialect, type Type, type UpdatePayload } from '../type/index.js';
|
|
2
2
|
import { type ParentPartition } from '../util/index.js';
|
|
3
3
|
import type { HydrateKind } from './hydrateColumn.js';
|
|
4
4
|
import { type JsonAccessMode } from './jsonSql.js';
|
|
@@ -6,6 +6,15 @@ import { type QueryJoins, type QuerySortOptions } from './queryJoins.js';
|
|
|
6
6
|
import { VectorSqlDialect } from './vectorSqlDialect.js';
|
|
7
7
|
/** How a column's values are bound: see {@link AbstractSqlDialect.persistKind}. */
|
|
8
8
|
type PersistKind = 'plain' | 'json' | 'vector';
|
|
9
|
+
/** What {@link AbstractSqlDialect.insertShape} resolves once for a write, indexed in step. */
|
|
10
|
+
type InsertShape<E> = {
|
|
11
|
+
readonly meta: EntityMeta<E>;
|
|
12
|
+
readonly payloads: EntityData<E>[];
|
|
13
|
+
readonly keys: FieldKey<E>[];
|
|
14
|
+
readonly fields: (FieldOptions | undefined)[];
|
|
15
|
+
readonly columns: string[];
|
|
16
|
+
readonly kinds: PersistKind[];
|
|
17
|
+
};
|
|
9
18
|
/** One entry of {@link AbstractSqlDialect.hydratableFields}: a field key and how it decodes. */
|
|
10
19
|
type HydratableField = readonly [string, HydrateKind];
|
|
11
20
|
export type { HydrateKind };
|
|
@@ -45,7 +54,6 @@ export declare abstract class AbstractSqlDialect extends VectorSqlDialect implem
|
|
|
45
54
|
*/
|
|
46
55
|
readonly dropPrimaryKeySyntax: 'DROP CONSTRAINT' | 'DROP PRIMARY KEY';
|
|
47
56
|
readonly dropIndexSyntax: 'on-table' | 'standalone';
|
|
48
|
-
readonly renameTableSyntax: 'rename-table' | 'alter-table';
|
|
49
57
|
readonly booleanLiteral: 'native' | 'integer';
|
|
50
58
|
/**
|
|
51
59
|
* Maximum number of bind parameters the driver accepts in a single statement.
|
|
@@ -111,6 +119,11 @@ export declare abstract class AbstractSqlDialect extends VectorSqlDialect implem
|
|
|
111
119
|
protected returningIdExpression<E>(meta: EntityMeta<E>): string;
|
|
112
120
|
search<E>(ctx: QueryContext, entity: Type<E>, q?: Query<E>, opts?: QueryOptions, joins?: QueryJoins): void;
|
|
113
121
|
selectFields<E>(ctx: QueryContext, entity: Type<E>, select: QuerySelectValue<E> | undefined, opts?: QuerySelectOptions, exclude?: QueryExclude<E>): void;
|
|
122
|
+
/**
|
|
123
|
+
* What follows `SELECT` before the projection. Empty everywhere but SQL Server, whose `FETCH` will
|
|
124
|
+
* not take a zero and which spells "no rows" as `TOP (0)` instead.
|
|
125
|
+
*/
|
|
126
|
+
protected selectModifier<E>(_q: Query<E>): string;
|
|
114
127
|
/**
|
|
115
128
|
* The expression a scalar field is read through, the plain column by default. MariaDB reads a
|
|
116
129
|
* vector column back with `VEC_ToText`, since selecting it raw yields its binary form.
|
|
@@ -280,7 +293,9 @@ export declare abstract class AbstractSqlDialect extends VectorSqlDialect implem
|
|
|
280
293
|
protected jsonScalarParam(ctx: QueryContext, value: unknown): string;
|
|
281
294
|
/** {@link resolveOperandField}, appended. */
|
|
282
295
|
getComparisonKey<E>(ctx: QueryContext, entity: Type<E>, key: FieldKey<E>, opts?: QueryOptions): void;
|
|
283
|
-
|
|
296
|
+
/** Appends the `ORDER BY`, reporting whether there was one - which {@link pager} needs on the
|
|
297
|
+
* engines that refuse to page an unordered statement. */
|
|
298
|
+
sort<E>(ctx: QueryContext, entity: Type<E>, sort: QuerySortMap<E> | undefined, opts?: QuerySortOptions): boolean;
|
|
284
299
|
/**
|
|
285
300
|
* Walks `$sort` against the metadata of the entity each level addresses, rather than flattening it
|
|
286
301
|
* to dotted strings and reading every key off the root: only that way does a related column resolve
|
|
@@ -293,7 +308,11 @@ export declare abstract class AbstractSqlDialect extends VectorSqlDialect implem
|
|
|
293
308
|
* `$agg` alias - is an output alias, which is never table-qualified and needs no resolving.
|
|
294
309
|
*/
|
|
295
310
|
private sortColumn;
|
|
296
|
-
|
|
311
|
+
/**
|
|
312
|
+
* `LIMIT`/`OFFSET`. `sorted` says whether an `ORDER BY` was emitted just before, which
|
|
313
|
+
* {@link MergeSqlDialect} needs: SQL Server refuses to page a statement that has none.
|
|
314
|
+
*/
|
|
315
|
+
pager(ctx: QueryContext, opts: QueryPager, _sorted?: boolean): void;
|
|
297
316
|
/** Whether this engine has row locks at all. The SQLite family locks the database instead. */
|
|
298
317
|
readonly supportsRowLocks: boolean;
|
|
299
318
|
/**
|
|
@@ -306,6 +325,12 @@ export declare abstract class AbstractSqlDialect extends VectorSqlDialect implem
|
|
|
306
325
|
readonly supportsLockOf: boolean;
|
|
307
326
|
/** Validated before the querier checks for a transaction, so the clearer error wins. */
|
|
308
327
|
assertLockSupported<E>(entity: Type<E>, q: Query<E>, joins?: QueryJoins): void;
|
|
328
|
+
/**
|
|
329
|
+
* The lock as a hint on the table itself, for the engine that has no trailing `FOR UPDATE`. Empty
|
|
330
|
+
* everywhere else, which is where {@link appendLock} does the work instead - the two are the same
|
|
331
|
+
* lock spelled at opposite ends of the statement, so exactly one of them ever emits.
|
|
332
|
+
*/
|
|
333
|
+
protected lockHint<E>(_q: Query<E>): string;
|
|
309
334
|
/**
|
|
310
335
|
* The trailing `FOR UPDATE`. Narrowing to the queried table is not a nicety once a relation is
|
|
311
336
|
* joined: Postgres refuses a bare `FOR UPDATE` over the nullable side of an outer join outright,
|
|
@@ -354,11 +379,32 @@ export declare abstract class AbstractSqlDialect extends VectorSqlDialect implem
|
|
|
354
379
|
protected readonly totalOverExpr = "COUNT(*) OVER ()";
|
|
355
380
|
find<E>(ctx: QueryContext, entity: Type<E>, q?: Query<E>, opts?: QueryOptions, totalAlias?: string): void;
|
|
356
381
|
insert<E>(ctx: QueryContext, entity: Type<E>, payload: E | E[], opts?: QueryOptions): void;
|
|
382
|
+
/**
|
|
383
|
+
* Where the clause reporting an insert's generated ids goes. `suffix` is `RETURNING ...` at the end
|
|
384
|
+
* of the statement, which every engine here but one spells that way; SQL Server's `OUTPUT` has no
|
|
385
|
+
* trailing form and sits between the column list and `VALUES`.
|
|
386
|
+
*
|
|
387
|
+
* A knob rather than a pair of hooks: one concept decides where the string {@link returningId}
|
|
388
|
+
* already built ends up, so the two ends cannot disagree.
|
|
389
|
+
*/
|
|
390
|
+
readonly returningPosition: 'suffix' | 'after-target';
|
|
357
391
|
/**
|
|
358
392
|
* `INSERT INTO ... VALUES (...)` and nothing more. The upsert builders extend this rather than
|
|
359
393
|
* {@link insert}: their own clause has to come before the `RETURNING`, not after it.
|
|
360
394
|
*/
|
|
361
|
-
protected appendInsertValues<E>(ctx: QueryContext, entity: Type<E>, payload: E | E[]
|
|
395
|
+
protected appendInsertValues<E>(ctx: QueryContext, entity: Type<E>, payload: E | E[],
|
|
396
|
+
/** Spliced between the column list and `VALUES`; see {@link returningPosition}. */
|
|
397
|
+
afterTarget?: string): void;
|
|
398
|
+
/**
|
|
399
|
+
* The columns an insert writes and the records it writes them from, resolved once.
|
|
400
|
+
*
|
|
401
|
+
* Split out of {@link appendInsertValues} because a `MERGE` needs the same rows as a `VALUES` row
|
|
402
|
+
* source rather than as an `INSERT`, and both have to apply `onInsert` defaults and the
|
|
403
|
+
* JSON/vector binding rules identically.
|
|
404
|
+
*/
|
|
405
|
+
protected insertShape<E>(entity: Type<E>, payload: E | E[]): InsertShape<E>;
|
|
406
|
+
/** `(a, b), (c, d)` - the row constructor an INSERT and a MERGE source both write. */
|
|
407
|
+
protected appendValueRows<E>(ctx: QueryContext, { payloads, keys, fields, kinds }: InsertShape<E>): void;
|
|
362
408
|
/**
|
|
363
409
|
* Emit the value for a column a payload record does not provide (the column list is the union
|
|
364
410
|
* across all records). `DEFAULT` delegates to the database default; SQLite overrides this since
|
|
@@ -550,7 +596,7 @@ export declare abstract class AbstractSqlDialect extends VectorSqlDialect implem
|
|
|
550
596
|
*/
|
|
551
597
|
private appendRelationSubquery;
|
|
552
598
|
/** Filter by relation: a parent matches when {@link appendRelationSubquery} finds one target row. */
|
|
553
|
-
protected compareRelation<E>(ctx: QueryContext, entity: Type<E>, val:
|
|
599
|
+
protected compareRelation<E>(ctx: QueryContext, entity: Type<E>, val: QueryWhere<unknown>, rel: RelationMeta, opts: QueryComparisonOptions): void;
|
|
554
600
|
/** Filter by relation size: the same subquery, counting instead of testing for existence. */
|
|
555
601
|
protected compareRelationSize<E>(ctx: QueryContext, entity: Type<E>, sizeVal: number | QuerySizeComparisonOps, rel: RelationMeta, opts: QueryComparisonOptions): void;
|
|
556
602
|
/**
|
|
@@ -587,6 +633,13 @@ export declare abstract class AbstractSqlDialect extends VectorSqlDialect implem
|
|
|
587
633
|
/** ANSI-style single-quote escaping. MySQL-family dialects override this for backslash escaping. */
|
|
588
634
|
escape(value: unknown): string;
|
|
589
635
|
protected get regexpOp(): string;
|
|
636
|
+
/**
|
|
637
|
+
* The `$regex` predicate. An infix operator on the MySQL family (`REGEXP`) and the Postgres one
|
|
638
|
+
* (`~`), but a function on Oracle and SQL Server 2025 (`REGEXP_LIKE(col, ?)`) - which is why this
|
|
639
|
+
* is a method rather than the operator token alone. An engine with no regex at all overrides it to
|
|
640
|
+
* throw, the way {@link appendTextSearch} already does.
|
|
641
|
+
*/
|
|
642
|
+
protected regexCondition(operand: string, placeholder: string): string;
|
|
590
643
|
protected get likeFn(): string;
|
|
591
644
|
/**
|
|
592
645
|
* Not-equal operator token for non-null comparisons.
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { getMeta, soleIdOf } from '../entity/index.js';
|
|
2
2
|
import { parseQueryLock, QueryRaw, RAW_ALIAS, RAW_VALUE, VECTOR_QUERY_KEYS, } from '../type/index.js';
|
|
3
3
|
import { computedExpression, isInlinedExpression } from '../util/field.util.js';
|
|
4
|
-
import { asSelectMap, assertNonNegativeInteger,
|
|
4
|
+
import { asSelectMap, assertNonNegativeInteger, escapeSqlId, fillOnFields, filterFieldKeys, getInsertFieldKeys, getKeys, getSoftDeleteValue, hasKeys, columnFamily, isJsonUpdateOp, isOperatorMap, isOperatorObject, isOperatorOnlyObject, isVectorSearch, normalizeScalarFieldSelection, parentJoins, targetKeyColumns, parseGroupMap, parseRelationSize, parseSortByCount, populatesRelations, queryChildrenOf, raw, someValue, throwUnknownAggregateColumn, withoutSoftDeleteFilter, } from '../util/index.js';
|
|
5
5
|
import { escapeAnsiSqlLiteral, escapeSingleQuotes } from '../util/sqlLiteral.js';
|
|
6
6
|
import { COUNT_ALIAS, DISTINCT_DERIVED_ALIAS, JSON_ELEM_ALIAS_PREFIX, PER_PARENT_BRANCH_ALIAS } from './aliases.js';
|
|
7
7
|
import { buildElemMatchConditions } from './jsonArrayElemMatchUtils.js';
|
|
@@ -36,7 +36,6 @@ export class AbstractSqlDialect extends VectorSqlDialect {
|
|
|
36
36
|
*/
|
|
37
37
|
dropPrimaryKeySyntax = 'DROP CONSTRAINT';
|
|
38
38
|
dropIndexSyntax = 'standalone';
|
|
39
|
-
renameTableSyntax = 'alter-table';
|
|
40
39
|
booleanLiteral = 'native';
|
|
41
40
|
/**
|
|
42
41
|
* Maximum number of bind parameters the driver accepts in a single statement.
|
|
@@ -168,8 +167,8 @@ export class AbstractSqlDialect extends VectorSqlDialect {
|
|
|
168
167
|
opts = { ...opts, prefix };
|
|
169
168
|
}
|
|
170
169
|
this.where(ctx, entity, q.$where, opts);
|
|
171
|
-
this.sort(ctx, entity, q.$sort, { prefix, joins, distinct: q.$distinct });
|
|
172
|
-
this.pager(ctx, q);
|
|
170
|
+
const sorted = this.sort(ctx, entity, q.$sort, { prefix, joins, distinct: q.$distinct });
|
|
171
|
+
this.pager(ctx, q, sorted);
|
|
173
172
|
}
|
|
174
173
|
selectFields(ctx, entity, select, opts = {}, exclude) {
|
|
175
174
|
const meta = getMeta(entity);
|
|
@@ -227,6 +226,13 @@ export class AbstractSqlDialect extends VectorSqlDialect {
|
|
|
227
226
|
}
|
|
228
227
|
});
|
|
229
228
|
}
|
|
229
|
+
/**
|
|
230
|
+
* What follows `SELECT` before the projection. Empty everywhere but SQL Server, whose `FETCH` will
|
|
231
|
+
* not take a zero and which spells "no rows" as `TOP (0)` instead.
|
|
232
|
+
*/
|
|
233
|
+
selectModifier(_q) {
|
|
234
|
+
return '';
|
|
235
|
+
}
|
|
230
236
|
/**
|
|
231
237
|
* The expression a scalar field is read through, the plain column by default. MariaDB reads a
|
|
232
238
|
* vector column back with `VEC_ToText`, since selecting it raw yields its binary form.
|
|
@@ -248,6 +254,7 @@ export class AbstractSqlDialect extends VectorSqlDialect {
|
|
|
248
254
|
const { alias, ref } = this.tableRef(meta);
|
|
249
255
|
const prefix = this.resolveRelationAwarePrefix(alias, meta, opts, q.$populate, joins);
|
|
250
256
|
ctx.append(q.$distinct ? 'SELECT DISTINCT ' : 'SELECT ');
|
|
257
|
+
ctx.append(this.selectModifier(q));
|
|
251
258
|
this.selectFields(ctx, entity, q.$select, { prefix }, q.$exclude);
|
|
252
259
|
// Add related fields BEFORE FROM clause
|
|
253
260
|
this.selectRelationFields(ctx, joins);
|
|
@@ -261,7 +268,7 @@ export class AbstractSqlDialect extends VectorSqlDialect {
|
|
|
261
268
|
if (totalAlias) {
|
|
262
269
|
ctx.append(`, ${this.totalOverExpr} ${this.escapeId(totalAlias, true)}`);
|
|
263
270
|
}
|
|
264
|
-
ctx.append(` FROM ${ref}`);
|
|
271
|
+
ctx.append(` FROM ${ref}${this.lockHint(q)}`);
|
|
265
272
|
// Add JOINs AFTER FROM clause
|
|
266
273
|
this.selectRelationJoins(ctx, meta, alias, joins);
|
|
267
274
|
}
|
|
@@ -322,21 +329,19 @@ export class AbstractSqlDialect extends VectorSqlDialect {
|
|
|
322
329
|
where(ctx, entity, where = {}, opts = {}) {
|
|
323
330
|
const meta = getMeta(entity);
|
|
324
331
|
// Filters are applied once, here at the scope entry point; recursion uses `renderWhere`.
|
|
325
|
-
this.renderWhere(ctx, entity, this.
|
|
332
|
+
this.renderWhere(ctx, entity, this.scopedWhere(meta, where, opts), opts);
|
|
326
333
|
}
|
|
327
334
|
/** Renders a `$where` tree without applying entity filters (used for same-scope group-operator recursion). */
|
|
328
335
|
renderWhere(ctx, entity, where = {}, opts = {}) {
|
|
329
|
-
const meta = getMeta(entity);
|
|
330
336
|
const { clause = 'WHERE' } = opts;
|
|
331
|
-
const whereMap = buildQueryWhereAsMap(meta, where);
|
|
332
337
|
// An `undefined` value emits nothing, so it must not count towards the terms either: it decides
|
|
333
338
|
// whether the keys below render as operands of an `AND`.
|
|
334
|
-
const whereKeys = getKeys(
|
|
339
|
+
const whereKeys = getKeys(where).filter((key) => where[key] !== undefined);
|
|
335
340
|
// Each key is an operand of the `AND` joining them; a lone key emits this fragment verbatim, so
|
|
336
341
|
// it inherits this one's position instead.
|
|
337
342
|
const childOperand = whereKeys.length > 1 || opts.operand || clause === 'AND';
|
|
338
343
|
const childOpts = opts.operand === childOperand ? opts : { ...opts, operand: childOperand };
|
|
339
|
-
const parts = this.renderOperands(ctx, whereKeys, (fragmentCtx, key) => this.compare(fragmentCtx, entity, key,
|
|
344
|
+
const parts = this.renderOperands(ctx, whereKeys, (fragmentCtx, key) => this.compare(fragmentCtx, entity, key, where[key], childOpts));
|
|
340
345
|
if (!parts.length) {
|
|
341
346
|
return;
|
|
342
347
|
}
|
|
@@ -582,7 +587,7 @@ export class AbstractSqlDialect extends VectorSqlDialect {
|
|
|
582
587
|
case '$ne':
|
|
583
588
|
return val === null ? `${operand} IS NOT NULL` : this.neExpr(operand, this.addValue(ctx.values, val));
|
|
584
589
|
case '$regex':
|
|
585
|
-
return
|
|
590
|
+
return this.regexCondition(operand, this.addValue(ctx.values, val));
|
|
586
591
|
case '$in':
|
|
587
592
|
case '$nin': {
|
|
588
593
|
if (!Array.isArray(val)) {
|
|
@@ -643,7 +648,7 @@ export class AbstractSqlDialect extends VectorSqlDialect {
|
|
|
643
648
|
return `${jsonField} IS NOT NULL`;
|
|
644
649
|
return this.neExpr(comparand(value), this.jsonOperand(ctx, value, asJson));
|
|
645
650
|
case '$regex':
|
|
646
|
-
return
|
|
651
|
+
return this.regexCondition(jsonField, this.addValue(ctx.values, value));
|
|
647
652
|
case '$in':
|
|
648
653
|
case '$nin':
|
|
649
654
|
return this.jsonInNin(ctx, jsonField, comparand, op, value, asJson);
|
|
@@ -737,15 +742,18 @@ export class AbstractSqlDialect extends VectorSqlDialect {
|
|
|
737
742
|
return this.addValue(ctx.values, value);
|
|
738
743
|
}
|
|
739
744
|
ctx.pushValue(JSON.stringify(value));
|
|
740
|
-
|
|
745
|
+
// The placeholder for the value just pushed, so a named or numbered one is spelled correctly.
|
|
746
|
+
return this.jsonCast(this.placeholder(ctx.values.length));
|
|
741
747
|
}
|
|
742
748
|
/** {@link resolveOperandField}, appended. */
|
|
743
749
|
getComparisonKey(ctx, entity, key, opts = {}) {
|
|
744
750
|
ctx.append(this.resolveOperandField(ctx, entity, key, opts));
|
|
745
751
|
}
|
|
752
|
+
/** Appends the `ORDER BY`, reporting whether there was one - which {@link pager} needs on the
|
|
753
|
+
* engines that refuse to page an unordered statement. */
|
|
746
754
|
sort(ctx, entity, sort, opts = {}) {
|
|
747
755
|
if (!hasKeys(sort)) {
|
|
748
|
-
return;
|
|
756
|
+
return false;
|
|
749
757
|
}
|
|
750
758
|
// Collected before anything is appended so an unorderable key is reported instead of half a
|
|
751
759
|
// clause, and because a vector distance is the primary ordering wherever it appears in the map.
|
|
@@ -756,6 +764,7 @@ export class AbstractSqlDialect extends VectorSqlDialect {
|
|
|
756
764
|
if (terms.length) {
|
|
757
765
|
ctx.append(` ORDER BY ${terms.join(', ')}`);
|
|
758
766
|
}
|
|
767
|
+
return terms.length > 0;
|
|
759
768
|
}
|
|
760
769
|
/**
|
|
761
770
|
* Walks `$sort` against the metadata of the entity each level addresses, rather than flattening it
|
|
@@ -815,7 +824,11 @@ export class AbstractSqlDialect extends VectorSqlDialect {
|
|
|
815
824
|
const json = this.resolveJsonDotPath(meta, key, prefix);
|
|
816
825
|
return json ? this.jsonPathExpr(json.column, json.jsonPath, 'text') : this.escapeId(key);
|
|
817
826
|
}
|
|
818
|
-
|
|
827
|
+
/**
|
|
828
|
+
* `LIMIT`/`OFFSET`. `sorted` says whether an `ORDER BY` was emitted just before, which
|
|
829
|
+
* {@link MergeSqlDialect} needs: SQL Server refuses to page a statement that has none.
|
|
830
|
+
*/
|
|
831
|
+
pager(ctx, opts, _sorted = false) {
|
|
819
832
|
// `!== undefined`, not truthiness: `$limit: 0` asks for no rows, where "unset" means every row.
|
|
820
833
|
if (opts.$limit !== undefined) {
|
|
821
834
|
ctx.append(` LIMIT ${assertNonNegativeInteger(opts.$limit, '$limit')}`);
|
|
@@ -847,6 +860,14 @@ export class AbstractSqlDialect extends VectorSqlDialect {
|
|
|
847
860
|
throw new TypeError(`${this.dialectName} cannot narrow a row lock to one table, so $lock cannot be combined with a joined relation`);
|
|
848
861
|
}
|
|
849
862
|
}
|
|
863
|
+
/**
|
|
864
|
+
* The lock as a hint on the table itself, for the engine that has no trailing `FOR UPDATE`. Empty
|
|
865
|
+
* everywhere else, which is where {@link appendLock} does the work instead - the two are the same
|
|
866
|
+
* lock spelled at opposite ends of the statement, so exactly one of them ever emits.
|
|
867
|
+
*/
|
|
868
|
+
lockHint(_q) {
|
|
869
|
+
return '';
|
|
870
|
+
}
|
|
850
871
|
/**
|
|
851
872
|
* The trailing `FOR UPDATE`. Narrowing to the queried table is not a nicety once a relation is
|
|
852
873
|
* joined: Postgres refuses a bare `FOR UPDATE` over the nullable side of an outer join outright,
|
|
@@ -946,8 +967,8 @@ export class AbstractSqlDialect extends VectorSqlDialect {
|
|
|
946
967
|
if (q.$having) {
|
|
947
968
|
this.having(ctx, q.$having, emittedColumns);
|
|
948
969
|
}
|
|
949
|
-
this.aggregateSort(ctx, q.$sort, emittedColumns);
|
|
950
|
-
this.pager(ctx, q);
|
|
970
|
+
const sorted = this.aggregateSort(ctx, q.$sort, emittedColumns);
|
|
971
|
+
this.pager(ctx, q, sorted);
|
|
951
972
|
}
|
|
952
973
|
/**
|
|
953
974
|
* ORDER BY for aggregate queries - handles both entity-field and alias references. A grouped
|
|
@@ -956,13 +977,14 @@ export class AbstractSqlDialect extends VectorSqlDialect {
|
|
|
956
977
|
*/
|
|
957
978
|
aggregateSort(ctx, sort, emittedColumns) {
|
|
958
979
|
if (!hasKeys(sort))
|
|
959
|
-
return;
|
|
980
|
+
return false;
|
|
960
981
|
ctx.append(' ORDER BY ');
|
|
961
982
|
Object.entries(sort).forEach(([key, dir], index) => {
|
|
962
983
|
if (index > 0)
|
|
963
984
|
ctx.append(', ');
|
|
964
985
|
ctx.append(this.aggregateRef(emittedColumns, key, '$sort') + this.resolveSortDirection(dir));
|
|
965
986
|
});
|
|
987
|
+
return true;
|
|
966
988
|
}
|
|
967
989
|
/** The SQL referencing one of an aggregate's emitted columns, rejecting any other name. */
|
|
968
990
|
aggregateRef(emittedColumns, key, clause) {
|
|
@@ -1021,22 +1043,48 @@ export class AbstractSqlDialect extends VectorSqlDialect {
|
|
|
1021
1043
|
this.appendLock(ctx, entity, q, joins);
|
|
1022
1044
|
}
|
|
1023
1045
|
insert(ctx, entity, payload, opts) {
|
|
1024
|
-
this.appendInsertValues(ctx, entity, payload);
|
|
1025
1046
|
// Every engine whose ids come back from the statement itself wants the same clause, so it is
|
|
1026
|
-
//
|
|
1047
|
+
// built once here instead of in an identical `insert` override per dialect. `returningId` is
|
|
1027
1048
|
// empty on a composite key, which has no id to ask for.
|
|
1028
|
-
|
|
1029
|
-
|
|
1030
|
-
|
|
1031
|
-
|
|
1032
|
-
|
|
1049
|
+
const returning = this.insertIdSource === 'returning' ? this.returningId(getMeta(entity)) : '';
|
|
1050
|
+
if (returning && this.returningPosition === 'after-target') {
|
|
1051
|
+
this.appendInsertValues(ctx, entity, payload, returning);
|
|
1052
|
+
return;
|
|
1053
|
+
}
|
|
1054
|
+
this.appendInsertValues(ctx, entity, payload);
|
|
1055
|
+
if (returning) {
|
|
1056
|
+
ctx.append(` ${returning}`);
|
|
1033
1057
|
}
|
|
1034
1058
|
}
|
|
1059
|
+
/**
|
|
1060
|
+
* Where the clause reporting an insert's generated ids goes. `suffix` is `RETURNING ...` at the end
|
|
1061
|
+
* of the statement, which every engine here but one spells that way; SQL Server's `OUTPUT` has no
|
|
1062
|
+
* trailing form and sits between the column list and `VALUES`.
|
|
1063
|
+
*
|
|
1064
|
+
* A knob rather than a pair of hooks: one concept decides where the string {@link returningId}
|
|
1065
|
+
* already built ends up, so the two ends cannot disagree.
|
|
1066
|
+
*/
|
|
1067
|
+
returningPosition = 'suffix';
|
|
1035
1068
|
/**
|
|
1036
1069
|
* `INSERT INTO ... VALUES (...)` and nothing more. The upsert builders extend this rather than
|
|
1037
1070
|
* {@link insert}: their own clause has to come before the `RETURNING`, not after it.
|
|
1038
1071
|
*/
|
|
1039
|
-
appendInsertValues(ctx, entity, payload
|
|
1072
|
+
appendInsertValues(ctx, entity, payload,
|
|
1073
|
+
/** Spliced between the column list and `VALUES`; see {@link returningPosition}. */
|
|
1074
|
+
afterTarget = '') {
|
|
1075
|
+
const shape = this.insertShape(entity, payload);
|
|
1076
|
+
const tableName = this.escapedTableName(getMeta(entity));
|
|
1077
|
+
ctx.append(`INSERT INTO ${tableName} (${shape.columns.join(', ')})${afterTarget ? ` ${afterTarget}` : ''} VALUES `);
|
|
1078
|
+
this.appendValueRows(ctx, shape);
|
|
1079
|
+
}
|
|
1080
|
+
/**
|
|
1081
|
+
* The columns an insert writes and the records it writes them from, resolved once.
|
|
1082
|
+
*
|
|
1083
|
+
* Split out of {@link appendInsertValues} because a `MERGE` needs the same rows as a `VALUES` row
|
|
1084
|
+
* source rather than as an `INSERT`, and both have to apply `onInsert` defaults and the
|
|
1085
|
+
* JSON/vector binding rules identically.
|
|
1086
|
+
*/
|
|
1087
|
+
insertShape(entity, payload) {
|
|
1040
1088
|
const meta = getMeta(entity);
|
|
1041
1089
|
const payloads = fillOnFields(meta, payload, 'onInsert');
|
|
1042
1090
|
const keys = getInsertFieldKeys(meta, payloads);
|
|
@@ -1053,12 +1101,13 @@ export class AbstractSqlDialect extends VectorSqlDialect {
|
|
|
1053
1101
|
columns[i] = this.escapedColumnName(meta, key);
|
|
1054
1102
|
kinds[i] = this.persistKind(field);
|
|
1055
1103
|
}
|
|
1056
|
-
|
|
1057
|
-
|
|
1104
|
+
return { meta, payloads, keys, fields, columns, kinds };
|
|
1105
|
+
}
|
|
1106
|
+
/** `(a, b), (c, d)` - the row constructor an INSERT and a MERGE source both write. */
|
|
1107
|
+
appendValueRows(ctx, { payloads, keys, fields, kinds }) {
|
|
1108
|
+
const width = keys.length;
|
|
1058
1109
|
for (let r = 0; r < payloads.length; r++) {
|
|
1059
|
-
|
|
1060
|
-
ctx.append('), (');
|
|
1061
|
-
}
|
|
1110
|
+
ctx.append(r > 0 ? '), (' : '(');
|
|
1062
1111
|
const record = payloads[r];
|
|
1063
1112
|
for (let i = 0; i < width; i++) {
|
|
1064
1113
|
if (i > 0) {
|
|
@@ -1532,7 +1581,7 @@ export class AbstractSqlDialect extends VectorSqlDialect {
|
|
|
1532
1581
|
const relatedMeta = getMeta(relatedEntity);
|
|
1533
1582
|
const { alias: relatedAlias, ref: relatedRef } = this.tableRef(relatedMeta);
|
|
1534
1583
|
// Resolved before any SQL is emitted: it also decides whether the mm form reaches the target.
|
|
1535
|
-
const targetWhere = this.
|
|
1584
|
+
const targetWhere = this.scopedWhere(relatedMeta, val);
|
|
1536
1585
|
ctx.append(`(SELECT ${projection} FROM `);
|
|
1537
1586
|
// One equality per key of the parent, anded: a composite correlates on every column, and matching
|
|
1538
1587
|
// on part of one would find the rows of a different parent. `parentJoins` is what keeps the two
|
|
@@ -1677,6 +1726,15 @@ export class AbstractSqlDialect extends VectorSqlDialect {
|
|
|
1677
1726
|
get regexpOp() {
|
|
1678
1727
|
return 'REGEXP';
|
|
1679
1728
|
}
|
|
1729
|
+
/**
|
|
1730
|
+
* The `$regex` predicate. An infix operator on the MySQL family (`REGEXP`) and the Postgres one
|
|
1731
|
+
* (`~`), but a function on Oracle and SQL Server 2025 (`REGEXP_LIKE(col, ?)`) - which is why this
|
|
1732
|
+
* is a method rather than the operator token alone. An engine with no regex at all overrides it to
|
|
1733
|
+
* throw, the way {@link appendTextSearch} already does.
|
|
1734
|
+
*/
|
|
1735
|
+
regexCondition(operand, placeholder) {
|
|
1736
|
+
return `${operand} ${this.regexpOp} ${placeholder}`;
|
|
1737
|
+
}
|
|
1680
1738
|
get likeFn() {
|
|
1681
1739
|
return 'LIKE';
|
|
1682
1740
|
}
|
|
@@ -32,6 +32,8 @@ export declare const REL_NESTED_KEY = "_uql_target";
|
|
|
32
32
|
* syntax and keeps `VALUES(col)`.
|
|
33
33
|
*/
|
|
34
34
|
export declare const UPSERT_NEW_ROW_ALIAS = "_uql_new";
|
|
35
|
+
/** The row source a `MERGE` upsert reads its incoming values from, on SQL Server and Oracle. */
|
|
36
|
+
export declare const UPSERT_SOURCE_ALIAS = "_uql_src";
|
|
35
37
|
/**
|
|
36
38
|
* Where a `$sort` by a relation's size parks its tally until the ordering has run. A function, so the
|
|
37
39
|
* `$sort` that names the field and the stage that produces it cannot spell it differently - MongoDB
|
package/dist/dialect/aliases.js
CHANGED
|
@@ -32,6 +32,8 @@ export const REL_NESTED_KEY = '_uql_target';
|
|
|
32
32
|
* syntax and keeps `VALUES(col)`.
|
|
33
33
|
*/
|
|
34
34
|
export const UPSERT_NEW_ROW_ALIAS = '_uql_new';
|
|
35
|
+
/** The row source a `MERGE` upsert reads its incoming values from, on SQL Server and Oracle. */
|
|
36
|
+
export const UPSERT_SOURCE_ALIAS = '_uql_src';
|
|
35
37
|
/**
|
|
36
38
|
* Where a `$sort` by a relation's size parks its tally until the ordering has run. A function, so the
|
|
37
39
|
* `$sort` that names the field and the stage that produces it cannot spell it differently - MongoDB
|