@mikro-orm/knex 7.0.0-dev.2 → 7.0.0-dev.4
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 +9 -3
- package/dialects/mssql/MsSqlNativeQueryBuilder.js +5 -3
- package/package.json +3 -3
- package/query/CriteriaNode.js +1 -5
- package/query/QueryBuilder.d.ts +0 -7
- package/query/QueryBuilder.js +0 -20
- package/query/QueryBuilderHelper.js +2 -8
- package/schema/SqlSchemaGenerator.js +5 -15
package/AbstractSqlDriver.js
CHANGED
|
@@ -252,6 +252,9 @@ export class AbstractSqlDriver extends DatabaseDriver {
|
|
|
252
252
|
: meta2.props.filter(prop => this.platform.shouldHaveColumn(prop, hint.children || []));
|
|
253
253
|
const tz = this.platform.getTimezone();
|
|
254
254
|
for (const prop of targetProps) {
|
|
255
|
+
if (prop.fieldNames.every(name => typeof root[`${relationAlias}__${name}`] === 'undefined')) {
|
|
256
|
+
continue;
|
|
257
|
+
}
|
|
255
258
|
if (prop.fieldNames.length > 1) { // composite keys
|
|
256
259
|
const fk = prop.fieldNames.map(name => root[`${relationAlias}__${name}`]);
|
|
257
260
|
const pk = Utils.mapFlatCompositePrimaryKey(fk, prop);
|
|
@@ -927,11 +930,11 @@ export class AbstractSqlDriver extends DatabaseDriver {
|
|
|
927
930
|
const fields = [];
|
|
928
931
|
const populate = options.populate ?? [];
|
|
929
932
|
const joinedProps = this.joinedProps(meta, populate, options);
|
|
930
|
-
const shouldHaveColumn = (prop, populate, fields) => {
|
|
933
|
+
const shouldHaveColumn = (meta, prop, populate, fields) => {
|
|
931
934
|
if (!this.platform.shouldHaveColumn(prop, populate, options.exclude)) {
|
|
932
935
|
return false;
|
|
933
936
|
}
|
|
934
|
-
if (!fields || fields.includes('*') || prop.primary) {
|
|
937
|
+
if (!fields || fields.includes('*') || prop.primary || meta.root.discriminatorColumn === prop.name) {
|
|
935
938
|
return true;
|
|
936
939
|
}
|
|
937
940
|
return fields.some(f => f === prop.name || f.toString().startsWith(prop.name + '.'));
|
|
@@ -941,7 +944,7 @@ export class AbstractSqlDriver extends DatabaseDriver {
|
|
|
941
944
|
if (options.parentJoinPath) {
|
|
942
945
|
// alias all fields in the primary table
|
|
943
946
|
meta.props
|
|
944
|
-
.filter(prop => shouldHaveColumn(prop, populate, options.explicitFields))
|
|
947
|
+
.filter(prop => shouldHaveColumn(meta, prop, populate, options.explicitFields))
|
|
945
948
|
.forEach(prop => fields.push(...this.mapPropToFieldNames(qb, prop, options.parentTableAlias)));
|
|
946
949
|
}
|
|
947
950
|
for (const hint of joinedProps) {
|
|
@@ -1289,6 +1292,9 @@ export class AbstractSqlDriver extends DatabaseDriver {
|
|
|
1289
1292
|
if (!options.fields.includes('*') && !options.fields.includes(`${qb.alias}.*`)) {
|
|
1290
1293
|
ret.unshift(...meta.primaryKeys.filter(pk => !options.fields.includes(pk)));
|
|
1291
1294
|
}
|
|
1295
|
+
if (meta.root.discriminatorColumn && !options.fields.includes(`${qb.alias}.${meta.root.discriminatorColumn}`)) {
|
|
1296
|
+
ret.push(meta.root.discriminatorColumn);
|
|
1297
|
+
}
|
|
1292
1298
|
}
|
|
1293
1299
|
else if (!Utils.isEmpty(options.exclude) || lazyProps.some(p => !p.formula && (p.kind !== '1:1' || p.owner))) {
|
|
1294
1300
|
const props = meta.props.filter(prop => this.platform.shouldHaveColumn(prop, populate, options.exclude, false));
|
|
@@ -65,9 +65,11 @@ export class MsSqlNativeQueryBuilder extends NativeQueryBuilder {
|
|
|
65
65
|
this.params.push(...clause.fields.params);
|
|
66
66
|
}
|
|
67
67
|
else if (clause.fields.length > 0) {
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
68
|
+
const fields = clause.fields.map(field => {
|
|
69
|
+
const col = this.quote(field);
|
|
70
|
+
return `${this.getTableName()}.${col} = tsource.${col}`;
|
|
71
|
+
});
|
|
72
|
+
this.parts.push(`on ${fields.join(' and ')}`);
|
|
71
73
|
}
|
|
72
74
|
const sourceColumns = keys.map(field => `tsource.${this.quote(field)}`).join(', ');
|
|
73
75
|
const destinationColumns = keys.map(field => this.quote(field)).join(', ');
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mikro-orm/knex",
|
|
3
|
-
"version": "7.0.0-dev.
|
|
3
|
+
"version": "7.0.0-dev.4",
|
|
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": {
|
|
@@ -54,9 +54,9 @@
|
|
|
54
54
|
"sqlstring": "2.3.3"
|
|
55
55
|
},
|
|
56
56
|
"devDependencies": {
|
|
57
|
-
"@mikro-orm/core": "^6.4.
|
|
57
|
+
"@mikro-orm/core": "^6.4.7"
|
|
58
58
|
},
|
|
59
59
|
"peerDependencies": {
|
|
60
|
-
"@mikro-orm/core": "7.0.0-dev.
|
|
60
|
+
"@mikro-orm/core": "7.0.0-dev.4"
|
|
61
61
|
}
|
|
62
62
|
}
|
package/query/CriteriaNode.js
CHANGED
|
@@ -69,16 +69,12 @@ export class CriteriaNode {
|
|
|
69
69
|
let joinAlias = qb.getAliasForJoinPath(this.getPath());
|
|
70
70
|
if (!joinAlias && this.parent && [ReferenceKind.MANY_TO_ONE, ReferenceKind.ONE_TO_ONE].includes(this.prop.kind) && this.prop.owner) {
|
|
71
71
|
joinAlias = qb.getAliasForJoinPath(this.parent.getPath());
|
|
72
|
-
return Utils.getPrimaryKeyHash(this.prop.
|
|
72
|
+
return Utils.getPrimaryKeyHash(this.prop.ownColumns.map(col => `${joinAlias ?? qb.alias}.${col}`));
|
|
73
73
|
}
|
|
74
74
|
const alias = joinAlias ?? qb.alias;
|
|
75
75
|
if (this.prop.kind === ReferenceKind.MANY_TO_MANY) {
|
|
76
76
|
return Utils.getPrimaryKeyHash(this.prop.inverseJoinColumns.map(col => `${alias}.${col}`));
|
|
77
77
|
}
|
|
78
|
-
// if we found a matching join, we need to use the target table column names, as we use that alias instead of the root
|
|
79
|
-
if (!joinAlias && this.prop.owner && this.prop.joinColumns.length > 1) {
|
|
80
|
-
return Utils.getPrimaryKeyHash(this.prop.joinColumns.map(col => `${alias}.${col}`));
|
|
81
|
-
}
|
|
82
78
|
return Utils.getPrimaryKeyHash(this.prop.referencedColumnNames.map(col => `${alias}.${col}`));
|
|
83
79
|
}
|
|
84
80
|
getPath(addIndex = false) {
|
package/query/QueryBuilder.d.ts
CHANGED
|
@@ -256,10 +256,6 @@ export declare class QueryBuilder<Entity extends object = AnyEntity, RootAlias e
|
|
|
256
256
|
* Executes the query, returning both array of results and total count query (without offset and limit).
|
|
257
257
|
*/
|
|
258
258
|
getResultAndCount(): Promise<[Entity[], number]>;
|
|
259
|
-
/**
|
|
260
|
-
* Provides promise-like interface so we can await the QB instance.
|
|
261
|
-
*/
|
|
262
|
-
then<TResult1 = any, TResult2 = never>(onfulfilled?: ((value: any) => TResult1 | PromiseLike<TResult1>) | undefined | null, onrejected?: ((reason: any) => TResult2 | PromiseLike<TResult2>) | undefined | null): Promise<Loaded<Entity, Hint>[] | number | QueryResult<Entity>>;
|
|
263
259
|
/**
|
|
264
260
|
* Returns native query builder instance with sub-query aliased with given alias.
|
|
265
261
|
* You can provide `EntityName.propName` as alias, then the field name will be used based on the metadata
|
|
@@ -303,14 +299,12 @@ export declare class QueryBuilder<Entity extends object = AnyEntity, RootAlias e
|
|
|
303
299
|
export interface RunQueryBuilder<Entity extends object> extends Omit<QueryBuilder<Entity, any, any>, 'getResult' | 'getSingleResult' | 'getResultList' | 'where'> {
|
|
304
300
|
where(cond: QBFilterQuery<Entity> | string, params?: keyof typeof GroupOperator | any[], operator?: keyof typeof GroupOperator): this;
|
|
305
301
|
execute<Result = QueryResult<Entity>>(method?: 'all' | 'get' | 'run', mapResults?: boolean): Promise<Result>;
|
|
306
|
-
then<TResult1 = QueryResult<Entity>, TResult2 = never>(onfulfilled?: ((value: QueryResult<Entity>) => TResult1 | PromiseLike<TResult1>) | undefined | null, onrejected?: ((reason: any) => TResult2 | PromiseLike<TResult2>) | undefined | null): Promise<QueryResult<Entity>>;
|
|
307
302
|
}
|
|
308
303
|
export interface SelectQueryBuilder<Entity extends object = AnyEntity, RootAlias extends string = never, Hint extends string = never, Context extends object = never> extends QueryBuilder<Entity, RootAlias, Hint, Context> {
|
|
309
304
|
execute<Result = Entity[]>(method?: 'all' | 'get' | 'run', mapResults?: boolean): Promise<Result>;
|
|
310
305
|
execute<Result = Entity[]>(method: 'all', mapResults?: boolean): Promise<Result>;
|
|
311
306
|
execute<Result = Entity>(method: 'get', mapResults?: boolean): Promise<Result>;
|
|
312
307
|
execute<Result = QueryResult<Entity>>(method: 'run', mapResults?: boolean): Promise<Result>;
|
|
313
|
-
then<TResult1 = Entity[], TResult2 = never>(onfulfilled?: ((value: Loaded<Entity, Hint>[]) => TResult1 | PromiseLike<TResult1>) | undefined | null, onrejected?: ((reason: any) => TResult2 | PromiseLike<TResult2>) | undefined | null): Promise<Loaded<Entity, Hint>[]>;
|
|
314
308
|
}
|
|
315
309
|
export interface CountQueryBuilder<Entity extends object> extends QueryBuilder<Entity, any, any> {
|
|
316
310
|
execute<Result = {
|
|
@@ -325,7 +319,6 @@ export interface CountQueryBuilder<Entity extends object> extends QueryBuilder<E
|
|
|
325
319
|
execute<Result = QueryResult<{
|
|
326
320
|
count: number;
|
|
327
321
|
}>>(method: 'run', mapResults?: boolean): Promise<Result>;
|
|
328
|
-
then<TResult1 = number, TResult2 = never>(onfulfilled?: ((value: number) => TResult1 | PromiseLike<TResult1>) | undefined | null, onrejected?: ((reason: any) => TResult2 | PromiseLike<TResult2>) | undefined | null): Promise<number>;
|
|
329
322
|
}
|
|
330
323
|
export interface InsertQueryBuilder<T extends object> extends RunQueryBuilder<T> {
|
|
331
324
|
}
|
package/query/QueryBuilder.js
CHANGED
|
@@ -753,26 +753,6 @@ export class QueryBuilder {
|
|
|
753
753
|
await this.clone().getCount(),
|
|
754
754
|
];
|
|
755
755
|
}
|
|
756
|
-
/**
|
|
757
|
-
* Provides promise-like interface so we can await the QB instance.
|
|
758
|
-
*/
|
|
759
|
-
then(onfulfilled, onrejected) {
|
|
760
|
-
let type = this.type;
|
|
761
|
-
if (this.flags.has(QueryFlag.UPDATE_SUB_QUERY) || this.flags.has(QueryFlag.DELETE_SUB_QUERY)) {
|
|
762
|
-
type = QueryType.UPDATE;
|
|
763
|
-
}
|
|
764
|
-
switch (type) {
|
|
765
|
-
case QueryType.INSERT:
|
|
766
|
-
case QueryType.UPDATE:
|
|
767
|
-
case QueryType.DELETE:
|
|
768
|
-
case QueryType.UPSERT:
|
|
769
|
-
case QueryType.TRUNCATE:
|
|
770
|
-
return this.execute('run').then(onfulfilled, onrejected);
|
|
771
|
-
case QueryType.COUNT:
|
|
772
|
-
return this.getCount().then(onfulfilled, onrejected);
|
|
773
|
-
case QueryType.SELECT: return this.getResultList().then(onfulfilled, onrejected);
|
|
774
|
-
}
|
|
775
|
-
}
|
|
776
756
|
/**
|
|
777
757
|
* Returns native query builder instance with sub-query aliased with given alias.
|
|
778
758
|
* You can provide `EntityName.propName` as alias, then the field name will be used based on the metadata
|
|
@@ -39,9 +39,6 @@ export class QueryBuilderHelper {
|
|
|
39
39
|
const prop = this.getProperty(f, a);
|
|
40
40
|
const fkIdx2 = prop?.fieldNames.findIndex(name => name === f) ?? -1;
|
|
41
41
|
if (fkIdx2 !== -1) {
|
|
42
|
-
if (prop?.ownColumns && !prop.ownColumns.includes(f)) {
|
|
43
|
-
continue;
|
|
44
|
-
}
|
|
45
42
|
parts.push(this.mapper(a !== this.alias ? `${a}.${prop.fieldNames[fkIdx2]}` : prop.fieldNames[fkIdx2], type, value, alias));
|
|
46
43
|
}
|
|
47
44
|
else if (prop) {
|
|
@@ -62,9 +59,6 @@ export class QueryBuilderHelper {
|
|
|
62
59
|
}
|
|
63
60
|
});
|
|
64
61
|
}
|
|
65
|
-
if (parts.length === 1) {
|
|
66
|
-
return parts[0];
|
|
67
|
-
}
|
|
68
62
|
return raw('(' + parts.map(part => this.platform.quoteIdentifier(part)).join(', ') + ')');
|
|
69
63
|
}
|
|
70
64
|
const rawField = RawQueryFragment.getKnownFragment(field);
|
|
@@ -473,8 +467,8 @@ export class QueryBuilderHelper {
|
|
|
473
467
|
parts.push(sql);
|
|
474
468
|
params.push(...params2);
|
|
475
469
|
}
|
|
476
|
-
else if (
|
|
477
|
-
parts.push(`1 = 0`);
|
|
470
|
+
else if (['$in', '$nin'].includes(op) && Array.isArray(value[op]) && value[op].length === 0) {
|
|
471
|
+
parts.push(`1 = ${op === '$in' ? 0 : 1}`);
|
|
478
472
|
}
|
|
479
473
|
else if (value[op] instanceof RawQueryFragment || value[op] instanceof NativeQueryBuilder) {
|
|
480
474
|
const query = value[op] instanceof NativeQueryBuilder ? value[op].toRaw() : value[op];
|
|
@@ -103,24 +103,14 @@ export class SqlSchemaGenerator extends AbstractSchemaGenerator {
|
|
|
103
103
|
return super.clearDatabase(options);
|
|
104
104
|
}
|
|
105
105
|
await this.execute(this.helper.disableForeignKeysSQL());
|
|
106
|
-
|
|
106
|
+
const schema = options?.schema ?? this.config.get('schema', this.platform.getDefaultSchemaName());
|
|
107
|
+
for (const meta of this.getOrderedMetadata(schema).reverse()) {
|
|
107
108
|
await this.driver.createQueryBuilder(meta.className, this.em?.getTransactionContext(), 'write', false)
|
|
108
|
-
.withSchema(
|
|
109
|
-
.truncate()
|
|
109
|
+
.withSchema(schema)
|
|
110
|
+
.truncate()
|
|
111
|
+
.execute();
|
|
110
112
|
}
|
|
111
113
|
await this.execute(this.helper.enableForeignKeysSQL());
|
|
112
|
-
// const parts: string[] = [this.helper.disableForeignKeysSQL()];
|
|
113
|
-
//
|
|
114
|
-
// for (const meta of this.getOrderedMetadata(options?.schema).reverse()) {
|
|
115
|
-
// const query = this.driver.createQueryBuilder(meta.className, this.em?.getTransactionContext(), 'write', false)
|
|
116
|
-
// .withSchema(options?.schema)
|
|
117
|
-
// .truncate()
|
|
118
|
-
// .getFormattedQuery();
|
|
119
|
-
// parts.push(query);
|
|
120
|
-
// }
|
|
121
|
-
//
|
|
122
|
-
// parts.push(this.helper.enableForeignKeysSQL());
|
|
123
|
-
// await this.execute(parts.join(';\n'));
|
|
124
114
|
this.clearIdentityMap();
|
|
125
115
|
}
|
|
126
116
|
async getDropSchemaSQL(options = {}) {
|