@mikro-orm/sql 7.0.0-dev.298 → 7.0.0-dev.300
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 +12 -12
- package/SqlEntityManager.d.ts +1 -1
- package/dialects/mssql/MsSqlNativeQueryBuilder.d.ts +2 -0
- package/dialects/mssql/MsSqlNativeQueryBuilder.js +5 -0
- package/package.json +2 -2
- package/query/NativeQueryBuilder.d.ts +25 -0
- package/query/NativeQueryBuilder.js +60 -0
- package/query/QueryBuilder.d.ts +94 -40
- package/query/QueryBuilder.js +65 -8
- package/query/QueryBuilderHelper.d.ts +1 -0
- package/query/QueryBuilderHelper.js +5 -1
- package/tsconfig.build.tsbuildinfo +1 -1
- package/typings.d.ts +5 -3
package/query/QueryBuilder.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { helper, inspect, isRaw, LoadStrategy, LockMode, PopulateHint, QueryFlag, QueryHelper, raw, RawQueryFragment, Reference, ReferenceKind, serialize, Utils, ValidationError, } from '@mikro-orm/core';
|
|
1
|
+
import { EntityMetadata, helper, inspect, isRaw, LoadStrategy, LockMode, PopulateHint, QueryFlag, QueryHelper, raw, RawQueryFragment, Reference, ReferenceKind, serialize, Utils, ValidationError, } from '@mikro-orm/core';
|
|
2
2
|
import { JoinType, QueryType } from './enums.js';
|
|
3
3
|
import { QueryBuilderHelper } from './QueryBuilderHelper.js';
|
|
4
4
|
import { CriteriaNodeFactory } from './CriteriaNodeFactory.js';
|
|
@@ -82,6 +82,7 @@ export class QueryBuilder {
|
|
|
82
82
|
_helper;
|
|
83
83
|
_query;
|
|
84
84
|
_unionQuery;
|
|
85
|
+
_ctes = [];
|
|
85
86
|
platform;
|
|
86
87
|
tptJoinsApplied = false;
|
|
87
88
|
autoJoinedPaths = [];
|
|
@@ -712,6 +713,9 @@ export class QueryBuilder {
|
|
|
712
713
|
if (target instanceof QueryBuilder) {
|
|
713
714
|
this.fromSubQuery(target, aliasName);
|
|
714
715
|
}
|
|
716
|
+
else if (typeof target === 'string' && !this.metadata.find(target)) {
|
|
717
|
+
this.fromRawTable(target, aliasName);
|
|
718
|
+
}
|
|
715
719
|
else {
|
|
716
720
|
if (aliasName && this._mainAlias && Utils.className(target) !== this._mainAlias.aliasName) {
|
|
717
721
|
throw new Error(`Cannot override the alias to '${aliasName}' since a query already contains references to '${this._mainAlias.aliasName}'`);
|
|
@@ -737,6 +741,16 @@ export class QueryBuilder {
|
|
|
737
741
|
this._query = {};
|
|
738
742
|
this.finalize();
|
|
739
743
|
const qb = this.getQueryBase(processVirtualEntity);
|
|
744
|
+
for (const cte of this._ctes) {
|
|
745
|
+
const query = cte.query;
|
|
746
|
+
const opts = { columns: cte.columns, materialized: cte.materialized };
|
|
747
|
+
if (cte.recursive) {
|
|
748
|
+
qb.withRecursive(cte.name, query, opts);
|
|
749
|
+
}
|
|
750
|
+
else {
|
|
751
|
+
qb.with(cte.name, query, opts);
|
|
752
|
+
}
|
|
753
|
+
}
|
|
740
754
|
const schema = this.getSchema(this.mainAlias);
|
|
741
755
|
const isNotEmptyObject = (obj) => Utils.hasObjectKeys(obj) || RawQueryFragment.hasObjectFragments(obj);
|
|
742
756
|
Utils.runIfNotEmpty(() => this.helper.appendQueryCondition(this.type, this._cond, qb), this._cond && !this._onConflict);
|
|
@@ -1121,6 +1135,28 @@ export class QueryBuilder {
|
|
|
1121
1135
|
result._unionQuery = { sql: parts.join(` ${separator} `), params };
|
|
1122
1136
|
return result;
|
|
1123
1137
|
}
|
|
1138
|
+
with(name, query, options) {
|
|
1139
|
+
return this.addCte(name, query, options);
|
|
1140
|
+
}
|
|
1141
|
+
withRecursive(name, query, options) {
|
|
1142
|
+
return this.addCte(name, query, options, true);
|
|
1143
|
+
}
|
|
1144
|
+
addCte(name, query, options, recursive) {
|
|
1145
|
+
this.ensureNotFinalized();
|
|
1146
|
+
if (this._ctes.some(cte => cte.name === name)) {
|
|
1147
|
+
throw new Error(`CTE with name '${name}' already exists`);
|
|
1148
|
+
}
|
|
1149
|
+
// Eagerly compile QueryBuilder to RawQueryFragment — later mutations to the sub-query won't be reflected
|
|
1150
|
+
const compiled = query instanceof QueryBuilder ? query.toRaw() : query;
|
|
1151
|
+
this._ctes.push({
|
|
1152
|
+
name,
|
|
1153
|
+
query: compiled,
|
|
1154
|
+
recursive,
|
|
1155
|
+
columns: options?.columns,
|
|
1156
|
+
materialized: options?.materialized,
|
|
1157
|
+
});
|
|
1158
|
+
return this;
|
|
1159
|
+
}
|
|
1124
1160
|
clone(reset, preserve) {
|
|
1125
1161
|
const qb = new QueryBuilder(this.mainAlias.entityName, this.metadata, this.driver, this.context, this.mainAlias.aliasName, this.connectionType, this.em);
|
|
1126
1162
|
reset = reset || [];
|
|
@@ -1140,6 +1176,9 @@ export class QueryBuilder {
|
|
|
1140
1176
|
if (this._fields && reset !== true && !reset.includes('_fields')) {
|
|
1141
1177
|
qb._fields = [...this._fields];
|
|
1142
1178
|
}
|
|
1179
|
+
if (this._ctes.length && reset !== true && !reset.includes('_ctes')) {
|
|
1180
|
+
qb._ctes = this._ctes.map(cte => ({ ...cte }));
|
|
1181
|
+
}
|
|
1143
1182
|
qb._aliases = { ...this._aliases };
|
|
1144
1183
|
qb._helper.aliasMap = qb._aliases;
|
|
1145
1184
|
qb.finalized = false;
|
|
@@ -1457,22 +1496,24 @@ export class QueryBuilder {
|
|
|
1457
1496
|
}
|
|
1458
1497
|
getQueryBase(processVirtualEntity) {
|
|
1459
1498
|
const qb = this.platform.createNativeQueryBuilder().setFlags(this.flags);
|
|
1460
|
-
const { subQuery, aliasName, entityName, meta } = this.mainAlias;
|
|
1499
|
+
const { subQuery, aliasName, entityName, meta, rawTableName } = this.mainAlias;
|
|
1461
1500
|
const requiresAlias = this.finalized && (this._explicitAlias || this.helper.isTableNameAliasRequired(this.type));
|
|
1462
1501
|
const alias = requiresAlias ? aliasName : undefined;
|
|
1463
1502
|
const schema = this.getSchema(this.mainAlias);
|
|
1464
|
-
const tableName =
|
|
1465
|
-
?
|
|
1466
|
-
: subQuery
|
|
1467
|
-
?
|
|
1468
|
-
:
|
|
1503
|
+
const tableName = rawTableName
|
|
1504
|
+
? rawTableName
|
|
1505
|
+
: subQuery instanceof NativeQueryBuilder
|
|
1506
|
+
? subQuery.as(aliasName)
|
|
1507
|
+
: subQuery
|
|
1508
|
+
? raw(`(${subQuery.sql}) as ${this.platform.quoteIdentifier(aliasName)}`, subQuery.params)
|
|
1509
|
+
: this.helper.getTableName(entityName);
|
|
1469
1510
|
const joinSchema = this._schema ?? this.em?.schema ?? schema;
|
|
1470
1511
|
if (meta.virtual && processVirtualEntity) {
|
|
1471
1512
|
qb.from(raw(this.fromVirtual(meta)), { indexHint: this._indexHint });
|
|
1472
1513
|
}
|
|
1473
1514
|
else {
|
|
1474
1515
|
qb.from(tableName, {
|
|
1475
|
-
schema,
|
|
1516
|
+
schema: rawTableName ? undefined : schema,
|
|
1476
1517
|
alias,
|
|
1477
1518
|
indexHint: this._indexHint,
|
|
1478
1519
|
});
|
|
@@ -2021,6 +2062,22 @@ export class QueryBuilder {
|
|
|
2021
2062
|
aliasName ??= this._mainAlias?.aliasName ?? this.getNextAlias(entityName);
|
|
2022
2063
|
this.createMainAlias(entityName, aliasName);
|
|
2023
2064
|
}
|
|
2065
|
+
fromRawTable(tableName, aliasName) {
|
|
2066
|
+
aliasName ??= this._mainAlias?.aliasName ?? this.getNextAlias(tableName);
|
|
2067
|
+
const meta = new EntityMetadata({
|
|
2068
|
+
className: tableName,
|
|
2069
|
+
collection: tableName,
|
|
2070
|
+
});
|
|
2071
|
+
meta.root = meta;
|
|
2072
|
+
this._mainAlias = {
|
|
2073
|
+
aliasName,
|
|
2074
|
+
entityName: tableName,
|
|
2075
|
+
meta,
|
|
2076
|
+
rawTableName: tableName,
|
|
2077
|
+
};
|
|
2078
|
+
this._aliases[aliasName] = this._mainAlias;
|
|
2079
|
+
this._helper = this.createQueryBuilderHelper();
|
|
2080
|
+
}
|
|
2024
2081
|
createQueryBuilderHelper() {
|
|
2025
2082
|
return new QueryBuilderHelper(this.mainAlias.entityName, this.mainAlias.aliasName, this._aliases, this.subQueries, this.driver, this._tptAlias);
|
|
2026
2083
|
}
|
|
@@ -803,7 +803,11 @@ export class QueryBuilderHelper {
|
|
|
803
803
|
}
|
|
804
804
|
getProperty(field, alias) {
|
|
805
805
|
const entityName = this.aliasMap[alias]?.entityName || this.entityName;
|
|
806
|
-
const meta = this.metadata.
|
|
806
|
+
const meta = this.metadata.find(entityName);
|
|
807
|
+
// raw table name (e.g. CTE) — no metadata available
|
|
808
|
+
if (!meta) {
|
|
809
|
+
return undefined;
|
|
810
|
+
}
|
|
807
811
|
// check if `alias` is not matching an embedded property name instead of alias, e.g. `address.city`
|
|
808
812
|
if (alias) {
|
|
809
813
|
const prop = meta.properties[alias];
|