@mikro-orm/knex 6.1.13-dev.27 → 6.1.13-dev.28

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.
@@ -1,5 +1,5 @@
1
1
  import type { Knex } from 'knex';
2
- import { type AnyEntity, type Collection, type Configuration, type ConnectionType, type Constructor, type CountOptions, DatabaseDriver, type DeleteOptions, type Dictionary, type DriverMethodOptions, type EntityData, type EntityDictionary, type EntityField, EntityManagerType, type EntityMetadata, type EntityName, type EntityProperty, type FilterQuery, type FindOneOptions, type FindOptions, type IDatabaseDriver, type LockOptions, type LoggingOptions, type NativeInsertUpdateManyOptions, type NativeInsertUpdateOptions, type ObjectQuery, type Options, type OrderDefinition, type PopulateOptions, type Primary, type QueryOrderMap, type QueryResult, type Transaction, type UpsertManyOptions, type UpsertOptions } from '@mikro-orm/core';
2
+ import { type AnyEntity, type Collection, type Configuration, type ConnectionType, type Constructor, type CountOptions, DatabaseDriver, type DeleteOptions, type Dictionary, type DriverMethodOptions, type EntityData, type EntityDictionary, type EntityField, EntityManagerType, type EntityMetadata, type EntityName, type EntityProperty, type FilterQuery, type FindOneOptions, type FindOptions, type IDatabaseDriver, type LockOptions, type LoggingOptions, type NativeInsertUpdateManyOptions, type NativeInsertUpdateOptions, type ObjectQuery, type Options, type OrderDefinition, type PopulateOptions, type PopulatePath, type Primary, type QueryOrderMap, type QueryResult, type Transaction, type UpsertManyOptions, type UpsertOptions } from '@mikro-orm/core';
3
3
  import type { AbstractSqlConnection } from './AbstractSqlConnection';
4
4
  import type { AbstractSqlPlatform } from './AbstractSqlPlatform';
5
5
  import { QueryBuilder, QueryType } from './query';
@@ -13,8 +13,8 @@ export declare abstract class AbstractSqlDriver<Connection extends AbstractSqlCo
13
13
  protected constructor(config: Configuration, platform: Platform, connection: Constructor<Connection>, connector: string[]);
14
14
  getPlatform(): Platform;
15
15
  createEntityManager<D extends IDatabaseDriver = IDatabaseDriver>(useContext?: boolean): D[typeof EntityManagerType];
16
- find<T extends object, P extends string = never, F extends string = '*', E extends string = never>(entityName: string, where: FilterQuery<T>, options?: FindOptions<T, P, F, E>): Promise<EntityData<T>[]>;
17
- findOne<T extends object, P extends string = never, F extends string = '*', E extends string = never>(entityName: string, where: FilterQuery<T>, options?: FindOneOptions<T, P, F, E>): Promise<EntityData<T> | null>;
16
+ find<T extends object, P extends string = never, F extends string = PopulatePath.ALL, E extends string = never>(entityName: string, where: FilterQuery<T>, options?: FindOptions<T, P, F, E>): Promise<EntityData<T>[]>;
17
+ findOne<T extends object, P extends string = never, F extends string = PopulatePath.ALL, E extends string = never>(entityName: string, where: FilterQuery<T>, options?: FindOneOptions<T, P, F, E>): Promise<EntityData<T> | null>;
18
18
  protected hasToManyJoins<T extends object>(hint: PopulateOptions<T>, meta: EntityMetadata<T>): boolean;
19
19
  findVirtual<T extends object>(entityName: string, where: FilterQuery<T>, options: FindOptions<T, any, any, any>): Promise<EntityData<T>[]>;
20
20
  countVirtual<T extends object>(entityName: string, where: FilterQuery<T>, options: CountOptions<T, any>): Promise<number>;
@@ -24,7 +24,7 @@ export declare abstract class AbstractSqlDriver<Connection extends AbstractSqlCo
24
24
  private mapJoinedProps;
25
25
  count<T extends object>(entityName: string, where: any, options?: CountOptions<T>): Promise<number>;
26
26
  nativeInsert<T extends object>(entityName: string, data: EntityDictionary<T>, options?: NativeInsertUpdateOptions<T>): Promise<QueryResult<T>>;
27
- nativeInsertMany<T extends object>(entityName: string, data: EntityDictionary<T>[], options?: NativeInsertUpdateManyOptions<T>): Promise<QueryResult<T>>;
27
+ nativeInsertMany<T extends object>(entityName: string, data: EntityDictionary<T>[], options?: NativeInsertUpdateManyOptions<T>, transform?: (sql: string) => string): Promise<QueryResult<T>>;
28
28
  nativeUpdate<T extends object>(entityName: string, where: FilterQuery<T>, data: EntityDictionary<T>, options?: NativeInsertUpdateOptions<T> & UpsertOptions<T>): Promise<QueryResult<T>>;
29
29
  nativeUpdateMany<T extends object>(entityName: string, where: FilterQuery<T>[], data: EntityDictionary<T>[], options?: NativeInsertUpdateManyOptions<T> & UpsertManyOptions<T>): Promise<QueryResult<T>>;
30
30
  nativeDelete<T extends object>(entityName: string, where: FilterQuery<T> | string | any, options?: DeleteOptions<T>): Promise<QueryResult<T>>;
@@ -55,7 +55,7 @@ export declare abstract class AbstractSqlDriver<Connection extends AbstractSqlCo
55
55
  */
56
56
  mapPropToFieldNames<T extends object>(qb: QueryBuilder<T>, prop: EntityProperty<T>, tableAlias?: string): Field<T>[];
57
57
  /** @internal */
58
- createQueryBuilder<T extends object>(entityName: EntityName<T> | QueryBuilder<T>, ctx?: Transaction<Knex.Transaction>, preferredConnectionType?: ConnectionType, convertCustomTypes?: boolean, loggerContext?: LoggingOptions): QueryBuilder<T>;
58
+ createQueryBuilder<T extends object>(entityName: EntityName<T> | QueryBuilder<T>, ctx?: Transaction<Knex.Transaction>, preferredConnectionType?: ConnectionType, convertCustomTypes?: boolean, loggerContext?: LoggingOptions, alias?: string, em?: SqlEntityManager): QueryBuilder<T>;
59
59
  protected resolveConnectionType(args: {
60
60
  ctx?: Transaction<Knex.Transaction>;
61
61
  connectionType?: ConnectionType;
@@ -321,7 +321,7 @@ class AbstractSqlDriver extends core_1.DatabaseDriver {
321
321
  await this.processManyToMany(meta, pk, collections, false, options);
322
322
  return res;
323
323
  }
324
- async nativeInsertMany(entityName, data, options = {}) {
324
+ async nativeInsertMany(entityName, data, options = {}, transform) {
325
325
  options.processCollections ??= true;
326
326
  options.convertCustomTypes ??= true;
327
327
  const meta = this.metadata.find(entityName)?.root;
@@ -340,6 +340,13 @@ class AbstractSqlDriver extends core_1.DatabaseDriver {
340
340
  const tableName = meta ? this.getTableName(meta, options) : this.platform.quoteIdentifier(entityName);
341
341
  let sql = `insert into ${tableName} `;
342
342
  sql += fields.length > 0 ? '(' + fields.map(k => this.platform.quoteIdentifier(k)).join(', ') + ')' : `(${this.platform.quoteIdentifier(pks[0])})`;
343
+ if (meta && this.platform.usesOutputStatement()) {
344
+ const returningProps = meta.props
345
+ .filter(prop => prop.persist !== false && prop.defaultRaw || prop.autoincrement || prop.generated)
346
+ .filter(prop => !(prop.name in data[0]) || core_1.Utils.isRawSql(data[0][prop.name]));
347
+ const returningFields = core_1.Utils.flatten(returningProps.map(prop => prop.fieldNames));
348
+ sql += returningFields.length > 0 ? ` output ${returningFields.map(field => 'inserted.' + this.platform.quoteIdentifier(field)).join(', ')}` : '';
349
+ }
343
350
  if (fields.length > 0 || this.platform.usesDefaultKeyword()) {
344
351
  sql += ' values ';
345
352
  }
@@ -406,6 +413,9 @@ class AbstractSqlDriver extends core_1.DatabaseDriver {
406
413
  /* istanbul ignore next */
407
414
  sql += returningFields.length > 0 ? ` returning ${returningFields.map(field => this.platform.quoteIdentifier(field)).join(', ')}` : '';
408
415
  }
416
+ if (transform) {
417
+ sql = transform(sql);
418
+ }
409
419
  const res = await this.execute(sql, params, 'run', options.ctx);
410
420
  let pk;
411
421
  /* istanbul ignore next */
@@ -949,9 +959,10 @@ class AbstractSqlDriver extends core_1.DatabaseDriver {
949
959
  return prop.fieldNames;
950
960
  }
951
961
  /** @internal */
952
- createQueryBuilder(entityName, ctx, preferredConnectionType, convertCustomTypes, loggerContext) {
953
- const connectionType = this.resolveConnectionType({ ctx, connectionType: preferredConnectionType });
954
- const qb = new query_1.QueryBuilder(entityName, this.metadata, this, ctx, undefined, connectionType, undefined, loggerContext);
962
+ createQueryBuilder(entityName, ctx, preferredConnectionType, convertCustomTypes, loggerContext, alias, em) {
963
+ // do not compute the connectionType if EM is provided as it will be computed from it in the QB later on
964
+ const connectionType = em ? preferredConnectionType : this.resolveConnectionType({ ctx, connectionType: preferredConnectionType });
965
+ const qb = new query_1.QueryBuilder(entityName, this.metadata, this, ctx, alias, connectionType, em, loggerContext);
955
966
  if (!convertCustomTypes) {
956
967
  qb.unsetFlag(core_1.QueryFlag.CONVERT_CUSTOM_TYPES);
957
968
  }
@@ -4,6 +4,10 @@ export declare const MonkeyPatchable: {
4
4
  MySqlDialect: any;
5
5
  MySqlColumnCompiler: any;
6
6
  MySqlQueryCompiler: any;
7
+ MsSqlColumnCompiler: any;
8
+ MsSqlTableCompiler: any;
9
+ MsSqlQueryCompiler: any;
10
+ MsSqlDialect: any;
7
11
  PostgresDialectTableCompiler: any;
8
12
  Sqlite3Dialect: any;
9
13
  Sqlite3DialectTableCompiler: any;
@@ -15,6 +15,14 @@ const mysql_columncompiler_1 = __importDefault(require("knex/lib/dialects/mysql/
15
15
  // @ts-ignore
16
16
  const mysql_querycompiler_1 = __importDefault(require("knex/lib/dialects/mysql/query/mysql-querycompiler"));
17
17
  // @ts-ignore
18
+ const mssql_columncompiler_1 = __importDefault(require("knex/lib/dialects/mssql/schema/mssql-columncompiler"));
19
+ // @ts-ignore
20
+ const mssql_tablecompiler_1 = __importDefault(require("knex/lib/dialects/mssql/schema/mssql-tablecompiler"));
21
+ // @ts-ignore
22
+ const mssql_querycompiler_1 = __importDefault(require("knex/lib/dialects/mssql/query/mssql-querycompiler"));
23
+ // @ts-ignore
24
+ const mssql_1 = __importDefault(require("knex/lib/dialects/mssql"));
25
+ // @ts-ignore
18
26
  const pg_tablecompiler_1 = __importDefault(require("knex/lib/dialects/postgres/schema/pg-tablecompiler"));
19
27
  // @ts-ignore
20
28
  const sqlite3_1 = __importDefault(require("knex/lib/dialects/sqlite3"));
@@ -34,6 +42,10 @@ exports.MonkeyPatchable = {
34
42
  MySqlDialect: mysql_1.default,
35
43
  MySqlColumnCompiler: mysql_columncompiler_1.default,
36
44
  MySqlQueryCompiler: mysql_querycompiler_1.default,
45
+ MsSqlColumnCompiler: mssql_columncompiler_1.default,
46
+ MsSqlTableCompiler: mssql_tablecompiler_1.default,
47
+ MsSqlQueryCompiler: mssql_querycompiler_1.default,
48
+ MsSqlDialect: mssql_1.default,
37
49
  PostgresDialectTableCompiler: pg_tablecompiler_1.default,
38
50
  Sqlite3Dialect: sqlite3_1.default,
39
51
  Sqlite3DialectTableCompiler: sqlite_tablecompiler_1.default,
package/README.md CHANGED
@@ -179,6 +179,7 @@ yarn add @mikro-orm/core @mikro-orm/mongodb # for mongo
179
179
  yarn add @mikro-orm/core @mikro-orm/mysql # for mysql/mariadb
180
180
  yarn add @mikro-orm/core @mikro-orm/mariadb # for mysql/mariadb
181
181
  yarn add @mikro-orm/core @mikro-orm/postgresql # for postgresql
182
+ yarn add @mikro-orm/core @mikro-orm/mssql # for mssql
182
183
  yarn add @mikro-orm/core @mikro-orm/sqlite # for sqlite
183
184
  yarn add @mikro-orm/core @mikro-orm/better-sqlite # for better-sqlite
184
185
  yarn add @mikro-orm/core @mikro-orm/libsql # for libsql
@@ -191,6 +192,7 @@ npm i -s @mikro-orm/core @mikro-orm/mongodb # for mongo
191
192
  npm i -s @mikro-orm/core @mikro-orm/mysql # for mysql/mariadb
192
193
  npm i -s @mikro-orm/core @mikro-orm/mariadb # for mysql/mariadb
193
194
  npm i -s @mikro-orm/core @mikro-orm/postgresql # for postgresql
195
+ npm i -s @mikro-orm/core @mikro-orm/mssql # for mssql
194
196
  npm i -s @mikro-orm/core @mikro-orm/sqlite # for sqlite
195
197
  npm i -s @mikro-orm/core @mikro-orm/better-sqlite # for better-sqlite
196
198
  npm i -s @mikro-orm/core @mikro-orm/libsql # for libsql
@@ -1,7 +1,7 @@
1
1
  import type { Knex } from 'knex';
2
2
  import { EntityManager, type AnyEntity, type ConnectionType, type EntityData, type EntityName, type EntityRepository, type GetRepository, type QueryResult, type FilterQuery, type LoggingOptions } from '@mikro-orm/core';
3
3
  import type { AbstractSqlDriver } from './AbstractSqlDriver';
4
- import { QueryBuilder } from './query';
4
+ import type { QueryBuilder } from './query';
5
5
  import type { SqlEntityRepository } from './SqlEntityRepository';
6
6
  /**
7
7
  * @inheritDoc
@@ -2,7 +2,6 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.SqlEntityManager = void 0;
4
4
  const core_1 = require("@mikro-orm/core");
5
- const query_1 = require("./query");
6
5
  /**
7
6
  * @inheritDoc
8
7
  */
@@ -12,7 +11,7 @@ class SqlEntityManager extends core_1.EntityManager {
12
11
  */
13
12
  createQueryBuilder(entityName, alias, type, loggerContext) {
14
13
  const context = this.getContext(false);
15
- return new query_1.QueryBuilder(entityName, this.getMetadata(), this.getDriver(), context.getTransactionContext(), alias, type, context, loggerContext ?? context.loggerContext);
14
+ return this.driver.createQueryBuilder(entityName, context.getTransactionContext(), type, true, loggerContext ?? context.loggerContext, alias, this);
16
15
  }
17
16
  /**
18
17
  * Shortcut for `createQueryBuilder()`
@@ -1 +1,2 @@
1
+ export * from './mssql';
1
2
  export * from './sqlite';
package/dialects/index.js CHANGED
@@ -14,4 +14,5 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
14
  for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
15
  };
16
16
  Object.defineProperty(exports, "__esModule", { value: true });
17
+ __exportStar(require("./mssql"), exports);
17
18
  __exportStar(require("./sqlite"), exports);
@@ -0,0 +1,4 @@
1
+ import { MonkeyPatchable } from '../../MonkeyPatchable';
2
+ export declare class MsSqlColumnCompiler extends MonkeyPatchable.MsSqlColumnCompiler {
3
+ enu(this: any, allowed: unknown[]): string;
4
+ }
@@ -0,0 +1,10 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.MsSqlColumnCompiler = void 0;
4
+ const MonkeyPatchable_1 = require("../../MonkeyPatchable");
5
+ class MsSqlColumnCompiler extends MonkeyPatchable_1.MonkeyPatchable.MsSqlColumnCompiler {
6
+ enu(allowed) {
7
+ return `nvarchar(100) check (${this.formatter.wrap(this.args[0])} in ('${(allowed.join("', '"))}'))`;
8
+ }
9
+ }
10
+ exports.MsSqlColumnCompiler = MsSqlColumnCompiler;
@@ -0,0 +1,6 @@
1
+ import { MonkeyPatchable } from '../../MonkeyPatchable';
2
+ export declare class MsSqlKnexDialect extends MonkeyPatchable.MsSqlDialect {
3
+ tableCompiler(): any;
4
+ columnCompiler(): any;
5
+ queryCompiler(): any;
6
+ }
@@ -0,0 +1,22 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.MsSqlKnexDialect = void 0;
4
+ const MonkeyPatchable_1 = require("../../MonkeyPatchable");
5
+ const MsSqlTableCompiler_1 = require("./MsSqlTableCompiler");
6
+ const MsSqlColumnCompiler_1 = require("./MsSqlColumnCompiler");
7
+ const MsSqlQueryCompiler_1 = require("./MsSqlQueryCompiler");
8
+ class MsSqlKnexDialect extends MonkeyPatchable_1.MonkeyPatchable.MsSqlDialect {
9
+ tableCompiler() {
10
+ // eslint-disable-next-line prefer-rest-params
11
+ return new MsSqlTableCompiler_1.MsSqlTableCompiler(this, ...arguments);
12
+ }
13
+ columnCompiler() {
14
+ // eslint-disable-next-line prefer-rest-params
15
+ return new MsSqlColumnCompiler_1.MsSqlColumnCompiler(this, ...arguments);
16
+ }
17
+ queryCompiler() {
18
+ // eslint-disable-next-line prefer-rest-params
19
+ return new MsSqlQueryCompiler_1.MsSqlQueryCompiler(this, ...arguments);
20
+ }
21
+ }
22
+ exports.MsSqlKnexDialect = MsSqlKnexDialect;
@@ -0,0 +1,12 @@
1
+ import { MonkeyPatchable } from '../../MonkeyPatchable';
2
+ export declare class MsSqlQueryCompiler extends MonkeyPatchable.MsSqlQueryCompiler {
3
+ constructor(client: any, builder: any, formatter: any);
4
+ insert(this: any): any;
5
+ _mergeAnd(this: any): string;
6
+ _mergeWhenMatched(this: any, columns: any, updates: any): string;
7
+ _mergeWhenNotMatched(this: any, columns: any): string;
8
+ _getParameters(this: any, params: any): any;
9
+ _mergeInsertIsEmpty(this: any, insert: any): boolean;
10
+ _mergeOn(this: any, conflict: any): string;
11
+ _insertWithMerge(this: any): string;
12
+ }
@@ -0,0 +1,94 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.MsSqlQueryCompiler = void 0;
4
+ /* istanbul ignore file */
5
+ const MonkeyPatchable_1 = require("../../MonkeyPatchable");
6
+ const core_1 = require("@mikro-orm/core");
7
+ // upsert support from https://github.com/knex/knex/pull/6050
8
+ class MsSqlQueryCompiler extends MonkeyPatchable_1.MonkeyPatchable.MsSqlQueryCompiler {
9
+ constructor(client, builder, formatter) {
10
+ const onConflict = builder._single.onConflict;
11
+ delete builder._single.onConflict;
12
+ super(client, builder, formatter);
13
+ this.single.onConflict = onConflict;
14
+ }
15
+ // Compiles an "insert" query, allowing for multiple
16
+ // inserts using a single query statement.
17
+ insert() {
18
+ if (this.single.onConflict) {
19
+ return this._insertWithMerge();
20
+ }
21
+ return super.insert();
22
+ }
23
+ _mergeAnd() {
24
+ const wheres = this.where();
25
+ if (!wheres) {
26
+ return '';
27
+ }
28
+ return `and ${wheres.slice(6)} `;
29
+ }
30
+ _mergeWhenMatched(columns, updates) {
31
+ let columnsData = [];
32
+ if (!updates || Array.isArray(updates)) {
33
+ columnsData = columns
34
+ .map((column) => `${this.formatter.columnize(column)}=tsource.${this.formatter.columnize(column)}`)
35
+ .join(', ');
36
+ }
37
+ if (typeof updates === 'string') {
38
+ columnsData = `${this.formatter.columnize(updates)}=tsource.${this.formatter.columnize(updates)}`;
39
+ }
40
+ if (!Array.isArray(updates) && typeof updates === 'object') {
41
+ columnsData = Object.entries(updates)
42
+ .map(([key, value]) => `${this.tableName}.${this.formatter.columnize(key)}=(${this._getParameters([value])})`);
43
+ }
44
+ const sql = ` when matched ${this._mergeAnd()}then update set ${columnsData}`;
45
+ return sql;
46
+ }
47
+ _mergeWhenNotMatched(columns) {
48
+ const destinationColumns = this.formatter.columnize(columns);
49
+ const sourceColumns = this.formatter.columnizeWithPrefix('tsource.', columns);
50
+ const sql = ` when not matched then insert (${destinationColumns}) values (${sourceColumns})`;
51
+ return sql;
52
+ }
53
+ _getParameters(params) {
54
+ const sql = this.client.parameterize(params, this.client.valueForUndefined, this.builder, this.bindingsHolder);
55
+ return sql;
56
+ }
57
+ _mergeInsertIsEmpty(insert) {
58
+ return (Array.isArray(insert) && insert.length === 0)
59
+ || (typeof insert === 'object' && core_1.Utils.isEmpty(insert));
60
+ }
61
+ _mergeOn(conflict) {
62
+ let sql = 'on 1=1';
63
+ if (Array.isArray(conflict)) {
64
+ const conflictColumn = this.formatter.columnize(conflict[0]);
65
+ sql = `on ${this.tableName}.${conflictColumn} = tsource.${conflictColumn}`;
66
+ }
67
+ return sql;
68
+ }
69
+ _insertWithMerge() {
70
+ const { insert = [], onConflict, ignore, merge, returning, options = {} } = this.single;
71
+ if (this._mergeInsertIsEmpty(insert)) {
72
+ return '';
73
+ }
74
+ const insertData = this._prepInsert(insert);
75
+ const insertParameters = insertData.values.map((value) => `(${this._getParameters(value)})`).join(', ');
76
+ const sourceColumns = this.formatter.columnize(insertData.columns);
77
+ const returningSql = returning
78
+ ? ` ${this._returning('insert', returning, options.includeTriggerModifications)}`
79
+ : '';
80
+ let sql = `merge into ${this.tableName} using (values ${insertParameters}) as tsource(${sourceColumns}) `;
81
+ sql += this._mergeOn(onConflict);
82
+ sql += this._mergeWhenNotMatched(insertData.columns);
83
+ if (!ignore) {
84
+ sql += this._mergeWhenMatched(insertData.columns, merge.updates);
85
+ }
86
+ sql += returningSql;
87
+ if (options.includeTriggerModifications) {
88
+ sql = this._buildTempTable(returning) + sql + this._buildReturningSelect(returning);
89
+ }
90
+ sql = this.with() + sql + ';';
91
+ return sql;
92
+ }
93
+ }
94
+ exports.MsSqlQueryCompiler = MsSqlQueryCompiler;
@@ -0,0 +1,9 @@
1
+ import { MonkeyPatchable } from '../../MonkeyPatchable';
2
+ export declare class MsSqlTableCompiler extends MonkeyPatchable.MsSqlTableCompiler {
3
+ lowerCase: boolean;
4
+ addColumnsPrefix: string;
5
+ dropColumnPrefix: string;
6
+ alterColumnPrefix: string;
7
+ alterColumns(this: any, columns: any, colBuilder: any): void;
8
+ dropForeign(this: any, columns: any, constraintName: any): void;
9
+ }
@@ -0,0 +1,39 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.MsSqlTableCompiler = void 0;
4
+ const MonkeyPatchable_1 = require("../../MonkeyPatchable");
5
+ class MsSqlTableCompiler extends MonkeyPatchable_1.MonkeyPatchable.MsSqlTableCompiler {
6
+ lowerCase = true;
7
+ addColumnsPrefix = 'add ';
8
+ dropColumnPrefix = 'drop column ';
9
+ alterColumnPrefix = 'alter column ';
10
+ alterColumns(columns, colBuilder) {
11
+ for (let i = 0, l = colBuilder.length; i < l; i++) {
12
+ const builder = colBuilder[i];
13
+ if (builder.modified.defaultTo) {
14
+ const schema = this.schemaNameRaw || 'dbo';
15
+ const baseQuery = `declare @constraint${i} varchar(100) = (select default_constraints.name from sys.all_columns`
16
+ + ' join sys.tables on all_columns.object_id = tables.object_id'
17
+ + ' join sys.schemas on tables.schema_id = schemas.schema_id'
18
+ + ' join sys.default_constraints on all_columns.default_object_id = default_constraints.object_id'
19
+ + ` where schemas.name = '${schema}' and tables.name = '${this.tableNameRaw}' and all_columns.name = '${builder.getColumnName()}')`
20
+ + ` if @constraint${i} is not null exec('alter table ${this.tableNameRaw} drop constraint ' + @constraint${i})`;
21
+ this.pushQuery(baseQuery);
22
+ }
23
+ }
24
+ // in SQL server only one column can be altered at a time
25
+ columns.sql.forEach((sql) => {
26
+ this.pushQuery({
27
+ sql: `alter table ${this.tableName()} ${this.alterColumnPrefix.toLowerCase()}${sql}`,
28
+ bindings: columns.bindings,
29
+ });
30
+ });
31
+ }
32
+ dropForeign(columns, constraintName) {
33
+ constraintName = constraintName
34
+ ? this.formatter.wrap(constraintName)
35
+ : this._indexCommand('foreign', this.tableNameRaw, columns);
36
+ this.pushQuery(`alter table ${this.tableName()} drop constraint ${constraintName}`);
37
+ }
38
+ }
39
+ exports.MsSqlTableCompiler = MsSqlTableCompiler;
@@ -0,0 +1 @@
1
+ export * from './MsSqlKnexDialect';
@@ -0,0 +1,17 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
+ };
16
+ Object.defineProperty(exports, "__esModule", { value: true });
17
+ __exportStar(require("./MsSqlKnexDialect"), exports);
package/index.mjs CHANGED
@@ -128,6 +128,7 @@ export const MetadataValidator = mod.MetadataValidator;
128
128
  export const MikroORM = mod.MikroORM;
129
129
  export const MongoNamingStrategy = mod.MongoNamingStrategy;
130
130
  export const MonkeyPatchable = mod.MonkeyPatchable;
131
+ export const MsSqlKnexDialect = mod.MsSqlKnexDialect;
131
132
  export const NodeState = mod.NodeState;
132
133
  export const NonUniqueFieldNameException = mod.NonUniqueFieldNameException;
133
134
  export const NotFoundError = mod.NotFoundError;
@@ -146,6 +147,7 @@ export const OptionalProps = mod.OptionalProps;
146
147
  export const PlainObject = mod.PlainObject;
147
148
  export const Platform = mod.Platform;
148
149
  export const PopulateHint = mod.PopulateHint;
150
+ export const PopulatePath = mod.PopulatePath;
149
151
  export const PrimaryKey = mod.PrimaryKey;
150
152
  export const PrimaryKeyProp = mod.PrimaryKeyProp;
151
153
  export const Property = mod.Property;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mikro-orm/knex",
3
- "version": "6.1.13-dev.27",
3
+ "version": "6.1.13-dev.28",
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,6 +66,6 @@
66
66
  "@mikro-orm/core": "^6.1.12"
67
67
  },
68
68
  "peerDependencies": {
69
- "@mikro-orm/core": "6.1.13-dev.27"
69
+ "@mikro-orm/core": "6.1.13-dev.28"
70
70
  }
71
71
  }
@@ -1,7 +1,7 @@
1
1
  /// <reference types="node" />
2
2
  import { inspect } from 'util';
3
3
  import type { Knex } from 'knex';
4
- import { type AnyEntity, type ConnectionType, type Dictionary, type EntityData, type EntityName, type EntityProperty, type FlushMode, type GroupOperator, LockMode, type LoggingOptions, type MetadataStorage, type ObjectQuery, PopulateHint, type PopulateOptions, type QBFilterQuery, type QBQueryOrderMap, QueryFlag, type QueryResult, type RequiredEntityData } from '@mikro-orm/core';
4
+ import { type AnyEntity, type ConnectionType, type Dictionary, type EntityData, type EntityName, type EntityProperty, type FlushMode, type GroupOperator, LockMode, type LoggingOptions, type MetadataStorage, type ObjectQuery, PopulateHint, type PopulateOptions, type QBFilterQuery, type QBQueryOrderMap, QueryFlag, type QueryOrderMap, type QueryResult, type RequiredEntityData } from '@mikro-orm/core';
5
5
  import { JoinType, QueryType } from './enums';
6
6
  import type { AbstractSqlDriver } from '../AbstractSqlDriver';
7
7
  import { type Alias, QueryBuilderHelper } from './QueryBuilderHelper';
@@ -32,13 +32,12 @@ export interface ExecuteOptions {
32
32
  * ```
33
33
  */
34
34
  export declare class QueryBuilder<T extends object = AnyEntity> {
35
- #private;
36
- private readonly metadata;
37
- private readonly driver;
38
- private readonly context?;
39
- private connectionType?;
40
- private readonly em?;
41
- private loggerContext?;
35
+ protected readonly metadata: MetadataStorage;
36
+ protected readonly driver: AbstractSqlDriver;
37
+ protected readonly context?: Knex.Transaction<any, any[]> | undefined;
38
+ protected connectionType?: ConnectionType | undefined;
39
+ protected em?: SqlEntityManager<AbstractSqlDriver<import("..").AbstractSqlConnection, AbstractSqlPlatform>> | undefined;
40
+ protected loggerContext?: (LoggingOptions & Dictionary) | undefined;
42
41
  get mainAlias(): Alias<T>;
43
42
  get alias(): string;
44
43
  get helper(): QueryBuilderHelper;
@@ -56,36 +55,47 @@ export declare class QueryBuilder<T extends object = AnyEntity> {
56
55
  _populateMap: Dictionary<string>;
57
56
  /** @internal */
58
57
  readonly rawFragments: Set<string>;
59
- private aliasCounter;
60
- private flags;
61
- private finalized;
62
- private _joins;
63
- private _explicitAlias;
64
- private _schema?;
65
- private _cond;
66
- private _data;
67
- private _orderBy;
68
- private _groupBy;
69
- private _having;
70
- private _returning?;
71
- private _onConflict?;
72
- private _limit?;
73
- private _offset?;
74
- private _distinctOn?;
75
- private _joinedProps;
76
- private _cache?;
77
- private _indexHint?;
78
- private _comments;
79
- private _hintComments;
80
- private flushMode?;
81
- private lockMode?;
82
- private lockTables?;
83
- private subQueries;
84
- private _mainAlias?;
85
- private _aliases;
86
- private _helper?;
87
- private readonly platform;
88
- private readonly knex;
58
+ protected aliasCounter: number;
59
+ protected flags: Set<QueryFlag>;
60
+ protected finalized: boolean;
61
+ protected _joins: Dictionary<JoinOptions>;
62
+ protected _explicitAlias: boolean;
63
+ protected _schema?: string;
64
+ protected _cond: Dictionary;
65
+ protected _data: Dictionary;
66
+ protected _orderBy: QueryOrderMap<T>[];
67
+ protected _groupBy: Field<T>[];
68
+ protected _having: Dictionary;
69
+ protected _returning?: Field<T>[];
70
+ protected _onConflict?: {
71
+ fields: string[];
72
+ ignore?: boolean;
73
+ merge?: EntityData<T> | Field<T>[];
74
+ where?: QBFilterQuery<T>;
75
+ }[];
76
+ protected _limit?: number;
77
+ protected _offset?: number;
78
+ protected _distinctOn?: string[];
79
+ protected _joinedProps: Map<string, PopulateOptions<any>>;
80
+ protected _cache?: boolean | number | [string, number];
81
+ protected _indexHint?: string;
82
+ protected _comments: string[];
83
+ protected _hintComments: string[];
84
+ protected flushMode?: FlushMode;
85
+ protected lockMode?: LockMode;
86
+ protected lockTables?: string[];
87
+ protected subQueries: Dictionary<string>;
88
+ protected _mainAlias?: Alias<T>;
89
+ protected _aliases: Dictionary<Alias<any>>;
90
+ protected _helper?: QueryBuilderHelper;
91
+ protected _query?: {
92
+ sql?: string;
93
+ _sql?: Knex.Sql;
94
+ params?: readonly unknown[];
95
+ qb: Knex.QueryBuilder<T>;
96
+ };
97
+ protected readonly platform: AbstractSqlPlatform;
98
+ protected readonly knex: Knex;
89
99
  /**
90
100
  * @internal
91
101
  */
@@ -85,6 +85,7 @@ class QueryBuilder {
85
85
  _mainAlias;
86
86
  _aliases = {};
87
87
  _helper;
88
+ _query;
88
89
  platform;
89
90
  knex;
90
91
  /**
@@ -459,10 +460,10 @@ class QueryBuilder {
459
460
  return this;
460
461
  }
461
462
  getKnexQuery(processVirtualEntity = true) {
462
- if (this.#query) {
463
- return this.#query.qb;
463
+ if (this._query?.qb) {
464
+ return this._query.qb;
464
465
  }
465
- this.#query = {};
466
+ this._query = {};
466
467
  this.finalize();
467
468
  const qb = this.getQueryBase(processVirtualEntity);
468
469
  const type = this.type ?? enums_1.QueryType.SELECT;
@@ -484,14 +485,14 @@ class QueryBuilder {
484
485
  core_1.Utils.runIfNotEmpty(() => this._hintComments.forEach(comment => qb.hintComment(comment)), this._hintComments);
485
486
  core_1.Utils.runIfNotEmpty(() => this.helper.appendOnConflictClause(type, this._onConflict, qb), this._onConflict);
486
487
  if (this.type === enums_1.QueryType.TRUNCATE && this.platform.usesCascadeStatement()) {
487
- return this.#query.qb = this.knex.raw(qb.toSQL().toNative().sql + ' cascade');
488
+ return this._query.qb = this.knex.raw(qb.toSQL().toNative().sql + ' cascade');
488
489
  }
489
490
  if (this.lockMode) {
490
491
  this.helper.getLockSQL(qb, this.lockMode, this.lockTables);
491
492
  }
492
493
  this.helper.finalize(type, qb, this.mainAlias.metadata, this._data, this._returning);
493
494
  this.clearRawFragmentsCache();
494
- return this.#query.qb = qb;
495
+ return this._query.qb = qb;
495
496
  }
496
497
  /**
497
498
  * @internal
@@ -506,17 +507,16 @@ class QueryBuilder {
506
507
  getQuery() {
507
508
  return this.toQuery().sql;
508
509
  }
509
- #query;
510
510
  toQuery() {
511
- if (this.#query?.sql) {
512
- return { sql: this.#query.sql, _sql: this.#query._sql, params: this.#query.params };
511
+ if (this._query?.sql) {
512
+ return { sql: this._query.sql, _sql: this._query._sql, params: this._query.params };
513
513
  }
514
514
  const sql = this.getKnexQuery().toSQL();
515
515
  const query = sql.toNative();
516
- this.#query.sql = query.sql;
517
- this.#query._sql = sql;
518
- this.#query.params = query.bindings ?? [];
519
- return { sql: this.#query.sql, _sql: this.#query._sql, params: this.#query.params };
516
+ this._query.sql = query.sql;
517
+ this._query._sql = sql;
518
+ this._query.params = query.bindings ?? [];
519
+ return { sql: this._query.sql, _sql: this._query._sql, params: this._query.params };
520
520
  }
521
521
  /**
522
522
  * Returns the list of all parameters for this query.
@@ -518,7 +518,8 @@ class QueryBuilderHelper {
518
518
  return ret;
519
519
  }
520
520
  finalize(type, qb, meta, data, returning) {
521
- if (!meta || !data || !this.platform.usesReturningStatement()) {
521
+ const usesReturningStatement = this.platform.usesReturningStatement() || this.platform.usesOutputStatement();
522
+ if (!meta || !data || !usesReturningStatement) {
522
523
  return;
523
524
  }
524
525
  // always respect explicit returning hint
@@ -79,6 +79,9 @@ class DatabaseTable {
79
79
  prop.length ??= this.platform.getDefaultDateTimeLength();
80
80
  }
81
81
  }
82
+ if (prop.length == null && prop.columnTypes[idx]) {
83
+ prop.length = this.platform.getSchemaHelper().inferLengthFromColumnType(prop.columnTypes[idx]);
84
+ }
82
85
  const primary = !meta.compositePK && !!prop.primary && prop.kind === core_1.ReferenceKind.SCALAR && this.platform.isNumericColumn(mappedType);
83
86
  this.columns[field] = {
84
87
  name: prop.fieldNames[idx],
@@ -120,9 +123,19 @@ class DatabaseTable {
120
123
  if (prop.deleteRule || cascade || prop.nullable) {
121
124
  this.foreignKeys[constraintName].deleteRule = prop.deleteRule || (cascade ? 'cascade' : 'set null');
122
125
  }
123
- if (prop.updateRule || prop.cascade.includes(core_1.Cascade.PERSIST) || prop.cascade.includes(core_1.Cascade.ALL)) {
126
+ if (prop.updateRule) {
124
127
  this.foreignKeys[constraintName].updateRule = prop.updateRule || 'cascade';
125
128
  }
129
+ if ((prop.cascade.includes(core_1.Cascade.PERSIST) || prop.cascade.includes(core_1.Cascade.ALL))) {
130
+ const hasCascadePath = Object.values(this.foreignKeys).some(fk => {
131
+ return fk.constraintName !== constraintName
132
+ && ((fk.updateRule && fk.updateRule !== 'no action') || (fk.deleteRule && fk.deleteRule !== 'no action'))
133
+ && fk.referencedTableName === this.foreignKeys[constraintName].referencedTableName;
134
+ });
135
+ if (!hasCascadePath || this.platform.supportsMultipleCascadePaths()) {
136
+ this.foreignKeys[constraintName].updateRule ??= 'cascade';
137
+ }
138
+ }
126
139
  if (prop.deferMode) {
127
140
  this.foreignKeys[constraintName].deferMode = prop.deferMode;
128
141
  }
@@ -589,7 +602,7 @@ class DatabaseTable {
589
602
  // The enum name will be a concatenation of the table name and the column name.
590
603
  return namingStrategy.getClassName(this.name + '_' + column.name, '_');
591
604
  }
592
- return column.mappedType?.compareAsType() ?? 'unknown';
605
+ return column.mappedType?.runtimeType ?? 'unknown';
593
606
  }
594
607
  getPropertyDefaultValue(schemaHelper, column, propType, raw = false) {
595
608
  const empty = raw ? 'null' : undefined;
@@ -358,6 +358,9 @@ class SchemaComparator {
358
358
  if (key1.deferMode !== key2.deferMode) {
359
359
  return true;
360
360
  }
361
+ if (key1.localTableName === key1.referencedTableName && !this.platform.supportsMultipleCascadePaths()) {
362
+ return false;
363
+ }
361
364
  const defaultRule = ['restrict', 'no action'];
362
365
  const rule = (key, method) => {
363
366
  return (key[method] ?? defaultRule[0]).toLowerCase().replace(defaultRule[1], defaultRule[0]);
@@ -383,8 +386,8 @@ class SchemaComparator {
383
386
  }
384
387
  };
385
388
  if (fromColumnType !== toColumnType &&
386
- !(fromColumn.ignoreSchemaChanges?.includes('type') ||
387
- toColumn.ignoreSchemaChanges?.includes('type'))) {
389
+ !(fromColumn.ignoreSchemaChanges?.includes('type') || toColumn.ignoreSchemaChanges?.includes('type')) &&
390
+ !fromColumn.generated && !toColumn.generated) {
388
391
  log(`'type' changed for column ${tableName}.${fromColumn.name}`, { fromColumnType, toColumnType });
389
392
  changedProperties.add('type');
390
393
  }
@@ -15,6 +15,7 @@ export declare abstract class SchemaHelper {
15
15
  finalizeTable(table: Knex.TableBuilder, charset: string, collate?: string): void;
16
16
  supportsSchemaConstraints(): boolean;
17
17
  getPrimaryKeys(connection: AbstractSqlConnection, indexes: IndexDef[] | undefined, tableName: string, schemaName?: string): Promise<string[]>;
18
+ inferLengthFromColumnType(type: string): number | undefined;
18
19
  getForeignKeys(connection: AbstractSqlConnection, tableName: string, schemaName?: string): Promise<Dictionary>;
19
20
  protected getTableKey(t: Table): string;
20
21
  getEnumDefinitions(connection: AbstractSqlConnection, checks: CheckDef[], tableName: string, schemaName?: string): Promise<Dictionary<string[]>>;
@@ -46,6 +47,8 @@ export declare abstract class SchemaHelper {
46
47
  normalizeDefaultValue(defaultValue: string, length?: number, defaultValues?: Dictionary<string[]>): string | number;
47
48
  getCreateDatabaseSQL(name: string): string;
48
49
  getDropDatabaseSQL(name: string): string;
50
+ getCreateNamespaceSQL(name: string): string;
51
+ getDropNamespaceSQL(name: string): string;
49
52
  getDatabaseExistsSQL(name: string): string;
50
53
  getDatabaseNotExistsError(dbName: string): string;
51
54
  getManagementDbName(): string;
@@ -29,6 +29,9 @@ class SchemaHelper {
29
29
  const pks = indexes.filter(i => i.primary).map(pk => pk.columnNames);
30
30
  return core_1.Utils.flatten(pks);
31
31
  }
32
+ inferLengthFromColumnType(type) {
33
+ return undefined;
34
+ }
32
35
  async getForeignKeys(connection, tableName, schemaName) {
33
36
  const fks = await connection.execute(this.getForeignKeysSQL(tableName, schemaName));
34
37
  return this.mapForeignKeys(fks, tableName, schemaName);
@@ -232,6 +235,14 @@ class SchemaHelper {
232
235
  getDropDatabaseSQL(name) {
233
236
  return `drop database if exists ${this.platform.quoteIdentifier(name)}`;
234
237
  }
238
+ /* istanbul ignore next */
239
+ getCreateNamespaceSQL(name) {
240
+ return `create schema if not exists ${this.platform.quoteIdentifier(name)}`;
241
+ }
242
+ /* istanbul ignore next */
243
+ getDropNamespaceSQL(name) {
244
+ return `drop schema if exists ${this.platform.quoteIdentifier(name)}`;
245
+ }
235
246
  getDatabaseExistsSQL(name) {
236
247
  return `select 1 from information_schema.schemata where schema_name = '${name}'`;
237
248
  }
@@ -3,8 +3,13 @@ import type { SchemaDifference } from '../typings';
3
3
  import { DatabaseSchema } from './DatabaseSchema';
4
4
  import type { AbstractSqlDriver } from '../AbstractSqlDriver';
5
5
  export declare class SqlSchemaGenerator extends AbstractSchemaGenerator<AbstractSqlDriver> implements ISchemaGenerator {
6
- private readonly helper;
7
- private readonly options;
6
+ protected readonly helper: import("./SchemaHelper").SchemaHelper;
7
+ protected readonly options: {
8
+ disableForeignKeys?: boolean | undefined;
9
+ createForeignKeyConstraints?: boolean | undefined;
10
+ ignoreSchema?: string[] | undefined;
11
+ managementDbName?: string | undefined;
12
+ };
8
13
  protected lastEnsuredDatabase?: string;
9
14
  static register(orm: MikroORM): void;
10
15
  createSchema(options?: CreateSchemaOptions): Promise<void>;
@@ -15,6 +20,8 @@ export declare class SqlSchemaGenerator extends AbstractSchemaGenerator<Abstract
15
20
  getTargetSchema(schema?: string): DatabaseSchema;
16
21
  getCreateSchemaSQL(options?: CreateSchemaOptions): Promise<string>;
17
22
  dropSchema(options?: DropSchemaOptions): Promise<void>;
23
+ createNamespace(name: string): Promise<void>;
24
+ dropNamespace(name: string): Promise<void>;
18
25
  clearDatabase(options?: ClearDatabaseOptions): Promise<void>;
19
26
  getDropSchemaSQL(options?: Omit<DropSchemaOptions, 'dropDb'>): Promise<string>;
20
27
  private getSchemaName;
@@ -58,7 +58,8 @@ class SqlSchemaGenerator extends core_1.AbstractSchemaGenerator {
58
58
  if (namespace === this.platform.getDefaultSchemaName()) {
59
59
  continue;
60
60
  }
61
- ret += await this.dump(this.knex.schema.createSchemaIfNotExists(namespace));
61
+ const sql = this.helper.getCreateNamespaceSQL(namespace);
62
+ ret += await this.dump(this.knex.schema.raw(sql), '\n');
62
63
  }
63
64
  if (this.platform.supportsNativeEnums()) {
64
65
  const created = [];
@@ -88,6 +89,14 @@ class SqlSchemaGenerator extends core_1.AbstractSchemaGenerator {
88
89
  const sql = await this.getDropSchemaSQL(options);
89
90
  await this.execute(sql);
90
91
  }
92
+ async createNamespace(name) {
93
+ const sql = await this.helper.getCreateNamespaceSQL(name);
94
+ await this.execute(sql);
95
+ }
96
+ async dropNamespace(name) {
97
+ const sql = await this.helper.getDropNamespaceSQL(name);
98
+ await this.execute(sql);
99
+ }
91
100
  async clearDatabase(options) {
92
101
  // truncate by default, so no value is considered as true
93
102
  /* istanbul ignore if */
@@ -101,12 +110,7 @@ class SqlSchemaGenerator extends core_1.AbstractSchemaGenerator {
101
110
  .truncate();
102
111
  }
103
112
  await this.execute(this.helper.enableForeignKeysSQL());
104
- if (this.em) {
105
- const allowGlobalContext = this.config.get('allowGlobalContext');
106
- this.config.set('allowGlobalContext', true);
107
- this.em.clear();
108
- this.config.set('allowGlobalContext', allowGlobalContext);
109
- }
113
+ this.clearIdentityMap();
110
114
  }
111
115
  async getDropSchemaSQL(options = {}) {
112
116
  await this.ensureDatabase();
@@ -186,8 +190,8 @@ class SqlSchemaGenerator extends core_1.AbstractSchemaGenerator {
186
190
  let ret = '';
187
191
  if (this.platform.supportsSchemas()) {
188
192
  for (const newNamespace of schemaDiff.newNamespaces) {
189
- // schema might already exist, e.g. explicit usage of `public` in postgres
190
- ret += await this.dump(this.knex.schema.createSchemaIfNotExists(newNamespace));
193
+ const sql = this.helper.getCreateNamespaceSQL(newNamespace);
194
+ ret += await this.dump(this.knex.schema.raw(sql), '\n');
191
195
  }
192
196
  }
193
197
  if (this.platform.supportsNativeEnums()) {
@@ -240,7 +244,8 @@ class SqlSchemaGenerator extends core_1.AbstractSchemaGenerator {
240
244
  }
241
245
  if (options.dropTables && !options.safe) {
242
246
  for (const removedNamespace of schemaDiff.removedNamespaces) {
243
- ret += await this.dump(this.knex.schema.dropSchema(removedNamespace));
247
+ const sql = this.helper.getDropNamespaceSQL(removedNamespace);
248
+ ret += await this.dump(this.knex.schema.raw(sql), '\n');
244
249
  }
245
250
  }
246
251
  return this.wrapSchema(ret, options);
@@ -266,11 +271,13 @@ class SqlSchemaGenerator extends core_1.AbstractSchemaGenerator {
266
271
  .references(foreignKey.referencedColumnNames)
267
272
  .inTable(this.getReferencedTableName(foreignKey.referencedTableName, schema))
268
273
  .withKeyName(foreignKey.constraintName);
269
- if (foreignKey.updateRule) {
270
- builder.onUpdate(foreignKey.updateRule);
271
- }
272
- if (foreignKey.deleteRule) {
273
- builder.onDelete(foreignKey.deleteRule);
274
+ if (foreignKey.localTableName !== foreignKey.referencedTableName || this.platform.supportsMultipleCascadePaths()) {
275
+ if (foreignKey.updateRule) {
276
+ builder.onUpdate(foreignKey.updateRule);
277
+ }
278
+ if (foreignKey.deleteRule) {
279
+ builder.onDelete(foreignKey.deleteRule);
280
+ }
274
281
  }
275
282
  if (foreignKey.deferMode) {
276
283
  builder.deferrable(foreignKey.deferMode);