@mikro-orm/sql 7.0.0-rc.3 → 7.0.1-dev.0
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 +5 -4
- package/AbstractSqlConnection.js +18 -5
- package/AbstractSqlDriver.d.ts +1 -1
- package/AbstractSqlDriver.js +39 -10
- package/AbstractSqlPlatform.d.ts +34 -0
- package/AbstractSqlPlatform.js +47 -3
- package/PivotCollectionPersister.d.ts +2 -11
- package/PivotCollectionPersister.js +59 -59
- package/README.md +5 -4
- package/SqlEntityManager.d.ts +1 -1
- package/dialects/index.d.ts +1 -0
- package/dialects/index.js +1 -0
- package/dialects/mysql/BaseMySqlPlatform.d.ts +6 -0
- package/dialects/mysql/BaseMySqlPlatform.js +17 -0
- package/dialects/mysql/MySqlSchemaHelper.d.ts +1 -1
- package/dialects/mysql/MySqlSchemaHelper.js +6 -6
- package/dialects/oracledb/OracleDialect.d.ts +78 -0
- package/dialects/oracledb/OracleDialect.js +166 -0
- package/dialects/oracledb/OracleNativeQueryBuilder.d.ts +19 -0
- package/dialects/oracledb/OracleNativeQueryBuilder.js +249 -0
- package/dialects/oracledb/index.d.ts +2 -0
- package/dialects/oracledb/index.js +2 -0
- package/dialects/postgresql/BasePostgreSqlPlatform.d.ts +6 -0
- package/dialects/postgresql/BasePostgreSqlPlatform.js +12 -8
- package/dialects/postgresql/PostgreSqlSchemaHelper.js +13 -13
- package/dialects/sqlite/SqlitePlatform.d.ts +1 -0
- package/dialects/sqlite/SqlitePlatform.js +3 -0
- package/dialects/sqlite/SqliteSchemaHelper.js +12 -8
- package/index.d.ts +1 -1
- package/index.js +0 -1
- package/package.json +3 -3
- package/plugin/index.d.ts +1 -14
- package/plugin/index.js +13 -13
- package/plugin/transformer.d.ts +6 -22
- package/plugin/transformer.js +81 -73
- package/query/ArrayCriteriaNode.d.ts +1 -1
- package/query/CriteriaNodeFactory.js +15 -3
- package/query/NativeQueryBuilder.d.ts +3 -3
- package/query/NativeQueryBuilder.js +4 -2
- package/query/ObjectCriteriaNode.js +4 -4
- package/query/QueryBuilder.d.ts +58 -62
- package/query/QueryBuilder.js +377 -370
- package/query/QueryBuilderHelper.d.ts +14 -11
- package/query/QueryBuilderHelper.js +324 -137
- package/query/ScalarCriteriaNode.js +3 -1
- package/query/enums.d.ts +2 -0
- package/query/enums.js +2 -0
- package/schema/DatabaseSchema.d.ts +7 -5
- package/schema/DatabaseSchema.js +50 -33
- package/schema/DatabaseTable.d.ts +8 -6
- package/schema/DatabaseTable.js +84 -60
- package/schema/SchemaComparator.d.ts +1 -3
- package/schema/SchemaComparator.js +22 -20
- package/schema/SchemaHelper.d.ts +2 -13
- package/schema/SchemaHelper.js +2 -1
- package/schema/SqlSchemaGenerator.d.ts +4 -14
- package/schema/SqlSchemaGenerator.js +15 -7
- package/typings.d.ts +4 -1
- package/tsconfig.build.tsbuildinfo +0 -1
|
@@ -18,7 +18,9 @@ export class ScalarCriteriaNode extends CriteriaNode {
|
|
|
18
18
|
const type = this.prop.kind === ReferenceKind.MANY_TO_MANY ? JoinType.pivotJoin : JoinType.leftJoin;
|
|
19
19
|
qb.join(field, nestedAlias, undefined, type, path);
|
|
20
20
|
// select the owner as virtual property when joining from 1:1 inverse side, but only if the parent is root entity
|
|
21
|
-
if (this.prop.kind === ReferenceKind.ONE_TO_ONE &&
|
|
21
|
+
if (this.prop.kind === ReferenceKind.ONE_TO_ONE &&
|
|
22
|
+
!parentPath.includes('.') &&
|
|
23
|
+
!qb.state.fields?.includes(field)) {
|
|
22
24
|
qb.addSelect(field);
|
|
23
25
|
}
|
|
24
26
|
}
|
package/query/enums.d.ts
CHANGED
|
@@ -7,6 +7,8 @@ export declare enum QueryType {
|
|
|
7
7
|
DELETE = "DELETE",
|
|
8
8
|
UPSERT = "UPSERT"
|
|
9
9
|
}
|
|
10
|
+
/** Operators that apply to the embedded array column itself, not to individual elements. */
|
|
11
|
+
export declare const EMBEDDABLE_ARRAY_OPS: string[];
|
|
10
12
|
export declare enum JoinType {
|
|
11
13
|
leftJoin = "left join",
|
|
12
14
|
innerJoin = "inner join",
|
package/query/enums.js
CHANGED
|
@@ -8,6 +8,8 @@ export var QueryType;
|
|
|
8
8
|
QueryType["DELETE"] = "DELETE";
|
|
9
9
|
QueryType["UPSERT"] = "UPSERT";
|
|
10
10
|
})(QueryType || (QueryType = {}));
|
|
11
|
+
/** Operators that apply to the embedded array column itself, not to individual elements. */
|
|
12
|
+
export const EMBEDDABLE_ARRAY_OPS = ['$contains', '$contained', '$overlap'];
|
|
11
13
|
export var JoinType;
|
|
12
14
|
(function (JoinType) {
|
|
13
15
|
JoinType["leftJoin"] = "left join";
|
|
@@ -7,19 +7,21 @@ import type { AbstractSqlPlatform } from '../AbstractSqlPlatform.js';
|
|
|
7
7
|
* @internal
|
|
8
8
|
*/
|
|
9
9
|
export declare class DatabaseSchema {
|
|
10
|
-
private
|
|
10
|
+
#private;
|
|
11
11
|
readonly name: string;
|
|
12
|
-
private tables;
|
|
13
|
-
private views;
|
|
14
|
-
private namespaces;
|
|
15
|
-
private nativeEnums;
|
|
16
12
|
constructor(platform: AbstractSqlPlatform, name: string);
|
|
17
13
|
addTable(name: string, schema: string | undefined | null, comment?: string): DatabaseTable;
|
|
18
14
|
getTables(): DatabaseTable[];
|
|
15
|
+
/** @internal */
|
|
16
|
+
setTables(tables: DatabaseTable[]): void;
|
|
17
|
+
/** @internal */
|
|
18
|
+
setNamespaces(namespaces: Set<string>): void;
|
|
19
19
|
getTable(name: string): DatabaseTable | undefined;
|
|
20
20
|
hasTable(name: string): boolean;
|
|
21
21
|
addView(name: string, schema: string | undefined | null, definition: string, materialized?: boolean, withData?: boolean): DatabaseView;
|
|
22
22
|
getViews(): DatabaseView[];
|
|
23
|
+
/** @internal */
|
|
24
|
+
setViews(views: DatabaseView[]): void;
|
|
23
25
|
getView(name: string): DatabaseView | undefined;
|
|
24
26
|
hasView(name: string): boolean;
|
|
25
27
|
setNativeEnums(nativeEnums: Dictionary<{
|
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;
|
|
@@ -43,7 +45,7 @@ export declare class DatabaseTable {
|
|
|
43
45
|
hasColumn(columnName: string): boolean;
|
|
44
46
|
getIndex(indexName: string): IndexDef | undefined;
|
|
45
47
|
hasIndex(indexName: string): boolean;
|
|
46
|
-
getCheck(checkName: string): CheckDef
|
|
48
|
+
getCheck(checkName: string): CheckDef | undefined;
|
|
47
49
|
hasCheck(checkName: string): boolean;
|
|
48
50
|
getPrimaryKey(): IndexDef | undefined;
|
|
49
51
|
hasPrimaryKey(): boolean;
|
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,14 +64,14 @@ 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
|
-
const match =
|
|
74
|
+
const match = /\w+\((\d+), ?(\d+)\)/.exec(prop.columnTypes[idx]);
|
|
66
75
|
/* v8 ignore next */
|
|
67
76
|
if (match) {
|
|
68
77
|
prop.precision ??= +match[1];
|
|
@@ -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,23 +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
|
}
|
|
126
|
+
// For cross-schema FKs on MySQL/MariaDB (where schema = database), when the referenced
|
|
127
|
+
// table has no explicit schema but the current table does, qualify with dbName so the
|
|
128
|
+
// FK can resolve the referenced table in the correct database
|
|
129
|
+
if (!schema && this.schema && !this.#platform.getDefaultSchemaName()) {
|
|
130
|
+
schema = config.get('dbName');
|
|
131
|
+
}
|
|
117
132
|
if (prop.createForeignKeyConstraint) {
|
|
118
|
-
this
|
|
133
|
+
this.#foreignKeys[constraintName] = {
|
|
119
134
|
constraintName,
|
|
120
135
|
columnNames: prop.fieldNames,
|
|
121
136
|
localTableName: this.getShortestName(false),
|
|
@@ -123,15 +138,15 @@ export class DatabaseTable {
|
|
|
123
138
|
referencedTableName: schema ? `${schema}.${prop.referencedTableName}` : prop.referencedTableName,
|
|
124
139
|
};
|
|
125
140
|
const schemaConfig = config.get('schemaGenerator');
|
|
126
|
-
this
|
|
127
|
-
this
|
|
141
|
+
this.#foreignKeys[constraintName].deleteRule = prop.deleteRule ?? schemaConfig.defaultDeleteRule;
|
|
142
|
+
this.#foreignKeys[constraintName].updateRule = prop.updateRule ?? schemaConfig.defaultUpdateRule;
|
|
128
143
|
if (prop.deferMode) {
|
|
129
|
-
this
|
|
144
|
+
this.#foreignKeys[constraintName].deferMode = prop.deferMode;
|
|
130
145
|
}
|
|
131
146
|
}
|
|
132
147
|
}
|
|
133
148
|
if (prop.index) {
|
|
134
|
-
this
|
|
149
|
+
this.#indexes.push({
|
|
135
150
|
columnNames: prop.fieldNames,
|
|
136
151
|
composite: prop.fieldNames.length > 1,
|
|
137
152
|
keyName: this.getIndexName(prop.index, prop.fieldNames, 'index'),
|
|
@@ -141,7 +156,7 @@ export class DatabaseTable {
|
|
|
141
156
|
});
|
|
142
157
|
}
|
|
143
158
|
if (prop.unique && !(prop.primary && !meta.compositePK)) {
|
|
144
|
-
this
|
|
159
|
+
this.#indexes.push({
|
|
145
160
|
columnNames: prop.fieldNames,
|
|
146
161
|
composite: prop.fieldNames.length > 1,
|
|
147
162
|
keyName: this.getIndexName(prop.unique, prop.fieldNames, 'unique'),
|
|
@@ -156,7 +171,7 @@ export class DatabaseTable {
|
|
|
156
171
|
if (typeof value === 'string') {
|
|
157
172
|
return value;
|
|
158
173
|
}
|
|
159
|
-
return this
|
|
174
|
+
return this.#platform.getIndexName(this.name, columnNames, type);
|
|
160
175
|
}
|
|
161
176
|
getEntityDeclaration(namingStrategy, schemaHelper, scalarPropertiesForRelations) {
|
|
162
177
|
const { fksOnColumnProps, fksOnStandaloneProps, columnFks, fkIndexes, nullableForeignKeys, skippedColumnNames } = this.foreignKeysToProps(namingStrategy, scalarPropertiesForRelations);
|
|
@@ -164,7 +179,7 @@ export class DatabaseTable {
|
|
|
164
179
|
const schema = new EntitySchema({ name, collection: this.name, schema: this.schema, comment: this.comment });
|
|
165
180
|
const compositeFkIndexes = {};
|
|
166
181
|
const compositeFkUniques = {};
|
|
167
|
-
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.
|
|
168
183
|
// Non-trivial non-composite indexes will be declared at the entity's metadata, though later outputted in the property
|
|
169
184
|
(index.columnNames.length > 1 || // All composite indexes are to be mapped to entity decorators or FK props.
|
|
170
185
|
skippedColumnNames.includes(index.columnNames[0]) || // Non-composite indexes for skipped columns are to be mapped as entity decorators.
|
|
@@ -456,7 +471,7 @@ export class DatabaseTable {
|
|
|
456
471
|
}
|
|
457
472
|
findFkIndex(currentFk) {
|
|
458
473
|
const fkColumnsLength = currentFk.columnNames.length;
|
|
459
|
-
const possibleIndexes = this
|
|
474
|
+
const possibleIndexes = this.#indexes.filter(index => {
|
|
460
475
|
return (index.columnNames.length === fkColumnsLength &&
|
|
461
476
|
!currentFk.columnNames.some((columnName, i) => index.columnNames[i] !== columnName));
|
|
462
477
|
});
|
|
@@ -557,7 +572,7 @@ export class DatabaseTable {
|
|
|
557
572
|
* The shortest name is stripped of the default namespace. All other namespaced elements are returned as full-qualified names.
|
|
558
573
|
*/
|
|
559
574
|
getShortestName(skipDefaultSchema = true) {
|
|
560
|
-
const defaultSchema = this
|
|
575
|
+
const defaultSchema = this.#platform.getDefaultSchemaName();
|
|
561
576
|
if (!this.schema ||
|
|
562
577
|
this.name.startsWith(defaultSchema + '.') ||
|
|
563
578
|
(this.schema === defaultSchema && skipDefaultSchema)) {
|
|
@@ -566,25 +581,25 @@ export class DatabaseTable {
|
|
|
566
581
|
return `${this.schema}.${this.name}`;
|
|
567
582
|
}
|
|
568
583
|
getForeignKeys() {
|
|
569
|
-
return this
|
|
584
|
+
return this.#foreignKeys;
|
|
570
585
|
}
|
|
571
586
|
hasColumn(columnName) {
|
|
572
|
-
return columnName in this
|
|
587
|
+
return columnName in this.#columns;
|
|
573
588
|
}
|
|
574
589
|
getIndex(indexName) {
|
|
575
|
-
return this
|
|
590
|
+
return this.#indexes.find(i => i.keyName === indexName);
|
|
576
591
|
}
|
|
577
592
|
hasIndex(indexName) {
|
|
578
593
|
return !!this.getIndex(indexName);
|
|
579
594
|
}
|
|
580
595
|
getCheck(checkName) {
|
|
581
|
-
return this
|
|
596
|
+
return this.#checks.find(i => i.name === checkName);
|
|
582
597
|
}
|
|
583
598
|
hasCheck(checkName) {
|
|
584
599
|
return !!this.getCheck(checkName);
|
|
585
600
|
}
|
|
586
601
|
getPrimaryKey() {
|
|
587
|
-
return this
|
|
602
|
+
return this.#indexes.find(i => i.primary);
|
|
588
603
|
}
|
|
589
604
|
hasPrimaryKey() {
|
|
590
605
|
return !!this.getPrimaryKey();
|
|
@@ -637,15 +652,15 @@ export class DatabaseTable {
|
|
|
637
652
|
const prop = this.getPropertyName(namingStrategy, column.name, fk);
|
|
638
653
|
const persist = !(column.name in columnFks && typeof fk === 'undefined');
|
|
639
654
|
const index = compositeFkIndexes[prop] ||
|
|
640
|
-
this
|
|
655
|
+
this.#indexes.find(idx => idx.columnNames[0] === column.name && !idx.composite && !idx.unique && !idx.primary);
|
|
641
656
|
const unique = compositeFkUniques[prop] ||
|
|
642
|
-
this
|
|
657
|
+
this.#indexes.find(idx => idx.columnNames[0] === column.name && !idx.composite && idx.unique && !idx.primary);
|
|
643
658
|
const kind = this.getReferenceKind(fk, unique);
|
|
644
659
|
const runtimeType = this.getPropertyTypeForColumn(namingStrategy, column, fk);
|
|
645
660
|
const type = fk
|
|
646
661
|
? runtimeType
|
|
647
662
|
: (Utils.keys(t).find(k => {
|
|
648
|
-
const typeInCoreMap = this
|
|
663
|
+
const typeInCoreMap = this.#platform.getMappedType(k);
|
|
649
664
|
return ((typeInCoreMap !== Type.getType(UnknownType) || k === 'unknown') && typeInCoreMap === column.mappedType);
|
|
650
665
|
}) ?? runtimeType);
|
|
651
666
|
const ignoreSchemaChanges = type === 'unknown' && column.length ? (column.extra ? ['type', 'extra'] : ['type']) : undefined;
|
|
@@ -728,7 +743,7 @@ export class DatabaseTable {
|
|
|
728
743
|
if (fk) {
|
|
729
744
|
return this.getPropertyTypeForForeignKey(namingStrategy, fk);
|
|
730
745
|
}
|
|
731
|
-
const enumMode = this
|
|
746
|
+
const enumMode = this.#platform.getConfig().get('entityGenerator').enumMode;
|
|
732
747
|
// If this column is using an enum.
|
|
733
748
|
if (column.enumItems?.length) {
|
|
734
749
|
const name = column.nativeEnumName ?? column.name;
|
|
@@ -755,7 +770,7 @@ export class DatabaseTable {
|
|
|
755
770
|
return +defaultValue;
|
|
756
771
|
}
|
|
757
772
|
// unquote string defaults if `raw = false`
|
|
758
|
-
const match = ('' + val)
|
|
773
|
+
const match = /^'(.*)'$/.exec('' + val);
|
|
759
774
|
if (!raw && match) {
|
|
760
775
|
return match[1];
|
|
761
776
|
}
|
|
@@ -772,7 +787,7 @@ export class DatabaseTable {
|
|
|
772
787
|
};
|
|
773
788
|
const columns = meta.createSchemaColumnMappingObject();
|
|
774
789
|
const exp = expression(columns, table, indexName);
|
|
775
|
-
return exp instanceof RawQueryFragment ? this
|
|
790
|
+
return exp instanceof RawQueryFragment ? this.#platform.formatQuery(exp.sql, exp.params) : exp;
|
|
776
791
|
}
|
|
777
792
|
return expression;
|
|
778
793
|
}
|
|
@@ -847,7 +862,7 @@ export class DatabaseTable {
|
|
|
847
862
|
if (index.fillFactor != null && (index.fillFactor < 0 || index.fillFactor > 100)) {
|
|
848
863
|
throw new Error(`fillFactor must be between 0 and 100, got ${index.fillFactor} for index '${name}' on entity '${meta.className}'`);
|
|
849
864
|
}
|
|
850
|
-
this
|
|
865
|
+
this.#indexes.push({
|
|
851
866
|
keyName: name,
|
|
852
867
|
columnNames: properties,
|
|
853
868
|
composite: properties.length > 1,
|
|
@@ -868,10 +883,10 @@ export class DatabaseTable {
|
|
|
868
883
|
});
|
|
869
884
|
}
|
|
870
885
|
addCheck(check) {
|
|
871
|
-
this
|
|
886
|
+
this.#checks.push(check);
|
|
872
887
|
}
|
|
873
888
|
toJSON() {
|
|
874
|
-
const
|
|
889
|
+
const columns = this.#columns;
|
|
875
890
|
const columnsMapped = Utils.keys(columns).reduce((o, col) => {
|
|
876
891
|
const c = columns[col];
|
|
877
892
|
const normalized = {
|
|
@@ -908,6 +923,15 @@ export class DatabaseTable {
|
|
|
908
923
|
o[col] = normalized;
|
|
909
924
|
return o;
|
|
910
925
|
}, {});
|
|
911
|
-
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
|
+
};
|
|
912
936
|
}
|
|
913
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.
|