@mikro-orm/sql 7.0.0-dev.97 → 7.0.0-dev.98

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.
Files changed (91) hide show
  1. package/AbstractSqlConnection.d.ts +56 -0
  2. package/AbstractSqlConnection.js +232 -0
  3. package/AbstractSqlDriver.d.ts +94 -0
  4. package/AbstractSqlDriver.js +1387 -0
  5. package/AbstractSqlPlatform.d.ts +38 -0
  6. package/AbstractSqlPlatform.js +104 -0
  7. package/LICENSE +21 -0
  8. package/PivotCollectionPersister.d.ts +22 -0
  9. package/PivotCollectionPersister.js +159 -0
  10. package/README.md +390 -0
  11. package/SqlEntityManager.d.ts +33 -0
  12. package/SqlEntityManager.js +44 -0
  13. package/SqlEntityRepository.d.ts +19 -0
  14. package/SqlEntityRepository.js +26 -0
  15. package/dialects/index.d.ts +4 -0
  16. package/dialects/index.js +4 -0
  17. package/dialects/mssql/MsSqlNativeQueryBuilder.d.ts +14 -0
  18. package/dialects/mssql/MsSqlNativeQueryBuilder.js +200 -0
  19. package/dialects/mssql/index.d.ts +1 -0
  20. package/dialects/mssql/index.js +1 -0
  21. package/dialects/mysql/MySqlExceptionConverter.d.ts +9 -0
  22. package/dialects/mysql/MySqlExceptionConverter.js +80 -0
  23. package/dialects/mysql/MySqlNativeQueryBuilder.d.ts +7 -0
  24. package/dialects/mysql/MySqlNativeQueryBuilder.js +77 -0
  25. package/dialects/mysql/MySqlPlatform.d.ts +45 -0
  26. package/dialects/mysql/MySqlPlatform.js +116 -0
  27. package/dialects/mysql/MySqlSchemaHelper.d.ts +36 -0
  28. package/dialects/mysql/MySqlSchemaHelper.js +269 -0
  29. package/dialects/mysql/index.d.ts +4 -0
  30. package/dialects/mysql/index.js +4 -0
  31. package/dialects/postgresql/PostgreSqlNativeQueryBuilder.d.ts +5 -0
  32. package/dialects/postgresql/PostgreSqlNativeQueryBuilder.js +8 -0
  33. package/dialects/postgresql/PostgreSqlTableCompiler.d.ts +1 -0
  34. package/dialects/postgresql/PostgreSqlTableCompiler.js +1 -0
  35. package/dialects/postgresql/index.d.ts +1 -0
  36. package/dialects/postgresql/index.js +1 -0
  37. package/dialects/sqlite/BaseSqliteConnection.d.ts +6 -0
  38. package/dialects/sqlite/BaseSqliteConnection.js +8 -0
  39. package/dialects/sqlite/BaseSqlitePlatform.d.ts +70 -0
  40. package/dialects/sqlite/BaseSqlitePlatform.js +104 -0
  41. package/dialects/sqlite/SqliteExceptionConverter.d.ts +9 -0
  42. package/dialects/sqlite/SqliteExceptionConverter.js +54 -0
  43. package/dialects/sqlite/SqliteNativeQueryBuilder.d.ts +6 -0
  44. package/dialects/sqlite/SqliteNativeQueryBuilder.js +11 -0
  45. package/dialects/sqlite/SqliteSchemaHelper.d.ts +38 -0
  46. package/dialects/sqlite/SqliteSchemaHelper.js +379 -0
  47. package/dialects/sqlite/index.d.ts +5 -0
  48. package/dialects/sqlite/index.js +5 -0
  49. package/index.d.ts +19 -0
  50. package/index.js +19 -0
  51. package/package.json +3 -3
  52. package/plugin/index.d.ts +53 -0
  53. package/plugin/index.js +42 -0
  54. package/plugin/transformer.d.ts +115 -0
  55. package/plugin/transformer.js +883 -0
  56. package/query/ArrayCriteriaNode.d.ts +11 -0
  57. package/query/ArrayCriteriaNode.js +24 -0
  58. package/query/CriteriaNode.d.ts +29 -0
  59. package/query/CriteriaNode.js +121 -0
  60. package/query/CriteriaNodeFactory.d.ts +12 -0
  61. package/query/CriteriaNodeFactory.js +90 -0
  62. package/query/NativeQueryBuilder.d.ts +108 -0
  63. package/query/NativeQueryBuilder.js +425 -0
  64. package/query/ObjectCriteriaNode.d.ts +19 -0
  65. package/query/ObjectCriteriaNode.js +249 -0
  66. package/query/QueryBuilder.d.ts +389 -0
  67. package/query/QueryBuilder.js +1558 -0
  68. package/query/QueryBuilderHelper.d.ts +73 -0
  69. package/query/QueryBuilderHelper.js +756 -0
  70. package/query/ScalarCriteriaNode.d.ts +10 -0
  71. package/query/ScalarCriteriaNode.js +49 -0
  72. package/query/enums.d.ts +18 -0
  73. package/query/enums.js +20 -0
  74. package/query/index.d.ts +10 -0
  75. package/query/index.js +10 -0
  76. package/query/raw.d.ts +59 -0
  77. package/query/raw.js +68 -0
  78. package/schema/DatabaseSchema.d.ts +45 -0
  79. package/schema/DatabaseSchema.js +185 -0
  80. package/schema/DatabaseTable.d.ts +68 -0
  81. package/schema/DatabaseTable.js +793 -0
  82. package/schema/SchemaComparator.d.ts +58 -0
  83. package/schema/SchemaComparator.js +577 -0
  84. package/schema/SchemaHelper.d.ts +76 -0
  85. package/schema/SchemaHelper.js +545 -0
  86. package/schema/SqlSchemaGenerator.d.ts +65 -0
  87. package/schema/SqlSchemaGenerator.js +375 -0
  88. package/schema/index.d.ts +5 -0
  89. package/schema/index.js +5 -0
  90. package/typings.d.ts +272 -0
  91. package/typings.js +1 -0
@@ -0,0 +1,200 @@
1
+ import { LockMode, QueryFlag, RawQueryFragment, Utils } from '@mikro-orm/core';
2
+ import { NativeQueryBuilder } from '../../query/NativeQueryBuilder.js';
3
+ import { QueryType } from '../../query/enums.js';
4
+ /** @internal */
5
+ export class MsSqlNativeQueryBuilder extends NativeQueryBuilder {
6
+ compile() {
7
+ if (!this.type) {
8
+ throw new Error('No query type provided');
9
+ }
10
+ this.parts.length = 0;
11
+ this.params.length = 0;
12
+ if (this.options.flags?.has(QueryFlag.IDENTITY_INSERT)) {
13
+ this.parts.push(`set identity_insert ${this.getTableName()} on;`);
14
+ }
15
+ const { prefix, suffix } = this.appendOutputTable();
16
+ if (prefix) {
17
+ this.parts.push(prefix);
18
+ }
19
+ if (this.options.comment) {
20
+ this.parts.push(...this.options.comment.map(comment => `/* ${comment} */`));
21
+ }
22
+ if (this.options.onConflict && !Utils.isEmpty(Utils.asArray(this.options.data)[0])) {
23
+ this.compileUpsert();
24
+ }
25
+ else {
26
+ switch (this.type) {
27
+ case QueryType.SELECT:
28
+ case QueryType.COUNT:
29
+ this.compileSelect();
30
+ break;
31
+ case QueryType.INSERT:
32
+ this.compileInsert();
33
+ break;
34
+ case QueryType.UPDATE:
35
+ this.compileUpdate();
36
+ break;
37
+ case QueryType.DELETE:
38
+ this.compileDelete();
39
+ break;
40
+ case QueryType.TRUNCATE:
41
+ this.compileTruncate();
42
+ break;
43
+ }
44
+ if (suffix) {
45
+ this.parts[this.parts.length - 1] += ';';
46
+ this.parts.push(suffix);
47
+ }
48
+ else if ([QueryType.INSERT, QueryType.UPDATE, QueryType.DELETE].includes(this.type)) {
49
+ this.parts[this.parts.length - 1] += '; select @@rowcount;';
50
+ }
51
+ }
52
+ if (this.options.flags?.has(QueryFlag.IDENTITY_INSERT)) {
53
+ this.parts.push(`set identity_insert ${this.getTableName()} off;`);
54
+ }
55
+ return this.combineParts();
56
+ }
57
+ compileInsert() {
58
+ if (!this.options.data) {
59
+ throw new Error('No data provided');
60
+ }
61
+ this.parts.push('insert');
62
+ this.addHintComment();
63
+ this.parts.push(`into ${this.getTableName()}`);
64
+ if (Object.keys(this.options.data).length === 0) {
65
+ this.addOutputClause('inserted');
66
+ this.parts.push('default values');
67
+ return;
68
+ }
69
+ const parts = this.processInsertData();
70
+ if (this.options.flags?.has(QueryFlag.OUTPUT_TABLE)) {
71
+ this.parts[this.parts.length - 2] += ' into #out ';
72
+ }
73
+ this.parts.push(parts.join(', '));
74
+ }
75
+ appendOutputTable() {
76
+ if (!this.options.flags?.has(QueryFlag.OUTPUT_TABLE)) {
77
+ return { prefix: '', suffix: '' };
78
+ }
79
+ const returningFields = this.options.returning;
80
+ const selections = returningFields
81
+ .map(field => `[t].${this.platform.quoteIdentifier(field)}`)
82
+ .join(',');
83
+ return {
84
+ prefix: `select top(0) ${selections} into #out from ${this.getTableName()} as t left join ${this.getTableName()} on 0 = 1;`,
85
+ suffix: `select ${selections} from #out as t; drop table #out`,
86
+ };
87
+ }
88
+ compileUpsert() {
89
+ const clause = this.options.onConflict;
90
+ const dataAsArray = Utils.asArray(this.options.data);
91
+ const keys = Object.keys(dataAsArray[0]);
92
+ const values = keys.map(() => '?');
93
+ const parts = [];
94
+ for (const data of dataAsArray) {
95
+ for (const key of keys) {
96
+ this.params.push(data[key]);
97
+ }
98
+ parts.push(`(${values.join(', ')})`);
99
+ }
100
+ this.parts.push(`merge into ${this.getTableName()}`);
101
+ this.parts.push(`using (values ${parts.join(', ')}) as tsource(${keys.map(key => this.quote(key)).join(', ')})`);
102
+ if (clause.fields instanceof RawQueryFragment) {
103
+ this.parts.push(clause.fields.sql);
104
+ this.params.push(...clause.fields.params);
105
+ }
106
+ else if (clause.fields.length > 0) {
107
+ const fields = clause.fields.map(field => {
108
+ const col = this.quote(field);
109
+ return `${this.getTableName()}.${col} = tsource.${col}`;
110
+ });
111
+ this.parts.push(`on ${fields.join(' and ')}`);
112
+ }
113
+ const sourceColumns = keys.map(field => `tsource.${this.quote(field)}`).join(', ');
114
+ const destinationColumns = keys.map(field => this.quote(field)).join(', ');
115
+ this.parts.push(`when not matched then insert (${destinationColumns}) values (${sourceColumns})`);
116
+ if (!clause.ignore) {
117
+ this.parts.push('when matched');
118
+ if (clause.where) {
119
+ this.parts.push(`and ${clause.where.sql}`);
120
+ this.params.push(...clause.where.params);
121
+ }
122
+ this.parts.push('then update set');
123
+ if (!clause.merge || Array.isArray(clause.merge)) {
124
+ const parts = (clause.merge || keys)
125
+ .filter(field => !Array.isArray(clause.fields) || !clause.fields.includes(field))
126
+ .map((column) => `${this.quote(column)} = tsource.${this.quote(column)}`);
127
+ this.parts.push(parts.join(', '));
128
+ }
129
+ else if (typeof clause.merge === 'object') {
130
+ const parts = Object.entries(clause.merge).map(([key, value]) => {
131
+ this.params.push(value);
132
+ return `${this.getTableName()}.${this.quote(key)} = ?`;
133
+ });
134
+ this.parts.push(parts.join(', '));
135
+ }
136
+ }
137
+ this.addOutputClause('inserted');
138
+ this.parts[this.parts.length - 1] += ';';
139
+ }
140
+ compileSelect() {
141
+ this.parts.push('select');
142
+ if (this.options.limit != null && this.options.offset == null) {
143
+ this.parts.push(`top (?)`);
144
+ this.params.push(this.options.limit);
145
+ }
146
+ this.addHintComment();
147
+ this.parts.push(`${this.getFields()} from ${this.getTableName()}`);
148
+ this.addLockClause();
149
+ if (this.options.joins) {
150
+ for (const join of this.options.joins) {
151
+ this.parts.push(join.sql);
152
+ this.params.push(...join.params);
153
+ }
154
+ }
155
+ if (this.options.where?.sql.trim()) {
156
+ this.parts.push(`where ${this.options.where.sql}`);
157
+ this.params.push(...this.options.where.params);
158
+ }
159
+ if (this.options.groupBy) {
160
+ const fields = this.options.groupBy.map(field => this.quote(field));
161
+ this.parts.push(`group by ${fields.join(', ')}`);
162
+ }
163
+ if (this.options.having) {
164
+ this.parts.push(`having ${this.options.having.sql}`);
165
+ this.params.push(...this.options.having.params);
166
+ }
167
+ if (this.options.orderBy) {
168
+ this.parts.push(`order by ${this.options.orderBy}`);
169
+ }
170
+ if (this.options.offset != null) {
171
+ /* v8 ignore next */
172
+ if (!this.options.orderBy) {
173
+ throw new Error('Order by clause is required for pagination');
174
+ }
175
+ this.parts.push(`offset ? rows`);
176
+ this.params.push(this.options.offset);
177
+ if (this.options.limit != null) {
178
+ this.parts.push(`fetch next ? rows only`);
179
+ this.params.push(this.options.limit);
180
+ }
181
+ }
182
+ }
183
+ addLockClause() {
184
+ if (!this.options.lockMode || ![LockMode.PESSIMISTIC_READ, LockMode.PESSIMISTIC_WRITE].includes(this.options.lockMode)) {
185
+ return;
186
+ }
187
+ const map = {
188
+ [LockMode.PESSIMISTIC_READ]: 'with (holdlock)',
189
+ [LockMode.PESSIMISTIC_WRITE]: 'with (updlock)',
190
+ };
191
+ if (this.options.lockMode !== LockMode.OPTIMISTIC) {
192
+ this.parts.push(map[this.options.lockMode]);
193
+ }
194
+ }
195
+ compileTruncate() {
196
+ const tableName = this.getTableName();
197
+ const sql = `delete from ${tableName}; declare @count int = case @@rowcount when 0 then 1 else 0 end; dbcc checkident ('${tableName.replace(/[[\]]/g, '')}', reseed, @count)`;
198
+ this.parts.push(sql);
199
+ }
200
+ }
@@ -0,0 +1 @@
1
+ export * from './MsSqlNativeQueryBuilder.js';
@@ -0,0 +1 @@
1
+ export * from './MsSqlNativeQueryBuilder.js';
@@ -0,0 +1,9 @@
1
+ import { ExceptionConverter, type Dictionary, type DriverException } from '@mikro-orm/core';
2
+ export declare class MySqlExceptionConverter extends ExceptionConverter {
3
+ /**
4
+ * @see http://dev.mysql.com/doc/refman/5.7/en/error-messages-client.html
5
+ * @see http://dev.mysql.com/doc/refman/5.7/en/error-messages-server.html
6
+ * @see https://github.com/doctrine/dbal/blob/master/src/Driver/AbstractMySQLDriver.php
7
+ */
8
+ convertException(exception: Error & Dictionary): DriverException;
9
+ }
@@ -0,0 +1,80 @@
1
+ import { DeadlockException, LockWaitTimeoutException, TableExistsException, TableNotFoundException, ForeignKeyConstraintViolationException, UniqueConstraintViolationException, InvalidFieldNameException, NonUniqueFieldNameException, SyntaxErrorException, ConnectionException, NotNullConstraintViolationException, ExceptionConverter, CheckConstraintViolationException, } from '@mikro-orm/core';
2
+ export class MySqlExceptionConverter extends ExceptionConverter {
3
+ /**
4
+ * @see http://dev.mysql.com/doc/refman/5.7/en/error-messages-client.html
5
+ * @see http://dev.mysql.com/doc/refman/5.7/en/error-messages-server.html
6
+ * @see https://github.com/doctrine/dbal/blob/master/src/Driver/AbstractMySQLDriver.php
7
+ */
8
+ convertException(exception) {
9
+ /* v8 ignore next */
10
+ switch (exception.errno) {
11
+ case 1213:
12
+ return new DeadlockException(exception);
13
+ case 1205:
14
+ return new LockWaitTimeoutException(exception);
15
+ case 1050:
16
+ return new TableExistsException(exception);
17
+ case 1051:
18
+ case 1146:
19
+ return new TableNotFoundException(exception);
20
+ case 1216:
21
+ case 1217:
22
+ case 1451:
23
+ case 1452:
24
+ case 1701:
25
+ return new ForeignKeyConstraintViolationException(exception);
26
+ case 3819:
27
+ case 4025:
28
+ return new CheckConstraintViolationException(exception);
29
+ case 1062:
30
+ case 1557:
31
+ case 1569:
32
+ case 1586:
33
+ return new UniqueConstraintViolationException(exception);
34
+ case 1054:
35
+ case 1166:
36
+ case 1611:
37
+ return new InvalidFieldNameException(exception);
38
+ case 1052:
39
+ case 1060:
40
+ case 1110:
41
+ return new NonUniqueFieldNameException(exception);
42
+ case 1064:
43
+ case 1149:
44
+ case 1287:
45
+ case 1341:
46
+ case 1342:
47
+ case 1343:
48
+ case 1344:
49
+ case 1382:
50
+ case 1479:
51
+ case 1541:
52
+ case 1554:
53
+ case 1626:
54
+ return new SyntaxErrorException(exception);
55
+ case 1044:
56
+ case 1045:
57
+ case 1046:
58
+ case 1049:
59
+ case 1095:
60
+ case 1142:
61
+ case 1143:
62
+ case 1227:
63
+ case 1370:
64
+ case 1429:
65
+ case 2002:
66
+ case 2005:
67
+ return new ConnectionException(exception);
68
+ case 1048:
69
+ case 1121:
70
+ case 1138:
71
+ case 1171:
72
+ case 1252:
73
+ case 1263:
74
+ case 1364:
75
+ case 1566:
76
+ return new NotNullConstraintViolationException(exception);
77
+ }
78
+ return super.convertException(exception);
79
+ }
80
+ }
@@ -0,0 +1,7 @@
1
+ import { NativeQueryBuilder } from '../../query/NativeQueryBuilder.js';
2
+ /** @internal */
3
+ export declare class MySqlNativeQueryBuilder extends NativeQueryBuilder {
4
+ protected compileInsert(): void;
5
+ protected addLockClause(): void;
6
+ protected addOnConflictClause(): void;
7
+ }
@@ -0,0 +1,77 @@
1
+ import { LockMode, RawQueryFragment, Utils } from '@mikro-orm/core';
2
+ import { NativeQueryBuilder } from '../../query/NativeQueryBuilder.js';
3
+ /** @internal */
4
+ export class MySqlNativeQueryBuilder extends NativeQueryBuilder {
5
+ compileInsert() {
6
+ if (!this.options.data) {
7
+ throw new Error('No data provided');
8
+ }
9
+ this.parts.push('insert');
10
+ if (this.options.onConflict?.ignore) {
11
+ this.parts.push('ignore');
12
+ }
13
+ this.addHintComment();
14
+ this.parts.push(`into ${this.getTableName()}`);
15
+ if (Object.keys(this.options.data).length === 0) {
16
+ this.parts.push('default values');
17
+ return;
18
+ }
19
+ const parts = this.processInsertData();
20
+ this.parts.push(parts.join(', '));
21
+ }
22
+ addLockClause() {
23
+ if (!this.options.lockMode) {
24
+ return;
25
+ }
26
+ const map = {
27
+ [LockMode.PESSIMISTIC_READ]: 'lock in share mode',
28
+ [LockMode.PESSIMISTIC_WRITE]: 'for update',
29
+ [LockMode.PESSIMISTIC_PARTIAL_WRITE]: 'for update skip locked',
30
+ [LockMode.PESSIMISTIC_WRITE_OR_FAIL]: 'for update nowait',
31
+ [LockMode.PESSIMISTIC_PARTIAL_READ]: 'lock in share mode skip locked',
32
+ [LockMode.PESSIMISTIC_READ_OR_FAIL]: 'lock in share mode nowait',
33
+ };
34
+ if (this.options.lockMode !== LockMode.OPTIMISTIC) {
35
+ this.parts.push(map[this.options.lockMode]);
36
+ }
37
+ }
38
+ addOnConflictClause() {
39
+ const clause = this.options.onConflict;
40
+ if (!clause || clause.ignore) {
41
+ return;
42
+ }
43
+ if (clause.merge) {
44
+ this.parts.push('on duplicate key update');
45
+ if (Utils.isObject(clause.merge)) {
46
+ const fields = Object.keys(clause.merge).map(field => {
47
+ this.params.push(clause.merge[field]);
48
+ return `${this.quote(field)} = ?`;
49
+ });
50
+ this.parts.push(fields.join(', '));
51
+ }
52
+ else if (clause.merge.length === 0) {
53
+ const dataAsArray = Utils.asArray(this.options.data);
54
+ const keys = Object.keys(dataAsArray[0]);
55
+ this.parts.push(keys.map(key => `${this.quote(key)} = values(${this.quote(key)})`).join(', '));
56
+ }
57
+ else {
58
+ const fields = clause.merge.map(key => `${this.quote(key)} = values(${this.quote(key)})`);
59
+ this.parts.push(fields.join(', '));
60
+ }
61
+ if (clause.where) {
62
+ this.parts.push(`where ${clause.where.sql}`);
63
+ this.params.push(...clause.where.params);
64
+ }
65
+ return;
66
+ }
67
+ this.parts.push('on conflict');
68
+ if (clause.fields instanceof RawQueryFragment) {
69
+ this.parts.push(clause.fields.sql);
70
+ this.params.push(...clause.fields.params);
71
+ }
72
+ else if (clause.fields.length > 0) {
73
+ const fields = clause.fields.map(field => this.quote(field));
74
+ this.parts.push(`(${fields.join(', ')})`);
75
+ }
76
+ }
77
+ }
@@ -0,0 +1,45 @@
1
+ import { type SimpleColumnMeta, type Type, type TransformContext, type IsolationLevel } from '@mikro-orm/core';
2
+ import { MySqlSchemaHelper } from './MySqlSchemaHelper.js';
3
+ import { MySqlExceptionConverter } from './MySqlExceptionConverter.js';
4
+ import { AbstractSqlPlatform } from '../../AbstractSqlPlatform.js';
5
+ import type { IndexDef } from '../../typings.js';
6
+ import { MySqlNativeQueryBuilder } from './MySqlNativeQueryBuilder.js';
7
+ export declare class MySqlPlatform extends AbstractSqlPlatform {
8
+ protected readonly schemaHelper: MySqlSchemaHelper;
9
+ protected readonly exceptionConverter: MySqlExceptionConverter;
10
+ protected readonly ORDER_BY_NULLS_TRANSLATE: {
11
+ readonly "asc nulls first": "is not null";
12
+ readonly "asc nulls last": "is null";
13
+ readonly "desc nulls first": "is not null";
14
+ readonly "desc nulls last": "is null";
15
+ };
16
+ /** @internal */
17
+ createNativeQueryBuilder(): MySqlNativeQueryBuilder;
18
+ getDefaultCharset(): string;
19
+ getBeginTransactionSQL(options?: {
20
+ isolationLevel?: IsolationLevel;
21
+ readOnly?: boolean;
22
+ }): string[];
23
+ convertJsonToDatabaseValue(value: unknown, context?: TransformContext): unknown;
24
+ getJsonIndexDefinition(index: IndexDef): string[];
25
+ getBooleanTypeDeclarationSQL(): string;
26
+ normalizeColumnType(type: string, options: {
27
+ length?: number;
28
+ precision?: number;
29
+ scale?: number;
30
+ }): string;
31
+ getDefaultMappedType(type: string): Type<unknown>;
32
+ isNumericColumn(mappedType: Type<unknown>): boolean;
33
+ supportsUnsigned(): boolean;
34
+ /**
35
+ * Returns the default name of index for the given columns
36
+ * cannot go past 64 character length for identifiers in MySQL
37
+ */
38
+ getIndexName(tableName: string, columns: string[], type: 'index' | 'unique' | 'foreign' | 'primary' | 'sequence'): string;
39
+ getDefaultPrimaryName(tableName: string, columns: string[]): string;
40
+ supportsCreatingFullTextIndex(): boolean;
41
+ getFullTextWhereClause(): string;
42
+ getFullTextIndexExpression(indexName: string, schemaName: string | undefined, tableName: string, columns: SimpleColumnMeta[]): string;
43
+ getOrderByExpression(column: string, direction: string): string[];
44
+ getDefaultClientUrl(): string;
45
+ }
@@ -0,0 +1,116 @@
1
+ import { Utils, QueryOrder, DecimalType, DoubleType, } from '@mikro-orm/core';
2
+ import { MySqlSchemaHelper } from './MySqlSchemaHelper.js';
3
+ import { MySqlExceptionConverter } from './MySqlExceptionConverter.js';
4
+ import { AbstractSqlPlatform } from '../../AbstractSqlPlatform.js';
5
+ import { MySqlNativeQueryBuilder } from './MySqlNativeQueryBuilder.js';
6
+ export class MySqlPlatform extends AbstractSqlPlatform {
7
+ schemaHelper = new MySqlSchemaHelper(this);
8
+ exceptionConverter = new MySqlExceptionConverter();
9
+ ORDER_BY_NULLS_TRANSLATE = {
10
+ [QueryOrder.asc_nulls_first]: 'is not null',
11
+ [QueryOrder.asc_nulls_last]: 'is null',
12
+ [QueryOrder.desc_nulls_first]: 'is not null',
13
+ [QueryOrder.desc_nulls_last]: 'is null',
14
+ };
15
+ /** @internal */
16
+ createNativeQueryBuilder() {
17
+ return new MySqlNativeQueryBuilder(this);
18
+ }
19
+ getDefaultCharset() {
20
+ return 'utf8mb4';
21
+ }
22
+ getBeginTransactionSQL(options) {
23
+ if (options?.isolationLevel || options?.readOnly) {
24
+ const parts = [];
25
+ if (options.isolationLevel) {
26
+ parts.push(`isolation level ${options.isolationLevel}`);
27
+ }
28
+ if (options.readOnly) {
29
+ parts.push('read only');
30
+ }
31
+ const sql = `set transaction ${parts.join(', ')}`;
32
+ return [sql, 'begin'];
33
+ }
34
+ return ['begin'];
35
+ }
36
+ convertJsonToDatabaseValue(value, context) {
37
+ if (context?.mode === 'query') {
38
+ return value;
39
+ }
40
+ return JSON.stringify(value);
41
+ }
42
+ getJsonIndexDefinition(index) {
43
+ return index.columnNames
44
+ .map(column => {
45
+ if (!column.includes('.')) {
46
+ return column;
47
+ }
48
+ const [root, ...path] = column.split('.');
49
+ return `(json_value(${this.quoteIdentifier(root)}, '$.${path.join('.')}' returning ${index.options?.returning ?? 'char(255)'}))`;
50
+ });
51
+ }
52
+ getBooleanTypeDeclarationSQL() {
53
+ return 'tinyint(1)';
54
+ }
55
+ normalizeColumnType(type, options) {
56
+ const simpleType = this.extractSimpleType(type);
57
+ if (['decimal', 'numeric'].includes(simpleType)) {
58
+ return this.getDecimalTypeDeclarationSQL(options);
59
+ }
60
+ return type;
61
+ }
62
+ getDefaultMappedType(type) {
63
+ if (type === 'tinyint(1)') {
64
+ return super.getDefaultMappedType('boolean');
65
+ }
66
+ return super.getDefaultMappedType(type);
67
+ }
68
+ isNumericColumn(mappedType) {
69
+ return super.isNumericColumn(mappedType) || [DecimalType, DoubleType].some(t => mappedType instanceof t);
70
+ }
71
+ supportsUnsigned() {
72
+ return true;
73
+ }
74
+ /**
75
+ * Returns the default name of index for the given columns
76
+ * cannot go past 64 character length for identifiers in MySQL
77
+ */
78
+ getIndexName(tableName, columns, type) {
79
+ if (type === 'primary') {
80
+ return this.getDefaultPrimaryName(tableName, columns);
81
+ }
82
+ const indexName = super.getIndexName(tableName, columns, type);
83
+ if (indexName.length > 64) {
84
+ return `${indexName.substring(0, 56 - type.length)}_${Utils.hash(indexName, 5)}_${type}`;
85
+ }
86
+ return indexName;
87
+ }
88
+ getDefaultPrimaryName(tableName, columns) {
89
+ return 'PRIMARY'; // https://dev.mysql.com/doc/refman/8.0/en/create-table.html#create-table-indexes-keys
90
+ }
91
+ supportsCreatingFullTextIndex() {
92
+ return true;
93
+ }
94
+ getFullTextWhereClause() {
95
+ return `match(:column:) against (:query in boolean mode)`;
96
+ }
97
+ getFullTextIndexExpression(indexName, schemaName, tableName, columns) {
98
+ /* v8 ignore next */
99
+ const quotedTableName = this.quoteIdentifier(schemaName ? `${schemaName}.${tableName}` : tableName);
100
+ const quotedColumnNames = columns.map(c => this.quoteIdentifier(c.name));
101
+ const quotedIndexName = this.quoteIdentifier(indexName);
102
+ return `alter table ${quotedTableName} add fulltext index ${quotedIndexName}(${quotedColumnNames.join(',')})`;
103
+ }
104
+ getOrderByExpression(column, direction) {
105
+ const ret = [];
106
+ const dir = direction.toLowerCase();
107
+ if (dir in this.ORDER_BY_NULLS_TRANSLATE) {
108
+ ret.push(`${column} ${this.ORDER_BY_NULLS_TRANSLATE[dir]}`);
109
+ }
110
+ ret.push(`${column} ${dir.replace(/(\s|nulls|first|last)*/gi, '')}`);
111
+ return ret;
112
+ }
113
+ getDefaultClientUrl() {
114
+ return 'mysql://root@127.0.0.1:3306';
115
+ }
116
+ }
@@ -0,0 +1,36 @@
1
+ import { type Dictionary, type Type } from '@mikro-orm/core';
2
+ import type { CheckDef, Column, IndexDef, TableDifference, Table, ForeignKey } from '../../typings.js';
3
+ import type { AbstractSqlConnection } from '../../AbstractSqlConnection.js';
4
+ import { SchemaHelper } from '../../schema/SchemaHelper.js';
5
+ import type { DatabaseSchema } from '../../schema/DatabaseSchema.js';
6
+ import type { DatabaseTable } from '../../schema/DatabaseTable.js';
7
+ export declare class MySqlSchemaHelper extends SchemaHelper {
8
+ private readonly _cache;
9
+ static readonly DEFAULT_VALUES: {
10
+ 'now()': string[];
11
+ 'current_timestamp(?)': string[];
12
+ '0': string[];
13
+ };
14
+ getSchemaBeginning(charset: string, disableForeignKeys?: boolean): string;
15
+ disableForeignKeysSQL(): string;
16
+ enableForeignKeysSQL(): string;
17
+ finalizeTable(table: DatabaseTable, charset: string, collate?: string): string;
18
+ getListTablesSQL(): string;
19
+ loadInformationSchema(schema: DatabaseSchema, connection: AbstractSqlConnection, tables: Table[]): Promise<void>;
20
+ getAllIndexes(connection: AbstractSqlConnection, tables: Table[]): Promise<Dictionary<IndexDef[]>>;
21
+ getCreateIndexSQL(tableName: string, index: IndexDef, partialExpression?: boolean): string;
22
+ getAllColumns(connection: AbstractSqlConnection, tables: Table[]): Promise<Dictionary<Column[]>>;
23
+ getAllChecks(connection: AbstractSqlConnection, tables: Table[]): Promise<Dictionary<CheckDef[]>>;
24
+ getAllForeignKeys(connection: AbstractSqlConnection, tables: Table[]): Promise<Dictionary<Dictionary<ForeignKey>>>;
25
+ getPreAlterTable(tableDiff: TableDifference, safe: boolean): string[];
26
+ getRenameColumnSQL(tableName: string, oldColumnName: string, to: Column): string;
27
+ getRenameIndexSQL(tableName: string, index: IndexDef, oldIndexName: string): string[];
28
+ getChangeColumnCommentSQL(tableName: string, to: Column, schemaName?: string): string;
29
+ alterTableColumn(column: Column, table: DatabaseTable, changedProperties: Set<string>): string[];
30
+ private getColumnDeclarationSQL;
31
+ getAllEnumDefinitions(connection: AbstractSqlConnection, tables: Table[]): Promise<Dictionary<Dictionary<string[]>>>;
32
+ private supportsCheckConstraints;
33
+ protected getChecksSQL(tables: Table[]): string;
34
+ normalizeDefaultValue(defaultValue: string, length: number): string | number;
35
+ protected wrap(val: string | null | undefined, type: Type<unknown>): string | null | undefined;
36
+ }