@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.
@@ -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
- // const fields = clause.fields.map(field => this.quote(field));
69
- const conflictColumn = this.quote(clause.fields[0]);
70
- this.parts.push(`on ${this.getTableName()}.${conflictColumn} = tsource.${conflictColumn}`);
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.2",
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.5"
57
+ "@mikro-orm/core": "^6.4.7"
58
58
  },
59
59
  "peerDependencies": {
60
- "@mikro-orm/core": "7.0.0-dev.2"
60
+ "@mikro-orm/core": "7.0.0-dev.4"
61
61
  }
62
62
  }
@@ -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.joinColumns.map(col => `${joinAlias ?? qb.alias}.${col}`));
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) {
@@ -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
  }
@@ -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 (op === '$in' && Array.isArray(value[op]) && value[op].length === 0) {
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
- for (const meta of this.getOrderedMetadata(options?.schema).reverse()) {
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(options?.schema)
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 = {}) {