@mikro-orm/sql 7.0.0-dev.320 → 7.0.0-dev.322
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/AbstractSqlDriver.js +4 -4
- package/PivotCollectionPersister.d.ts +2 -11
- package/PivotCollectionPersister.js +59 -59
- package/dialects/mysql/MySqlSchemaHelper.d.ts +1 -1
- package/dialects/mysql/MySqlSchemaHelper.js +4 -4
- package/package.json +2 -2
- package/plugin/index.d.ts +1 -3
- package/plugin/index.js +12 -12
- package/plugin/transformer.d.ts +5 -20
- package/plugin/transformer.js +81 -73
- package/query/ObjectCriteriaNode.js +3 -3
- package/query/QueryBuilder.d.ts +57 -51
- package/query/QueryBuilder.js +339 -368
- package/query/QueryBuilderHelper.d.ts +1 -8
- package/query/QueryBuilderHelper.js +97 -97
- package/query/ScalarCriteriaNode.js +3 -1
- package/schema/DatabaseSchema.d.ts +7 -5
- package/schema/DatabaseSchema.js +50 -33
- package/schema/DatabaseTable.d.ts +7 -5
- package/schema/DatabaseTable.js +77 -59
- package/schema/SchemaComparator.d.ts +1 -3
- package/schema/SchemaComparator.js +18 -18
- package/tsconfig.build.tsbuildinfo +1 -1
- package/typings.d.ts +4 -1
package/schema/DatabaseSchema.js
CHANGED
|
@@ -4,32 +4,40 @@ import { DatabaseTable } from './DatabaseTable.js';
|
|
|
4
4
|
* @internal
|
|
5
5
|
*/
|
|
6
6
|
export class DatabaseSchema {
|
|
7
|
-
platform;
|
|
8
7
|
name;
|
|
9
|
-
tables = [];
|
|
10
|
-
views = [];
|
|
11
|
-
namespaces = new Set();
|
|
12
|
-
nativeEnums = {}; // for postgres
|
|
8
|
+
#tables = [];
|
|
9
|
+
#views = [];
|
|
10
|
+
#namespaces = new Set();
|
|
11
|
+
#nativeEnums = {}; // for postgres
|
|
12
|
+
#platform;
|
|
13
13
|
constructor(platform, name) {
|
|
14
|
-
this.platform = platform;
|
|
15
14
|
this.name = name;
|
|
15
|
+
this.#platform = platform;
|
|
16
16
|
}
|
|
17
17
|
addTable(name, schema, comment) {
|
|
18
18
|
const namespaceName = schema ?? this.name;
|
|
19
|
-
const table = new DatabaseTable(this
|
|
20
|
-
table.nativeEnums = this
|
|
19
|
+
const table = new DatabaseTable(this.#platform, name, namespaceName);
|
|
20
|
+
table.nativeEnums = this.#nativeEnums;
|
|
21
21
|
table.comment = comment;
|
|
22
|
-
this
|
|
22
|
+
this.#tables.push(table);
|
|
23
23
|
if (namespaceName != null) {
|
|
24
|
-
this
|
|
24
|
+
this.#namespaces.add(namespaceName);
|
|
25
25
|
}
|
|
26
26
|
return table;
|
|
27
27
|
}
|
|
28
28
|
getTables() {
|
|
29
|
-
return this
|
|
29
|
+
return this.#tables;
|
|
30
|
+
}
|
|
31
|
+
/** @internal */
|
|
32
|
+
setTables(tables) {
|
|
33
|
+
this.#tables = tables;
|
|
34
|
+
}
|
|
35
|
+
/** @internal */
|
|
36
|
+
setNamespaces(namespaces) {
|
|
37
|
+
this.#namespaces = namespaces;
|
|
30
38
|
}
|
|
31
39
|
getTable(name) {
|
|
32
|
-
return this
|
|
40
|
+
return this.#tables.find(t => t.name === name || `${t.schema}.${t.name}` === name);
|
|
33
41
|
}
|
|
34
42
|
hasTable(name) {
|
|
35
43
|
return !!this.getTable(name);
|
|
@@ -37,43 +45,47 @@ export class DatabaseSchema {
|
|
|
37
45
|
addView(name, schema, definition, materialized, withData) {
|
|
38
46
|
const namespaceName = schema ?? this.name;
|
|
39
47
|
const view = { name, schema: namespaceName, definition, materialized, withData };
|
|
40
|
-
this
|
|
48
|
+
this.#views.push(view);
|
|
41
49
|
if (namespaceName != null) {
|
|
42
|
-
this
|
|
50
|
+
this.#namespaces.add(namespaceName);
|
|
43
51
|
}
|
|
44
52
|
return view;
|
|
45
53
|
}
|
|
46
54
|
getViews() {
|
|
47
|
-
return this
|
|
55
|
+
return this.#views;
|
|
56
|
+
}
|
|
57
|
+
/** @internal */
|
|
58
|
+
setViews(views) {
|
|
59
|
+
this.#views = views;
|
|
48
60
|
}
|
|
49
61
|
getView(name) {
|
|
50
|
-
return this
|
|
62
|
+
return this.#views.find(v => v.name === name || `${v.schema}.${v.name}` === name);
|
|
51
63
|
}
|
|
52
64
|
hasView(name) {
|
|
53
65
|
return !!this.getView(name);
|
|
54
66
|
}
|
|
55
67
|
setNativeEnums(nativeEnums) {
|
|
56
|
-
this
|
|
68
|
+
this.#nativeEnums = nativeEnums;
|
|
57
69
|
for (const nativeEnum of Object.values(nativeEnums)) {
|
|
58
70
|
if (nativeEnum.schema && nativeEnum.schema !== '*') {
|
|
59
|
-
this
|
|
71
|
+
this.#namespaces.add(nativeEnum.schema);
|
|
60
72
|
}
|
|
61
73
|
}
|
|
62
74
|
}
|
|
63
75
|
getNativeEnums() {
|
|
64
|
-
return this
|
|
76
|
+
return this.#nativeEnums;
|
|
65
77
|
}
|
|
66
78
|
getNativeEnum(name) {
|
|
67
|
-
return this
|
|
79
|
+
return this.#nativeEnums[name];
|
|
68
80
|
}
|
|
69
81
|
hasNamespace(namespace) {
|
|
70
|
-
return this
|
|
82
|
+
return this.#namespaces.has(namespace);
|
|
71
83
|
}
|
|
72
84
|
hasNativeEnum(name) {
|
|
73
|
-
return name in this
|
|
85
|
+
return name in this.#nativeEnums;
|
|
74
86
|
}
|
|
75
87
|
getNamespaces() {
|
|
76
|
-
return [...this
|
|
88
|
+
return [...this.#namespaces];
|
|
77
89
|
}
|
|
78
90
|
static async create(connection, platform, config, schemaName, schemas, takeTables, skipTables, skipViews) {
|
|
79
91
|
const schema = new DatabaseSchema(platform, schemaName ?? config.get('schema') ?? platform.getDefaultSchemaName());
|
|
@@ -94,7 +106,7 @@ export class DatabaseSchema {
|
|
|
94
106
|
}
|
|
95
107
|
// Filter out skipped views
|
|
96
108
|
if (skipViews && skipViews.length > 0) {
|
|
97
|
-
schema
|
|
109
|
+
schema.#views = schema.#views.filter(v => this.isNameAllowed(v.name, skipViews));
|
|
98
110
|
}
|
|
99
111
|
return schema;
|
|
100
112
|
}
|
|
@@ -291,28 +303,33 @@ export class DatabaseSchema {
|
|
|
291
303
|
(prop.kind === ReferenceKind.ONE_TO_ONE && prop.owner));
|
|
292
304
|
}
|
|
293
305
|
toJSON() {
|
|
294
|
-
|
|
295
|
-
|
|
306
|
+
return {
|
|
307
|
+
name: this.name,
|
|
308
|
+
namespaces: [...this.#namespaces],
|
|
309
|
+
tables: this.#tables,
|
|
310
|
+
views: this.#views,
|
|
311
|
+
nativeEnums: this.#nativeEnums,
|
|
312
|
+
};
|
|
296
313
|
}
|
|
297
314
|
prune(schema, wildcardSchemaTables) {
|
|
298
315
|
const hasWildcardSchema = wildcardSchemaTables.length > 0;
|
|
299
|
-
this
|
|
316
|
+
this.#tables = this.#tables.filter(table => {
|
|
300
317
|
return ((!schema && !hasWildcardSchema) || // no schema specified and we don't have any multi-schema entity
|
|
301
318
|
table.schema === schema || // specified schema matches the table's one
|
|
302
319
|
(!schema && !wildcardSchemaTables.includes(table.name))); // no schema specified and the table has fixed one provided
|
|
303
320
|
});
|
|
304
|
-
this
|
|
321
|
+
this.#views = this.#views.filter(view => {
|
|
305
322
|
/* v8 ignore next */
|
|
306
323
|
return ((!schema && !hasWildcardSchema) ||
|
|
307
324
|
view.schema === schema ||
|
|
308
325
|
(!schema && !wildcardSchemaTables.includes(view.name)));
|
|
309
326
|
});
|
|
310
327
|
// remove namespaces of ignored tables and views
|
|
311
|
-
for (const ns of this
|
|
312
|
-
if (!this
|
|
313
|
-
!this
|
|
314
|
-
!Object.values(this
|
|
315
|
-
this
|
|
328
|
+
for (const ns of this.#namespaces) {
|
|
329
|
+
if (!this.#tables.some(t => t.schema === ns) &&
|
|
330
|
+
!this.#views.some(v => v.schema === ns) &&
|
|
331
|
+
!Object.values(this.#nativeEnums).some(e => e.schema === ns)) {
|
|
332
|
+
this.#namespaces.delete(ns);
|
|
316
333
|
}
|
|
317
334
|
}
|
|
318
335
|
}
|
|
@@ -6,13 +6,9 @@ import type { AbstractSqlPlatform } from '../AbstractSqlPlatform.js';
|
|
|
6
6
|
* @internal
|
|
7
7
|
*/
|
|
8
8
|
export declare class DatabaseTable {
|
|
9
|
-
private
|
|
9
|
+
#private;
|
|
10
10
|
readonly name: string;
|
|
11
11
|
readonly schema?: string | undefined;
|
|
12
|
-
private columns;
|
|
13
|
-
private indexes;
|
|
14
|
-
private checks;
|
|
15
|
-
private foreignKeys;
|
|
16
12
|
nativeEnums: Dictionary<{
|
|
17
13
|
name: string;
|
|
18
14
|
schema?: string;
|
|
@@ -26,6 +22,12 @@ export declare class DatabaseTable {
|
|
|
26
22
|
removeColumn(name: string): void;
|
|
27
23
|
getIndexes(): IndexDef[];
|
|
28
24
|
getChecks(): CheckDef[];
|
|
25
|
+
/** @internal */
|
|
26
|
+
setIndexes(indexes: IndexDef[]): void;
|
|
27
|
+
/** @internal */
|
|
28
|
+
setChecks(checks: CheckDef[]): void;
|
|
29
|
+
/** @internal */
|
|
30
|
+
setForeignKeys(fks: Dictionary<ForeignKey>): void;
|
|
29
31
|
init(cols: Column[], indexes: IndexDef[] | undefined, checks: CheckDef[] | undefined, pks: string[], fks?: Dictionary<ForeignKey>, enums?: Dictionary<string[]>): void;
|
|
30
32
|
addColumn(column: Column): void;
|
|
31
33
|
addColumnFromProperty(prop: EntityProperty, meta: EntityMetadata, config: Configuration): void;
|
package/schema/DatabaseTable.js
CHANGED
|
@@ -3,51 +3,60 @@ import { DecimalType, EntitySchema, RawQueryFragment, ReferenceKind, t, Type, Un
|
|
|
3
3
|
* @internal
|
|
4
4
|
*/
|
|
5
5
|
export class DatabaseTable {
|
|
6
|
-
platform;
|
|
7
6
|
name;
|
|
8
7
|
schema;
|
|
9
|
-
columns = {};
|
|
10
|
-
indexes = [];
|
|
11
|
-
checks = [];
|
|
12
|
-
foreignKeys = {};
|
|
8
|
+
#columns = {};
|
|
9
|
+
#indexes = [];
|
|
10
|
+
#checks = [];
|
|
11
|
+
#foreignKeys = {};
|
|
12
|
+
#platform;
|
|
13
13
|
nativeEnums = {}; // for postgres
|
|
14
14
|
comment;
|
|
15
15
|
constructor(platform, name, schema) {
|
|
16
|
-
this.platform = platform;
|
|
17
16
|
this.name = name;
|
|
18
17
|
this.schema = schema;
|
|
19
|
-
|
|
20
|
-
platform: { enumerable: false, writable: true },
|
|
21
|
-
});
|
|
18
|
+
this.#platform = platform;
|
|
22
19
|
}
|
|
23
20
|
getQuotedName() {
|
|
24
|
-
return this
|
|
21
|
+
return this.#platform.quoteIdentifier(this.getShortestName());
|
|
25
22
|
}
|
|
26
23
|
getColumns() {
|
|
27
|
-
return Object.values(this
|
|
24
|
+
return Object.values(this.#columns);
|
|
28
25
|
}
|
|
29
26
|
getColumn(name) {
|
|
30
|
-
return this
|
|
27
|
+
return this.#columns[name];
|
|
31
28
|
}
|
|
32
29
|
removeColumn(name) {
|
|
33
|
-
delete this
|
|
30
|
+
delete this.#columns[name];
|
|
34
31
|
}
|
|
35
32
|
getIndexes() {
|
|
36
|
-
return Utils.removeDuplicates(this
|
|
33
|
+
return Utils.removeDuplicates(this.#indexes);
|
|
37
34
|
}
|
|
38
35
|
getChecks() {
|
|
39
|
-
return this
|
|
36
|
+
return this.#checks;
|
|
37
|
+
}
|
|
38
|
+
/** @internal */
|
|
39
|
+
setIndexes(indexes) {
|
|
40
|
+
this.#indexes = indexes;
|
|
41
|
+
}
|
|
42
|
+
/** @internal */
|
|
43
|
+
setChecks(checks) {
|
|
44
|
+
this.#checks = checks;
|
|
45
|
+
}
|
|
46
|
+
/** @internal */
|
|
47
|
+
setForeignKeys(fks) {
|
|
48
|
+
this.#foreignKeys = fks;
|
|
40
49
|
}
|
|
41
50
|
init(cols, indexes = [], checks = [], pks, fks = {}, enums = {}) {
|
|
42
|
-
this
|
|
43
|
-
this
|
|
44
|
-
this
|
|
45
|
-
this
|
|
51
|
+
this.#indexes = indexes;
|
|
52
|
+
this.#checks = checks;
|
|
53
|
+
this.#foreignKeys = fks;
|
|
54
|
+
this.#columns = cols.reduce((o, v) => {
|
|
46
55
|
const index = indexes.filter(i => i.columnNames[0] === v.name);
|
|
47
56
|
v.primary = v.primary || pks.includes(v.name);
|
|
48
57
|
v.unique = index.some(i => i.unique && !i.primary);
|
|
49
58
|
const type = v.name in enums ? 'enum' : v.type;
|
|
50
|
-
v.mappedType = this
|
|
59
|
+
v.mappedType = this.#platform.getMappedType(type);
|
|
51
60
|
v.default = v.default?.toString().startsWith('nextval(') ? null : v.default;
|
|
52
61
|
v.enumItems ??= enums[v.name] || [];
|
|
53
62
|
o[v.name] = v;
|
|
@@ -55,12 +64,12 @@ export class DatabaseTable {
|
|
|
55
64
|
}, {});
|
|
56
65
|
}
|
|
57
66
|
addColumn(column) {
|
|
58
|
-
this
|
|
67
|
+
this.#columns[column.name] = column;
|
|
59
68
|
}
|
|
60
69
|
addColumnFromProperty(prop, meta, config) {
|
|
61
70
|
prop.fieldNames?.forEach((field, idx) => {
|
|
62
71
|
const type = prop.enum ? 'enum' : prop.columnTypes[idx];
|
|
63
|
-
const mappedType = this
|
|
72
|
+
const mappedType = this.#platform.getMappedType(type);
|
|
64
73
|
if (mappedType instanceof DecimalType) {
|
|
65
74
|
const match = /\w+\((\d+), ?(\d+)\)/.exec(prop.columnTypes[idx]);
|
|
66
75
|
/* v8 ignore next */
|
|
@@ -71,24 +80,24 @@ export class DatabaseTable {
|
|
|
71
80
|
}
|
|
72
81
|
}
|
|
73
82
|
if (prop.length == null && prop.columnTypes[idx]) {
|
|
74
|
-
prop.length = this
|
|
83
|
+
prop.length = this.#platform.getSchemaHelper().inferLengthFromColumnType(prop.columnTypes[idx]);
|
|
75
84
|
if (typeof mappedType.getDefaultLength !== 'undefined') {
|
|
76
|
-
prop.length ??= mappedType.getDefaultLength(this
|
|
85
|
+
prop.length ??= mappedType.getDefaultLength(this.#platform);
|
|
77
86
|
}
|
|
78
87
|
}
|
|
79
88
|
const primary = !meta.compositePK && prop.fieldNames.length === 1 && !!prop.primary;
|
|
80
|
-
this
|
|
89
|
+
this.#columns[field] = {
|
|
81
90
|
name: prop.fieldNames[idx],
|
|
82
91
|
type: prop.columnTypes[idx],
|
|
83
92
|
generated: prop.generated instanceof RawQueryFragment
|
|
84
|
-
? this
|
|
93
|
+
? this.#platform.formatQuery(prop.generated.sql, prop.generated.params)
|
|
85
94
|
: prop.generated,
|
|
86
95
|
mappedType,
|
|
87
|
-
unsigned: prop.unsigned && this
|
|
96
|
+
unsigned: prop.unsigned && this.#platform.isNumericColumn(mappedType),
|
|
88
97
|
autoincrement: prop.autoincrement ??
|
|
89
|
-
(primary && prop.kind === ReferenceKind.SCALAR && this
|
|
98
|
+
(primary && prop.kind === ReferenceKind.SCALAR && this.#platform.isNumericColumn(mappedType)),
|
|
90
99
|
primary,
|
|
91
|
-
nullable: this
|
|
100
|
+
nullable: this.#columns[field]?.nullable ?? !!prop.nullable,
|
|
92
101
|
nativeEnumName: prop.nativeEnumName,
|
|
93
102
|
length: prop.length,
|
|
94
103
|
precision: prop.precision,
|
|
@@ -99,29 +108,29 @@ export class DatabaseTable {
|
|
|
99
108
|
extra: prop.extra,
|
|
100
109
|
ignoreSchemaChanges: prop.ignoreSchemaChanges,
|
|
101
110
|
};
|
|
102
|
-
this
|
|
111
|
+
this.#columns[field].unsigned ??= this.#columns[field].autoincrement;
|
|
103
112
|
if (this.nativeEnums[type]) {
|
|
104
|
-
this
|
|
113
|
+
this.#columns[field].enumItems ??= this.nativeEnums[type].items;
|
|
105
114
|
}
|
|
106
|
-
const defaultValue = this
|
|
107
|
-
this
|
|
115
|
+
const defaultValue = this.#platform.getSchemaHelper().normalizeDefaultValue(prop.defaultRaw, prop.length);
|
|
116
|
+
this.#columns[field].default = defaultValue;
|
|
108
117
|
});
|
|
109
118
|
if ([ReferenceKind.MANY_TO_ONE, ReferenceKind.ONE_TO_ONE].includes(prop.kind) && !prop.polymorphic) {
|
|
110
119
|
const constraintName = this.getIndexName(prop.foreignKeyName ?? true, prop.fieldNames, 'foreign');
|
|
111
120
|
let schema = prop.targetMeta.root.schema === '*'
|
|
112
121
|
? this.schema
|
|
113
|
-
: (prop.targetMeta.root.schema ?? config.get('schema', this
|
|
122
|
+
: (prop.targetMeta.root.schema ?? config.get('schema', this.#platform.getDefaultSchemaName()));
|
|
114
123
|
if (prop.referencedTableName.includes('.')) {
|
|
115
124
|
schema = undefined;
|
|
116
125
|
}
|
|
117
126
|
// For cross-schema FKs on MySQL/MariaDB (where schema = database), when the referenced
|
|
118
127
|
// table has no explicit schema but the current table does, qualify with dbName so the
|
|
119
128
|
// FK can resolve the referenced table in the correct database
|
|
120
|
-
if (!schema && this.schema && !this
|
|
129
|
+
if (!schema && this.schema && !this.#platform.getDefaultSchemaName()) {
|
|
121
130
|
schema = config.get('dbName');
|
|
122
131
|
}
|
|
123
132
|
if (prop.createForeignKeyConstraint) {
|
|
124
|
-
this
|
|
133
|
+
this.#foreignKeys[constraintName] = {
|
|
125
134
|
constraintName,
|
|
126
135
|
columnNames: prop.fieldNames,
|
|
127
136
|
localTableName: this.getShortestName(false),
|
|
@@ -129,15 +138,15 @@ export class DatabaseTable {
|
|
|
129
138
|
referencedTableName: schema ? `${schema}.${prop.referencedTableName}` : prop.referencedTableName,
|
|
130
139
|
};
|
|
131
140
|
const schemaConfig = config.get('schemaGenerator');
|
|
132
|
-
this
|
|
133
|
-
this
|
|
141
|
+
this.#foreignKeys[constraintName].deleteRule = prop.deleteRule ?? schemaConfig.defaultDeleteRule;
|
|
142
|
+
this.#foreignKeys[constraintName].updateRule = prop.updateRule ?? schemaConfig.defaultUpdateRule;
|
|
134
143
|
if (prop.deferMode) {
|
|
135
|
-
this
|
|
144
|
+
this.#foreignKeys[constraintName].deferMode = prop.deferMode;
|
|
136
145
|
}
|
|
137
146
|
}
|
|
138
147
|
}
|
|
139
148
|
if (prop.index) {
|
|
140
|
-
this
|
|
149
|
+
this.#indexes.push({
|
|
141
150
|
columnNames: prop.fieldNames,
|
|
142
151
|
composite: prop.fieldNames.length > 1,
|
|
143
152
|
keyName: this.getIndexName(prop.index, prop.fieldNames, 'index'),
|
|
@@ -147,7 +156,7 @@ export class DatabaseTable {
|
|
|
147
156
|
});
|
|
148
157
|
}
|
|
149
158
|
if (prop.unique && !(prop.primary && !meta.compositePK)) {
|
|
150
|
-
this
|
|
159
|
+
this.#indexes.push({
|
|
151
160
|
columnNames: prop.fieldNames,
|
|
152
161
|
composite: prop.fieldNames.length > 1,
|
|
153
162
|
keyName: this.getIndexName(prop.unique, prop.fieldNames, 'unique'),
|
|
@@ -162,7 +171,7 @@ export class DatabaseTable {
|
|
|
162
171
|
if (typeof value === 'string') {
|
|
163
172
|
return value;
|
|
164
173
|
}
|
|
165
|
-
return this
|
|
174
|
+
return this.#platform.getIndexName(this.name, columnNames, type);
|
|
166
175
|
}
|
|
167
176
|
getEntityDeclaration(namingStrategy, schemaHelper, scalarPropertiesForRelations) {
|
|
168
177
|
const { fksOnColumnProps, fksOnStandaloneProps, columnFks, fkIndexes, nullableForeignKeys, skippedColumnNames } = this.foreignKeysToProps(namingStrategy, scalarPropertiesForRelations);
|
|
@@ -170,7 +179,7 @@ export class DatabaseTable {
|
|
|
170
179
|
const schema = new EntitySchema({ name, collection: this.name, schema: this.schema, comment: this.comment });
|
|
171
180
|
const compositeFkIndexes = {};
|
|
172
181
|
const compositeFkUniques = {};
|
|
173
|
-
const potentiallyUnmappedIndexes = this
|
|
182
|
+
const potentiallyUnmappedIndexes = this.#indexes.filter(index => !index.primary && // Skip primary index. Whether it's in use by scalar column or FK, it's already mapped.
|
|
174
183
|
// Non-trivial non-composite indexes will be declared at the entity's metadata, though later outputted in the property
|
|
175
184
|
(index.columnNames.length > 1 || // All composite indexes are to be mapped to entity decorators or FK props.
|
|
176
185
|
skippedColumnNames.includes(index.columnNames[0]) || // Non-composite indexes for skipped columns are to be mapped as entity decorators.
|
|
@@ -462,7 +471,7 @@ export class DatabaseTable {
|
|
|
462
471
|
}
|
|
463
472
|
findFkIndex(currentFk) {
|
|
464
473
|
const fkColumnsLength = currentFk.columnNames.length;
|
|
465
|
-
const possibleIndexes = this
|
|
474
|
+
const possibleIndexes = this.#indexes.filter(index => {
|
|
466
475
|
return (index.columnNames.length === fkColumnsLength &&
|
|
467
476
|
!currentFk.columnNames.some((columnName, i) => index.columnNames[i] !== columnName));
|
|
468
477
|
});
|
|
@@ -563,7 +572,7 @@ export class DatabaseTable {
|
|
|
563
572
|
* The shortest name is stripped of the default namespace. All other namespaced elements are returned as full-qualified names.
|
|
564
573
|
*/
|
|
565
574
|
getShortestName(skipDefaultSchema = true) {
|
|
566
|
-
const defaultSchema = this
|
|
575
|
+
const defaultSchema = this.#platform.getDefaultSchemaName();
|
|
567
576
|
if (!this.schema ||
|
|
568
577
|
this.name.startsWith(defaultSchema + '.') ||
|
|
569
578
|
(this.schema === defaultSchema && skipDefaultSchema)) {
|
|
@@ -572,25 +581,25 @@ export class DatabaseTable {
|
|
|
572
581
|
return `${this.schema}.${this.name}`;
|
|
573
582
|
}
|
|
574
583
|
getForeignKeys() {
|
|
575
|
-
return this
|
|
584
|
+
return this.#foreignKeys;
|
|
576
585
|
}
|
|
577
586
|
hasColumn(columnName) {
|
|
578
|
-
return columnName in this
|
|
587
|
+
return columnName in this.#columns;
|
|
579
588
|
}
|
|
580
589
|
getIndex(indexName) {
|
|
581
|
-
return this
|
|
590
|
+
return this.#indexes.find(i => i.keyName === indexName);
|
|
582
591
|
}
|
|
583
592
|
hasIndex(indexName) {
|
|
584
593
|
return !!this.getIndex(indexName);
|
|
585
594
|
}
|
|
586
595
|
getCheck(checkName) {
|
|
587
|
-
return this
|
|
596
|
+
return this.#checks.find(i => i.name === checkName);
|
|
588
597
|
}
|
|
589
598
|
hasCheck(checkName) {
|
|
590
599
|
return !!this.getCheck(checkName);
|
|
591
600
|
}
|
|
592
601
|
getPrimaryKey() {
|
|
593
|
-
return this
|
|
602
|
+
return this.#indexes.find(i => i.primary);
|
|
594
603
|
}
|
|
595
604
|
hasPrimaryKey() {
|
|
596
605
|
return !!this.getPrimaryKey();
|
|
@@ -643,15 +652,15 @@ export class DatabaseTable {
|
|
|
643
652
|
const prop = this.getPropertyName(namingStrategy, column.name, fk);
|
|
644
653
|
const persist = !(column.name in columnFks && typeof fk === 'undefined');
|
|
645
654
|
const index = compositeFkIndexes[prop] ||
|
|
646
|
-
this
|
|
655
|
+
this.#indexes.find(idx => idx.columnNames[0] === column.name && !idx.composite && !idx.unique && !idx.primary);
|
|
647
656
|
const unique = compositeFkUniques[prop] ||
|
|
648
|
-
this
|
|
657
|
+
this.#indexes.find(idx => idx.columnNames[0] === column.name && !idx.composite && idx.unique && !idx.primary);
|
|
649
658
|
const kind = this.getReferenceKind(fk, unique);
|
|
650
659
|
const runtimeType = this.getPropertyTypeForColumn(namingStrategy, column, fk);
|
|
651
660
|
const type = fk
|
|
652
661
|
? runtimeType
|
|
653
662
|
: (Utils.keys(t).find(k => {
|
|
654
|
-
const typeInCoreMap = this
|
|
663
|
+
const typeInCoreMap = this.#platform.getMappedType(k);
|
|
655
664
|
return ((typeInCoreMap !== Type.getType(UnknownType) || k === 'unknown') && typeInCoreMap === column.mappedType);
|
|
656
665
|
}) ?? runtimeType);
|
|
657
666
|
const ignoreSchemaChanges = type === 'unknown' && column.length ? (column.extra ? ['type', 'extra'] : ['type']) : undefined;
|
|
@@ -734,7 +743,7 @@ export class DatabaseTable {
|
|
|
734
743
|
if (fk) {
|
|
735
744
|
return this.getPropertyTypeForForeignKey(namingStrategy, fk);
|
|
736
745
|
}
|
|
737
|
-
const enumMode = this
|
|
746
|
+
const enumMode = this.#platform.getConfig().get('entityGenerator').enumMode;
|
|
738
747
|
// If this column is using an enum.
|
|
739
748
|
if (column.enumItems?.length) {
|
|
740
749
|
const name = column.nativeEnumName ?? column.name;
|
|
@@ -778,7 +787,7 @@ export class DatabaseTable {
|
|
|
778
787
|
};
|
|
779
788
|
const columns = meta.createSchemaColumnMappingObject();
|
|
780
789
|
const exp = expression(columns, table, indexName);
|
|
781
|
-
return exp instanceof RawQueryFragment ? this
|
|
790
|
+
return exp instanceof RawQueryFragment ? this.#platform.formatQuery(exp.sql, exp.params) : exp;
|
|
782
791
|
}
|
|
783
792
|
return expression;
|
|
784
793
|
}
|
|
@@ -853,7 +862,7 @@ export class DatabaseTable {
|
|
|
853
862
|
if (index.fillFactor != null && (index.fillFactor < 0 || index.fillFactor > 100)) {
|
|
854
863
|
throw new Error(`fillFactor must be between 0 and 100, got ${index.fillFactor} for index '${name}' on entity '${meta.className}'`);
|
|
855
864
|
}
|
|
856
|
-
this
|
|
865
|
+
this.#indexes.push({
|
|
857
866
|
keyName: name,
|
|
858
867
|
columnNames: properties,
|
|
859
868
|
composite: properties.length > 1,
|
|
@@ -874,10 +883,10 @@ export class DatabaseTable {
|
|
|
874
883
|
});
|
|
875
884
|
}
|
|
876
885
|
addCheck(check) {
|
|
877
|
-
this
|
|
886
|
+
this.#checks.push(check);
|
|
878
887
|
}
|
|
879
888
|
toJSON() {
|
|
880
|
-
const
|
|
889
|
+
const columns = this.#columns;
|
|
881
890
|
const columnsMapped = Utils.keys(columns).reduce((o, col) => {
|
|
882
891
|
const c = columns[col];
|
|
883
892
|
const normalized = {
|
|
@@ -914,6 +923,15 @@ export class DatabaseTable {
|
|
|
914
923
|
o[col] = normalized;
|
|
915
924
|
return o;
|
|
916
925
|
}, {});
|
|
917
|
-
return {
|
|
926
|
+
return {
|
|
927
|
+
name: this.name,
|
|
928
|
+
schema: this.schema,
|
|
929
|
+
columns: columnsMapped,
|
|
930
|
+
indexes: this.#indexes,
|
|
931
|
+
checks: this.#checks,
|
|
932
|
+
foreignKeys: this.#foreignKeys,
|
|
933
|
+
nativeEnums: this.nativeEnums,
|
|
934
|
+
comment: this.comment,
|
|
935
|
+
};
|
|
918
936
|
}
|
|
919
937
|
}
|
|
@@ -7,9 +7,7 @@ import type { AbstractSqlPlatform } from '../AbstractSqlPlatform.js';
|
|
|
7
7
|
* Compares two Schemas and return an instance of SchemaDifference.
|
|
8
8
|
*/
|
|
9
9
|
export declare class SchemaComparator {
|
|
10
|
-
private
|
|
11
|
-
private readonly helper;
|
|
12
|
-
private readonly logger;
|
|
10
|
+
#private;
|
|
13
11
|
constructor(platform: AbstractSqlPlatform);
|
|
14
12
|
/**
|
|
15
13
|
* Returns a SchemaDifference object containing the differences between the schemas fromSchema and toSchema.
|
|
@@ -3,13 +3,13 @@ import { ArrayType, BooleanType, DateTimeType, inspect, JsonType, parseJsonSafe,
|
|
|
3
3
|
* Compares two Schemas and return an instance of SchemaDifference.
|
|
4
4
|
*/
|
|
5
5
|
export class SchemaComparator {
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
6
|
+
#helper;
|
|
7
|
+
#logger;
|
|
8
|
+
#platform;
|
|
9
9
|
constructor(platform) {
|
|
10
|
-
this
|
|
11
|
-
this
|
|
12
|
-
this
|
|
10
|
+
this.#platform = platform;
|
|
11
|
+
this.#helper = this.#platform.getSchemaHelper();
|
|
12
|
+
this.#logger = this.#platform.getConfig().getLogger();
|
|
13
13
|
}
|
|
14
14
|
/**
|
|
15
15
|
* Returns a SchemaDifference object containing the differences between the schemas fromSchema and toSchema.
|
|
@@ -35,13 +35,13 @@ export class SchemaComparator {
|
|
|
35
35
|
};
|
|
36
36
|
const foreignKeysToTable = {};
|
|
37
37
|
for (const namespace of toSchema.getNamespaces()) {
|
|
38
|
-
if (fromSchema.hasNamespace(namespace) || namespace === this
|
|
38
|
+
if (fromSchema.hasNamespace(namespace) || namespace === this.#platform.getDefaultSchemaName()) {
|
|
39
39
|
continue;
|
|
40
40
|
}
|
|
41
41
|
diff.newNamespaces.add(namespace);
|
|
42
42
|
}
|
|
43
43
|
for (const namespace of fromSchema.getNamespaces()) {
|
|
44
|
-
if (toSchema.hasNamespace(namespace) || namespace === this
|
|
44
|
+
if (toSchema.hasNamespace(namespace) || namespace === this.#platform.getDefaultSchemaName()) {
|
|
45
45
|
continue;
|
|
46
46
|
}
|
|
47
47
|
diff.removedNamespaces.add(namespace);
|
|
@@ -418,7 +418,7 @@ export class SchemaComparator {
|
|
|
418
418
|
if (key1.deferMode !== key2.deferMode) {
|
|
419
419
|
return true;
|
|
420
420
|
}
|
|
421
|
-
if (key1.localTableName === key1.referencedTableName && !this
|
|
421
|
+
if (key1.localTableName === key1.referencedTableName && !this.#platform.supportsMultipleCascadePaths()) {
|
|
422
422
|
return false;
|
|
423
423
|
}
|
|
424
424
|
if (key1.columnNames.some(col => tableDifferences.changedColumns[col]?.changedProperties.has('type'))) {
|
|
@@ -430,7 +430,7 @@ export class SchemaComparator {
|
|
|
430
430
|
};
|
|
431
431
|
const compare = (method) => rule(key1, method) === rule(key2, method);
|
|
432
432
|
// Skip updateRule comparison for platforms that don't support ON UPDATE (e.g., Oracle)
|
|
433
|
-
const updateRuleDiffers = this
|
|
433
|
+
const updateRuleDiffers = this.#platform.supportsOnUpdate() && !compare('updateRule');
|
|
434
434
|
return updateRuleDiffers || !compare('deleteRule');
|
|
435
435
|
}
|
|
436
436
|
/**
|
|
@@ -440,10 +440,10 @@ export class SchemaComparator {
|
|
|
440
440
|
const changedProperties = new Set();
|
|
441
441
|
const fromProp = this.mapColumnToProperty({ ...fromColumn, autoincrement: false });
|
|
442
442
|
const toProp = this.mapColumnToProperty({ ...toColumn, autoincrement: false });
|
|
443
|
-
const fromColumnType = this
|
|
443
|
+
const fromColumnType = this.#platform.normalizeColumnType(fromColumn.mappedType.getColumnType(fromProp, this.#platform).toLowerCase(), fromProp);
|
|
444
444
|
const fromNativeEnum = fromTable.nativeEnums[fromColumnType] ??
|
|
445
445
|
Object.values(fromTable.nativeEnums).find(e => e.name === fromColumnType && e.schema !== '*');
|
|
446
|
-
let toColumnType = this
|
|
446
|
+
let toColumnType = this.#platform.normalizeColumnType(toColumn.mappedType.getColumnType(toProp, this.#platform).toLowerCase(), toProp);
|
|
447
447
|
const log = (msg, params) => {
|
|
448
448
|
if (logging) {
|
|
449
449
|
const copy = Utils.copy(params);
|
|
@@ -458,7 +458,7 @@ export class SchemaComparator {
|
|
|
458
458
|
!toColumn.generated) {
|
|
459
459
|
if (!toColumnType.includes('.') &&
|
|
460
460
|
fromTable.schema &&
|
|
461
|
-
fromTable.schema !== this
|
|
461
|
+
fromTable.schema !== this.#platform.getDefaultSchemaName()) {
|
|
462
462
|
toColumnType = `${fromTable.schema}.${toColumnType}`;
|
|
463
463
|
}
|
|
464
464
|
if (fromColumnType !== toColumnType) {
|
|
@@ -478,7 +478,7 @@ export class SchemaComparator {
|
|
|
478
478
|
log(`'autoincrement' changed for column ${fromTable.name}.${fromColumn.name}`, { fromColumn, toColumn });
|
|
479
479
|
changedProperties.add('autoincrement');
|
|
480
480
|
}
|
|
481
|
-
if (!!fromColumn.unsigned !== !!toColumn.unsigned && this
|
|
481
|
+
if (!!fromColumn.unsigned !== !!toColumn.unsigned && this.#platform.supportsUnsigned()) {
|
|
482
482
|
log(`'unsigned' changed for column ${fromTable.name}.${fromColumn.name}`, { fromColumn, toColumn });
|
|
483
483
|
changedProperties.add('unsigned');
|
|
484
484
|
}
|
|
@@ -575,7 +575,7 @@ export class SchemaComparator {
|
|
|
575
575
|
// index that has no constraints.
|
|
576
576
|
return true;
|
|
577
577
|
}
|
|
578
|
-
if (this
|
|
578
|
+
if (this.#platform.supportsDeferredUniqueConstraints() && index1.deferMode !== index2.deferMode) {
|
|
579
579
|
return false;
|
|
580
580
|
}
|
|
581
581
|
return index1.primary === index2.primary && index1.unique === index2.unique;
|
|
@@ -699,8 +699,8 @@ export class SchemaComparator {
|
|
|
699
699
|
if (from.default && to.default) {
|
|
700
700
|
return from.default.toString().toLowerCase() === to.default.toString().toLowerCase();
|
|
701
701
|
}
|
|
702
|
-
if (['', this
|
|
703
|
-
return ['', this
|
|
702
|
+
if (['', this.#helper.getDefaultEmptyString()].includes(to.default) && from.default != null) {
|
|
703
|
+
return ['', this.#helper.getDefaultEmptyString()].includes(from.default.toString());
|
|
704
704
|
}
|
|
705
705
|
// eslint-disable-next-line eqeqeq
|
|
706
706
|
return from.default == to.default; // == intentionally
|
|
@@ -722,6 +722,6 @@ export class SchemaComparator {
|
|
|
722
722
|
if (params) {
|
|
723
723
|
message += ' ' + inspect(params);
|
|
724
724
|
}
|
|
725
|
-
this
|
|
725
|
+
this.#logger.log('schema', message);
|
|
726
726
|
}
|
|
727
727
|
}
|