@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,76 @@
1
+ import { type Connection, type Dictionary } from '@mikro-orm/core';
2
+ import type { AbstractSqlConnection } from '../AbstractSqlConnection.js';
3
+ import type { AbstractSqlPlatform } from '../AbstractSqlPlatform.js';
4
+ import type { CheckDef, Column, ForeignKey, IndexDef, Table, TableDifference } from '../typings.js';
5
+ import type { DatabaseSchema } from './DatabaseSchema.js';
6
+ import type { DatabaseTable } from './DatabaseTable.js';
7
+ export declare abstract class SchemaHelper {
8
+ protected readonly platform: AbstractSqlPlatform;
9
+ constructor(platform: AbstractSqlPlatform);
10
+ getSchemaBeginning(_charset: string, disableForeignKeys?: boolean): string;
11
+ disableForeignKeysSQL(): string;
12
+ enableForeignKeysSQL(): string;
13
+ getSchemaEnd(disableForeignKeys?: boolean): string;
14
+ finalizeTable(table: DatabaseTable, charset: string, collate?: string): string;
15
+ appendComments(table: DatabaseTable): string[];
16
+ supportsSchemaConstraints(): boolean;
17
+ getPrimaryKeys(connection: AbstractSqlConnection, indexes: IndexDef[] | undefined, tableName: string, schemaName?: string): Promise<string[]>;
18
+ inferLengthFromColumnType(type: string): number | undefined;
19
+ protected getTableKey(t: Table): string;
20
+ getCreateNativeEnumSQL(name: string, values: unknown[], schema?: string): string;
21
+ getDropNativeEnumSQL(name: string, schema?: string): string;
22
+ getAlterNativeEnumSQL(name: string, schema?: string, value?: string, items?: string[], oldItems?: string[]): string;
23
+ abstract loadInformationSchema(schema: DatabaseSchema, connection: AbstractSqlConnection, tables: Table[], schemas?: string[]): Promise<void>;
24
+ getListTablesSQL(schemaName?: string): string;
25
+ getRenameColumnSQL(tableName: string, oldColumnName: string, to: Column, schemaName?: string): string;
26
+ getCreateIndexSQL(tableName: string, index: IndexDef): string;
27
+ getDropIndexSQL(tableName: string, index: IndexDef): string;
28
+ getRenameIndexSQL(tableName: string, index: IndexDef, oldIndexName: string): string[];
29
+ alterTable(diff: TableDifference, safe?: boolean): string[];
30
+ getAddColumnsSQL(table: DatabaseTable, columns: Column[]): string[];
31
+ getDropColumnsSQL(tableName: string, columns: Column[], schemaName?: string): string;
32
+ hasNonDefaultPrimaryKeyName(table: DatabaseTable): boolean;
33
+ castColumn(name: string, type: string): string;
34
+ alterTableColumn(column: Column, table: DatabaseTable, changedProperties: Set<string>): string[];
35
+ createTableColumn(column: Column, table: DatabaseTable, changedProperties?: Set<string>): string | undefined;
36
+ getPreAlterTable(tableDiff: TableDifference, safe: boolean): string[];
37
+ getPostAlterTable(tableDiff: TableDifference, safe: boolean): string[];
38
+ getChangeColumnCommentSQL(tableName: string, to: Column, schemaName?: string): string;
39
+ getNamespaces(connection: AbstractSqlConnection): Promise<string[]>;
40
+ protected mapIndexes(indexes: IndexDef[]): Promise<IndexDef[]>;
41
+ mapForeignKeys(fks: any[], tableName: string, schemaName?: string): Dictionary;
42
+ normalizeDefaultValue(defaultValue: string, length?: number, defaultValues?: Dictionary<string[]>): string | number;
43
+ getCreateDatabaseSQL(name: string): string;
44
+ getDropDatabaseSQL(name: string): string;
45
+ getCreateNamespaceSQL(name: string): string;
46
+ getDropNamespaceSQL(name: string): string;
47
+ getDatabaseExistsSQL(name: string): string;
48
+ getDatabaseNotExistsError(dbName: string): string;
49
+ getManagementDbName(): string;
50
+ getDefaultEmptyString(): string;
51
+ databaseExists(connection: Connection, name: string): Promise<boolean>;
52
+ append(array: string[], sql: string | string[], pad?: boolean): void;
53
+ createTable(table: DatabaseTable, alter?: boolean): string[];
54
+ alterTableComment(table: DatabaseTable, comment?: string): string;
55
+ createForeignKey(table: DatabaseTable, foreignKey: ForeignKey, alterTable?: boolean, inline?: boolean): string;
56
+ splitTableName(name: string, skipDefaultSchema?: boolean): [string | undefined, string];
57
+ getReferencedTableName(referencedTableName: string, schema?: string): string;
58
+ createIndex(index: IndexDef, table: DatabaseTable, createPrimary?: boolean): string;
59
+ createCheck(table: DatabaseTable, check: CheckDef): string;
60
+ protected getTableName(table: string, schema?: string): string;
61
+ getTablesGroupedBySchemas(tables: Table[]): Map<string | undefined, Table[]>;
62
+ get options(): {
63
+ disableForeignKeys?: boolean;
64
+ createForeignKeyConstraints?: boolean;
65
+ ignoreSchema?: string[];
66
+ skipTables?: (string | RegExp)[];
67
+ skipColumns?: Dictionary<(string | RegExp)[]>;
68
+ managementDbName?: string;
69
+ };
70
+ protected processComment(comment: string): string;
71
+ protected quote(...keys: (string | undefined)[]): string;
72
+ dropForeignKey(tableName: string, constraintName: string): string;
73
+ dropIndex(table: string, index: IndexDef, oldIndexName?: string): string;
74
+ dropConstraint(table: string, name: string): string;
75
+ dropTableIfExists(name: string, schema?: string): string;
76
+ }
@@ -0,0 +1,545 @@
1
+ import { RawQueryFragment, Utils } from '@mikro-orm/core';
2
+ export class SchemaHelper {
3
+ platform;
4
+ constructor(platform) {
5
+ this.platform = platform;
6
+ }
7
+ getSchemaBeginning(_charset, disableForeignKeys) {
8
+ if (disableForeignKeys) {
9
+ return `${this.disableForeignKeysSQL()}\n`;
10
+ }
11
+ return '';
12
+ }
13
+ disableForeignKeysSQL() {
14
+ return '';
15
+ }
16
+ enableForeignKeysSQL() {
17
+ return '';
18
+ }
19
+ getSchemaEnd(disableForeignKeys) {
20
+ if (disableForeignKeys) {
21
+ return `${this.enableForeignKeysSQL()}\n`;
22
+ }
23
+ return '';
24
+ }
25
+ finalizeTable(table, charset, collate) {
26
+ return '';
27
+ }
28
+ appendComments(table) {
29
+ return [];
30
+ }
31
+ supportsSchemaConstraints() {
32
+ return true;
33
+ }
34
+ async getPrimaryKeys(connection, indexes = [], tableName, schemaName) {
35
+ const pks = indexes.filter(i => i.primary).map(pk => pk.columnNames);
36
+ return Utils.flatten(pks);
37
+ }
38
+ inferLengthFromColumnType(type) {
39
+ const match = type.match(/^\w+\s*(?:\(\s*(\d+)\s*\)|$)/);
40
+ if (!match) {
41
+ return;
42
+ }
43
+ return +match[1];
44
+ }
45
+ getTableKey(t) {
46
+ const unquote = (str) => str.replace(/['"`]/g, '');
47
+ const parts = t.table_name.split('.');
48
+ if (parts.length > 1) {
49
+ return `${unquote(parts[0])}.${unquote(parts[1])}`;
50
+ }
51
+ if (t.schema_name) {
52
+ return `${unquote(t.schema_name)}.${unquote(t.table_name)}`;
53
+ }
54
+ return unquote(t.table_name);
55
+ }
56
+ getCreateNativeEnumSQL(name, values, schema) {
57
+ throw new Error('Not supported by given driver');
58
+ }
59
+ getDropNativeEnumSQL(name, schema) {
60
+ throw new Error('Not supported by given driver');
61
+ }
62
+ getAlterNativeEnumSQL(name, schema, value, items, oldItems) {
63
+ throw new Error('Not supported by given driver');
64
+ }
65
+ getListTablesSQL(schemaName) {
66
+ throw new Error('Not supported by given driver');
67
+ }
68
+ getRenameColumnSQL(tableName, oldColumnName, to, schemaName) {
69
+ tableName = this.quote(tableName);
70
+ oldColumnName = this.quote(oldColumnName);
71
+ const columnName = this.quote(to.name);
72
+ const schemaReference = (schemaName !== undefined && schemaName !== 'public') ? ('"' + schemaName + '".') : '';
73
+ const tableReference = schemaReference + tableName;
74
+ return `alter table ${tableReference} rename column ${oldColumnName} to ${columnName}`;
75
+ }
76
+ getCreateIndexSQL(tableName, index) {
77
+ /* v8 ignore next */
78
+ if (index.expression) {
79
+ return index.expression;
80
+ }
81
+ tableName = this.quote(tableName);
82
+ const keyName = this.quote(index.keyName);
83
+ const defer = index.deferMode ? ` deferrable initially ${index.deferMode}` : '';
84
+ let sql = `create ${index.unique ? 'unique ' : ''}index ${keyName} on ${tableName} `;
85
+ if (index.unique && index.constraint) {
86
+ sql = `alter table ${tableName} add constraint ${keyName} unique `;
87
+ }
88
+ if (index.columnNames.some(column => column.includes('.'))) {
89
+ // JSON columns can have unique index but not unique constraint, and we need to distinguish those, so we can properly drop them
90
+ const sql = `create ${index.unique ? 'unique ' : ''}index ${keyName} on ${tableName} `;
91
+ const columns = this.platform.getJsonIndexDefinition(index);
92
+ return `${sql}(${columns.join(', ')})${defer}`;
93
+ }
94
+ return `${sql}(${index.columnNames.map(c => this.quote(c)).join(', ')})${defer}`;
95
+ }
96
+ getDropIndexSQL(tableName, index) {
97
+ return `drop index ${this.quote(index.keyName)}`;
98
+ }
99
+ getRenameIndexSQL(tableName, index, oldIndexName) {
100
+ return [
101
+ this.getDropIndexSQL(tableName, { ...index, keyName: oldIndexName }),
102
+ this.getCreateIndexSQL(tableName, index),
103
+ ];
104
+ }
105
+ alterTable(diff, safe) {
106
+ const ret = [];
107
+ const [schemaName, tableName] = this.splitTableName(diff.name);
108
+ if (this.platform.supportsNativeEnums()) {
109
+ const changedNativeEnums = [];
110
+ for (const { column, changedProperties } of Object.values(diff.changedColumns)) {
111
+ if (!column.nativeEnumName) {
112
+ continue;
113
+ }
114
+ const key = schemaName && schemaName !== this.platform.getDefaultSchemaName() && !column.nativeEnumName.includes('.')
115
+ ? schemaName + '.' + column.nativeEnumName
116
+ : column.nativeEnumName;
117
+ if (changedProperties.has('enumItems') && key in diff.fromTable.nativeEnums) {
118
+ changedNativeEnums.push([column.nativeEnumName, column.enumItems, diff.fromTable.nativeEnums[key].items]);
119
+ }
120
+ }
121
+ Utils.removeDuplicates(changedNativeEnums).forEach(([enumName, itemsNew, itemsOld]) => {
122
+ // postgres allows only adding new items
123
+ const newItems = itemsNew.filter(val => !itemsOld.includes(val));
124
+ if (enumName.includes('.')) {
125
+ const [enumSchemaName, rawEnumName] = enumName.split('.');
126
+ ret.push(...newItems.map(val => this.getAlterNativeEnumSQL(rawEnumName, enumSchemaName, val, itemsNew, itemsOld)));
127
+ return;
128
+ }
129
+ ret.push(...newItems.map(val => this.getAlterNativeEnumSQL(enumName, schemaName, val, itemsNew, itemsOld)));
130
+ });
131
+ }
132
+ for (const index of Object.values(diff.removedIndexes)) {
133
+ ret.push(this.dropIndex(diff.name, index));
134
+ }
135
+ for (const index of Object.values(diff.changedIndexes)) {
136
+ ret.push(this.dropIndex(diff.name, index));
137
+ }
138
+ for (const check of Object.values(diff.removedChecks)) {
139
+ ret.push(this.dropConstraint(diff.name, check.name));
140
+ }
141
+ for (const check of Object.values(diff.changedChecks)) {
142
+ ret.push(this.dropConstraint(diff.name, check.name));
143
+ }
144
+ /* v8 ignore next */
145
+ if (!safe && Object.values(diff.removedColumns).length > 0) {
146
+ ret.push(this.getDropColumnsSQL(tableName, Object.values(diff.removedColumns), schemaName));
147
+ }
148
+ if (Object.values(diff.addedColumns).length > 0) {
149
+ this.append(ret, this.getAddColumnsSQL(diff.toTable, Object.values(diff.addedColumns)));
150
+ }
151
+ for (const column of Object.values(diff.addedColumns)) {
152
+ const foreignKey = Object.values(diff.addedForeignKeys).find(fk => fk.columnNames.length === 1 && fk.columnNames[0] === column.name);
153
+ if (foreignKey && this.options.createForeignKeyConstraints) {
154
+ delete diff.addedForeignKeys[foreignKey.constraintName];
155
+ ret.push(this.createForeignKey(diff.toTable, foreignKey));
156
+ }
157
+ }
158
+ for (const { column, changedProperties } of Object.values(diff.changedColumns)) {
159
+ if (changedProperties.size === 1 && changedProperties.has('comment')) {
160
+ continue;
161
+ }
162
+ if (changedProperties.size === 1 && changedProperties.has('enumItems') && column.nativeEnumName) {
163
+ continue;
164
+ }
165
+ this.append(ret, this.alterTableColumn(column, diff.fromTable, changedProperties));
166
+ }
167
+ for (const { column, changedProperties } of Object.values(diff.changedColumns).filter(diff => diff.changedProperties.has('comment'))) {
168
+ if (['type', 'nullable', 'autoincrement', 'unsigned', 'default', 'enumItems'].some(t => changedProperties.has(t))) {
169
+ continue; // will be handled via column update
170
+ }
171
+ ret.push(this.getChangeColumnCommentSQL(tableName, column, schemaName));
172
+ }
173
+ for (const [oldColumnName, column] of Object.entries(diff.renamedColumns)) {
174
+ ret.push(this.getRenameColumnSQL(tableName, oldColumnName, column, schemaName));
175
+ }
176
+ for (const foreignKey of Object.values(diff.addedForeignKeys)) {
177
+ ret.push(this.createForeignKey(diff.toTable, foreignKey));
178
+ }
179
+ for (const foreignKey of Object.values(diff.changedForeignKeys)) {
180
+ ret.push(this.createForeignKey(diff.toTable, foreignKey));
181
+ }
182
+ for (const index of Object.values(diff.addedIndexes)) {
183
+ ret.push(this.createIndex(index, diff.toTable));
184
+ }
185
+ for (const index of Object.values(diff.changedIndexes)) {
186
+ ret.push(this.createIndex(index, diff.toTable, true));
187
+ }
188
+ for (const [oldIndexName, index] of Object.entries(diff.renamedIndexes)) {
189
+ if (index.unique) {
190
+ ret.push(this.dropIndex(diff.name, index, oldIndexName));
191
+ ret.push(this.createIndex(index, diff.toTable));
192
+ }
193
+ else {
194
+ ret.push(...this.getRenameIndexSQL(diff.name, index, oldIndexName));
195
+ }
196
+ }
197
+ for (const check of Object.values(diff.addedChecks)) {
198
+ ret.push(this.createCheck(diff.toTable, check));
199
+ }
200
+ for (const check of Object.values(diff.changedChecks)) {
201
+ ret.push(this.createCheck(diff.toTable, check));
202
+ }
203
+ if ('changedComment' in diff) {
204
+ ret.push(this.alterTableComment(diff.toTable, diff.changedComment));
205
+ }
206
+ return ret;
207
+ }
208
+ getAddColumnsSQL(table, columns) {
209
+ const adds = columns.map(column => {
210
+ return `add ${this.createTableColumn(column, table)}`;
211
+ }).join(', ');
212
+ return [`alter table ${table.getQuotedName()} ${adds}`];
213
+ }
214
+ getDropColumnsSQL(tableName, columns, schemaName) {
215
+ const name = this.quote(this.getTableName(tableName, schemaName));
216
+ const drops = columns.map(column => `drop column ${this.quote(column.name)}`).join(', ');
217
+ return `alter table ${name} ${drops}`;
218
+ }
219
+ hasNonDefaultPrimaryKeyName(table) {
220
+ const pkIndex = table.getPrimaryKey();
221
+ if (!pkIndex || !this.platform.supportsCustomPrimaryKeyNames()) {
222
+ return false;
223
+ }
224
+ const defaultName = this.platform.getDefaultPrimaryName(table.name, pkIndex.columnNames);
225
+ return pkIndex?.keyName !== defaultName;
226
+ }
227
+ /* v8 ignore next */
228
+ castColumn(name, type) {
229
+ return '';
230
+ }
231
+ alterTableColumn(column, table, changedProperties) {
232
+ const sql = [];
233
+ if (changedProperties.has('default') && column.default == null) {
234
+ sql.push(`alter table ${table.getQuotedName()} alter column ${this.quote(column.name)} drop default`);
235
+ }
236
+ if (changedProperties.has('type')) {
237
+ let type = column.type + (column.generated ? ` generated always as ${column.generated}` : '');
238
+ if (column.nativeEnumName) {
239
+ type = this.quote(this.getTableName(type, table.schema));
240
+ }
241
+ sql.push(`alter table ${table.getQuotedName()} alter column ${this.quote(column.name)} type ${type + this.castColumn(column.name, type)}`);
242
+ }
243
+ if (changedProperties.has('default') && column.default != null) {
244
+ sql.push(`alter table ${table.getQuotedName()} alter column ${this.quote(column.name)} set default ${column.default}`);
245
+ }
246
+ if (changedProperties.has('nullable')) {
247
+ const action = column.nullable ? 'drop' : 'set';
248
+ sql.push(`alter table ${table.getQuotedName()} alter column ${this.quote(column.name)} ${action} not null`);
249
+ }
250
+ return sql;
251
+ }
252
+ createTableColumn(column, table, changedProperties) {
253
+ const compositePK = table.getPrimaryKey()?.composite;
254
+ const primaryKey = !changedProperties && !this.hasNonDefaultPrimaryKeyName(table);
255
+ const columnType = column.type + (column.generated ? ` generated always as ${column.generated}` : '');
256
+ const useDefault = column.default != null && column.default !== 'null' && !column.autoincrement;
257
+ const col = [this.quote(column.name), columnType];
258
+ Utils.runIfNotEmpty(() => col.push('unsigned'), column.unsigned && this.platform.supportsUnsigned());
259
+ Utils.runIfNotEmpty(() => col.push('null'), column.nullable);
260
+ Utils.runIfNotEmpty(() => col.push('not null'), !column.nullable && !column.generated);
261
+ Utils.runIfNotEmpty(() => col.push('auto_increment'), column.autoincrement);
262
+ Utils.runIfNotEmpty(() => col.push('unique'), column.autoincrement && !column.primary);
263
+ if (column.autoincrement && !column.generated && !compositePK && (!changedProperties || changedProperties.has('autoincrement') || changedProperties.has('type'))) {
264
+ Utils.runIfNotEmpty(() => col.push('primary key'), primaryKey && column.primary);
265
+ }
266
+ if (useDefault) {
267
+ // https://dev.mysql.com/doc/refman/9.0/en/data-type-defaults.html
268
+ const needsExpression = ['blob', 'text', 'json', 'point', 'linestring', 'polygon', 'multipoint', 'multilinestring', 'multipolygon', 'geometrycollection'].some(type => column.type.toLowerCase().startsWith(type));
269
+ const defaultSql = needsExpression && !column.default.startsWith('(') ? `(${column.default})` : column.default;
270
+ col.push(`default ${defaultSql}`);
271
+ }
272
+ Utils.runIfNotEmpty(() => col.push(column.extra), column.extra);
273
+ Utils.runIfNotEmpty(() => col.push(`comment ${this.platform.quoteValue(column.comment)}`), column.comment);
274
+ return col.join(' ');
275
+ }
276
+ getPreAlterTable(tableDiff, safe) {
277
+ return [];
278
+ }
279
+ getPostAlterTable(tableDiff, safe) {
280
+ return [];
281
+ }
282
+ getChangeColumnCommentSQL(tableName, to, schemaName) {
283
+ return '';
284
+ }
285
+ async getNamespaces(connection) {
286
+ return [];
287
+ }
288
+ async mapIndexes(indexes) {
289
+ const map = {};
290
+ indexes.forEach(index => {
291
+ if (map[index.keyName]) {
292
+ map[index.keyName].composite = true;
293
+ map[index.keyName].columnNames.push(index.columnNames[0]);
294
+ }
295
+ else {
296
+ map[index.keyName] = index;
297
+ }
298
+ });
299
+ return Object.values(map);
300
+ }
301
+ mapForeignKeys(fks, tableName, schemaName) {
302
+ return fks.reduce((ret, fk) => {
303
+ if (ret[fk.constraint_name]) {
304
+ ret[fk.constraint_name].columnNames.push(fk.column_name);
305
+ ret[fk.constraint_name].referencedColumnNames.push(fk.referenced_column_name);
306
+ }
307
+ else {
308
+ ret[fk.constraint_name] = {
309
+ columnNames: [fk.column_name],
310
+ constraintName: fk.constraint_name,
311
+ localTableName: schemaName ? `${schemaName}.${tableName}` : tableName,
312
+ referencedTableName: fk.referenced_schema_name ? `${fk.referenced_schema_name}.${fk.referenced_table_name}` : fk.referenced_table_name,
313
+ referencedColumnNames: [fk.referenced_column_name],
314
+ updateRule: fk.update_rule.toLowerCase(),
315
+ deleteRule: fk.delete_rule.toLowerCase(),
316
+ deferMode: fk.defer_mode,
317
+ };
318
+ }
319
+ return ret;
320
+ }, {});
321
+ }
322
+ normalizeDefaultValue(defaultValue, length, defaultValues = {}) {
323
+ if (defaultValue == null) {
324
+ return defaultValue;
325
+ }
326
+ const raw = RawQueryFragment.getKnownFragment(defaultValue);
327
+ if (raw) {
328
+ return this.platform.formatQuery(raw.sql, raw.params);
329
+ }
330
+ const genericValue = defaultValue.replace(/\(\d+\)/, '(?)').toLowerCase();
331
+ const norm = defaultValues[genericValue];
332
+ if (!norm) {
333
+ return defaultValue;
334
+ }
335
+ return norm[0].replace('(?)', length != null ? `(${length})` : '');
336
+ }
337
+ getCreateDatabaseSQL(name) {
338
+ // two line breaks to force separate execution
339
+ return `create database ${name};\n\nuse ${name}`;
340
+ }
341
+ getDropDatabaseSQL(name) {
342
+ return `drop database if exists ${this.quote(name)}`;
343
+ }
344
+ /* v8 ignore next */
345
+ getCreateNamespaceSQL(name) {
346
+ return `create schema if not exists ${this.quote(name)}`;
347
+ }
348
+ /* v8 ignore next */
349
+ getDropNamespaceSQL(name) {
350
+ return `drop schema if exists ${this.quote(name)}`;
351
+ }
352
+ getDatabaseExistsSQL(name) {
353
+ return `select 1 from information_schema.schemata where schema_name = '${name}'`;
354
+ }
355
+ getDatabaseNotExistsError(dbName) {
356
+ return `Unknown database '${dbName}'`;
357
+ }
358
+ getManagementDbName() {
359
+ return 'information_schema';
360
+ }
361
+ getDefaultEmptyString() {
362
+ return "''";
363
+ }
364
+ async databaseExists(connection, name) {
365
+ try {
366
+ const res = await connection.execute(this.getDatabaseExistsSQL(name));
367
+ return res.length > 0;
368
+ }
369
+ catch (e) {
370
+ if (e instanceof Error && e.message.includes(this.getDatabaseNotExistsError(name))) {
371
+ return false;
372
+ }
373
+ /* v8 ignore next */
374
+ throw e;
375
+ }
376
+ }
377
+ append(array, sql, pad = false) {
378
+ const length = array.length;
379
+ for (const row of Utils.asArray(sql)) {
380
+ if (!row) {
381
+ continue;
382
+ }
383
+ let tmp = row.trim();
384
+ if (!tmp.endsWith(';')) {
385
+ tmp += ';';
386
+ }
387
+ array.push(tmp);
388
+ }
389
+ if (pad && array.length > length) {
390
+ array.push('');
391
+ }
392
+ }
393
+ createTable(table, alter) {
394
+ let sql = `create table ${table.getQuotedName()} (`;
395
+ const columns = table.getColumns();
396
+ const lastColumn = columns[columns.length - 1].name;
397
+ for (const column of columns) {
398
+ const col = this.createTableColumn(column, table);
399
+ if (col) {
400
+ const comma = column.name === lastColumn ? '' : ', ';
401
+ sql += col + comma;
402
+ }
403
+ }
404
+ const primaryKey = table.getPrimaryKey();
405
+ const createPrimary = !table.getColumns().some(c => c.autoincrement && c.primary) || this.hasNonDefaultPrimaryKeyName(table);
406
+ if (createPrimary && primaryKey) {
407
+ const name = this.hasNonDefaultPrimaryKeyName(table) ? `constraint ${this.quote(primaryKey.keyName)} ` : '';
408
+ sql += `, ${name}primary key (${primaryKey.columnNames.map(c => this.quote(c)).join(', ')})`;
409
+ }
410
+ sql += ')';
411
+ sql += this.finalizeTable(table, this.platform.getConfig().get('charset'), this.platform.getConfig().get('collate'));
412
+ const ret = [];
413
+ this.append(ret, sql);
414
+ this.append(ret, this.appendComments(table));
415
+ for (const index of table.getIndexes()) {
416
+ this.append(ret, this.createIndex(index, table));
417
+ }
418
+ if (!alter) {
419
+ for (const check of table.getChecks()) {
420
+ this.append(ret, this.createCheck(table, check));
421
+ }
422
+ }
423
+ return ret;
424
+ }
425
+ alterTableComment(table, comment) {
426
+ return `alter table ${table.getQuotedName()} comment = ${this.platform.quoteValue(comment ?? '')}`;
427
+ }
428
+ createForeignKey(table, foreignKey, alterTable = true, inline = false) {
429
+ if (!this.options.createForeignKeyConstraints) {
430
+ return '';
431
+ }
432
+ const constraintName = this.quote(foreignKey.constraintName);
433
+ const columnNames = foreignKey.columnNames.map(c => this.quote(c)).join(', ');
434
+ const referencedColumnNames = foreignKey.referencedColumnNames.map(c => this.quote(c)).join(', ');
435
+ const referencedTableName = this.quote(this.getReferencedTableName(foreignKey.referencedTableName, table.schema));
436
+ const sql = [];
437
+ if (alterTable) {
438
+ sql.push(`alter table ${table.getQuotedName()} add`);
439
+ }
440
+ sql.push(`constraint ${constraintName}`);
441
+ if (!inline) {
442
+ sql.push(`foreign key (${columnNames})`);
443
+ }
444
+ sql.push(`references ${referencedTableName} (${referencedColumnNames})`);
445
+ if (foreignKey.localTableName !== foreignKey.referencedTableName || this.platform.supportsMultipleCascadePaths()) {
446
+ if (foreignKey.updateRule) {
447
+ sql.push(`on update ${foreignKey.updateRule}`);
448
+ }
449
+ if (foreignKey.deleteRule) {
450
+ sql.push(`on delete ${foreignKey.deleteRule}`);
451
+ }
452
+ }
453
+ if (foreignKey.deferMode) {
454
+ sql.push(`deferrable initially ${foreignKey.deferMode}`);
455
+ }
456
+ return sql.join(' ');
457
+ }
458
+ splitTableName(name, skipDefaultSchema = false) {
459
+ const parts = name.split('.');
460
+ const tableName = parts.pop();
461
+ let schemaName = parts.pop();
462
+ if (skipDefaultSchema && schemaName === this.platform.getDefaultSchemaName()) {
463
+ schemaName = undefined;
464
+ }
465
+ return [schemaName, tableName];
466
+ }
467
+ getReferencedTableName(referencedTableName, schema) {
468
+ const [schemaName, tableName] = this.splitTableName(referencedTableName);
469
+ schema = schemaName ?? schema ?? this.platform.getConfig().get('schema');
470
+ /* v8 ignore next */
471
+ if (schema && schemaName === '*') {
472
+ return `${schema}.${referencedTableName.replace(/^\*\./, '')}`;
473
+ }
474
+ return this.getTableName(tableName, schema);
475
+ }
476
+ createIndex(index, table, createPrimary = false) {
477
+ if (index.primary && !createPrimary) {
478
+ return '';
479
+ }
480
+ if (index.expression) {
481
+ return index.expression;
482
+ }
483
+ const columns = index.columnNames.map(c => this.quote(c)).join(', ');
484
+ const defer = index.deferMode ? ` deferrable initially ${index.deferMode}` : '';
485
+ if (index.primary) {
486
+ const keyName = this.hasNonDefaultPrimaryKeyName(table) ? `constraint ${index.keyName} ` : '';
487
+ return `alter table ${table.getQuotedName()} add ${keyName}primary key (${columns})${defer}`;
488
+ }
489
+ if (index.type === 'fulltext') {
490
+ const columns = index.columnNames.map(name => ({ name, type: table.getColumn(name).type }));
491
+ if (this.platform.supportsCreatingFullTextIndex()) {
492
+ return this.platform.getFullTextIndexExpression(index.keyName, table.schema, table.name, columns);
493
+ }
494
+ }
495
+ return this.getCreateIndexSQL(table.getShortestName(), index);
496
+ }
497
+ createCheck(table, check) {
498
+ return `alter table ${table.getQuotedName()} add constraint ${this.quote(check.name)} check (${check.expression})`;
499
+ }
500
+ getTableName(table, schema) {
501
+ if (schema && schema !== this.platform.getDefaultSchemaName()) {
502
+ return `${schema}.${table}`;
503
+ }
504
+ return table;
505
+ }
506
+ getTablesGroupedBySchemas(tables) {
507
+ return tables.reduce((acc, table) => {
508
+ const schemaTables = acc.get(table.schema_name);
509
+ if (!schemaTables) {
510
+ acc.set(table.schema_name, [table]);
511
+ return acc;
512
+ }
513
+ schemaTables.push(table);
514
+ return acc;
515
+ }, new Map());
516
+ }
517
+ get options() {
518
+ return this.platform.getConfig().get('schemaGenerator');
519
+ }
520
+ processComment(comment) {
521
+ return comment;
522
+ }
523
+ quote(...keys) {
524
+ return this.platform.quoteIdentifier(keys.filter(Boolean).join('.'));
525
+ }
526
+ dropForeignKey(tableName, constraintName) {
527
+ return `alter table ${this.quote(tableName)} drop foreign key ${this.quote(constraintName)}`;
528
+ }
529
+ dropIndex(table, index, oldIndexName = index.keyName) {
530
+ if (index.primary) {
531
+ return `alter table ${this.quote(table)} drop primary key`;
532
+ }
533
+ return `alter table ${this.quote(table)} drop index ${this.quote(oldIndexName)}`;
534
+ }
535
+ dropConstraint(table, name) {
536
+ return `alter table ${this.quote(table)} drop constraint ${this.quote(name)}`;
537
+ }
538
+ dropTableIfExists(name, schema) {
539
+ let sql = `drop table if exists ${this.quote(this.getTableName(name, schema))}`;
540
+ if (this.platform.usesCascadeStatement()) {
541
+ sql += ' cascade';
542
+ }
543
+ return sql;
544
+ }
545
+ }
@@ -0,0 +1,65 @@
1
+ import { AbstractSchemaGenerator, type ClearDatabaseOptions, type CreateSchemaOptions, type Dictionary, type DropSchemaOptions, type EnsureDatabaseOptions, type EntityMetadata, type ISchemaGenerator, type MikroORM, type Transaction, type UpdateSchemaOptions } from '@mikro-orm/core';
2
+ import type { SchemaDifference } from '../typings.js';
3
+ import { DatabaseSchema } from './DatabaseSchema.js';
4
+ import type { AbstractSqlDriver } from '../AbstractSqlDriver.js';
5
+ export declare class SqlSchemaGenerator extends AbstractSchemaGenerator<AbstractSqlDriver> implements ISchemaGenerator {
6
+ protected readonly helper: import("./SchemaHelper.js").SchemaHelper;
7
+ protected readonly options: {
8
+ disableForeignKeys?: boolean;
9
+ createForeignKeyConstraints?: boolean;
10
+ ignoreSchema?: string[];
11
+ skipTables?: (string | RegExp)[];
12
+ skipColumns?: Dictionary<(string | RegExp)[]>;
13
+ managementDbName?: string;
14
+ };
15
+ protected lastEnsuredDatabase?: string;
16
+ static register(orm: MikroORM): void;
17
+ create(options?: CreateSchemaOptions): Promise<void>;
18
+ /**
19
+ * Returns true if the database was created.
20
+ */
21
+ ensureDatabase(options?: EnsureDatabaseOptions): Promise<boolean>;
22
+ getTargetSchema(schema?: string): DatabaseSchema;
23
+ protected getOrderedMetadata(schema?: string): EntityMetadata[];
24
+ getCreateSchemaSQL(options?: CreateSchemaOptions): Promise<string>;
25
+ drop(options?: DropSchemaOptions): Promise<void>;
26
+ createNamespace(name: string): Promise<void>;
27
+ dropNamespace(name: string): Promise<void>;
28
+ clear(options?: ClearDatabaseOptions): Promise<void>;
29
+ getDropSchemaSQL(options?: Omit<DropSchemaOptions, 'dropDb'>): Promise<string>;
30
+ private getSchemaName;
31
+ update(options?: UpdateSchemaOptions<DatabaseSchema>): Promise<void>;
32
+ getUpdateSchemaSQL(options?: UpdateSchemaOptions<DatabaseSchema>): Promise<string>;
33
+ getUpdateSchemaMigrationSQL(options?: UpdateSchemaOptions<DatabaseSchema>): Promise<{
34
+ up: string;
35
+ down: string;
36
+ }>;
37
+ private prepareSchemaForComparison;
38
+ diffToSQL(schemaDiff: SchemaDifference, options: {
39
+ wrap?: boolean;
40
+ safe?: boolean;
41
+ dropTables?: boolean;
42
+ schema?: string;
43
+ }): string;
44
+ /**
45
+ * We need to drop foreign keys first for all tables to allow dropping PK constraints.
46
+ */
47
+ private preAlterTable;
48
+ /**
49
+ * creates new database and connects to it
50
+ */
51
+ createDatabase(name?: string, options?: {
52
+ skipOnConnect?: boolean;
53
+ }): Promise<void>;
54
+ dropDatabase(name?: string): Promise<void>;
55
+ execute(sql: string, options?: {
56
+ wrap?: boolean;
57
+ ctx?: Transaction;
58
+ }): Promise<void>;
59
+ dropTableIfExists(name: string, schema?: string): Promise<void>;
60
+ private wrapSchema;
61
+ private append;
62
+ private matchName;
63
+ private isTableSkipped;
64
+ }
65
+ export { SqlSchemaGenerator as SchemaGenerator };