@mikro-orm/knex 6.6.5-dev.5 → 6.6.5
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 +2 -2
- package/AbstractSqlDriver.js +32 -10
- package/package.json +3 -3
- package/query/QueryBuilder.js +14 -9
- package/query/QueryBuilderHelper.d.ts +3 -2
- package/query/QueryBuilderHelper.js +20 -3
package/AbstractSqlDriver.d.ts
CHANGED
|
@@ -61,7 +61,7 @@ export declare abstract class AbstractSqlDriver<Connection extends AbstractSqlCo
|
|
|
61
61
|
/**
|
|
62
62
|
* @internal
|
|
63
63
|
*/
|
|
64
|
-
mapPropToFieldNames<T extends object>(qb: QueryBuilder<T, any, any, any>, prop: EntityProperty<T>, tableAlias?: string, explicitFields?: Field<T>[]): Field<T>[];
|
|
64
|
+
mapPropToFieldNames<T extends object>(qb: QueryBuilder<T, any, any, any>, prop: EntityProperty<T>, tableAlias: string | undefined, meta: EntityMetadata<T>, schema?: string, explicitFields?: readonly Field<T>[]): Field<T>[];
|
|
65
65
|
/** @internal */
|
|
66
66
|
createQueryBuilder<T extends object>(entityName: EntityName<T> | QueryBuilder<T, any, any, any>, ctx?: Transaction<Knex.Transaction>, preferredConnectionType?: ConnectionType, convertCustomTypes?: boolean, loggerContext?: LoggingOptions, alias?: string, em?: SqlEntityManager): QueryBuilder<T, any, any, any>;
|
|
67
67
|
protected resolveConnectionType(args: {
|
|
@@ -77,5 +77,5 @@ export declare abstract class AbstractSqlDriver<Connection extends AbstractSqlCo
|
|
|
77
77
|
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>[];
|
|
78
78
|
protected normalizeFields<T extends object>(fields: Field<T>[], prefix?: string): string[];
|
|
79
79
|
protected processField<T extends object>(meta: EntityMetadata<T>, prop: EntityProperty<T> | undefined, field: string, ret: Field<T>[]): void;
|
|
80
|
-
protected buildFields<T extends object>(meta: EntityMetadata<T>, populate: PopulateOptions<T>[], joinedProps: PopulateOptions<T>[], qb: QueryBuilder<T, any, any, any>, alias: string, options: Pick<FindOptions<T, any, any, any>, 'strategy' | 'fields' | 'exclude'
|
|
80
|
+
protected buildFields<T extends object>(meta: EntityMetadata<T>, populate: PopulateOptions<T>[], joinedProps: PopulateOptions<T>[], qb: QueryBuilder<T, any, any, any>, alias: string, options: Pick<FindOptions<T, any, any, any>, 'strategy' | 'fields' | 'exclude'>, schema?: string): Field<T>[];
|
|
81
81
|
}
|
package/AbstractSqlDriver.js
CHANGED
|
@@ -31,9 +31,10 @@ class AbstractSqlDriver extends core_1.DatabaseDriver {
|
|
|
31
31
|
}
|
|
32
32
|
const populate = this.autoJoinOneToOneOwner(meta, options.populate, options.fields);
|
|
33
33
|
const joinedProps = this.joinedProps(meta, populate, options);
|
|
34
|
+
const schema = this.getSchemaName(meta, options);
|
|
34
35
|
const qb = this.createQueryBuilder(entityName, options.ctx, options.connectionType, false, options.logging)
|
|
35
|
-
.withSchema(
|
|
36
|
-
const fields = this.buildFields(meta, populate, joinedProps, qb, qb.alias, options);
|
|
36
|
+
.withSchema(schema);
|
|
37
|
+
const fields = this.buildFields(meta, populate, joinedProps, qb, qb.alias, options, schema);
|
|
37
38
|
const orderBy = this.buildOrderBy(qb, meta, populate, options);
|
|
38
39
|
const populateWhere = this.buildPopulateWhere(meta, joinedProps, options);
|
|
39
40
|
core_1.Utils.asArray(options.flags).forEach(flag => qb.setFlag(flag));
|
|
@@ -320,10 +321,11 @@ class AbstractSqlDriver extends core_1.DatabaseDriver {
|
|
|
320
321
|
options = { populate: [], ...options };
|
|
321
322
|
const populate = options.populate;
|
|
322
323
|
const joinedProps = this.joinedProps(meta, populate, options);
|
|
324
|
+
const schema = this.getSchemaName(meta, options);
|
|
323
325
|
const qb = this.createQueryBuilder(entityName, options.ctx, options.connectionType, false, options.logging);
|
|
324
326
|
const populateWhere = this.buildPopulateWhere(meta, joinedProps, options);
|
|
325
327
|
if (meta && !core_1.Utils.isEmpty(populate)) {
|
|
326
|
-
this.buildFields(meta, populate, joinedProps, qb, qb.alias, options);
|
|
328
|
+
this.buildFields(meta, populate, joinedProps, qb, qb.alias, options, schema);
|
|
327
329
|
}
|
|
328
330
|
qb.__populateWhere = options._populateWhere;
|
|
329
331
|
qb.indexHint(options.indexHint)
|
|
@@ -332,7 +334,7 @@ class AbstractSqlDriver extends core_1.DatabaseDriver {
|
|
|
332
334
|
.groupBy(options.groupBy)
|
|
333
335
|
.having(options.having)
|
|
334
336
|
.populate(populate, joinedProps.length > 0 ? populateWhere : undefined, joinedProps.length > 0 ? options.populateFilter : undefined)
|
|
335
|
-
.withSchema(
|
|
337
|
+
.withSchema(schema)
|
|
336
338
|
.where(where);
|
|
337
339
|
if (options.em) {
|
|
338
340
|
await qb.applyJoinedFilters(options.em, options.filters);
|
|
@@ -952,7 +954,7 @@ class AbstractSqlDriver extends core_1.DatabaseDriver {
|
|
|
952
954
|
// alias all fields in the primary table
|
|
953
955
|
meta.props
|
|
954
956
|
.filter(prop => this.shouldHaveColumn(meta, prop, populate, explicitFields, exclude))
|
|
955
|
-
.forEach(prop => fields.push(...this.mapPropToFieldNames(qb, prop, parentTableAlias, explicitFields)));
|
|
957
|
+
.forEach(prop => fields.push(...this.mapPropToFieldNames(qb, prop, parentTableAlias, meta, undefined, explicitFields)));
|
|
956
958
|
}
|
|
957
959
|
for (const hint of joinedProps) {
|
|
958
960
|
const [propName, ref] = hint.field.split(':', 2);
|
|
@@ -1003,14 +1005,14 @@ class AbstractSqlDriver extends core_1.DatabaseDriver {
|
|
|
1003
1005
|
/**
|
|
1004
1006
|
* @internal
|
|
1005
1007
|
*/
|
|
1006
|
-
mapPropToFieldNames(qb, prop, tableAlias, explicitFields) {
|
|
1008
|
+
mapPropToFieldNames(qb, prop, tableAlias, meta, schema, explicitFields) {
|
|
1007
1009
|
if (prop.kind === core_1.ReferenceKind.EMBEDDED && !prop.object) {
|
|
1008
1010
|
return Object.entries(prop.embeddedProps).flatMap(([name, childProp]) => {
|
|
1009
1011
|
const childFields = explicitFields ? core_1.Utils.extractChildElements(explicitFields, prop.name) : [];
|
|
1010
1012
|
if (!this.shouldHaveColumn(prop.targetMeta, { ...childProp, name }, [], childFields.length > 0 ? childFields : undefined)) {
|
|
1011
1013
|
return [];
|
|
1012
1014
|
}
|
|
1013
|
-
return this.mapPropToFieldNames(qb, childProp, tableAlias, childFields);
|
|
1015
|
+
return this.mapPropToFieldNames(qb, childProp, tableAlias, meta, schema, childFields);
|
|
1014
1016
|
});
|
|
1015
1017
|
}
|
|
1016
1018
|
const aliased = this.platform.quoteIdentifier(tableAlias ? `${tableAlias}__${prop.fieldNames[0]}` : prop.fieldNames[0]);
|
|
@@ -1030,7 +1032,17 @@ class AbstractSqlDriver extends core_1.DatabaseDriver {
|
|
|
1030
1032
|
}
|
|
1031
1033
|
if (prop.formula) {
|
|
1032
1034
|
const alias = this.platform.quoteIdentifier(tableAlias ?? qb.alias);
|
|
1033
|
-
|
|
1035
|
+
const effectiveSchema = schema ?? (meta.schema !== '*' ? meta.schema : undefined);
|
|
1036
|
+
const qualifiedName = effectiveSchema ? `${effectiveSchema}.${meta.tableName}` : meta.tableName;
|
|
1037
|
+
const table = {
|
|
1038
|
+
alias: alias.toString(),
|
|
1039
|
+
name: meta.tableName,
|
|
1040
|
+
schema: effectiveSchema,
|
|
1041
|
+
qualifiedName,
|
|
1042
|
+
toString: () => alias.toString(),
|
|
1043
|
+
};
|
|
1044
|
+
const columns = meta.createColumnMappingObject();
|
|
1045
|
+
return [(0, core_1.raw)(`${(prop.formula(table, columns))} as ${aliased}`)];
|
|
1034
1046
|
}
|
|
1035
1047
|
if (tableAlias) {
|
|
1036
1048
|
return prop.fieldNames.map(fieldName => {
|
|
@@ -1260,7 +1272,7 @@ class AbstractSqlDriver extends core_1.DatabaseDriver {
|
|
|
1260
1272
|
}
|
|
1261
1273
|
ret.push(prop.name);
|
|
1262
1274
|
}
|
|
1263
|
-
buildFields(meta, populate, joinedProps, qb, alias, options) {
|
|
1275
|
+
buildFields(meta, populate, joinedProps, qb, alias, options, schema) {
|
|
1264
1276
|
const lazyProps = meta.props.filter(prop => prop.lazy && !populate.some(p => this.isPopulated(meta, prop, p)));
|
|
1265
1277
|
const hasLazyFormulas = meta.props.some(p => p.lazy && p.formula);
|
|
1266
1278
|
const requiresSQLConversion = meta.props.some(p => p.customType?.convertToJSValueSQL && p.persist !== false);
|
|
@@ -1305,6 +1317,8 @@ class AbstractSqlDriver extends core_1.DatabaseDriver {
|
|
|
1305
1317
|
ret.push('*');
|
|
1306
1318
|
}
|
|
1307
1319
|
if (ret.length > 0 && !hasExplicitFields && addFormulas) {
|
|
1320
|
+
const columns = meta.createColumnMappingObject();
|
|
1321
|
+
const effectiveSchema = schema ?? (meta.schema !== '*' ? meta.schema : undefined);
|
|
1308
1322
|
for (const prop of meta.props) {
|
|
1309
1323
|
if (lazyProps.includes(prop)) {
|
|
1310
1324
|
continue;
|
|
@@ -1312,7 +1326,15 @@ class AbstractSqlDriver extends core_1.DatabaseDriver {
|
|
|
1312
1326
|
if (prop.formula) {
|
|
1313
1327
|
const a = this.platform.quoteIdentifier(alias);
|
|
1314
1328
|
const aliased = this.platform.quoteIdentifier(prop.fieldNames[0]);
|
|
1315
|
-
|
|
1329
|
+
const qualifiedName = effectiveSchema ? `${effectiveSchema}.${meta.tableName}` : meta.tableName;
|
|
1330
|
+
const table = {
|
|
1331
|
+
alias: a.toString(),
|
|
1332
|
+
name: meta.tableName,
|
|
1333
|
+
schema: effectiveSchema,
|
|
1334
|
+
qualifiedName,
|
|
1335
|
+
toString: () => a.toString(),
|
|
1336
|
+
};
|
|
1337
|
+
ret.push((0, core_1.raw)(`${(prop.formula(table, columns))} as ${aliased}`));
|
|
1316
1338
|
}
|
|
1317
1339
|
if (!prop.object && (prop.hasConvertToDatabaseValueSQL || prop.hasConvertToJSValueSQL)) {
|
|
1318
1340
|
ret.push(prop.name);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mikro-orm/knex",
|
|
3
|
-
"version": "6.6.5
|
|
3
|
+
"version": "6.6.5",
|
|
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",
|
|
@@ -63,10 +63,10 @@
|
|
|
63
63
|
"sqlstring": "2.3.3"
|
|
64
64
|
},
|
|
65
65
|
"devDependencies": {
|
|
66
|
-
"@mikro-orm/core": "^6.6.
|
|
66
|
+
"@mikro-orm/core": "^6.6.5"
|
|
67
67
|
},
|
|
68
68
|
"peerDependencies": {
|
|
69
|
-
"@mikro-orm/core": "6.
|
|
69
|
+
"@mikro-orm/core": "^6.0.0",
|
|
70
70
|
"better-sqlite3": "*",
|
|
71
71
|
"libsql": "*",
|
|
72
72
|
"mariadb": "*"
|
package/query/QueryBuilder.js
CHANGED
|
@@ -222,6 +222,8 @@ class QueryBuilder {
|
|
|
222
222
|
const fields = [];
|
|
223
223
|
const populate = [];
|
|
224
224
|
const joinKey = Object.keys(this._joins).find(join => join.endsWith(`#${alias}`));
|
|
225
|
+
const targetMeta = prop.targetMeta;
|
|
226
|
+
const schema = this._schema ?? (targetMeta.schema !== '*' ? targetMeta.schema : undefined);
|
|
225
227
|
if (joinKey) {
|
|
226
228
|
const path = this._joins[joinKey].path.split('.').slice(1);
|
|
227
229
|
let children = this._populate;
|
|
@@ -234,29 +236,29 @@ class QueryBuilder {
|
|
|
234
236
|
}
|
|
235
237
|
populate.push(...children);
|
|
236
238
|
}
|
|
237
|
-
for (const p of
|
|
238
|
-
fields.push(...this.driver.mapPropToFieldNames(this, p, alias));
|
|
239
|
+
for (const p of targetMeta.getPrimaryProps()) {
|
|
240
|
+
fields.push(...this.driver.mapPropToFieldNames(this, p, alias, targetMeta, schema));
|
|
239
241
|
}
|
|
240
242
|
if (explicitFields) {
|
|
241
243
|
for (const field of explicitFields) {
|
|
242
244
|
const [a, f] = this.helper.splitField(field);
|
|
243
|
-
const p =
|
|
245
|
+
const p = targetMeta.properties[f];
|
|
244
246
|
if (p) {
|
|
245
|
-
fields.push(...this.driver.mapPropToFieldNames(this, p, alias));
|
|
247
|
+
fields.push(...this.driver.mapPropToFieldNames(this, p, alias, targetMeta, schema));
|
|
246
248
|
}
|
|
247
249
|
else {
|
|
248
250
|
fields.push(`${a}.${f} as ${a}__${f}`);
|
|
249
251
|
}
|
|
250
252
|
}
|
|
251
253
|
}
|
|
252
|
-
|
|
254
|
+
targetMeta.props
|
|
253
255
|
.filter(prop => {
|
|
254
256
|
if (!explicitFields) {
|
|
255
257
|
return this.platform.shouldHaveColumn(prop, populate);
|
|
256
258
|
}
|
|
257
259
|
return prop.primary && !explicitFields.includes(prop.name) && !explicitFields.includes(`${alias}.${prop.name}`);
|
|
258
260
|
})
|
|
259
|
-
.forEach(prop => fields.push(...this.driver.mapPropToFieldNames(this, prop, alias)));
|
|
261
|
+
.forEach(prop => fields.push(...this.driver.mapPropToFieldNames(this, prop, alias, targetMeta, schema)));
|
|
260
262
|
return fields;
|
|
261
263
|
}
|
|
262
264
|
/**
|
|
@@ -1164,12 +1166,15 @@ class QueryBuilder {
|
|
|
1164
1166
|
this.processPopulateHint();
|
|
1165
1167
|
this.processNestedJoins();
|
|
1166
1168
|
if (meta && (this._fields?.includes('*') || this._fields?.includes(`${this.mainAlias.aliasName}.*`))) {
|
|
1169
|
+
const schema = this.getSchema(this.mainAlias);
|
|
1170
|
+
const columns = meta.createColumnMappingObject();
|
|
1167
1171
|
meta.props
|
|
1168
1172
|
.filter(prop => prop.formula && (!prop.lazy || this.flags.has(core_1.QueryFlag.INCLUDE_LAZY_FORMULAS)))
|
|
1169
1173
|
.map(prop => {
|
|
1170
|
-
const alias = this.
|
|
1171
|
-
const aliased = this.
|
|
1172
|
-
|
|
1174
|
+
const alias = this.platform.quoteIdentifier(this.mainAlias.aliasName);
|
|
1175
|
+
const aliased = this.platform.quoteIdentifier(prop.fieldNames[0]);
|
|
1176
|
+
const table = this.helper.createFormulaTable(alias.toString(), meta, schema);
|
|
1177
|
+
return `${(prop.formula(table, columns))} as ${aliased}`;
|
|
1173
1178
|
})
|
|
1174
1179
|
.filter(field => !this._fields.some(f => {
|
|
1175
1180
|
if (f instanceof core_1.RawQueryFragment) {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { Knex } from 'knex';
|
|
2
|
-
import { type Dictionary, type EntityData, type EntityKey, type EntityMetadata, type EntityProperty, type FlatQueryOrderMap, LockMode, type QBFilterQuery, RawQueryFragment } from '@mikro-orm/core';
|
|
2
|
+
import { type Dictionary, type EntityData, type EntityKey, type EntityMetadata, type EntityProperty, type FlatQueryOrderMap, type FormulaTable, LockMode, type QBFilterQuery, RawQueryFragment } from '@mikro-orm/core';
|
|
3
3
|
import { JoinType, QueryType } from './enums';
|
|
4
4
|
import type { Field, JoinOptions } from '../typings';
|
|
5
5
|
import type { AbstractSqlDriver } from '../AbstractSqlDriver';
|
|
@@ -17,7 +17,7 @@ export declare class QueryBuilderHelper {
|
|
|
17
17
|
private readonly metadata;
|
|
18
18
|
constructor(entityName: string, alias: string, aliasMap: Dictionary<Alias<any>>, subQueries: Dictionary<string>, knex: Knex, driver: AbstractSqlDriver);
|
|
19
19
|
mapper(field: string | Knex.Raw, type?: QueryType): string;
|
|
20
|
-
mapper(field: string | Knex.Raw, type?: QueryType, value?: any, alias?: string | null): string;
|
|
20
|
+
mapper(field: string | Knex.Raw, type?: QueryType, value?: any, alias?: string | null, schema?: string): string;
|
|
21
21
|
processData(data: Dictionary, convertCustomTypes: boolean, multi?: boolean): any;
|
|
22
22
|
joinOneToReference(prop: EntityProperty, ownerAlias: string, alias: string, type: JoinType, cond?: Dictionary, schema?: string): JoinOptions;
|
|
23
23
|
joinManyToOneReference(prop: EntityProperty, ownerAlias: string, alias: string, type: JoinType, cond?: Dictionary, schema?: string): JoinOptions;
|
|
@@ -60,6 +60,7 @@ export declare class QueryBuilderHelper {
|
|
|
60
60
|
getProperty(field: string, alias?: string): EntityProperty | undefined;
|
|
61
61
|
isTableNameAliasRequired(type?: QueryType): boolean;
|
|
62
62
|
processOnConflictCondition(cond: QBFilterQuery, schema?: string): QBFilterQuery;
|
|
63
|
+
createFormulaTable(alias: string, meta: EntityMetadata, schema?: string): FormulaTable;
|
|
63
64
|
}
|
|
64
65
|
export interface Alias<T> {
|
|
65
66
|
aliasName: string;
|
|
@@ -26,7 +26,7 @@ class QueryBuilderHelper {
|
|
|
26
26
|
this.platform = this.driver.getPlatform();
|
|
27
27
|
this.metadata = this.driver.getMetadata();
|
|
28
28
|
}
|
|
29
|
-
mapper(field, type = enums_1.QueryType.SELECT, value, alias) {
|
|
29
|
+
mapper(field, type = enums_1.QueryType.SELECT, value, alias, schema) {
|
|
30
30
|
if (core_1.Utils.isRawSql(field)) {
|
|
31
31
|
return this.knex.raw(field.sql, field.params);
|
|
32
32
|
}
|
|
@@ -87,7 +87,10 @@ class QueryBuilderHelper {
|
|
|
87
87
|
const alias2 = this.knex.ref(a).toString();
|
|
88
88
|
const aliased = this.knex.ref(prop.fieldNames[0]).toString();
|
|
89
89
|
const as = alias === null ? '' : ` as ${aliased}`;
|
|
90
|
-
|
|
90
|
+
const meta = this.aliasMap[a]?.metadata ?? this.metadata.get(this.entityName);
|
|
91
|
+
const table = this.createFormulaTable(alias2, meta, schema);
|
|
92
|
+
const columns = meta.createColumnMappingObject();
|
|
93
|
+
let value = prop.formula(table, columns);
|
|
91
94
|
if (!this.isTableNameAliasRequired(type)) {
|
|
92
95
|
value = value.replaceAll(alias2 + '.', '');
|
|
93
96
|
}
|
|
@@ -208,7 +211,10 @@ class QueryBuilderHelper {
|
|
|
208
211
|
const right = `${join.alias}.${join.joinColumns[idx]}`;
|
|
209
212
|
if (join.prop.formula) {
|
|
210
213
|
const alias = this.platform.quoteIdentifier(join.ownerAlias);
|
|
211
|
-
const
|
|
214
|
+
const ownerMeta = this.aliasMap[join.ownerAlias]?.metadata ?? this.metadata.get(this.entityName);
|
|
215
|
+
const table = this.createFormulaTable(alias.toString(), ownerMeta, schema);
|
|
216
|
+
const columns = ownerMeta.createColumnMappingObject();
|
|
217
|
+
const left = join.prop.formula(table, columns);
|
|
212
218
|
conditions.push(`${left} = ${this.knex.ref(right)}`);
|
|
213
219
|
return;
|
|
214
220
|
}
|
|
@@ -770,5 +776,16 @@ class QueryBuilderHelper {
|
|
|
770
776
|
}
|
|
771
777
|
return cond;
|
|
772
778
|
}
|
|
779
|
+
createFormulaTable(alias, meta, schema) {
|
|
780
|
+
const effectiveSchema = schema ?? (meta.schema !== '*' ? meta.schema : undefined);
|
|
781
|
+
const qualifiedName = effectiveSchema ? `${effectiveSchema}.${meta.tableName}` : meta.tableName;
|
|
782
|
+
return {
|
|
783
|
+
alias,
|
|
784
|
+
name: meta.tableName,
|
|
785
|
+
schema: effectiveSchema,
|
|
786
|
+
qualifiedName,
|
|
787
|
+
toString: () => alias,
|
|
788
|
+
};
|
|
789
|
+
}
|
|
773
790
|
}
|
|
774
791
|
exports.QueryBuilderHelper = QueryBuilderHelper;
|