@mikro-orm/knex 7.0.0-dev.7 → 7.0.0-dev.70
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 +11 -5
- package/AbstractSqlConnection.js +79 -32
- package/AbstractSqlDriver.d.ts +9 -5
- package/AbstractSqlDriver.js +268 -220
- package/AbstractSqlPlatform.js +3 -3
- package/PivotCollectionPersister.d.ts +3 -2
- package/PivotCollectionPersister.js +12 -21
- package/README.md +3 -2
- package/SqlEntityManager.d.ts +9 -2
- package/SqlEntityManager.js +2 -2
- package/dialects/mssql/MsSqlNativeQueryBuilder.d.ts +2 -0
- package/dialects/mssql/MsSqlNativeQueryBuilder.js +43 -2
- package/dialects/mysql/MySqlPlatform.js +2 -1
- package/dialects/postgresql/PostgreSqlTableCompiler.d.ts +1 -0
- package/dialects/postgresql/PostgreSqlTableCompiler.js +1 -0
- package/dialects/sqlite/BaseSqliteConnection.d.ts +4 -2
- package/dialects/sqlite/BaseSqliteConnection.js +8 -5
- package/dialects/sqlite/BaseSqlitePlatform.js +1 -2
- package/dialects/sqlite/SqliteSchemaHelper.js +1 -1
- package/index.d.ts +1 -1
- package/index.js +1 -1
- package/package.json +5 -5
- package/query/ArrayCriteriaNode.d.ts +1 -0
- package/query/ArrayCriteriaNode.js +3 -0
- package/query/CriteriaNode.d.ts +4 -2
- package/query/CriteriaNode.js +11 -6
- package/query/CriteriaNodeFactory.js +12 -7
- package/query/NativeQueryBuilder.js +1 -1
- package/query/ObjectCriteriaNode.d.ts +1 -0
- package/query/ObjectCriteriaNode.js +38 -9
- package/query/QueryBuilder.d.ts +59 -7
- package/query/QueryBuilder.js +171 -47
- package/query/QueryBuilderHelper.d.ts +1 -1
- package/query/QueryBuilderHelper.js +15 -8
- package/query/ScalarCriteriaNode.d.ts +3 -3
- package/query/ScalarCriteriaNode.js +9 -7
- package/query/index.d.ts +1 -0
- package/query/index.js +1 -0
- package/query/raw.d.ts +59 -0
- package/query/raw.js +68 -0
- package/query/rawKnex.d.ts +58 -0
- package/query/rawKnex.js +72 -0
- package/schema/DatabaseSchema.js +25 -4
- package/schema/DatabaseTable.d.ts +5 -4
- package/schema/DatabaseTable.js +67 -33
- package/schema/SchemaComparator.js +2 -2
- package/schema/SchemaHelper.d.ts +2 -0
- package/schema/SchemaHelper.js +8 -4
- package/schema/SqlSchemaGenerator.d.ts +13 -6
- package/schema/SqlSchemaGenerator.js +38 -17
- package/typings.d.ts +85 -3
package/schema/DatabaseTable.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Cascade, DecimalType, EntitySchema, ReferenceKind, t, Type, UnknownType, Utils, } from '@mikro-orm/core';
|
|
1
|
+
import { Cascade, DecimalType, EntitySchema, RawQueryFragment, ReferenceKind, t, Type, UnknownType, Utils, } from '@mikro-orm/core';
|
|
2
2
|
/**
|
|
3
3
|
* @internal
|
|
4
4
|
*/
|
|
@@ -91,47 +91,52 @@ export class DatabaseTable {
|
|
|
91
91
|
precision: prop.precision,
|
|
92
92
|
scale: prop.scale,
|
|
93
93
|
default: prop.defaultRaw,
|
|
94
|
-
enumItems: prop.nativeEnumName || prop.items?.every(
|
|
94
|
+
enumItems: prop.nativeEnumName || prop.items?.every(i => typeof i === 'string') ? prop.items : undefined,
|
|
95
95
|
comment: prop.comment,
|
|
96
96
|
extra: prop.extra,
|
|
97
97
|
ignoreSchemaChanges: prop.ignoreSchemaChanges,
|
|
98
98
|
};
|
|
99
99
|
this.columns[field].unsigned ??= this.columns[field].autoincrement;
|
|
100
|
+
if (this.nativeEnums[type]) {
|
|
101
|
+
this.columns[field].enumItems ??= this.nativeEnums[type].items;
|
|
102
|
+
}
|
|
100
103
|
const defaultValue = this.platform.getSchemaHelper().normalizeDefaultValue(prop.defaultRaw, prop.length);
|
|
101
104
|
this.columns[field].default = defaultValue;
|
|
102
105
|
});
|
|
103
106
|
if ([ReferenceKind.MANY_TO_ONE, ReferenceKind.ONE_TO_ONE].includes(prop.kind)) {
|
|
104
|
-
const constraintName = this.getIndexName(true, prop.fieldNames, 'foreign');
|
|
107
|
+
const constraintName = this.getIndexName(prop.foreignKeyName ?? true, prop.fieldNames, 'foreign');
|
|
105
108
|
let schema = prop.targetMeta.root.schema === '*' ? this.schema : (prop.targetMeta.root.schema ?? config.get('schema', this.platform.getDefaultSchemaName()));
|
|
106
109
|
if (prop.referencedTableName.includes('.')) {
|
|
107
110
|
schema = undefined;
|
|
108
111
|
}
|
|
109
|
-
|
|
110
|
-
constraintName
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
this.
|
|
112
|
+
if (prop.createForeignKeyConstraint) {
|
|
113
|
+
this.foreignKeys[constraintName] = {
|
|
114
|
+
constraintName,
|
|
115
|
+
columnNames: prop.fieldNames,
|
|
116
|
+
localTableName: this.getShortestName(false),
|
|
117
|
+
referencedColumnNames: prop.referencedColumnNames,
|
|
118
|
+
referencedTableName: schema ? `${schema}.${prop.referencedTableName}` : prop.referencedTableName,
|
|
119
|
+
};
|
|
120
|
+
const cascade = prop.cascade.includes(Cascade.REMOVE) || prop.cascade.includes(Cascade.ALL);
|
|
121
|
+
if (prop.deleteRule || cascade || prop.nullable) {
|
|
122
|
+
this.foreignKeys[constraintName].deleteRule = prop.deleteRule || (cascade ? 'cascade' : 'set null');
|
|
123
|
+
}
|
|
124
|
+
if (prop.updateRule) {
|
|
125
|
+
this.foreignKeys[constraintName].updateRule = prop.updateRule || 'cascade';
|
|
126
|
+
}
|
|
127
|
+
if ((prop.cascade.includes(Cascade.PERSIST) || prop.cascade.includes(Cascade.ALL))) {
|
|
128
|
+
const hasCascadePath = Object.values(this.foreignKeys).some(fk => {
|
|
129
|
+
return fk.constraintName !== constraintName
|
|
130
|
+
&& ((fk.updateRule && fk.updateRule !== 'no action') || (fk.deleteRule && fk.deleteRule !== 'no action'))
|
|
131
|
+
&& fk.referencedTableName === this.foreignKeys[constraintName].referencedTableName;
|
|
132
|
+
});
|
|
133
|
+
if (!hasCascadePath || this.platform.supportsMultipleCascadePaths()) {
|
|
134
|
+
this.foreignKeys[constraintName].updateRule ??= 'cascade';
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
if (prop.deferMode) {
|
|
138
|
+
this.foreignKeys[constraintName].deferMode = prop.deferMode;
|
|
131
139
|
}
|
|
132
|
-
}
|
|
133
|
-
if (prop.deferMode) {
|
|
134
|
-
this.foreignKeys[constraintName].deferMode = prop.deferMode;
|
|
135
140
|
}
|
|
136
141
|
}
|
|
137
142
|
if (prop.index) {
|
|
@@ -157,7 +162,7 @@ export class DatabaseTable {
|
|
|
157
162
|
}
|
|
158
163
|
}
|
|
159
164
|
getIndexName(value, columnNames, type) {
|
|
160
|
-
if (
|
|
165
|
+
if (typeof value === 'string') {
|
|
161
166
|
return value;
|
|
162
167
|
}
|
|
163
168
|
return this.platform.getIndexName(this.name, columnNames, type);
|
|
@@ -610,7 +615,7 @@ export class DatabaseTable {
|
|
|
610
615
|
fkOptions.deferMode = fk.deferMode;
|
|
611
616
|
fkOptions.columnTypes = fk.columnNames.map(col => this.getColumn(col).type);
|
|
612
617
|
}
|
|
613
|
-
|
|
618
|
+
const ret = {
|
|
614
619
|
name: prop,
|
|
615
620
|
type,
|
|
616
621
|
runtimeType,
|
|
@@ -638,6 +643,11 @@ export class DatabaseTable {
|
|
|
638
643
|
persist,
|
|
639
644
|
...fkOptions,
|
|
640
645
|
};
|
|
646
|
+
const nativeEnumName = Object.keys(this.nativeEnums).find(name => name === column.type);
|
|
647
|
+
if (nativeEnumName) {
|
|
648
|
+
ret.nativeEnumName = nativeEnumName;
|
|
649
|
+
}
|
|
650
|
+
return ret;
|
|
641
651
|
}
|
|
642
652
|
getReferenceKind(fk, unique) {
|
|
643
653
|
if (fk && unique) {
|
|
@@ -671,10 +681,17 @@ export class DatabaseTable {
|
|
|
671
681
|
if (fk) {
|
|
672
682
|
return this.getPropertyTypeForForeignKey(namingStrategy, fk);
|
|
673
683
|
}
|
|
684
|
+
const enumMode = this.platform.getConfig().get('entityGenerator').enumMode;
|
|
674
685
|
// If this column is using an enum.
|
|
675
686
|
if (column.enumItems?.length) {
|
|
676
|
-
|
|
677
|
-
|
|
687
|
+
const name = column.nativeEnumName ?? column.name;
|
|
688
|
+
const tableName = column.nativeEnumName ? undefined : this.name;
|
|
689
|
+
if (enumMode === 'ts-enum') {
|
|
690
|
+
// We will create a new enum name for this type and set it as the property type as well.
|
|
691
|
+
return namingStrategy.getEnumClassName(name, tableName, this.schema);
|
|
692
|
+
}
|
|
693
|
+
// With other enum strategies, we need to use the type name.
|
|
694
|
+
return namingStrategy.getEnumTypeName(name, tableName, this.schema);
|
|
678
695
|
}
|
|
679
696
|
return column.mappedType?.runtimeType ?? 'unknown';
|
|
680
697
|
}
|
|
@@ -697,6 +714,23 @@ export class DatabaseTable {
|
|
|
697
714
|
}
|
|
698
715
|
return '' + val;
|
|
699
716
|
}
|
|
717
|
+
processIndexExpression(indexName, expression, meta) {
|
|
718
|
+
if (expression instanceof Function) {
|
|
719
|
+
const table = {
|
|
720
|
+
name: this.name,
|
|
721
|
+
schema: this.schema,
|
|
722
|
+
toString() {
|
|
723
|
+
if (this.schema) {
|
|
724
|
+
return `${this.schema}.${this.name}`;
|
|
725
|
+
}
|
|
726
|
+
return this.name;
|
|
727
|
+
},
|
|
728
|
+
};
|
|
729
|
+
const exp = expression(table, meta.createColumnMappingObject(), indexName);
|
|
730
|
+
return exp instanceof RawQueryFragment ? this.platform.formatQuery(exp.sql, exp.params) : exp;
|
|
731
|
+
}
|
|
732
|
+
return expression;
|
|
733
|
+
}
|
|
700
734
|
addIndex(meta, index, type) {
|
|
701
735
|
const properties = Utils.unique(Utils.flatten(Utils.asArray(index.properties).map(prop => {
|
|
702
736
|
const parts = prop.split('.');
|
|
@@ -738,7 +772,7 @@ export class DatabaseTable {
|
|
|
738
772
|
primary: type === 'primary',
|
|
739
773
|
unique: type !== 'index',
|
|
740
774
|
type: index.type,
|
|
741
|
-
expression: index.expression,
|
|
775
|
+
expression: this.processIndexExpression(name, index.expression, meta),
|
|
742
776
|
options: index.options,
|
|
743
777
|
deferMode: index.deferMode,
|
|
744
778
|
});
|
|
@@ -269,7 +269,7 @@ export class SchemaComparator {
|
|
|
269
269
|
}
|
|
270
270
|
for (const toConstraint of Object.values(toForeignKeys)) {
|
|
271
271
|
tableDifferences.addedForeignKeys[toConstraint.constraintName] = toConstraint;
|
|
272
|
-
this.log(`FK constraint ${toConstraint.constraintName} added
|
|
272
|
+
this.log(`FK constraint ${toConstraint.constraintName} added to table ${tableDifferences.name}`, { constraint: toConstraint });
|
|
273
273
|
changes++;
|
|
274
274
|
}
|
|
275
275
|
return changes ? tableDifferences : false;
|
|
@@ -511,7 +511,7 @@ export class SchemaComparator {
|
|
|
511
511
|
return str
|
|
512
512
|
?.replace(/_\w+'(.*?)'/g, '$1')
|
|
513
513
|
.replace(/in\s*\((.*?)\)/ig, '= any (array[$1])')
|
|
514
|
-
.replace(/['"`()]|::\w+| +/g, '')
|
|
514
|
+
.replace(/['"`()\n[\]]|::\w+| +/g, '')
|
|
515
515
|
.replace(/anyarray\[(.*)]/ig, '$1')
|
|
516
516
|
.toLowerCase();
|
|
517
517
|
};
|
package/schema/SchemaHelper.d.ts
CHANGED
|
@@ -63,6 +63,8 @@ export declare abstract class SchemaHelper {
|
|
|
63
63
|
disableForeignKeys?: boolean;
|
|
64
64
|
createForeignKeyConstraints?: boolean;
|
|
65
65
|
ignoreSchema?: string[];
|
|
66
|
+
skipTables?: (string | RegExp)[];
|
|
67
|
+
skipColumns?: Dictionary<(string | RegExp)[]>;
|
|
66
68
|
managementDbName?: string;
|
|
67
69
|
};
|
|
68
70
|
protected processComment(comment: string): string;
|
package/schema/SchemaHelper.js
CHANGED
|
@@ -119,9 +119,8 @@ export class SchemaHelper {
|
|
|
119
119
|
}
|
|
120
120
|
}
|
|
121
121
|
Utils.removeDuplicates(changedNativeEnums).forEach(([enumName, itemsNew, itemsOld]) => {
|
|
122
|
-
// postgres allows only adding new items
|
|
123
|
-
|
|
124
|
-
const newItems = itemsNew.filter(val => !itemsOld.includes(val.toLowerCase()));
|
|
122
|
+
// postgres allows only adding new items
|
|
123
|
+
const newItems = itemsNew.filter(val => !itemsOld.includes(val));
|
|
125
124
|
if (enumName.includes('.')) {
|
|
126
125
|
const [enumSchemaName, rawEnumName] = enumName.split('.');
|
|
127
126
|
ret.push(...newItems.map(val => this.getAlterNativeEnumSQL(rawEnumName, enumSchemaName, val, itemsNew, itemsOld)));
|
|
@@ -264,7 +263,12 @@ export class SchemaHelper {
|
|
|
264
263
|
if (column.autoincrement && !column.generated && !compositePK && (!changedProperties || changedProperties.has('autoincrement') || changedProperties.has('type'))) {
|
|
265
264
|
Utils.runIfNotEmpty(() => col.push('primary key'), primaryKey && column.primary);
|
|
266
265
|
}
|
|
267
|
-
|
|
266
|
+
if (useDefault) {
|
|
267
|
+
// https://dev.mysql.com/doc/refman/9.0/en/data-type-defaults.html
|
|
268
|
+
const needsExpression = ['blob', 'text', 'json', 'point', 'linestring', 'polygon', 'multipoint', 'multilinestring', 'multipolygon', 'geometrycollection'].some(type => column.type.toLowerCase().startsWith(type));
|
|
269
|
+
const defaultSql = needsExpression && !column.default.startsWith('(') ? `(${column.default})` : column.default;
|
|
270
|
+
col.push(`default ${defaultSql}`);
|
|
271
|
+
}
|
|
268
272
|
Utils.runIfNotEmpty(() => col.push(column.extra), column.extra);
|
|
269
273
|
Utils.runIfNotEmpty(() => col.push(`comment ${this.platform.quoteValue(column.comment)}`), column.comment);
|
|
270
274
|
return col.join(' ');
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { AbstractSchemaGenerator, type ClearDatabaseOptions, type CreateSchemaOptions, type DropSchemaOptions, type EnsureDatabaseOptions, type ISchemaGenerator, type MikroORM, type Transaction, type UpdateSchemaOptions } from '@mikro-orm/core';
|
|
1
|
+
import { AbstractSchemaGenerator, type ClearDatabaseOptions, type CreateSchemaOptions, type Dictionary, type DropSchemaOptions, type EnsureDatabaseOptions, type EntityMetadata, type ISchemaGenerator, type MikroORM, type Transaction, type UpdateSchemaOptions } from '@mikro-orm/core';
|
|
2
2
|
import type { SchemaDifference } from '../typings.js';
|
|
3
3
|
import { DatabaseSchema } from './DatabaseSchema.js';
|
|
4
4
|
import type { AbstractSqlDriver } from '../AbstractSqlDriver.js';
|
|
@@ -8,24 +8,27 @@ export declare class SqlSchemaGenerator extends AbstractSchemaGenerator<Abstract
|
|
|
8
8
|
disableForeignKeys?: boolean;
|
|
9
9
|
createForeignKeyConstraints?: boolean;
|
|
10
10
|
ignoreSchema?: string[];
|
|
11
|
+
skipTables?: (string | RegExp)[];
|
|
12
|
+
skipColumns?: Dictionary<(string | RegExp)[]>;
|
|
11
13
|
managementDbName?: string;
|
|
12
14
|
};
|
|
13
15
|
protected lastEnsuredDatabase?: string;
|
|
14
16
|
static register(orm: MikroORM): void;
|
|
15
|
-
|
|
17
|
+
create(options?: CreateSchemaOptions): Promise<void>;
|
|
16
18
|
/**
|
|
17
19
|
* Returns true if the database was created.
|
|
18
20
|
*/
|
|
19
21
|
ensureDatabase(options?: EnsureDatabaseOptions): Promise<boolean>;
|
|
20
22
|
getTargetSchema(schema?: string): DatabaseSchema;
|
|
23
|
+
protected getOrderedMetadata(schema?: string): EntityMetadata[];
|
|
21
24
|
getCreateSchemaSQL(options?: CreateSchemaOptions): Promise<string>;
|
|
22
|
-
|
|
25
|
+
drop(options?: DropSchemaOptions): Promise<void>;
|
|
23
26
|
createNamespace(name: string): Promise<void>;
|
|
24
27
|
dropNamespace(name: string): Promise<void>;
|
|
25
|
-
|
|
28
|
+
clear(options?: ClearDatabaseOptions): Promise<void>;
|
|
26
29
|
getDropSchemaSQL(options?: Omit<DropSchemaOptions, 'dropDb'>): Promise<string>;
|
|
27
30
|
private getSchemaName;
|
|
28
|
-
|
|
31
|
+
update(options?: UpdateSchemaOptions<DatabaseSchema>): Promise<void>;
|
|
29
32
|
getUpdateSchemaSQL(options?: UpdateSchemaOptions<DatabaseSchema>): Promise<string>;
|
|
30
33
|
getUpdateSchemaMigrationSQL(options?: UpdateSchemaOptions<DatabaseSchema>): Promise<{
|
|
31
34
|
up: string;
|
|
@@ -45,7 +48,9 @@ export declare class SqlSchemaGenerator extends AbstractSchemaGenerator<Abstract
|
|
|
45
48
|
/**
|
|
46
49
|
* creates new database and connects to it
|
|
47
50
|
*/
|
|
48
|
-
createDatabase(name?: string
|
|
51
|
+
createDatabase(name?: string, options?: {
|
|
52
|
+
skipOnConnect?: boolean;
|
|
53
|
+
}): Promise<void>;
|
|
49
54
|
dropDatabase(name?: string): Promise<void>;
|
|
50
55
|
execute(sql: string, options?: {
|
|
51
56
|
wrap?: boolean;
|
|
@@ -54,5 +59,7 @@ export declare class SqlSchemaGenerator extends AbstractSchemaGenerator<Abstract
|
|
|
54
59
|
dropTableIfExists(name: string, schema?: string): Promise<void>;
|
|
55
60
|
private wrapSchema;
|
|
56
61
|
private append;
|
|
62
|
+
private matchName;
|
|
63
|
+
private isTableSkipped;
|
|
57
64
|
}
|
|
58
65
|
export { SqlSchemaGenerator as SchemaGenerator };
|
|
@@ -8,7 +8,7 @@ export class SqlSchemaGenerator extends AbstractSchemaGenerator {
|
|
|
8
8
|
static register(orm) {
|
|
9
9
|
orm.config.registerExtension('@mikro-orm/schema-generator', () => new SqlSchemaGenerator(orm.em));
|
|
10
10
|
}
|
|
11
|
-
async
|
|
11
|
+
async create(options) {
|
|
12
12
|
await this.ensureDatabase();
|
|
13
13
|
const sql = await this.getCreateSchemaSQL(options);
|
|
14
14
|
await this.execute(sql);
|
|
@@ -17,6 +17,7 @@ export class SqlSchemaGenerator extends AbstractSchemaGenerator {
|
|
|
17
17
|
* Returns true if the database was created.
|
|
18
18
|
*/
|
|
19
19
|
async ensureDatabase(options) {
|
|
20
|
+
await this.connection.ensureConnection();
|
|
20
21
|
const dbName = this.config.get('dbName');
|
|
21
22
|
if (this.lastEnsuredDatabase === dbName && !options?.forceCheck) {
|
|
22
23
|
return true;
|
|
@@ -27,18 +28,17 @@ export class SqlSchemaGenerator extends AbstractSchemaGenerator {
|
|
|
27
28
|
const managementDbName = this.helper.getManagementDbName();
|
|
28
29
|
if (managementDbName) {
|
|
29
30
|
this.config.set('dbName', managementDbName);
|
|
30
|
-
await this.driver.reconnect();
|
|
31
|
-
await this.createDatabase(dbName);
|
|
32
|
-
this.config.set('dbName', dbName);
|
|
33
|
-
await this.driver.reconnect();
|
|
31
|
+
await this.driver.reconnect({ skipOnConnect: true });
|
|
32
|
+
await this.createDatabase(dbName, { skipOnConnect: true });
|
|
34
33
|
}
|
|
35
34
|
if (options?.create) {
|
|
36
|
-
await this.
|
|
35
|
+
await this.create(options);
|
|
37
36
|
}
|
|
38
37
|
return true;
|
|
39
38
|
}
|
|
39
|
+
/* v8 ignore next 3 */
|
|
40
40
|
if (options?.clear) {
|
|
41
|
-
await this.
|
|
41
|
+
await this.clear({ ...options, clearIdentityMap: false });
|
|
42
42
|
}
|
|
43
43
|
return false;
|
|
44
44
|
}
|
|
@@ -47,6 +47,15 @@ export class SqlSchemaGenerator extends AbstractSchemaGenerator {
|
|
|
47
47
|
const schemaName = schema ?? this.config.get('schema') ?? this.platform.getDefaultSchemaName();
|
|
48
48
|
return DatabaseSchema.fromMetadata(metadata, this.platform, this.config, schemaName);
|
|
49
49
|
}
|
|
50
|
+
getOrderedMetadata(schema) {
|
|
51
|
+
const metadata = super.getOrderedMetadata(schema);
|
|
52
|
+
// Filter out skipped tables
|
|
53
|
+
return metadata.filter(meta => {
|
|
54
|
+
const tableName = meta.tableName;
|
|
55
|
+
const tableSchema = meta.schema ?? schema ?? this.config.get('schema');
|
|
56
|
+
return !this.isTableSkipped(tableName, tableSchema);
|
|
57
|
+
});
|
|
58
|
+
}
|
|
50
59
|
async getCreateSchemaSQL(options = {}) {
|
|
51
60
|
const toSchema = this.getTargetSchema(options.schema);
|
|
52
61
|
const ret = [];
|
|
@@ -80,7 +89,7 @@ export class SqlSchemaGenerator extends AbstractSchemaGenerator {
|
|
|
80
89
|
}
|
|
81
90
|
return this.wrapSchema(ret, options);
|
|
82
91
|
}
|
|
83
|
-
async
|
|
92
|
+
async drop(options = {}) {
|
|
84
93
|
if (options.dropDb) {
|
|
85
94
|
const name = this.config.get('dbName');
|
|
86
95
|
return this.dropDatabase(name);
|
|
@@ -96,11 +105,11 @@ export class SqlSchemaGenerator extends AbstractSchemaGenerator {
|
|
|
96
105
|
const sql = this.helper.getDropNamespaceSQL(name);
|
|
97
106
|
await this.execute(sql);
|
|
98
107
|
}
|
|
99
|
-
async
|
|
108
|
+
async clear(options) {
|
|
100
109
|
// truncate by default, so no value is considered as true
|
|
101
110
|
/* v8 ignore next 3 */
|
|
102
111
|
if (options?.truncate === false) {
|
|
103
|
-
return super.
|
|
112
|
+
return super.clear(options);
|
|
104
113
|
}
|
|
105
114
|
await this.execute(this.helper.disableForeignKeysSQL());
|
|
106
115
|
const schema = options?.schema ?? this.config.get('schema', this.platform.getDefaultSchemaName());
|
|
@@ -111,7 +120,9 @@ export class SqlSchemaGenerator extends AbstractSchemaGenerator {
|
|
|
111
120
|
.execute();
|
|
112
121
|
}
|
|
113
122
|
await this.execute(this.helper.enableForeignKeysSQL());
|
|
114
|
-
|
|
123
|
+
if (options?.clearIdentityMap ?? true) {
|
|
124
|
+
this.clearIdentityMap();
|
|
125
|
+
}
|
|
115
126
|
}
|
|
116
127
|
async getDropSchemaSQL(options = {}) {
|
|
117
128
|
await this.ensureDatabase();
|
|
@@ -156,7 +167,7 @@ export class SqlSchemaGenerator extends AbstractSchemaGenerator {
|
|
|
156
167
|
}
|
|
157
168
|
return resolvedName;
|
|
158
169
|
}
|
|
159
|
-
async
|
|
170
|
+
async update(options = {}) {
|
|
160
171
|
const sql = await this.getUpdateSchemaSQL(options);
|
|
161
172
|
await this.execute(sql);
|
|
162
173
|
}
|
|
@@ -280,15 +291,14 @@ export class SqlSchemaGenerator extends AbstractSchemaGenerator {
|
|
|
280
291
|
/**
|
|
281
292
|
* creates new database and connects to it
|
|
282
293
|
*/
|
|
283
|
-
async createDatabase(name) {
|
|
294
|
+
async createDatabase(name, options) {
|
|
284
295
|
name ??= this.config.get('dbName');
|
|
285
296
|
const sql = this.helper.getCreateDatabaseSQL('' + this.platform.quoteIdentifier(name));
|
|
286
297
|
if (sql) {
|
|
287
|
-
// console.log(sql);
|
|
288
298
|
await this.execute(sql);
|
|
289
299
|
}
|
|
290
300
|
this.config.set('dbName', name);
|
|
291
|
-
await this.driver.reconnect();
|
|
301
|
+
await this.driver.reconnect(options);
|
|
292
302
|
}
|
|
293
303
|
async dropDatabase(name) {
|
|
294
304
|
name ??= this.config.get('dbName');
|
|
@@ -318,12 +328,10 @@ export class SqlSchemaGenerator extends AbstractSchemaGenerator {
|
|
|
318
328
|
if (this.platform.supportsMultipleStatements()) {
|
|
319
329
|
for (const group of groups) {
|
|
320
330
|
const query = group.join('\n');
|
|
321
|
-
// console.log(query);
|
|
322
331
|
await this.driver.execute(query);
|
|
323
332
|
}
|
|
324
333
|
return;
|
|
325
334
|
}
|
|
326
|
-
// console.log(groups);
|
|
327
335
|
await Utils.runSerial(groups.flat(), line => this.driver.execute(line));
|
|
328
336
|
}
|
|
329
337
|
async dropTableIfExists(name, schema) {
|
|
@@ -349,6 +357,19 @@ export class SqlSchemaGenerator extends AbstractSchemaGenerator {
|
|
|
349
357
|
append(array, sql, pad) {
|
|
350
358
|
return this.helper.append(array, sql, pad);
|
|
351
359
|
}
|
|
360
|
+
matchName(name, nameToMatch) {
|
|
361
|
+
return typeof nameToMatch === 'string'
|
|
362
|
+
? name.toLocaleLowerCase() === nameToMatch.toLocaleLowerCase()
|
|
363
|
+
: nameToMatch.test(name);
|
|
364
|
+
}
|
|
365
|
+
isTableSkipped(tableName, schemaName) {
|
|
366
|
+
const skipTables = this.options.skipTables;
|
|
367
|
+
if (!skipTables || skipTables.length === 0) {
|
|
368
|
+
return false;
|
|
369
|
+
}
|
|
370
|
+
const fullTableName = schemaName ? `${schemaName}.${tableName}` : tableName;
|
|
371
|
+
return skipTables.some(pattern => this.matchName(tableName, pattern) || this.matchName(fullTableName, pattern));
|
|
372
|
+
}
|
|
352
373
|
}
|
|
353
374
|
// for back compatibility
|
|
354
375
|
export { SqlSchemaGenerator as SchemaGenerator };
|
package/typings.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { Generated, Kysely } from 'kysely';
|
|
2
|
+
import type { DeferMode, CheckCallback, Dictionary, EntityProperty, GroupOperator, RawQueryFragment, QBFilterQuery, QueryOrderMap, Type, QueryFlag, AnyEntity, EntityName, EntitySchemaWithMeta, Primary, PrimaryProperty, Opt } from '@mikro-orm/core';
|
|
2
3
|
import type { JoinType, QueryType } from './query/enums.js';
|
|
3
4
|
import type { DatabaseSchema } from './schema/DatabaseSchema.js';
|
|
4
5
|
import type { DatabaseTable } from './schema/DatabaseTable.js';
|
|
@@ -27,6 +28,7 @@ export interface JoinOptions {
|
|
|
27
28
|
cond_?: Dictionary;
|
|
28
29
|
subquery?: string;
|
|
29
30
|
nested?: Set<JoinOptions>;
|
|
31
|
+
parent?: JoinOptions;
|
|
30
32
|
}
|
|
31
33
|
export interface Column {
|
|
32
34
|
name: string;
|
|
@@ -74,7 +76,7 @@ export interface IndexDef {
|
|
|
74
76
|
storageEngineIndexType?: 'hash' | 'btree';
|
|
75
77
|
predicate?: string;
|
|
76
78
|
}>;
|
|
77
|
-
deferMode?: DeferMode
|
|
79
|
+
deferMode?: DeferMode | `${DeferMode}`;
|
|
78
80
|
}
|
|
79
81
|
export interface CheckDef<T = unknown> {
|
|
80
82
|
name: string;
|
|
@@ -170,11 +172,14 @@ export interface ICriteriaNodeProcessOptions {
|
|
|
170
172
|
matchPopulateJoins?: boolean;
|
|
171
173
|
ignoreBranching?: boolean;
|
|
172
174
|
preferNoBranch?: boolean;
|
|
175
|
+
type?: 'orderBy';
|
|
176
|
+
filter?: boolean;
|
|
173
177
|
}
|
|
174
178
|
export interface ICriteriaNode<T extends object> {
|
|
175
179
|
readonly entityName: string;
|
|
176
180
|
readonly parent?: ICriteriaNode<T> | undefined;
|
|
177
181
|
readonly key?: string | undefined;
|
|
182
|
+
readonly strict?: boolean;
|
|
178
183
|
payload: any;
|
|
179
184
|
prop?: EntityProperty;
|
|
180
185
|
index?: number;
|
|
@@ -182,8 +187,85 @@ export interface ICriteriaNode<T extends object> {
|
|
|
182
187
|
shouldInline(payload: any): boolean;
|
|
183
188
|
willAutoJoin(qb: IQueryBuilder<T>, alias?: string, options?: ICriteriaNodeProcessOptions): boolean;
|
|
184
189
|
shouldRename(payload: any): boolean;
|
|
185
|
-
renameFieldToPK<T>(qb: IQueryBuilder<T
|
|
190
|
+
renameFieldToPK<T>(qb: IQueryBuilder<T>, ownerAlias?: string): string;
|
|
186
191
|
getPath(addIndex?: boolean): string;
|
|
187
192
|
getPivotPath(path: string): string;
|
|
188
193
|
}
|
|
194
|
+
export type MaybeReturnType<T> = T extends (...args: any[]) => infer R ? R : T;
|
|
195
|
+
export type InferEntityProperties<Schema> = Schema extends EntitySchemaWithMeta<any, any, any, any, infer Properties> ? Properties : never;
|
|
196
|
+
export type InferKyselyDB<TEntities extends {
|
|
197
|
+
name: string;
|
|
198
|
+
}, TOptions = {}> = MapValueAsTable<MapByName<TEntities>, TOptions>;
|
|
199
|
+
export type InferDBFromKysely<TKysely extends Kysely<any>> = TKysely extends Kysely<infer TDB> ? TDB : never;
|
|
200
|
+
type PreferStringLiteral<TCandidate, TFallback> = [
|
|
201
|
+
TCandidate
|
|
202
|
+
] extends [never] ? TFallback : string extends TCandidate ? TFallback : TCandidate extends string ? TCandidate : TFallback;
|
|
203
|
+
export type MapByName<T extends {
|
|
204
|
+
name: string;
|
|
205
|
+
tableName?: string;
|
|
206
|
+
}> = {
|
|
207
|
+
[P in T as PreferStringLiteral<NonNullable<P['tableName']>, P['name']>]: P;
|
|
208
|
+
};
|
|
209
|
+
export type MapValueAsTable<TMap extends Record<string, any>, TOptions = {}> = {
|
|
210
|
+
[K in keyof TMap as TransformName<K, 'underscore'>]: InferKyselyTable<TMap[K], 'underscore'>;
|
|
211
|
+
};
|
|
212
|
+
export type InferKyselyTable<TSchema extends EntitySchemaWithMeta, TNamingStrategy extends 'underscore' | 'entity' = 'underscore', TProcessOnCreate extends boolean = false> = ExcludeNever<{
|
|
213
|
+
-readonly [K in keyof InferEntityProperties<TSchema> as TransformColumnName<K, TNamingStrategy, MaybeReturnType<InferEntityProperties<TSchema>[K]>>]: InferColumnValue<MaybeReturnType<InferEntityProperties<TSchema>[K]>, TProcessOnCreate>;
|
|
214
|
+
}>;
|
|
215
|
+
type TransformName<TName, TNamingStrategy extends 'underscore' | 'entity'> = TNamingStrategy extends 'underscore' ? TName extends string ? SnakeCase<TName> : TName : TName;
|
|
216
|
+
type TransformColumnName<TName, TNamingStrategy extends 'underscore' | 'entity', TBuilder> = TNamingStrategy extends 'entity' ? TName : TBuilder extends {
|
|
217
|
+
'~options': {
|
|
218
|
+
fieldName: string;
|
|
219
|
+
};
|
|
220
|
+
} ? TBuilder['~options']['fieldName'] : TName extends string ? MaybeJoinColumnName<SnakeCase<TName>, TBuilder> : never;
|
|
221
|
+
type MaybeJoinColumnName<TName extends string, TBuilder> = TBuilder extends {
|
|
222
|
+
'~type'?: {
|
|
223
|
+
value: infer Value;
|
|
224
|
+
};
|
|
225
|
+
'~options': {
|
|
226
|
+
kind: 'm:1';
|
|
227
|
+
};
|
|
228
|
+
} ? PrimaryProperty<Value> extends string ? `${TName}_${SnakeCase<PrimaryProperty<Value>>}` : never : TBuilder extends {
|
|
229
|
+
'~type'?: {
|
|
230
|
+
value: infer Value;
|
|
231
|
+
};
|
|
232
|
+
'~options': {
|
|
233
|
+
kind: '1:1';
|
|
234
|
+
owner: true;
|
|
235
|
+
};
|
|
236
|
+
} ? PrimaryProperty<Value> extends string ? `${TName}_${SnakeCase<PrimaryProperty<Value>>}` : never : TName;
|
|
237
|
+
export type SnakeCase<TName extends string> = TName extends `${infer P1}${infer P2}` ? P2 extends Uncapitalize<P2> ? `${Uncapitalize<P1>}${SnakeCase<P2>}` : `${Uncapitalize<P1>}_${SnakeCase<Uncapitalize<P2>>}` : TName;
|
|
238
|
+
type InferColumnValue<TBuilder, TProcessOnCreate extends boolean> = TBuilder extends {
|
|
239
|
+
'~type'?: {
|
|
240
|
+
value: infer Value;
|
|
241
|
+
};
|
|
242
|
+
'~options': infer TOptions;
|
|
243
|
+
} ? MaybeNever<MaybeGenerated<MaybeJoinKey<Value, TOptions>, TOptions, TProcessOnCreate>, TOptions> : never;
|
|
244
|
+
type MaybeGenerated<TValue, TOptions, TProcessOnCreate extends boolean> = TOptions extends {
|
|
245
|
+
nullable: true;
|
|
246
|
+
} ? (TValue | null) : TOptions extends {
|
|
247
|
+
autoincrement: true;
|
|
248
|
+
} ? Generated<TValue> : TOptions extends {
|
|
249
|
+
default: true;
|
|
250
|
+
} ? Generated<TValue> : TOptions extends {
|
|
251
|
+
defaultRaw: true;
|
|
252
|
+
} ? Generated<TValue> : TProcessOnCreate extends false ? TValue : TOptions extends {
|
|
253
|
+
onCreate: Function;
|
|
254
|
+
} ? Generated<TValue> : TValue;
|
|
255
|
+
type MaybeJoinKey<TValue, TOptions> = TOptions extends {
|
|
256
|
+
kind: 'm:1';
|
|
257
|
+
} ? UnwrapOpt<Primary<TValue>> : TOptions extends {
|
|
258
|
+
kind: '1:1';
|
|
259
|
+
} ? TOptions extends {
|
|
260
|
+
owner: true;
|
|
261
|
+
} ? UnwrapOpt<Primary<TValue>> : never : TValue;
|
|
262
|
+
type UnwrapOpt<TValue> = TValue extends Opt<infer OriginalValue> ? OriginalValue : TValue;
|
|
263
|
+
type MaybeNever<TValue, TOptions> = TOptions extends {
|
|
264
|
+
persist: true;
|
|
265
|
+
} ? never : TOptions extends {
|
|
266
|
+
kind: 'm:n';
|
|
267
|
+
} ? never : TValue;
|
|
268
|
+
type ExcludeNever<TMap extends Record<string, any>> = {
|
|
269
|
+
[K in keyof TMap as TMap[K] extends never ? never : K]: TMap[K];
|
|
270
|
+
};
|
|
189
271
|
export {};
|