@contember/schema-migrations 1.2.0-alpha.14 → 1.2.0-alpha.16
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/dist/src/SchemaDiffer.d.ts.map +1 -1
- package/dist/src/SchemaDiffer.js +2 -1
- package/dist/src/SchemaDiffer.js.map +1 -1
- package/dist/src/modifications/ModificationHandler.d.ts +7 -4
- package/dist/src/modifications/ModificationHandler.d.ts.map +1 -1
- package/dist/src/modifications/ModificationHandler.js.map +1 -1
- package/dist/src/modifications/ModificationHandlerFactory.d.ts +2 -2
- package/dist/src/modifications/ModificationHandlerFactory.d.ts.map +1 -1
- package/dist/src/modifications/ModificationHandlerFactory.js.map +1 -1
- package/dist/src/modifications/columns/CreateColumnModification.d.ts +1 -3
- package/dist/src/modifications/columns/CreateColumnModification.d.ts.map +1 -1
- package/dist/src/modifications/columns/UpdateColumnDefinitionModification.d.ts +3 -5
- package/dist/src/modifications/columns/UpdateColumnDefinitionModification.d.ts.map +1 -1
- package/dist/src/modifications/columns/UpdateColumnDefinitionModification.js +11 -5
- package/dist/src/modifications/columns/UpdateColumnDefinitionModification.js.map +1 -1
- package/dist/src/modifications/columns/UpdateColumnNameModification.d.ts +1 -3
- package/dist/src/modifications/columns/UpdateColumnNameModification.d.ts.map +1 -1
- package/dist/src/modifications/differs/RemoveChangedFieldDiffer.d.ts +1 -3
- package/dist/src/modifications/differs/RemoveChangedFieldDiffer.d.ts.map +1 -1
- package/dist/src/modifications/differs/RemoveChangedViewDiffer.d.ts +1 -2
- package/dist/src/modifications/differs/RemoveChangedViewDiffer.d.ts.map +1 -1
- package/dist/src/modifications/differs/RemoveChangedViewDiffer.js +7 -20
- package/dist/src/modifications/differs/RemoveChangedViewDiffer.js.map +1 -1
- package/dist/src/modifications/entities/RemoveEntityModification.d.ts +2 -1
- package/dist/src/modifications/entities/RemoveEntityModification.d.ts.map +1 -1
- package/dist/src/modifications/entities/RemoveEntityModification.js.map +1 -1
- package/dist/src/modifications/entities/UpdateEntityNameModification.d.ts +2 -2
- package/dist/src/modifications/entities/UpdateEntityNameModification.d.ts.map +1 -1
- package/dist/src/modifications/entities/UpdateEntityNameModification.js.map +1 -1
- package/dist/src/modifications/fields/UpdateFieldNameModification.d.ts +2 -2
- package/dist/src/modifications/fields/UpdateFieldNameModification.d.ts.map +1 -1
- package/dist/src/modifications/fields/UpdateFieldNameModification.js.map +1 -1
- package/dist/src/modifications/relations/ConvertOneHasManyToManyHasManyRelationModification.d.ts +3 -4
- package/dist/src/modifications/relations/ConvertOneHasManyToManyHasManyRelationModification.d.ts.map +1 -1
- package/dist/src/modifications/relations/ConvertOneHasManyToManyHasManyRelationModification.js +2 -2
- package/dist/src/modifications/relations/ConvertOneHasManyToManyHasManyRelationModification.js.map +1 -1
- package/dist/src/modifications/relations/ConvertOneToManyRelationModification.d.ts +3 -4
- package/dist/src/modifications/relations/ConvertOneToManyRelationModification.d.ts.map +1 -1
- package/dist/src/modifications/relations/ConvertOneToManyRelationModification.js +10 -2
- package/dist/src/modifications/relations/ConvertOneToManyRelationModification.js.map +1 -1
- package/dist/src/modifications/relations/CreateRelationInverseSideModification.d.ts +1 -3
- package/dist/src/modifications/relations/CreateRelationInverseSideModification.d.ts.map +1 -1
- package/dist/src/modifications/relations/CreateRelationModification.d.ts +3 -4
- package/dist/src/modifications/relations/CreateRelationModification.d.ts.map +1 -1
- package/dist/src/modifications/relations/CreateRelationModification.js +14 -3
- package/dist/src/modifications/relations/CreateRelationModification.js.map +1 -1
- package/dist/src/modifications/relations/DisableOrphanRemovalModification.d.ts +1 -3
- package/dist/src/modifications/relations/DisableOrphanRemovalModification.d.ts.map +1 -1
- package/dist/src/modifications/relations/EnableOrphanRemovalModification.d.ts +1 -3
- package/dist/src/modifications/relations/EnableOrphanRemovalModification.d.ts.map +1 -1
- package/dist/src/modifications/relations/MakeRelationNotNullModification.d.ts +1 -3
- package/dist/src/modifications/relations/MakeRelationNotNullModification.d.ts.map +1 -1
- package/dist/src/modifications/relations/MakeRelationNullableModification.d.ts +1 -3
- package/dist/src/modifications/relations/MakeRelationNullableModification.d.ts.map +1 -1
- package/dist/src/modifications/relations/ToggleJunctionEventLogModification.d.ts +1 -3
- package/dist/src/modifications/relations/ToggleJunctionEventLogModification.d.ts.map +1 -1
- package/dist/src/modifications/relations/UpdateRelationOnDeleteModification.d.ts +1 -3
- package/dist/src/modifications/relations/UpdateRelationOnDeleteModification.d.ts.map +1 -1
- package/dist/src/modifications/relations/UpdateRelationOrderByModification.d.ts +1 -3
- package/dist/src/modifications/relations/UpdateRelationOrderByModification.d.ts.map +1 -1
- package/dist/src/modifications/utils/columnUtils.d.ts +1 -1
- package/dist/src/modifications/utils/columnUtils.d.ts.map +1 -1
- package/dist/src/modifications/utils/columnUtils.js.map +1 -1
- package/dist/src/modifications/utils/createJunctionTable.d.ts +2 -1
- package/dist/src/modifications/utils/createJunctionTable.d.ts.map +1 -1
- package/dist/src/modifications/utils/createJunctionTable.js +7 -5
- package/dist/src/modifications/utils/createJunctionTable.js.map +1 -1
- package/dist/src/modifications/utils/diffUtils.d.ts +14 -12
- package/dist/src/modifications/utils/diffUtils.d.ts.map +1 -1
- package/dist/src/modifications/utils/diffUtils.js.map +1 -1
- package/dist/src/modifications/utils/schemaMeta.d.ts +8 -0
- package/dist/src/modifications/utils/schemaMeta.d.ts.map +1 -0
- package/dist/src/modifications/utils/schemaMeta.js +13 -0
- package/dist/src/modifications/utils/schemaMeta.js.map +1 -0
- package/dist/src/modifications/utils/schemaUpdateUtils.d.ts +4 -2
- package/dist/src/modifications/utils/schemaUpdateUtils.d.ts.map +1 -1
- package/dist/src/modifications/utils/schemaUpdateUtils.js +16 -1
- package/dist/src/modifications/utils/schemaUpdateUtils.js.map +1 -1
- package/dist/src/modifications/utils/viewDependencies.d.ts +4 -2
- package/dist/src/modifications/utils/viewDependencies.d.ts.map +1 -1
- package/dist/src/modifications/utils/viewDependencies.js +29 -6
- package/dist/src/modifications/utils/viewDependencies.js.map +1 -1
- package/dist/src/tsconfig.tsbuildinfo +1 -1
- package/dist/tests/cases/integration/convertOneHasManyToManyHasManyRelation.test.js +3 -2
- package/dist/tests/cases/integration/convertOneHasManyToManyHasManyRelation.test.js.map +1 -1
- package/dist/tests/cases/integration/createManyHasMany.test.js +3 -2
- package/dist/tests/cases/integration/createManyHasMany.test.js.map +1 -1
- package/dist/tests/cases/integration/takenIndexName.test.d.ts +2 -0
- package/dist/tests/cases/integration/takenIndexName.test.d.ts.map +1 -0
- package/dist/tests/cases/integration/takenIndexName.test.js +307 -0
- package/dist/tests/cases/integration/takenIndexName.test.js.map +1 -0
- package/dist/tests/cases/integration/updateColumnDefinition.test.js +160 -0
- package/dist/tests/cases/integration/updateColumnDefinition.test.js.map +1 -1
- package/dist/tests/src/tests.d.ts.map +1 -1
- package/dist/tests/src/tests.js +2 -2
- package/dist/tests/src/tests.js.map +1 -1
- package/dist/tests/tsconfig.tsbuildinfo +1 -1
- package/package.json +6 -6
- package/src/SchemaDiffer.ts +3 -1
- package/src/modifications/ModificationHandler.ts +5 -4
- package/src/modifications/ModificationHandlerFactory.ts +2 -1
- package/src/modifications/columns/UpdateColumnDefinitionModification.ts +19 -10
- package/src/modifications/differs/RemoveChangedViewDiffer.ts +9 -22
- package/src/modifications/entities/RemoveEntityModification.ts +2 -1
- package/src/modifications/entities/UpdateEntityNameModification.ts +2 -1
- package/src/modifications/fields/UpdateFieldNameModification.ts +2 -1
- package/src/modifications/relations/ConvertOneHasManyToManyHasManyRelationModification.ts +13 -4
- package/src/modifications/relations/ConvertOneToManyRelationModification.ts +19 -3
- package/src/modifications/relations/CreateRelationModification.ts +30 -8
- package/src/modifications/utils/columnUtils.ts +1 -1
- package/src/modifications/utils/createJunctionTable.ts +7 -5
- package/src/modifications/utils/diffUtils.ts +12 -12
- package/src/modifications/utils/schemaMeta.ts +18 -0
- package/src/modifications/utils/schemaUpdateUtils.ts +14 -1
- package/src/modifications/utils/viewDependencies.ts +28 -5
- package/tests/cases/integration/convertOneHasManyToManyHasManyRelation.test.ts +3 -2
- package/tests/cases/integration/createManyHasMany.test.ts +3 -2
- package/tests/cases/integration/takenIndexName.test.ts +314 -0
- package/tests/cases/integration/updateColumnDefinition.test.ts +138 -1
- package/tests/src/tests.ts +5 -4
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { MigrationBuilder } from '@contember/database-migrations'
|
|
1
|
+
import { escapeValue, MigrationBuilder } from '@contember/database-migrations'
|
|
2
2
|
import { Model, Schema } from '@contember/schema'
|
|
3
3
|
import { SchemaUpdater, updateEntity, updateField, updateModel } from '../utils/schemaUpdateUtils'
|
|
4
4
|
import { createModificationType, Differ, ModificationHandler } from '../ModificationHandler'
|
|
@@ -6,6 +6,7 @@ import deepEqual from 'fast-deep-equal'
|
|
|
6
6
|
import { updateColumns } from '../utils/diffUtils'
|
|
7
7
|
import { wrapIdentifier } from '@contember/database'
|
|
8
8
|
import { getColumnSqlType } from '../utils/columnUtils'
|
|
9
|
+
import { getEntityDependantViews } from '../utils/viewDependencies'
|
|
9
10
|
|
|
10
11
|
export class UpdateColumnDefinitionModificationHandler implements ModificationHandler<UpdateColumnDefinitionModificationData> {
|
|
11
12
|
constructor(private readonly data: UpdateColumnDefinitionModificationData, private readonly schema: Schema) {}
|
|
@@ -17,14 +18,21 @@ export class UpdateColumnDefinitionModificationHandler implements ModificationHa
|
|
|
17
18
|
}
|
|
18
19
|
const oldColumn = entity.fields[this.data.fieldName] as Model.AnyColumn
|
|
19
20
|
const newColumn = this.data.definition
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
21
|
+
|
|
22
|
+
const hasNewSequence = !oldColumn.sequence && newColumn.sequence
|
|
23
|
+
const hasNewType = newColumn.columnType !== oldColumn.columnType
|
|
24
|
+
const columnType = getColumnSqlType(newColumn)
|
|
25
|
+
|
|
26
|
+
const usingCast = `${wrapIdentifier(oldColumn.columnName)}::${columnType}`
|
|
23
27
|
|
|
24
28
|
builder.alterColumn(entity.tableName, oldColumn.columnName, {
|
|
25
|
-
type:
|
|
29
|
+
type: hasNewSequence || hasNewType ? columnType : undefined,
|
|
26
30
|
notNull: oldColumn.nullable !== newColumn.nullable ? !newColumn.nullable : undefined,
|
|
27
|
-
using:
|
|
31
|
+
using: hasNewSequence
|
|
32
|
+
? `COALESCE(${usingCast}, nextval(PG_GET_SERIAL_SEQUENCE(${escapeValue(entity.tableName)}, ${escapeValue(oldColumn.columnName)})))`
|
|
33
|
+
: hasNewType
|
|
34
|
+
? usingCast
|
|
35
|
+
: undefined,
|
|
28
36
|
sequenceGenerated: oldColumn.sequence && !newColumn.sequence ? false : (!oldColumn.sequence ? newColumn.sequence : undefined),
|
|
29
37
|
})
|
|
30
38
|
|
|
@@ -79,7 +87,7 @@ type SequenceDefinitionAlter =
|
|
|
79
87
|
}
|
|
80
88
|
|
|
81
89
|
type ColumnDefinitionAlter =
|
|
82
|
-
& Model.AnyColumn
|
|
90
|
+
& Omit<Model.AnyColumn, 'sequence' | 'columnName' | 'name'>
|
|
83
91
|
& {
|
|
84
92
|
sequence?: SequenceDefinitionAlter
|
|
85
93
|
}
|
|
@@ -95,22 +103,23 @@ export const updateColumnDefinitionModification = createModificationType({
|
|
|
95
103
|
handler: UpdateColumnDefinitionModificationHandler,
|
|
96
104
|
})
|
|
97
105
|
|
|
98
|
-
export class UpdateColumnDefinitionDiffer implements Differ {
|
|
106
|
+
export class UpdateColumnDefinitionDiffer implements Differ<UpdateColumnDefinitionModificationData> {
|
|
99
107
|
createDiff(originalSchema: Schema, updatedSchema: Schema) {
|
|
100
108
|
return updateColumns(originalSchema, updatedSchema, ({ originalColumn, updatedColumn, updatedEntity }) => {
|
|
101
109
|
const {
|
|
102
110
|
name: {},
|
|
103
111
|
columnName: {},
|
|
104
112
|
...updatedDefinition
|
|
105
|
-
} = updatedColumn
|
|
113
|
+
} = updatedColumn
|
|
106
114
|
const {
|
|
107
115
|
name: {},
|
|
108
116
|
columnName: {},
|
|
109
117
|
...originalDefinition
|
|
110
|
-
} = originalColumn
|
|
118
|
+
} = originalColumn
|
|
111
119
|
if (deepEqual(updatedDefinition, originalDefinition)) {
|
|
112
120
|
return undefined
|
|
113
121
|
}
|
|
122
|
+
|
|
114
123
|
return updateColumnDefinitionModification.createModification({
|
|
115
124
|
entityName: updatedEntity.name,
|
|
116
125
|
fieldName: updatedColumn.name,
|
|
@@ -1,9 +1,8 @@
|
|
|
1
1
|
import { Differ } from '../ModificationHandler'
|
|
2
|
-
import {
|
|
2
|
+
import { Schema } from '@contember/schema'
|
|
3
3
|
import deepEqual from 'fast-deep-equal'
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
import { Migration } from '../../Migration'
|
|
4
|
+
import { cascadeRemoveDependantViews } from '../utils/viewDependencies'
|
|
5
|
+
import { UpdateColumnDefinitionDiffer } from '../columns'
|
|
7
6
|
|
|
8
7
|
export class RemoveChangedViewDiffer implements Differ {
|
|
9
8
|
constructor() {
|
|
@@ -18,25 +17,13 @@ export class RemoveChangedViewDiffer implements Differ {
|
|
|
18
17
|
}
|
|
19
18
|
return !deepEqual(updatedEntity.view, it.view)
|
|
20
19
|
})
|
|
21
|
-
|
|
20
|
+
const columnDiffer = new UpdateColumnDefinitionDiffer()
|
|
21
|
+
const columnChanges = columnDiffer.createDiff(originalSchema, updatedSchema)
|
|
22
|
+
if (changedViews.length === 0 && columnChanges.length === 0) {
|
|
22
23
|
return []
|
|
23
24
|
}
|
|
24
|
-
const
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
const removeCascade = (entity: Model.Entity) => {
|
|
28
|
-
if (removed.has(entity.name)) {
|
|
29
|
-
return
|
|
30
|
-
}
|
|
31
|
-
removed.add(entity.name)
|
|
32
|
-
for (const dependant of dependants.get(entity.name) ?? []) {
|
|
33
|
-
removeCascade(dependant)
|
|
34
|
-
}
|
|
35
|
-
modifications.push(removeEntityModification.createModification({ entityName: entity.name }))
|
|
36
|
-
}
|
|
37
|
-
for (const changed of changedViews) {
|
|
38
|
-
removeCascade(changed)
|
|
39
|
-
}
|
|
40
|
-
return modifications
|
|
25
|
+
const changedColumnsEntities = Array.from(new Set(columnChanges.map(it => it.entityName)))
|
|
26
|
+
.map(it => originalSchema.model.entities[it])
|
|
27
|
+
return cascadeRemoveDependantViews(originalSchema.model, [...changedViews, ...changedColumnsEntities])
|
|
41
28
|
}
|
|
42
29
|
}
|
|
@@ -20,11 +20,12 @@ import {
|
|
|
20
20
|
import { VERSION_ACL_PATCH, VERSION_REMOVE_REFERENCING_RELATIONS } from '../ModificationVersions'
|
|
21
21
|
import { isRelation, PredicateDefinitionProcessor } from '@contember/schema-utils'
|
|
22
22
|
import { removeFieldModification } from '../fields'
|
|
23
|
+
import { SchemaWithMeta } from '../utils/schemaMeta'
|
|
23
24
|
|
|
24
25
|
export class RemoveEntityModificationHandler implements ModificationHandler<RemoveEntityModificationData> {
|
|
25
26
|
constructor(
|
|
26
27
|
private readonly data: RemoveEntityModificationData,
|
|
27
|
-
private readonly schema:
|
|
28
|
+
private readonly schema: SchemaWithMeta,
|
|
28
29
|
private readonly options: ModificationHandlerOptions,
|
|
29
30
|
) {}
|
|
30
31
|
|
|
@@ -19,13 +19,14 @@ import { NoopModification } from '../NoopModification'
|
|
|
19
19
|
import { renameConstraintSchemaUpdater, renameConstraintsSqlBuilder } from '../utils/renameConstraintsHelper'
|
|
20
20
|
import { changeValue } from '../utils/valueUtils'
|
|
21
21
|
import { updateEntityTableNameModification } from './UpdateEntityTableNameModification'
|
|
22
|
+
import { SchemaWithMeta } from '../utils/schemaMeta'
|
|
22
23
|
|
|
23
24
|
export class UpdateEntityNameModificationHandler implements ModificationHandler<UpdateEntityNameModificationData> {
|
|
24
25
|
private subModification: ModificationHandler<any>
|
|
25
26
|
|
|
26
27
|
constructor(
|
|
27
28
|
private readonly data: UpdateEntityNameModificationData,
|
|
28
|
-
private readonly schema:
|
|
29
|
+
private readonly schema: SchemaWithMeta,
|
|
29
30
|
private readonly options: ModificationHandlerOptions,
|
|
30
31
|
) {
|
|
31
32
|
this.subModification = data.tableName
|
|
@@ -20,13 +20,14 @@ import { renameConstraintSchemaUpdater, renameConstraintsSqlBuilder } from '../u
|
|
|
20
20
|
import { changeValue } from '../utils/valueUtils'
|
|
21
21
|
import { updateColumnNameModification } from '../columns'
|
|
22
22
|
import { NoopModification } from '../NoopModification'
|
|
23
|
+
import { SchemaWithMeta } from '../utils/schemaMeta'
|
|
23
24
|
|
|
24
25
|
export class UpdateFieldNameModificationHandler implements ModificationHandler<UpdateFieldNameModificationData> {
|
|
25
26
|
private renameColumnSubModification: ModificationHandler<any> = new NoopModification()
|
|
26
27
|
|
|
27
28
|
constructor(
|
|
28
29
|
private readonly data: UpdateFieldNameModificationData,
|
|
29
|
-
private readonly schema:
|
|
30
|
+
private readonly schema: SchemaWithMeta,
|
|
30
31
|
private readonly options: ModificationHandlerOptions,
|
|
31
32
|
) {
|
|
32
33
|
if (this.data.columnName) {
|
|
@@ -1,25 +1,33 @@
|
|
|
1
1
|
import { MigrationBuilder } from '@contember/database-migrations'
|
|
2
2
|
import { Model, Schema } from '@contember/schema'
|
|
3
|
-
import {
|
|
3
|
+
import {
|
|
4
|
+
addField,
|
|
5
|
+
addTakenIndexName,
|
|
6
|
+
SchemaUpdater,
|
|
7
|
+
updateEntity,
|
|
8
|
+
updateModel,
|
|
9
|
+
updateSchema,
|
|
10
|
+
} from '../utils/schemaUpdateUtils'
|
|
4
11
|
import {
|
|
5
12
|
createModificationType,
|
|
6
13
|
Differ,
|
|
7
14
|
ModificationHandler,
|
|
8
15
|
ModificationHandlerOptions,
|
|
9
16
|
} from '../ModificationHandler'
|
|
10
|
-
import { isInverseRelation, isOwningRelation } from '@contember/schema-utils'
|
|
17
|
+
import { isInverseRelation, isOwningRelation, NamingHelper } from '@contember/schema-utils'
|
|
11
18
|
import { updateRelations } from '../utils/diffUtils'
|
|
12
19
|
import { createJunctionTableSql } from '../utils/createJunctionTable'
|
|
13
20
|
import { wrapIdentifier } from '@contember/database'
|
|
14
21
|
import { normalizeManyHasManyRelation, PartialManyHasManyRelation } from './normalization'
|
|
15
22
|
import { updateFieldNameModification } from '../fields'
|
|
23
|
+
import { SchemaWithMeta } from '../utils/schemaMeta'
|
|
16
24
|
|
|
17
25
|
export class ConvertOneHasManyToManyHasManyRelationModificationHandler implements ModificationHandler<ConvertOneHasManyToManyHasManyRelationModificationData> {
|
|
18
26
|
private subModification: ModificationHandler<any>
|
|
19
27
|
|
|
20
28
|
constructor(
|
|
21
29
|
private readonly data: ConvertOneHasManyToManyHasManyRelationModificationData,
|
|
22
|
-
private readonly schema:
|
|
30
|
+
private readonly schema: SchemaWithMeta,
|
|
23
31
|
private readonly options: ModificationHandlerOptions,
|
|
24
32
|
) {
|
|
25
33
|
this.subModification = updateFieldNameModification.createHandler(
|
|
@@ -38,7 +46,7 @@ export class ConvertOneHasManyToManyHasManyRelationModificationHandler implement
|
|
|
38
46
|
const { relation: oldRelation } = this.getRelation()
|
|
39
47
|
const entity = this.schema.model.entities[this.data.entityName]
|
|
40
48
|
|
|
41
|
-
createJunctionTableSql(builder, this.options.systemSchema, entity, targetEntity, normalizeManyHasManyRelation(this.data.owningSide))
|
|
49
|
+
createJunctionTableSql(builder, this.options.systemSchema, this.schema, entity, targetEntity, normalizeManyHasManyRelation(this.data.owningSide))
|
|
42
50
|
const joiningTable = this.data.owningSide.joiningTable
|
|
43
51
|
builder.sql(`
|
|
44
52
|
INSERT INTO ${wrapIdentifier(joiningTable.tableName)} (
|
|
@@ -58,6 +66,7 @@ export class ConvertOneHasManyToManyHasManyRelationModificationHandler implement
|
|
|
58
66
|
this.subModification.getSchemaUpdater(),
|
|
59
67
|
updateModel(updateEntity(entityName, addField(normalizeManyHasManyRelation(this.data.owningSide)))),
|
|
60
68
|
this.data.inverseSide ? updateModel(updateEntity(this.data.owningSide.target, addField(this.data.inverseSide))) : undefined,
|
|
69
|
+
addTakenIndexName(NamingHelper.createJunctionTablePrimaryConstraintName(this.data.owningSide.joiningTable.tableName)),
|
|
61
70
|
)
|
|
62
71
|
}
|
|
63
72
|
|
|
@@ -1,6 +1,13 @@
|
|
|
1
1
|
import { MigrationBuilder } from '@contember/database-migrations'
|
|
2
2
|
import { Model, Schema } from '@contember/schema'
|
|
3
|
-
import {
|
|
3
|
+
import {
|
|
4
|
+
addTakenIndexName,
|
|
5
|
+
SchemaUpdater,
|
|
6
|
+
updateEntity,
|
|
7
|
+
updateField,
|
|
8
|
+
updateModel,
|
|
9
|
+
updateSchema,
|
|
10
|
+
} from '../utils/schemaUpdateUtils'
|
|
4
11
|
import {
|
|
5
12
|
createModificationType,
|
|
6
13
|
Differ,
|
|
@@ -11,13 +18,14 @@ import { isOwningRelation, NamingHelper } from '@contember/schema-utils'
|
|
|
11
18
|
import { updateRelations } from '../utils/diffUtils'
|
|
12
19
|
import { NoopModification } from '../NoopModification'
|
|
13
20
|
import { updateFieldNameModification } from '../fields'
|
|
21
|
+
import { resolveIndexName, SchemaWithMeta } from '../utils/schemaMeta'
|
|
14
22
|
|
|
15
23
|
export class ConvertOneToManyRelationModificationHandler implements ModificationHandler<ConvertOneToManyRelationModificationData> {
|
|
16
24
|
private subModification: ModificationHandler<any>
|
|
17
25
|
|
|
18
26
|
constructor(
|
|
19
27
|
private readonly data: ConvertOneToManyRelationModificationData,
|
|
20
|
-
private readonly schema:
|
|
28
|
+
private readonly schema: SchemaWithMeta,
|
|
21
29
|
private readonly options: ModificationHandlerOptions,
|
|
22
30
|
) {
|
|
23
31
|
const { relation } = this.getRelation()
|
|
@@ -36,7 +44,12 @@ export class ConvertOneToManyRelationModificationHandler implements Modification
|
|
|
36
44
|
|
|
37
45
|
public createSql(builder: MigrationBuilder): void {
|
|
38
46
|
const { entity, relation } = this.getRelation()
|
|
39
|
-
|
|
47
|
+
const columnName = relation.joiningColumn.columnName
|
|
48
|
+
const proposedIndexName = NamingHelper.createForeignKeyIndexName(entity.tableName, columnName)
|
|
49
|
+
const indexName = resolveIndexName(this.schema, proposedIndexName)
|
|
50
|
+
builder.addIndex(entity.tableName, columnName, {
|
|
51
|
+
name: indexName,
|
|
52
|
+
})
|
|
40
53
|
const uniqueConstraintName = NamingHelper.createUniqueConstraintName(entity.name, [relation.name])
|
|
41
54
|
builder.dropConstraint(entity.tableName, uniqueConstraintName)
|
|
42
55
|
this.subModification.createSql(builder)
|
|
@@ -45,6 +58,8 @@ export class ConvertOneToManyRelationModificationHandler implements Modification
|
|
|
45
58
|
public getSchemaUpdater(): SchemaUpdater {
|
|
46
59
|
const { relation } = this.getRelation()
|
|
47
60
|
const { entityName, fieldName } = this.data
|
|
61
|
+
const entity = this.schema.model.entities[this.data.entityName]
|
|
62
|
+
const field = entity.fields[fieldName] as Model.OneHasOneOwningRelation
|
|
48
63
|
return updateSchema(
|
|
49
64
|
updateModel(
|
|
50
65
|
updateEntity(
|
|
@@ -72,6 +87,7 @@ export class ConvertOneToManyRelationModificationHandler implements Modification
|
|
|
72
87
|
),
|
|
73
88
|
),
|
|
74
89
|
) : undefined,
|
|
90
|
+
addTakenIndexName(NamingHelper.createForeignKeyIndexName(entity.tableName, field.joiningColumn.columnName)),
|
|
75
91
|
)
|
|
76
92
|
}
|
|
77
93
|
|
|
@@ -7,7 +7,14 @@ import {
|
|
|
7
7
|
NamingHelper,
|
|
8
8
|
} from '@contember/schema-utils'
|
|
9
9
|
import { MigrationBuilder } from '@contember/database-migrations'
|
|
10
|
-
import {
|
|
10
|
+
import {
|
|
11
|
+
addField,
|
|
12
|
+
addTakenIndexName,
|
|
13
|
+
SchemaUpdater,
|
|
14
|
+
updateEntity,
|
|
15
|
+
updateModel,
|
|
16
|
+
updateSchema,
|
|
17
|
+
} from '../utils/schemaUpdateUtils'
|
|
11
18
|
import {
|
|
12
19
|
createModificationType,
|
|
13
20
|
Differ,
|
|
@@ -19,13 +26,14 @@ import { createFields } from '../utils/diffUtils'
|
|
|
19
26
|
import { getPrimaryColumnType } from '../utils/getPrimaryColumnType'
|
|
20
27
|
import { createJunctionTableSql } from '../utils/createJunctionTable'
|
|
21
28
|
import { normalizeManyHasManyRelation, PartialManyHasManyRelation } from './normalization'
|
|
29
|
+
import { resolveIndexName, SchemaWithMeta } from '../utils/schemaMeta'
|
|
22
30
|
|
|
23
31
|
|
|
24
32
|
export class CreateRelationModificationHandler implements ModificationHandler<CreateRelationModificationData> {
|
|
25
33
|
|
|
26
34
|
constructor(
|
|
27
35
|
private readonly data: CreateRelationModificationData,
|
|
28
|
-
private readonly schema:
|
|
36
|
+
private readonly schema: SchemaWithMeta,
|
|
29
37
|
private readonly options: ModificationHandlerOptions,
|
|
30
38
|
) {}
|
|
31
39
|
|
|
@@ -61,7 +69,12 @@ export class CreateRelationModificationHandler implements ModificationHandler<Cr
|
|
|
61
69
|
acceptRelationTypeVisitor(this.schema.model, entity, this.getNormalizedOwningSide(), {
|
|
62
70
|
visitManyHasOne: ({ relation }) => {
|
|
63
71
|
createOwningSide(relation)
|
|
64
|
-
|
|
72
|
+
const columnName = relation.joiningColumn.columnName
|
|
73
|
+
const proposedIndexName = NamingHelper.createForeignKeyIndexName(entity.tableName, columnName)
|
|
74
|
+
const indexName = resolveIndexName(this.schema, proposedIndexName)
|
|
75
|
+
builder.addIndex(entity.tableName, columnName, {
|
|
76
|
+
name: indexName,
|
|
77
|
+
})
|
|
65
78
|
},
|
|
66
79
|
visitOneHasMany: () => {},
|
|
67
80
|
visitOneHasOneOwning: ({ relation }) => {
|
|
@@ -71,17 +84,26 @@ export class CreateRelationModificationHandler implements ModificationHandler<Cr
|
|
|
71
84
|
},
|
|
72
85
|
visitOneHasOneInverse: () => {},
|
|
73
86
|
visitManyHasManyOwning: ({ relation }) => {
|
|
74
|
-
createJunctionTableSql(builder, this.options.systemSchema,
|
|
87
|
+
createJunctionTableSql(builder, this.options.systemSchema, this.schema, entity, targetEntity, relation)
|
|
75
88
|
},
|
|
76
89
|
visitManyHasManyInverse: () => {},
|
|
77
90
|
})
|
|
78
91
|
}
|
|
79
92
|
|
|
80
93
|
public getSchemaUpdater(): SchemaUpdater {
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
94
|
+
const entity = this.schema.model.entities[this.data.entityName]
|
|
95
|
+
return updateSchema(
|
|
96
|
+
updateModel(
|
|
97
|
+
updateEntity(this.data.entityName, addField(this.getNormalizedOwningSide())),
|
|
98
|
+
this.data.inverseSide !== undefined
|
|
99
|
+
? updateEntity(this.data.owningSide.target, addField(this.data.inverseSide))
|
|
100
|
+
: undefined,
|
|
101
|
+
),
|
|
102
|
+
this.data.owningSide.type === Model.RelationType.ManyHasOne
|
|
103
|
+
? addTakenIndexName(NamingHelper.createForeignKeyIndexName(entity.tableName, this.data.owningSide.joiningColumn.columnName))
|
|
104
|
+
: undefined,
|
|
105
|
+
this.data.owningSide.type === Model.RelationType.ManyHasMany && isOwningRelation(this.data.owningSide)
|
|
106
|
+
? addTakenIndexName(NamingHelper.createJunctionTablePrimaryConstraintName(this.data.owningSide.joiningTable.tableName))
|
|
85
107
|
: undefined,
|
|
86
108
|
)
|
|
87
109
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Model } from '@contember/schema'
|
|
2
2
|
|
|
3
|
-
export const getColumnSqlType = (column: Model.AnyColumn) => column.type === Model.ColumnType.Enum
|
|
3
|
+
export const getColumnSqlType = (column: Pick<Model.AnyColumn, 'type' | 'columnType'>) => column.type === Model.ColumnType.Enum
|
|
4
4
|
? `"${column.columnType}"`
|
|
5
5
|
: column.columnType
|
|
@@ -2,10 +2,12 @@ import { createEventTrigger, createEventTrxTrigger } from './sqlUpdateUtils'
|
|
|
2
2
|
import { MigrationBuilder } from '@contember/database-migrations'
|
|
3
3
|
import { Model } from '@contember/schema'
|
|
4
4
|
import { getPrimaryColumnType } from './getPrimaryColumnType'
|
|
5
|
+
import { resolveIndexName, SchemaWithMeta } from './schemaMeta'
|
|
5
6
|
|
|
6
7
|
export const createJunctionTableSql = (
|
|
7
8
|
builder: MigrationBuilder,
|
|
8
9
|
systemSchema: string,
|
|
10
|
+
schema: SchemaWithMeta,
|
|
9
11
|
entity: Model.Entity,
|
|
10
12
|
targetEntity: Model.Entity,
|
|
11
13
|
relation: Model.ManyHasManyOwningRelation,
|
|
@@ -30,12 +32,12 @@ export const createJunctionTableSql = (
|
|
|
30
32
|
onDelete: 'CASCADE',
|
|
31
33
|
},
|
|
32
34
|
},
|
|
33
|
-
{
|
|
34
|
-
constraints: {
|
|
35
|
-
primaryKey: primaryColumns,
|
|
36
|
-
},
|
|
37
|
-
},
|
|
38
35
|
)
|
|
36
|
+
const proposedIndexName = `${relation.joiningTable.tableName}_pkey`
|
|
37
|
+
const indexName = resolveIndexName(schema, proposedIndexName)
|
|
38
|
+
builder.addConstraint(relation.joiningTable.tableName, indexName, {
|
|
39
|
+
primaryKey: primaryColumns,
|
|
40
|
+
})
|
|
39
41
|
if (relation.joiningTable.eventLog.enabled) {
|
|
40
42
|
createEventTrigger(builder, systemSchema, relation.joiningTable.tableName, primaryColumns)
|
|
41
43
|
createEventTrxTrigger(builder, systemSchema, relation.joiningTable.tableName)
|
|
@@ -4,7 +4,7 @@ import { isColumn, isRelation } from '@contember/schema-utils'
|
|
|
4
4
|
import { isDefined } from '../../utils/isDefined'
|
|
5
5
|
import deepEqual from 'fast-deep-equal'
|
|
6
6
|
|
|
7
|
-
export const updateFields = (
|
|
7
|
+
export const updateFields = <Data = { [field: string]: any }>(
|
|
8
8
|
originalSchema: Schema,
|
|
9
9
|
updatedSchema: Schema,
|
|
10
10
|
modificationGenerator: (args: {
|
|
@@ -12,8 +12,8 @@ export const updateFields = (
|
|
|
12
12
|
updatedEntity: Model.Entity
|
|
13
13
|
originalField: Model.AnyField
|
|
14
14
|
updatedField: Model.AnyField
|
|
15
|
-
}) => Migration.Modification | Migration.Modification[] | undefined,
|
|
16
|
-
): Migration.Modification[] => {
|
|
15
|
+
}) => Migration.Modification<Data> | Migration.Modification<Data>[] | undefined,
|
|
16
|
+
): Migration.Modification<Data>[] => {
|
|
17
17
|
return Object.values(updatedSchema.model.entities)
|
|
18
18
|
.filter(({ name }) => originalSchema.model.entities[name])
|
|
19
19
|
.flatMap(updatedEntity => {
|
|
@@ -43,7 +43,7 @@ export const updateFields = (
|
|
|
43
43
|
})
|
|
44
44
|
}
|
|
45
45
|
|
|
46
|
-
export const updateColumns = (
|
|
46
|
+
export const updateColumns = <Data = { [field: string]: any }>(
|
|
47
47
|
originalSchema: Schema,
|
|
48
48
|
updatedSchema: Schema,
|
|
49
49
|
modificationGenerator: (args: {
|
|
@@ -51,8 +51,8 @@ export const updateColumns = (
|
|
|
51
51
|
originalColumn: Model.AnyColumn
|
|
52
52
|
updatedEntity: Model.Entity
|
|
53
53
|
updatedColumn: Model.AnyColumn
|
|
54
|
-
}) => Migration.Modification | undefined,
|
|
55
|
-
) => {
|
|
54
|
+
}) => Migration.Modification<Data> | undefined,
|
|
55
|
+
): Migration.Modification<Data>[] => {
|
|
56
56
|
return updateFields(
|
|
57
57
|
originalSchema,
|
|
58
58
|
updatedSchema,
|
|
@@ -70,7 +70,7 @@ export const updateColumns = (
|
|
|
70
70
|
)
|
|
71
71
|
}
|
|
72
72
|
|
|
73
|
-
export const updateRelations = (
|
|
73
|
+
export const updateRelations = <Data = { [field: string]: any }>(
|
|
74
74
|
originalSchema: Schema,
|
|
75
75
|
updatedSchema: Schema,
|
|
76
76
|
modificationGenerator: (args: {
|
|
@@ -78,8 +78,8 @@ export const updateRelations = (
|
|
|
78
78
|
originalRelation: Model.AnyRelation
|
|
79
79
|
updatedEntity: Model.Entity
|
|
80
80
|
updatedRelation: Model.AnyRelation
|
|
81
|
-
}) => Migration.Modification | undefined,
|
|
82
|
-
) => {
|
|
81
|
+
}) => Migration.Modification<Data> | undefined,
|
|
82
|
+
): Migration.Modification<Data>[] => {
|
|
83
83
|
return updateFields(
|
|
84
84
|
originalSchema,
|
|
85
85
|
updatedSchema,
|
|
@@ -97,15 +97,15 @@ export const updateRelations = (
|
|
|
97
97
|
)
|
|
98
98
|
}
|
|
99
99
|
|
|
100
|
-
export const createFields = (
|
|
100
|
+
export const createFields = <Data = { [field: string]: any }>(
|
|
101
101
|
originalSchema: Schema,
|
|
102
102
|
updatedSchema: Schema,
|
|
103
103
|
modificationGenerator: (args: {
|
|
104
104
|
originalEntity: Model.Entity
|
|
105
105
|
updatedEntity: Model.Entity
|
|
106
106
|
newField: Model.AnyField
|
|
107
|
-
}) => Migration.Modification | undefined,
|
|
108
|
-
) => {
|
|
107
|
+
}) => Migration.Modification<Data> | undefined,
|
|
108
|
+
): Migration.Modification<Data>[] => {
|
|
109
109
|
return Object.values(updatedSchema.model.entities)
|
|
110
110
|
.filter(({ name }) => originalSchema.model.entities[name])
|
|
111
111
|
.flatMap(updatedEntity => {
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { Schema } from '@contember/schema'
|
|
2
|
+
|
|
3
|
+
export type SchemaWithMeta =
|
|
4
|
+
& Schema
|
|
5
|
+
& {
|
|
6
|
+
meta?: {
|
|
7
|
+
takenIndexNames: Record<string, true>
|
|
8
|
+
}
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export const resolveIndexName = (schema: SchemaWithMeta, indexName: string): string => {
|
|
12
|
+
for (let i = 0; ; i++) {
|
|
13
|
+
const name = indexName + (i === 0 ? '' : `${i}`)
|
|
14
|
+
if (!schema.meta || !(name in schema.meta.takenIndexNames)) {
|
|
15
|
+
return name
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
}
|
|
@@ -3,8 +3,10 @@ import { SchemaUpdateError } from '../exceptions'
|
|
|
3
3
|
import { isDefined } from '../../utils/isDefined'
|
|
4
4
|
import { isInverseRelation, isOwningRelation, isRelation, PredicateDefinitionProcessor } from '@contember/schema-utils'
|
|
5
5
|
import { VERSION_ACL_PATCH, VERSION_REMOVE_RELATION_INVERSE_SIDE } from '../ModificationVersions'
|
|
6
|
+
import { resolveIndexName, SchemaWithMeta } from './schemaMeta'
|
|
6
7
|
|
|
7
|
-
|
|
8
|
+
|
|
9
|
+
export type SchemaUpdater = (args: { schema: SchemaWithMeta }) => SchemaWithMeta
|
|
8
10
|
export type ModelUpdater = (args: { schema: Schema; model: Model.Schema }) => Model.Schema
|
|
9
11
|
export type EntityUpdater = (args: { schema: Schema; model: Model.Schema; entity: Model.Entity }) => Model.Entity
|
|
10
12
|
export type FieldUpdater<In extends Model.AnyField, Out extends Model.AnyField> = (args: {
|
|
@@ -281,3 +283,14 @@ export const removeField = (entityName: string, fieldName: string, version: numb
|
|
|
281
283
|
)({ schema })
|
|
282
284
|
}
|
|
283
285
|
}
|
|
286
|
+
|
|
287
|
+
export const addTakenIndexName = (indexName: string): SchemaUpdater => ({ schema }) => ({
|
|
288
|
+
...schema,
|
|
289
|
+
meta: {
|
|
290
|
+
...schema.meta,
|
|
291
|
+
takenIndexNames: {
|
|
292
|
+
...schema.meta?.takenIndexNames,
|
|
293
|
+
[resolveIndexName(schema, indexName)]: true,
|
|
294
|
+
},
|
|
295
|
+
},
|
|
296
|
+
})
|
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
import { Model } from '@contember/schema'
|
|
2
|
+
import { Migration } from '../../Migration'
|
|
3
|
+
import { removeEntityModification } from '../entities'
|
|
2
4
|
|
|
3
|
-
type
|
|
4
|
-
export const
|
|
5
|
-
const dependants:
|
|
5
|
+
type EntityDependantViews = Map<string, Set<Model.Entity>>
|
|
6
|
+
export const getEntityDependantViews = (model: Model.Schema): EntityDependantViews => {
|
|
7
|
+
const dependants: EntityDependantViews = new Map(Object.values(model.entities).map(it => [it.name, new Set()]))
|
|
6
8
|
for (const entity of Object.values(model.entities)) {
|
|
7
9
|
if (!entity.view?.dependencies?.length) {
|
|
8
10
|
continue
|
|
@@ -10,11 +12,32 @@ export const getViewDirectDependants = (model: Model.Schema): ViewDependants =>
|
|
|
10
12
|
for (const dependency of entity.view.dependencies) {
|
|
11
13
|
const entityDependants = dependants.get(dependency)
|
|
12
14
|
if (!entityDependants) {
|
|
13
|
-
|
|
14
|
-
continue
|
|
15
|
+
throw new Error()
|
|
15
16
|
}
|
|
16
17
|
entityDependants.add(entity)
|
|
17
18
|
}
|
|
18
19
|
}
|
|
19
20
|
return dependants
|
|
20
21
|
}
|
|
22
|
+
|
|
23
|
+
export const cascadeRemoveDependantViews = (model: Model.Schema, entities: Model.Entity[]): Migration.Modification[] => {
|
|
24
|
+
const removed = new Set<string>()
|
|
25
|
+
const dependants = getEntityDependantViews(model)
|
|
26
|
+
const modifications: Migration.Modification[] = []
|
|
27
|
+
const removeCascade = (entity: Model.Entity) => {
|
|
28
|
+
if (removed.has(entity.name)) {
|
|
29
|
+
return
|
|
30
|
+
}
|
|
31
|
+
removed.add(entity.name)
|
|
32
|
+
for (const dependant of dependants.get(entity.name) ?? []) {
|
|
33
|
+
removeCascade(dependant)
|
|
34
|
+
}
|
|
35
|
+
if (entity.view) {
|
|
36
|
+
modifications.push(removeEntityModification.createModification({ entityName: entity.name }))
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
for (const entity of entities) {
|
|
40
|
+
removeCascade(entity)
|
|
41
|
+
}
|
|
42
|
+
return modifications
|
|
43
|
+
}
|
|
@@ -64,9 +64,10 @@ testMigrations('convert one has many to many has many', {
|
|
|
64
64
|
sql: SQL`
|
|
65
65
|
CREATE TABLE "article_categories" (
|
|
66
66
|
"article_id" uuid NOT NULL REFERENCES "article"("id") ON DELETE CASCADE,
|
|
67
|
-
"category_id" uuid NOT NULL REFERENCES "category"("id") ON DELETE CASCADE
|
|
68
|
-
"article_categories_pkey" PRIMARY KEY ("article_id", "category_id")
|
|
67
|
+
"category_id" uuid NOT NULL REFERENCES "category"("id") ON DELETE CASCADE
|
|
69
68
|
);
|
|
69
|
+
ALTER TABLE "article_categories"
|
|
70
|
+
ADD CONSTRAINT "article_categories_pkey" PRIMARY KEY ("article_id", "category_id");
|
|
70
71
|
|
|
71
72
|
CREATE TRIGGER "log_event" AFTER INSERT OR UPDATE OR DELETE
|
|
72
73
|
ON "article_categories" FOR EACH ROW
|
|
@@ -90,9 +90,10 @@ testMigrations('create many has many relation (post with categories)', {
|
|
|
90
90
|
ADD "title" text;
|
|
91
91
|
CREATE TABLE "post_categories" (
|
|
92
92
|
"post_id" uuid NOT NULL REFERENCES "post"("id") ON DELETE CASCADE,
|
|
93
|
-
"category_id" uuid NOT NULL REFERENCES "category"("id") ON DELETE CASCADE
|
|
94
|
-
CONSTRAINT "post_categories_pkey" PRIMARY KEY ("post_id", "category_id")
|
|
93
|
+
"category_id" uuid NOT NULL REFERENCES "category"("id") ON DELETE CASCADE
|
|
95
94
|
);
|
|
95
|
+
ALTER TABLE "post_categories"
|
|
96
|
+
ADD CONSTRAINT "post_categories_pkey" PRIMARY KEY ("post_id", "category_id");
|
|
96
97
|
CREATE TRIGGER "log_event"
|
|
97
98
|
AFTER INSERT OR UPDATE OR DELETE
|
|
98
99
|
ON "post_categories"
|