@mikro-orm/knex 7.0.0-dev.83 → 7.0.0-dev.85

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.
@@ -792,7 +792,7 @@ export class AbstractSqlDriver extends DatabaseDriver {
792
792
  }
793
793
  const tableName = `${schema ?? '_'}.${pivotMeta.tableName}`;
794
794
  const persister = groups[tableName] ??= new PivotCollectionPersister(pivotMeta, this, options?.ctx, schema, options?.loggerContext);
795
- persister.enqueueUpdate(coll.property, insertDiff, deleteDiff, pks);
795
+ persister.enqueueUpdate(coll.property, insertDiff, deleteDiff, pks, coll.isInitialized());
796
796
  }
797
797
  for (const persister of Utils.values(groups)) {
798
798
  await this.rethrow(persister.execute());
@@ -1063,7 +1063,7 @@ export class AbstractSqlDriver extends DatabaseDriver {
1063
1063
  if (prop.kind === ReferenceKind.EMBEDDED && !prop.object) {
1064
1064
  return Object.entries(prop.embeddedProps).flatMap(([name, childProp]) => {
1065
1065
  const childFields = explicitFields ? Utils.extractChildElements(explicitFields, prop.name) : [];
1066
- if (childFields.length > 0 && !this.shouldHaveColumn(prop.targetMeta, { ...childProp, name }, [], childFields)) {
1066
+ if (!this.shouldHaveColumn(prop.targetMeta, { ...childProp, name }, [], childFields.length > 0 ? childFields : undefined)) {
1067
1067
  return [];
1068
1068
  }
1069
1069
  return this.mapPropToFieldNames(qb, childProp, tableAlias, childFields);
@@ -6,14 +6,17 @@ export declare class PivotCollectionPersister<Entity extends object> {
6
6
  private readonly ctx?;
7
7
  private readonly schema?;
8
8
  private readonly loggerContext?;
9
- private readonly platform;
10
9
  private readonly inserts;
10
+ private readonly upserts;
11
11
  private readonly deletes;
12
12
  private readonly batchSize;
13
13
  private order;
14
14
  constructor(meta: EntityMetadata<Entity>, driver: AbstractSqlDriver, ctx?: Transaction | undefined, schema?: string | undefined, loggerContext?: Dictionary | undefined);
15
- enqueueUpdate(prop: EntityProperty<Entity>, insertDiff: Primary<Entity>[][], deleteDiff: Primary<Entity>[][] | boolean, pks: Primary<Entity>[]): void;
15
+ enqueueUpdate(prop: EntityProperty<Entity>, insertDiff: Primary<Entity>[][], deleteDiff: Primary<Entity>[][] | boolean, pks: Primary<Entity>[], isInitialized?: boolean): void;
16
16
  private enqueueInsert;
17
+ private enqueueUpsert;
18
+ private createInsertStatement;
17
19
  private enqueueDelete;
20
+ private collectStatements;
18
21
  execute(): Promise<void>;
19
22
  }
@@ -38,8 +38,8 @@ export class PivotCollectionPersister {
38
38
  ctx;
39
39
  schema;
40
40
  loggerContext;
41
- platform;
42
41
  inserts = new Map();
42
+ upserts = new Map();
43
43
  deletes = new Map();
44
44
  batchSize;
45
45
  order = 0;
@@ -49,12 +49,16 @@ export class PivotCollectionPersister {
49
49
  this.ctx = ctx;
50
50
  this.schema = schema;
51
51
  this.loggerContext = loggerContext;
52
- this.platform = this.driver.getPlatform();
53
52
  this.batchSize = this.driver.config.get('batchSize');
54
53
  }
55
- enqueueUpdate(prop, insertDiff, deleteDiff, pks) {
54
+ enqueueUpdate(prop, insertDiff, deleteDiff, pks, isInitialized = true) {
56
55
  if (insertDiff.length) {
57
- this.enqueueInsert(prop, insertDiff, pks);
56
+ if (isInitialized) {
57
+ this.enqueueInsert(prop, insertDiff, pks);
58
+ }
59
+ else {
60
+ this.enqueueUpsert(prop, insertDiff, pks);
61
+ }
58
62
  }
59
63
  if (deleteDiff === true || (Array.isArray(deleteDiff) && deleteDiff.length)) {
60
64
  this.enqueueDelete(prop, deleteDiff, pks);
@@ -62,17 +66,29 @@ export class PivotCollectionPersister {
62
66
  }
63
67
  enqueueInsert(prop, insertDiff, pks) {
64
68
  for (const fks of insertDiff) {
65
- const data = prop.owner ? [...fks, ...pks] : [...pks, ...fks];
66
- const keys = prop.owner
67
- ? [...prop.inverseJoinColumns, ...prop.joinColumns]
68
- : [...prop.joinColumns, ...prop.inverseJoinColumns];
69
- const statement = new InsertStatement(keys, data, this.order++);
69
+ const statement = this.createInsertStatement(prop, fks, pks);
70
70
  const hash = statement.getHash();
71
71
  if (prop.owner || !this.inserts.has(hash)) {
72
72
  this.inserts.set(hash, statement);
73
73
  }
74
74
  }
75
75
  }
76
+ enqueueUpsert(prop, insertDiff, pks) {
77
+ for (const fks of insertDiff) {
78
+ const statement = this.createInsertStatement(prop, fks, pks);
79
+ const hash = statement.getHash();
80
+ if (prop.owner || !this.upserts.has(hash)) {
81
+ this.upserts.set(hash, statement);
82
+ }
83
+ }
84
+ }
85
+ createInsertStatement(prop, fks, pks) {
86
+ const data = prop.owner ? [...fks, ...pks] : [...pks, ...fks];
87
+ const keys = prop.owner
88
+ ? [...prop.inverseJoinColumns, ...prop.joinColumns]
89
+ : [...prop.joinColumns, ...prop.inverseJoinColumns];
90
+ return new InsertStatement(keys, data, this.order++);
91
+ }
76
92
  enqueueDelete(prop, deleteDiff, pks) {
77
93
  if (deleteDiff === true) {
78
94
  const statement = new DeleteStatement(prop.joinColumns, pks);
@@ -88,6 +104,13 @@ export class PivotCollectionPersister {
88
104
  this.deletes.set(statement.getHash(), statement);
89
105
  }
90
106
  }
107
+ collectStatements(statements) {
108
+ const items = [];
109
+ for (const statement of statements.values()) {
110
+ items[statement.order] = statement.getData();
111
+ }
112
+ return items.filter(Boolean);
113
+ }
91
114
  async execute() {
92
115
  if (this.deletes.size > 0) {
93
116
  const deletes = [...this.deletes.values()];
@@ -104,23 +127,33 @@ export class PivotCollectionPersister {
104
127
  });
105
128
  }
106
129
  }
107
- if (this.inserts.size === 0) {
108
- return;
109
- }
110
- let items = [];
111
- for (const insert of this.inserts.values()) {
112
- items[insert.order] = insert.getData();
130
+ if (this.inserts.size > 0) {
131
+ const filtered = this.collectStatements(this.inserts);
132
+ for (let i = 0; i < filtered.length; i += this.batchSize) {
133
+ const chunk = filtered.slice(i, i + this.batchSize);
134
+ await this.driver.nativeInsertMany(this.meta.className, chunk, {
135
+ ctx: this.ctx,
136
+ schema: this.schema,
137
+ convertCustomTypes: false,
138
+ processCollections: false,
139
+ loggerContext: this.loggerContext,
140
+ });
141
+ }
113
142
  }
114
- items = items.filter(i => i);
115
- for (let i = 0; i < items.length; i += this.batchSize) {
116
- const chunk = items.slice(i, i + this.batchSize);
117
- await this.driver.nativeInsertMany(this.meta.className, chunk, {
118
- ctx: this.ctx,
119
- schema: this.schema,
120
- convertCustomTypes: false,
121
- processCollections: false,
122
- loggerContext: this.loggerContext,
123
- });
143
+ if (this.upserts.size > 0) {
144
+ const filtered = this.collectStatements(this.upserts);
145
+ for (let i = 0; i < filtered.length; i += this.batchSize) {
146
+ const chunk = filtered.slice(i, i + this.batchSize);
147
+ await this.driver.nativeUpdateMany(this.meta.className, [], chunk, {
148
+ ctx: this.ctx,
149
+ schema: this.schema,
150
+ convertCustomTypes: false,
151
+ processCollections: false,
152
+ upsert: true,
153
+ onConflictAction: 'ignore',
154
+ loggerContext: this.loggerContext,
155
+ });
156
+ }
124
157
  }
125
158
  }
126
159
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mikro-orm/knex",
3
- "version": "7.0.0-dev.83",
3
+ "version": "7.0.0-dev.85",
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.6.1"
57
+ "@mikro-orm/core": "^6.6.2"
58
58
  },
59
59
  "peerDependencies": {
60
- "@mikro-orm/core": "7.0.0-dev.83"
60
+ "@mikro-orm/core": "7.0.0-dev.85"
61
61
  }
62
62
  }
@@ -1,4 +1,3 @@
1
- import { inspect } from 'node:util';
2
1
  import { type EntityKey, type EntityProperty, type MetadataStorage } from '@mikro-orm/core';
3
2
  import type { ICriteriaNode, ICriteriaNodeProcessOptions, IQueryBuilder } from '../typings.js';
4
3
  /**
@@ -27,6 +26,4 @@ export declare class CriteriaNode<T extends object> implements ICriteriaNode<T>
27
26
  getPivotPath(path: string): string;
28
27
  aliased(field: string, alias?: string): string;
29
28
  isStrict(): boolean;
30
- /** @ignore */
31
- [inspect.custom](): string;
32
29
  }
@@ -1,5 +1,4 @@
1
- import { inspect } from 'node:util';
2
- import { RawQueryFragment, ReferenceKind, Utils, } from '@mikro-orm/core';
1
+ import { RawQueryFragment, ReferenceKind, Utils, inspect, } from '@mikro-orm/core';
3
2
  /**
4
3
  * Helper for working with deeply nested where/orderBy/having criteria. Uses composite pattern to build tree from the payload.
5
4
  * Auto-joins relations and converts payload from { books: { publisher: { name: '...' } } } to { 'publisher_alias.name': '...' }
@@ -112,7 +111,7 @@ export class CriteriaNode {
112
111
  return this.strict;
113
112
  }
114
113
  /** @ignore */
115
- [inspect.custom]() {
114
+ [Symbol.for('nodejs.util.inspect.custom')]() {
116
115
  const o = {};
117
116
  ['entityName', 'key', 'index', 'payload']
118
117
  .filter(k => this[k] !== undefined)
@@ -1,4 +1,3 @@
1
- import { inspect } from 'node:util';
2
1
  import { type AnyEntity, type ConnectionType, type Dictionary, type EntityData, type EntityKey, type EntityManager, type EntityMetadata, type EntityName, type EntityProperty, type ExpandProperty, type FilterOptions, type FlushMode, type GroupOperator, type Loaded, LockMode, type LoggingOptions, type MetadataStorage, type ObjectQuery, PopulateHint, type PopulateOptions, type QBFilterQuery, type QBQueryOrderMap, QueryFlag, type QueryOrderMap, type QueryResult, RawQueryFragment, type RequiredEntityData, type Transaction } from '@mikro-orm/core';
3
2
  import { JoinType, QueryType } from './enums.js';
4
3
  import type { AbstractSqlDriver } from '../AbstractSqlDriver.js';
@@ -354,8 +353,6 @@ export declare class QueryBuilder<Entity extends object = AnyEntity, RootAlias e
354
353
  private createQueryBuilderHelper;
355
354
  private ensureFromClause;
356
355
  private ensureNotFinalized;
357
- /** @ignore */
358
- [inspect.custom](depth?: number): string;
359
356
  }
360
357
  export interface RunQueryBuilder<Entity extends object> extends Omit<QueryBuilder<Entity, any, any>, 'getResult' | 'getSingleResult' | 'getResultList' | 'where'> {
361
358
  where(cond: QBFilterQuery<Entity> | string, params?: keyof typeof GroupOperator | any[], operator?: keyof typeof GroupOperator): this;
@@ -1,5 +1,4 @@
1
- import { inspect } from 'node:util';
2
- import { helper, isRaw, LoadStrategy, LockMode, PopulateHint, QueryFlag, QueryHelper, raw, RawQueryFragment, Reference, ReferenceKind, serialize, Utils, ValidationError, } from '@mikro-orm/core';
1
+ import { helper, isRaw, LoadStrategy, LockMode, PopulateHint, QueryFlag, QueryHelper, raw, RawQueryFragment, Reference, ReferenceKind, serialize, Utils, ValidationError, inspect, } from '@mikro-orm/core';
3
2
  import { JoinType, QueryType } from './enums.js';
4
3
  import { QueryBuilderHelper } from './QueryBuilderHelper.js';
5
4
  import { CriteriaNodeFactory } from './CriteriaNodeFactory.js';
@@ -1529,7 +1528,7 @@ export class QueryBuilder {
1529
1528
  }
1530
1529
  /** @ignore */
1531
1530
  /* v8 ignore next */
1532
- [inspect.custom](depth = 2) {
1531
+ [Symbol.for('nodejs.util.inspect.custom')](depth = 2) {
1533
1532
  const object = { ...this };
1534
1533
  const hidden = ['metadata', 'driver', 'context', 'platform', 'type'];
1535
1534
  Object.keys(object).filter(k => k.startsWith('_')).forEach(k => delete object[k]);
@@ -1,5 +1,4 @@
1
- import { inspect } from 'node:util';
2
- import { ALIAS_REPLACEMENT, ALIAS_REPLACEMENT_RE, ArrayType, isRaw, LockMode, OptimisticLockError, QueryOperator, QueryOrderNumeric, raw, RawQueryFragment, ReferenceKind, Utils, } from '@mikro-orm/core';
1
+ import { ALIAS_REPLACEMENT, ALIAS_REPLACEMENT_RE, ArrayType, isRaw, LockMode, OptimisticLockError, QueryOperator, QueryOrderNumeric, raw, RawQueryFragment, ReferenceKind, Utils, ValidationError, } from '@mikro-orm/core';
3
2
  import { JoinType, QueryType } from './enums.js';
4
3
  import { NativeQueryBuilder } from './NativeQueryBuilder.js';
5
4
  /**
@@ -422,7 +421,7 @@ export class QueryBuilderHelper {
422
421
  const op = Object.keys(QueryOperator).find(op => op in value);
423
422
  /* v8 ignore next */
424
423
  if (!op) {
425
- throw new Error(`Invalid query condition: ${inspect(cond, { depth: 5 })}`);
424
+ throw ValidationError.invalidQueryCondition(cond);
426
425
  }
427
426
  const replacement = this.getOperatorReplacement(op, value);
428
427
  const fields = Utils.splitPrimaryKeys(key);
@@ -1,5 +1,4 @@
1
- import { inspect } from 'node:util';
2
- import { ArrayType, BooleanType, DateTimeType, JsonType, parseJsonSafe, Utils, } from '@mikro-orm/core';
1
+ import { ArrayType, BooleanType, DateTimeType, JsonType, parseJsonSafe, Utils, inspect, } from '@mikro-orm/core';
3
2
  /**
4
3
  * Compares two Schemas and return an instance of SchemaDifference.
5
4
  */