@mikro-orm/knex 6.2.10-dev.5 → 6.2.10-dev.50
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 -1
- package/dialects/mysql/MySqlSchemaHelper.js +1 -1
- package/dialects/sqlite/BaseSqliteSchemaHelper.d.ts +2 -1
- package/dialects/sqlite/BaseSqliteSchemaHelper.js +17 -0
- package/package.json +2 -2
- package/query/ObjectCriteriaNode.js +2 -2
- package/query/QueryBuilder.d.ts +2 -2
- package/query/QueryBuilder.js +11 -7
- package/query/QueryBuilderHelper.d.ts +2 -2
- package/query/QueryBuilderHelper.js +14 -3
- package/schema/DatabaseTable.js +4 -3
- package/schema/SchemaComparator.js +4 -1
- package/schema/SchemaHelper.d.ts +17 -1
- package/schema/SchemaHelper.js +133 -2
- package/schema/SqlSchemaGenerator.d.ts +0 -7
- package/schema/SqlSchemaGenerator.js +35 -150
- package/typings.d.ts +2 -0
package/AbstractSqlDriver.js
CHANGED
|
@@ -1099,9 +1099,12 @@ class AbstractSqlDriver extends core_1.DatabaseDriver {
|
|
|
1099
1099
|
if (!prop) {
|
|
1100
1100
|
throw new Error(`Trying to order by not existing property ${meta.className}.${propName}`);
|
|
1101
1101
|
}
|
|
1102
|
+
let path = parentPath;
|
|
1102
1103
|
const meta2 = this.metadata.find(prop.type);
|
|
1103
1104
|
const childOrder = orderHint[prop.name];
|
|
1104
|
-
|
|
1105
|
+
if (![core_1.ReferenceKind.MANY_TO_ONE, core_1.ReferenceKind.ONE_TO_ONE].includes(prop.kind) || !prop.owner || core_1.Utils.isPlainObject(childOrder)) {
|
|
1106
|
+
path += `.${propName}`;
|
|
1107
|
+
}
|
|
1105
1108
|
if (prop.kind === core_1.ReferenceKind.MANY_TO_MANY && typeof childOrder !== 'object') {
|
|
1106
1109
|
path += '[pivot]';
|
|
1107
1110
|
}
|
|
@@ -78,7 +78,7 @@ class MySqlSchemaHelper extends SchemaHelper_1.SchemaHelper {
|
|
|
78
78
|
nullif(table_schema, schema()) as schema_name,
|
|
79
79
|
column_name as column_name,
|
|
80
80
|
column_default as column_default,
|
|
81
|
-
column_comment as column_comment,
|
|
81
|
+
nullif(column_comment, '') as column_comment,
|
|
82
82
|
is_nullable as is_nullable,
|
|
83
83
|
data_type as data_type,
|
|
84
84
|
column_type as column_type,
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { Connection, Dictionary } from '@mikro-orm/core';
|
|
2
2
|
import type { AbstractSqlConnection } from '../../AbstractSqlConnection';
|
|
3
3
|
import { SchemaHelper } from '../../schema/SchemaHelper';
|
|
4
|
-
import type { CheckDef, Column, IndexDef } from '../../typings';
|
|
4
|
+
import type { CheckDef, Column, IndexDef, TableDifference } from '../../typings';
|
|
5
5
|
export declare abstract class BaseSqliteSchemaHelper extends SchemaHelper {
|
|
6
6
|
disableForeignKeysSQL(): string;
|
|
7
7
|
enableForeignKeysSQL(): string;
|
|
@@ -24,4 +24,5 @@ export declare abstract class BaseSqliteSchemaHelper extends SchemaHelper {
|
|
|
24
24
|
* Implicit indexes will be ignored when diffing
|
|
25
25
|
*/
|
|
26
26
|
isImplicitIndex(name: string): boolean;
|
|
27
|
+
getAlterTable(changedTable: TableDifference, wrap?: boolean): Promise<string>;
|
|
27
28
|
}
|
|
@@ -168,5 +168,22 @@ class BaseSqliteSchemaHelper extends SchemaHelper_1.SchemaHelper {
|
|
|
168
168
|
// Ignore indexes with reserved names, e.g. autoindexes
|
|
169
169
|
return name.startsWith('sqlite_');
|
|
170
170
|
}
|
|
171
|
+
async getAlterTable(changedTable, wrap) {
|
|
172
|
+
wrap ??= this.options.disableForeignKeys;
|
|
173
|
+
const tempName = `${(changedTable.toTable.name)}__temp_alter`;
|
|
174
|
+
const quotedName = this.platform.quoteIdentifier(changedTable.toTable.name);
|
|
175
|
+
const quotedTempName = this.platform.quoteIdentifier(tempName);
|
|
176
|
+
const createSql = await this.dump(this.createTable(changedTable.toTable), '');
|
|
177
|
+
const [first, ...rest] = createSql.split('\n');
|
|
178
|
+
return [
|
|
179
|
+
'pragma foreign_keys = off;',
|
|
180
|
+
first.replace(`create table ${quotedName}`, `create table ${quotedTempName}`),
|
|
181
|
+
`insert into ${quotedTempName} select * from ${quotedName};`,
|
|
182
|
+
`drop table ${quotedName};`,
|
|
183
|
+
`alter table ${quotedTempName} rename to ${quotedName};`,
|
|
184
|
+
...rest,
|
|
185
|
+
'pragma foreign_keys = on;',
|
|
186
|
+
].join('\n');
|
|
187
|
+
}
|
|
171
188
|
}
|
|
172
189
|
exports.BaseSqliteSchemaHelper = BaseSqliteSchemaHelper;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mikro-orm/knex",
|
|
3
|
-
"version": "6.2.10-dev.
|
|
3
|
+
"version": "6.2.10-dev.50",
|
|
4
4
|
"description": "TypeScript ORM for Node.js based on Data Mapper, Unit of Work and Identity Map patterns. Supports MongoDB, MySQL, PostgreSQL and SQLite databases as well as usage with vanilla JavaScript.",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"module": "index.mjs",
|
|
@@ -66,7 +66,7 @@
|
|
|
66
66
|
"@mikro-orm/core": "^6.2.9"
|
|
67
67
|
},
|
|
68
68
|
"peerDependencies": {
|
|
69
|
-
"@mikro-orm/core": "6.2.10-dev.
|
|
69
|
+
"@mikro-orm/core": "6.2.10-dev.50",
|
|
70
70
|
"better-sqlite3": "*",
|
|
71
71
|
"libsql": "*",
|
|
72
72
|
"mariadb": "*"
|
|
@@ -70,7 +70,8 @@ class ObjectCriteriaNode extends CriteriaNode_1.CriteriaNode {
|
|
|
70
70
|
const primaryKey = this.key && this.metadata.find(this.entityName).primaryKeys.includes(field);
|
|
71
71
|
if (childNode.shouldInline(payload)) {
|
|
72
72
|
const childAlias = qb.getAliasForJoinPath(childNode.getPath(), options);
|
|
73
|
-
|
|
73
|
+
const a = qb.helper.isTableNameAliasRequired(qb.type) ? alias : undefined;
|
|
74
|
+
this.inlineChildPayload(o, payload, field, a, childAlias);
|
|
74
75
|
}
|
|
75
76
|
else if (childNode.shouldRename(payload)) {
|
|
76
77
|
o[childNode.renameFieldToPK(qb)] = payload;
|
|
@@ -149,7 +150,6 @@ class ObjectCriteriaNode extends CriteriaNode_1.CriteriaNode {
|
|
|
149
150
|
o[k] = payload[k];
|
|
150
151
|
}
|
|
151
152
|
else {
|
|
152
|
-
o[`${childAlias}.${k}`] = payload[k];
|
|
153
153
|
o[this.aliased(k, childAlias)] = payload[k];
|
|
154
154
|
}
|
|
155
155
|
}
|
package/query/QueryBuilder.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/// <reference types="node" />
|
|
2
2
|
import { inspect } from 'util';
|
|
3
3
|
import type { Knex } from 'knex';
|
|
4
|
-
import { type AnyEntity, type ConnectionType, type Dictionary, type EntityData, type EntityKey, type EntityMetadata, type EntityName, type EntityProperty, type FlushMode, type GroupOperator, type Loaded, LockMode, type LoggingOptions, type MetadataStorage, type ObjectQuery, PopulateHint, type PopulateOptions, type QBFilterQuery, type QBQueryOrderMap, QueryFlag, type QueryOrderMap, type QueryResult, type RequiredEntityData, type ExpandProperty } from '@mikro-orm/core';
|
|
4
|
+
import { type AnyEntity, type ConnectionType, type Dictionary, type EntityData, type EntityKey, type EntityMetadata, type EntityName, type EntityProperty, type FlushMode, type GroupOperator, type Loaded, LockMode, type LoggingOptions, type MetadataStorage, type ObjectQuery, PopulateHint, type PopulateOptions, type QBFilterQuery, type QBQueryOrderMap, QueryFlag, type QueryOrderMap, type QueryResult, RawQueryFragment, type RequiredEntityData, type ExpandProperty } from '@mikro-orm/core';
|
|
5
5
|
import { JoinType, QueryType } from './enums';
|
|
6
6
|
import type { AbstractSqlDriver } from '../AbstractSqlDriver';
|
|
7
7
|
import { type Alias, QueryBuilderHelper } from './QueryBuilderHelper';
|
|
@@ -88,7 +88,7 @@ export declare class QueryBuilder<Entity extends object = AnyEntity, RootAlias e
|
|
|
88
88
|
protected _having: Dictionary;
|
|
89
89
|
protected _returning?: Field<Entity>[];
|
|
90
90
|
protected _onConflict?: {
|
|
91
|
-
fields: string[];
|
|
91
|
+
fields: string[] | RawQueryFragment;
|
|
92
92
|
ignore?: boolean;
|
|
93
93
|
merge?: EntityData<Entity> | Field<Entity>[];
|
|
94
94
|
where?: QBFilterQuery<Entity>;
|
package/query/QueryBuilder.js
CHANGED
|
@@ -348,11 +348,13 @@ class QueryBuilder {
|
|
|
348
348
|
this.ensureNotFinalized();
|
|
349
349
|
this._onConflict ??= [];
|
|
350
350
|
this._onConflict.push({
|
|
351
|
-
fields: core_1.Utils.
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
351
|
+
fields: core_1.Utils.isRawSql(fields)
|
|
352
|
+
? fields
|
|
353
|
+
: core_1.Utils.asArray(fields).flatMap(f => {
|
|
354
|
+
const key = f.toString();
|
|
355
|
+
/* istanbul ignore next */
|
|
356
|
+
return meta.properties[key]?.fieldNames ?? [key];
|
|
357
|
+
}),
|
|
356
358
|
});
|
|
357
359
|
return this;
|
|
358
360
|
}
|
|
@@ -1222,7 +1224,7 @@ class QueryBuilder {
|
|
|
1222
1224
|
const prop = this.helper.getProperty(f, a);
|
|
1223
1225
|
const type = this.platform.castColumn(prop);
|
|
1224
1226
|
const fieldName = this.helper.mapper(field, this.type, undefined, null);
|
|
1225
|
-
if (!prop?.persist && !prop?.formula && !pks.includes(fieldName)) {
|
|
1227
|
+
if (!prop?.persist && !prop?.formula && !prop?.hasConvertToJSValueSQL && !pks.includes(fieldName)) {
|
|
1226
1228
|
addToSelect.push(fieldName);
|
|
1227
1229
|
}
|
|
1228
1230
|
const key = (0, core_1.raw)(`min(${this.knex.ref(fieldName)}${type})`);
|
|
@@ -1245,8 +1247,10 @@ class QueryBuilder {
|
|
|
1245
1247
|
}
|
|
1246
1248
|
return false;
|
|
1247
1249
|
});
|
|
1250
|
+
/* istanbul ignore next */
|
|
1248
1251
|
if (field instanceof core_1.RawQueryFragment) {
|
|
1249
|
-
|
|
1252
|
+
const sql = this.platform.formatQuery(field.sql, field.params);
|
|
1253
|
+
knexQuery.select(this.knex.raw(sql));
|
|
1250
1254
|
}
|
|
1251
1255
|
else if (field) {
|
|
1252
1256
|
knexQuery.select(field);
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { Knex } from 'knex';
|
|
2
|
-
import { type Dictionary, type EntityData, type EntityKey, type EntityMetadata, type EntityProperty, type FlatQueryOrderMap, LockMode, type QBFilterQuery } from '@mikro-orm/core';
|
|
2
|
+
import { type Dictionary, type EntityData, type EntityKey, type EntityMetadata, type EntityProperty, type FlatQueryOrderMap, LockMode, type QBFilterQuery, RawQueryFragment } from '@mikro-orm/core';
|
|
3
3
|
import { JoinType, QueryType } from './enums';
|
|
4
4
|
import type { Field, JoinOptions } from '../typings';
|
|
5
5
|
import type { AbstractSqlDriver } from '../AbstractSqlDriver';
|
|
@@ -34,7 +34,7 @@ export declare class QueryBuilderHelper {
|
|
|
34
34
|
isSimpleRegExp(re: any): re is RegExp;
|
|
35
35
|
getRegExpParam(re: RegExp): string;
|
|
36
36
|
appendOnConflictClause<T>(type: QueryType, onConflict: {
|
|
37
|
-
fields: string[];
|
|
37
|
+
fields: string[] | RawQueryFragment;
|
|
38
38
|
ignore?: boolean;
|
|
39
39
|
merge?: EntityData<T> | Field<T>[];
|
|
40
40
|
where?: QBFilterQuery<T>;
|
|
@@ -67,7 +67,8 @@ class QueryBuilderHelper {
|
|
|
67
67
|
}
|
|
68
68
|
const rawField = core_1.RawQueryFragment.getKnownFragment(field);
|
|
69
69
|
if (rawField) {
|
|
70
|
-
|
|
70
|
+
// sometimes knex is confusing the binding positions, we need to interpolate early
|
|
71
|
+
return this.knex.raw(this.platform.formatQuery(rawField.sql, rawField.params));
|
|
71
72
|
}
|
|
72
73
|
const [a, f] = this.splitField(field);
|
|
73
74
|
const prop = this.getProperty(f, a);
|
|
@@ -194,7 +195,8 @@ class QueryBuilderHelper {
|
|
|
194
195
|
join.primaryKeys.forEach((primaryKey, idx) => {
|
|
195
196
|
const right = `${join.alias}.${join.joinColumns[idx]}`;
|
|
196
197
|
if (join.prop.formula) {
|
|
197
|
-
const
|
|
198
|
+
const alias = this.platform.quoteIdentifier(join.ownerAlias);
|
|
199
|
+
const left = join.prop.formula(alias);
|
|
198
200
|
conditions.push(`${left} = ${this.knex.ref(right)}`);
|
|
199
201
|
return;
|
|
200
202
|
}
|
|
@@ -352,7 +354,16 @@ class QueryBuilderHelper {
|
|
|
352
354
|
}
|
|
353
355
|
appendOnConflictClause(type, onConflict, qb) {
|
|
354
356
|
onConflict.forEach(item => {
|
|
355
|
-
|
|
357
|
+
let sub;
|
|
358
|
+
if (core_1.Utils.isRawSql(item.fields)) {
|
|
359
|
+
sub = qb.onConflict(this.knex.raw(item.fields.sql, item.fields.params));
|
|
360
|
+
}
|
|
361
|
+
else if (item.fields.length > 0) {
|
|
362
|
+
sub = qb.onConflict(item.fields);
|
|
363
|
+
}
|
|
364
|
+
else {
|
|
365
|
+
sub = qb.onConflict();
|
|
366
|
+
}
|
|
356
367
|
core_1.Utils.runIfNotEmpty(() => sub.ignore(), item.ignore);
|
|
357
368
|
core_1.Utils.runIfNotEmpty(() => {
|
|
358
369
|
let mergeParam = item.merge;
|
package/schema/DatabaseTable.js
CHANGED
|
@@ -171,7 +171,7 @@ class DatabaseTable {
|
|
|
171
171
|
getEntityDeclaration(namingStrategy, schemaHelper, scalarPropertiesForRelations) {
|
|
172
172
|
const { fksOnColumnProps, fksOnStandaloneProps, columnFks, fkIndexes, nullableForeignKeys, skippedColumnNames, } = this.foreignKeysToProps(namingStrategy, scalarPropertiesForRelations);
|
|
173
173
|
const name = namingStrategy.getEntityName(this.name, this.schema);
|
|
174
|
-
const schema = new core_1.EntitySchema({ name, collection: this.name, schema: this.schema });
|
|
174
|
+
const schema = new core_1.EntitySchema({ name, collection: this.name, schema: this.schema, comment: this.comment });
|
|
175
175
|
const compositeFkIndexes = {};
|
|
176
176
|
const compositeFkUniques = {};
|
|
177
177
|
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.
|
|
@@ -505,6 +505,7 @@ class DatabaseTable {
|
|
|
505
505
|
columnOptions.length = column.length;
|
|
506
506
|
columnOptions.precision = column.precision;
|
|
507
507
|
columnOptions.scale = column.scale;
|
|
508
|
+
columnOptions.comment = column.comment;
|
|
508
509
|
columnOptions.enum = !!column.enumItems?.length;
|
|
509
510
|
columnOptions.items = column.enumItems;
|
|
510
511
|
}
|
|
@@ -558,6 +559,7 @@ class DatabaseTable {
|
|
|
558
559
|
length: column.length,
|
|
559
560
|
precision: column.precision,
|
|
560
561
|
scale: column.scale,
|
|
562
|
+
comment: column.comment,
|
|
561
563
|
index: index ? index.keyName : undefined,
|
|
562
564
|
unique: unique ? unique.keyName : undefined,
|
|
563
565
|
enum: !!column.enumItems?.length,
|
|
@@ -601,8 +603,7 @@ class DatabaseTable {
|
|
|
601
603
|
// If this column is using an enum.
|
|
602
604
|
if (column.enumItems?.length) {
|
|
603
605
|
// We will create a new enum name for this type and set it as the property type as well.
|
|
604
|
-
|
|
605
|
-
return namingStrategy.getClassName(this.name + '_' + column.name, '_');
|
|
606
|
+
return namingStrategy.getEnumClassName(column.name, this.name, this.schema);
|
|
606
607
|
}
|
|
607
608
|
return column.mappedType?.runtimeType ?? 'unknown';
|
|
608
609
|
}
|
|
@@ -369,7 +369,10 @@ class SchemaComparator {
|
|
|
369
369
|
}
|
|
370
370
|
const defaultRule = ['restrict', 'no action'];
|
|
371
371
|
const rule = (key, method) => {
|
|
372
|
-
return (key[method] ?? defaultRule[0])
|
|
372
|
+
return (key[method] ?? defaultRule[0])
|
|
373
|
+
.toLowerCase()
|
|
374
|
+
.replace(defaultRule[1], defaultRule[0])
|
|
375
|
+
.replace(/"/g, '');
|
|
373
376
|
};
|
|
374
377
|
const compare = (method) => rule(key1, method) === rule(key2, method);
|
|
375
378
|
return !compare('updateRule') || !compare('deleteRule');
|
package/schema/SchemaHelper.d.ts
CHANGED
|
@@ -2,7 +2,7 @@ import { type Connection, type Dictionary } from '@mikro-orm/core';
|
|
|
2
2
|
import type { Knex } from 'knex';
|
|
3
3
|
import type { AbstractSqlConnection } from '../AbstractSqlConnection';
|
|
4
4
|
import type { AbstractSqlPlatform } from '../AbstractSqlPlatform';
|
|
5
|
-
import type { CheckDef, Column, IndexDef, Table, TableDifference } from '../typings';
|
|
5
|
+
import type { CheckDef, Column, ForeignKey, IndexDef, Table, TableDifference } from '../typings';
|
|
6
6
|
import type { DatabaseSchema } from './DatabaseSchema';
|
|
7
7
|
import type { DatabaseTable } from './DatabaseTable';
|
|
8
8
|
export declare abstract class SchemaHelper {
|
|
@@ -58,4 +58,20 @@ export declare abstract class SchemaHelper {
|
|
|
58
58
|
* Uses `raw` method injected in `AbstractSqlConnection` to allow adding custom queries inside alter statements.
|
|
59
59
|
*/
|
|
60
60
|
pushTableQuery(table: Knex.TableBuilder, expression: string, grouping?: string): void;
|
|
61
|
+
dump(builder: Knex.SchemaBuilder | string, append: string): Promise<string>;
|
|
62
|
+
createTable(tableDef: DatabaseTable, alter?: boolean): Knex.SchemaBuilder;
|
|
63
|
+
createForeignKey(table: Knex.CreateTableBuilder, foreignKey: ForeignKey, schema?: string): void;
|
|
64
|
+
splitTableName(name: string): [string | undefined, string];
|
|
65
|
+
getReferencedTableName(referencedTableName: string, schema?: string): string;
|
|
66
|
+
createIndex(table: Knex.CreateTableBuilder, index: IndexDef, tableDef: DatabaseTable, createPrimary?: boolean): void;
|
|
67
|
+
createCheck(table: Knex.CreateTableBuilder, check: CheckDef): void;
|
|
68
|
+
createSchemaBuilder(schema?: string): Knex.SchemaBuilder;
|
|
69
|
+
getAlterTable?(changedTable: TableDifference, wrap?: boolean): Promise<string>;
|
|
70
|
+
get knex(): Knex;
|
|
71
|
+
get options(): {
|
|
72
|
+
disableForeignKeys?: boolean | undefined;
|
|
73
|
+
createForeignKeyConstraints?: boolean | undefined;
|
|
74
|
+
ignoreSchema?: string[] | undefined;
|
|
75
|
+
managementDbName?: string | undefined;
|
|
76
|
+
};
|
|
61
77
|
}
|
package/schema/SchemaHelper.js
CHANGED
|
@@ -61,8 +61,7 @@ class SchemaHelper {
|
|
|
61
61
|
}
|
|
62
62
|
async loadInformationSchema(schema, connection, tables, schemas) {
|
|
63
63
|
for (const t of tables) {
|
|
64
|
-
const table = schema.addTable(t.table_name, t.schema_name);
|
|
65
|
-
table.comment = t.table_comment;
|
|
64
|
+
const table = schema.addTable(t.table_name, t.schema_name, t.table_comment);
|
|
66
65
|
const cols = await this.getColumns(connection, table.name, table.schema);
|
|
67
66
|
const indexes = await this.getIndexes(connection, table.name, table.schema);
|
|
68
67
|
const checks = await this.getChecks(connection, table.name, table.schema, cols);
|
|
@@ -273,5 +272,137 @@ class SchemaHelper {
|
|
|
273
272
|
pushTableQuery(table, expression, grouping = 'alterTable') {
|
|
274
273
|
table._statements.push({ grouping, method: 'raw', args: [expression] });
|
|
275
274
|
}
|
|
275
|
+
async dump(builder, append) {
|
|
276
|
+
if (typeof builder === 'string') {
|
|
277
|
+
return builder ? builder + (builder.endsWith(';') ? '' : ';') + append : '';
|
|
278
|
+
}
|
|
279
|
+
const sql = await builder.generateDdlCommands();
|
|
280
|
+
const queries = [...sql.pre, ...sql.sql, ...sql.post];
|
|
281
|
+
if (queries.length === 0) {
|
|
282
|
+
return '';
|
|
283
|
+
}
|
|
284
|
+
const dump = `${queries.map(q => typeof q === 'object' ? q.sql : q).join(';\n')};${append}`;
|
|
285
|
+
const tmp = dump.replace(/pragma table_.+/ig, '').replace(/\n\n+/g, '\n').trim();
|
|
286
|
+
return tmp ? tmp + append : '';
|
|
287
|
+
}
|
|
288
|
+
createTable(tableDef, alter) {
|
|
289
|
+
return this.createSchemaBuilder(tableDef.schema).createTable(tableDef.name, table => {
|
|
290
|
+
tableDef.getColumns().forEach(column => {
|
|
291
|
+
const col = this.createTableColumn(table, column, tableDef, undefined, alter);
|
|
292
|
+
this.configureColumn(column, col, this.knex);
|
|
293
|
+
});
|
|
294
|
+
for (const index of tableDef.getIndexes()) {
|
|
295
|
+
const createPrimary = !tableDef.getColumns().some(c => c.autoincrement && c.primary) || this.hasNonDefaultPrimaryKeyName(tableDef);
|
|
296
|
+
this.createIndex(table, index, tableDef, createPrimary);
|
|
297
|
+
}
|
|
298
|
+
for (const check of tableDef.getChecks()) {
|
|
299
|
+
this.createCheck(table, check);
|
|
300
|
+
}
|
|
301
|
+
if (tableDef.comment) {
|
|
302
|
+
const comment = this.platform.quoteValue(tableDef.comment).replace(/^'|'$/g, '');
|
|
303
|
+
table.comment(comment);
|
|
304
|
+
}
|
|
305
|
+
if (!this.supportsSchemaConstraints()) {
|
|
306
|
+
for (const fk of Object.values(tableDef.getForeignKeys())) {
|
|
307
|
+
this.createForeignKey(table, fk);
|
|
308
|
+
}
|
|
309
|
+
}
|
|
310
|
+
this.finalizeTable(table, this.platform.getConfig().get('charset'), this.platform.getConfig().get('collate'));
|
|
311
|
+
});
|
|
312
|
+
}
|
|
313
|
+
createForeignKey(table, foreignKey, schema) {
|
|
314
|
+
if (!this.options.createForeignKeyConstraints) {
|
|
315
|
+
return;
|
|
316
|
+
}
|
|
317
|
+
const builder = table
|
|
318
|
+
.foreign(foreignKey.columnNames, foreignKey.constraintName)
|
|
319
|
+
.references(foreignKey.referencedColumnNames)
|
|
320
|
+
.inTable(this.getReferencedTableName(foreignKey.referencedTableName, schema))
|
|
321
|
+
.withKeyName(foreignKey.constraintName);
|
|
322
|
+
if (foreignKey.localTableName !== foreignKey.referencedTableName || this.platform.supportsMultipleCascadePaths()) {
|
|
323
|
+
if (foreignKey.updateRule) {
|
|
324
|
+
builder.onUpdate(foreignKey.updateRule);
|
|
325
|
+
}
|
|
326
|
+
if (foreignKey.deleteRule) {
|
|
327
|
+
builder.onDelete(foreignKey.deleteRule);
|
|
328
|
+
}
|
|
329
|
+
}
|
|
330
|
+
if (foreignKey.deferMode) {
|
|
331
|
+
builder.deferrable(foreignKey.deferMode);
|
|
332
|
+
}
|
|
333
|
+
}
|
|
334
|
+
splitTableName(name) {
|
|
335
|
+
const parts = name.split('.');
|
|
336
|
+
const tableName = parts.pop();
|
|
337
|
+
const schemaName = parts.pop();
|
|
338
|
+
return [schemaName, tableName];
|
|
339
|
+
}
|
|
340
|
+
getReferencedTableName(referencedTableName, schema) {
|
|
341
|
+
const [schemaName, tableName] = this.splitTableName(referencedTableName);
|
|
342
|
+
schema = schemaName ?? schema ?? this.platform.getConfig().get('schema');
|
|
343
|
+
/* istanbul ignore next */
|
|
344
|
+
if (schema && schemaName === '*') {
|
|
345
|
+
return `${schema}.${referencedTableName.replace(/^\*\./, '')}`;
|
|
346
|
+
}
|
|
347
|
+
if (!schemaName || schemaName === this.platform.getDefaultSchemaName()) {
|
|
348
|
+
return tableName;
|
|
349
|
+
}
|
|
350
|
+
return `${schemaName}.${tableName}`;
|
|
351
|
+
}
|
|
352
|
+
createIndex(table, index, tableDef, createPrimary = false) {
|
|
353
|
+
if (index.primary && !createPrimary) {
|
|
354
|
+
return;
|
|
355
|
+
}
|
|
356
|
+
if (index.expression) {
|
|
357
|
+
this.pushTableQuery(table, index.expression);
|
|
358
|
+
}
|
|
359
|
+
else if (index.primary) {
|
|
360
|
+
const keyName = this.hasNonDefaultPrimaryKeyName(tableDef) ? index.keyName : undefined;
|
|
361
|
+
table.primary(index.columnNames, keyName);
|
|
362
|
+
}
|
|
363
|
+
else if (index.unique) {
|
|
364
|
+
// JSON columns can have unique index but not unique constraint, and we need to distinguish those, so we can properly drop them
|
|
365
|
+
if (index.columnNames.some(column => column.includes('.'))) {
|
|
366
|
+
const columns = this.platform.getJsonIndexDefinition(index);
|
|
367
|
+
table.index(columns.map(column => this.knex.raw(column)), index.keyName, { indexType: 'unique' });
|
|
368
|
+
}
|
|
369
|
+
else {
|
|
370
|
+
table.unique(index.columnNames, { indexName: index.keyName, deferrable: index.deferMode });
|
|
371
|
+
}
|
|
372
|
+
}
|
|
373
|
+
else if (index.type === 'fulltext') {
|
|
374
|
+
const columns = index.columnNames.map(name => ({ name, type: tableDef.getColumn(name).type }));
|
|
375
|
+
if (this.platform.supportsCreatingFullTextIndex()) {
|
|
376
|
+
this.pushTableQuery(table, this.platform.getFullTextIndexExpression(index.keyName, tableDef.schema, tableDef.name, columns));
|
|
377
|
+
}
|
|
378
|
+
}
|
|
379
|
+
else {
|
|
380
|
+
// JSON columns can have unique index but not unique constraint, and we need to distinguish those, so we can properly drop them
|
|
381
|
+
if (index.columnNames.some(column => column.includes('.'))) {
|
|
382
|
+
const columns = this.platform.getJsonIndexDefinition(index);
|
|
383
|
+
table.index(columns.map(column => this.knex.raw(column)), index.keyName, index.type);
|
|
384
|
+
}
|
|
385
|
+
else {
|
|
386
|
+
table.index(index.columnNames, index.keyName, index.type);
|
|
387
|
+
}
|
|
388
|
+
}
|
|
389
|
+
}
|
|
390
|
+
createCheck(table, check) {
|
|
391
|
+
table.check(check.expression, {}, check.name);
|
|
392
|
+
}
|
|
393
|
+
createSchemaBuilder(schema) {
|
|
394
|
+
const builder = this.knex.schema;
|
|
395
|
+
if (schema && schema !== this.platform.getDefaultSchemaName()) {
|
|
396
|
+
builder.withSchema(schema);
|
|
397
|
+
}
|
|
398
|
+
return builder;
|
|
399
|
+
}
|
|
400
|
+
get knex() {
|
|
401
|
+
const connection = this.platform.getConfig().getDriver().getConnection();
|
|
402
|
+
return connection.getKnex();
|
|
403
|
+
}
|
|
404
|
+
get options() {
|
|
405
|
+
return this.platform.getConfig().get('schemaGenerator');
|
|
406
|
+
}
|
|
276
407
|
}
|
|
277
408
|
exports.SchemaHelper = SchemaHelper;
|
|
@@ -38,14 +38,11 @@ export declare class SqlSchemaGenerator extends AbstractSchemaGenerator<Abstract
|
|
|
38
38
|
dropTables?: boolean;
|
|
39
39
|
schema?: string;
|
|
40
40
|
}): Promise<string>;
|
|
41
|
-
private getReferencedTableName;
|
|
42
|
-
private createForeignKey;
|
|
43
41
|
/**
|
|
44
42
|
* We need to drop foreign keys first for all tables to allow dropping PK constraints.
|
|
45
43
|
*/
|
|
46
44
|
private preAlterTable;
|
|
47
45
|
private postAlterTable;
|
|
48
|
-
private splitTableName;
|
|
49
46
|
private alterTable;
|
|
50
47
|
/**
|
|
51
48
|
* creates new database and connects to it
|
|
@@ -57,11 +54,7 @@ export declare class SqlSchemaGenerator extends AbstractSchemaGenerator<Abstract
|
|
|
57
54
|
ctx?: Transaction;
|
|
58
55
|
}): Promise<void>;
|
|
59
56
|
private wrapSchema;
|
|
60
|
-
private createSchemaBuilder;
|
|
61
|
-
private createTable;
|
|
62
|
-
private createIndex;
|
|
63
57
|
private dropIndex;
|
|
64
|
-
private createCheck;
|
|
65
58
|
private dropCheck;
|
|
66
59
|
private dropTable;
|
|
67
60
|
private createForeignKeys;
|
|
@@ -59,7 +59,7 @@ class SqlSchemaGenerator extends core_1.AbstractSchemaGenerator {
|
|
|
59
59
|
continue;
|
|
60
60
|
}
|
|
61
61
|
const sql = this.helper.getCreateNamespaceSQL(namespace);
|
|
62
|
-
ret += await this.dump(
|
|
62
|
+
ret += await this.dump(sql, '\n');
|
|
63
63
|
}
|
|
64
64
|
if (this.platform.supportsNativeEnums()) {
|
|
65
65
|
const created = [];
|
|
@@ -70,14 +70,14 @@ class SqlSchemaGenerator extends core_1.AbstractSchemaGenerator {
|
|
|
70
70
|
}
|
|
71
71
|
created.push(enumName);
|
|
72
72
|
const sql = this.helper.getCreateNativeEnumSQL(enumOptions.name, enumOptions.items, this.getSchemaName(enumOptions, options));
|
|
73
|
-
ret += await this.dump(
|
|
73
|
+
ret += await this.dump(sql, '\n');
|
|
74
74
|
}
|
|
75
75
|
}
|
|
76
76
|
for (const tableDef of toSchema.getTables()) {
|
|
77
|
-
ret += await this.dump(this.createTable(tableDef));
|
|
77
|
+
ret += await this.dump(this.helper.createTable(tableDef));
|
|
78
78
|
}
|
|
79
79
|
for (const tableDef of toSchema.getTables()) {
|
|
80
|
-
ret += await this.dump(this.createSchemaBuilder(tableDef.schema).alterTable(tableDef.name, table => this.createForeignKeys(table, tableDef, options.schema)));
|
|
80
|
+
ret += await this.dump(this.helper.createSchemaBuilder(tableDef.schema).alterTable(tableDef.name, table => this.createForeignKeys(table, tableDef, options.schema)));
|
|
81
81
|
}
|
|
82
82
|
return this.wrapSchema(ret, { wrap });
|
|
83
83
|
}
|
|
@@ -124,7 +124,7 @@ class SqlSchemaGenerator extends core_1.AbstractSchemaGenerator {
|
|
|
124
124
|
const table = schema.getTable(meta.tableName);
|
|
125
125
|
if (!this.platform.usesCascadeStatement() && table && (!wrap || options.dropForeignKeys)) {
|
|
126
126
|
for (const fk of Object.values(table.getForeignKeys())) {
|
|
127
|
-
const builder = this.createSchemaBuilder(table.schema).alterTable(table.name, tbl => {
|
|
127
|
+
const builder = this.helper.createSchemaBuilder(table.schema).alterTable(table.name, tbl => {
|
|
128
128
|
tbl.dropForeign(fk.columnNames, fk.constraintName);
|
|
129
129
|
});
|
|
130
130
|
ret += await this.dump(builder, '\n');
|
|
@@ -137,7 +137,7 @@ class SqlSchemaGenerator extends core_1.AbstractSchemaGenerator {
|
|
|
137
137
|
if (this.platform.supportsNativeEnums()) {
|
|
138
138
|
for (const columnName of Object.keys(schema.getNativeEnums())) {
|
|
139
139
|
const sql = this.helper.getDropNativeEnumSQL(columnName, options.schema ?? this.config.get('schema'));
|
|
140
|
-
ret += await this.dump(
|
|
140
|
+
ret += await this.dump(sql, '\n');
|
|
141
141
|
}
|
|
142
142
|
}
|
|
143
143
|
if (options.dropMigrationsTable) {
|
|
@@ -191,28 +191,28 @@ class SqlSchemaGenerator extends core_1.AbstractSchemaGenerator {
|
|
|
191
191
|
if (this.platform.supportsSchemas()) {
|
|
192
192
|
for (const newNamespace of schemaDiff.newNamespaces) {
|
|
193
193
|
const sql = this.helper.getCreateNamespaceSQL(newNamespace);
|
|
194
|
-
ret += await this.dump(
|
|
194
|
+
ret += await this.dump(sql, '\n');
|
|
195
195
|
}
|
|
196
196
|
}
|
|
197
197
|
if (this.platform.supportsNativeEnums()) {
|
|
198
198
|
for (const newNativeEnum of schemaDiff.newNativeEnums) {
|
|
199
199
|
const sql = this.helper.getCreateNativeEnumSQL(newNativeEnum.name, newNativeEnum.items, this.getSchemaName(newNativeEnum, options));
|
|
200
|
-
ret += await this.dump(
|
|
200
|
+
ret += await this.dump(sql, '\n');
|
|
201
201
|
}
|
|
202
202
|
}
|
|
203
203
|
if (!options.safe) {
|
|
204
204
|
for (const orphanedForeignKey of schemaDiff.orphanedForeignKeys) {
|
|
205
|
-
const [schemaName, tableName] = this.splitTableName(orphanedForeignKey.localTableName);
|
|
206
|
-
ret += await this.dump(this.createSchemaBuilder(schemaName).alterTable(tableName, table => {
|
|
205
|
+
const [schemaName, tableName] = this.helper.splitTableName(orphanedForeignKey.localTableName);
|
|
206
|
+
ret += await this.dump(this.helper.createSchemaBuilder(schemaName).alterTable(tableName, table => {
|
|
207
207
|
return table.dropForeign(orphanedForeignKey.columnNames, orphanedForeignKey.constraintName);
|
|
208
208
|
}));
|
|
209
209
|
}
|
|
210
210
|
}
|
|
211
211
|
for (const newTable of Object.values(schemaDiff.newTables)) {
|
|
212
|
-
ret += await this.dump(this.createTable(newTable, true));
|
|
212
|
+
ret += await this.dump(this.helper.createTable(newTable, true));
|
|
213
213
|
}
|
|
214
214
|
for (const newTable of Object.values(schemaDiff.newTables)) {
|
|
215
|
-
ret += await this.dump(this.createSchemaBuilder(newTable.schema).alterTable(newTable.name, table => {
|
|
215
|
+
ret += await this.dump(this.helper.createSchemaBuilder(newTable.schema).alterTable(newTable.name, table => {
|
|
216
216
|
this.createForeignKeys(table, newTable, options.schema);
|
|
217
217
|
}));
|
|
218
218
|
}
|
|
@@ -228,7 +228,11 @@ class SqlSchemaGenerator extends core_1.AbstractSchemaGenerator {
|
|
|
228
228
|
}
|
|
229
229
|
for (const changedTable of Object.values(schemaDiff.changedTables)) {
|
|
230
230
|
for (const builder of this.alterTable(changedTable, options.safe)) {
|
|
231
|
-
|
|
231
|
+
let diff = await this.dump(builder);
|
|
232
|
+
if (diff.includes('CREATE TABLE `_knex_temp_alter') && this.helper.getAlterTable) {
|
|
233
|
+
diff = await this.helper.getAlterTable(changedTable, options.wrap);
|
|
234
|
+
}
|
|
235
|
+
ret += diff;
|
|
232
236
|
}
|
|
233
237
|
}
|
|
234
238
|
for (const changedTable of Object.values(schemaDiff.changedTables)) {
|
|
@@ -239,50 +243,17 @@ class SqlSchemaGenerator extends core_1.AbstractSchemaGenerator {
|
|
|
239
243
|
if (!options.safe && this.platform.supportsNativeEnums()) {
|
|
240
244
|
for (const removedNativeEnum of schemaDiff.removedNativeEnums) {
|
|
241
245
|
const sql = this.helper.getDropNativeEnumSQL(removedNativeEnum.name, removedNativeEnum.schema);
|
|
242
|
-
ret += await this.dump(
|
|
246
|
+
ret += await this.dump(sql, '\n');
|
|
243
247
|
}
|
|
244
248
|
}
|
|
245
249
|
if (options.dropTables && !options.safe) {
|
|
246
250
|
for (const removedNamespace of schemaDiff.removedNamespaces) {
|
|
247
251
|
const sql = this.helper.getDropNamespaceSQL(removedNamespace);
|
|
248
|
-
ret += await this.dump(
|
|
252
|
+
ret += await this.dump(sql, '\n');
|
|
249
253
|
}
|
|
250
254
|
}
|
|
251
255
|
return this.wrapSchema(ret, options);
|
|
252
256
|
}
|
|
253
|
-
getReferencedTableName(referencedTableName, schema) {
|
|
254
|
-
const [schemaName, tableName] = this.splitTableName(referencedTableName);
|
|
255
|
-
schema = schemaName ?? schema ?? this.config.get('schema');
|
|
256
|
-
/* istanbul ignore next */
|
|
257
|
-
if (schema && schemaName === '*') {
|
|
258
|
-
return `${schema}.${referencedTableName.replace(/^\*\./, '')}`;
|
|
259
|
-
}
|
|
260
|
-
if (!schemaName || schemaName === this.platform.getDefaultSchemaName()) {
|
|
261
|
-
return tableName;
|
|
262
|
-
}
|
|
263
|
-
return `${schemaName}.${tableName}`;
|
|
264
|
-
}
|
|
265
|
-
createForeignKey(table, foreignKey, schema) {
|
|
266
|
-
if (!this.options.createForeignKeyConstraints) {
|
|
267
|
-
return;
|
|
268
|
-
}
|
|
269
|
-
const builder = table
|
|
270
|
-
.foreign(foreignKey.columnNames, foreignKey.constraintName)
|
|
271
|
-
.references(foreignKey.referencedColumnNames)
|
|
272
|
-
.inTable(this.getReferencedTableName(foreignKey.referencedTableName, schema))
|
|
273
|
-
.withKeyName(foreignKey.constraintName);
|
|
274
|
-
if (foreignKey.localTableName !== foreignKey.referencedTableName || this.platform.supportsMultipleCascadePaths()) {
|
|
275
|
-
if (foreignKey.updateRule) {
|
|
276
|
-
builder.onUpdate(foreignKey.updateRule);
|
|
277
|
-
}
|
|
278
|
-
if (foreignKey.deleteRule) {
|
|
279
|
-
builder.onDelete(foreignKey.deleteRule);
|
|
280
|
-
}
|
|
281
|
-
}
|
|
282
|
-
if (foreignKey.deferMode) {
|
|
283
|
-
builder.deferrable(foreignKey.deferMode);
|
|
284
|
-
}
|
|
285
|
-
}
|
|
286
257
|
/**
|
|
287
258
|
* We need to drop foreign keys first for all tables to allow dropping PK constraints.
|
|
288
259
|
*/
|
|
@@ -290,8 +261,8 @@ class SqlSchemaGenerator extends core_1.AbstractSchemaGenerator {
|
|
|
290
261
|
const ret = [];
|
|
291
262
|
const push = (sql) => sql ? ret.push(this.knex.schema.raw(sql)) : undefined;
|
|
292
263
|
push(this.helper.getPreAlterTable(diff, safe));
|
|
293
|
-
const [schemaName, tableName] = this.splitTableName(diff.name);
|
|
294
|
-
ret.push(this.createSchemaBuilder(schemaName).alterTable(tableName, table => {
|
|
264
|
+
const [schemaName, tableName] = this.helper.splitTableName(diff.name);
|
|
265
|
+
ret.push(this.helper.createSchemaBuilder(schemaName).alterTable(tableName, table => {
|
|
295
266
|
for (const foreignKey of Object.values(diff.removedForeignKeys)) {
|
|
296
267
|
table.dropForeign(foreignKey.columnNames, foreignKey.constraintName);
|
|
297
268
|
}
|
|
@@ -307,15 +278,9 @@ class SqlSchemaGenerator extends core_1.AbstractSchemaGenerator {
|
|
|
307
278
|
push(this.helper.getPostAlterTable(diff, safe));
|
|
308
279
|
return ret;
|
|
309
280
|
}
|
|
310
|
-
splitTableName(name) {
|
|
311
|
-
const parts = name.split('.');
|
|
312
|
-
const tableName = parts.pop();
|
|
313
|
-
const schemaName = parts.pop();
|
|
314
|
-
return [schemaName, tableName];
|
|
315
|
-
}
|
|
316
281
|
alterTable(diff, safe) {
|
|
317
282
|
const ret = [];
|
|
318
|
-
const [schemaName, tableName] = this.splitTableName(diff.name);
|
|
283
|
+
const [schemaName, tableName] = this.helper.splitTableName(diff.name);
|
|
319
284
|
if (this.platform.supportsNativeEnums()) {
|
|
320
285
|
const changedNativeEnums = [];
|
|
321
286
|
for (const { column, changedProperties } of Object.values(diff.changedColumns)) {
|
|
@@ -334,7 +299,7 @@ class SqlSchemaGenerator extends core_1.AbstractSchemaGenerator {
|
|
|
334
299
|
ret.push(...newItems.map(val => this.knex.schema.raw(this.helper.getAlterNativeEnumSQL(enumName, schemaName, val))));
|
|
335
300
|
});
|
|
336
301
|
}
|
|
337
|
-
ret.push(this.createSchemaBuilder(schemaName).alterTable(tableName, table => {
|
|
302
|
+
ret.push(this.helper.createSchemaBuilder(schemaName).alterTable(tableName, table => {
|
|
338
303
|
for (const index of Object.values(diff.removedIndexes)) {
|
|
339
304
|
this.dropIndex(table, index);
|
|
340
305
|
}
|
|
@@ -352,7 +317,7 @@ class SqlSchemaGenerator extends core_1.AbstractSchemaGenerator {
|
|
|
352
317
|
this.helper.pushTableQuery(table, this.helper.getDropColumnsSQL(tableName, Object.values(diff.removedColumns), schemaName));
|
|
353
318
|
}
|
|
354
319
|
}));
|
|
355
|
-
ret.push(this.createSchemaBuilder(schemaName).alterTable(tableName, table => {
|
|
320
|
+
ret.push(this.helper.createSchemaBuilder(schemaName).alterTable(tableName, table => {
|
|
356
321
|
for (const column of Object.values(diff.addedColumns)) {
|
|
357
322
|
const col = this.helper.createTableColumn(table, column, diff.fromTable, undefined, true);
|
|
358
323
|
this.helper.configureColumn(column, col, this.knex);
|
|
@@ -360,7 +325,7 @@ class SqlSchemaGenerator extends core_1.AbstractSchemaGenerator {
|
|
|
360
325
|
if (foreignKey && this.options.createForeignKeyConstraints) {
|
|
361
326
|
delete diff.addedForeignKeys[foreignKey.constraintName];
|
|
362
327
|
const builder = col.references(foreignKey.referencedColumnNames[0])
|
|
363
|
-
.inTable(this.getReferencedTableName(foreignKey.referencedTableName))
|
|
328
|
+
.inTable(this.helper.getReferencedTableName(foreignKey.referencedTableName))
|
|
364
329
|
.withKeyName(foreignKey.constraintName)
|
|
365
330
|
.onUpdate(foreignKey.updateRule)
|
|
366
331
|
.onDelete(foreignKey.deleteRule);
|
|
@@ -394,31 +359,31 @@ class SqlSchemaGenerator extends core_1.AbstractSchemaGenerator {
|
|
|
394
359
|
this.helper.pushTableQuery(table, this.helper.getRenameColumnSQL(tableName, oldColumnName, column, schemaName));
|
|
395
360
|
}
|
|
396
361
|
for (const foreignKey of Object.values(diff.addedForeignKeys)) {
|
|
397
|
-
this.createForeignKey(table, foreignKey);
|
|
362
|
+
this.helper.createForeignKey(table, foreignKey, undefined);
|
|
398
363
|
}
|
|
399
364
|
for (const foreignKey of Object.values(diff.changedForeignKeys)) {
|
|
400
|
-
this.createForeignKey(table, foreignKey);
|
|
365
|
+
this.helper.createForeignKey(table, foreignKey, undefined);
|
|
401
366
|
}
|
|
402
367
|
for (const index of Object.values(diff.addedIndexes)) {
|
|
403
|
-
this.createIndex(table, index, diff.toTable);
|
|
368
|
+
this.helper.createIndex(table, index, diff.toTable);
|
|
404
369
|
}
|
|
405
370
|
for (const index of Object.values(diff.changedIndexes)) {
|
|
406
|
-
this.createIndex(table, index, diff.toTable, true);
|
|
371
|
+
this.helper.createIndex(table, index, diff.toTable, true);
|
|
407
372
|
}
|
|
408
373
|
for (const [oldIndexName, index] of Object.entries(diff.renamedIndexes)) {
|
|
409
374
|
if (index.unique) {
|
|
410
375
|
this.dropIndex(table, index, oldIndexName);
|
|
411
|
-
this.createIndex(table, index, diff.toTable);
|
|
376
|
+
this.helper.createIndex(table, index, diff.toTable);
|
|
412
377
|
}
|
|
413
378
|
else {
|
|
414
379
|
this.helper.pushTableQuery(table, this.helper.getRenameIndexSQL(diff.name, index, oldIndexName));
|
|
415
380
|
}
|
|
416
381
|
}
|
|
417
382
|
for (const check of Object.values(diff.addedChecks)) {
|
|
418
|
-
this.createCheck(table, check);
|
|
383
|
+
this.helper.createCheck(table, check);
|
|
419
384
|
}
|
|
420
385
|
for (const check of Object.values(diff.changedChecks)) {
|
|
421
|
-
this.createCheck(table, check);
|
|
386
|
+
this.helper.createCheck(table, check);
|
|
422
387
|
}
|
|
423
388
|
if ('changedComment' in diff) {
|
|
424
389
|
const comment = diff.changedComment ? this.platform.quoteValue(diff.changedComment).replace(/^'|'$/g, '') : '';
|
|
@@ -483,76 +448,6 @@ class SqlSchemaGenerator extends core_1.AbstractSchemaGenerator {
|
|
|
483
448
|
ret += this.helper.getSchemaEnd();
|
|
484
449
|
return ret;
|
|
485
450
|
}
|
|
486
|
-
createSchemaBuilder(schema) {
|
|
487
|
-
const builder = this.knex.schema;
|
|
488
|
-
if (schema && schema !== this.platform.getDefaultSchemaName()) {
|
|
489
|
-
builder.withSchema(schema);
|
|
490
|
-
}
|
|
491
|
-
return builder;
|
|
492
|
-
}
|
|
493
|
-
createTable(tableDef, alter) {
|
|
494
|
-
return this.createSchemaBuilder(tableDef.schema).createTable(tableDef.name, table => {
|
|
495
|
-
tableDef.getColumns().forEach(column => {
|
|
496
|
-
const col = this.helper.createTableColumn(table, column, tableDef, undefined, alter);
|
|
497
|
-
this.helper.configureColumn(column, col, this.knex);
|
|
498
|
-
});
|
|
499
|
-
for (const index of tableDef.getIndexes()) {
|
|
500
|
-
const createPrimary = !tableDef.getColumns().some(c => c.autoincrement && c.primary) || this.helper.hasNonDefaultPrimaryKeyName(tableDef);
|
|
501
|
-
this.createIndex(table, index, tableDef, createPrimary);
|
|
502
|
-
}
|
|
503
|
-
for (const check of tableDef.getChecks()) {
|
|
504
|
-
this.createCheck(table, check);
|
|
505
|
-
}
|
|
506
|
-
if (tableDef.comment) {
|
|
507
|
-
const comment = this.platform.quoteValue(tableDef.comment).replace(/^'|'$/g, '');
|
|
508
|
-
table.comment(comment);
|
|
509
|
-
}
|
|
510
|
-
if (!this.helper.supportsSchemaConstraints()) {
|
|
511
|
-
for (const fk of Object.values(tableDef.getForeignKeys())) {
|
|
512
|
-
this.createForeignKey(table, fk);
|
|
513
|
-
}
|
|
514
|
-
}
|
|
515
|
-
this.helper.finalizeTable(table, this.config.get('charset'), this.config.get('collate'));
|
|
516
|
-
});
|
|
517
|
-
}
|
|
518
|
-
createIndex(table, index, tableDef, createPrimary = false) {
|
|
519
|
-
if (index.primary && !createPrimary) {
|
|
520
|
-
return;
|
|
521
|
-
}
|
|
522
|
-
if (index.primary) {
|
|
523
|
-
const keyName = this.helper.hasNonDefaultPrimaryKeyName(tableDef) ? index.keyName : undefined;
|
|
524
|
-
table.primary(index.columnNames, keyName);
|
|
525
|
-
}
|
|
526
|
-
else if (index.unique) {
|
|
527
|
-
// JSON columns can have unique index but not unique constraint, and we need to distinguish those, so we can properly drop them
|
|
528
|
-
if (index.columnNames.some(column => column.includes('.'))) {
|
|
529
|
-
const columns = this.platform.getJsonIndexDefinition(index);
|
|
530
|
-
table.index(columns.map(column => this.knex.raw(column)), index.keyName, { indexType: 'unique' });
|
|
531
|
-
}
|
|
532
|
-
else {
|
|
533
|
-
table.unique(index.columnNames, { indexName: index.keyName, deferrable: index.deferMode });
|
|
534
|
-
}
|
|
535
|
-
}
|
|
536
|
-
else if (index.expression) {
|
|
537
|
-
this.helper.pushTableQuery(table, index.expression);
|
|
538
|
-
}
|
|
539
|
-
else if (index.type === 'fulltext') {
|
|
540
|
-
const columns = index.columnNames.map(name => ({ name, type: tableDef.getColumn(name).type }));
|
|
541
|
-
if (this.platform.supportsCreatingFullTextIndex()) {
|
|
542
|
-
this.helper.pushTableQuery(table, this.platform.getFullTextIndexExpression(index.keyName, tableDef.schema, tableDef.name, columns));
|
|
543
|
-
}
|
|
544
|
-
}
|
|
545
|
-
else {
|
|
546
|
-
// JSON columns can have unique index but not unique constraint, and we need to distinguish those, so we can properly drop them
|
|
547
|
-
if (index.columnNames.some(column => column.includes('.'))) {
|
|
548
|
-
const columns = this.platform.getJsonIndexDefinition(index);
|
|
549
|
-
table.index(columns.map(column => this.knex.raw(column)), index.keyName, index.type);
|
|
550
|
-
}
|
|
551
|
-
else {
|
|
552
|
-
table.index(index.columnNames, index.keyName, index.type);
|
|
553
|
-
}
|
|
554
|
-
}
|
|
555
|
-
}
|
|
556
451
|
dropIndex(table, index, oldIndexName = index.keyName) {
|
|
557
452
|
if (index.primary) {
|
|
558
453
|
table.dropPrimary(oldIndexName);
|
|
@@ -564,14 +459,11 @@ class SqlSchemaGenerator extends core_1.AbstractSchemaGenerator {
|
|
|
564
459
|
table.dropIndex(index.columnNames, oldIndexName);
|
|
565
460
|
}
|
|
566
461
|
}
|
|
567
|
-
createCheck(table, check) {
|
|
568
|
-
table.check(check.expression, {}, check.name);
|
|
569
|
-
}
|
|
570
462
|
dropCheck(table, check) {
|
|
571
463
|
table.dropChecks(check.name);
|
|
572
464
|
}
|
|
573
465
|
dropTable(name, schema) {
|
|
574
|
-
let builder = this.createSchemaBuilder(schema).dropTableIfExists(name);
|
|
466
|
+
let builder = this.helper.createSchemaBuilder(schema).dropTableIfExists(name);
|
|
575
467
|
if (this.platform.usesCascadeStatement()) {
|
|
576
468
|
builder = this.knex.schema.raw(builder.toQuery() + ' cascade');
|
|
577
469
|
}
|
|
@@ -582,18 +474,11 @@ class SqlSchemaGenerator extends core_1.AbstractSchemaGenerator {
|
|
|
582
474
|
return;
|
|
583
475
|
}
|
|
584
476
|
for (const fk of Object.values(tableDef.getForeignKeys())) {
|
|
585
|
-
this.createForeignKey(table, fk, schema);
|
|
477
|
+
this.helper.createForeignKey(table, fk, schema);
|
|
586
478
|
}
|
|
587
479
|
}
|
|
588
480
|
async dump(builder, append = '\n\n') {
|
|
589
|
-
|
|
590
|
-
const queries = [...sql.pre, ...sql.sql, ...sql.post];
|
|
591
|
-
if (queries.length === 0) {
|
|
592
|
-
return '';
|
|
593
|
-
}
|
|
594
|
-
const dump = `${queries.map(q => typeof q === 'object' ? q.sql : q).join(';\n')};${append}`;
|
|
595
|
-
const tmp = dump.replace(/pragma table_.+/ig, '').replace(/\n\n+/g, '\n').trim();
|
|
596
|
-
return tmp ? tmp + append : '';
|
|
481
|
+
return this.helper.dump(builder, append);
|
|
597
482
|
}
|
|
598
483
|
get knex() {
|
|
599
484
|
return this.connection.getKnex();
|
package/typings.d.ts
CHANGED
|
@@ -129,6 +129,8 @@ export interface IQueryBuilder<T> {
|
|
|
129
129
|
readonly alias: string;
|
|
130
130
|
readonly type?: QueryType;
|
|
131
131
|
_fields?: Field<T>[];
|
|
132
|
+
/** @internal */
|
|
133
|
+
helper: any;
|
|
132
134
|
select(fields: Field<T> | Field<T>[], distinct?: boolean): this;
|
|
133
135
|
addSelect(fields: string | string[]): this;
|
|
134
136
|
from<T extends AnyEntity<T> = AnyEntity>(target: EntityName<T> | IQueryBuilder<T>, aliasName?: string): IQueryBuilder<T>;
|