@mikro-orm/mssql 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.
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2018 Martin Adámek
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,14 @@
1
+ import { AbstractSqlConnection, type IsolationLevel, type Knex, type TransactionEventBroadcaster } from '@mikro-orm/knex';
2
+ export declare class MsSqlConnection extends AbstractSqlConnection {
3
+ createKnex(): void;
4
+ getDefaultClientUrl(): string;
5
+ getConnectionOptions(): Knex.MsSqlConnectionConfig;
6
+ begin(options?: {
7
+ isolationLevel?: IsolationLevel;
8
+ ctx?: Knex.Transaction;
9
+ eventBroadcaster?: TransactionEventBroadcaster;
10
+ }): Promise<Knex.Transaction>;
11
+ commit(ctx: Knex.Transaction, eventBroadcaster?: TransactionEventBroadcaster): Promise<void>;
12
+ rollback(ctx: Knex.Transaction, eventBroadcaster?: TransactionEventBroadcaster): Promise<void>;
13
+ protected transformRawResult<T>(res: any, method: 'all' | 'get' | 'run'): T;
14
+ }
@@ -0,0 +1,61 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.MsSqlConnection = void 0;
4
+ const knex_1 = require("@mikro-orm/knex");
5
+ class MsSqlConnection extends knex_1.AbstractSqlConnection {
6
+ createKnex() {
7
+ this.client = this.createKnexClient(knex_1.MsSqlKnexDialect);
8
+ this.connected = true;
9
+ }
10
+ getDefaultClientUrl() {
11
+ return 'mssql://sa@localhost:1433';
12
+ }
13
+ getConnectionOptions() {
14
+ const config = super.getConnectionOptions();
15
+ const overrides = {
16
+ options: {
17
+ enableArithAbort: true,
18
+ fallbackToDefaultDb: true,
19
+ },
20
+ };
21
+ knex_1.Utils.mergeConfig(config, overrides);
22
+ return config;
23
+ }
24
+ async begin(options = {}) {
25
+ if (!options.ctx) {
26
+ if (options.isolationLevel) {
27
+ this.logQuery(`set transaction isolation level ${options.isolationLevel}`);
28
+ }
29
+ this.logQuery('begin');
30
+ }
31
+ return super.begin(options);
32
+ }
33
+ async commit(ctx, eventBroadcaster) {
34
+ this.logQuery('commit');
35
+ return super.commit(ctx, eventBroadcaster);
36
+ }
37
+ async rollback(ctx, eventBroadcaster) {
38
+ if (eventBroadcaster?.isTopLevel()) {
39
+ this.logQuery('rollback');
40
+ }
41
+ return super.rollback(ctx, eventBroadcaster);
42
+ }
43
+ transformRawResult(res, method) {
44
+ if (method === 'get') {
45
+ return res[0];
46
+ }
47
+ if (method === 'all' || !res) {
48
+ return res;
49
+ }
50
+ const rowCount = res.length;
51
+ const hasEmptyCount = (rowCount === 1) && ('' in res[0]);
52
+ const emptyRow = hasEmptyCount && res[0][''];
53
+ return {
54
+ affectedRows: hasEmptyCount ? emptyRow : res.length,
55
+ insertId: res[0] ? res[0].id : 0,
56
+ row: res[0],
57
+ rows: res,
58
+ };
59
+ }
60
+ }
61
+ exports.MsSqlConnection = MsSqlConnection;
@@ -0,0 +1,9 @@
1
+ import { type AnyEntity, type Configuration, type ConnectionType, type EntityDictionary, type LoggingOptions, type NativeInsertUpdateManyOptions, type QueryResult, type Transaction } from '@mikro-orm/core';
2
+ import { AbstractSqlDriver, type Knex, type SqlEntityManager } from '@mikro-orm/knex';
3
+ import { MsSqlConnection } from './MsSqlConnection';
4
+ import { MsSqlQueryBuilder } from './MsSqlQueryBuilder';
5
+ export declare class MsSqlDriver extends AbstractSqlDriver<MsSqlConnection> {
6
+ constructor(config: Configuration);
7
+ nativeInsertMany<T extends AnyEntity<T>>(entityName: string, data: EntityDictionary<T>[], options?: NativeInsertUpdateManyOptions<T>): Promise<QueryResult<T>>;
8
+ createQueryBuilder<T extends AnyEntity<T>>(entityName: string, ctx?: Transaction<Knex.Transaction>, preferredConnectionType?: ConnectionType, convertCustomTypes?: boolean, loggerContext?: LoggingOptions, alias?: string, em?: SqlEntityManager): MsSqlQueryBuilder<T>;
9
+ }
package/MsSqlDriver.js ADDED
@@ -0,0 +1,61 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.MsSqlDriver = void 0;
4
+ const core_1 = require("@mikro-orm/core");
5
+ const knex_1 = require("@mikro-orm/knex");
6
+ const MsSqlConnection_1 = require("./MsSqlConnection");
7
+ const MsSqlPlatform_1 = require("./MsSqlPlatform");
8
+ const MsSqlQueryBuilder_1 = require("./MsSqlQueryBuilder");
9
+ class MsSqlDriver extends knex_1.AbstractSqlDriver {
10
+ constructor(config) {
11
+ super(config, new MsSqlPlatform_1.MsSqlPlatform(), MsSqlConnection_1.MsSqlConnection, ['knex', 'tedious']);
12
+ }
13
+ async nativeInsertMany(entityName, data, options = {}) {
14
+ const meta = this.metadata.get(entityName);
15
+ const keys = new Set();
16
+ data.forEach(row => Object.keys(row).forEach(k => keys.add(k)));
17
+ const props = [...keys].map(name => meta.properties[name] ?? { name, fieldNames: [name] });
18
+ const fields = core_1.Utils.flatten(props.map(prop => prop.fieldNames));
19
+ const tableName = this.getTableName(meta, options);
20
+ const hasFields = fields.length > 0;
21
+ // Is this en empty insert... this is rather hard in mssql (especially with an insert many)
22
+ if (!hasFields) {
23
+ const returningProps = meta.props.filter(prop => prop.primary || prop.defaultRaw);
24
+ const returningFields = core_1.Utils.flatten(returningProps.map(prop => prop.fieldNames));
25
+ const using2 = `select * from (values ${data.map((x, i) => `(${i})`).join(',')}) v (id) where 1 = 1`;
26
+ /* istanbul ignore next */
27
+ const output = returningFields.length > 0 ? `output ${returningFields.map(field => 'inserted.' + this.platform.quoteIdentifier(field)).join(', ')}` : '';
28
+ const sql = `merge into ${tableName} using (${using2}) s on 1 = 0 when not matched then insert default values ${output};`;
29
+ const res = await this.execute(sql, [], 'run', options.ctx);
30
+ const pks = this.getPrimaryKeyFields(entityName);
31
+ let pk;
32
+ /* istanbul ignore next */
33
+ if (pks.length > 1) { // owner has composite pk
34
+ pk = data.map(d => core_1.Utils.getPrimaryKeyCond(d, pks));
35
+ }
36
+ else {
37
+ res.row ??= {};
38
+ res.rows ??= [];
39
+ pk = data.map((d, i) => d[pks[0]] ?? res.rows[i]?.[pks[0]]).map(d => [d]);
40
+ res.insertId = res.insertId || res.row[pks[0]];
41
+ }
42
+ return res;
43
+ }
44
+ if (props.some(prop => prop.autoincrement)) {
45
+ return super.nativeInsertMany(entityName, data, options, sql => {
46
+ return `set identity_insert ${tableName} on; ${sql}; set identity_insert ${tableName} off`;
47
+ });
48
+ }
49
+ return super.nativeInsertMany(entityName, data, options);
50
+ }
51
+ createQueryBuilder(entityName, ctx, preferredConnectionType, convertCustomTypes, loggerContext, alias, em) {
52
+ // do not compute the connectionType if EM is provided as it will be computed from it in the QB later on
53
+ const connectionType = em ? preferredConnectionType : this.resolveConnectionType({ ctx, connectionType: preferredConnectionType });
54
+ const qb = new MsSqlQueryBuilder_1.MsSqlQueryBuilder(entityName, this.metadata, this, ctx, alias, connectionType, em, loggerContext);
55
+ if (!convertCustomTypes) {
56
+ qb.unsetFlag(core_1.QueryFlag.CONVERT_CUSTOM_TYPES);
57
+ }
58
+ return qb;
59
+ }
60
+ }
61
+ exports.MsSqlDriver = MsSqlDriver;
@@ -0,0 +1,8 @@
1
+ import { ExceptionConverter, type Dictionary, type DriverException } from '@mikro-orm/core';
2
+ export declare class MsSqlExceptionConverter extends ExceptionConverter {
3
+ /**
4
+ * @link https://docs.microsoft.com/en-us/sql/relational-databases/errors-events/mssqlserver-511-database-engine-error?view=sql-server-ver15
5
+ * @link https://github.com/doctrine/dbal/blob/master/src/Driver/AbstractPostgreSQLDriver.php
6
+ */
7
+ convertException(exception: Error & Dictionary): DriverException;
8
+ }
@@ -0,0 +1,37 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.MsSqlExceptionConverter = void 0;
4
+ const core_1 = require("@mikro-orm/core");
5
+ class MsSqlExceptionConverter extends core_1.ExceptionConverter {
6
+ /* istanbul ignore next */
7
+ /**
8
+ * @link https://docs.microsoft.com/en-us/sql/relational-databases/errors-events/mssqlserver-511-database-engine-error?view=sql-server-ver15
9
+ * @link https://github.com/doctrine/dbal/blob/master/src/Driver/AbstractPostgreSQLDriver.php
10
+ */
11
+ convertException(exception) {
12
+ let errno = exception.number;
13
+ if ('errors' in exception && Array.isArray(exception.errors) && typeof exception.errors[0] === 'object' && 'message' in exception.errors[0]) {
14
+ exception.message += '\n' + exception.errors.map(e => e.message).join('\n');
15
+ errno ??= exception.errors[0].number;
16
+ exception.lineNumber ??= exception.errors[0].lineNumber;
17
+ }
18
+ switch (errno) {
19
+ case 515:
20
+ return new core_1.NotNullConstraintViolationException(exception);
21
+ case 102:
22
+ return new core_1.SyntaxErrorException(exception);
23
+ case 207:
24
+ return new core_1.InvalidFieldNameException(exception);
25
+ case 208:
26
+ return new core_1.TableNotFoundException(exception);
27
+ case 209:
28
+ return new core_1.NonUniqueFieldNameException(exception);
29
+ case 2601:
30
+ return new core_1.UniqueConstraintViolationException(exception);
31
+ case 2714:
32
+ return new core_1.TableExistsException(exception);
33
+ }
34
+ return super.convertException(exception);
35
+ }
36
+ }
37
+ exports.MsSqlExceptionConverter = MsSqlExceptionConverter;
@@ -0,0 +1,19 @@
1
+ import { MikroORM, type Options, type IDatabaseDriver, type EntityManager, type EntityManagerType } from '@mikro-orm/core';
2
+ import { MsSqlDriver } from './MsSqlDriver';
3
+ import type { SqlEntityManager } from '@mikro-orm/knex';
4
+ /**
5
+ * @inheritDoc
6
+ */
7
+ export declare class MsSqlMikroORM<EM extends EntityManager = SqlEntityManager> extends MikroORM<MsSqlDriver, EM> {
8
+ private static DRIVER;
9
+ /**
10
+ * @inheritDoc
11
+ */
12
+ static init<D extends IDatabaseDriver = MsSqlDriver, EM extends EntityManager = D[typeof EntityManagerType] & EntityManager>(options?: Options<D, EM>): Promise<MikroORM<D, EM>>;
13
+ /**
14
+ * @inheritDoc
15
+ */
16
+ static initSync<D extends IDatabaseDriver = MsSqlDriver, EM extends EntityManager = D[typeof EntityManagerType] & EntityManager>(options: Options<D, EM>): MikroORM<D, EM>;
17
+ }
18
+ export type MsSqlOptions = Options<MsSqlDriver>;
19
+ export declare function defineMsSqlConfig(options: MsSqlOptions): Options<MsSqlDriver, SqlEntityManager<MsSqlDriver> & EntityManager<IDatabaseDriver<import("@mikro-orm/core").Connection>>>;
@@ -0,0 +1,29 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.defineMsSqlConfig = exports.MsSqlMikroORM = void 0;
4
+ const core_1 = require("@mikro-orm/core");
5
+ const MsSqlDriver_1 = require("./MsSqlDriver");
6
+ /**
7
+ * @inheritDoc
8
+ */
9
+ class MsSqlMikroORM extends core_1.MikroORM {
10
+ static DRIVER = MsSqlDriver_1.MsSqlDriver;
11
+ /**
12
+ * @inheritDoc
13
+ */
14
+ static async init(options) {
15
+ return super.init(options);
16
+ }
17
+ /**
18
+ * @inheritDoc
19
+ */
20
+ static initSync(options) {
21
+ return super.initSync(options);
22
+ }
23
+ }
24
+ exports.MsSqlMikroORM = MsSqlMikroORM;
25
+ /* istanbul ignore next */
26
+ function defineMsSqlConfig(options) {
27
+ return (0, core_1.defineConfig)({ driver: MsSqlDriver_1.MsSqlDriver, ...options });
28
+ }
29
+ exports.defineMsSqlConfig = defineMsSqlConfig;
@@ -0,0 +1,47 @@
1
+ import { AbstractSqlPlatform, type EntityMetadata, type IDatabaseDriver, type EntityManager, type MikroORM, Type, type Primary, type IPrimaryKey } from '@mikro-orm/knex';
2
+ import { MsSqlSchemaHelper } from './MsSqlSchemaHelper';
3
+ import { MsSqlExceptionConverter } from './MsSqlExceptionConverter';
4
+ import { MsSqlSchemaGenerator } from './MsSqlSchemaGenerator';
5
+ export declare class MsSqlPlatform extends AbstractSqlPlatform {
6
+ protected readonly schemaHelper: MsSqlSchemaHelper;
7
+ protected readonly exceptionConverter: MsSqlExceptionConverter;
8
+ /** @inheritDoc */
9
+ lookupExtensions(orm: MikroORM): void;
10
+ usesOutputStatement(): boolean;
11
+ convertDateToJSValue(value: string | Date): string;
12
+ convertsJsonAutomatically(): boolean;
13
+ indexForeignKeys(): boolean;
14
+ supportsSchemas(): boolean;
15
+ getCurrentTimestampSQL(length: number): string;
16
+ getDateTimeTypeDeclarationSQL(column: {
17
+ length?: number;
18
+ }): string;
19
+ getTimeTypeDeclarationSQL(): string;
20
+ getFloatDeclarationSQL(): string;
21
+ getDoubleDeclarationSQL(): string;
22
+ getBooleanTypeDeclarationSQL(): string;
23
+ getRegExpOperator(): string;
24
+ getBlobDeclarationSQL(): string;
25
+ getJsonDeclarationSQL(): string;
26
+ getEnumTypeDeclarationSQL(column: {
27
+ fieldNames: string[];
28
+ items?: unknown[];
29
+ length?: number;
30
+ }): string;
31
+ getDefaultMappedType(type: string): Type<unknown>;
32
+ getDefaultSchemaName(): string | undefined;
33
+ getVarcharTypeDeclarationSQL(column: {
34
+ length?: number;
35
+ }): string;
36
+ getUuidTypeDeclarationSQL(column: {
37
+ length?: number;
38
+ }): string;
39
+ validateMetadata(meta: EntityMetadata): void;
40
+ getSearchJsonPropertyKey(path: string[], type: string, aliased: boolean, value?: unknown): string;
41
+ normalizePrimaryKey<T extends number | string = number | string>(data: Primary<T> | IPrimaryKey | string): T;
42
+ supportsMultipleCascadePaths(): boolean;
43
+ supportsMultipleStatements(): boolean;
44
+ quoteIdentifier(id: string): string;
45
+ quoteValue(value: any): string;
46
+ getSchemaGenerator(driver: IDatabaseDriver, em?: EntityManager): MsSqlSchemaGenerator;
47
+ }
@@ -0,0 +1,171 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.MsSqlPlatform = void 0;
7
+ const knex_1 = require("@mikro-orm/knex");
8
+ // @ts-expect-error no types available
9
+ const tsqlstring_1 = __importDefault(require("tsqlstring"));
10
+ const MsSqlSchemaHelper_1 = require("./MsSqlSchemaHelper");
11
+ const MsSqlExceptionConverter_1 = require("./MsSqlExceptionConverter");
12
+ const MsSqlSchemaGenerator_1 = require("./MsSqlSchemaGenerator");
13
+ const UnicodeStringType_1 = require("./UnicodeStringType");
14
+ class MsSqlPlatform extends knex_1.AbstractSqlPlatform {
15
+ schemaHelper = new MsSqlSchemaHelper_1.MsSqlSchemaHelper(this);
16
+ exceptionConverter = new MsSqlExceptionConverter_1.MsSqlExceptionConverter();
17
+ /** @inheritDoc */
18
+ lookupExtensions(orm) {
19
+ MsSqlSchemaGenerator_1.MsSqlSchemaGenerator.register(orm);
20
+ }
21
+ usesOutputStatement() {
22
+ return true;
23
+ }
24
+ convertDateToJSValue(value) {
25
+ /* istanbul ignore next */
26
+ if (typeof value === 'string') {
27
+ return value;
28
+ }
29
+ return value.toISOString().substring(0, 10);
30
+ }
31
+ convertsJsonAutomatically() {
32
+ return false;
33
+ }
34
+ indexForeignKeys() {
35
+ return false;
36
+ }
37
+ supportsSchemas() {
38
+ return true;
39
+ }
40
+ getCurrentTimestampSQL(length) {
41
+ return `current_timestamp`;
42
+ }
43
+ getDateTimeTypeDeclarationSQL(column) {
44
+ /* istanbul ignore next */
45
+ return 'datetime2' + (column.length != null ? `(${column.length})` : '');
46
+ }
47
+ getTimeTypeDeclarationSQL() {
48
+ return 'time';
49
+ }
50
+ getFloatDeclarationSQL() {
51
+ return 'float(24)';
52
+ }
53
+ getDoubleDeclarationSQL() {
54
+ return 'float(53)';
55
+ }
56
+ getBooleanTypeDeclarationSQL() {
57
+ return 'bit';
58
+ }
59
+ getRegExpOperator() {
60
+ throw new Error('Not supported');
61
+ }
62
+ getBlobDeclarationSQL() {
63
+ return 'varbinary(max)';
64
+ }
65
+ getJsonDeclarationSQL() {
66
+ return 'nvarchar(max)';
67
+ }
68
+ getEnumTypeDeclarationSQL(column) {
69
+ if (column.items?.every(item => knex_1.Utils.isString(item))) {
70
+ return this.getVarcharTypeDeclarationSQL({ length: 100, ...column });
71
+ }
72
+ /* istanbul ignore next */
73
+ return this.getSmallIntTypeDeclarationSQL(column);
74
+ }
75
+ getDefaultMappedType(type) {
76
+ const normalizedType = this.extractSimpleType(type);
77
+ if (normalizedType !== 'uuid' && ['string', 'nvarchar'].includes(normalizedType)) {
78
+ return knex_1.Type.getType(UnicodeStringType_1.UnicodeStringType);
79
+ }
80
+ const map = {
81
+ int: 'integer',
82
+ bit: 'boolean',
83
+ real: 'float',
84
+ uniqueidentifier: 'uuid',
85
+ varbinary: 'blob',
86
+ datetime2: 'datetime',
87
+ };
88
+ return super.getDefaultMappedType(map[normalizedType] ?? type);
89
+ }
90
+ getDefaultSchemaName() {
91
+ return 'dbo';
92
+ }
93
+ getVarcharTypeDeclarationSQL(column) {
94
+ return `nvarchar(${column.length ?? 255})`;
95
+ }
96
+ getUuidTypeDeclarationSQL(column) {
97
+ return 'uniqueidentifier';
98
+ }
99
+ validateMetadata(meta) {
100
+ for (const prop of meta.props) {
101
+ if ((prop.runtimeType === 'string' || ['string', 'nvarchar'].includes(prop.type))
102
+ && !['uuid'].includes(prop.type)
103
+ && !prop.columnTypes[0].startsWith('varchar')) {
104
+ prop.customType ??= new UnicodeStringType_1.UnicodeStringType();
105
+ prop.customType.prop = prop;
106
+ prop.customType.platform = this;
107
+ prop.customType.meta = meta;
108
+ }
109
+ }
110
+ }
111
+ getSearchJsonPropertyKey(path, type, aliased, value) {
112
+ const [a, ...b] = path;
113
+ /* istanbul ignore next */
114
+ const root = this.quoteIdentifier(aliased ? `${knex_1.ALIAS_REPLACEMENT}.${a}` : a);
115
+ const types = {
116
+ boolean: 'bit',
117
+ };
118
+ const cast = (key) => (0, knex_1.raw)(type in types ? `cast(${key} as ${types[type]})` : key);
119
+ const quoteKey = (key) => key.match(/^[a-z]\w*$/i) ? key : `"${key}"`;
120
+ /* istanbul ignore if */
121
+ if (path.length === 0) {
122
+ return cast(`json_value(${root}, '$.${b.map(quoteKey).join('.')}')`);
123
+ }
124
+ return cast(`json_value(${root}, '$.${b.map(quoteKey).join('.')}')`);
125
+ }
126
+ normalizePrimaryKey(data) {
127
+ /* istanbul ignore if */
128
+ if (data instanceof UnicodeStringType_1.UnicodeString) {
129
+ return data.value;
130
+ }
131
+ return data;
132
+ }
133
+ supportsMultipleCascadePaths() {
134
+ return false;
135
+ }
136
+ supportsMultipleStatements() {
137
+ return true;
138
+ }
139
+ quoteIdentifier(id) {
140
+ return `[${id.replace('.', `].[`)}]`;
141
+ }
142
+ quoteValue(value) {
143
+ /* istanbul ignore if */
144
+ if (knex_1.Utils.isRawSql(value)) {
145
+ return this.formatQuery(value.sql, value.params ?? []);
146
+ }
147
+ /* istanbul ignore if */
148
+ if (this.isRaw(value)) {
149
+ return value;
150
+ }
151
+ if (value instanceof UnicodeStringType_1.UnicodeString) {
152
+ return `N${tsqlstring_1.default.escape(value.value)}`;
153
+ }
154
+ /* istanbul ignore if */
155
+ if (knex_1.Utils.isPlainObject(value) || value?.[knex_1.JsonProperty]) {
156
+ return tsqlstring_1.default.escape(JSON.stringify(value), true, this.timezone);
157
+ }
158
+ if (value instanceof Buffer) {
159
+ return `0x${value.toString('hex')}`;
160
+ }
161
+ if (value instanceof Date) {
162
+ return tsqlstring_1.default.dateToString(value.toISOString(), 'Z');
163
+ }
164
+ return tsqlstring_1.default.escape(value);
165
+ }
166
+ /* istanbul ignore next: kept for type inference only */
167
+ getSchemaGenerator(driver, em) {
168
+ return new MsSqlSchemaGenerator_1.MsSqlSchemaGenerator(em ?? driver);
169
+ }
170
+ }
171
+ exports.MsSqlPlatform = MsSqlPlatform;
@@ -0,0 +1,9 @@
1
+ import { type AnyEntity, type RequiredEntityData } from '@mikro-orm/core';
2
+ import { type InsertQueryBuilder, type Knex, QueryBuilder } from '@mikro-orm/knex';
3
+ export declare class MsSqlQueryBuilder<T extends AnyEntity<T> = AnyEntity> extends QueryBuilder<T> {
4
+ insert(data: RequiredEntityData<T> | RequiredEntityData<T>[]): InsertQueryBuilder<T>;
5
+ getKnex(): Knex.QueryBuilder;
6
+ getKnexQuery(processVirtualEntity?: boolean): Knex.QueryBuilder;
7
+ private appendIdentityInsert;
8
+ private checkIdentityInsert;
9
+ }
@@ -0,0 +1,53 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.MsSqlQueryBuilder = void 0;
4
+ const core_1 = require("@mikro-orm/core");
5
+ const knex_1 = require("@mikro-orm/knex");
6
+ class MsSqlQueryBuilder extends knex_1.QueryBuilder {
7
+ insert(data) {
8
+ this.checkIdentityInsert(data);
9
+ return super.insert(data);
10
+ }
11
+ getKnex() {
12
+ const qb = super.getKnex();
13
+ if (this.flags.has(core_1.QueryFlag.IDENTITY_INSERT)) {
14
+ this.appendIdentityInsert(qb);
15
+ }
16
+ return qb;
17
+ }
18
+ getKnexQuery(processVirtualEntity = true) {
19
+ if (this.type === knex_1.QueryType.TRUNCATE) {
20
+ const tableName = this.driver.getTableName(this.mainAlias.metadata, { schema: this._schema }, false);
21
+ const tableNameQuoted = this.platform.quoteIdentifier(tableName);
22
+ const sql = `delete from ${tableNameQuoted}; declare @count int = case @@rowcount when 0 then 1 else 0 end; dbcc checkident ('${tableName}', reseed, @count)`;
23
+ this._query = {};
24
+ return this._query.qb = this.knex.raw(sql);
25
+ }
26
+ return super.getKnexQuery(processVirtualEntity);
27
+ }
28
+ appendIdentityInsert(qb) {
29
+ const meta = this.metadata.get(this.mainAlias.entityName);
30
+ const table = this.driver.getTableName(meta, { schema: this._schema });
31
+ const originalToSQL = qb.toSQL;
32
+ qb.toSQL = () => {
33
+ const res = originalToSQL.apply(qb);
34
+ return {
35
+ ...res,
36
+ sql: `set identity_insert ${table} on; ${res.sql}; set identity_insert ${table} off;`,
37
+ toNative: () => res.toNative(),
38
+ };
39
+ };
40
+ }
41
+ checkIdentityInsert(data) {
42
+ const meta = this.metadata.find(this.mainAlias.entityName);
43
+ if (!meta) {
44
+ return;
45
+ }
46
+ const dataKeys = core_1.Utils.unique(core_1.Utils.asArray(data).flatMap(Object.keys));
47
+ const hasAutoincrement = dataKeys.some(x => meta.properties[x]?.autoincrement);
48
+ if (hasAutoincrement) {
49
+ this.setFlag(core_1.QueryFlag.IDENTITY_INSERT);
50
+ }
51
+ }
52
+ }
53
+ exports.MsSqlQueryBuilder = MsSqlQueryBuilder;
@@ -0,0 +1,6 @@
1
+ import { type ClearDatabaseOptions, type DropSchemaOptions, type MikroORM, SchemaGenerator } from '@mikro-orm/knex';
2
+ export declare class MsSqlSchemaGenerator extends SchemaGenerator {
3
+ static register(orm: MikroORM): void;
4
+ clearDatabase(options?: ClearDatabaseOptions): Promise<void>;
5
+ getDropSchemaSQL(options?: Omit<DropSchemaOptions, 'dropDb'>): Promise<string>;
6
+ }
@@ -0,0 +1,31 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.MsSqlSchemaGenerator = void 0;
4
+ const knex_1 = require("@mikro-orm/knex");
5
+ class MsSqlSchemaGenerator extends knex_1.SchemaGenerator {
6
+ static register(orm) {
7
+ orm.config.registerExtension('@mikro-orm/schema-generator', () => new MsSqlSchemaGenerator(orm.em));
8
+ }
9
+ async clearDatabase(options) {
10
+ // truncate by default, so no value is considered as true
11
+ /* istanbul ignore if */
12
+ if (options?.truncate === false) {
13
+ return super.clearDatabase(options);
14
+ }
15
+ // https://stackoverflow.com/questions/253849/cannot-truncate-table-because-it-is-being-referenced-by-a-foreign-key-constraint
16
+ for (const meta of this.getOrderedMetadata(options?.schema).reverse()) {
17
+ const res = await this.driver.nativeDelete(meta.className, {}, options);
18
+ if (meta.getPrimaryProps().some(pk => pk.autoincrement)) {
19
+ const tableName = this.driver.getTableName(meta, { schema: options?.schema }, false);
20
+ await this.execute(`dbcc checkident ('${tableName}', reseed, ${res.affectedRows > 0 ? 0 : 1})`, {
21
+ ctx: this.em?.getTransactionContext(),
22
+ });
23
+ }
24
+ }
25
+ this.clearIdentityMap();
26
+ }
27
+ async getDropSchemaSQL(options = {}) {
28
+ return super.getDropSchemaSQL({ dropForeignKeys: true, ...options });
29
+ }
30
+ }
31
+ exports.MsSqlSchemaGenerator = MsSqlSchemaGenerator;
@@ -0,0 +1,32 @@
1
+ import { type AbstractSqlConnection, type CheckDef, type Column, type DatabaseSchema, type DatabaseTable, type Dictionary, type ForeignKey, type IndexDef, type Knex, SchemaHelper, type Table, type TableDifference, type Type } from '@mikro-orm/knex';
2
+ export declare class MsSqlSchemaHelper extends SchemaHelper {
3
+ static readonly DEFAULT_VALUES: {
4
+ true: string[];
5
+ false: string[];
6
+ 'getdate()': string[];
7
+ };
8
+ getManagementDbName(): string;
9
+ disableForeignKeysSQL(): string;
10
+ enableForeignKeysSQL(): string;
11
+ getDatabaseExistsSQL(name: string): string;
12
+ getListTablesSQL(): string;
13
+ normalizeDefaultValue(defaultValue: string, length: number, defaultValues?: Dictionary<string[]>, stripQuotes?: boolean): string | number;
14
+ getAllColumns(connection: AbstractSqlConnection, tables: Table[]): Promise<Dictionary<Column[]>>;
15
+ getAllIndexes(connection: AbstractSqlConnection, tables: Table[]): Promise<Dictionary<IndexDef[]>>;
16
+ mapForeignKeys(fks: any[], tableName: string, schemaName?: string): Dictionary;
17
+ getAllForeignKeys(connection: AbstractSqlConnection, tables: Table[]): Promise<Dictionary<Dictionary<ForeignKey>>>;
18
+ getEnumDefinitions(connection: AbstractSqlConnection, checks: CheckDef[], tableName?: string, schemaName?: string): Promise<Dictionary<string[]>>;
19
+ private getChecksSQL;
20
+ getAllChecks(connection: AbstractSqlConnection, tables: Table[]): Promise<Dictionary<CheckDef[]>>;
21
+ loadInformationSchema(schema: DatabaseSchema, connection: AbstractSqlConnection, tables: Table[]): Promise<void>;
22
+ getPreAlterTable(tableDiff: TableDifference, safe: boolean): string;
23
+ getPostAlterTable(tableDiff: TableDifference, safe: boolean): string;
24
+ getCreateNamespaceSQL(name: string): string;
25
+ getDropNamespaceSQL(name: string): string;
26
+ getDropIndexSQL(tableName: string, index: IndexDef): string;
27
+ getDropColumnsSQL(tableName: string, columns: Column[], schemaName?: string): string;
28
+ getRenameColumnSQL(tableName: string, oldColumnName: string, to: Column, schemaName?: string): string;
29
+ createTableColumn(table: Knex.TableBuilder, column: Column, fromTable: DatabaseTable, changedProperties?: Set<string>, alter?: boolean): Knex.ColumnBuilder | undefined;
30
+ inferLengthFromColumnType(type: string): number | undefined;
31
+ protected wrap(val: string | undefined, type: Type<unknown>): string | undefined;
32
+ }