@mikro-orm/knex 6.3.3-dev.0 → 6.3.3-dev.10
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/package.json +2 -2
- package/query/CriteriaNode.js +1 -1
- package/query/QueryBuilder.d.ts +5 -1
- package/query/QueryBuilder.js +23 -1
- package/query/QueryBuilderHelper.d.ts +4 -0
- package/query/QueryBuilderHelper.js +64 -45
- package/query/enums.d.ts +2 -0
- package/query/enums.js +2 -0
- package/typings.d.ts +1 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mikro-orm/knex",
|
|
3
|
-
"version": "6.3.3-dev.
|
|
3
|
+
"version": "6.3.3-dev.10",
|
|
4
4
|
"description": "TypeScript ORM for Node.js based on Data Mapper, Unit of Work and Identity Map patterns. Supports MongoDB, MySQL, PostgreSQL and SQLite databases as well as usage with vanilla JavaScript.",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"module": "index.mjs",
|
|
@@ -66,7 +66,7 @@
|
|
|
66
66
|
"@mikro-orm/core": "^6.3.2"
|
|
67
67
|
},
|
|
68
68
|
"peerDependencies": {
|
|
69
|
-
"@mikro-orm/core": "6.3.3-dev.
|
|
69
|
+
"@mikro-orm/core": "6.3.3-dev.10",
|
|
70
70
|
"better-sqlite3": "*",
|
|
71
71
|
"libsql": "*",
|
|
72
72
|
"mariadb": "*"
|
package/query/CriteriaNode.js
CHANGED
|
@@ -28,7 +28,7 @@ class CriteriaNode {
|
|
|
28
28
|
return;
|
|
29
29
|
}
|
|
30
30
|
for (const k of pks) {
|
|
31
|
-
this.prop = meta.props.find(prop => prop.name === k || (prop.fieldNames?.length === 1 && prop.fieldNames[0] === k));
|
|
31
|
+
this.prop = meta.props.find(prop => prop.name === k || (prop.fieldNames?.length === 1 && prop.fieldNames[0] === k && prop.persist !== false));
|
|
32
32
|
const isProp = this.prop || meta.props.find(prop => (prop.fieldNames || []).includes(k));
|
|
33
33
|
// do not validate if the key is prefixed or type casted (e.g. `k::text`)
|
|
34
34
|
if (validate && !isProp && !k.includes('.') && !k.includes('::') && !core_1.Utils.isOperator(k) && !core_1.RawQueryFragment.isKnownFragment(k)) {
|
package/query/QueryBuilder.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { inspect } from 'node:util';
|
|
2
2
|
import type { Knex } from 'knex';
|
|
3
|
-
import { type AnyEntity, type ConnectionType, type Dictionary, type EntityData, type EntityKey, type EntityMetadata, type EntityName, type EntityProperty, type FlushMode, type GroupOperator, type Loaded, LockMode, type LoggingOptions, type MetadataStorage, type ObjectQuery, PopulateHint, type PopulateOptions, type QBFilterQuery, type QBQueryOrderMap, QueryFlag, type QueryOrderMap, type QueryResult, RawQueryFragment, type RequiredEntityData
|
|
3
|
+
import { type AnyEntity, type ConnectionType, type Dictionary, type EntityData, type EntityKey, type EntityMetadata, type EntityName, type EntityProperty, type ExpandProperty, type FlushMode, type GroupOperator, type Loaded, LockMode, type LoggingOptions, type MetadataStorage, type ObjectQuery, PopulateHint, type PopulateOptions, type QBFilterQuery, type QBQueryOrderMap, QueryFlag, type QueryOrderMap, type QueryResult, RawQueryFragment, type RequiredEntityData } from '@mikro-orm/core';
|
|
4
4
|
import { JoinType, QueryType } from './enums';
|
|
5
5
|
import type { AbstractSqlDriver } from '../AbstractSqlDriver';
|
|
6
6
|
import { type Alias, QueryBuilderHelper } from './QueryBuilderHelper';
|
|
@@ -140,6 +140,10 @@ export declare class QueryBuilder<Entity extends object = AnyEntity, RootAlias e
|
|
|
140
140
|
innerJoinAndSelect<Field extends QBField<Entity, RootAlias, Context>, Alias extends string>(field: Field | [field: Field, qb: Knex.QueryBuilder | QueryBuilder<any>], alias: Alias, cond?: QBFilterQuery, fields?: string[], schema?: string): SelectQueryBuilder<Entity, RootAlias, ModifyHint<RootAlias, Context, Hint, Field, true> & {}, ModifyContext<Entity, Context, Field, Alias, true>>;
|
|
141
141
|
innerJoinLateralAndSelect<Field extends QBField<Entity, RootAlias, Context>, Alias extends string>(field: [field: Field, qb: Knex.QueryBuilder | QueryBuilder<any>], alias: Alias, cond?: QBFilterQuery, fields?: string[], schema?: string): SelectQueryBuilder<Entity, RootAlias, ModifyHint<RootAlias, Context, Hint, Field, true> & {}, ModifyContext<Entity, Context, Field, Alias, true>>;
|
|
142
142
|
protected getFieldsForJoinedLoad(prop: EntityProperty<Entity>, alias: string, explicitFields?: string[]): Field<Entity>[];
|
|
143
|
+
/**
|
|
144
|
+
* Apply filters to the QB where condition.
|
|
145
|
+
*/
|
|
146
|
+
applyFilters(filterOptions?: Dictionary<boolean | Dictionary> | string[] | boolean): Promise<this>;
|
|
143
147
|
withSubQuery(subQuery: Knex.QueryBuilder, alias: string): this;
|
|
144
148
|
where(cond: QBFilterQuery<Entity>, operator?: keyof typeof GroupOperator): this;
|
|
145
149
|
where(cond: string, params?: any[], operator?: keyof typeof GroupOperator): this;
|
package/query/QueryBuilder.js
CHANGED
|
@@ -253,6 +253,18 @@ class QueryBuilder {
|
|
|
253
253
|
.forEach(prop => fields.push(...this.driver.mapPropToFieldNames(this, prop, alias)));
|
|
254
254
|
return fields;
|
|
255
255
|
}
|
|
256
|
+
/**
|
|
257
|
+
* Apply filters to the QB where condition.
|
|
258
|
+
*/
|
|
259
|
+
async applyFilters(filterOptions = {}) {
|
|
260
|
+
/* istanbul ignore next */
|
|
261
|
+
if (!this.em) {
|
|
262
|
+
throw new Error('Cannot apply filters, this QueryBuilder is not attached to an EntityManager');
|
|
263
|
+
}
|
|
264
|
+
const cond = await this.em.applyFilters(this.mainAlias.entityName, {}, filterOptions, 'read');
|
|
265
|
+
this.andWhere(cond);
|
|
266
|
+
return this;
|
|
267
|
+
}
|
|
256
268
|
withSubQuery(subQuery, alias) {
|
|
257
269
|
this.ensureNotFinalized();
|
|
258
270
|
this.subQueries[alias] = subQuery.toString();
|
|
@@ -1155,7 +1167,7 @@ class QueryBuilder {
|
|
|
1155
1167
|
if (this._populateWhere == null || this._populateWhere === core_1.PopulateHint.ALL) {
|
|
1156
1168
|
return;
|
|
1157
1169
|
}
|
|
1158
|
-
|
|
1170
|
+
let joins = Object.values(this._joins);
|
|
1159
1171
|
joins.forEach(join => {
|
|
1160
1172
|
join.cond_ = join.cond;
|
|
1161
1173
|
join.cond = {};
|
|
@@ -1172,6 +1184,15 @@ class QueryBuilder {
|
|
|
1172
1184
|
const [alias] = this.helper.splitField(k);
|
|
1173
1185
|
const join = joins.find(j => j.alias === alias);
|
|
1174
1186
|
if (join) {
|
|
1187
|
+
const parentJoin = joins.find(j => j.alias === join.ownerAlias);
|
|
1188
|
+
// https://stackoverflow.com/a/56815807/3665878
|
|
1189
|
+
if (parentJoin) {
|
|
1190
|
+
const nested = (parentJoin.nested ??= new Set());
|
|
1191
|
+
join.type = join.type === enums_1.JoinType.innerJoin || [core_1.ReferenceKind.ONE_TO_MANY, core_1.ReferenceKind.MANY_TO_MANY].includes(parentJoin.prop.kind)
|
|
1192
|
+
? enums_1.JoinType.nestedInnerJoin
|
|
1193
|
+
: enums_1.JoinType.nestedLeftJoin;
|
|
1194
|
+
nested.add(join);
|
|
1195
|
+
}
|
|
1175
1196
|
if (join.cond[k]) {
|
|
1176
1197
|
join.cond = { [op ?? '$and']: [join.cond, { [k]: cond[k] }] };
|
|
1177
1198
|
}
|
|
@@ -1189,6 +1210,7 @@ class QueryBuilder {
|
|
|
1189
1210
|
const cond = CriteriaNodeFactory_1.CriteriaNodeFactory
|
|
1190
1211
|
.createNode(this.metadata, this.mainAlias.entityName, this._populateWhere)
|
|
1191
1212
|
.process(this, { matchPopulateJoins: true, ignoreBranching: true, preferNoBranch: true });
|
|
1213
|
+
joins = Object.values(this._joins); // there might be new joins created by processing the `populateWhere` object
|
|
1192
1214
|
replaceOnConditions(cond);
|
|
1193
1215
|
}
|
|
1194
1216
|
}
|
|
@@ -23,6 +23,10 @@ export declare class QueryBuilderHelper {
|
|
|
23
23
|
joinManyToOneReference(prop: EntityProperty, ownerAlias: string, alias: string, type: JoinType, cond?: Dictionary, schema?: string): JoinOptions;
|
|
24
24
|
joinManyToManyReference(prop: EntityProperty, ownerAlias: string, alias: string, pivotAlias: string, type: JoinType, cond: Dictionary, path: string, schema?: string): Dictionary<JoinOptions>;
|
|
25
25
|
processJoins(qb: Knex.QueryBuilder, joins: Dictionary<JoinOptions>, schema?: string): void;
|
|
26
|
+
createJoinExpression(join: JoinOptions, joins: Dictionary<JoinOptions>, schema?: string): {
|
|
27
|
+
sql: string;
|
|
28
|
+
params: Knex.Value[];
|
|
29
|
+
};
|
|
26
30
|
private processJoinClause;
|
|
27
31
|
private wrapQueryGroup;
|
|
28
32
|
mapJoinColumns(type: QueryType, join: JoinOptions): (string | Knex.Raw)[];
|
|
@@ -183,56 +183,75 @@ class QueryBuilderHelper {
|
|
|
183
183
|
}
|
|
184
184
|
processJoins(qb, joins, schema) {
|
|
185
185
|
Object.values(joins).forEach(join => {
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
const conditions = [];
|
|
189
|
-
const params = [];
|
|
190
|
-
schema = join.schema && join.schema !== '*' ? join.schema : schema;
|
|
191
|
-
if (schema) {
|
|
192
|
-
table = `${schema}.${table}`;
|
|
186
|
+
if ([enums_1.JoinType.nestedInnerJoin, enums_1.JoinType.nestedLeftJoin].includes(join.type)) {
|
|
187
|
+
return;
|
|
193
188
|
}
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
189
|
+
const { sql, params } = this.createJoinExpression(join, joins, schema);
|
|
190
|
+
qb.joinRaw(sql, params);
|
|
191
|
+
});
|
|
192
|
+
}
|
|
193
|
+
createJoinExpression(join, joins, schema) {
|
|
194
|
+
let table = join.table;
|
|
195
|
+
const method = {
|
|
196
|
+
[enums_1.JoinType.nestedInnerJoin]: 'inner join',
|
|
197
|
+
[enums_1.JoinType.nestedLeftJoin]: 'left join',
|
|
198
|
+
[enums_1.JoinType.pivotJoin]: 'left join',
|
|
199
|
+
}[join.type] ?? join.type;
|
|
200
|
+
const conditions = [];
|
|
201
|
+
const params = [];
|
|
202
|
+
schema = join.schema && join.schema !== '*' ? join.schema : schema;
|
|
203
|
+
if (schema) {
|
|
204
|
+
table = `${schema}.${table}`;
|
|
205
|
+
}
|
|
206
|
+
if (join.prop.name !== '__subquery__') {
|
|
207
|
+
join.primaryKeys.forEach((primaryKey, idx) => {
|
|
208
|
+
const right = `${join.alias}.${join.joinColumns[idx]}`;
|
|
209
|
+
if (join.prop.formula) {
|
|
210
|
+
const alias = this.platform.quoteIdentifier(join.ownerAlias);
|
|
211
|
+
const left = join.prop.formula(alias);
|
|
206
212
|
conditions.push(`${left} = ${this.knex.ref(right)}`);
|
|
207
|
-
|
|
208
|
-
}
|
|
209
|
-
if (join.prop.targetMeta?.discriminatorValue && !join.path?.endsWith('[pivot]')) {
|
|
210
|
-
const typeProperty = join.prop.targetMeta.root.discriminatorColumn;
|
|
211
|
-
const alias = join.inverseAlias ?? join.alias;
|
|
212
|
-
join.cond[`${alias}.${typeProperty}`] = join.prop.targetMeta.discriminatorValue;
|
|
213
|
-
}
|
|
214
|
-
for (const key of Object.keys(join.cond)) {
|
|
215
|
-
const hasPrefix = key.includes('.') || core_1.Utils.isOperator(key) || core_1.RawQueryFragment.isKnownFragment(key);
|
|
216
|
-
const newKey = hasPrefix ? key : `${join.alias}.${key}`;
|
|
217
|
-
const clause = this.processJoinClause(newKey, join.cond[key], join.alias, params);
|
|
218
|
-
/* istanbul ignore else */
|
|
219
|
-
if (clause !== '()') {
|
|
220
|
-
conditions.push(clause);
|
|
213
|
+
return;
|
|
221
214
|
}
|
|
215
|
+
const left = join.prop.object && join.prop.fieldNameRaw
|
|
216
|
+
? join.prop.fieldNameRaw.replaceAll(core_1.ALIAS_REPLACEMENT, join.ownerAlias)
|
|
217
|
+
: this.knex.ref(`${join.ownerAlias}.${primaryKey}`);
|
|
218
|
+
conditions.push(`${left} = ${this.knex.ref(right)}`);
|
|
219
|
+
});
|
|
220
|
+
}
|
|
221
|
+
if (join.prop.targetMeta?.discriminatorValue && !join.path?.endsWith('[pivot]')) {
|
|
222
|
+
const typeProperty = join.prop.targetMeta.root.discriminatorColumn;
|
|
223
|
+
const alias = join.inverseAlias ?? join.alias;
|
|
224
|
+
join.cond[`${alias}.${typeProperty}`] = join.prop.targetMeta.discriminatorValue;
|
|
225
|
+
}
|
|
226
|
+
for (const key of Object.keys(join.cond)) {
|
|
227
|
+
const hasPrefix = key.includes('.') || core_1.Utils.isOperator(key) || core_1.RawQueryFragment.isKnownFragment(key);
|
|
228
|
+
const newKey = hasPrefix ? key : `${join.alias}.${key}`;
|
|
229
|
+
const clause = this.processJoinClause(newKey, join.cond[key], join.alias, params);
|
|
230
|
+
/* istanbul ignore else */
|
|
231
|
+
if (clause !== '()') {
|
|
232
|
+
conditions.push(clause);
|
|
222
233
|
}
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
}
|
|
227
|
-
|
|
228
|
-
sql
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
if (conditions.length > 0) {
|
|
232
|
-
sql += ` on ${conditions.join(' and ')}`;
|
|
234
|
+
}
|
|
235
|
+
let sql = method + ' ';
|
|
236
|
+
if (join.nested) {
|
|
237
|
+
sql += `(${this.knex.ref(table)} as ${this.knex.ref(join.alias)}`;
|
|
238
|
+
for (const nested of join.nested) {
|
|
239
|
+
const { sql: nestedSql, params: nestedParams } = this.createJoinExpression(nested, joins, schema);
|
|
240
|
+
sql += ' ' + nestedSql;
|
|
241
|
+
params.unshift(...nestedParams);
|
|
233
242
|
}
|
|
234
|
-
|
|
235
|
-
}
|
|
243
|
+
sql += `)`;
|
|
244
|
+
}
|
|
245
|
+
else if (join.subquery) {
|
|
246
|
+
sql += `(${join.subquery}) as ${this.knex.ref(join.alias)}`;
|
|
247
|
+
}
|
|
248
|
+
else {
|
|
249
|
+
sql += `${this.knex.ref(table)} as ${this.knex.ref(join.alias)}`;
|
|
250
|
+
}
|
|
251
|
+
if (conditions.length > 0) {
|
|
252
|
+
sql += ` on ${conditions.join(' and ')}`;
|
|
253
|
+
}
|
|
254
|
+
return { sql, params };
|
|
236
255
|
}
|
|
237
256
|
processJoinClause(key, value, alias, params, operator = '$eq') {
|
|
238
257
|
if (core_1.Utils.isGroupOperator(key) && Array.isArray(value)) {
|
package/query/enums.d.ts
CHANGED
|
@@ -9,6 +9,8 @@ export declare enum QueryType {
|
|
|
9
9
|
export declare enum JoinType {
|
|
10
10
|
leftJoin = "left join",
|
|
11
11
|
innerJoin = "inner join",
|
|
12
|
+
nestedLeftJoin = "nested left join",
|
|
13
|
+
nestedInnerJoin = "nested inner join",
|
|
12
14
|
pivotJoin = "pivot join",
|
|
13
15
|
innerJoinLateral = "inner join lateral",
|
|
14
16
|
leftJoinLateral = "left join lateral"
|
package/query/enums.js
CHANGED
|
@@ -14,6 +14,8 @@ var JoinType;
|
|
|
14
14
|
(function (JoinType) {
|
|
15
15
|
JoinType["leftJoin"] = "left join";
|
|
16
16
|
JoinType["innerJoin"] = "inner join";
|
|
17
|
+
JoinType["nestedLeftJoin"] = "nested left join";
|
|
18
|
+
JoinType["nestedInnerJoin"] = "nested inner join";
|
|
17
19
|
JoinType["pivotJoin"] = "pivot join";
|
|
18
20
|
JoinType["innerJoinLateral"] = "inner join lateral";
|
|
19
21
|
JoinType["leftJoinLateral"] = "left join lateral";
|