uql-orm 0.79.0 → 0.81.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/dist/browser/uql-browser.min.js.map +2 -2
- package/dist/cockroachdb/cockroachDialect.js +5 -1
- package/dist/dialect/abstractDialect.d.ts +1 -31
- package/dist/dialect/abstractDialect.js +3 -27
- package/dist/dialect/abstractSqlDialect.d.ts +25 -56
- package/dist/dialect/abstractSqlDialect.js +78 -145
- package/dist/dialect/aliases.d.ts +5 -0
- package/dist/dialect/aliases.js +5 -0
- package/dist/dialect/mysqlLikeSqlDialect.d.ts +4 -2
- package/dist/dialect/mysqlLikeSqlDialect.js +14 -1
- package/dist/dialect/operators.d.ts +66 -0
- package/dist/dialect/operators.js +129 -0
- package/dist/dialect/pgLikeSqlDialect.d.ts +4 -1
- package/dist/dialect/pgLikeSqlDialect.js +16 -3
- package/dist/dialect/vectorSqlDialect.d.ts +2 -0
- package/dist/dialect/vectorSqlDialect.js +4 -0
- package/dist/entity/decorator/entity.d.ts +6 -1
- package/dist/entity/decorator/entity.js +12 -1
- package/dist/entity/index.d.ts +1 -1
- package/dist/entity/index.js +1 -1
- package/dist/entity/metadata/definition.d.ts +6 -1
- package/dist/entity/metadata/definition.js +19 -0
- package/dist/migrate/builder/expressions.d.ts +2 -0
- package/dist/migrate/builder/expressions.js +24 -0
- package/dist/migrate/cli.js +1 -1
- package/dist/migrate/codegen/entityCodeGenerator.js +2 -2
- package/dist/migrate/codegen/entityTypes.js +1 -2
- package/dist/migrate/codegen/indexDecoratorSource.d.ts +3 -2
- package/dist/migrate/codegen/indexDecoratorSource.js +5 -23
- package/dist/migrate/ddl/mssqlIndexDdl.d.ts +5 -0
- package/dist/migrate/ddl/mssqlIndexDdl.js +10 -0
- package/dist/migrate/ddl/mssqlTableDdl.d.ts +6 -4
- package/dist/migrate/ddl/mssqlTableDdl.js +25 -14
- package/dist/migrate/ddl/mysqlIndexDdl.d.ts +2 -2
- package/dist/migrate/ddl/mysqlIndexDdl.js +7 -6
- package/dist/migrate/ddl/pgIndexDdl.d.ts +2 -1
- package/dist/migrate/ddl/pgIndexDdl.js +8 -6
- package/dist/migrate/ddl/tableDdl.d.ts +5 -2
- package/dist/migrate/ddl/tableDdl.js +13 -7
- package/dist/migrate/drift/driftDetector.d.ts +4 -5
- package/dist/migrate/drift/driftDetector.js +21 -21
- package/dist/migrate/generator/definitionToNode.d.ts +1 -1
- package/dist/migrate/generator/definitionToNode.js +9 -20
- package/dist/migrate/generator/mongoSchemaGenerator.d.ts +5 -1
- package/dist/migrate/generator/mongoSchemaGenerator.js +20 -18
- package/dist/migrate/index.d.ts +2 -1
- package/dist/migrate/index.js +1 -0
- package/dist/migrate/introspection/abstractSqlSchemaIntrospector.d.ts +16 -6
- package/dist/migrate/introspection/abstractSqlSchemaIntrospector.js +18 -4
- package/dist/migrate/introspection/baseSqlIntrospector.js +7 -18
- package/dist/migrate/introspection/mongoIntrospector.d.ts +3 -1
- package/dist/migrate/introspection/mongoIntrospector.js +7 -3
- package/dist/migrate/introspection/mssqlIntrospector.d.ts +1 -0
- package/dist/migrate/introspection/mssqlIntrospector.js +9 -0
- package/dist/migrate/introspection/mysqlIntrospector.d.ts +16 -5
- package/dist/migrate/introspection/mysqlIntrospector.js +39 -2
- package/dist/migrate/introspection/postgresIntrospector.d.ts +30 -21
- package/dist/migrate/introspection/postgresIntrospector.js +70 -43
- package/dist/migrate/introspection/sqliteIntrospector.d.ts +1 -0
- package/dist/migrate/introspection/sqliteIntrospector.js +13 -8
- package/dist/migrate/migrator.d.ts +33 -1
- package/dist/migrate/migrator.js +111 -43
- package/dist/migrate/schemaChange.d.ts +18 -0
- package/dist/migrate/schemaChange.js +37 -0
- package/dist/migrate/schemaGenerator.d.ts +25 -15
- package/dist/migrate/schemaGenerator.js +130 -182
- package/dist/migrate/storage/databaseStorage.d.ts +4 -0
- package/dist/migrate/storage/databaseStorage.js +14 -8
- package/dist/migrate/triggerSql.d.ts +24 -0
- package/dist/migrate/triggerSql.js +229 -0
- package/dist/mongo/mongoDialect.d.ts +0 -21
- package/dist/mongo/mongoDialect.js +105 -100
- package/dist/mongo/mongodbQuerier.js +17 -1
- package/dist/mssql/mssqlDialect.d.ts +18 -7
- package/dist/mssql/mssqlDialect.js +77 -33
- package/dist/mssql/mssqlQuerier.js +2 -2
- package/dist/schema/canonicalType.d.ts +6 -1
- package/dist/schema/canonicalType.js +14 -0
- package/dist/schema/indexDifferences.d.ts +22 -6
- package/dist/schema/indexDifferences.js +23 -8
- package/dist/schema/matchByKey.d.ts +10 -0
- package/dist/schema/matchByKey.js +18 -0
- package/dist/schema/schemaAST.d.ts +6 -2
- package/dist/schema/schemaAST.js +7 -3
- package/dist/schema/schemaASTBuilder.d.ts +4 -8
- package/dist/schema/schemaASTBuilder.js +20 -29
- package/dist/schema/schemaASTDiffer.d.ts +2 -3
- package/dist/schema/schemaASTDiffer.js +15 -36
- package/dist/schema/types.d.ts +14 -15
- package/dist/sqlite/sqliteDialect.d.ts +1 -1
- package/dist/sqlite/sqliteDialect.js +12 -3
- package/dist/type/dialect.d.ts +69 -9
- package/dist/type/entity.d.ts +96 -3
- package/dist/type/migration.d.ts +43 -44
- package/dist/type/query.d.ts +13 -4
- package/dist/type/queryWhere.d.ts +4 -2
- package/dist/util/ddlExpression.util.d.ts +5 -1
- package/dist/util/ddlExpression.util.js +6 -2
- package/dist/util/field.util.d.ts +9 -1
- package/dist/util/field.util.js +14 -2
- package/dist/util/fieldOption.util.d.ts +2 -2
- package/dist/util/fieldOption.util.js +2 -2
- package/dist/util/raw.d.ts +9 -1
- package/dist/util/raw.js +36 -11
- package/dist/util/sql.util.d.ts +12 -0
- package/dist/util/sql.util.js +24 -3
- package/dist/util/uqlError.d.ts +2 -0
- package/dist/util/uqlError.js +4 -0
- package/package.json +4 -4
- package/skills/uql-orm/SKILL.md +11 -6
|
@@ -0,0 +1,229 @@
|
|
|
1
|
+
import { stampEvents } from '../util/field.util.js';
|
|
2
|
+
import { definedEntries } from '../util/object.util.js';
|
|
3
|
+
import { raw, rowColumn, rowRefs } from '../util/raw.js';
|
|
4
|
+
import { ownedName } from '../util/sql.util.js';
|
|
5
|
+
/**
|
|
6
|
+
* One trigger for `dialect`, named for its table and label and ending in a hash of its own SQL. That hash
|
|
7
|
+
* is the whole of change detection: a trigger is in place exactly when its name is installed, and an
|
|
8
|
+
* edited one is a new name, created while the old one drops as no longer declared.
|
|
9
|
+
*/
|
|
10
|
+
export function renderTrigger(dialect, meta, trigger, position) {
|
|
11
|
+
const table = dialect.resolveTableAlias(meta);
|
|
12
|
+
const label = trigger.name ?? `${trigger.on}_${position}`;
|
|
13
|
+
const draft = triggerStatements(dialect, meta, trigger, label);
|
|
14
|
+
const name = ownedName(table, label, draft.join('\n'));
|
|
15
|
+
return { name, statements: triggerStatements(dialect, meta, trigger, name) };
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* What removes one trigger: the trigger, named with its table only where the engine scopes the name to
|
|
19
|
+
* one, and on the Postgres family the function holding its body, which dropping a trigger leaves behind.
|
|
20
|
+
*/
|
|
21
|
+
export function dropTrigger(dialect, meta, name) {
|
|
22
|
+
const { scope, body } = dialect.features.triggers;
|
|
23
|
+
const table = dialect.escapeId(dialect.resolveTableName(meta));
|
|
24
|
+
return [
|
|
25
|
+
`DROP TRIGGER IF EXISTS ${triggerId(dialect, meta, name)}${scope === 'table' ? ` ON ${table}` : ''}`,
|
|
26
|
+
...(body === 'function' ? [`DROP FUNCTION IF EXISTS ${schemaObjectId(dialect, meta, name)}()`] : []),
|
|
27
|
+
];
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* A trigger's name as its statements spell it: bare where the engine keeps the name under its table,
|
|
31
|
+
* since Postgres refuses a schema there, and in the table's schema where the engine keeps names per
|
|
32
|
+
* schema, or MySQL would look for it in the connection's database and SQL Server in its default schema.
|
|
33
|
+
*/
|
|
34
|
+
function triggerId(dialect, meta, name) {
|
|
35
|
+
return dialect.features.triggers.scope === 'table' ? dialect.escapeId(name) : schemaObjectId(dialect, meta, name);
|
|
36
|
+
}
|
|
37
|
+
/** A name in the schema of `meta`'s table, where uql keeps whatever it installs beside it. */
|
|
38
|
+
function schemaObjectId(dialect, meta, name) {
|
|
39
|
+
return dialect.escapeQualifiedId(name, dialect.resolveSchema(meta));
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* The statements creating one trigger under `name`. Every difference between engines is read off
|
|
43
|
+
* `dialect.features.triggers` rather than branched on a dialect name, so a seventh engine states its
|
|
44
|
+
* shape and renders here unchanged.
|
|
45
|
+
*/
|
|
46
|
+
function triggerStatements(dialect, meta, trigger, name) {
|
|
47
|
+
const features = dialect.features.triggers;
|
|
48
|
+
// The event, read apart once: `beforeUpdate` is `BEFORE` and `UPDATE`, and everything else follows.
|
|
49
|
+
const before = trigger.on.startsWith('before');
|
|
50
|
+
const operation = trigger.on.slice(before ? 6 : 5).toUpperCase();
|
|
51
|
+
const body = triggerBody(dialect, meta, trigger, before);
|
|
52
|
+
const id = triggerId(dialect, meta, name);
|
|
53
|
+
const table = dialect.escapeId(dialect.resolveTableName(meta));
|
|
54
|
+
const column = (key) => dialect.escapeId(dialect.columnOf(meta, key));
|
|
55
|
+
const names = rowNames(dialect);
|
|
56
|
+
const rows = [rowRefs(names.$new), rowRefs(names.$old)];
|
|
57
|
+
const sql = dialect.compileDdl(body(...rows), meta.entity);
|
|
58
|
+
const guard = triggerGuard(dialect, meta, trigger, rows, names, column);
|
|
59
|
+
const inBody = features.guards !== 'clause';
|
|
60
|
+
const guarded = !guard || !inBody
|
|
61
|
+
? sql
|
|
62
|
+
: features.guards === 'beginEnd'
|
|
63
|
+
? `IF ${guard}\nBEGIN\n${sql}\nEND`
|
|
64
|
+
: `IF ${guard} THEN\n${sql}\nEND IF;`;
|
|
65
|
+
// The preamble opens the body, outside the guard: it settles how the batch reports itself rather than
|
|
66
|
+
// which rows are touched, so it runs even when the guard keeps the statements from running.
|
|
67
|
+
const opened = features.preamble ? `${features.preamble}\n${guarded}` : guarded;
|
|
68
|
+
const of = features.guards === 'clause' && operation === 'UPDATE' && trigger.of?.length
|
|
69
|
+
? ` OF ${trigger.of.map(column).join(', ')}`
|
|
70
|
+
: '';
|
|
71
|
+
const each = features.rows === 'set' ? '' : '\nFOR EACH ROW';
|
|
72
|
+
const clause = guard && !inBody ? `\nWHEN (${guard})` : '';
|
|
73
|
+
const timing = `${before ? 'BEFORE' : 'AFTER'} ${operation}${of}`;
|
|
74
|
+
const header = features.layout === 'tableFirst'
|
|
75
|
+
? `CREATE TRIGGER ${id}\nON ${table} ${timing}${each}${clause}\nAS`
|
|
76
|
+
: `CREATE TRIGGER ${id}\n${timing} ON ${table}${each}${clause}`;
|
|
77
|
+
if (features.body !== 'function') {
|
|
78
|
+
return [`${header}\nBEGIN\n${opened}\nEND`];
|
|
79
|
+
}
|
|
80
|
+
// A `BEFORE` trigger returning NULL discards the write, so it hands back the row it leaves behind;
|
|
81
|
+
// after the write the value is ignored.
|
|
82
|
+
const returned = before ? (operation === 'DELETE' ? names.$old : names.$new) : 'NULL';
|
|
83
|
+
const fn = schemaObjectId(dialect, meta, name);
|
|
84
|
+
return [plpgsqlFunction(fn, `BEGIN\n${opened}\nRETURN ${returned};\nEND`), `${header}\nEXECUTE FUNCTION ${fn}()`];
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* The body for the engine in use, refusing first what the engine cannot render at all. One body serves
|
|
88
|
+
* every engine; in a map, one written for the family serves its forks: CockroachDB runs Postgres's
|
|
89
|
+
* PL/pgSQL, MariaDB MySQL's.
|
|
90
|
+
*/
|
|
91
|
+
function triggerBody(dialect, meta, trigger, before) {
|
|
92
|
+
const features = dialect.features.triggers;
|
|
93
|
+
if (before && !features.before) {
|
|
94
|
+
throw new TypeError(`${dialect.dialectName} has no BEFORE trigger, only AFTER and INSTEAD OF, so '${trigger.on}' cannot be ` +
|
|
95
|
+
'rendered there. Use the matching after event, which sees the row already written.');
|
|
96
|
+
}
|
|
97
|
+
if (trigger.where && features.rows === 'set') {
|
|
98
|
+
throw new TypeError(`${dialect.dialectName} fires a trigger once per statement, over the rows it touched, so no condition ` +
|
|
99
|
+
`can read one row: '${meta.entity.name}' cannot state a trigger 'where' there. Guard inside the body ` +
|
|
100
|
+
'instead, where `inserted` and `deleted` can be read as tables.');
|
|
101
|
+
}
|
|
102
|
+
const { run } = trigger;
|
|
103
|
+
const body = typeof run === 'function' ? run : (run[dialect.dialectName] ?? run[dialect.dialectFamily]);
|
|
104
|
+
if (!body) {
|
|
105
|
+
throw new TypeError(`'${meta.entity.name}' has a trigger with no body for ${dialect.dialectName}, the engine in use. ` +
|
|
106
|
+
'Write one for it, or one body for every engine.');
|
|
107
|
+
}
|
|
108
|
+
return body;
|
|
109
|
+
}
|
|
110
|
+
/** The one condition both guards reduce to: any watched column that moved, and whatever `where` asks. */
|
|
111
|
+
function triggerGuard(dialect, meta, trigger, rows, names, column) {
|
|
112
|
+
const moved = movedColumns(dialect, meta, trigger.of ?? [], names, column);
|
|
113
|
+
return [
|
|
114
|
+
...(moved ? [moved] : []),
|
|
115
|
+
...(trigger.where ? condition(dialect, meta, trigger.where, rows, names, Boolean(moved)) : []),
|
|
116
|
+
].join(' AND ');
|
|
117
|
+
}
|
|
118
|
+
/** The PL/pgSQL function holding a body. `OR REPLACE`, since a dropped table leaves its function behind. */
|
|
119
|
+
function plpgsqlFunction(id, block) {
|
|
120
|
+
const quote = dollarQuote(block);
|
|
121
|
+
return `CREATE OR REPLACE FUNCTION ${id}() RETURNS trigger AS ${quote}\n${block} ${quote} LANGUAGE plpgsql`;
|
|
122
|
+
}
|
|
123
|
+
/** What the engine calls the rows it hands a trigger: records on a row-based engine, tables on a set-based one. */
|
|
124
|
+
function rowNames(dialect) {
|
|
125
|
+
return dialect.features.triggers.rows === 'set'
|
|
126
|
+
? { $new: 'inserted', $old: 'deleted' }
|
|
127
|
+
: { $new: 'NEW', $old: 'OLD' };
|
|
128
|
+
}
|
|
129
|
+
/**
|
|
130
|
+
* The `where` guard as the terms an `AND` joins. A callback writes its own off the rows; a predicate
|
|
131
|
+
* renders a term per row it names, spelled verbatim because `NEW` is a record the engine declares. Each
|
|
132
|
+
* is an `operand` wherever another term sits beside it, bracketing itself if compound, as `$where` does.
|
|
133
|
+
*/
|
|
134
|
+
function condition(dialect, meta, where, rows, names, operand) {
|
|
135
|
+
if (typeof where === 'function') {
|
|
136
|
+
const sql = dialect.compileDdl(where(...rows), meta.entity);
|
|
137
|
+
return [operand ? `(${sql})` : sql];
|
|
138
|
+
}
|
|
139
|
+
const predicates = definedEntries(where);
|
|
140
|
+
return predicates.map(([row, predicate]) => {
|
|
141
|
+
const ctx = dialect.createContext({ inlineValues: true });
|
|
142
|
+
const escapedPrefix = `${names[row]}.`;
|
|
143
|
+
dialect.where(ctx, meta.entity, predicate, {
|
|
144
|
+
clause: false,
|
|
145
|
+
operand: operand || predicates.length > 1,
|
|
146
|
+
escapedPrefix,
|
|
147
|
+
});
|
|
148
|
+
return ctx.sql;
|
|
149
|
+
});
|
|
150
|
+
}
|
|
151
|
+
/**
|
|
152
|
+
* The triggers a stamp needs: one per event it names, each assigning the field's expression to its
|
|
153
|
+
* column. Generated rather than authored, so unlike an authored body it renders on every engine from
|
|
154
|
+
* one declaration - and not at all on the MySQL family, whose columns stamp themselves.
|
|
155
|
+
*/
|
|
156
|
+
export function stampTriggers(dialect, meta) {
|
|
157
|
+
const features = dialect.features.triggers;
|
|
158
|
+
// Restating the row has to wait for it to be there, so those engines stamp after the write.
|
|
159
|
+
const after = !features.assignsRow;
|
|
160
|
+
const newName = rowNames(dialect).$new;
|
|
161
|
+
return definedEntries(meta.fields).flatMap(([key, field]) => {
|
|
162
|
+
const events = stampEvents(field);
|
|
163
|
+
const { computed } = field;
|
|
164
|
+
if (!events?.length || !computed) {
|
|
165
|
+
return [];
|
|
166
|
+
}
|
|
167
|
+
return events.map((event) => ({
|
|
168
|
+
on: STAMP_EVENTS[after ? 'after' : 'before'][event],
|
|
169
|
+
// The event is part of the name: a stamp on both writes installs two triggers, and one identifier
|
|
170
|
+
// between them would have the second replace the first rather than sit beside it.
|
|
171
|
+
name: `${key}_${event}`,
|
|
172
|
+
run: () => stampBody(dialect, meta, key, computed, newName),
|
|
173
|
+
}));
|
|
174
|
+
});
|
|
175
|
+
}
|
|
176
|
+
/** The trigger event a stamp fires on, by when the engine lets it write and what it stamps. */
|
|
177
|
+
const STAMP_EVENTS = {
|
|
178
|
+
before: { insert: 'beforeInsert', update: 'beforeUpdate' },
|
|
179
|
+
after: { insert: 'afterInsert', update: 'afterUpdate' },
|
|
180
|
+
};
|
|
181
|
+
/** The one statement a stamp runs, in whichever of the two shapes the engine leaves open. */
|
|
182
|
+
function stampBody(dialect, meta, key, value, newName) {
|
|
183
|
+
const features = dialect.features.triggers;
|
|
184
|
+
const read = (member) => rowColumn(newName, member);
|
|
185
|
+
if (features.assignsRow) {
|
|
186
|
+
const target = read(key);
|
|
187
|
+
return features.body === 'function' ? raw `${target} := ${value};` : raw `SET ${target} = ${value};`;
|
|
188
|
+
}
|
|
189
|
+
const table = dialect.escapeId(dialect.resolveTableName(meta));
|
|
190
|
+
const column = dialect.escapeId(dialect.columnOf(meta, key));
|
|
191
|
+
const keyed = meta.ids
|
|
192
|
+
.map((id) => raw `${text(`${table}.${dialect.escapeId(dialect.columnOf(meta, id))}`)} = ${read(id)}`)
|
|
193
|
+
.reduce((all, part) => raw `${all} AND ${part}`);
|
|
194
|
+
// A set-based engine hands the rows as a table, which an `UPDATE` has to name in a `FROM` before its
|
|
195
|
+
// condition can read one: `inserted."id"` binds to nothing on its own.
|
|
196
|
+
const from = features.rows === 'set' ? ` FROM ${newName}` : '';
|
|
197
|
+
// Only where the stamp still differs: this `UPDATE` fires the trigger again, and with recursive triggers
|
|
198
|
+
// on, the restatement it runs then finds nothing left to change instead of recursing without end.
|
|
199
|
+
const differs = dialect.neExpr(`${table}.${column}`, dialect.compileDdl(value, meta.entity));
|
|
200
|
+
return raw `UPDATE ${text(table)} SET ${text(column)} = ${value}${text(from)} WHERE ${keyed} AND ${text(differs)};`;
|
|
201
|
+
}
|
|
202
|
+
/** A dollar quote the body does not contain, so no `$$` in it - a literal, a comment - ends the function early. */
|
|
203
|
+
function dollarQuote(body) {
|
|
204
|
+
let tag = '$uql$';
|
|
205
|
+
for (let i = 1; body.includes(tag); i++) {
|
|
206
|
+
tag = `$uql${i}$`;
|
|
207
|
+
}
|
|
208
|
+
return tag;
|
|
209
|
+
}
|
|
210
|
+
/** SQL already written out, for the identifiers a statement splices rather than binds. */
|
|
211
|
+
function text(sql) {
|
|
212
|
+
return raw((opts) => opts.ctx.append(sql));
|
|
213
|
+
}
|
|
214
|
+
/**
|
|
215
|
+
* Whether any watched column moved, null-safely, or `undefined` where none is watched: the two records
|
|
216
|
+
* compared on a row-based engine, and on a set-based one the same question over a join of its two tables.
|
|
217
|
+
*/
|
|
218
|
+
function movedColumns(dialect, meta, of, { $new: newName, $old: oldName }, column) {
|
|
219
|
+
if (!of.length) {
|
|
220
|
+
return undefined;
|
|
221
|
+
}
|
|
222
|
+
const differs = of.map((key) => dialect.neExpr(`${oldName}.${column(key)}`, `${newName}.${column(key)}`));
|
|
223
|
+
const moved = differs.length > 1 ? `(${differs.join(' OR ')})` : differs.join('');
|
|
224
|
+
if (dialect.features.triggers.rows === 'row') {
|
|
225
|
+
return moved;
|
|
226
|
+
}
|
|
227
|
+
const keyed = meta.ids.map((id) => `${newName}.${column(id)} = ${oldName}.${column(id)}`).join(' AND ');
|
|
228
|
+
return `EXISTS (SELECT 1 FROM ${newName} JOIN ${oldName} ON ${keyed} WHERE ${moved})`;
|
|
229
|
+
}
|
|
@@ -36,9 +36,6 @@ export declare class MongoDialect extends AbstractDialect {
|
|
|
36
36
|
readonly features: DialectFeatures;
|
|
37
37
|
readonly dialectName = "mongodb";
|
|
38
38
|
readonly insertIdSource = "returning";
|
|
39
|
-
private static readonly ID_KEY;
|
|
40
|
-
/** Atlas rejects a `$vectorSearch` asking for more candidates than this. */
|
|
41
|
-
private static readonly MAX_NUM_CANDIDATES;
|
|
42
39
|
/**
|
|
43
40
|
* MongoDB stores the primary key as `_id`; everything else resolves as usual. Projections, sorts,
|
|
44
41
|
* `$group` refs and `$where` keys all map through here, so no read path can address a property name
|
|
@@ -70,14 +67,6 @@ export declare class MongoDialect extends AbstractDialect {
|
|
|
70
67
|
* relation subquery can no more read out-of-scope rows than a direct query on the target can.
|
|
71
68
|
*/
|
|
72
69
|
private appendRelationLookup;
|
|
73
|
-
/** Adds `expr` to `filter`'s `$expr`, `AND`ed with any already there. */
|
|
74
|
-
private static andExpr;
|
|
75
|
-
/**
|
|
76
|
-
* `$size` against bounds, which MongoDB's own `$size` takes only as a number: the array at `path` counted
|
|
77
|
-
* in an `$expr`, which no other value satisfies. `$and` may evaluate every operand, so the count reads an
|
|
78
|
-
* empty array in place of any other value.
|
|
79
|
-
*/
|
|
80
|
-
private static arraySize;
|
|
81
70
|
/**
|
|
82
71
|
* The correlated `$lookup` for the target rows of one relation `where` narrows, as `temp`: straight at
|
|
83
72
|
* the target, or for a many-to-many from inside its junction's rows. The caller's filter bypass is not
|
|
@@ -91,8 +80,6 @@ export declare class MongoDialect extends AbstractDialect {
|
|
|
91
80
|
* Each end is one field matched against one `_id`, so both sides must be sole-keyed.
|
|
92
81
|
*/
|
|
93
82
|
private junctionOf;
|
|
94
|
-
/** `count` compared with `size`, a number or its bounds, as an aggregation expression. */
|
|
95
|
-
private static compareCount;
|
|
96
83
|
/** Whether a query subtracts `key` from the projection, via `$exclude` or a negative `$select`. */
|
|
97
84
|
private subtractsKey;
|
|
98
85
|
/** `raw()` renders SQL, so it has no MongoDB equivalent - say so instead of emitting `{}`. */
|
|
@@ -103,10 +90,6 @@ export declare class MongoDialect extends AbstractDialect {
|
|
|
103
90
|
* apply to JSON paths.
|
|
104
91
|
*/
|
|
105
92
|
private assertKnownPathRoot;
|
|
106
|
-
/** String operators -> { pattern: (v) => regex, caseInsensitive } */
|
|
107
|
-
private static readonly REGEX_OP_MAP;
|
|
108
|
-
/** MongoDB native operators - pass through as-is. */
|
|
109
|
-
private static readonly NATIVE_OPS;
|
|
110
93
|
/**
|
|
111
94
|
* Transform UQL operators to MongoDB operators.
|
|
112
95
|
*/
|
|
@@ -271,10 +254,6 @@ export declare class MongoDialect extends AbstractDialect {
|
|
|
271
254
|
* filters included, so each relation aggregate among them is put on the document first.
|
|
272
255
|
*/
|
|
273
256
|
private buildGroupSpec;
|
|
274
|
-
/** `1` where `ref` holds a value, `0` where it is null or missing, which an expression tells apart. */
|
|
275
|
-
private static countOf;
|
|
276
|
-
/** Whether `ref` is null or missing: an expression compares a missing field as neither. */
|
|
277
|
-
private static isNullExpr;
|
|
278
257
|
/** The field a grouped path reads, on the document or on the joined one its lookup unwound. */
|
|
279
258
|
private groupedPath;
|
|
280
259
|
/**
|