@mikro-orm/knex 6.3.13-dev.8 → 6.3.13
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
CHANGED
|
@@ -55,7 +55,8 @@ export declare abstract class AbstractSqlDriver<Connection extends AbstractSqlCo
|
|
|
55
55
|
protected getFieldsForJoinedLoad<T extends object>(qb: QueryBuilder<T, any, any, any>, meta: EntityMetadata<T>, explicitFields?: Field<T>[], exclude?: Field<T>[], populate?: PopulateOptions<T>[], options?: {
|
|
56
56
|
strategy?: Options['loadStrategy'];
|
|
57
57
|
populateWhere?: FindOptions<any>['populateWhere'];
|
|
58
|
-
|
|
58
|
+
populateFilter?: FindOptions<any>['populateFilter'];
|
|
59
|
+
}, parentTableAlias?: string, parentJoinPath?: string, count?: boolean): Field<T>[];
|
|
59
60
|
/**
|
|
60
61
|
* @internal
|
|
61
62
|
*/
|
|
@@ -76,5 +77,5 @@ export declare abstract class AbstractSqlDriver<Connection extends AbstractSqlCo
|
|
|
76
77
|
protected normalizeFields<T extends object>(fields: Field<T>[], prefix?: string): string[];
|
|
77
78
|
protected processField<T extends object>(meta: EntityMetadata<T>, prop: EntityProperty<T> | undefined, field: string, ret: Field<T>[], populate: PopulateOptions<T>[], joinedProps: PopulateOptions<T>[], qb: QueryBuilder<T, any, any, any>): void;
|
|
78
79
|
protected isPopulated<T extends object>(meta: EntityMetadata<T>, prop: EntityProperty<T>, hint: PopulateOptions<T>, name?: string): boolean;
|
|
79
|
-
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'>, count?: boolean): Field<T>[];
|
|
80
81
|
}
|
package/AbstractSqlDriver.js
CHANGED
|
@@ -311,15 +311,21 @@ class AbstractSqlDriver extends core_1.DatabaseDriver {
|
|
|
311
311
|
if (meta?.virtual) {
|
|
312
312
|
return this.countVirtual(entityName, where, options);
|
|
313
313
|
}
|
|
314
|
+
const joinedProps = meta ? this.joinedProps(meta, options.populate ?? []) : [];
|
|
315
|
+
const populateWhere = meta ? this.buildPopulateWhere(meta, joinedProps, options) : undefined;
|
|
316
|
+
const populate = options.populate ?? [];
|
|
314
317
|
const qb = this.createQueryBuilder(entityName, options.ctx, options.connectionType, false, options.logging)
|
|
315
318
|
.indexHint(options.indexHint)
|
|
316
319
|
.comment(options.comments)
|
|
317
320
|
.hintComment(options.hintComments)
|
|
318
321
|
.groupBy(options.groupBy)
|
|
319
322
|
.having(options.having)
|
|
320
|
-
.populate(options.
|
|
323
|
+
.populate(populate, joinedProps.length > 0 ? populateWhere : undefined, joinedProps.length > 0 ? options.populateFilter : undefined)
|
|
321
324
|
.withSchema(this.getSchemaName(meta, options))
|
|
322
325
|
.where(where);
|
|
326
|
+
if (meta && !core_1.Utils.isEmpty(populate)) {
|
|
327
|
+
this.buildFields(meta, populate, joinedProps, qb, qb.alias, options, true);
|
|
328
|
+
}
|
|
323
329
|
return this.rethrow(qb.getCount());
|
|
324
330
|
}
|
|
325
331
|
async nativeInsert(entityName, data, options = {}) {
|
|
@@ -909,7 +915,7 @@ class AbstractSqlDriver extends core_1.DatabaseDriver {
|
|
|
909
915
|
}
|
|
910
916
|
return res;
|
|
911
917
|
}
|
|
912
|
-
getFieldsForJoinedLoad(qb, meta, explicitFields, exclude, populate = [], options, parentTableAlias, parentJoinPath) {
|
|
918
|
+
getFieldsForJoinedLoad(qb, meta, explicitFields, exclude, populate = [], options, parentTableAlias, parentJoinPath, count) {
|
|
913
919
|
const fields = [];
|
|
914
920
|
const joinedProps = this.joinedProps(meta, populate, options);
|
|
915
921
|
const shouldHaveColumn = (prop, populate, fields) => {
|
|
@@ -929,12 +935,15 @@ class AbstractSqlDriver extends core_1.DatabaseDriver {
|
|
|
929
935
|
.filter(prop => shouldHaveColumn(prop, populate, explicitFields))
|
|
930
936
|
.forEach(prop => fields.push(...this.mapPropToFieldNames(qb, prop, parentTableAlias)));
|
|
931
937
|
}
|
|
932
|
-
|
|
938
|
+
for (const hint of joinedProps) {
|
|
933
939
|
const [propName, ref] = hint.field.split(':', 2);
|
|
934
940
|
const prop = meta.properties[propName];
|
|
935
941
|
// ignore ref joins of known FKs unless it's a filter hint
|
|
936
942
|
if (ref && !hint.filter && (prop.kind === core_1.ReferenceKind.MANY_TO_ONE || (prop.kind === core_1.ReferenceKind.ONE_TO_ONE && !prop.owner))) {
|
|
937
|
-
|
|
943
|
+
continue;
|
|
944
|
+
}
|
|
945
|
+
if (count && (!options?.populateFilter || !options.populateFilter[prop.name])) {
|
|
946
|
+
continue;
|
|
938
947
|
}
|
|
939
948
|
const meta2 = this.metadata.find(prop.type);
|
|
940
949
|
const pivotRefJoin = prop.kind === core_1.ReferenceKind.MANY_TO_MANY && ref;
|
|
@@ -954,7 +963,7 @@ class AbstractSqlDriver extends core_1.DatabaseDriver {
|
|
|
954
963
|
fields.push(...prop.joinColumns.map(col => qb.helper.mapper(`${tableAlias}.${col}`, qb.type, undefined, `${tableAlias}__${col}`)), ...prop.inverseJoinColumns.map(col => qb.helper.mapper(`${tableAlias}.${col}`, qb.type, undefined, `${tableAlias}__${col}`)));
|
|
955
964
|
}
|
|
956
965
|
if (prop.kind === core_1.ReferenceKind.ONE_TO_MANY && ref) {
|
|
957
|
-
fields.push(...this.getFieldsForJoinedLoad(qb, meta2, prop.referencedColumnNames, undefined, hint.children, options, tableAlias, path));
|
|
966
|
+
fields.push(...this.getFieldsForJoinedLoad(qb, meta2, prop.referencedColumnNames, undefined, hint.children, options, tableAlias, path, count));
|
|
958
967
|
}
|
|
959
968
|
const childExplicitFields = explicitFields?.filter(f => core_1.Utils.isPlainObject(f)).map(o => o[prop.name])[0] || [];
|
|
960
969
|
explicitFields?.forEach(f => {
|
|
@@ -964,12 +973,12 @@ class AbstractSqlDriver extends core_1.DatabaseDriver {
|
|
|
964
973
|
});
|
|
965
974
|
const childExclude = exclude ? core_1.Utils.extractChildElements(exclude, prop.name) : exclude;
|
|
966
975
|
if (!ref) {
|
|
967
|
-
fields.push(...this.getFieldsForJoinedLoad(qb, meta2, childExplicitFields.length === 0 ? undefined : childExplicitFields, childExclude, hint.children, options, tableAlias, path));
|
|
976
|
+
fields.push(...this.getFieldsForJoinedLoad(qb, meta2, childExplicitFields.length === 0 ? undefined : childExplicitFields, childExclude, hint.children, options, tableAlias, path, count));
|
|
968
977
|
}
|
|
969
978
|
else if (hint.filter) {
|
|
970
979
|
fields.push(...prop.referencedColumnNames.map(col => qb.helper.mapper(`${tableAlias}.${col}`, qb.type, undefined, `${tableAlias}__${col}`)));
|
|
971
980
|
}
|
|
972
|
-
}
|
|
981
|
+
}
|
|
973
982
|
return fields;
|
|
974
983
|
}
|
|
975
984
|
/**
|
|
@@ -1232,7 +1241,7 @@ class AbstractSqlDriver extends core_1.DatabaseDriver {
|
|
|
1232
1241
|
}
|
|
1233
1242
|
return false;
|
|
1234
1243
|
}
|
|
1235
|
-
buildFields(meta, populate, joinedProps, qb, alias, options) {
|
|
1244
|
+
buildFields(meta, populate, joinedProps, qb, alias, options, count = false) {
|
|
1236
1245
|
const lazyProps = meta.props.filter(prop => prop.lazy && !populate.some(p => this.isPopulated(meta, prop, p)));
|
|
1237
1246
|
const hasLazyFormulas = meta.props.some(p => p.lazy && p.formula);
|
|
1238
1247
|
const requiresSQLConversion = meta.props.some(p => p.customType?.convertToJSValueSQL && p.persist !== false);
|
|
@@ -1287,7 +1296,7 @@ class AbstractSqlDriver extends core_1.DatabaseDriver {
|
|
|
1287
1296
|
}
|
|
1288
1297
|
// add joined relations after the root entity fields
|
|
1289
1298
|
if (joinedProps.length > 0) {
|
|
1290
|
-
ret.push(...this.getFieldsForJoinedLoad(qb, meta, options.fields, options.exclude, populate, options, alias));
|
|
1299
|
+
ret.push(...this.getFieldsForJoinedLoad(qb, meta, options.fields, options.exclude, populate, options, alias, undefined, count));
|
|
1291
1300
|
}
|
|
1292
1301
|
return core_1.Utils.unique(ret);
|
|
1293
1302
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mikro-orm/knex",
|
|
3
|
-
"version": "6.3.13
|
|
3
|
+
"version": "6.3.13",
|
|
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.3.
|
|
66
|
+
"@mikro-orm/core": "^6.3.13"
|
|
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.d.ts
CHANGED
|
@@ -31,6 +31,7 @@ type EntityRelations<T> = EntityKey<T, true>;
|
|
|
31
31
|
type AddAliasesFromContext<Context> = Context[keyof Context] extends infer Join ? Join extends any ? Join extends [string, infer Alias, infer Type, any] ? `${Alias & string}.${EntityRelations<Type & {}>}` : never : never : never;
|
|
32
32
|
export type QBField<Entity, RootAlias extends string, Context> = (EntityRelations<Entity> | `${RootAlias}.${EntityRelations<Entity>}` | AddAliasesFromContext<Context>) & {} | AnyString;
|
|
33
33
|
export type QBField2<Entity, RootAlias extends string, Context> = (EntityKey<Entity> | `${RootAlias}.${EntityKey<Entity>}` | AddAliasesFromContext<Context>) & {} | AnyString;
|
|
34
|
+
type EntityKeyOrString<Entity extends object = AnyEntity> = AnyString | keyof Entity;
|
|
34
35
|
/**
|
|
35
36
|
* SQL query builder with fluent interface.
|
|
36
37
|
*
|
|
@@ -125,12 +126,12 @@ export declare class QueryBuilder<Entity extends object = AnyEntity, RootAlias e
|
|
|
125
126
|
addSelect(fields: Field<Entity> | Field<Entity>[]): SelectQueryBuilder<Entity, RootAlias, Hint, Context>;
|
|
126
127
|
distinct(): SelectQueryBuilder<Entity, RootAlias, Hint, Context>;
|
|
127
128
|
/** postgres only */
|
|
128
|
-
distinctOn(fields:
|
|
129
|
+
distinctOn(fields: EntityKeyOrString<Entity> | EntityKeyOrString<Entity>[]): SelectQueryBuilder<Entity, RootAlias, Hint, Context>;
|
|
129
130
|
insert(data: RequiredEntityData<Entity> | RequiredEntityData<Entity>[]): InsertQueryBuilder<Entity>;
|
|
130
131
|
update(data: EntityData<Entity>): UpdateQueryBuilder<Entity>;
|
|
131
132
|
delete(cond?: QBFilterQuery): DeleteQueryBuilder<Entity>;
|
|
132
133
|
truncate(): TruncateQueryBuilder<Entity>;
|
|
133
|
-
count(field?:
|
|
134
|
+
count(field?: EntityKeyOrString<Entity> | EntityKeyOrString<Entity>[], distinct?: boolean): CountQueryBuilder<Entity>;
|
|
134
135
|
join<Field extends QBField<Entity, RootAlias, Context>, Alias extends string>(field: Field | Knex.QueryBuilder | QueryBuilder<any>, alias: Alias, cond?: QBFilterQuery, type?: JoinType, path?: string, schema?: string): SelectQueryBuilder<Entity, RootAlias, ModifyHint<RootAlias, Context, Hint, Field> & {}, ModifyContext<Entity, Context, Field, Alias>>;
|
|
135
136
|
innerJoin<Field extends QBField<Entity, RootAlias, Context>, Alias extends string>(field: Field | Knex.QueryBuilder | QueryBuilder<any>, alias: Alias, cond?: QBFilterQuery, schema?: string): SelectQueryBuilder<Entity, RootAlias, ModifyHint<RootAlias, Context, Hint, Field> & {}, ModifyContext<Entity, Context, Field, Alias>>;
|
|
136
137
|
innerJoinLateral(field: Knex.QueryBuilder | QueryBuilder<any>, alias: string, cond?: QBFilterQuery, schema?: string): this;
|
|
@@ -154,7 +155,7 @@ export declare class QueryBuilder<Entity extends object = AnyEntity, RootAlias e
|
|
|
154
155
|
orWhere(cond: QBFilterQuery<Entity>): this;
|
|
155
156
|
orWhere(cond: string, params?: any[]): this;
|
|
156
157
|
orderBy(orderBy: QBQueryOrderMap<Entity> | QBQueryOrderMap<Entity>[]): SelectQueryBuilder<Entity, RootAlias, Hint, Context>;
|
|
157
|
-
groupBy(fields:
|
|
158
|
+
groupBy(fields: EntityKeyOrString<Entity> | readonly EntityKeyOrString<Entity>[]): SelectQueryBuilder<Entity, RootAlias, Hint, Context>;
|
|
158
159
|
having(cond?: QBFilterQuery | string, params?: any[]): SelectQueryBuilder<Entity, RootAlias, Hint, Context>;
|
|
159
160
|
onConflict(fields?: Field<Entity> | Field<Entity>[]): InsertQueryBuilder<Entity>;
|
|
160
161
|
ignore(): this;
|
|
@@ -251,7 +252,7 @@ export declare class QueryBuilder<Entity extends object = AnyEntity, RootAlias e
|
|
|
251
252
|
/**
|
|
252
253
|
* Executes count query (without offset and limit), returning total count of results
|
|
253
254
|
*/
|
|
254
|
-
getCount(field?:
|
|
255
|
+
getCount(field?: EntityKeyOrString<Entity> | EntityKeyOrString<Entity>[], distinct?: boolean): Promise<number>;
|
|
255
256
|
/**
|
|
256
257
|
* Executes the query, returning both array of results and total count query (without offset and limit).
|
|
257
258
|
*/
|
package/query/QueryBuilder.js
CHANGED
|
@@ -1172,7 +1172,6 @@ class QueryBuilder {
|
|
|
1172
1172
|
let joins = Object.values(this._joins);
|
|
1173
1173
|
for (const join of joins) {
|
|
1174
1174
|
join.cond_ ??= join.cond;
|
|
1175
|
-
// join.cond = {};
|
|
1176
1175
|
join.cond = filter ? { ...join.cond } : {};
|
|
1177
1176
|
}
|
|
1178
1177
|
if (typeof this[key] === 'object') {
|
|
@@ -1335,6 +1334,7 @@ class QueryBuilder {
|
|
|
1335
1334
|
// wrap one more time to get around MySQL limitations
|
|
1336
1335
|
// https://stackoverflow.com/questions/45494/mysql-error-1093-cant-specify-target-table-for-update-in-from-clause
|
|
1337
1336
|
const subSubQuery = this.getKnex().select(this.prepareFields(meta.primaryKeys)).from(subQuery.as(this.mainAlias.aliasName));
|
|
1337
|
+
subSubQuery.__raw = true; // tag it as there is now way to check via `instanceof`
|
|
1338
1338
|
const method = this.flags.has(core_1.QueryFlag.UPDATE_SUB_QUERY) ? 'update' : 'delete';
|
|
1339
1339
|
this._cond = {}; // otherwise we would trigger validation error
|
|
1340
1340
|
this[method](this._data).where({
|
|
@@ -390,7 +390,7 @@ class SchemaComparator {
|
|
|
390
390
|
const toProp = this.mapColumnToProperty({ ...toColumn, autoincrement: false });
|
|
391
391
|
const fromColumnType = this.platform.normalizeColumnType(fromColumn.mappedType.getColumnType(fromProp, this.platform).toLowerCase(), fromProp);
|
|
392
392
|
const fromNativeEnum = fromTable.nativeEnums[fromColumnType] ?? Object.values(fromTable.nativeEnums).find(e => e.name === fromColumnType && e.schema !== '*');
|
|
393
|
-
|
|
393
|
+
let toColumnType = this.platform.normalizeColumnType(toColumn.mappedType.getColumnType(toProp, this.platform).toLowerCase(), toProp);
|
|
394
394
|
const log = (msg, params) => {
|
|
395
395
|
if (tableName) {
|
|
396
396
|
const copy = core_1.Utils.copy(params);
|
|
@@ -402,8 +402,13 @@ class SchemaComparator {
|
|
|
402
402
|
(!fromNativeEnum || `${fromNativeEnum.schema}.${fromNativeEnum.name}` !== toColumnType) &&
|
|
403
403
|
!(fromColumn.ignoreSchemaChanges?.includes('type') || toColumn.ignoreSchemaChanges?.includes('type')) &&
|
|
404
404
|
!fromColumn.generated && !toColumn.generated) {
|
|
405
|
-
|
|
406
|
-
|
|
405
|
+
if (!toColumnType.includes('.') && fromTable.schema && fromTable.schema !== this.platform.getDefaultSchemaName()) {
|
|
406
|
+
toColumnType = `${fromTable.schema}.${toColumnType}`;
|
|
407
|
+
}
|
|
408
|
+
if (fromColumnType !== toColumnType) {
|
|
409
|
+
log(`'type' changed for column ${tableName}.${fromColumn.name}`, { fromColumnType, toColumnType });
|
|
410
|
+
changedProperties.add('type');
|
|
411
|
+
}
|
|
407
412
|
}
|
|
408
413
|
if (fromColumn.nullable !== toColumn.nullable && !fromColumn.generated && !toColumn.generated) {
|
|
409
414
|
log(`'nullable' changed for column ${tableName}.${fromColumn.name}`, { fromColumn, toColumn });
|
|
@@ -284,7 +284,9 @@ class SqlSchemaGenerator extends core_1.AbstractSchemaGenerator {
|
|
|
284
284
|
if (!column.nativeEnumName) {
|
|
285
285
|
continue;
|
|
286
286
|
}
|
|
287
|
-
const key = schemaName && schemaName !== this.platform.getDefaultSchemaName()
|
|
287
|
+
const key = schemaName && schemaName !== this.platform.getDefaultSchemaName() && !column.nativeEnumName.includes('.')
|
|
288
|
+
? schemaName + '.' + column.nativeEnumName
|
|
289
|
+
: column.nativeEnumName;
|
|
288
290
|
if (changedProperties.has('enumItems') && key in diff.fromTable.nativeEnums) {
|
|
289
291
|
changedNativeEnums.push([column.nativeEnumName, column.enumItems, diff.fromTable.nativeEnums[key].items]);
|
|
290
292
|
}
|
|
@@ -293,6 +295,11 @@ class SqlSchemaGenerator extends core_1.AbstractSchemaGenerator {
|
|
|
293
295
|
// postgres allows only adding new items, the values are case insensitive
|
|
294
296
|
itemsOld = itemsOld.map(v => v.toLowerCase());
|
|
295
297
|
const newItems = itemsNew.filter(val => !itemsOld.includes(val.toLowerCase()));
|
|
298
|
+
if (enumName.includes('.')) {
|
|
299
|
+
const [enumSchemaName, rawEnumName] = enumName.split('.');
|
|
300
|
+
ret.push(...newItems.map(val => this.knex.schema.raw(this.helper.getAlterNativeEnumSQL(rawEnumName, enumSchemaName, val, itemsNew, itemsOld))));
|
|
301
|
+
return;
|
|
302
|
+
}
|
|
296
303
|
ret.push(...newItems.map(val => this.knex.schema.raw(this.helper.getAlterNativeEnumSQL(enumName, schemaName, val, itemsNew, itemsOld))));
|
|
297
304
|
});
|
|
298
305
|
}
|