@mikro-orm/mssql 7.2.0-dev.0 → 7.2.0-dev.10
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/MsSqlConnection.d.ts +7 -1
- package/MsSqlConnection.js +7 -1
- package/MsSqlPlatform.d.ts +2 -0
- package/MsSqlPlatform.js +13 -6
- package/MsSqlSchemaGenerator.d.ts +1 -0
- package/MsSqlSchemaGenerator.js +5 -0
- package/MsSqlSchemaHelper.d.ts +5 -0
- package/MsSqlSchemaHelper.js +40 -16
- package/package.json +5 -5
package/MsSqlConnection.d.ts
CHANGED
|
@@ -2,7 +2,13 @@ import { AbstractSqlConnection, type TransactionEventBroadcaster } from '@mikro-
|
|
|
2
2
|
import { type ControlledTransaction, MssqlDialect } from 'kysely';
|
|
3
3
|
import { type Routine, type Transaction } from '@mikro-orm/core';
|
|
4
4
|
import type { ConnectionConfiguration } from 'tedious';
|
|
5
|
-
/**
|
|
5
|
+
/**
|
|
6
|
+
* Microsoft SQL Server database connection using the `tedious` driver.
|
|
7
|
+
*
|
|
8
|
+
* There is no `getNativeClient()` here: tedious has no long-lived client object, and the pool
|
|
9
|
+
* kysely builds holds its own connection wrappers rather than tedious ones. Reach individual
|
|
10
|
+
* `Tedious.Connection`s through the `onCreateConnection`/`onReserveConnection` hooks instead.
|
|
11
|
+
*/
|
|
6
12
|
export declare class MsSqlConnection extends AbstractSqlConnection {
|
|
7
13
|
createKyselyDialect(overrides: ConnectionConfiguration): MssqlDialect;
|
|
8
14
|
private mapOptions;
|
package/MsSqlConnection.js
CHANGED
|
@@ -28,7 +28,13 @@ class MsSqlReserveDialect extends MssqlDialect {
|
|
|
28
28
|
return driver;
|
|
29
29
|
}
|
|
30
30
|
}
|
|
31
|
-
/**
|
|
31
|
+
/**
|
|
32
|
+
* Microsoft SQL Server database connection using the `tedious` driver.
|
|
33
|
+
*
|
|
34
|
+
* There is no `getNativeClient()` here: tedious has no long-lived client object, and the pool
|
|
35
|
+
* kysely builds holds its own connection wrappers rather than tedious ones. Reach individual
|
|
36
|
+
* `Tedious.Connection`s through the `onCreateConnection`/`onReserveConnection` hooks instead.
|
|
37
|
+
*/
|
|
32
38
|
export class MsSqlConnection extends AbstractSqlConnection {
|
|
33
39
|
createKyselyDialect(overrides) {
|
|
34
40
|
const options = this.mapOptions(overrides);
|
package/MsSqlPlatform.d.ts
CHANGED
|
@@ -52,6 +52,8 @@ export declare class MsSqlPlatform extends AbstractSqlPlatform {
|
|
|
52
52
|
}): string;
|
|
53
53
|
getDefaultMappedType(type: string): Type<unknown>;
|
|
54
54
|
getDefaultSchemaName(): string | undefined;
|
|
55
|
+
getDefaultPrimaryName(tableName: string, columns: string[]): string;
|
|
56
|
+
supportsCustomPrimaryKeyNames(): boolean;
|
|
55
57
|
getUuidTypeDeclarationSQL(column: {
|
|
56
58
|
length?: number;
|
|
57
59
|
}): string;
|
package/MsSqlPlatform.js
CHANGED
|
@@ -139,6 +139,12 @@ export class MsSqlPlatform extends AbstractSqlPlatform {
|
|
|
139
139
|
getDefaultSchemaName() {
|
|
140
140
|
return 'dbo';
|
|
141
141
|
}
|
|
142
|
+
getDefaultPrimaryName(tableName, columns) {
|
|
143
|
+
return this.getIndexName(tableName, columns, 'primary');
|
|
144
|
+
}
|
|
145
|
+
supportsCustomPrimaryKeyNames() {
|
|
146
|
+
return true;
|
|
147
|
+
}
|
|
142
148
|
getUuidTypeDeclarationSQL(column) {
|
|
143
149
|
return 'uniqueidentifier';
|
|
144
150
|
}
|
|
@@ -223,18 +229,19 @@ export class MsSqlPlatform extends AbstractSqlPlatform {
|
|
|
223
229
|
return collation;
|
|
224
230
|
}
|
|
225
231
|
getOrderByExpression(column, direction, collation) {
|
|
232
|
+
const dir = this.validateOrderByDirection(direction);
|
|
226
233
|
const col = collation ? `${column} collate ${this.quoteCollation(collation)}` : column;
|
|
227
|
-
switch (
|
|
228
|
-
case QueryOrder.
|
|
234
|
+
switch (dir) {
|
|
235
|
+
case QueryOrder.asc_nulls_first:
|
|
229
236
|
return [`case when ${column} is null then 0 else 1 end, ${col} asc`];
|
|
230
|
-
case QueryOrder.
|
|
237
|
+
case QueryOrder.asc_nulls_last:
|
|
231
238
|
return [`case when ${column} is null then 1 else 0 end, ${col} asc`];
|
|
232
|
-
case QueryOrder.
|
|
239
|
+
case QueryOrder.desc_nulls_first:
|
|
233
240
|
return [`case when ${column} is null then 0 else 1 end, ${col} desc`];
|
|
234
|
-
case QueryOrder.
|
|
241
|
+
case QueryOrder.desc_nulls_last:
|
|
235
242
|
return [`case when ${column} is null then 1 else 0 end, ${col} desc`];
|
|
236
243
|
default:
|
|
237
|
-
return [`${col} ${
|
|
244
|
+
return [`${col} ${dir}`];
|
|
238
245
|
}
|
|
239
246
|
}
|
|
240
247
|
getDefaultClientUrl() {
|
|
@@ -8,4 +8,5 @@ export declare class MsSqlSchemaGenerator extends SchemaGenerator {
|
|
|
8
8
|
}): Promise<void>;
|
|
9
9
|
clear(options?: ClearDatabaseOptions): Promise<void>;
|
|
10
10
|
getDropSchemaSQL(options?: Omit<DropSchemaOptions, 'dropDb'>): Promise<string>;
|
|
11
|
+
protected startsBatch(statement: string): boolean;
|
|
11
12
|
}
|
package/MsSqlSchemaGenerator.js
CHANGED
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
import { SchemaGenerator } from '@mikro-orm/sql';
|
|
2
|
+
/** MSSQL rejects these unless they are the first statement in a query batch. */
|
|
3
|
+
const BATCH_FIRST_STATEMENT = /^create\s+(or\s+alter\s+)?(trigger|view|proc(edure)?|function|schema)\b/i;
|
|
2
4
|
/** Schema generator with MSSQL-specific behavior for clearing and dropping schemas. */
|
|
3
5
|
export class MsSqlSchemaGenerator extends SchemaGenerator {
|
|
4
6
|
static register(orm) {
|
|
@@ -40,4 +42,7 @@ export class MsSqlSchemaGenerator extends SchemaGenerator {
|
|
|
40
42
|
async getDropSchemaSQL(options = {}) {
|
|
41
43
|
return super.getDropSchemaSQL({ dropForeignKeys: true, ...options });
|
|
42
44
|
}
|
|
45
|
+
startsBatch(statement) {
|
|
46
|
+
return BATCH_FIRST_STATEMENT.test(statement);
|
|
47
|
+
}
|
|
43
48
|
}
|
package/MsSqlSchemaHelper.d.ts
CHANGED
|
@@ -51,6 +51,7 @@ export declare class MsSqlSchemaHelper extends SchemaHelper {
|
|
|
51
51
|
private getDropDefaultsSQL;
|
|
52
52
|
getRenameColumnSQL(tableName: string, oldColumnName: string, to: Column, schemaName?: string): string;
|
|
53
53
|
createTableColumn(column: Column, table: DatabaseTable, changedProperties?: Set<string>): string | undefined;
|
|
54
|
+
protected getPrimaryKeyConstraintPrefix(table: DatabaseTable, index: IndexDef): string;
|
|
54
55
|
alterTableColumn(column: Column, table: DatabaseTable, changedProperties: Set<string>): string[];
|
|
55
56
|
getCreateIndexSQL(tableName: string, index: IndexDef, partialExpression?: boolean): string;
|
|
56
57
|
/**
|
|
@@ -67,6 +68,10 @@ export declare class MsSqlSchemaHelper extends SchemaHelper {
|
|
|
67
68
|
dropViewIfExists(name: string, schema?: string): string;
|
|
68
69
|
getAddColumnsSQL(table: DatabaseTable, columns: Column[]): string[];
|
|
69
70
|
appendComments(table: DatabaseTable): string[];
|
|
71
|
+
alterTableComment(table: DatabaseTable, comment?: string): string;
|
|
72
|
+
getChangeColumnCommentSQL(tableName: string, to: Column, schemaName?: string): string;
|
|
73
|
+
/** Comments are stored as `MS_Description` extended properties, which have separate add/update/drop procedures. */
|
|
74
|
+
private getCommentSQL;
|
|
70
75
|
inferLengthFromColumnType(type: string): number | undefined;
|
|
71
76
|
protected wrap(val: string | undefined, type: Type<unknown>): string | undefined;
|
|
72
77
|
}
|
package/MsSqlSchemaHelper.js
CHANGED
|
@@ -347,7 +347,7 @@ export class MsSqlSchemaHelper extends SchemaHelper {
|
|
|
347
347
|
const timing = trigger.timing.toUpperCase();
|
|
348
348
|
const events = trigger.events.map(e => e.toUpperCase()).join(', ');
|
|
349
349
|
const qualifiedName = this.getSchemaQualifiedName(table, trigger.name);
|
|
350
|
-
return `create trigger ${qualifiedName} on ${table.getQuotedName()} ${timing} ${events} as begin ${trigger.body}
|
|
350
|
+
return `create trigger ${qualifiedName} on ${table.getQuotedName()} ${timing} ${events} as begin ${this.normalizeTriggerBody(trigger.body)} end`;
|
|
351
351
|
}
|
|
352
352
|
/** Generates SQL to drop an MSSQL trigger. */
|
|
353
353
|
dropTrigger(table, trigger) {
|
|
@@ -400,6 +400,7 @@ export class MsSqlSchemaHelper extends SchemaHelper {
|
|
|
400
400
|
on ep.major_id = o.object_id and ep.minor_id = 0 and ep.name = 'MS_Description'
|
|
401
401
|
where o.type in ('P', 'FN', 'IF', 'TF')
|
|
402
402
|
and o.is_ms_shipped = 0
|
|
403
|
+
order by s.name, o.name
|
|
403
404
|
`;
|
|
404
405
|
const [rows, paramsAndReturns] = await Promise.all([
|
|
405
406
|
connection.execute(sql),
|
|
@@ -669,7 +670,8 @@ export class MsSqlSchemaHelper extends SchemaHelper {
|
|
|
669
670
|
!column.generated &&
|
|
670
671
|
!compositePK &&
|
|
671
672
|
(!changedProperties || changedProperties.has('autoincrement') || changedProperties.has('type'))) {
|
|
672
|
-
|
|
673
|
+
const primaryKeyName = this.platform.getDefaultPrimaryName(table.name, [column.name]);
|
|
674
|
+
Utils.runIfNotEmpty(() => col.push(`constraint ${this.quote(primaryKeyName)} primary key`), primaryKey && column.primary);
|
|
673
675
|
}
|
|
674
676
|
const useDefault = changedProperties
|
|
675
677
|
? false
|
|
@@ -678,6 +680,10 @@ export class MsSqlSchemaHelper extends SchemaHelper {
|
|
|
678
680
|
Utils.runIfNotEmpty(() => col.push(`constraint ${this.quote(defaultName)} default ${column.default}`), useDefault);
|
|
679
681
|
return col.join(' ');
|
|
680
682
|
}
|
|
683
|
+
// SQL Server generates a random `PK__…` name when the constraint is unnamed, so always name it
|
|
684
|
+
getPrimaryKeyConstraintPrefix(table, index) {
|
|
685
|
+
return `constraint ${this.quote(index.keyName)} `;
|
|
686
|
+
}
|
|
681
687
|
alterTableColumn(column, table, changedProperties) {
|
|
682
688
|
const parts = [];
|
|
683
689
|
if (changedProperties.has('default')) {
|
|
@@ -793,31 +799,49 @@ export class MsSqlSchemaHelper extends SchemaHelper {
|
|
|
793
799
|
return this.createTableColumn(column, table);
|
|
794
800
|
})
|
|
795
801
|
.join(', ');
|
|
796
|
-
|
|
802
|
+
const sql = [`alter table ${table.getQuotedName()} add ${adds}`];
|
|
803
|
+
for (const column of columns) {
|
|
804
|
+
if (column.comment) {
|
|
805
|
+
sql.push(this.getCommentSQL(table.schema, table.name, column.comment, column.name));
|
|
806
|
+
}
|
|
807
|
+
}
|
|
808
|
+
return sql;
|
|
797
809
|
}
|
|
798
810
|
appendComments(table) {
|
|
799
811
|
const sql = [];
|
|
800
|
-
const schema = this.platform.quoteValue(table.schema);
|
|
801
|
-
const tableName = this.platform.quoteValue(table.name);
|
|
802
812
|
if (table.comment) {
|
|
803
|
-
|
|
804
|
-
sql.push(`if exists(select * from sys.fn_listextendedproperty(N'MS_Description', N'Schema', N${schema}, N'Table', N${tableName}, null, null))
|
|
805
|
-
exec sys.sp_updateextendedproperty N'MS_Description', N${comment}, N'Schema', N${schema}, N'Table', N${tableName}
|
|
806
|
-
else
|
|
807
|
-
exec sys.sp_addextendedproperty N'MS_Description', N${comment}, N'Schema', N${schema}, N'Table', N${tableName}`);
|
|
813
|
+
sql.push(this.getCommentSQL(table.schema, table.name, table.comment));
|
|
808
814
|
}
|
|
809
815
|
for (const column of table.getColumns()) {
|
|
810
816
|
if (column.comment) {
|
|
811
|
-
|
|
812
|
-
const columnName = this.platform.quoteValue(column.name);
|
|
813
|
-
sql.push(`if exists(select * from sys.fn_listextendedproperty(N'MS_Description', N'Schema', N${schema}, N'Table', N${tableName}, N'Column', N${columnName}))
|
|
814
|
-
exec sys.sp_updateextendedproperty N'MS_Description', N${comment}, N'Schema', N${schema}, N'Table', N${tableName}, N'Column', N${columnName}
|
|
815
|
-
else
|
|
816
|
-
exec sys.sp_addextendedproperty N'MS_Description', N${comment}, N'Schema', N${schema}, N'Table', N${tableName}, N'Column', N${columnName}`);
|
|
817
|
+
sql.push(this.getCommentSQL(table.schema, table.name, column.comment, column.name));
|
|
817
818
|
}
|
|
818
819
|
}
|
|
819
820
|
return sql;
|
|
820
821
|
}
|
|
822
|
+
alterTableComment(table, comment) {
|
|
823
|
+
return this.getCommentSQL(table.schema, table.name, comment);
|
|
824
|
+
}
|
|
825
|
+
getChangeColumnCommentSQL(tableName, to, schemaName) {
|
|
826
|
+
return this.getCommentSQL(schemaName, tableName, to.comment, to.name);
|
|
827
|
+
}
|
|
828
|
+
/** Comments are stored as `MS_Description` extended properties, which have separate add/update/drop procedures. */
|
|
829
|
+
getCommentSQL(schemaName, tableName, comment, columnName) {
|
|
830
|
+
const schema = this.platform.quoteValue(schemaName ?? this.platform.getDefaultSchemaName());
|
|
831
|
+
const table = this.platform.quoteValue(tableName);
|
|
832
|
+
const level1 = `N'Schema', N${schema}, N'Table', N${table}`;
|
|
833
|
+
const level2 = columnName ? `N'Column', N${this.platform.quoteValue(columnName)}` : '';
|
|
834
|
+
const exists = `if exists(select * from sys.fn_listextendedproperty(N'MS_Description', ${level1}, ${level2 || 'null, null'}))`;
|
|
835
|
+
const target = level2 ? `${level1}, ${level2}` : level1;
|
|
836
|
+
if (!comment) {
|
|
837
|
+
return `${exists}\n exec sys.sp_dropextendedproperty N'MS_Description', ${target}`;
|
|
838
|
+
}
|
|
839
|
+
const value = this.platform.quoteValue(comment);
|
|
840
|
+
return `${exists}
|
|
841
|
+
exec sys.sp_updateextendedproperty N'MS_Description', N${value}, ${target}
|
|
842
|
+
else
|
|
843
|
+
exec sys.sp_addextendedproperty N'MS_Description', N${value}, ${target}`;
|
|
844
|
+
}
|
|
821
845
|
inferLengthFromColumnType(type) {
|
|
822
846
|
const match = /^(\w+)\s*\(\s*(-?\d+|max)\s*\)/.exec(type);
|
|
823
847
|
if (!match) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mikro-orm/mssql",
|
|
3
|
-
"version": "7.2.0-dev.
|
|
3
|
+
"version": "7.2.0-dev.10",
|
|
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
|
"keywords": [
|
|
6
6
|
"data-mapper",
|
|
@@ -47,17 +47,17 @@
|
|
|
47
47
|
"copy": "node ../../scripts/copy.mjs"
|
|
48
48
|
},
|
|
49
49
|
"dependencies": {
|
|
50
|
-
"@mikro-orm/sql": "7.2.0-dev.
|
|
51
|
-
"kysely": "0.29.
|
|
50
|
+
"@mikro-orm/sql": "7.2.0-dev.10",
|
|
51
|
+
"kysely": "0.29.5",
|
|
52
52
|
"tarn": "3.1.2",
|
|
53
53
|
"tedious": "20.0.0",
|
|
54
54
|
"tsqlstring": "1.0.1"
|
|
55
55
|
},
|
|
56
56
|
"devDependencies": {
|
|
57
|
-
"@mikro-orm/core": "^7.1.
|
|
57
|
+
"@mikro-orm/core": "^7.1.11"
|
|
58
58
|
},
|
|
59
59
|
"peerDependencies": {
|
|
60
|
-
"@mikro-orm/core": "7.2.0-dev.
|
|
60
|
+
"@mikro-orm/core": "7.2.0-dev.10"
|
|
61
61
|
},
|
|
62
62
|
"engines": {
|
|
63
63
|
"node": ">= 22.17.0"
|