@mikro-orm/knex 6.3.14-dev.7 → 6.3.14-dev.71

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.
@@ -22,8 +22,10 @@ export declare abstract class AbstractSqlConnection extends Connection {
22
22
  * @inheritDoc
23
23
  */
24
24
  checkConnection(): Promise<{
25
- ok: boolean;
26
- reason?: string;
25
+ ok: true;
26
+ } | {
27
+ ok: false;
28
+ reason: string;
27
29
  error?: Error;
28
30
  }>;
29
31
  transactional<T>(cb: (trx: Transaction<Knex.Transaction>) => Promise<T>, options?: {
@@ -109,6 +109,7 @@ class AbstractSqlConnection extends core_1.Connection {
109
109
  queryOrKnex = q.sql;
110
110
  params = q.bindings;
111
111
  }
112
+ queryOrKnex = this.config.get('onQuery')(queryOrKnex, params);
112
113
  const formatted = this.platform.formatQuery(queryOrKnex, params);
113
114
  const sql = this.getSql(queryOrKnex, formatted, loggerContext);
114
115
  return this.executeQuery(sql, async () => {
@@ -570,7 +570,7 @@ class AbstractSqlDriver extends core_1.DatabaseDriver {
570
570
  for (const key of keys) {
571
571
  const prop = meta.properties[key] ?? meta.root.properties[key];
572
572
  prop.fieldNames.forEach((fieldName, fieldNameIdx) => {
573
- if (fields.has(fieldName)) {
573
+ if (fields.has(fieldName) || (prop.ownColumns && !prop.ownColumns.includes(fieldName))) {
574
574
  return;
575
575
  }
576
576
  fields.add(fieldName);
package/index.mjs CHANGED
@@ -199,6 +199,7 @@ export const TimeType = mod.TimeType;
199
199
  export const TinyIntType = mod.TinyIntType;
200
200
  export const TransactionContext = mod.TransactionContext;
201
201
  export const TransactionEventBroadcaster = mod.TransactionEventBroadcaster;
202
+ export const Transactional = mod.Transactional;
202
203
  export const Type = mod.Type;
203
204
  export const Uint8ArrayType = mod.Uint8ArrayType;
204
205
  export const UnderscoreNamingStrategy = mod.UnderscoreNamingStrategy;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mikro-orm/knex",
3
- "version": "6.3.14-dev.7",
3
+ "version": "6.3.14-dev.71",
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",
@@ -66,7 +66,7 @@
66
66
  "@mikro-orm/core": "^6.3.13"
67
67
  },
68
68
  "peerDependencies": {
69
- "@mikro-orm/core": "6.3.14-dev.7",
69
+ "@mikro-orm/core": "6.3.14-dev.71",
70
70
  "better-sqlite3": "*",
71
71
  "libsql": "*",
72
72
  "mariadb": "*"
@@ -156,7 +156,9 @@ export declare class QueryBuilder<Entity extends object = AnyEntity, RootAlias e
156
156
  orWhere(cond: string, params?: any[]): this;
157
157
  orderBy(orderBy: QBQueryOrderMap<Entity> | QBQueryOrderMap<Entity>[]): SelectQueryBuilder<Entity, RootAlias, Hint, Context>;
158
158
  groupBy(fields: EntityKeyOrString<Entity> | readonly EntityKeyOrString<Entity>[]): SelectQueryBuilder<Entity, RootAlias, Hint, Context>;
159
- having(cond?: QBFilterQuery | string, params?: any[]): SelectQueryBuilder<Entity, RootAlias, Hint, Context>;
159
+ having(cond?: QBFilterQuery | string, params?: any[], operator?: keyof typeof GroupOperator): SelectQueryBuilder<Entity, RootAlias, Hint, Context>;
160
+ andHaving(cond?: QBFilterQuery | string, params?: any[]): SelectQueryBuilder<Entity, RootAlias, Hint, Context>;
161
+ orHaving(cond?: QBFilterQuery | string, params?: any[]): SelectQueryBuilder<Entity, RootAlias, Hint, Context>;
160
162
  onConflict(fields?: Field<Entity> | Field<Entity>[]): InsertQueryBuilder<Entity>;
161
163
  ignore(): this;
162
164
  merge(data?: EntityData<Entity> | Field<Entity>[]): this;
@@ -314,7 +314,7 @@ class QueryBuilder {
314
314
  this._cond = { [op]: cond1 };
315
315
  }
316
316
  if (this._onConflict) {
317
- this._onConflict[this._onConflict.length - 1].where = this._cond;
317
+ this._onConflict[this._onConflict.length - 1].where = this.helper.processOnConflictCondition(this._cond, this._schema);
318
318
  this._cond = {};
319
319
  }
320
320
  return this;
@@ -348,14 +348,27 @@ class QueryBuilder {
348
348
  this._groupBy = core_1.Utils.asArray(fields);
349
349
  return this;
350
350
  }
351
- having(cond = {}, params) {
351
+ having(cond = {}, params, operator) {
352
352
  this.ensureNotFinalized();
353
353
  if (core_1.Utils.isString(cond)) {
354
354
  cond = { [(0, core_1.raw)(`(${cond})`, params)]: [] };
355
355
  }
356
- this._having = CriteriaNodeFactory_1.CriteriaNodeFactory.createNode(this.metadata, this.mainAlias.entityName, cond).process(this);
356
+ cond = CriteriaNodeFactory_1.CriteriaNodeFactory.createNode(this.metadata, this.mainAlias.entityName, cond).process(this);
357
+ if (!this._having || !operator) {
358
+ this._having = cond;
359
+ }
360
+ else {
361
+ const cond1 = [this._having, cond];
362
+ this._having = { [operator]: cond1 };
363
+ }
357
364
  return this;
358
365
  }
366
+ andHaving(cond, params) {
367
+ return this.having(cond, params, '$and');
368
+ }
369
+ orHaving(cond, params) {
370
+ return this.having(cond, params, '$or');
371
+ }
359
372
  onConflict(fields = []) {
360
373
  const meta = this.mainAlias.metadata;
361
374
  this.ensureNotFinalized();
@@ -691,7 +704,6 @@ class QueryBuilder {
691
704
  const [propName] = hint.field.split(':', 2);
692
705
  const value = core_1.Reference.unwrapReference(entity[propName]);
693
706
  if (core_1.Utils.isEntity(value)) {
694
- (0, core_1.helper)(value).populated();
695
707
  propagatePopulateHint(value, hint.children ?? []);
696
708
  }
697
709
  else if (core_1.Utils.isCollection(value)) {
@@ -1051,7 +1063,7 @@ class QueryBuilder {
1051
1063
  case enums_1.QueryType.SELECT:
1052
1064
  qb.select(this.prepareFields(this._fields));
1053
1065
  if (this._distinctOn) {
1054
- qb.distinctOn(this._distinctOn);
1066
+ qb.distinctOn(this.prepareFields(this._distinctOn));
1055
1067
  }
1056
1068
  else if (this.flags.has(core_1.QueryFlag.DISTINCT)) {
1057
1069
  qb.distinct();
@@ -1069,6 +1081,7 @@ class QueryBuilder {
1069
1081
  break;
1070
1082
  case enums_1.QueryType.UPDATE:
1071
1083
  qb.update(this._data);
1084
+ this.helper.processJoins(qb, this._joins, joinSchema);
1072
1085
  this.helper.updateVersionProperty(qb, this._data);
1073
1086
  break;
1074
1087
  case enums_1.QueryType.DELETE:
@@ -1337,6 +1350,7 @@ class QueryBuilder {
1337
1350
  subSubQuery.__raw = true; // tag it as there is now way to check via `instanceof`
1338
1351
  const method = this.flags.has(core_1.QueryFlag.UPDATE_SUB_QUERY) ? 'update' : 'delete';
1339
1352
  this._cond = {}; // otherwise we would trigger validation error
1353
+ this._joins = {}; // included in the subquery
1340
1354
  this[method](this._data).where({
1341
1355
  [core_1.Utils.getPrimaryKeyHash(meta.primaryKeys)]: { $in: subSubQuery },
1342
1356
  });
@@ -59,6 +59,7 @@ export declare class QueryBuilderHelper {
59
59
  private fieldName;
60
60
  getProperty(field: string, alias?: string): EntityProperty | undefined;
61
61
  isTableNameAliasRequired(type?: QueryType): boolean;
62
+ processOnConflictCondition(cond: QBFilterQuery, schema?: string): QBFilterQuery;
62
63
  }
63
64
  export interface Alias<T> {
64
65
  aliasName: string;
@@ -471,13 +471,14 @@ class QueryBuilderHelper {
471
471
  if (fields.length > 1 && Array.isArray(value[op])) {
472
472
  const singleTuple = !value[op].every((v) => Array.isArray(v));
473
473
  if (!this.platform.allowsComparingTuples()) {
474
+ const mapped = fields.map(f => this.mapper(f, type));
474
475
  if (op === '$in') {
475
476
  const conds = value[op].map(() => {
476
- return `(${fields.map(field => `${this.platform.quoteIdentifier(field)} = ?`).join(' and ')})`;
477
+ return `(${mapped.map(field => `${this.platform.quoteIdentifier(field)} = ?`).join(' and ')})`;
477
478
  });
478
479
  return void qb[m](this.knex.raw(`(${conds.join(' or ')})`, core_1.Utils.flatten(value[op])));
479
480
  }
480
- return void qb[m](this.knex.raw(`${fields.map(field => `${this.platform.quoteIdentifier(field)} = ?`).join(' and ')}`, core_1.Utils.flatten(value[op])));
481
+ return void qb[m](this.knex.raw(`${mapped.map(field => `${this.platform.quoteIdentifier(field)} = ?`).join(' and ')}`, core_1.Utils.flatten(value[op])));
481
482
  }
482
483
  if (singleTuple) {
483
484
  const tmp = value[op].length === 1 && core_1.Utils.isPlainObject(value[op][0]) ? fields.map(f => value[op][0][f]) : value[op];
@@ -583,7 +584,7 @@ class QueryBuilderHelper {
583
584
  return;
584
585
  }
585
586
  if (type === enums_1.QueryType.UPDATE) {
586
- const returningProps = meta.hydrateProps.filter(prop => core_1.Utils.isRawSql(data[prop.name]));
587
+ const returningProps = meta.hydrateProps.filter(prop => prop.fieldNames && core_1.Utils.isRawSql(data[prop.fieldNames[0]]));
587
588
  if (returningProps.length > 0) {
588
589
  qb.returning(returningProps.flatMap(prop => {
589
590
  if (prop.hasConvertToJSValueSQL) {
@@ -730,5 +731,15 @@ class QueryBuilderHelper {
730
731
  isTableNameAliasRequired(type) {
731
732
  return [enums_1.QueryType.SELECT, enums_1.QueryType.COUNT].includes(type ?? enums_1.QueryType.SELECT);
732
733
  }
734
+ // workaround for https://github.com/knex/knex/issues/5257
735
+ processOnConflictCondition(cond, schema) {
736
+ const meta = this.metadata.get(this.entityName);
737
+ const tableName = this.driver.getTableName(meta, { schema }, false);
738
+ for (const key of Object.keys(cond)) {
739
+ const mapped = this.mapper(key, enums_1.QueryType.INSERT);
740
+ core_1.Utils.renameKey(cond, key, tableName + '.' + mapped);
741
+ }
742
+ return cond;
743
+ }
733
744
  }
734
745
  exports.QueryBuilderHelper = QueryBuilderHelper;
@@ -34,9 +34,11 @@ export declare class DatabaseSchema {
34
34
  hasNamespace(namespace: string): boolean;
35
35
  hasNativeEnum(name: string): boolean;
36
36
  getNamespaces(): string[];
37
- static create(connection: AbstractSqlConnection, platform: AbstractSqlPlatform, config: Configuration, schemaName?: string, schemas?: string[]): Promise<DatabaseSchema>;
37
+ static create(connection: AbstractSqlConnection, platform: AbstractSqlPlatform, config: Configuration, schemaName?: string, schemas?: string[], takeTables?: (string | RegExp)[], skipTables?: (string | RegExp)[]): Promise<DatabaseSchema>;
38
38
  static fromMetadata(metadata: EntityMetadata[], platform: AbstractSqlPlatform, config: Configuration, schemaName?: string): DatabaseSchema;
39
39
  private static getSchemaName;
40
+ private static matchName;
41
+ private static isTableNameAllowed;
40
42
  private static shouldHaveColumn;
41
43
  toJSON(): Dictionary;
42
44
  prune(schema: string | undefined, wildcardSchemaTables: string[]): void;
@@ -59,13 +59,13 @@ class DatabaseSchema {
59
59
  getNamespaces() {
60
60
  return [...this.namespaces];
61
61
  }
62
- static async create(connection, platform, config, schemaName, schemas) {
62
+ static async create(connection, platform, config, schemaName, schemas, takeTables, skipTables) {
63
63
  const schema = new DatabaseSchema(platform, schemaName ?? config.get('schema') ?? platform.getDefaultSchemaName());
64
64
  const allTables = await connection.execute(platform.getSchemaHelper().getListTablesSQL());
65
65
  const parts = config.get('migrations').tableName.split('.');
66
66
  const migrationsTableName = parts[1] ?? parts[0];
67
67
  const migrationsSchemaName = parts.length > 1 ? parts[0] : config.get('schema', platform.getDefaultSchemaName());
68
- const tables = allTables.filter(t => t.table_name !== migrationsTableName || (t.schema_name && t.schema_name !== migrationsSchemaName));
68
+ const tables = allTables.filter(t => this.isTableNameAllowed(t.table_name, takeTables, skipTables) && (t.table_name !== migrationsTableName || (t.schema_name && t.schema_name !== migrationsSchemaName)));
69
69
  await platform.getSchemaHelper().loadInformationSchema(schema, connection, tables, schemas && schemas.length > 0 ? schemas : undefined);
70
70
  return schema;
71
71
  }
@@ -120,6 +120,15 @@ class DatabaseSchema {
120
120
  static getSchemaName(meta, config, schema) {
121
121
  return (meta.schema === '*' ? schema : meta.schema) ?? config.get('schema');
122
122
  }
123
+ static matchName(name, nameToMatch) {
124
+ return typeof nameToMatch === 'string'
125
+ ? name.toLocaleLowerCase() === nameToMatch.toLocaleLowerCase()
126
+ : nameToMatch.test(name);
127
+ }
128
+ static isTableNameAllowed(tableName, takeTables, skipTables) {
129
+ return ((takeTables?.some(tableNameToMatch => this.matchName(tableName, tableNameToMatch)) ?? true) &&
130
+ !(skipTables?.some(tableNameToMatch => this.matchName(tableName, tableNameToMatch)) ?? false));
131
+ }
123
132
  static shouldHaveColumn(meta, prop) {
124
133
  if (prop.persist === false || (prop.columnTypes?.length ?? 0) === 0) {
125
134
  return false;
@@ -358,6 +358,9 @@ class SchemaComparator {
358
358
  if (key1.referencedColumnNames.join('~').toLowerCase() !== key2.referencedColumnNames.join('~').toLowerCase()) {
359
359
  return true;
360
360
  }
361
+ if (key1.constraintName !== key2.constraintName) {
362
+ return true;
363
+ }
361
364
  if (key1.referencedTableName !== key2.referencedTableName) {
362
365
  return true;
363
366
  }