@mikro-orm/knex 6.4.6-dev.9 → 7.0.0-dev.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/AbstractSqlConnection.d.ts +15 -25
- package/AbstractSqlConnection.js +101 -126
- package/AbstractSqlDriver.d.ts +20 -13
- package/AbstractSqlDriver.js +73 -54
- package/AbstractSqlPlatform.d.ts +15 -3
- package/AbstractSqlPlatform.js +32 -11
- package/README.md +0 -2
- package/SqlEntityManager.d.ts +5 -6
- package/SqlEntityManager.js +5 -5
- package/SqlEntityRepository.d.ts +1 -6
- package/SqlEntityRepository.js +0 -6
- package/dialects/mssql/MsSqlNativeQueryBuilder.d.ts +12 -0
- package/dialects/mssql/MsSqlNativeQueryBuilder.js +161 -0
- package/dialects/mssql/index.d.ts +1 -1
- package/dialects/mssql/index.js +1 -1
- package/dialects/mysql/MySqlExceptionConverter.js +1 -0
- package/dialects/mysql/MySqlNativeQueryBuilder.d.ts +7 -0
- package/dialects/mysql/MySqlNativeQueryBuilder.js +81 -0
- package/dialects/mysql/MySqlPlatform.d.ts +10 -2
- package/dialects/mysql/MySqlPlatform.js +23 -1
- package/dialects/mysql/MySqlSchemaHelper.d.ts +6 -12
- package/dialects/mysql/MySqlSchemaHelper.js +42 -75
- package/dialects/mysql/index.d.ts +1 -3
- package/dialects/mysql/index.js +1 -3
- package/dialects/postgresql/PostgreSqlNativeQueryBuilder.d.ts +5 -0
- package/dialects/postgresql/PostgreSqlNativeQueryBuilder.js +12 -0
- package/dialects/postgresql/index.d.ts +1 -1
- package/dialects/postgresql/index.js +1 -1
- package/dialects/sqlite/BaseSqliteConnection.d.ts +0 -5
- package/dialects/sqlite/BaseSqliteConnection.js +4 -42
- package/dialects/sqlite/BaseSqlitePlatform.d.ts +15 -3
- package/dialects/sqlite/BaseSqlitePlatform.js +20 -4
- package/dialects/sqlite/SqliteExceptionConverter.d.ts +9 -0
- package/dialects/sqlite/SqliteExceptionConverter.js +55 -0
- package/dialects/sqlite/SqliteNativeQueryBuilder.d.ts +6 -0
- package/dialects/sqlite/SqliteNativeQueryBuilder.js +15 -0
- package/dialects/sqlite/SqliteSchemaHelper.d.ts +38 -0
- package/dialects/sqlite/SqliteSchemaHelper.js +384 -0
- package/dialects/sqlite/index.d.ts +3 -5
- package/dialects/sqlite/index.js +3 -5
- package/index.d.ts +1 -2
- package/index.js +3 -5
- package/index.mjs +10 -13
- package/package.json +4 -18
- package/query/CriteriaNodeFactory.js +5 -5
- package/query/NativeQueryBuilder.d.ts +108 -0
- package/query/NativeQueryBuilder.js +429 -0
- package/query/ObjectCriteriaNode.js +3 -3
- package/query/QueryBuilder.d.ts +30 -34
- package/query/QueryBuilder.js +112 -123
- package/query/QueryBuilderHelper.d.ts +27 -23
- package/query/QueryBuilderHelper.js +174 -168
- package/query/ScalarCriteriaNode.js +4 -0
- package/query/index.d.ts +1 -0
- package/query/index.js +1 -0
- package/schema/DatabaseSchema.js +9 -6
- package/schema/DatabaseTable.d.ts +2 -1
- package/schema/DatabaseTable.js +9 -5
- package/schema/SchemaComparator.d.ts +1 -2
- package/schema/SchemaComparator.js +31 -18
- package/schema/SchemaHelper.d.ts +27 -33
- package/schema/SchemaHelper.js +294 -184
- package/schema/SqlSchemaGenerator.d.ts +3 -9
- package/schema/SqlSchemaGenerator.js +105 -229
- package/typings.d.ts +7 -17
- package/MonkeyPatchable.d.ts +0 -18
- package/MonkeyPatchable.js +0 -60
- package/dialects/mssql/MsSqlColumnCompiler.d.ts +0 -4
- package/dialects/mssql/MsSqlColumnCompiler.js +0 -10
- package/dialects/mssql/MsSqlKnexDialect.d.ts +0 -6
- package/dialects/mssql/MsSqlKnexDialect.js +0 -22
- package/dialects/mssql/MsSqlQueryCompiler.d.ts +0 -12
- package/dialects/mssql/MsSqlQueryCompiler.js +0 -94
- package/dialects/mssql/MsSqlTableCompiler.d.ts +0 -9
- package/dialects/mssql/MsSqlTableCompiler.js +0 -40
- package/dialects/mysql/MariaDbKnexDialect.d.ts +0 -6
- package/dialects/mysql/MariaDbKnexDialect.js +0 -16
- package/dialects/mysql/MySqlColumnCompiler.d.ts +0 -7
- package/dialects/mysql/MySqlColumnCompiler.js +0 -26
- package/dialects/mysql/MySqlConnection.d.ts +0 -8
- package/dialects/mysql/MySqlConnection.js +0 -43
- package/dialects/mysql/MySqlKnexDialect.d.ts +0 -5
- package/dialects/mysql/MySqlKnexDialect.js +0 -17
- package/dialects/mysql/MySqlQueryCompiler.d.ts +0 -5
- package/dialects/mysql/MySqlQueryCompiler.js +0 -23
- package/dialects/postgresql/PostgreSqlKnexDialect.d.ts +0 -7
- package/dialects/postgresql/PostgreSqlKnexDialect.js +0 -20
- package/dialects/postgresql/PostgreSqlQueryCompiler.d.ts +0 -4
- package/dialects/postgresql/PostgreSqlQueryCompiler.js +0 -13
- package/dialects/postgresql/PostgreSqlTableCompiler.d.ts +0 -11
- package/dialects/postgresql/PostgreSqlTableCompiler.js +0 -89
- package/dialects/sqlite/BaseSqliteSchemaHelper.d.ts +0 -28
- package/dialects/sqlite/BaseSqliteSchemaHelper.js +0 -200
- package/dialects/sqlite/BetterSqliteKnexDialect.d.ts +0 -5
- package/dialects/sqlite/BetterSqliteKnexDialect.js +0 -15
- package/dialects/sqlite/LibSqlKnexDialect.d.ts +0 -11
- package/dialects/sqlite/LibSqlKnexDialect.js +0 -85
- package/dialects/sqlite/SqliteKnexDialect.d.ts +0 -8
- package/dialects/sqlite/SqliteKnexDialect.js +0 -67
- package/dialects/sqlite/SqliteTableCompiler.d.ts +0 -6
- package/dialects/sqlite/SqliteTableCompiler.js +0 -71
package/schema/SchemaHelper.js
CHANGED
|
@@ -7,7 +7,7 @@ class SchemaHelper {
|
|
|
7
7
|
constructor(platform) {
|
|
8
8
|
this.platform = platform;
|
|
9
9
|
}
|
|
10
|
-
getSchemaBeginning(
|
|
10
|
+
getSchemaBeginning(_charset, disableForeignKeys) {
|
|
11
11
|
if (disableForeignKeys) {
|
|
12
12
|
return `${this.disableForeignKeysSQL()}\n`;
|
|
13
13
|
}
|
|
@@ -26,7 +26,10 @@ class SchemaHelper {
|
|
|
26
26
|
return '';
|
|
27
27
|
}
|
|
28
28
|
finalizeTable(table, charset, collate) {
|
|
29
|
-
|
|
29
|
+
return '';
|
|
30
|
+
}
|
|
31
|
+
appendComments(table) {
|
|
32
|
+
return [];
|
|
30
33
|
}
|
|
31
34
|
supportsSchemaConstraints() {
|
|
32
35
|
return true;
|
|
@@ -42,10 +45,6 @@ class SchemaHelper {
|
|
|
42
45
|
}
|
|
43
46
|
return +match[1];
|
|
44
47
|
}
|
|
45
|
-
async getForeignKeys(connection, tableName, schemaName) {
|
|
46
|
-
const fks = await connection.execute(this.getForeignKeysSQL(tableName, schemaName));
|
|
47
|
-
return this.mapForeignKeys(fks, tableName, schemaName);
|
|
48
|
-
}
|
|
49
48
|
getTableKey(t) {
|
|
50
49
|
const unquote = (str) => str.replace(/['"`]/g, '');
|
|
51
50
|
const parts = t.table_name.split('.');
|
|
@@ -57,9 +56,6 @@ class SchemaHelper {
|
|
|
57
56
|
}
|
|
58
57
|
return unquote(t.table_name);
|
|
59
58
|
}
|
|
60
|
-
async getEnumDefinitions(connection, checks, tableName, schemaName) {
|
|
61
|
-
return {};
|
|
62
|
-
}
|
|
63
59
|
getCreateNativeEnumSQL(name, values, schema) {
|
|
64
60
|
throw new Error('Not supported by given driver');
|
|
65
61
|
}
|
|
@@ -69,51 +65,159 @@ class SchemaHelper {
|
|
|
69
65
|
getAlterNativeEnumSQL(name, schema, value, items, oldItems) {
|
|
70
66
|
throw new Error('Not supported by given driver');
|
|
71
67
|
}
|
|
72
|
-
async loadInformationSchema(schema, connection, tables, schemas) {
|
|
73
|
-
for (const t of tables) {
|
|
74
|
-
const table = schema.addTable(t.table_name, t.schema_name, t.table_comment);
|
|
75
|
-
const cols = await this.getColumns(connection, table.name, table.schema);
|
|
76
|
-
const indexes = await this.getIndexes(connection, table.name, table.schema);
|
|
77
|
-
const checks = await this.getChecks(connection, table.name, table.schema, cols);
|
|
78
|
-
const pks = await this.getPrimaryKeys(connection, indexes, table.name, table.schema);
|
|
79
|
-
const fks = await this.getForeignKeys(connection, table.name, table.schema);
|
|
80
|
-
const enums = await this.getEnumDefinitions(connection, checks, table.name, table.schema);
|
|
81
|
-
table.init(cols, indexes, checks, pks, fks, enums);
|
|
82
|
-
}
|
|
83
|
-
}
|
|
84
68
|
getListTablesSQL(schemaName) {
|
|
85
69
|
throw new Error('Not supported by given driver');
|
|
86
70
|
}
|
|
87
71
|
getRenameColumnSQL(tableName, oldColumnName, to, schemaName) {
|
|
88
|
-
tableName = this.
|
|
89
|
-
oldColumnName = this.
|
|
90
|
-
const columnName = this.
|
|
72
|
+
tableName = this.quote(tableName);
|
|
73
|
+
oldColumnName = this.quote(oldColumnName);
|
|
74
|
+
const columnName = this.quote(to.name);
|
|
91
75
|
const schemaReference = (schemaName !== undefined && schemaName !== 'public') ? ('"' + schemaName + '".') : '';
|
|
92
76
|
const tableReference = schemaReference + tableName;
|
|
93
77
|
return `alter table ${tableReference} rename column ${oldColumnName} to ${columnName}`;
|
|
94
78
|
}
|
|
95
|
-
getCreateIndexSQL(tableName, index
|
|
79
|
+
getCreateIndexSQL(tableName, index) {
|
|
96
80
|
/* istanbul ignore next */
|
|
97
|
-
if (index.expression
|
|
81
|
+
if (index.expression) {
|
|
98
82
|
return index.expression;
|
|
99
83
|
}
|
|
100
|
-
tableName = this.
|
|
101
|
-
const keyName = this.
|
|
102
|
-
const
|
|
103
|
-
|
|
104
|
-
|
|
84
|
+
tableName = this.quote(tableName);
|
|
85
|
+
const keyName = this.quote(index.keyName);
|
|
86
|
+
const defer = index.deferMode ? ` deferrable initially ${index.deferMode}` : '';
|
|
87
|
+
let sql = `create ${index.unique ? 'unique ' : ''}index ${keyName} on ${tableName} `;
|
|
88
|
+
if (index.unique && index.constraint) {
|
|
89
|
+
sql = `alter table ${tableName} add constraint ${keyName} unique `;
|
|
90
|
+
}
|
|
91
|
+
if (index.columnNames.some(column => column.includes('.'))) {
|
|
92
|
+
// JSON columns can have unique index but not unique constraint, and we need to distinguish those, so we can properly drop them
|
|
93
|
+
const sql = `create ${index.unique ? 'unique ' : ''}index ${keyName} on ${tableName} `;
|
|
94
|
+
const columns = this.platform.getJsonIndexDefinition(index);
|
|
95
|
+
return `${sql}(${columns.join(', ')})${defer}`;
|
|
105
96
|
}
|
|
106
|
-
return `${sql}(${index.columnNames.map(c => this.
|
|
97
|
+
return `${sql}(${index.columnNames.map(c => this.quote(c)).join(', ')})${defer}`;
|
|
107
98
|
}
|
|
108
99
|
getDropIndexSQL(tableName, index) {
|
|
109
|
-
return `drop index ${this.
|
|
100
|
+
return `drop index ${this.quote(index.keyName)}`;
|
|
110
101
|
}
|
|
111
102
|
getRenameIndexSQL(tableName, index, oldIndexName) {
|
|
112
|
-
return [
|
|
103
|
+
return [
|
|
104
|
+
this.getDropIndexSQL(tableName, { ...index, keyName: oldIndexName }),
|
|
105
|
+
this.getCreateIndexSQL(tableName, index),
|
|
106
|
+
];
|
|
107
|
+
}
|
|
108
|
+
alterTable(diff, safe) {
|
|
109
|
+
const ret = [];
|
|
110
|
+
const [schemaName, tableName] = this.splitTableName(diff.name);
|
|
111
|
+
if (this.platform.supportsNativeEnums()) {
|
|
112
|
+
const changedNativeEnums = [];
|
|
113
|
+
for (const { column, changedProperties } of Object.values(diff.changedColumns)) {
|
|
114
|
+
if (!column.nativeEnumName) {
|
|
115
|
+
continue;
|
|
116
|
+
}
|
|
117
|
+
const key = schemaName && schemaName !== this.platform.getDefaultSchemaName() && !column.nativeEnumName.includes('.')
|
|
118
|
+
? schemaName + '.' + column.nativeEnumName
|
|
119
|
+
: column.nativeEnumName;
|
|
120
|
+
if (changedProperties.has('enumItems') && key in diff.fromTable.nativeEnums) {
|
|
121
|
+
changedNativeEnums.push([column.nativeEnumName, column.enumItems, diff.fromTable.nativeEnums[key].items]);
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
core_1.Utils.removeDuplicates(changedNativeEnums).forEach(([enumName, itemsNew, itemsOld]) => {
|
|
125
|
+
// postgres allows only adding new items, the values are case insensitive
|
|
126
|
+
itemsOld = itemsOld.map(v => v.toLowerCase());
|
|
127
|
+
const newItems = itemsNew.filter(val => !itemsOld.includes(val.toLowerCase()));
|
|
128
|
+
if (enumName.includes('.')) {
|
|
129
|
+
const [enumSchemaName, rawEnumName] = enumName.split('.');
|
|
130
|
+
ret.push(...newItems.map(val => this.getAlterNativeEnumSQL(rawEnumName, enumSchemaName, val, itemsNew, itemsOld)));
|
|
131
|
+
return;
|
|
132
|
+
}
|
|
133
|
+
ret.push(...newItems.map(val => this.getAlterNativeEnumSQL(enumName, schemaName, val, itemsNew, itemsOld)));
|
|
134
|
+
});
|
|
135
|
+
}
|
|
136
|
+
for (const index of Object.values(diff.removedIndexes)) {
|
|
137
|
+
ret.push(this.dropIndex(diff.name, index));
|
|
138
|
+
}
|
|
139
|
+
for (const index of Object.values(diff.changedIndexes)) {
|
|
140
|
+
ret.push(this.dropIndex(diff.name, index));
|
|
141
|
+
}
|
|
142
|
+
for (const check of Object.values(diff.removedChecks)) {
|
|
143
|
+
ret.push(this.dropConstraint(diff.name, check.name));
|
|
144
|
+
}
|
|
145
|
+
for (const check of Object.values(diff.changedChecks)) {
|
|
146
|
+
ret.push(this.dropConstraint(diff.name, check.name));
|
|
147
|
+
}
|
|
148
|
+
/* istanbul ignore else */
|
|
149
|
+
if (!safe && Object.values(diff.removedColumns).length > 0) {
|
|
150
|
+
ret.push(this.getDropColumnsSQL(tableName, Object.values(diff.removedColumns), schemaName));
|
|
151
|
+
}
|
|
152
|
+
if (Object.values(diff.addedColumns).length > 0) {
|
|
153
|
+
this.append(ret, this.getAddColumnsSQL(diff.toTable, Object.values(diff.addedColumns)));
|
|
154
|
+
}
|
|
155
|
+
for (const column of Object.values(diff.addedColumns)) {
|
|
156
|
+
const foreignKey = Object.values(diff.addedForeignKeys).find(fk => fk.columnNames.length === 1 && fk.columnNames[0] === column.name);
|
|
157
|
+
if (foreignKey && this.options.createForeignKeyConstraints) {
|
|
158
|
+
delete diff.addedForeignKeys[foreignKey.constraintName];
|
|
159
|
+
ret.push(this.createForeignKey(diff.toTable, foreignKey));
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
for (const { column, changedProperties } of Object.values(diff.changedColumns)) {
|
|
163
|
+
if (changedProperties.size === 1 && changedProperties.has('comment')) {
|
|
164
|
+
continue;
|
|
165
|
+
}
|
|
166
|
+
if (changedProperties.size === 1 && changedProperties.has('enumItems') && column.nativeEnumName) {
|
|
167
|
+
continue;
|
|
168
|
+
}
|
|
169
|
+
this.append(ret, this.alterTableColumn(column, diff.fromTable, changedProperties));
|
|
170
|
+
}
|
|
171
|
+
for (const { column, changedProperties } of Object.values(diff.changedColumns).filter(diff => diff.changedProperties.has('comment'))) {
|
|
172
|
+
if (['type', 'nullable', 'autoincrement', 'unsigned', 'default', 'enumItems'].some(t => changedProperties.has(t))) {
|
|
173
|
+
continue; // will be handled via column update
|
|
174
|
+
}
|
|
175
|
+
ret.push(this.getChangeColumnCommentSQL(tableName, column, schemaName));
|
|
176
|
+
}
|
|
177
|
+
for (const [oldColumnName, column] of Object.entries(diff.renamedColumns)) {
|
|
178
|
+
ret.push(this.getRenameColumnSQL(tableName, oldColumnName, column, schemaName));
|
|
179
|
+
}
|
|
180
|
+
for (const foreignKey of Object.values(diff.addedForeignKeys)) {
|
|
181
|
+
ret.push(this.createForeignKey(diff.toTable, foreignKey));
|
|
182
|
+
}
|
|
183
|
+
for (const foreignKey of Object.values(diff.changedForeignKeys)) {
|
|
184
|
+
ret.push(this.createForeignKey(diff.toTable, foreignKey));
|
|
185
|
+
}
|
|
186
|
+
for (const index of Object.values(diff.addedIndexes)) {
|
|
187
|
+
ret.push(this.createIndex(index, diff.toTable));
|
|
188
|
+
}
|
|
189
|
+
for (const index of Object.values(diff.changedIndexes)) {
|
|
190
|
+
ret.push(this.createIndex(index, diff.toTable, true));
|
|
191
|
+
}
|
|
192
|
+
for (const [oldIndexName, index] of Object.entries(diff.renamedIndexes)) {
|
|
193
|
+
if (index.unique) {
|
|
194
|
+
ret.push(this.dropIndex(diff.name, index, oldIndexName));
|
|
195
|
+
ret.push(this.createIndex(index, diff.toTable));
|
|
196
|
+
}
|
|
197
|
+
else {
|
|
198
|
+
ret.push(...this.getRenameIndexSQL(diff.name, index, oldIndexName));
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
for (const check of Object.values(diff.addedChecks)) {
|
|
202
|
+
ret.push(this.createCheck(diff.toTable, check));
|
|
203
|
+
}
|
|
204
|
+
for (const check of Object.values(diff.changedChecks)) {
|
|
205
|
+
ret.push(this.createCheck(diff.toTable, check));
|
|
206
|
+
}
|
|
207
|
+
if ('changedComment' in diff) {
|
|
208
|
+
ret.push(this.alterTableComment(diff.toTable, diff.changedComment));
|
|
209
|
+
}
|
|
210
|
+
return ret;
|
|
211
|
+
}
|
|
212
|
+
getAddColumnsSQL(table, columns) {
|
|
213
|
+
const adds = columns.map(column => {
|
|
214
|
+
return `add ${this.createTableColumn(column, table)}`;
|
|
215
|
+
}).join(', ');
|
|
216
|
+
return [`alter table ${table.getQuotedName()} ${adds}`];
|
|
113
217
|
}
|
|
114
218
|
getDropColumnsSQL(tableName, columns, schemaName) {
|
|
115
|
-
const name = this.
|
|
116
|
-
const drops = columns.map(column => `drop column ${this.
|
|
219
|
+
const name = this.quote(this.getTableName(tableName, schemaName));
|
|
220
|
+
const drops = columns.map(column => `drop column ${this.quote(column.name)}`).join(', ');
|
|
117
221
|
return `alter table ${name} ${drops}`;
|
|
118
222
|
}
|
|
119
223
|
hasNonDefaultPrimaryKeyName(table) {
|
|
@@ -124,51 +228,55 @@ class SchemaHelper {
|
|
|
124
228
|
const defaultName = this.platform.getDefaultPrimaryName(table.name, pkIndex.columnNames);
|
|
125
229
|
return pkIndex?.keyName !== defaultName;
|
|
126
230
|
}
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
const primaryKey = !changedProperties && !this.hasNonDefaultPrimaryKeyName(fromTable);
|
|
131
|
-
if (column.mappedType instanceof core_1.BigIntType) {
|
|
132
|
-
return table.bigIncrements(column.name, { primaryKey });
|
|
133
|
-
}
|
|
134
|
-
return table.increments(column.name, { primaryKey });
|
|
135
|
-
}
|
|
136
|
-
if (column.mappedType instanceof core_1.EnumType && column.enumItems?.every(item => core_1.Utils.isString(item))) {
|
|
137
|
-
return table.enum(column.name, column.enumItems);
|
|
138
|
-
}
|
|
139
|
-
let columnType = column.type;
|
|
140
|
-
if (column.generated) {
|
|
141
|
-
columnType += ` generated always as ${column.generated}`;
|
|
142
|
-
}
|
|
143
|
-
return table.specificType(column.name, columnType);
|
|
144
|
-
}
|
|
145
|
-
configureColumn(column, col, knex, changedProperties) {
|
|
146
|
-
const guard = (key) => !changedProperties || changedProperties.has(key);
|
|
147
|
-
core_1.Utils.runIfNotEmpty(() => col.nullable(), column.nullable && guard('nullable'));
|
|
148
|
-
core_1.Utils.runIfNotEmpty(() => col.notNullable(), !column.nullable && !column.generated);
|
|
149
|
-
core_1.Utils.runIfNotEmpty(() => col.unsigned(), column.unsigned);
|
|
150
|
-
core_1.Utils.runIfNotEmpty(() => col.comment(this.processComment(column.comment)), column.comment);
|
|
151
|
-
this.configureColumnDefault(column, col, knex, changedProperties);
|
|
152
|
-
return col;
|
|
231
|
+
/* istanbul ignore next */
|
|
232
|
+
castColumn(name, type) {
|
|
233
|
+
return '';
|
|
153
234
|
}
|
|
154
|
-
|
|
155
|
-
const
|
|
156
|
-
if (changedProperties) {
|
|
157
|
-
|
|
235
|
+
alterTableColumn(column, table, changedProperties) {
|
|
236
|
+
const sql = [];
|
|
237
|
+
if (changedProperties.has('default') && column.default == null) {
|
|
238
|
+
sql.push(`alter table ${table.getQuotedName()} alter column ${this.quote(column.name)} drop default`);
|
|
158
239
|
}
|
|
159
|
-
|
|
160
|
-
|
|
240
|
+
if (changedProperties.has('type')) {
|
|
241
|
+
let type = column.type + (column.generated ? ` generated always as ${column.generated}` : '');
|
|
242
|
+
if (column.nativeEnumName) {
|
|
243
|
+
type = this.quote(this.getTableName(type, table.schema));
|
|
244
|
+
}
|
|
245
|
+
sql.push(`alter table ${table.getQuotedName()} alter column ${this.quote(column.name)} type ${type + this.castColumn(column.name, type)}`);
|
|
246
|
+
}
|
|
247
|
+
if (changedProperties.has('default') && column.default != null) {
|
|
248
|
+
sql.push(`alter table ${table.getQuotedName()} alter column ${this.quote(column.name)} set default ${column.default}`);
|
|
249
|
+
}
|
|
250
|
+
if (changedProperties.has('nullable')) {
|
|
251
|
+
const action = column.nullable ? 'drop' : 'set';
|
|
252
|
+
sql.push(`alter table ${table.getQuotedName()} alter column ${this.quote(column.name)} ${action} not null`);
|
|
253
|
+
}
|
|
254
|
+
return sql;
|
|
255
|
+
}
|
|
256
|
+
createTableColumn(column, table, changedProperties) {
|
|
257
|
+
const compositePK = table.getPrimaryKey()?.composite;
|
|
258
|
+
const primaryKey = !changedProperties && !this.hasNonDefaultPrimaryKeyName(table);
|
|
259
|
+
const columnType = column.type + (column.generated ? ` generated always as ${column.generated}` : '');
|
|
260
|
+
const useDefault = column.default != null && column.default !== 'null' && !column.autoincrement;
|
|
261
|
+
const col = [this.quote(column.name), columnType];
|
|
262
|
+
core_1.Utils.runIfNotEmpty(() => col.push('unsigned'), column.unsigned && this.platform.supportsUnsigned());
|
|
263
|
+
core_1.Utils.runIfNotEmpty(() => col.push('null'), column.nullable);
|
|
264
|
+
core_1.Utils.runIfNotEmpty(() => col.push('not null'), !column.nullable && !column.generated);
|
|
265
|
+
core_1.Utils.runIfNotEmpty(() => col.push('auto_increment'), column.autoincrement);
|
|
266
|
+
core_1.Utils.runIfNotEmpty(() => col.push('unique'), column.autoincrement && !column.primary);
|
|
267
|
+
if (column.autoincrement && !column.generated && !compositePK && (!changedProperties || changedProperties.has('autoincrement') || changedProperties.has('type'))) {
|
|
268
|
+
core_1.Utils.runIfNotEmpty(() => col.push('primary key'), primaryKey && column.primary);
|
|
161
269
|
}
|
|
162
|
-
|
|
270
|
+
core_1.Utils.runIfNotEmpty(() => col.push(`default ${column.default}`), useDefault);
|
|
271
|
+
core_1.Utils.runIfNotEmpty(() => col.push(column.extra), column.extra);
|
|
272
|
+
core_1.Utils.runIfNotEmpty(() => col.push(`comment ${this.platform.quoteValue(column.comment)}`), column.comment);
|
|
273
|
+
return col.join(' ');
|
|
163
274
|
}
|
|
164
275
|
getPreAlterTable(tableDiff, safe) {
|
|
165
|
-
return
|
|
276
|
+
return [];
|
|
166
277
|
}
|
|
167
278
|
getPostAlterTable(tableDiff, safe) {
|
|
168
|
-
return
|
|
169
|
-
}
|
|
170
|
-
getAlterColumnAutoincrement(tableName, column, schemaName) {
|
|
171
|
-
return '';
|
|
279
|
+
return [];
|
|
172
280
|
}
|
|
173
281
|
getChangeColumnCommentSQL(tableName, to, schemaName) {
|
|
174
282
|
return '';
|
|
@@ -176,15 +284,6 @@ class SchemaHelper {
|
|
|
176
284
|
async getNamespaces(connection) {
|
|
177
285
|
return [];
|
|
178
286
|
}
|
|
179
|
-
async getColumns(connection, tableName, schemaName) {
|
|
180
|
-
throw new Error('Not supported by given driver');
|
|
181
|
-
}
|
|
182
|
-
async getIndexes(connection, tableName, schemaName) {
|
|
183
|
-
throw new Error('Not supported by given driver');
|
|
184
|
-
}
|
|
185
|
-
async getChecks(connection, tableName, schemaName, columns) {
|
|
186
|
-
throw new Error('Not supported by given driver');
|
|
187
|
-
}
|
|
188
287
|
async mapIndexes(indexes) {
|
|
189
288
|
const map = {};
|
|
190
289
|
indexes.forEach(index => {
|
|
@@ -198,9 +297,6 @@ class SchemaHelper {
|
|
|
198
297
|
});
|
|
199
298
|
return Object.values(map);
|
|
200
299
|
}
|
|
201
|
-
getForeignKeysSQL(tableName, schemaName) {
|
|
202
|
-
throw new Error('Not supported by given driver');
|
|
203
|
-
}
|
|
204
300
|
mapForeignKeys(fks, tableName, schemaName) {
|
|
205
301
|
return fks.reduce((ret, fk) => {
|
|
206
302
|
if (ret[fk.constraint_name]) {
|
|
@@ -242,15 +338,15 @@ class SchemaHelper {
|
|
|
242
338
|
return `create database ${name};\n\nuse ${name}`;
|
|
243
339
|
}
|
|
244
340
|
getDropDatabaseSQL(name) {
|
|
245
|
-
return `drop database if exists ${this.
|
|
341
|
+
return `drop database if exists ${this.quote(name)}`;
|
|
246
342
|
}
|
|
247
343
|
/* istanbul ignore next */
|
|
248
344
|
getCreateNamespaceSQL(name) {
|
|
249
|
-
return `create schema if not exists ${this.
|
|
345
|
+
return `create schema if not exists ${this.quote(name)}`;
|
|
250
346
|
}
|
|
251
347
|
/* istanbul ignore next */
|
|
252
348
|
getDropNamespaceSQL(name) {
|
|
253
|
-
return `drop schema if exists ${this.
|
|
349
|
+
return `drop schema if exists ${this.quote(name)}`;
|
|
254
350
|
}
|
|
255
351
|
getDatabaseExistsSQL(name) {
|
|
256
352
|
return `select 1 from information_schema.schemata where schema_name = '${name}'`;
|
|
@@ -273,78 +369,98 @@ class SchemaHelper {
|
|
|
273
369
|
if (e instanceof Error && e.message.includes(this.getDatabaseNotExistsError(name))) {
|
|
274
370
|
return false;
|
|
275
371
|
}
|
|
372
|
+
/* istanbul ignore next */
|
|
276
373
|
throw e;
|
|
277
374
|
}
|
|
278
375
|
}
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
376
|
+
append(array, sql, pad = false) {
|
|
377
|
+
const length = array.length;
|
|
378
|
+
for (const row of core_1.Utils.asArray(sql)) {
|
|
379
|
+
if (!row) {
|
|
380
|
+
continue;
|
|
381
|
+
}
|
|
382
|
+
let tmp = row.trim();
|
|
383
|
+
if (!tmp.endsWith(';')) {
|
|
384
|
+
tmp += ';';
|
|
385
|
+
}
|
|
386
|
+
array.push(tmp);
|
|
288
387
|
}
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
if (queries.length === 0) {
|
|
292
|
-
return '';
|
|
388
|
+
if (pad && array.length > length) {
|
|
389
|
+
array.push('');
|
|
293
390
|
}
|
|
294
|
-
const dump = `${queries.map(q => typeof q === 'object' ? q.sql : q).join(';\n')};${append}`;
|
|
295
|
-
const tmp = dump.replace(/pragma table_.+/ig, '').replace(/\n\n+/g, '\n').trim();
|
|
296
|
-
return tmp ? tmp + append : '';
|
|
297
391
|
}
|
|
298
|
-
createTable(
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
const
|
|
306
|
-
|
|
307
|
-
}
|
|
308
|
-
for (const check of tableDef.getChecks()) {
|
|
309
|
-
this.createCheck(table, check);
|
|
392
|
+
createTable(table, alter) {
|
|
393
|
+
let sql = `create table ${table.getQuotedName()} (`;
|
|
394
|
+
const columns = table.getColumns();
|
|
395
|
+
const lastColumn = columns[columns.length - 1].name;
|
|
396
|
+
for (const column of columns) {
|
|
397
|
+
const col = this.createTableColumn(column, table);
|
|
398
|
+
if (col) {
|
|
399
|
+
const comma = column.name === lastColumn ? '' : ', ';
|
|
400
|
+
sql += col + comma;
|
|
310
401
|
}
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
402
|
+
}
|
|
403
|
+
const primaryKey = table.getPrimaryKey();
|
|
404
|
+
const createPrimary = !table.getColumns().some(c => c.autoincrement && c.primary) || this.hasNonDefaultPrimaryKeyName(table);
|
|
405
|
+
if (createPrimary && primaryKey) {
|
|
406
|
+
const name = this.hasNonDefaultPrimaryKeyName(table) ? `constraint ${this.quote(primaryKey.keyName)} ` : '';
|
|
407
|
+
sql += `, ${name}primary key (${primaryKey.columnNames.map(c => this.quote(c)).join(', ')})`;
|
|
408
|
+
}
|
|
409
|
+
sql += ')';
|
|
410
|
+
sql += this.finalizeTable(table, this.platform.getConfig().get('charset'), this.platform.getConfig().get('collate'));
|
|
411
|
+
const ret = [];
|
|
412
|
+
this.append(ret, sql);
|
|
413
|
+
this.append(ret, this.appendComments(table));
|
|
414
|
+
for (const index of table.getIndexes()) {
|
|
415
|
+
this.append(ret, this.createIndex(index, table));
|
|
416
|
+
}
|
|
417
|
+
if (!alter) {
|
|
418
|
+
for (const check of table.getChecks()) {
|
|
419
|
+
this.append(ret, this.createCheck(table, check));
|
|
319
420
|
}
|
|
320
|
-
|
|
321
|
-
|
|
421
|
+
}
|
|
422
|
+
return ret;
|
|
423
|
+
}
|
|
424
|
+
alterTableComment(table, comment) {
|
|
425
|
+
return `alter table ${table.getQuotedName()} comment = ${this.platform.quoteValue(comment ?? '')}`;
|
|
322
426
|
}
|
|
323
|
-
createForeignKey(table, foreignKey,
|
|
427
|
+
createForeignKey(table, foreignKey, alterTable = true, inline = false) {
|
|
324
428
|
if (!this.options.createForeignKeyConstraints) {
|
|
325
|
-
return;
|
|
429
|
+
return '';
|
|
430
|
+
}
|
|
431
|
+
const constraintName = this.quote(foreignKey.constraintName);
|
|
432
|
+
const columnNames = foreignKey.columnNames.map(c => this.quote(c)).join(', ');
|
|
433
|
+
const referencedColumnNames = foreignKey.referencedColumnNames.map(c => this.quote(c)).join(', ');
|
|
434
|
+
const referencedTableName = this.quote(this.getReferencedTableName(foreignKey.referencedTableName, table.schema));
|
|
435
|
+
const sql = [];
|
|
436
|
+
if (alterTable) {
|
|
437
|
+
sql.push(`alter table ${table.getQuotedName()} add`);
|
|
438
|
+
}
|
|
439
|
+
sql.push(`constraint ${constraintName}`);
|
|
440
|
+
if (!inline) {
|
|
441
|
+
sql.push(`foreign key (${columnNames})`);
|
|
326
442
|
}
|
|
327
|
-
|
|
328
|
-
.foreign(foreignKey.columnNames, foreignKey.constraintName)
|
|
329
|
-
.references(foreignKey.referencedColumnNames)
|
|
330
|
-
.inTable(this.getReferencedTableName(foreignKey.referencedTableName, schema))
|
|
331
|
-
.withKeyName(foreignKey.constraintName);
|
|
443
|
+
sql.push(`references ${referencedTableName} (${referencedColumnNames})`);
|
|
332
444
|
if (foreignKey.localTableName !== foreignKey.referencedTableName || this.platform.supportsMultipleCascadePaths()) {
|
|
333
445
|
if (foreignKey.updateRule) {
|
|
334
|
-
|
|
446
|
+
sql.push(`on update ${foreignKey.updateRule}`);
|
|
335
447
|
}
|
|
336
448
|
if (foreignKey.deleteRule) {
|
|
337
|
-
|
|
449
|
+
sql.push(`on delete ${foreignKey.deleteRule}`);
|
|
338
450
|
}
|
|
339
451
|
}
|
|
340
452
|
if (foreignKey.deferMode) {
|
|
341
|
-
|
|
453
|
+
sql.push(`deferrable initially ${foreignKey.deferMode}`);
|
|
342
454
|
}
|
|
455
|
+
return sql.join(' ');
|
|
343
456
|
}
|
|
344
|
-
splitTableName(name) {
|
|
457
|
+
splitTableName(name, skipDefaultSchema = false) {
|
|
345
458
|
const parts = name.split('.');
|
|
346
459
|
const tableName = parts.pop();
|
|
347
|
-
|
|
460
|
+
let schemaName = parts.pop();
|
|
461
|
+
if (skipDefaultSchema && schemaName === this.platform.getDefaultSchemaName()) {
|
|
462
|
+
schemaName = undefined;
|
|
463
|
+
}
|
|
348
464
|
return [schemaName, tableName];
|
|
349
465
|
}
|
|
350
466
|
getReferencedTableName(referencedTableName, schema) {
|
|
@@ -354,58 +470,37 @@ class SchemaHelper {
|
|
|
354
470
|
if (schema && schemaName === '*') {
|
|
355
471
|
return `${schema}.${referencedTableName.replace(/^\*\./, '')}`;
|
|
356
472
|
}
|
|
357
|
-
|
|
358
|
-
return tableName;
|
|
359
|
-
}
|
|
360
|
-
return `${schemaName}.${tableName}`;
|
|
473
|
+
return this.getTableName(tableName, schema);
|
|
361
474
|
}
|
|
362
|
-
createIndex(
|
|
475
|
+
createIndex(index, table, createPrimary = false) {
|
|
363
476
|
if (index.primary && !createPrimary) {
|
|
364
|
-
return;
|
|
477
|
+
return '';
|
|
365
478
|
}
|
|
366
479
|
if (index.expression) {
|
|
367
|
-
|
|
368
|
-
}
|
|
369
|
-
else if (index.primary) {
|
|
370
|
-
const keyName = this.hasNonDefaultPrimaryKeyName(tableDef) ? index.keyName : undefined;
|
|
371
|
-
table.primary(index.columnNames, keyName);
|
|
480
|
+
return index.expression;
|
|
372
481
|
}
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
}
|
|
379
|
-
else {
|
|
380
|
-
table.unique(index.columnNames, { indexName: index.keyName, deferrable: index.deferMode });
|
|
381
|
-
}
|
|
482
|
+
const columns = index.columnNames.map(c => this.quote(c)).join(', ');
|
|
483
|
+
const defer = index.deferMode ? ` deferrable initially ${index.deferMode}` : '';
|
|
484
|
+
if (index.primary) {
|
|
485
|
+
const keyName = this.hasNonDefaultPrimaryKeyName(table) ? `constraint ${index.keyName} ` : '';
|
|
486
|
+
return `alter table ${table.getQuotedName()} add ${keyName}primary key (${columns})${defer}`;
|
|
382
487
|
}
|
|
383
|
-
|
|
384
|
-
const columns = index.columnNames.map(name => ({ name, type:
|
|
488
|
+
if (index.type === 'fulltext') {
|
|
489
|
+
const columns = index.columnNames.map(name => ({ name, type: table.getColumn(name).type }));
|
|
385
490
|
if (this.platform.supportsCreatingFullTextIndex()) {
|
|
386
|
-
|
|
387
|
-
}
|
|
388
|
-
}
|
|
389
|
-
else {
|
|
390
|
-
// JSON columns can have unique index but not unique constraint, and we need to distinguish those, so we can properly drop them
|
|
391
|
-
if (index.columnNames.some(column => column.includes('.'))) {
|
|
392
|
-
const columns = this.platform.getJsonIndexDefinition(index);
|
|
393
|
-
table.index(columns.map(column => this.knex.raw(column)), index.keyName, index.type);
|
|
394
|
-
}
|
|
395
|
-
else {
|
|
396
|
-
table.index(index.columnNames, index.keyName, index.type);
|
|
491
|
+
return this.platform.getFullTextIndexExpression(index.keyName, table.schema, table.name, columns);
|
|
397
492
|
}
|
|
398
493
|
}
|
|
494
|
+
return this.getCreateIndexSQL(table.getShortestName(), index);
|
|
399
495
|
}
|
|
400
496
|
createCheck(table, check) {
|
|
401
|
-
table.
|
|
497
|
+
return `alter table ${table.getQuotedName()} add constraint ${this.quote(check.name)} check (${check.expression})`;
|
|
402
498
|
}
|
|
403
|
-
|
|
404
|
-
const builder = this.knex.schema;
|
|
499
|
+
getTableName(table, schema) {
|
|
405
500
|
if (schema && schema !== this.platform.getDefaultSchemaName()) {
|
|
406
|
-
|
|
501
|
+
return `${schema}.${table}`;
|
|
407
502
|
}
|
|
408
|
-
return
|
|
503
|
+
return table;
|
|
409
504
|
}
|
|
410
505
|
getTablesGroupedBySchemas(tables) {
|
|
411
506
|
return tables.reduce((acc, table) => {
|
|
@@ -418,18 +513,33 @@ class SchemaHelper {
|
|
|
418
513
|
return acc;
|
|
419
514
|
}, new Map());
|
|
420
515
|
}
|
|
421
|
-
get knex() {
|
|
422
|
-
const connection = this.platform.getConfig().getDriver().getConnection();
|
|
423
|
-
return connection.getKnex();
|
|
424
|
-
}
|
|
425
516
|
get options() {
|
|
426
517
|
return this.platform.getConfig().get('schemaGenerator');
|
|
427
518
|
}
|
|
428
519
|
processComment(comment) {
|
|
429
|
-
return
|
|
520
|
+
return comment;
|
|
430
521
|
}
|
|
431
|
-
|
|
432
|
-
return
|
|
522
|
+
quote(...keys) {
|
|
523
|
+
return this.platform.quoteIdentifier(keys.filter(Boolean).join('.'));
|
|
524
|
+
}
|
|
525
|
+
dropForeignKey(tableName, constraintName) {
|
|
526
|
+
return `alter table ${this.quote(tableName)} drop foreign key ${this.quote(constraintName)}`;
|
|
527
|
+
}
|
|
528
|
+
dropIndex(table, index, oldIndexName = index.keyName) {
|
|
529
|
+
if (index.primary) {
|
|
530
|
+
return `alter table ${this.quote(table)} drop primary key`;
|
|
531
|
+
}
|
|
532
|
+
return `alter table ${this.quote(table)} drop index ${this.quote(oldIndexName)}`;
|
|
533
|
+
}
|
|
534
|
+
dropConstraint(table, name) {
|
|
535
|
+
return `alter table ${this.quote(table)} drop constraint ${this.quote(name)}`;
|
|
536
|
+
}
|
|
537
|
+
dropTableIfExists(name, schema) {
|
|
538
|
+
let sql = `drop table if exists ${this.quote(this.getTableName(name, schema))}`;
|
|
539
|
+
if (this.platform.usesCascadeStatement()) {
|
|
540
|
+
sql += ' cascade';
|
|
541
|
+
}
|
|
542
|
+
return sql;
|
|
433
543
|
}
|
|
434
544
|
}
|
|
435
545
|
exports.SchemaHelper = SchemaHelper;
|
|
@@ -37,13 +37,11 @@ export declare class SqlSchemaGenerator extends AbstractSchemaGenerator<Abstract
|
|
|
37
37
|
safe?: boolean;
|
|
38
38
|
dropTables?: boolean;
|
|
39
39
|
schema?: string;
|
|
40
|
-
}):
|
|
40
|
+
}): string;
|
|
41
41
|
/**
|
|
42
42
|
* We need to drop foreign keys first for all tables to allow dropping PK constraints.
|
|
43
43
|
*/
|
|
44
44
|
private preAlterTable;
|
|
45
|
-
private postAlterTable;
|
|
46
|
-
private alterTable;
|
|
47
45
|
/**
|
|
48
46
|
* creates new database and connects to it
|
|
49
47
|
*/
|
|
@@ -53,12 +51,8 @@ export declare class SqlSchemaGenerator extends AbstractSchemaGenerator<Abstract
|
|
|
53
51
|
wrap?: boolean;
|
|
54
52
|
ctx?: Transaction;
|
|
55
53
|
}): Promise<void>;
|
|
54
|
+
dropTableIfExists(name: string, schema?: string): Promise<void>;
|
|
56
55
|
private wrapSchema;
|
|
57
|
-
private
|
|
58
|
-
private dropCheck;
|
|
59
|
-
private dropTable;
|
|
60
|
-
private createForeignKeys;
|
|
61
|
-
private dump;
|
|
62
|
-
private get knex();
|
|
56
|
+
private append;
|
|
63
57
|
}
|
|
64
58
|
export { SqlSchemaGenerator as SchemaGenerator };
|