@mikro-orm/knex 6.1.13-dev.27 → 6.1.13-dev.29
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.d.ts +5 -5
- package/AbstractSqlDriver.js +15 -4
- package/MonkeyPatchable.d.ts +4 -0
- package/MonkeyPatchable.js +12 -0
- package/README.md +2 -0
- package/SqlEntityManager.d.ts +1 -1
- package/SqlEntityManager.js +1 -2
- package/dialects/index.d.ts +1 -0
- package/dialects/index.js +1 -0
- package/dialects/mssql/MsSqlColumnCompiler.d.ts +4 -0
- package/dialects/mssql/MsSqlColumnCompiler.js +10 -0
- package/dialects/mssql/MsSqlKnexDialect.d.ts +6 -0
- package/dialects/mssql/MsSqlKnexDialect.js +22 -0
- package/dialects/mssql/MsSqlQueryCompiler.d.ts +12 -0
- package/dialects/mssql/MsSqlQueryCompiler.js +94 -0
- package/dialects/mssql/MsSqlTableCompiler.d.ts +9 -0
- package/dialects/mssql/MsSqlTableCompiler.js +39 -0
- package/dialects/mssql/index.d.ts +1 -0
- package/dialects/mssql/index.js +17 -0
- package/index.mjs +2 -0
- package/package.json +2 -2
- package/query/QueryBuilder.d.ts +48 -38
- package/query/QueryBuilder.js +12 -12
- package/query/QueryBuilderHelper.js +2 -1
- package/schema/DatabaseTable.js +15 -2
- package/schema/SchemaComparator.js +5 -2
- package/schema/SchemaHelper.d.ts +3 -0
- package/schema/SchemaHelper.js +11 -0
- package/schema/SqlSchemaGenerator.d.ts +9 -2
- package/schema/SqlSchemaGenerator.js +22 -15
package/AbstractSqlDriver.d.ts
CHANGED
|
@@ -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 =
|
|
17
|
-
findOne<T extends object, P extends string = never, F extends string =
|
|
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
|
|
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;
|
package/AbstractSqlDriver.js
CHANGED
|
@@ -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
|
-
|
|
954
|
-
const
|
|
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
|
}
|
package/MonkeyPatchable.d.ts
CHANGED
|
@@ -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;
|
package/MonkeyPatchable.js
CHANGED
|
@@ -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
|
package/SqlEntityManager.d.ts
CHANGED
|
@@ -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
|
package/SqlEntityManager.js
CHANGED
|
@@ -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
|
|
14
|
+
return this.driver.createQueryBuilder(entityName, context.getTransactionContext(), type, true, loggerContext ?? context.loggerContext, alias, this);
|
|
16
15
|
}
|
|
17
16
|
/**
|
|
18
17
|
* Shortcut for `createQueryBuilder()`
|
package/dialects/index.d.ts
CHANGED
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,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,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.
|
|
3
|
+
"version": "6.1.13-dev.29",
|
|
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.
|
|
69
|
+
"@mikro-orm/core": "6.1.13-dev.29"
|
|
70
70
|
}
|
|
71
71
|
}
|
package/query/QueryBuilder.d.ts
CHANGED
|
@@ -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
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
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
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
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
|
*/
|
package/query/QueryBuilder.js
CHANGED
|
@@ -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
|
|
463
|
-
return this
|
|
463
|
+
if (this._query?.qb) {
|
|
464
|
+
return this._query.qb;
|
|
464
465
|
}
|
|
465
|
-
this
|
|
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
|
|
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
|
|
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
|
|
512
|
-
return { sql: this
|
|
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
|
|
517
|
-
this
|
|
518
|
-
this
|
|
519
|
-
return { sql: this
|
|
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
|
-
|
|
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
|
package/schema/DatabaseTable.js
CHANGED
|
@@ -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
|
|
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?.
|
|
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
|
-
|
|
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
|
}
|
package/schema/SchemaHelper.d.ts
CHANGED
|
@@ -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;
|
package/schema/SchemaHelper.js
CHANGED
|
@@ -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
|
-
|
|
7
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
190
|
-
ret += await this.dump(this.knex.schema.
|
|
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
|
-
|
|
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.
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
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);
|