@yandjin-mikro-orm/mysql 6.1.4-rc-sti-changes-1
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 +21 -0
- package/MySqlConnection.d.ts +8 -0
- package/MySqlConnection.js +60 -0
- package/MySqlDriver.d.ts +10 -0
- package/MySqlDriver.js +36 -0
- package/MySqlExceptionConverter.d.ts +9 -0
- package/MySqlExceptionConverter.js +83 -0
- package/MySqlMikroORM.d.ts +19 -0
- package/MySqlMikroORM.js +29 -0
- package/MySqlPlatform.d.ts +25 -0
- package/MySqlPlatform.js +89 -0
- package/MySqlSchemaHelper.d.ts +38 -0
- package/MySqlSchemaHelper.js +320 -0
- package/README.md +383 -0
- package/index.d.ts +7 -0
- package/index.js +26 -0
- package/index.mjs +220 -0
- package/package.json +70 -0
|
@@ -0,0 +1,320 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.MySqlSchemaHelper = void 0;
|
|
4
|
+
const knex_1 = require("@yandjin-mikro-orm/knex");
|
|
5
|
+
const core_1 = require("@yandjin-mikro-orm/core");
|
|
6
|
+
class MySqlSchemaHelper extends knex_1.SchemaHelper {
|
|
7
|
+
_cache = {};
|
|
8
|
+
static DEFAULT_VALUES = {
|
|
9
|
+
"now()": ["now()", "current_timestamp"],
|
|
10
|
+
"current_timestamp(?)": ["current_timestamp(?)"],
|
|
11
|
+
"0": ["0", "false"],
|
|
12
|
+
};
|
|
13
|
+
getSchemaBeginning(charset) {
|
|
14
|
+
return `set names ${charset};\n${this.disableForeignKeysSQL()}\n\n`;
|
|
15
|
+
}
|
|
16
|
+
disableForeignKeysSQL() {
|
|
17
|
+
return "set foreign_key_checks = 0;";
|
|
18
|
+
}
|
|
19
|
+
enableForeignKeysSQL() {
|
|
20
|
+
return "set foreign_key_checks = 1;";
|
|
21
|
+
}
|
|
22
|
+
finalizeTable(table, charset, collate) {
|
|
23
|
+
table.engine("InnoDB");
|
|
24
|
+
table.charset(charset);
|
|
25
|
+
if (collate) {
|
|
26
|
+
table.collate(collate);
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
getListTablesSQL() {
|
|
30
|
+
return `select table_name as table_name, nullif(table_schema, schema()) as schema_name, table_comment as table_comment from information_schema.tables where table_type = 'BASE TABLE' and table_schema = schema()`;
|
|
31
|
+
}
|
|
32
|
+
async loadInformationSchema(schema, connection, tables) {
|
|
33
|
+
if (tables.length === 0) {
|
|
34
|
+
return;
|
|
35
|
+
}
|
|
36
|
+
const columns = await this.getAllColumns(connection, tables);
|
|
37
|
+
const indexes = await this.getAllIndexes(connection, tables);
|
|
38
|
+
const checks = await this.getAllChecks(connection, tables);
|
|
39
|
+
const fks = await this.getAllForeignKeys(connection, tables);
|
|
40
|
+
const enums = await this.getAllEnumDefinitions(connection, tables);
|
|
41
|
+
for (const t of tables) {
|
|
42
|
+
const key = this.getTableKey(t);
|
|
43
|
+
const table = schema.addTable(t.table_name, t.schema_name, t.table_comment);
|
|
44
|
+
const pks = await this.getPrimaryKeys(connection, indexes[key], table.name, table.schema);
|
|
45
|
+
table.init(columns[key], indexes[key], checks[key], pks, fks[key], enums[key]);
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
async getAllIndexes(connection, tables) {
|
|
49
|
+
const sql = `select table_name as table_name, nullif(table_schema, schema()) as schema_name, index_name as index_name, non_unique as non_unique, column_name as column_name, expression as expression
|
|
50
|
+
from information_schema.statistics where table_schema = database()
|
|
51
|
+
and table_name in (${tables.map((t) => this.platform.quoteValue(t.table_name)).join(", ")})
|
|
52
|
+
order by schema_name, table_name, index_name, seq_in_index`;
|
|
53
|
+
const allIndexes = await connection.execute(sql);
|
|
54
|
+
const ret = {};
|
|
55
|
+
for (const index of allIndexes) {
|
|
56
|
+
const key = this.getTableKey(index);
|
|
57
|
+
const indexDef = {
|
|
58
|
+
columnNames: [index.column_name],
|
|
59
|
+
keyName: index.index_name,
|
|
60
|
+
unique: !index.non_unique,
|
|
61
|
+
primary: index.index_name === "PRIMARY",
|
|
62
|
+
constraint: !index.non_unique,
|
|
63
|
+
};
|
|
64
|
+
if (!index.column_name ||
|
|
65
|
+
index.column_name.match(/[(): ,"'`]/) ||
|
|
66
|
+
index.expression?.match(/ where /i)) {
|
|
67
|
+
indexDef.expression = index.expression; // required for the `getCreateIndexSQL()` call
|
|
68
|
+
indexDef.expression = this.getCreateIndexSQL(index.table_name, indexDef, !!index.expression);
|
|
69
|
+
}
|
|
70
|
+
ret[key] ??= [];
|
|
71
|
+
ret[key].push(indexDef);
|
|
72
|
+
}
|
|
73
|
+
for (const key of Object.keys(ret)) {
|
|
74
|
+
ret[key] = await this.mapIndexes(ret[key]);
|
|
75
|
+
}
|
|
76
|
+
return ret;
|
|
77
|
+
}
|
|
78
|
+
async getAllColumns(connection, tables) {
|
|
79
|
+
const sql = `select table_name as table_name,
|
|
80
|
+
nullif(table_schema, schema()) as schema_name,
|
|
81
|
+
column_name as column_name,
|
|
82
|
+
column_default as column_default,
|
|
83
|
+
column_comment as column_comment,
|
|
84
|
+
is_nullable as is_nullable,
|
|
85
|
+
data_type as data_type,
|
|
86
|
+
column_type as column_type,
|
|
87
|
+
column_key as column_key,
|
|
88
|
+
extra as extra,
|
|
89
|
+
generation_expression as generation_expression,
|
|
90
|
+
numeric_precision as numeric_precision,
|
|
91
|
+
numeric_scale as numeric_scale,
|
|
92
|
+
ifnull(datetime_precision, character_maximum_length) length
|
|
93
|
+
from information_schema.columns where table_schema = database() and table_name in (${tables.map((t) => this.platform.quoteValue(t.table_name))})
|
|
94
|
+
order by ordinal_position`;
|
|
95
|
+
const allColumns = await connection.execute(sql);
|
|
96
|
+
const str = (val) => (val != null ? "" + val : val);
|
|
97
|
+
const extra = (val) => val
|
|
98
|
+
.replace(/auto_increment|default_generated|(stored|virtual) generated/i, "")
|
|
99
|
+
.trim();
|
|
100
|
+
const ret = {};
|
|
101
|
+
for (const col of allColumns) {
|
|
102
|
+
const mappedType = this.platform.getMappedType(col.column_type);
|
|
103
|
+
const defaultValue = str(this.normalizeDefaultValue(col.column_default, col.length));
|
|
104
|
+
const key = this.getTableKey(col);
|
|
105
|
+
const generated = col.generation_expression
|
|
106
|
+
? `${col.generation_expression} ${col.extra.match(/stored generated/i) ? "stored" : "virtual"}`
|
|
107
|
+
: undefined;
|
|
108
|
+
ret[key] ??= [];
|
|
109
|
+
ret[key].push({
|
|
110
|
+
name: col.column_name,
|
|
111
|
+
type: this.platform.isNumericColumn(mappedType)
|
|
112
|
+
? col.column_type.replace(/ unsigned$/, "").replace(/\(\d+\)$/, "")
|
|
113
|
+
: col.column_type,
|
|
114
|
+
mappedType,
|
|
115
|
+
unsigned: col.column_type.endsWith(" unsigned"),
|
|
116
|
+
length: col.length,
|
|
117
|
+
default: this.wrap(defaultValue, mappedType),
|
|
118
|
+
nullable: col.is_nullable === "YES",
|
|
119
|
+
primary: col.column_key === "PRI",
|
|
120
|
+
unique: col.column_key === "UNI",
|
|
121
|
+
autoincrement: col.extra === "auto_increment",
|
|
122
|
+
precision: col.numeric_precision,
|
|
123
|
+
scale: col.numeric_scale,
|
|
124
|
+
comment: col.column_comment,
|
|
125
|
+
extra: extra(col.extra),
|
|
126
|
+
generated,
|
|
127
|
+
});
|
|
128
|
+
}
|
|
129
|
+
return ret;
|
|
130
|
+
}
|
|
131
|
+
async getAllChecks(connection, tables) {
|
|
132
|
+
/* istanbul ignore next */
|
|
133
|
+
if (!(await this.supportsCheckConstraints(connection))) {
|
|
134
|
+
return {};
|
|
135
|
+
}
|
|
136
|
+
const sql = this.getChecksSQL(tables);
|
|
137
|
+
const allChecks = await connection.execute(sql);
|
|
138
|
+
const ret = {};
|
|
139
|
+
for (const check of allChecks) {
|
|
140
|
+
const key = this.getTableKey(check);
|
|
141
|
+
ret[key] ??= [];
|
|
142
|
+
ret[key].push({
|
|
143
|
+
name: check.name,
|
|
144
|
+
columnName: check.column_name,
|
|
145
|
+
definition: `check ${check.expression}`,
|
|
146
|
+
expression: check.expression.replace(/^\((.*)\)$/, "$1"),
|
|
147
|
+
});
|
|
148
|
+
}
|
|
149
|
+
return ret;
|
|
150
|
+
}
|
|
151
|
+
async getAllForeignKeys(connection, tables) {
|
|
152
|
+
const sql = `select k.constraint_name as constraint_name, nullif(k.table_schema, schema()) as schema_name, k.table_name as table_name, k.column_name as column_name, k.referenced_table_name as referenced_table_name, k.referenced_column_name as referenced_column_name, c.update_rule as update_rule, c.delete_rule as delete_rule
|
|
153
|
+
from information_schema.key_column_usage k
|
|
154
|
+
inner join information_schema.referential_constraints c on c.constraint_name = k.constraint_name and c.table_name = k.table_name
|
|
155
|
+
where k.table_name in (${tables.map((t) => this.platform.quoteValue(t.table_name)).join(", ")})
|
|
156
|
+
and k.table_schema = database() and c.constraint_schema = database() and k.referenced_column_name is not null
|
|
157
|
+
order by constraint_name, k.ordinal_position`;
|
|
158
|
+
const allFks = await connection.execute(sql);
|
|
159
|
+
const ret = {};
|
|
160
|
+
for (const fk of allFks) {
|
|
161
|
+
const key = this.getTableKey(fk);
|
|
162
|
+
ret[key] ??= [];
|
|
163
|
+
ret[key].push(fk);
|
|
164
|
+
}
|
|
165
|
+
Object.keys(ret).forEach((key) => {
|
|
166
|
+
const parts = key.split(".");
|
|
167
|
+
/* istanbul ignore next */
|
|
168
|
+
const schemaName = parts.length > 1 ? parts[0] : undefined;
|
|
169
|
+
ret[key] = this.mapForeignKeys(ret[key], key, schemaName);
|
|
170
|
+
});
|
|
171
|
+
return ret;
|
|
172
|
+
}
|
|
173
|
+
getPreAlterTable(tableDiff, safe) {
|
|
174
|
+
// Dropping primary keys requires to unset autoincrement attribute on the particular column first.
|
|
175
|
+
const pk = Object.values(tableDiff.removedIndexes).find((idx) => idx.primary);
|
|
176
|
+
if (!pk || safe) {
|
|
177
|
+
return "";
|
|
178
|
+
}
|
|
179
|
+
return pk.columnNames
|
|
180
|
+
.filter((col) => tableDiff.fromTable.hasColumn(col))
|
|
181
|
+
.map((col) => tableDiff.fromTable.getColumn(col))
|
|
182
|
+
.filter((col) => col.autoincrement)
|
|
183
|
+
.map((col) => `alter table \`${tableDiff.name}\` modify \`${col.name}\` ${this.getColumnDeclarationSQL({ ...col, autoincrement: false })}`)
|
|
184
|
+
.join(";\n");
|
|
185
|
+
}
|
|
186
|
+
configureColumnDefault(column, col, knex, changedProperties) {
|
|
187
|
+
if (changedProperties || column.default !== undefined) {
|
|
188
|
+
if (column.default == null) {
|
|
189
|
+
col.defaultTo(null);
|
|
190
|
+
}
|
|
191
|
+
else {
|
|
192
|
+
col.defaultTo(knex.raw(column.default + (column.extra ? " " + column.extra : "")));
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
return col;
|
|
196
|
+
}
|
|
197
|
+
getRenameColumnSQL(tableName, oldColumnName, to) {
|
|
198
|
+
tableName = this.platform.quoteIdentifier(tableName);
|
|
199
|
+
oldColumnName = this.platform.quoteIdentifier(oldColumnName);
|
|
200
|
+
const columnName = this.platform.quoteIdentifier(to.name);
|
|
201
|
+
return `alter table ${tableName} change ${oldColumnName} ${columnName} ${this.getColumnDeclarationSQL(to)}`;
|
|
202
|
+
}
|
|
203
|
+
getRenameIndexSQL(tableName, index, oldIndexName) {
|
|
204
|
+
tableName = this.platform.quoteIdentifier(tableName);
|
|
205
|
+
oldIndexName = this.platform.quoteIdentifier(oldIndexName);
|
|
206
|
+
const keyName = this.platform.quoteIdentifier(index.keyName);
|
|
207
|
+
return `alter table ${tableName} rename index ${oldIndexName} to ${keyName}`;
|
|
208
|
+
}
|
|
209
|
+
getChangeColumnCommentSQL(tableName, to, schemaName) {
|
|
210
|
+
tableName = this.platform.quoteIdentifier(tableName);
|
|
211
|
+
const columnName = this.platform.quoteIdentifier(to.name);
|
|
212
|
+
return `alter table ${tableName} modify ${columnName} ${this.getColumnDeclarationSQL(to)}`;
|
|
213
|
+
}
|
|
214
|
+
createTableColumn(table, column, fromTable, changedProperties) {
|
|
215
|
+
if (column.mappedType instanceof core_1.MediumIntType) {
|
|
216
|
+
return table.specificType(column.name, this.getColumnDeclarationSQL(column, true));
|
|
217
|
+
}
|
|
218
|
+
return super.createTableColumn(table, column, fromTable, changedProperties);
|
|
219
|
+
}
|
|
220
|
+
configureColumn(column, col, knex, changedProperties) {
|
|
221
|
+
if (column.mappedType instanceof core_1.MediumIntType) {
|
|
222
|
+
return col;
|
|
223
|
+
}
|
|
224
|
+
return super.configureColumn(column, col, knex, changedProperties);
|
|
225
|
+
}
|
|
226
|
+
getColumnDeclarationSQL(col, addPrimary = false) {
|
|
227
|
+
let ret = col.type;
|
|
228
|
+
ret += col.unsigned ? " unsigned" : "";
|
|
229
|
+
ret += col.autoincrement ? " auto_increment" : "";
|
|
230
|
+
ret += " ";
|
|
231
|
+
ret += col.nullable ? "null" : "not null";
|
|
232
|
+
ret += col.default ? " default " + col.default : "";
|
|
233
|
+
if (addPrimary && col.primary) {
|
|
234
|
+
ret += " primary key";
|
|
235
|
+
}
|
|
236
|
+
ret += col.comment
|
|
237
|
+
? ` comment ${this.platform.quoteValue(col.comment)}`
|
|
238
|
+
: "";
|
|
239
|
+
return ret;
|
|
240
|
+
}
|
|
241
|
+
/* istanbul ignore next kept for BC */
|
|
242
|
+
getForeignKeysSQL(tableName, schemaName) {
|
|
243
|
+
return (`select distinct k.constraint_name as constraint_name, k.column_name as column_name, k.referenced_table_name as referenced_table_name, k.referenced_column_name as referenced_column_name, c.update_rule as update_rule, c.delete_rule as delete_rule ` +
|
|
244
|
+
`from information_schema.key_column_usage k ` +
|
|
245
|
+
`inner join information_schema.referential_constraints c on c.constraint_name = k.constraint_name and c.table_name = '${tableName}' ` +
|
|
246
|
+
`where k.table_name = '${tableName}' and k.table_schema = database() and c.constraint_schema = database() and k.referenced_column_name is not null`);
|
|
247
|
+
}
|
|
248
|
+
async getAllEnumDefinitions(connection, tables) {
|
|
249
|
+
const sql = `select column_name as column_name, column_type as column_type, table_name as table_name
|
|
250
|
+
from information_schema.columns
|
|
251
|
+
where data_type = 'enum' and table_name in (${tables.map((t) => `'${t.table_name}'`).join(", ")}) and table_schema = database()`;
|
|
252
|
+
const enums = await connection.execute(sql);
|
|
253
|
+
return enums.reduce((o, item) => {
|
|
254
|
+
o[item.table_name] ??= {};
|
|
255
|
+
o[item.table_name][item.column_name] = item.column_type
|
|
256
|
+
.match(/enum\((.*)\)/)[1]
|
|
257
|
+
.split(",")
|
|
258
|
+
.map((item) => item.match(/'(.*)'/)[1]);
|
|
259
|
+
return o;
|
|
260
|
+
}, {});
|
|
261
|
+
}
|
|
262
|
+
async supportsCheckConstraints(connection) {
|
|
263
|
+
if (this._cache.supportsCheckConstraints != null) {
|
|
264
|
+
return this._cache.supportsCheckConstraints;
|
|
265
|
+
}
|
|
266
|
+
const sql = `select 1 from information_schema.tables where table_name = 'CHECK_CONSTRAINTS' and table_schema = 'information_schema'`;
|
|
267
|
+
const res = await connection.execute(sql);
|
|
268
|
+
return (this._cache.supportsCheckConstraints = res.length > 0);
|
|
269
|
+
}
|
|
270
|
+
getChecksSQL(tables) {
|
|
271
|
+
return `select cc.constraint_schema as table_schema, tc.table_name as table_name, cc.constraint_name as name, cc.check_clause as expression
|
|
272
|
+
from information_schema.check_constraints cc
|
|
273
|
+
join information_schema.table_constraints tc
|
|
274
|
+
on tc.constraint_schema = cc.constraint_schema
|
|
275
|
+
and tc.constraint_name = cc.constraint_name
|
|
276
|
+
and constraint_type = 'CHECK'
|
|
277
|
+
where tc.table_name in (${tables.map((t) => this.platform.quoteValue(t.table_name))}) and tc.constraint_schema = database()
|
|
278
|
+
order by tc.constraint_name`;
|
|
279
|
+
}
|
|
280
|
+
/* istanbul ignore next */
|
|
281
|
+
async getChecks(connection, tableName, schemaName, columns) {
|
|
282
|
+
const res = await this.getAllChecks(connection, [
|
|
283
|
+
{ table_name: tableName, schema_name: schemaName },
|
|
284
|
+
]);
|
|
285
|
+
return res[tableName];
|
|
286
|
+
}
|
|
287
|
+
/* istanbul ignore next */
|
|
288
|
+
async getEnumDefinitions(connection, checks, tableName, schemaName) {
|
|
289
|
+
const res = await this.getAllEnumDefinitions(connection, [
|
|
290
|
+
{ table_name: tableName, schema_name: schemaName },
|
|
291
|
+
]);
|
|
292
|
+
return res[tableName];
|
|
293
|
+
}
|
|
294
|
+
/* istanbul ignore next */
|
|
295
|
+
async getColumns(connection, tableName, schemaName) {
|
|
296
|
+
const res = await this.getAllColumns(connection, [
|
|
297
|
+
{ table_name: tableName, schema_name: schemaName },
|
|
298
|
+
]);
|
|
299
|
+
return res[tableName];
|
|
300
|
+
}
|
|
301
|
+
/* istanbul ignore next */
|
|
302
|
+
async getIndexes(connection, tableName, schemaName) {
|
|
303
|
+
const res = await this.getAllIndexes(connection, [
|
|
304
|
+
{ table_name: tableName, schema_name: schemaName },
|
|
305
|
+
]);
|
|
306
|
+
return res[tableName];
|
|
307
|
+
}
|
|
308
|
+
normalizeDefaultValue(defaultValue, length) {
|
|
309
|
+
return super.normalizeDefaultValue(defaultValue, length, MySqlSchemaHelper.DEFAULT_VALUES);
|
|
310
|
+
}
|
|
311
|
+
wrap(val, type) {
|
|
312
|
+
const stringType = type instanceof core_1.StringType ||
|
|
313
|
+
type instanceof core_1.TextType ||
|
|
314
|
+
type instanceof core_1.EnumType;
|
|
315
|
+
return typeof val === "string" && val.length > 0 && stringType
|
|
316
|
+
? this.platform.quoteValue(val)
|
|
317
|
+
: val;
|
|
318
|
+
}
|
|
319
|
+
}
|
|
320
|
+
exports.MySqlSchemaHelper = MySqlSchemaHelper;
|