@mikro-orm/knex 6.0.0-dev.12 → 6.0.0-dev.121
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 +8 -4
- package/AbstractSqlConnection.js +30 -18
- package/AbstractSqlDriver.d.ts +21 -23
- package/AbstractSqlDriver.js +378 -221
- package/AbstractSqlPlatform.d.ts +5 -4
- package/AbstractSqlPlatform.js +34 -5
- package/MonkeyPatchable.d.ts +1 -0
- package/MonkeyPatchable.js +3 -0
- package/PivotCollectionPersister.d.ts +17 -0
- package/PivotCollectionPersister.js +128 -0
- package/README.md +64 -107
- package/SqlEntityManager.d.ts +2 -6
- package/SqlEntityManager.js +5 -9
- package/SqlEntityRepository.d.ts +7 -6
- package/SqlEntityRepository.js +11 -8
- package/index.mjs +23 -6
- package/package.json +8 -8
- package/query/ArrayCriteriaNode.d.ts +3 -3
- package/query/CriteriaNode.d.ts +8 -8
- package/query/CriteriaNode.js +16 -9
- package/query/CriteriaNodeFactory.d.ts +6 -6
- package/query/CriteriaNodeFactory.js +17 -13
- package/query/ObjectCriteriaNode.d.ts +3 -3
- package/query/ObjectCriteriaNode.js +12 -8
- package/query/QueryBuilder.d.ts +44 -20
- package/query/QueryBuilder.js +371 -130
- package/query/QueryBuilderHelper.d.ts +10 -15
- package/query/QueryBuilderHelper.js +197 -158
- package/query/ScalarCriteriaNode.d.ts +3 -2
- package/query/ScalarCriteriaNode.js +9 -6
- package/query/enums.js +1 -1
- package/schema/DatabaseSchema.d.ts +5 -2
- package/schema/DatabaseSchema.js +27 -9
- package/schema/DatabaseTable.d.ts +4 -2
- package/schema/DatabaseTable.js +66 -32
- package/schema/SchemaComparator.js +15 -3
- package/schema/SchemaHelper.d.ts +6 -4
- package/schema/SchemaHelper.js +11 -4
- package/schema/SqlSchemaGenerator.d.ts +3 -6
- package/schema/SqlSchemaGenerator.js +61 -28
- package/typings.d.ts +13 -7
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type
|
|
1
|
+
import { type Configuration, type Dictionary, type EntityMetadata } from '@mikro-orm/core';
|
|
2
2
|
import { DatabaseTable } from './DatabaseTable';
|
|
3
3
|
import type { AbstractSqlConnection } from '../AbstractSqlConnection';
|
|
4
4
|
import type { AbstractSqlPlatform } from '../AbstractSqlPlatform';
|
|
@@ -10,14 +10,17 @@ export declare class DatabaseSchema {
|
|
|
10
10
|
readonly name: string;
|
|
11
11
|
private tables;
|
|
12
12
|
private namespaces;
|
|
13
|
+
private nativeEnums;
|
|
13
14
|
constructor(platform: AbstractSqlPlatform, name: string);
|
|
14
15
|
addTable(name: string, schema: string | undefined | null, comment?: string): DatabaseTable;
|
|
15
16
|
getTables(): DatabaseTable[];
|
|
16
17
|
getTable(name: string): DatabaseTable | undefined;
|
|
17
18
|
hasTable(name: string): boolean;
|
|
19
|
+
setNativeEnums(nativeEnums: Dictionary<unknown[]>): void;
|
|
20
|
+
getNativeEnums(): Dictionary<unknown[]>;
|
|
18
21
|
hasNamespace(namespace: string): boolean;
|
|
19
22
|
getNamespaces(): string[];
|
|
20
|
-
static create(connection: AbstractSqlConnection, platform: AbstractSqlPlatform, config: Configuration, schemaName?: string): Promise<DatabaseSchema>;
|
|
23
|
+
static create(connection: AbstractSqlConnection, platform: AbstractSqlPlatform, config: Configuration, schemaName?: string, schemas?: string[]): Promise<DatabaseSchema>;
|
|
21
24
|
static fromMetadata(metadata: EntityMetadata[], platform: AbstractSqlPlatform, config: Configuration, schemaName?: string): DatabaseSchema;
|
|
22
25
|
private static getSchemaName;
|
|
23
26
|
private static shouldHaveColumn;
|
package/schema/DatabaseSchema.js
CHANGED
|
@@ -7,15 +7,19 @@ const DatabaseTable_1 = require("./DatabaseTable");
|
|
|
7
7
|
* @internal
|
|
8
8
|
*/
|
|
9
9
|
class DatabaseSchema {
|
|
10
|
+
platform;
|
|
11
|
+
name;
|
|
12
|
+
tables = [];
|
|
13
|
+
namespaces = new Set();
|
|
14
|
+
nativeEnums = {}; // for postgres
|
|
10
15
|
constructor(platform, name) {
|
|
11
16
|
this.platform = platform;
|
|
12
17
|
this.name = name;
|
|
13
|
-
this.tables = [];
|
|
14
|
-
this.namespaces = new Set();
|
|
15
18
|
}
|
|
16
19
|
addTable(name, schema, comment) {
|
|
17
20
|
const namespaceName = schema ?? this.name;
|
|
18
21
|
const table = new DatabaseTable_1.DatabaseTable(this.platform, name, namespaceName);
|
|
22
|
+
table.nativeEnums = this.nativeEnums;
|
|
19
23
|
table.comment = comment;
|
|
20
24
|
this.tables.push(table);
|
|
21
25
|
if (namespaceName != null) {
|
|
@@ -32,24 +36,38 @@ class DatabaseSchema {
|
|
|
32
36
|
hasTable(name) {
|
|
33
37
|
return !!this.getTable(name);
|
|
34
38
|
}
|
|
39
|
+
setNativeEnums(nativeEnums) {
|
|
40
|
+
this.nativeEnums = nativeEnums;
|
|
41
|
+
this.tables.forEach(t => t.nativeEnums = nativeEnums);
|
|
42
|
+
}
|
|
43
|
+
getNativeEnums() {
|
|
44
|
+
return this.nativeEnums;
|
|
45
|
+
}
|
|
35
46
|
hasNamespace(namespace) {
|
|
36
47
|
return this.namespaces.has(namespace);
|
|
37
48
|
}
|
|
38
49
|
getNamespaces() {
|
|
39
50
|
return [...this.namespaces];
|
|
40
51
|
}
|
|
41
|
-
static async create(connection, platform, config, schemaName) {
|
|
42
|
-
const schema = new DatabaseSchema(platform, schemaName ?? config.get('schema'));
|
|
52
|
+
static async create(connection, platform, config, schemaName, schemas) {
|
|
53
|
+
const schema = new DatabaseSchema(platform, schemaName ?? config.get('schema') ?? platform.getDefaultSchemaName());
|
|
43
54
|
const allTables = await connection.execute(platform.getSchemaHelper().getListTablesSQL());
|
|
44
55
|
const parts = config.get('migrations').tableName.split('.');
|
|
45
56
|
const migrationsTableName = parts[1] ?? parts[0];
|
|
46
57
|
const migrationsSchemaName = parts.length > 1 ? parts[0] : config.get('schema', platform.getDefaultSchemaName());
|
|
47
58
|
const tables = allTables.filter(t => t.table_name !== migrationsTableName || (t.schema_name && t.schema_name !== migrationsSchemaName));
|
|
48
|
-
await platform.getSchemaHelper().loadInformationSchema(schema, connection, tables);
|
|
59
|
+
await platform.getSchemaHelper().loadInformationSchema(schema, connection, tables, schemas && schemas.length > 0 ? schemas : undefined);
|
|
49
60
|
return schema;
|
|
50
61
|
}
|
|
51
62
|
static fromMetadata(metadata, platform, config, schemaName) {
|
|
52
63
|
const schema = new DatabaseSchema(platform, schemaName ?? config.get('schema'));
|
|
64
|
+
const nativeEnums = {};
|
|
65
|
+
for (const meta of metadata) {
|
|
66
|
+
meta.props
|
|
67
|
+
.filter(prop => prop.nativeEnumName)
|
|
68
|
+
.forEach(prop => nativeEnums[prop.nativeEnumName] = prop.items?.map(val => '' + val) ?? []);
|
|
69
|
+
}
|
|
70
|
+
schema.setNativeEnums(nativeEnums);
|
|
53
71
|
for (const meta of metadata) {
|
|
54
72
|
const table = schema.addTable(meta.collection, this.getSchemaName(meta, config, schemaName));
|
|
55
73
|
table.comment = meta.comment;
|
|
@@ -75,18 +93,18 @@ class DatabaseSchema {
|
|
|
75
93
|
return (meta.schema === '*' ? schema : meta.schema) ?? config.get('schema');
|
|
76
94
|
}
|
|
77
95
|
static shouldHaveColumn(meta, prop) {
|
|
78
|
-
if (prop.persist === false ||
|
|
96
|
+
if (prop.persist === false || (prop.columnTypes?.length ?? 0) === 0) {
|
|
79
97
|
return false;
|
|
80
98
|
}
|
|
81
|
-
if (meta.pivotTable || (core_1.
|
|
99
|
+
if (meta.pivotTable || (prop.kind === core_1.ReferenceKind.EMBEDDED && prop.object)) {
|
|
82
100
|
return true;
|
|
83
101
|
}
|
|
84
102
|
const getRootProperty = (prop) => prop.embedded ? getRootProperty(meta.properties[prop.embedded[0]]) : prop;
|
|
85
103
|
const rootProp = getRootProperty(prop);
|
|
86
|
-
if (rootProp.
|
|
104
|
+
if (rootProp.kind === core_1.ReferenceKind.EMBEDDED) {
|
|
87
105
|
return prop === rootProp || !rootProp.object;
|
|
88
106
|
}
|
|
89
|
-
return [core_1.
|
|
107
|
+
return [core_1.ReferenceKind.SCALAR, core_1.ReferenceKind.MANY_TO_ONE].includes(prop.kind) || (prop.kind === core_1.ReferenceKind.ONE_TO_ONE && prop.owner);
|
|
90
108
|
}
|
|
91
109
|
toJSON() {
|
|
92
110
|
const { platform, namespaces, ...rest } = this;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type
|
|
1
|
+
import { type Dictionary, type EntityMetadata, type EntityProperty, type NamingStrategy } from '@mikro-orm/core';
|
|
2
2
|
import type { SchemaHelper } from './SchemaHelper';
|
|
3
3
|
import type { CheckDef, Column, ForeignKey, IndexDef } from '../typings';
|
|
4
4
|
import type { AbstractSqlPlatform } from '../AbstractSqlPlatform';
|
|
@@ -13,10 +13,12 @@ export declare class DatabaseTable {
|
|
|
13
13
|
private indexes;
|
|
14
14
|
private checks;
|
|
15
15
|
private foreignKeys;
|
|
16
|
+
nativeEnums: Dictionary<unknown[]>;
|
|
16
17
|
comment?: string;
|
|
17
18
|
constructor(platform: AbstractSqlPlatform, name: string, schema?: string | undefined);
|
|
18
19
|
getColumns(): Column[];
|
|
19
20
|
getColumn(name: string): Column | undefined;
|
|
21
|
+
removeColumn(name: string): void;
|
|
20
22
|
getIndexes(): IndexDef[];
|
|
21
23
|
getChecks(): CheckDef[];
|
|
22
24
|
init(cols: Column[], indexes: IndexDef[] | undefined, checks: CheckDef<unknown>[] | undefined, pks: string[], fks?: Dictionary<ForeignKey>, enums?: Dictionary<string[]>): void;
|
|
@@ -37,7 +39,7 @@ export declare class DatabaseTable {
|
|
|
37
39
|
getPrimaryKey(): IndexDef | undefined;
|
|
38
40
|
hasPrimaryKey(): boolean;
|
|
39
41
|
private getPropertyDeclaration;
|
|
40
|
-
private
|
|
42
|
+
private getReferenceKind;
|
|
41
43
|
private getPropertyName;
|
|
42
44
|
private getPropertyType;
|
|
43
45
|
private getPropertyDefaultValue;
|
package/schema/DatabaseTable.js
CHANGED
|
@@ -6,14 +6,19 @@ const core_1 = require("@mikro-orm/core");
|
|
|
6
6
|
* @internal
|
|
7
7
|
*/
|
|
8
8
|
class DatabaseTable {
|
|
9
|
+
platform;
|
|
10
|
+
name;
|
|
11
|
+
schema;
|
|
12
|
+
columns = {};
|
|
13
|
+
indexes = [];
|
|
14
|
+
checks = [];
|
|
15
|
+
foreignKeys = {};
|
|
16
|
+
nativeEnums = {}; // for postgres
|
|
17
|
+
comment;
|
|
9
18
|
constructor(platform, name, schema) {
|
|
10
19
|
this.platform = platform;
|
|
11
20
|
this.name = name;
|
|
12
21
|
this.schema = schema;
|
|
13
|
-
this.columns = {};
|
|
14
|
-
this.indexes = [];
|
|
15
|
-
this.checks = [];
|
|
16
|
-
this.foreignKeys = {};
|
|
17
22
|
Object.defineProperties(this, {
|
|
18
23
|
platform: { enumerable: false, writable: true },
|
|
19
24
|
});
|
|
@@ -24,8 +29,11 @@ class DatabaseTable {
|
|
|
24
29
|
getColumn(name) {
|
|
25
30
|
return this.columns[name];
|
|
26
31
|
}
|
|
32
|
+
removeColumn(name) {
|
|
33
|
+
delete this.columns[name];
|
|
34
|
+
}
|
|
27
35
|
getIndexes() {
|
|
28
|
-
return this.indexes;
|
|
36
|
+
return core_1.Utils.removeDuplicates(this.indexes);
|
|
29
37
|
}
|
|
30
38
|
getChecks() {
|
|
31
39
|
return this.checks;
|
|
@@ -41,7 +49,7 @@ class DatabaseTable {
|
|
|
41
49
|
const type = v.name in enums ? 'enum' : v.type;
|
|
42
50
|
v.mappedType = this.platform.getMappedType(type);
|
|
43
51
|
v.default = v.default?.toString().startsWith('nextval(') ? null : v.default;
|
|
44
|
-
v.enumItems
|
|
52
|
+
v.enumItems ??= enums[v.name] || [];
|
|
45
53
|
o[v.name] = v;
|
|
46
54
|
return o;
|
|
47
55
|
}, {});
|
|
@@ -51,22 +59,27 @@ class DatabaseTable {
|
|
|
51
59
|
}
|
|
52
60
|
addColumnFromProperty(prop, meta) {
|
|
53
61
|
prop.fieldNames.forEach((field, idx) => {
|
|
54
|
-
var _a;
|
|
55
62
|
const type = prop.enum ? 'enum' : prop.columnTypes[idx];
|
|
56
63
|
const mappedType = this.platform.getMappedType(type);
|
|
57
64
|
if (mappedType instanceof core_1.DecimalType) {
|
|
58
65
|
const match = prop.columnTypes[idx].match(/\w+\((\d+), ?(\d+)\)/);
|
|
59
66
|
/* istanbul ignore else */
|
|
60
67
|
if (match) {
|
|
61
|
-
prop.precision
|
|
62
|
-
prop.scale
|
|
68
|
+
prop.precision ??= +match[1];
|
|
69
|
+
prop.scale ??= +match[2];
|
|
63
70
|
prop.length = undefined;
|
|
64
71
|
}
|
|
65
72
|
}
|
|
66
73
|
if (mappedType instanceof core_1.DateTimeType) {
|
|
67
|
-
|
|
74
|
+
const match = prop.columnTypes[idx].match(/\w+\((\d+)\)/);
|
|
75
|
+
if (match) {
|
|
76
|
+
prop.length ??= +match[1];
|
|
77
|
+
}
|
|
78
|
+
else {
|
|
79
|
+
prop.length ??= this.platform.getDefaultDateTimeLength();
|
|
80
|
+
}
|
|
68
81
|
}
|
|
69
|
-
const primary = !meta.compositePK && !!prop.primary && prop.
|
|
82
|
+
const primary = !meta.compositePK && !!prop.primary && prop.kind === core_1.ReferenceKind.SCALAR && this.platform.isNumericColumn(mappedType);
|
|
70
83
|
this.columns[field] = {
|
|
71
84
|
name: prop.fieldNames[idx],
|
|
72
85
|
type: prop.columnTypes[idx],
|
|
@@ -74,21 +87,22 @@ class DatabaseTable {
|
|
|
74
87
|
unsigned: prop.unsigned && this.platform.isNumericColumn(mappedType),
|
|
75
88
|
autoincrement: prop.autoincrement ?? primary,
|
|
76
89
|
primary,
|
|
77
|
-
nullable: !!prop.nullable,
|
|
90
|
+
nullable: this.columns[field]?.nullable ?? !!prop.nullable,
|
|
91
|
+
nativeEnumName: prop.nativeEnumName,
|
|
78
92
|
length: prop.length,
|
|
79
93
|
precision: prop.precision,
|
|
80
94
|
scale: prop.scale,
|
|
81
95
|
default: prop.defaultRaw,
|
|
82
|
-
enumItems: prop.items?.every(core_1.Utils.isString) ? prop.items : undefined,
|
|
96
|
+
enumItems: prop.nativeEnumName || prop.items?.every(core_1.Utils.isString) ? prop.items : undefined,
|
|
83
97
|
comment: prop.comment,
|
|
84
98
|
extra: prop.extra,
|
|
85
99
|
ignoreSchemaChanges: prop.ignoreSchemaChanges,
|
|
86
100
|
};
|
|
87
|
-
|
|
101
|
+
this.columns[field].unsigned ||= this.columns[field].autoincrement;
|
|
88
102
|
const defaultValue = this.platform.getSchemaHelper().normalizeDefaultValue(prop.defaultRaw, prop.length);
|
|
89
103
|
this.columns[field].default = defaultValue;
|
|
90
104
|
});
|
|
91
|
-
if ([core_1.
|
|
105
|
+
if ([core_1.ReferenceKind.MANY_TO_ONE, core_1.ReferenceKind.ONE_TO_ONE].includes(prop.kind)) {
|
|
92
106
|
const constraintName = this.getIndexName(true, prop.fieldNames, 'foreign');
|
|
93
107
|
let schema = prop.targetMeta.schema === '*' ? this.schema : prop.targetMeta.schema ?? this.schema;
|
|
94
108
|
if (prop.referencedTableName.includes('.')) {
|
|
@@ -102,11 +116,11 @@ class DatabaseTable {
|
|
|
102
116
|
referencedTableName: schema ? `${schema}.${prop.referencedTableName}` : prop.referencedTableName,
|
|
103
117
|
};
|
|
104
118
|
const cascade = prop.cascade.includes(core_1.Cascade.REMOVE) || prop.cascade.includes(core_1.Cascade.ALL);
|
|
105
|
-
if (prop.
|
|
106
|
-
this.foreignKeys[constraintName].deleteRule = prop.
|
|
119
|
+
if (prop.deleteRule || cascade || prop.nullable) {
|
|
120
|
+
this.foreignKeys[constraintName].deleteRule = prop.deleteRule || (cascade ? 'cascade' : 'set null');
|
|
107
121
|
}
|
|
108
|
-
if (prop.
|
|
109
|
-
this.foreignKeys[constraintName].updateRule = prop.
|
|
122
|
+
if (prop.updateRule || prop.cascade.includes(core_1.Cascade.PERSIST) || prop.cascade.includes(core_1.Cascade.ALL)) {
|
|
123
|
+
this.foreignKeys[constraintName].updateRule = prop.updateRule || 'cascade';
|
|
110
124
|
}
|
|
111
125
|
}
|
|
112
126
|
if (prop.index) {
|
|
@@ -114,6 +128,7 @@ class DatabaseTable {
|
|
|
114
128
|
columnNames: prop.fieldNames,
|
|
115
129
|
composite: prop.fieldNames.length > 1,
|
|
116
130
|
keyName: this.getIndexName(prop.index, prop.fieldNames, 'index'),
|
|
131
|
+
constraint: false,
|
|
117
132
|
primary: false,
|
|
118
133
|
unique: false,
|
|
119
134
|
});
|
|
@@ -123,6 +138,7 @@ class DatabaseTable {
|
|
|
123
138
|
columnNames: prop.fieldNames,
|
|
124
139
|
composite: prop.fieldNames.length > 1,
|
|
125
140
|
keyName: this.getIndexName(prop.unique, prop.fieldNames, 'unique'),
|
|
141
|
+
constraint: !prop.fieldNames.some((d) => d.includes('.')),
|
|
126
142
|
primary: false,
|
|
127
143
|
unique: true,
|
|
128
144
|
});
|
|
@@ -164,8 +180,8 @@ class DatabaseTable {
|
|
|
164
180
|
}
|
|
165
181
|
const meta = schema.init().meta;
|
|
166
182
|
meta.relations
|
|
167
|
-
.filter(prop => prop.primary && prop.
|
|
168
|
-
.forEach(prop => prop.
|
|
183
|
+
.filter(prop => prop.primary && prop.kind === core_1.ReferenceKind.MANY_TO_ONE && !meta.compositePK)
|
|
184
|
+
.forEach(prop => prop.kind = core_1.ReferenceKind.ONE_TO_ONE);
|
|
169
185
|
return meta;
|
|
170
186
|
}
|
|
171
187
|
/**
|
|
@@ -206,20 +222,20 @@ class DatabaseTable {
|
|
|
206
222
|
const prop = this.getPropertyName(namingStrategy, column);
|
|
207
223
|
const index = compositeFkIndexes[prop] || this.indexes.find(idx => idx.columnNames[0] === column.name && !idx.composite && !idx.unique && !idx.primary);
|
|
208
224
|
const unique = compositeFkUniques[prop] || this.indexes.find(idx => idx.columnNames[0] === column.name && !idx.composite && idx.unique && !idx.primary);
|
|
209
|
-
const
|
|
225
|
+
const kind = this.getReferenceKind(fk, unique);
|
|
210
226
|
const type = this.getPropertyType(namingStrategy, column, fk);
|
|
211
227
|
const fkOptions = {};
|
|
212
228
|
if (fk) {
|
|
213
229
|
fkOptions.fieldNames = fk.columnNames;
|
|
214
230
|
fkOptions.referencedTableName = fk.referencedTableName;
|
|
215
231
|
fkOptions.referencedColumnNames = fk.referencedColumnNames;
|
|
216
|
-
fkOptions.
|
|
217
|
-
fkOptions.
|
|
232
|
+
fkOptions.updateRule = fk.updateRule?.toLowerCase();
|
|
233
|
+
fkOptions.deleteRule = fk.deleteRule?.toLowerCase();
|
|
218
234
|
}
|
|
219
235
|
return {
|
|
220
236
|
name: prop,
|
|
221
237
|
type,
|
|
222
|
-
|
|
238
|
+
kind,
|
|
223
239
|
columnType: column.type,
|
|
224
240
|
default: this.getPropertyDefaultValue(schemaHelper, column, type),
|
|
225
241
|
defaultRaw: this.getPropertyDefaultValue(schemaHelper, column, type, true),
|
|
@@ -227,6 +243,8 @@ class DatabaseTable {
|
|
|
227
243
|
primary: column.primary,
|
|
228
244
|
fieldName: column.name,
|
|
229
245
|
length: column.length,
|
|
246
|
+
precision: column.precision,
|
|
247
|
+
scale: column.scale,
|
|
230
248
|
index: index ? index.keyName : undefined,
|
|
231
249
|
unique: unique ? unique.keyName : undefined,
|
|
232
250
|
enum: !!column.enumItems?.length,
|
|
@@ -234,14 +252,14 @@ class DatabaseTable {
|
|
|
234
252
|
...fkOptions,
|
|
235
253
|
};
|
|
236
254
|
}
|
|
237
|
-
|
|
255
|
+
getReferenceKind(fk, unique) {
|
|
238
256
|
if (fk && unique) {
|
|
239
|
-
return core_1.
|
|
257
|
+
return core_1.ReferenceKind.ONE_TO_ONE;
|
|
240
258
|
}
|
|
241
259
|
if (fk) {
|
|
242
|
-
return core_1.
|
|
260
|
+
return core_1.ReferenceKind.MANY_TO_ONE;
|
|
243
261
|
}
|
|
244
|
-
return core_1.
|
|
262
|
+
return core_1.ReferenceKind.SCALAR;
|
|
245
263
|
}
|
|
246
264
|
getPropertyName(namingStrategy, column) {
|
|
247
265
|
const fk = Object.values(this.foreignKeys).find(fk => fk.columnNames.includes(column.name));
|
|
@@ -288,7 +306,20 @@ class DatabaseTable {
|
|
|
288
306
|
return '' + val;
|
|
289
307
|
}
|
|
290
308
|
addIndex(meta, index, type) {
|
|
291
|
-
const properties = core_1.Utils.flatten(core_1.Utils.asArray(index.properties).map(prop =>
|
|
309
|
+
const properties = core_1.Utils.unique(core_1.Utils.flatten(core_1.Utils.asArray(index.properties).map(prop => {
|
|
310
|
+
const root = prop.replace(/\..+$/, '');
|
|
311
|
+
if (meta.properties[prop]) {
|
|
312
|
+
if (meta.properties[prop].embeddedPath) {
|
|
313
|
+
return [meta.properties[prop].embeddedPath.join('.')];
|
|
314
|
+
}
|
|
315
|
+
return meta.properties[prop].fieldNames;
|
|
316
|
+
}
|
|
317
|
+
// json index, we need to rename the column only
|
|
318
|
+
if (meta.properties[root]) {
|
|
319
|
+
return [prop.replace(root, meta.properties[root].fieldNames[0])];
|
|
320
|
+
}
|
|
321
|
+
return [prop];
|
|
322
|
+
})));
|
|
292
323
|
if (properties.length === 0 && !index.expression) {
|
|
293
324
|
return;
|
|
294
325
|
}
|
|
@@ -297,10 +328,13 @@ class DatabaseTable {
|
|
|
297
328
|
keyName: name,
|
|
298
329
|
columnNames: properties,
|
|
299
330
|
composite: properties.length > 1,
|
|
331
|
+
// JSON columns can have unique index but not unique constraint, and we need to distinguish those, so we can properly drop them
|
|
332
|
+
constraint: type !== 'index' && !properties.some((d) => d.includes('.')),
|
|
300
333
|
primary: type === 'primary',
|
|
301
334
|
unique: type !== 'index',
|
|
302
335
|
type: index.type,
|
|
303
336
|
expression: index.expression,
|
|
337
|
+
options: index.options,
|
|
304
338
|
});
|
|
305
339
|
}
|
|
306
340
|
addCheck(check) {
|
|
@@ -308,10 +342,10 @@ class DatabaseTable {
|
|
|
308
342
|
}
|
|
309
343
|
toJSON() {
|
|
310
344
|
const { platform, columns, ...rest } = this;
|
|
311
|
-
const columnsMapped =
|
|
345
|
+
const columnsMapped = core_1.Utils.keys(columns).reduce((o, col) => {
|
|
312
346
|
const { mappedType, ...restCol } = columns[col];
|
|
313
347
|
o[col] = restCol;
|
|
314
|
-
o[col].mappedType =
|
|
348
|
+
o[col].mappedType = core_1.Utils.keys(core_1.t).find(k => core_1.t[k] === mappedType.constructor);
|
|
315
349
|
return o;
|
|
316
350
|
}, {});
|
|
317
351
|
return { columns: columnsMapped, ...rest };
|
|
@@ -7,6 +7,9 @@ const core_1 = require("@mikro-orm/core");
|
|
|
7
7
|
* Compares two Schemas and return an instance of SchemaDifference.
|
|
8
8
|
*/
|
|
9
9
|
class SchemaComparator {
|
|
10
|
+
platform;
|
|
11
|
+
helper;
|
|
12
|
+
logger;
|
|
10
13
|
constructor(platform) {
|
|
11
14
|
this.platform = platform;
|
|
12
15
|
this.helper = this.platform.getSchemaHelper();
|
|
@@ -363,7 +366,9 @@ class SchemaComparator {
|
|
|
363
366
|
log(`'comment' changed for column ${tableName}.${column1.name}`, { column1, column2 });
|
|
364
367
|
changedProperties.add('comment');
|
|
365
368
|
}
|
|
366
|
-
if (
|
|
369
|
+
if (!(column1.mappedType instanceof core_1.ArrayType) &&
|
|
370
|
+
!(column2.mappedType instanceof core_1.ArrayType) &&
|
|
371
|
+
this.diffEnumItems(column1.enumItems, column2.enumItems)) {
|
|
367
372
|
log(`'enumItems' changed for column ${tableName}.${column1.name}`, { column1, column2 });
|
|
368
373
|
changedProperties.add('enumItems');
|
|
369
374
|
}
|
|
@@ -425,8 +430,10 @@ class SchemaComparator {
|
|
|
425
430
|
return index1.primary === index2.primary && index1.unique === index2.unique;
|
|
426
431
|
}
|
|
427
432
|
diffCheck(check1, check2) {
|
|
428
|
-
|
|
429
|
-
|
|
433
|
+
// check constraint definition might be normalized by the driver,
|
|
434
|
+
// e.g. quotes might be added (https://github.com/mikro-orm/mikro-orm/issues/3827)
|
|
435
|
+
const simplify = (str) => str?.replace(/['"`()]/g, '').toLowerCase();
|
|
436
|
+
return simplify(check1.expression) !== simplify(check2.expression);
|
|
430
437
|
}
|
|
431
438
|
hasSameDefaultValue(from, to) {
|
|
432
439
|
if (from.default == null || from.default.toString().toLowerCase() === 'null' || from.default.toString().startsWith('nextval(')) {
|
|
@@ -437,6 +444,11 @@ class SchemaComparator {
|
|
|
437
444
|
const defaultValueTo = !['0', 'false', 'f', 'n', 'no', 'off'].includes('' + to.default);
|
|
438
445
|
return defaultValueFrom === defaultValueTo;
|
|
439
446
|
}
|
|
447
|
+
if (to.mappedType instanceof core_1.JsonType) {
|
|
448
|
+
const defaultValueFrom = (0, core_1.parseJsonSafe)(from.default.replace(/^'(.*)'$/, '$1'));
|
|
449
|
+
const defaultValueTo = (0, core_1.parseJsonSafe)(to.default?.replace(/^'(.*)'$/, '$1'));
|
|
450
|
+
return core_1.Utils.equals(defaultValueFrom, defaultValueTo);
|
|
451
|
+
}
|
|
440
452
|
if (to.mappedType instanceof core_1.DateTimeType && from.default && to.default) {
|
|
441
453
|
// normalize now/current_timestamp defaults, also remove `()` from the end of default expression
|
|
442
454
|
const defaultValueFrom = from.default.toLowerCase().replace('current_timestamp', 'now').replace(/\(\)$/, '');
|
package/schema/SchemaHelper.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { Knex } from 'knex';
|
|
2
|
-
import type
|
|
2
|
+
import { type Connection, type Dictionary } from '@mikro-orm/core';
|
|
3
3
|
import type { AbstractSqlConnection } from '../AbstractSqlConnection';
|
|
4
4
|
import type { AbstractSqlPlatform } from '../AbstractSqlPlatform';
|
|
5
5
|
import type { CheckDef, Column, IndexDef, Table, TableDifference } from '../typings';
|
|
@@ -18,7 +18,9 @@ export declare abstract class SchemaHelper {
|
|
|
18
18
|
getForeignKeys(connection: AbstractSqlConnection, tableName: string, schemaName?: string): Promise<Dictionary>;
|
|
19
19
|
protected getTableKey(t: Table): string;
|
|
20
20
|
getEnumDefinitions(connection: AbstractSqlConnection, checks: CheckDef[], tableName: string, schemaName?: string): Promise<Dictionary<string[]>>;
|
|
21
|
-
|
|
21
|
+
getDropNativeEnumSQL(name: string, schema?: string): string;
|
|
22
|
+
getAlterNativeEnumSQL(name: string, schema?: string, value?: string): string;
|
|
23
|
+
loadInformationSchema(schema: DatabaseSchema, connection: AbstractSqlConnection, tables: Table[], schemas?: string[]): Promise<void>;
|
|
22
24
|
getListTablesSQL(schemaName?: string): string;
|
|
23
25
|
getRenameColumnSQL(tableName: string, oldColumnName: string, to: Column, schemaName?: string): string;
|
|
24
26
|
getCreateIndexSQL(tableName: string, index: IndexDef): string;
|
|
@@ -29,8 +31,8 @@ export declare abstract class SchemaHelper {
|
|
|
29
31
|
configureColumn(column: Column, col: Knex.ColumnBuilder, knex: Knex, changedProperties?: Set<string>): Knex.ColumnBuilder;
|
|
30
32
|
configureColumnDefault(column: Column, col: Knex.ColumnBuilder, knex: Knex, changedProperties?: Set<string>): Knex.ColumnBuilder;
|
|
31
33
|
getPreAlterTable(tableDiff: TableDifference, safe: boolean): string;
|
|
32
|
-
getAlterColumnAutoincrement(tableName: string, column: Column): string;
|
|
33
|
-
getChangeColumnCommentSQL(tableName: string, to: Column): string;
|
|
34
|
+
getAlterColumnAutoincrement(tableName: string, column: Column, schemaName?: string): string;
|
|
35
|
+
getChangeColumnCommentSQL(tableName: string, to: Column, schemaName?: string): string;
|
|
34
36
|
getNamespaces(connection: AbstractSqlConnection): Promise<string[]>;
|
|
35
37
|
getColumns(connection: AbstractSqlConnection, tableName: string, schemaName?: string): Promise<Column[]>;
|
|
36
38
|
getIndexes(connection: AbstractSqlConnection, tableName: string, schemaName?: string): Promise<IndexDef[]>;
|
package/schema/SchemaHelper.js
CHANGED
|
@@ -3,6 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.SchemaHelper = void 0;
|
|
4
4
|
const core_1 = require("@mikro-orm/core");
|
|
5
5
|
class SchemaHelper {
|
|
6
|
+
platform;
|
|
6
7
|
constructor(platform) {
|
|
7
8
|
this.platform = platform;
|
|
8
9
|
}
|
|
@@ -46,7 +47,13 @@ class SchemaHelper {
|
|
|
46
47
|
async getEnumDefinitions(connection, checks, tableName, schemaName) {
|
|
47
48
|
return {};
|
|
48
49
|
}
|
|
49
|
-
|
|
50
|
+
getDropNativeEnumSQL(name, schema) {
|
|
51
|
+
throw new Error('Not supported by given driver');
|
|
52
|
+
}
|
|
53
|
+
getAlterNativeEnumSQL(name, schema, value) {
|
|
54
|
+
throw new Error('Not supported by given driver');
|
|
55
|
+
}
|
|
56
|
+
async loadInformationSchema(schema, connection, tables, schemas) {
|
|
50
57
|
for (const t of tables) {
|
|
51
58
|
const table = schema.addTable(t.table_name, t.schema_name);
|
|
52
59
|
table.comment = t.table_comment;
|
|
@@ -122,17 +129,17 @@ class SchemaHelper {
|
|
|
122
129
|
core_1.Utils.runIfNotEmpty(() => col.defaultTo(column.default == null ? null : knex.raw(column.default)), guard('default'));
|
|
123
130
|
}
|
|
124
131
|
else {
|
|
125
|
-
core_1.Utils.runIfNotEmpty(() => col.defaultTo(
|
|
132
|
+
core_1.Utils.runIfNotEmpty(() => col.defaultTo(knex.raw(column.default)), column.default != null && column.default !== 'null');
|
|
126
133
|
}
|
|
127
134
|
return col;
|
|
128
135
|
}
|
|
129
136
|
getPreAlterTable(tableDiff, safe) {
|
|
130
137
|
return '';
|
|
131
138
|
}
|
|
132
|
-
getAlterColumnAutoincrement(tableName, column) {
|
|
139
|
+
getAlterColumnAutoincrement(tableName, column, schemaName) {
|
|
133
140
|
return '';
|
|
134
141
|
}
|
|
135
|
-
getChangeColumnCommentSQL(tableName, to) {
|
|
142
|
+
getChangeColumnCommentSQL(tableName, to, schemaName) {
|
|
136
143
|
return '';
|
|
137
144
|
}
|
|
138
145
|
async getNamespaces(connection) {
|
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
import type
|
|
2
|
-
import { AbstractSchemaGenerator } from '@mikro-orm/core';
|
|
1
|
+
import { AbstractSchemaGenerator, type MikroORM, type ISchemaGenerator } from '@mikro-orm/core';
|
|
3
2
|
import type { SchemaDifference } from '../typings';
|
|
4
3
|
import { DatabaseSchema } from './DatabaseSchema';
|
|
5
4
|
import type { AbstractSqlDriver } from '../AbstractSqlDriver';
|
|
@@ -8,8 +7,6 @@ export declare class SqlSchemaGenerator extends AbstractSchemaGenerator<Abstract
|
|
|
8
7
|
private readonly options;
|
|
9
8
|
protected lastEnsuredDatabase?: string;
|
|
10
9
|
static register(orm: MikroORM): void;
|
|
11
|
-
/** @deprecated use `dropSchema` and `createSchema` commands respectively */
|
|
12
|
-
generate(): Promise<string>;
|
|
13
10
|
createSchema(options?: {
|
|
14
11
|
wrap?: boolean;
|
|
15
12
|
schema?: string;
|
|
@@ -82,10 +79,10 @@ export declare class SqlSchemaGenerator extends AbstractSchemaGenerator<Abstract
|
|
|
82
79
|
* creates new database and connects to it
|
|
83
80
|
*/
|
|
84
81
|
createDatabase(name: string): Promise<void>;
|
|
85
|
-
dropDatabase(name
|
|
82
|
+
dropDatabase(name?: string): Promise<void>;
|
|
86
83
|
execute(sql: string, options?: {
|
|
87
84
|
wrap?: boolean;
|
|
88
|
-
}): Promise<
|
|
85
|
+
}): Promise<void>;
|
|
89
86
|
private wrapSchema;
|
|
90
87
|
private createSchemaBuilder;
|
|
91
88
|
private createTable;
|