@mikro-orm/knex 6.0.3-dev.4 → 6.0.3-dev.6
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.js +4 -0
- package/package.json +2 -2
- package/query/QueryBuilder.d.ts +7 -1
- package/query/QueryBuilder.js +42 -8
package/AbstractSqlDriver.js
CHANGED
|
@@ -699,6 +699,9 @@ class AbstractSqlDriver extends core_1.DatabaseDriver {
|
|
|
699
699
|
for (const field of targetFields) {
|
|
700
700
|
const f = field.toString();
|
|
701
701
|
fields.unshift(f.includes('.') ? field : `${targetAlias}.${f}`);
|
|
702
|
+
if (core_1.RawQueryFragment.isKnownFragment(field)) {
|
|
703
|
+
qb.rawFragments.add(f);
|
|
704
|
+
}
|
|
702
705
|
}
|
|
703
706
|
// we need to handle 1:1 owner auto-joins explicitly, as the QB type is the pivot table, not the target
|
|
704
707
|
populate.forEach(hint => {
|
|
@@ -722,6 +725,7 @@ class AbstractSqlDriver extends core_1.DatabaseDriver {
|
|
|
722
725
|
}
|
|
723
726
|
const res = owners.length ? await this.rethrow(qb.execute('all', { mergeResults: false, mapResults: false })) : [];
|
|
724
727
|
const items = res.map((row) => super.mapResult(row, prop.targetMeta));
|
|
728
|
+
qb.clearRawFragmentsCache();
|
|
725
729
|
const map = {};
|
|
726
730
|
const pkProps = ownerMeta.getPrimaryProps();
|
|
727
731
|
owners.forEach(owner => {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mikro-orm/knex",
|
|
3
|
-
"version": "6.0.3-dev.
|
|
3
|
+
"version": "6.0.3-dev.6",
|
|
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,6 +66,6 @@
|
|
|
66
66
|
"@mikro-orm/core": "^6.0.2"
|
|
67
67
|
},
|
|
68
68
|
"peerDependencies": {
|
|
69
|
-
"@mikro-orm/core": "6.0.3-dev.
|
|
69
|
+
"@mikro-orm/core": "6.0.3-dev.6"
|
|
70
70
|
}
|
|
71
71
|
}
|
package/query/QueryBuilder.d.ts
CHANGED
|
@@ -54,6 +54,8 @@ export declare class QueryBuilder<T extends object = AnyEntity> {
|
|
|
54
54
|
__populateWhere?: ObjectQuery<T> | PopulateHint | `${PopulateHint}`;
|
|
55
55
|
/** @internal */
|
|
56
56
|
_populateMap: Dictionary<string>;
|
|
57
|
+
/** @internal */
|
|
58
|
+
readonly rawFragments: Set<string>;
|
|
57
59
|
private aliasCounter;
|
|
58
60
|
private flags;
|
|
59
61
|
private finalized;
|
|
@@ -157,6 +159,10 @@ export declare class QueryBuilder<T extends object = AnyEntity> {
|
|
|
157
159
|
from<T extends AnyEntity<T> = AnyEntity>(target: QueryBuilder<T>, aliasName?: string): SelectQueryBuilder<T>;
|
|
158
160
|
from<T extends AnyEntity<T> = AnyEntity>(target: EntityName<T>): SelectQueryBuilder<T>;
|
|
159
161
|
getKnexQuery(processVirtualEntity?: boolean): Knex.QueryBuilder;
|
|
162
|
+
/**
|
|
163
|
+
* @internal
|
|
164
|
+
*/
|
|
165
|
+
clearRawFragmentsCache(): void;
|
|
160
166
|
/**
|
|
161
167
|
* Returns the query with parameters as wildcards.
|
|
162
168
|
*/
|
|
@@ -224,7 +230,7 @@ export declare class QueryBuilder<T extends object = AnyEntity> {
|
|
|
224
230
|
* You can provide `EntityName.propName` as alias, then the field name will be used based on the metadata
|
|
225
231
|
*/
|
|
226
232
|
as(alias: string): Knex.QueryBuilder;
|
|
227
|
-
clone(reset?: boolean): QueryBuilder<T>;
|
|
233
|
+
clone(reset?: boolean | string[]): QueryBuilder<T>;
|
|
228
234
|
getKnex(processVirtualEntity?: boolean): Knex.QueryBuilder;
|
|
229
235
|
private fromVirtual;
|
|
230
236
|
private joinReference;
|
package/query/QueryBuilder.js
CHANGED
|
@@ -55,6 +55,8 @@ class QueryBuilder {
|
|
|
55
55
|
__populateWhere;
|
|
56
56
|
/** @internal */
|
|
57
57
|
_populateMap = {};
|
|
58
|
+
/** @internal */
|
|
59
|
+
rawFragments = new Set();
|
|
58
60
|
aliasCounter = 0;
|
|
59
61
|
flags = new Set([core_1.QueryFlag.CONVERT_CUSTOM_TYPES]);
|
|
60
62
|
finalized = false;
|
|
@@ -484,8 +486,16 @@ class QueryBuilder {
|
|
|
484
486
|
this.helper.getLockSQL(qb, this.lockMode, this.lockTables);
|
|
485
487
|
}
|
|
486
488
|
this.helper.finalize(type, qb, this.mainAlias.metadata, this._data, this._returning);
|
|
489
|
+
this.clearRawFragmentsCache();
|
|
487
490
|
return qb;
|
|
488
491
|
}
|
|
492
|
+
/**
|
|
493
|
+
* @internal
|
|
494
|
+
*/
|
|
495
|
+
clearRawFragmentsCache() {
|
|
496
|
+
this.rawFragments.forEach(key => core_1.RawQueryFragment.remove(key));
|
|
497
|
+
this.rawFragments.clear();
|
|
498
|
+
}
|
|
489
499
|
/**
|
|
490
500
|
* Returns the query with parameters as wildcards.
|
|
491
501
|
*/
|
|
@@ -719,19 +729,26 @@ class QueryBuilder {
|
|
|
719
729
|
}
|
|
720
730
|
clone(reset) {
|
|
721
731
|
const qb = new QueryBuilder(this.mainAlias.entityName, this.metadata, this.driver, this.context, this.mainAlias.aliasName, this.connectionType, this.em);
|
|
722
|
-
if (reset) {
|
|
732
|
+
if (reset === true) {
|
|
723
733
|
return qb;
|
|
724
734
|
}
|
|
725
|
-
|
|
735
|
+
reset = reset || [];
|
|
726
736
|
// clone array/object properties
|
|
727
737
|
const properties = [
|
|
728
738
|
'flags', '_populate', '_populateWhere', '__populateWhere', '_populateMap', '_joins', '_joinedProps', '_cond', '_data', '_orderBy',
|
|
729
739
|
'_schema', '_indexHint', '_cache', 'subQueries', 'lockMode', 'lockTables', '_groupBy', '_having', '_returning',
|
|
730
|
-
'_comments', '_hintComments',
|
|
740
|
+
'_comments', '_hintComments', 'rawFragments',
|
|
731
741
|
];
|
|
732
|
-
|
|
742
|
+
core_1.RawQueryFragment.cloneRegistry = this.rawFragments;
|
|
743
|
+
for (const prop of Object.keys(this)) {
|
|
744
|
+
if (reset.includes(prop)) {
|
|
745
|
+
continue;
|
|
746
|
+
}
|
|
747
|
+
qb[prop] = properties.includes(prop) ? core_1.Utils.copy(this[prop]) : this[prop];
|
|
748
|
+
}
|
|
749
|
+
delete core_1.RawQueryFragment.cloneRegistry;
|
|
733
750
|
/* istanbul ignore else */
|
|
734
|
-
if (this._fields) {
|
|
751
|
+
if (this._fields && !reset.includes('_fields')) {
|
|
735
752
|
qb._fields = [...this._fields];
|
|
736
753
|
}
|
|
737
754
|
qb._aliases = { ...this._aliases };
|
|
@@ -1120,7 +1137,7 @@ class QueryBuilder {
|
|
|
1120
1137
|
}
|
|
1121
1138
|
wrapPaginateSubQuery(meta) {
|
|
1122
1139
|
const pks = this.prepareFields(meta.primaryKeys, 'sub-query');
|
|
1123
|
-
const subQuery = this.clone().select(pks).groupBy(pks).limit(this._limit);
|
|
1140
|
+
const subQuery = this.clone(['_orderBy', '_fields']).select(pks).groupBy(pks).limit(this._limit);
|
|
1124
1141
|
// revert the on conditions added via populateWhere, we want to apply those only once
|
|
1125
1142
|
Object.values(subQuery._joins).forEach(join => join.cond = join.cond_ ?? {});
|
|
1126
1143
|
if (this._offset) {
|
|
@@ -1131,6 +1148,12 @@ class QueryBuilder {
|
|
|
1131
1148
|
const orderBy = [];
|
|
1132
1149
|
for (const orderMap of this._orderBy) {
|
|
1133
1150
|
for (const [field, direction] of Object.entries(orderMap)) {
|
|
1151
|
+
if (core_1.RawQueryFragment.isKnownFragment(field)) {
|
|
1152
|
+
const rawField = core_1.RawQueryFragment.getKnownFragment(field, false);
|
|
1153
|
+
this.rawFragments.add(field);
|
|
1154
|
+
orderBy.push({ [rawField.clone()]: direction });
|
|
1155
|
+
continue;
|
|
1156
|
+
}
|
|
1134
1157
|
const [a, f] = this.helper.splitField(field);
|
|
1135
1158
|
const prop = this.helper.getProperty(f, a);
|
|
1136
1159
|
const type = this.platform.castColumn(prop);
|
|
@@ -1138,7 +1161,8 @@ class QueryBuilder {
|
|
|
1138
1161
|
if (!prop?.persist && !prop?.formula) {
|
|
1139
1162
|
addToSelect.push(fieldName);
|
|
1140
1163
|
}
|
|
1141
|
-
|
|
1164
|
+
const key = (0, core_1.raw)(`min(${this.knex.ref(fieldName)}${type})`);
|
|
1165
|
+
orderBy.push({ [key]: direction });
|
|
1142
1166
|
}
|
|
1143
1167
|
}
|
|
1144
1168
|
subQuery.orderBy(orderBy);
|
|
@@ -1151,10 +1175,17 @@ class QueryBuilder {
|
|
|
1151
1175
|
if (typeof field === 'object' && field && '__as' in field) {
|
|
1152
1176
|
return field.__as === prop;
|
|
1153
1177
|
}
|
|
1178
|
+
if (field instanceof core_1.RawQueryFragment) {
|
|
1179
|
+
// not perfect, but should work most of the time, ideally we should check only the alias (`... as alias`)
|
|
1180
|
+
return field.sql.includes(prop);
|
|
1181
|
+
}
|
|
1154
1182
|
// not perfect, but should work most of the time, ideally we should check only the alias (`... as alias`)
|
|
1155
1183
|
return field.toString().includes(prop);
|
|
1156
1184
|
});
|
|
1157
|
-
if (field) {
|
|
1185
|
+
if (field instanceof core_1.RawQueryFragment) {
|
|
1186
|
+
knexQuery.select(this.platform.formatQuery(field.sql, field.params));
|
|
1187
|
+
}
|
|
1188
|
+
else if (field) {
|
|
1158
1189
|
knexQuery.select(field);
|
|
1159
1190
|
}
|
|
1160
1191
|
});
|
|
@@ -1241,6 +1272,9 @@ class QueryBuilder {
|
|
|
1241
1272
|
prefix = 'Upsert';
|
|
1242
1273
|
object.onConflict = this._onConflict[0];
|
|
1243
1274
|
}
|
|
1275
|
+
if (!core_1.Utils.isEmpty(this._orderBy)) {
|
|
1276
|
+
object.orderBy = this._orderBy;
|
|
1277
|
+
}
|
|
1244
1278
|
const name = this._mainAlias ? `${prefix}QueryBuilder<${this._mainAlias?.entityName}>` : 'QueryBuilder';
|
|
1245
1279
|
const ret = (0, util_1.inspect)(object, { depth });
|
|
1246
1280
|
return ret === '[Object]' ? `[${name}]` : name + ' ' + ret;
|