@mikro-orm/sql 7.0.0-dev.291 → 7.0.0-dev.293
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/AbstractSqlDriver.d.ts +6 -0
- package/AbstractSqlDriver.js +53 -0
- package/AbstractSqlPlatform.d.ts +1 -0
- package/AbstractSqlPlatform.js +3 -0
- package/package.json +2 -2
- package/query/QueryBuilder.d.ts +37 -1
- package/query/QueryBuilder.js +69 -3
- package/query/QueryBuilderHelper.d.ts +3 -3
- package/query/QueryBuilderHelper.js +2 -3
- package/query/ScalarCriteriaNode.js +1 -1
- package/tsconfig.build.tsbuildinfo +1 -1
package/AbstractSqlDriver.d.ts
CHANGED
|
@@ -137,6 +137,12 @@ export declare abstract class AbstractSqlDriver<Connection extends AbstractSqlCo
|
|
|
137
137
|
protected processManyToMany<T extends object>(meta: EntityMetadata<T>, pks: Primary<T>[], collections: EntityData<T>, clear: boolean, options?: DriverMethodOptions): Promise<void>;
|
|
138
138
|
lockPessimistic<T extends object>(entity: T, options: LockOptions): Promise<void>;
|
|
139
139
|
protected buildPopulateWhere<T extends object>(meta: EntityMetadata<T>, joinedProps: PopulateOptions<T>[], options: Pick<FindOptions<any>, 'populateWhere'>): ObjectQuery<T>;
|
|
140
|
+
/**
|
|
141
|
+
* Builds a UNION ALL (or UNION) subquery from `unionWhere` branches and merges it
|
|
142
|
+
* into the main WHERE as `pk IN (branch_1 UNION ALL branch_2 ...)`.
|
|
143
|
+
* Each branch is planned independently by the database, enabling per-table index usage.
|
|
144
|
+
*/
|
|
145
|
+
protected applyUnionWhere<T extends object>(meta: EntityMetadata<T>, where: ObjectQuery<T>, options: FindOptions<T, any, any, any> | CountOptions<T> | NativeInsertUpdateOptions<T> | DeleteOptions<T>, forDml?: boolean): Promise<ObjectQuery<T>>;
|
|
140
146
|
protected buildOrderBy<T extends object>(qb: QueryBuilder<T, any, any, any>, meta: EntityMetadata<T>, populate: PopulateOptions<T>[], options: Pick<FindOptions<any>, 'strategy' | 'orderBy' | 'populateOrderBy'>): QueryOrderMap<T>[];
|
|
141
147
|
protected buildPopulateOrderBy<T extends object>(qb: QueryBuilder<T, any, any, any>, meta: EntityMetadata<T>, populateOrderBy: QueryOrderMap<T>[], parentPath: string, explicit: boolean, parentAlias?: string): QueryOrderMap<T>[];
|
|
142
148
|
protected buildJoinedPropsOrderBy<T extends object>(qb: QueryBuilder<T, any, any, any>, meta: EntityMetadata<T>, populate: PopulateOptions<T>[], options?: Pick<FindOptions<any>, 'strategy' | 'orderBy' | 'populateOrderBy'>, parentPath?: string): QueryOrderMap<T>[];
|
package/AbstractSqlDriver.js
CHANGED
|
@@ -95,6 +95,9 @@ export class AbstractSqlDriver extends DatabaseDriver {
|
|
|
95
95
|
if (meta.virtual) {
|
|
96
96
|
return this.findVirtual(entityName, where, options);
|
|
97
97
|
}
|
|
98
|
+
if (options.unionWhere?.length) {
|
|
99
|
+
where = await this.applyUnionWhere(meta, where, options);
|
|
100
|
+
}
|
|
98
101
|
const qb = await this.createQueryBuilderFromOptions(meta, where, options);
|
|
99
102
|
const result = await this.rethrow(qb.execute('all'));
|
|
100
103
|
if (options.last && !options.first) {
|
|
@@ -493,6 +496,9 @@ export class AbstractSqlDriver extends DatabaseDriver {
|
|
|
493
496
|
if (meta.virtual) {
|
|
494
497
|
return this.countVirtual(entityName, where, options);
|
|
495
498
|
}
|
|
499
|
+
if (options.unionWhere?.length) {
|
|
500
|
+
where = await this.applyUnionWhere(meta, where, options);
|
|
501
|
+
}
|
|
496
502
|
options = { populate: [], ...options };
|
|
497
503
|
const populate = options.populate;
|
|
498
504
|
const joinedProps = this.joinedProps(meta, populate, options);
|
|
@@ -704,6 +710,9 @@ export class AbstractSqlDriver extends DatabaseDriver {
|
|
|
704
710
|
/* v8 ignore next */
|
|
705
711
|
where = { [meta.primaryKeys[0] ?? pks[0]]: where };
|
|
706
712
|
}
|
|
713
|
+
if (!options.upsert && options.unionWhere?.length) {
|
|
714
|
+
where = await this.applyUnionWhere(meta, where, options, true);
|
|
715
|
+
}
|
|
707
716
|
if (Utils.hasObjectKeys(data)) {
|
|
708
717
|
const qb = this.createQueryBuilder(entityName, options.ctx, 'write', options.convertCustomTypes, options.loggerContext).withSchema(this.getSchemaName(meta, options));
|
|
709
718
|
if (options.upsert) {
|
|
@@ -881,6 +890,9 @@ export class AbstractSqlDriver extends DatabaseDriver {
|
|
|
881
890
|
if (Utils.isPrimaryKey(where) && pks.length === 1) {
|
|
882
891
|
where = { [pks[0]]: where };
|
|
883
892
|
}
|
|
893
|
+
if (options.unionWhere?.length) {
|
|
894
|
+
where = await this.applyUnionWhere(meta, where, options, true);
|
|
895
|
+
}
|
|
884
896
|
const qb = this.createQueryBuilder(entityName, options.ctx, 'write', false, options.loggerContext)
|
|
885
897
|
.delete(where)
|
|
886
898
|
.withSchema(this.getSchemaName(meta, options));
|
|
@@ -1598,6 +1610,47 @@ export class AbstractSqlDriver extends DatabaseDriver {
|
|
|
1598
1610
|
/* v8 ignore next */
|
|
1599
1611
|
return { $and: [options.populateWhere, where] };
|
|
1600
1612
|
}
|
|
1613
|
+
/**
|
|
1614
|
+
* Builds a UNION ALL (or UNION) subquery from `unionWhere` branches and merges it
|
|
1615
|
+
* into the main WHERE as `pk IN (branch_1 UNION ALL branch_2 ...)`.
|
|
1616
|
+
* Each branch is planned independently by the database, enabling per-table index usage.
|
|
1617
|
+
*/
|
|
1618
|
+
async applyUnionWhere(meta, where, options, forDml = false) {
|
|
1619
|
+
const unionWhere = options.unionWhere;
|
|
1620
|
+
const strategy = options.unionWhereStrategy ?? 'union-all';
|
|
1621
|
+
const schema = this.getSchemaName(meta, options);
|
|
1622
|
+
const connectionType = this.resolveConnectionType({
|
|
1623
|
+
ctx: options.ctx,
|
|
1624
|
+
connectionType: options.connectionType,
|
|
1625
|
+
});
|
|
1626
|
+
const branchQbs = [];
|
|
1627
|
+
for (const branch of unionWhere) {
|
|
1628
|
+
const qb = this.createQueryBuilder(meta.class, options.ctx, connectionType, false, options.logging).withSchema(schema);
|
|
1629
|
+
const pkFields = meta.primaryKeys.map(pk => {
|
|
1630
|
+
const prop = meta.properties[pk];
|
|
1631
|
+
return `${qb.alias}.${prop.fieldNames[0]}`;
|
|
1632
|
+
});
|
|
1633
|
+
qb.select(pkFields).where(branch);
|
|
1634
|
+
if (options.em) {
|
|
1635
|
+
await qb.applyJoinedFilters(options.em, options.filters);
|
|
1636
|
+
}
|
|
1637
|
+
branchQbs.push(qb);
|
|
1638
|
+
}
|
|
1639
|
+
const [first, ...rest] = branchQbs;
|
|
1640
|
+
const unionQb = strategy === 'union' ? first.union(...rest) : first.unionAll(...rest);
|
|
1641
|
+
const pkHash = Utils.getPrimaryKeyHash(meta.primaryKeys);
|
|
1642
|
+
// MySQL does not allow referencing the target table in a subquery
|
|
1643
|
+
// for UPDATE/DELETE, so we wrap the union in a derived table.
|
|
1644
|
+
if (forDml) {
|
|
1645
|
+
const { sql, params } = unionQb.toQuery();
|
|
1646
|
+
return {
|
|
1647
|
+
$and: [where, { [pkHash]: { $in: raw(`select * from (${sql}) as __u`, params) } }],
|
|
1648
|
+
};
|
|
1649
|
+
}
|
|
1650
|
+
return {
|
|
1651
|
+
$and: [where, { [pkHash]: { $in: unionQb.toRaw() } }],
|
|
1652
|
+
};
|
|
1653
|
+
}
|
|
1601
1654
|
buildOrderBy(qb, meta, populate, options) {
|
|
1602
1655
|
const joinedProps = this.joinedProps(meta, populate, options);
|
|
1603
1656
|
// `options._populateWhere` is a copy of the value provided by user with a fallback to the global config option
|
package/AbstractSqlPlatform.d.ts
CHANGED
|
@@ -27,6 +27,7 @@ export declare abstract class AbstractSqlPlatform extends Platform {
|
|
|
27
27
|
getSearchJsonPropertySQL(path: string, type: string, aliased: boolean): string | RawQueryFragment;
|
|
28
28
|
getSearchJsonPropertyKey(path: string[], type: string, aliased: boolean, value?: unknown): string | RawQueryFragment;
|
|
29
29
|
getJsonIndexDefinition(index: IndexDef): string[];
|
|
30
|
+
supportsUnionWhere(): boolean;
|
|
30
31
|
supportsSchemas(): boolean;
|
|
31
32
|
/** @inheritDoc */
|
|
32
33
|
generateCustomOrder(escapedColumn: string, values: unknown[]): string;
|
package/AbstractSqlPlatform.js
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mikro-orm/sql",
|
|
3
|
-
"version": "7.0.0-dev.
|
|
3
|
+
"version": "7.0.0-dev.293",
|
|
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
|
"type": "module",
|
|
6
6
|
"exports": {
|
|
@@ -56,6 +56,6 @@
|
|
|
56
56
|
"@mikro-orm/core": "^6.6.8"
|
|
57
57
|
},
|
|
58
58
|
"peerDependencies": {
|
|
59
|
-
"@mikro-orm/core": "7.0.0-dev.
|
|
59
|
+
"@mikro-orm/core": "7.0.0-dev.293"
|
|
60
60
|
}
|
|
61
61
|
}
|
package/query/QueryBuilder.d.ts
CHANGED
|
@@ -220,6 +220,10 @@ export declare class QueryBuilder<Entity extends object = AnyEntity, RootAlias e
|
|
|
220
220
|
params?: readonly unknown[];
|
|
221
221
|
qb: NativeQueryBuilder;
|
|
222
222
|
};
|
|
223
|
+
protected _unionQuery?: {
|
|
224
|
+
sql: string;
|
|
225
|
+
params: readonly unknown[];
|
|
226
|
+
};
|
|
223
227
|
protected readonly platform: AbstractSqlPlatform;
|
|
224
228
|
private tptJoinsApplied;
|
|
225
229
|
private readonly autoJoinedPaths;
|
|
@@ -750,6 +754,38 @@ export declare class QueryBuilder<Entity extends object = AnyEntity, RootAlias e
|
|
|
750
754
|
* You can provide the target entity name as the first parameter and use the second parameter to point to an existing property to infer its field name.
|
|
751
755
|
*/
|
|
752
756
|
as<T>(targetEntity: EntityName<T>, alias: EntityKey<T>): NativeQueryBuilder;
|
|
757
|
+
/**
|
|
758
|
+
* Combines the current query with one or more other queries using `UNION ALL`.
|
|
759
|
+
* All queries must select the same columns. Returns a `QueryBuilder` that
|
|
760
|
+
* can be used with `$in`, passed to `qb.from()`, or converted via `.getQuery()`,
|
|
761
|
+
* `.getParams()`, `.toQuery()`, `.toRaw()`, etc.
|
|
762
|
+
*
|
|
763
|
+
* ```ts
|
|
764
|
+
* const qb1 = em.createQueryBuilder(Employee).select('id').where(condition1);
|
|
765
|
+
* const qb2 = em.createQueryBuilder(Employee).select('id').where(condition2);
|
|
766
|
+
* const qb3 = em.createQueryBuilder(Employee).select('id').where(condition3);
|
|
767
|
+
* const subquery = qb1.unionAll(qb2, qb3);
|
|
768
|
+
*
|
|
769
|
+
* const results = await em.find(Employee, { id: { $in: subquery } });
|
|
770
|
+
* ```
|
|
771
|
+
*/
|
|
772
|
+
unionAll(...others: (QueryBuilder<any> | NativeQueryBuilder)[]): QueryBuilder<Entity>;
|
|
773
|
+
/**
|
|
774
|
+
* Combines the current query with one or more other queries using `UNION` (with deduplication).
|
|
775
|
+
* All queries must select the same columns. Returns a `QueryBuilder` that
|
|
776
|
+
* can be used with `$in`, passed to `qb.from()`, or converted via `.getQuery()`,
|
|
777
|
+
* `.getParams()`, `.toQuery()`, `.toRaw()`, etc.
|
|
778
|
+
*
|
|
779
|
+
* ```ts
|
|
780
|
+
* const qb1 = em.createQueryBuilder(Employee).select('id').where(condition1);
|
|
781
|
+
* const qb2 = em.createQueryBuilder(Employee).select('id').where(condition2);
|
|
782
|
+
* const subquery = qb1.union(qb2);
|
|
783
|
+
*
|
|
784
|
+
* const results = await em.find(Employee, { id: { $in: subquery } });
|
|
785
|
+
* ```
|
|
786
|
+
*/
|
|
787
|
+
union(...others: (QueryBuilder<any> | NativeQueryBuilder)[]): QueryBuilder<Entity>;
|
|
788
|
+
private buildUnionQuery;
|
|
753
789
|
clone(reset?: boolean | string[], preserve?: string[]): QueryBuilder<Entity, RootAlias, Hint, Context, RawAliases, Fields>;
|
|
754
790
|
/**
|
|
755
791
|
* Sets logger context for this query builder.
|
|
@@ -836,7 +872,7 @@ export declare class QueryBuilder<Entity extends object = AnyEntity, RootAlias e
|
|
|
836
872
|
private wrapModifySubQuery;
|
|
837
873
|
private getSchema;
|
|
838
874
|
/** @internal */
|
|
839
|
-
createAlias<U = unknown>(entityName: EntityName<U>, aliasName: string, subQuery?: NativeQueryBuilder): Alias<U>;
|
|
875
|
+
createAlias<U = unknown>(entityName: EntityName<U>, aliasName: string, subQuery?: NativeQueryBuilder | RawQueryFragment): Alias<U>;
|
|
840
876
|
private createMainAlias;
|
|
841
877
|
private fromSubQuery;
|
|
842
878
|
private fromEntityName;
|
package/query/QueryBuilder.js
CHANGED
|
@@ -81,6 +81,7 @@ export class QueryBuilder {
|
|
|
81
81
|
_tptAlias = {}; // maps entity className to alias for TPT parent tables
|
|
82
82
|
_helper;
|
|
83
83
|
_query;
|
|
84
|
+
_unionQuery;
|
|
84
85
|
platform;
|
|
85
86
|
tptJoinsApplied = false;
|
|
86
87
|
autoJoinedPaths = [];
|
|
@@ -720,6 +721,16 @@ export class QueryBuilder {
|
|
|
720
721
|
return this;
|
|
721
722
|
}
|
|
722
723
|
getNativeQuery(processVirtualEntity = true) {
|
|
724
|
+
if (this._unionQuery) {
|
|
725
|
+
if (!this._query?.qb) {
|
|
726
|
+
this._query = {};
|
|
727
|
+
const nqb = this.platform.createNativeQueryBuilder();
|
|
728
|
+
nqb.select('*');
|
|
729
|
+
nqb.from(raw(`(${this._unionQuery.sql})`, this._unionQuery.params));
|
|
730
|
+
this._query.qb = nqb;
|
|
731
|
+
}
|
|
732
|
+
return this._query.qb;
|
|
733
|
+
}
|
|
723
734
|
if (this._query?.qb) {
|
|
724
735
|
return this._query.qb;
|
|
725
736
|
}
|
|
@@ -764,6 +775,9 @@ export class QueryBuilder {
|
|
|
764
775
|
return raw(sql, params);
|
|
765
776
|
}
|
|
766
777
|
toQuery() {
|
|
778
|
+
if (this._unionQuery) {
|
|
779
|
+
return this._unionQuery;
|
|
780
|
+
}
|
|
767
781
|
if (this._query?.sql) {
|
|
768
782
|
return { sql: this._query.sql, params: this._query.params };
|
|
769
783
|
}
|
|
@@ -1059,6 +1073,54 @@ export class QueryBuilder {
|
|
|
1059
1073
|
Object.defineProperty(qb, '__as', { enumerable: false, value: finalAlias });
|
|
1060
1074
|
return qb;
|
|
1061
1075
|
}
|
|
1076
|
+
/**
|
|
1077
|
+
* Combines the current query with one or more other queries using `UNION ALL`.
|
|
1078
|
+
* All queries must select the same columns. Returns a `QueryBuilder` that
|
|
1079
|
+
* can be used with `$in`, passed to `qb.from()`, or converted via `.getQuery()`,
|
|
1080
|
+
* `.getParams()`, `.toQuery()`, `.toRaw()`, etc.
|
|
1081
|
+
*
|
|
1082
|
+
* ```ts
|
|
1083
|
+
* const qb1 = em.createQueryBuilder(Employee).select('id').where(condition1);
|
|
1084
|
+
* const qb2 = em.createQueryBuilder(Employee).select('id').where(condition2);
|
|
1085
|
+
* const qb3 = em.createQueryBuilder(Employee).select('id').where(condition3);
|
|
1086
|
+
* const subquery = qb1.unionAll(qb2, qb3);
|
|
1087
|
+
*
|
|
1088
|
+
* const results = await em.find(Employee, { id: { $in: subquery } });
|
|
1089
|
+
* ```
|
|
1090
|
+
*/
|
|
1091
|
+
unionAll(...others) {
|
|
1092
|
+
return this.buildUnionQuery('union all', others);
|
|
1093
|
+
}
|
|
1094
|
+
/**
|
|
1095
|
+
* Combines the current query with one or more other queries using `UNION` (with deduplication).
|
|
1096
|
+
* All queries must select the same columns. Returns a `QueryBuilder` that
|
|
1097
|
+
* can be used with `$in`, passed to `qb.from()`, or converted via `.getQuery()`,
|
|
1098
|
+
* `.getParams()`, `.toQuery()`, `.toRaw()`, etc.
|
|
1099
|
+
*
|
|
1100
|
+
* ```ts
|
|
1101
|
+
* const qb1 = em.createQueryBuilder(Employee).select('id').where(condition1);
|
|
1102
|
+
* const qb2 = em.createQueryBuilder(Employee).select('id').where(condition2);
|
|
1103
|
+
* const subquery = qb1.union(qb2);
|
|
1104
|
+
*
|
|
1105
|
+
* const results = await em.find(Employee, { id: { $in: subquery } });
|
|
1106
|
+
* ```
|
|
1107
|
+
*/
|
|
1108
|
+
union(...others) {
|
|
1109
|
+
return this.buildUnionQuery('union', others);
|
|
1110
|
+
}
|
|
1111
|
+
buildUnionQuery(separator, others) {
|
|
1112
|
+
const all = [this, ...others];
|
|
1113
|
+
const parts = [];
|
|
1114
|
+
const params = [];
|
|
1115
|
+
for (const qb of all) {
|
|
1116
|
+
const compiled = qb instanceof QueryBuilder ? qb.toQuery() : qb.compile();
|
|
1117
|
+
parts.push(`(${compiled.sql})`);
|
|
1118
|
+
params.push(...compiled.params);
|
|
1119
|
+
}
|
|
1120
|
+
const result = this.clone(true);
|
|
1121
|
+
result._unionQuery = { sql: parts.join(` ${separator} `), params };
|
|
1122
|
+
return result;
|
|
1123
|
+
}
|
|
1062
1124
|
clone(reset, preserve) {
|
|
1063
1125
|
const qb = new QueryBuilder(this.mainAlias.entityName, this.metadata, this.driver, this.context, this.mainAlias.aliasName, this.connectionType, this.em);
|
|
1064
1126
|
reset = reset || [];
|
|
@@ -1066,7 +1128,7 @@ export class QueryBuilder {
|
|
|
1066
1128
|
const properties = [
|
|
1067
1129
|
'flags', '_populate', '_populateWhere', '_populateFilter', '__populateWhere', '_populateMap', '_joins', '_joinedProps', '_cond', '_data', '_orderBy',
|
|
1068
1130
|
'_schema', '_indexHint', '_collation', '_cache', 'subQueries', 'lockMode', 'lockTables', '_groupBy', '_having', '_returning',
|
|
1069
|
-
'_comments', '_hintComments', 'aliasCounter',
|
|
1131
|
+
'_comments', '_hintComments', 'aliasCounter', '_unionQuery',
|
|
1070
1132
|
];
|
|
1071
1133
|
for (const prop of Object.keys(this)) {
|
|
1072
1134
|
if (!preserve?.includes(prop) && (reset === true || reset.includes(prop) || ['_helper', '_query'].includes(prop))) {
|
|
@@ -1399,7 +1461,11 @@ export class QueryBuilder {
|
|
|
1399
1461
|
const requiresAlias = this.finalized && (this._explicitAlias || this.helper.isTableNameAliasRequired(this.type));
|
|
1400
1462
|
const alias = requiresAlias ? aliasName : undefined;
|
|
1401
1463
|
const schema = this.getSchema(this.mainAlias);
|
|
1402
|
-
const tableName = subQuery
|
|
1464
|
+
const tableName = subQuery instanceof NativeQueryBuilder
|
|
1465
|
+
? subQuery.as(aliasName)
|
|
1466
|
+
: subQuery
|
|
1467
|
+
? raw(`(${subQuery.sql}) as ${this.platform.quoteIdentifier(aliasName)}`, subQuery.params)
|
|
1468
|
+
: this.helper.getTableName(entityName);
|
|
1403
1469
|
const joinSchema = this._schema ?? this.em?.schema ?? schema;
|
|
1404
1470
|
if (meta.virtual && processVirtualEntity) {
|
|
1405
1471
|
qb.from(raw(this.fromVirtual(meta)), { indexHint: this._indexHint });
|
|
@@ -1946,9 +2012,9 @@ export class QueryBuilder {
|
|
|
1946
2012
|
return this._mainAlias;
|
|
1947
2013
|
}
|
|
1948
2014
|
fromSubQuery(target, aliasName) {
|
|
1949
|
-
const subQuery = target.getNativeQuery();
|
|
1950
2015
|
const { entityName } = target.mainAlias;
|
|
1951
2016
|
aliasName ??= this.getNextAlias(entityName);
|
|
2017
|
+
const subQuery = target._unionQuery ? target.toRaw() : target.getNativeQuery();
|
|
1952
2018
|
this.createMainAlias(entityName, aliasName, subQuery);
|
|
1953
2019
|
}
|
|
1954
2020
|
fromEntityName(entityName, aliasName) {
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { type Dictionary, type EntityData, type EntityKey, type EntityMetadata, type EntityName, type EntityProperty, type FilterQuery, type FlatQueryOrderMap, type FormulaTable, LockMode, type QueryOrderMap, Raw, type RawQueryFragmentSymbol } from '@mikro-orm/core';
|
|
1
|
+
import { type Dictionary, type EntityData, type EntityKey, type EntityMetadata, type EntityName, type EntityProperty, type FilterQuery, type FlatQueryOrderMap, type FormulaTable, LockMode, type QueryOrderMap, Raw, type RawQueryFragment, type RawQueryFragmentSymbol } from '@mikro-orm/core';
|
|
2
2
|
import { JoinType, QueryType } from './enums.js';
|
|
3
3
|
import type { InternalField, JoinOptions } from '../typings.js';
|
|
4
4
|
import type { AbstractSqlDriver } from '../AbstractSqlDriver.js';
|
|
5
|
-
import { NativeQueryBuilder } from './NativeQueryBuilder.js';
|
|
5
|
+
import type { NativeQueryBuilder } from './NativeQueryBuilder.js';
|
|
6
6
|
/**
|
|
7
7
|
* @internal
|
|
8
8
|
*/
|
|
@@ -71,7 +71,7 @@ export interface Alias<T> {
|
|
|
71
71
|
aliasName: string;
|
|
72
72
|
entityName: EntityName<T>;
|
|
73
73
|
meta: EntityMetadata<T>;
|
|
74
|
-
subQuery?: NativeQueryBuilder;
|
|
74
|
+
subQuery?: NativeQueryBuilder | RawQueryFragment;
|
|
75
75
|
}
|
|
76
76
|
export interface OnConflictClause<T> {
|
|
77
77
|
fields: string[] | Raw;
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { ALIAS_REPLACEMENT, ALIAS_REPLACEMENT_RE, ArrayType, inspect, isRaw, LockMode, OptimisticLockError, QueryOperator, QueryOrderNumeric, raw, Raw, QueryHelper, ReferenceKind, Utils, ValidationError, } from '@mikro-orm/core';
|
|
2
2
|
import { JoinType, QueryType } from './enums.js';
|
|
3
|
-
import { NativeQueryBuilder } from './NativeQueryBuilder.js';
|
|
4
3
|
/**
|
|
5
4
|
* @internal
|
|
6
5
|
*/
|
|
@@ -521,8 +520,8 @@ export class QueryBuilderHelper {
|
|
|
521
520
|
else if (['$in', '$nin'].includes(op) && Array.isArray(value[op]) && value[op].length === 0) {
|
|
522
521
|
parts.push(`1 = ${op === '$in' ? 0 : 1}`);
|
|
523
522
|
}
|
|
524
|
-
else if (value[op] instanceof Raw || value[op]
|
|
525
|
-
const query = value[op] instanceof
|
|
523
|
+
else if (value[op] instanceof Raw || (typeof value[op]?.toRaw === 'function')) {
|
|
524
|
+
const query = value[op] instanceof Raw ? value[op] : value[op].toRaw();
|
|
526
525
|
const mappedKey = this.mapper(key, type, query, null);
|
|
527
526
|
let sql = query.sql;
|
|
528
527
|
if (['$in', '$nin'].includes(op)) {
|
|
@@ -22,7 +22,7 @@ export class ScalarCriteriaNode extends CriteriaNode {
|
|
|
22
22
|
}
|
|
23
23
|
}
|
|
24
24
|
if (this.payload instanceof QueryBuilder) {
|
|
25
|
-
return this.payload.
|
|
25
|
+
return this.payload.toRaw();
|
|
26
26
|
}
|
|
27
27
|
if (this.payload && typeof this.payload === 'object') {
|
|
28
28
|
const keys = Object.keys(this.payload).filter(key => ARRAY_OPERATORS.includes(key) && Array.isArray(this.payload[key]));
|