@contember/schema-migrations 1.2.1 → 1.3.0-alpha.2
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/MigrationCreator.js +2 -2
- package/dist/src/MigrationCreator.js.map +1 -1
- package/dist/src/MigrationFilesManager.js +2 -2
- package/dist/src/MigrationFilesManager.js.map +1 -1
- package/dist/src/MigrationsResolver.js +3 -3
- package/dist/src/MigrationsResolver.js.map +1 -1
- package/dist/src/SchemaDiffer.d.ts.map +1 -1
- package/dist/src/SchemaDiffer.js +1 -0
- package/dist/src/SchemaDiffer.js.map +1 -1
- package/dist/src/index.d.ts +1 -1
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.js +3 -1
- package/dist/src/index.js.map +1 -1
- package/dist/src/modifications/ModificationHandlerFactory.d.ts.map +1 -1
- package/dist/src/modifications/ModificationHandlerFactory.js +2 -0
- package/dist/src/modifications/ModificationHandlerFactory.js.map +1 -1
- package/dist/src/modifications/ModificationVersions.d.ts +2 -1
- package/dist/src/modifications/ModificationVersions.d.ts.map +1 -1
- package/dist/src/modifications/ModificationVersions.js +3 -2
- package/dist/src/modifications/ModificationVersions.js.map +1 -1
- package/dist/src/modifications/entities/UpdateEntityNameModification.d.ts.map +1 -1
- package/dist/src/modifications/entities/UpdateEntityNameModification.js +15 -0
- package/dist/src/modifications/entities/UpdateEntityNameModification.js.map +1 -1
- package/dist/src/modifications/entities/UpdateEntityOrderByModification.d.ts +23 -0
- package/dist/src/modifications/entities/UpdateEntityOrderByModification.d.ts.map +1 -0
- package/dist/src/modifications/entities/UpdateEntityOrderByModification.js +63 -0
- package/dist/src/modifications/entities/UpdateEntityOrderByModification.js.map +1 -0
- package/dist/src/modifications/entities/index.d.ts +1 -0
- package/dist/src/modifications/entities/index.d.ts.map +1 -1
- package/dist/src/modifications/entities/index.js +1 -0
- package/dist/src/modifications/entities/index.js.map +1 -1
- package/dist/src/modifications/fields/UpdateFieldNameModification.d.ts.map +1 -1
- package/dist/src/modifications/fields/UpdateFieldNameModification.js +15 -0
- package/dist/src/modifications/fields/UpdateFieldNameModification.js.map +1 -1
- package/dist/src/modifications/relations/CreateRelationModification.d.ts.map +1 -1
- package/dist/src/modifications/relations/CreateRelationModification.js +2 -10
- package/dist/src/modifications/relations/CreateRelationModification.js.map +1 -1
- package/dist/src/modifications/relations/UpdateRelationOnDeleteModification.d.ts.map +1 -1
- package/dist/src/modifications/relations/UpdateRelationOnDeleteModification.js +20 -1
- package/dist/src/modifications/relations/UpdateRelationOnDeleteModification.js.map +1 -1
- package/dist/src/modifications/relations/helpers.d.ts +10 -0
- package/dist/src/modifications/relations/helpers.d.ts.map +1 -0
- package/dist/src/modifications/relations/helpers.js +26 -0
- package/dist/src/modifications/relations/helpers.js.map +1 -0
- package/dist/src/tsconfig.tsbuildinfo +1 -1
- package/dist/tests/cases/integration/createManyHasOne.test.js +1 -1
- package/dist/tests/cases/integration/createRelationInverseSide.test.js +1 -1
- package/dist/tests/cases/integration/createRelationInverseSide.test.js.map +1 -1
- package/dist/tests/cases/integration/takenIndexName.test.js +2 -2
- package/dist/tests/cases/integration/updateEntityName.test.js +20 -0
- package/dist/tests/cases/integration/updateEntityName.test.js.map +1 -1
- package/dist/tests/cases/integration/updateEntityOrderBy.test.d.ts +2 -0
- package/dist/tests/cases/integration/updateEntityOrderBy.test.d.ts.map +1 -0
- package/dist/tests/cases/integration/updateEntityOrderBy.test.js +57 -0
- package/dist/tests/cases/integration/updateEntityOrderBy.test.js.map +1 -0
- package/dist/tests/cases/integration/updateFieldName.test.js +21 -0
- package/dist/tests/cases/integration/updateFieldName.test.js.map +1 -1
- package/dist/tests/cases/integration/updateRelationOnDelete.test.js +2 -1
- package/dist/tests/cases/integration/updateRelationOnDelete.test.js.map +1 -1
- package/dist/tests/src/tests.d.ts.map +1 -1
- package/dist/tests/src/tests.js +4 -6
- package/dist/tests/src/tests.js.map +1 -1
- package/dist/tests/tsconfig.tsbuildinfo +1 -1
- package/package.json +7 -6
- package/src/MigrationCreator.ts +1 -1
- package/src/MigrationFilesManager.ts +1 -1
- package/src/MigrationsResolver.ts +1 -1
- package/src/SchemaDiffer.ts +2 -0
- package/src/index.ts +1 -1
- package/src/modifications/ModificationHandlerFactory.ts +2 -0
- package/src/modifications/ModificationVersions.ts +2 -1
- package/src/modifications/entities/UpdateEntityNameModification.ts +23 -2
- package/src/modifications/entities/UpdateEntityOrderByModification.ts +68 -0
- package/src/modifications/entities/index.ts +1 -0
- package/src/modifications/fields/UpdateFieldNameModification.ts +22 -1
- package/src/modifications/relations/CreateRelationModification.ts +2 -15
- package/src/modifications/relations/UpdateRelationOnDeleteModification.ts +20 -1
- package/src/modifications/relations/helpers.ts +34 -0
- package/src/tsconfig.json +5 -12
- package/tests/cases/integration/createManyHasOne.test.ts +1 -1
- package/tests/cases/integration/createRelationInverseSide.test.ts +1 -1
- package/tests/cases/integration/takenIndexName.test.ts +2 -2
- package/tests/cases/integration/updateEntityName.test.ts +21 -0
- package/tests/cases/integration/updateEntityOrderBy.test.ts +43 -0
- package/tests/cases/integration/updateFieldName.test.ts +22 -0
- package/tests/cases/integration/updateRelationOnDelete.test.ts +2 -1
- package/tests/src/tests.ts +5 -7
- package/tests/tsconfig.json +2 -6
- package/dist/src/MigrationVersionHelper.d.ts +0 -9
- package/dist/src/MigrationVersionHelper.d.ts.map +0 -1
- package/dist/src/MigrationVersionHelper.js +0 -45
- package/dist/src/MigrationVersionHelper.js.map +0 -1
- package/src/MigrationVersionHelper.ts +0 -46
|
@@ -31,6 +31,7 @@ import { patchValidationSchemaModification, updateValidationSchemaModification }
|
|
|
31
31
|
import { createIndexModification, removeIndexModification } from './indexes'
|
|
32
32
|
import { SchemaWithMeta } from './utils/schemaMeta'
|
|
33
33
|
import { updateSettingsModification } from './settings'
|
|
34
|
+
import { updateEntityOrderByModification } from './entities/UpdateEntityOrderByModification'
|
|
34
35
|
|
|
35
36
|
|
|
36
37
|
class ModificationHandlerFactory {
|
|
@@ -83,6 +84,7 @@ namespace ModificationHandlerFactory {
|
|
|
83
84
|
toggleEventLogModification,
|
|
84
85
|
toggleJunctionEventLogModification,
|
|
85
86
|
convertOneHasManyToManyHasManyRelationModification,
|
|
87
|
+
updateEntityOrderByModification,
|
|
86
88
|
]
|
|
87
89
|
|
|
88
90
|
export const defaultFactoryMap: HandlerMap<any> = Object.fromEntries(handlers.map(it => [it.id, it]))
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
export const VERSION_INITIAL = 1
|
|
2
|
-
export const VERSION_LATEST =
|
|
2
|
+
export const VERSION_LATEST = 4
|
|
3
3
|
|
|
4
4
|
export const VERSION_ACL_PATCH = 2
|
|
5
5
|
export const VERSION_UPDATE_CONSTRAINT_NAME = 2
|
|
6
6
|
export const VERSION_REMOVE_RELATION_INVERSE_SIDE = 3
|
|
7
7
|
export const VERSION_REMOVE_REFERENCING_RELATIONS = 3
|
|
8
|
+
export const VERSION_UPDATE_CONSTRAINT_NAME_ONE_HAS_ONE = 4
|
|
@@ -13,8 +13,12 @@ import {
|
|
|
13
13
|
} from '../utils/schemaUpdateUtils'
|
|
14
14
|
import { createModificationType, ModificationHandler, ModificationHandlerOptions } from '../ModificationHandler'
|
|
15
15
|
import { isIt } from '../../utils/isIt'
|
|
16
|
-
import {
|
|
17
|
-
|
|
16
|
+
import {
|
|
17
|
+
VERSION_ACL_PATCH,
|
|
18
|
+
VERSION_UPDATE_CONSTRAINT_NAME,
|
|
19
|
+
VERSION_UPDATE_CONSTRAINT_NAME_ONE_HAS_ONE,
|
|
20
|
+
} from '../ModificationVersions'
|
|
21
|
+
import { acceptEveryFieldVisitor, NamingHelper } from '@contember/schema-utils'
|
|
18
22
|
import { NoopModification } from '../NoopModification'
|
|
19
23
|
import { renameConstraintSchemaUpdater, renameConstraintsSqlBuilder } from '../utils/renameConstraintsHelper'
|
|
20
24
|
import { changeValue } from '../utils/valueUtils'
|
|
@@ -43,6 +47,23 @@ export class UpdateEntityNameModificationHandler implements ModificationHandler<
|
|
|
43
47
|
if (!entity.view && this.options.formatVersion >= VERSION_UPDATE_CONSTRAINT_NAME) {
|
|
44
48
|
renameConstraintsSqlBuilder(builder, entity, this.getNewConstraintName.bind(this))
|
|
45
49
|
}
|
|
50
|
+
|
|
51
|
+
if (this.options.formatVersion >= VERSION_UPDATE_CONSTRAINT_NAME_ONE_HAS_ONE) {
|
|
52
|
+
acceptEveryFieldVisitor(this.schema.model, this.data.entityName, {
|
|
53
|
+
visitColumn: () => {},
|
|
54
|
+
visitManyHasManyOwning: () => {},
|
|
55
|
+
visitManyHasManyInverse: () => {},
|
|
56
|
+
visitOneHasOneInverse: () => {},
|
|
57
|
+
visitManyHasOne: () => {},
|
|
58
|
+
visitOneHasMany: () => {},
|
|
59
|
+
visitOneHasOneOwning: ({ relation }) => {
|
|
60
|
+
const uniqueConstraintName = NamingHelper.createUniqueConstraintName(entity.name, [relation.name])
|
|
61
|
+
const newUniqueConstraintName = NamingHelper.createUniqueConstraintName(this.data.newEntityName, [relation.name])
|
|
62
|
+
builder.renameConstraint(entity.tableName, uniqueConstraintName, newUniqueConstraintName)
|
|
63
|
+
},
|
|
64
|
+
})
|
|
65
|
+
}
|
|
66
|
+
|
|
46
67
|
this.subModification.createSql(builder)
|
|
47
68
|
}
|
|
48
69
|
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import { MigrationBuilder } from '@contember/database-migrations'
|
|
2
|
+
import { Model, Schema } from '@contember/schema'
|
|
3
|
+
import { SchemaUpdater, updateEntity, updateModel } from '../utils/schemaUpdateUtils'
|
|
4
|
+
import { createModificationType, Differ, ModificationHandler } from '../ModificationHandler'
|
|
5
|
+
import deepEqual from 'fast-deep-equal'
|
|
6
|
+
|
|
7
|
+
export class UpdateEntityOrderByModificationHandler implements ModificationHandler<UpdateEntityOrderByModificationData> {
|
|
8
|
+
|
|
9
|
+
constructor(private readonly data: UpdateEntityOrderByModificationData, private readonly schema: Schema) { }
|
|
10
|
+
|
|
11
|
+
public createSql(builder: MigrationBuilder): void { }
|
|
12
|
+
|
|
13
|
+
public getSchemaUpdater(): SchemaUpdater {
|
|
14
|
+
const { entityName, orderBy } = this.data
|
|
15
|
+
return updateModel(
|
|
16
|
+
updateEntity(entityName, ({ entity }) => {
|
|
17
|
+
if (orderBy) {
|
|
18
|
+
return {
|
|
19
|
+
...entity,
|
|
20
|
+
orderBy,
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
const { orderBy: _, ...rest } = entity
|
|
24
|
+
return rest
|
|
25
|
+
}),
|
|
26
|
+
)
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
describe() {
|
|
30
|
+
return { message: `Update order-by of entity ${this.data.entityName}` }
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export interface UpdateEntityOrderByModificationData {
|
|
35
|
+
entityName: string
|
|
36
|
+
orderBy?: readonly Model.OrderBy[]
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
export const updateEntityOrderByModification = createModificationType({
|
|
40
|
+
id: 'updateEntityOrderBy',
|
|
41
|
+
handler: UpdateEntityOrderByModificationHandler,
|
|
42
|
+
})
|
|
43
|
+
|
|
44
|
+
export class UpdateEntityOrderByDiffer implements Differ {
|
|
45
|
+
createDiff(originalSchema: Schema, updatedSchema: Schema) {
|
|
46
|
+
return Object.values(updatedSchema.model.entities)
|
|
47
|
+
.flatMap(updatedEntity => {
|
|
48
|
+
const origEntity = originalSchema.model.entities[updatedEntity.name]
|
|
49
|
+
if (!origEntity) {
|
|
50
|
+
return []
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
if (!deepEqual(updatedEntity.orderBy ?? [], origEntity.orderBy ?? [])) {
|
|
54
|
+
if (updatedEntity.orderBy) {
|
|
55
|
+
return [updateEntityOrderByModification.createModification({
|
|
56
|
+
entityName: updatedEntity.name,
|
|
57
|
+
orderBy: updatedEntity.orderBy,
|
|
58
|
+
})]
|
|
59
|
+
}
|
|
60
|
+
return [updateEntityOrderByModification.createModification({
|
|
61
|
+
entityName: updatedEntity.name,
|
|
62
|
+
})]
|
|
63
|
+
}
|
|
64
|
+
return []
|
|
65
|
+
})
|
|
66
|
+
|
|
67
|
+
}
|
|
68
|
+
}
|
|
@@ -15,7 +15,11 @@ import {
|
|
|
15
15
|
} from '../utils/schemaUpdateUtils'
|
|
16
16
|
import { createModificationType, ModificationHandler, ModificationHandlerOptions } from '../ModificationHandler'
|
|
17
17
|
import { acceptFieldVisitor, NamingHelper, PredicateDefinitionProcessor } from '@contember/schema-utils'
|
|
18
|
-
import {
|
|
18
|
+
import {
|
|
19
|
+
VERSION_ACL_PATCH,
|
|
20
|
+
VERSION_UPDATE_CONSTRAINT_NAME,
|
|
21
|
+
VERSION_UPDATE_CONSTRAINT_NAME_ONE_HAS_ONE,
|
|
22
|
+
} from '../ModificationVersions'
|
|
19
23
|
import { renameConstraintSchemaUpdater, renameConstraintsSqlBuilder } from '../utils/renameConstraintsHelper'
|
|
20
24
|
import { changeValue } from '../utils/valueUtils'
|
|
21
25
|
import { updateColumnNameModification } from '../columns'
|
|
@@ -47,6 +51,23 @@ export class UpdateFieldNameModificationHandler implements ModificationHandler<U
|
|
|
47
51
|
if (this.options.formatVersion >= VERSION_UPDATE_CONSTRAINT_NAME) {
|
|
48
52
|
renameConstraintsSqlBuilder(builder, entity, this.getNewConstraintName.bind(this))
|
|
49
53
|
}
|
|
54
|
+
|
|
55
|
+
if (this.options.formatVersion >= VERSION_UPDATE_CONSTRAINT_NAME_ONE_HAS_ONE) {
|
|
56
|
+
acceptFieldVisitor(this.schema.model, this.data.entityName, this.data.fieldName, {
|
|
57
|
+
visitColumn: () => {},
|
|
58
|
+
visitManyHasManyOwning: () => {},
|
|
59
|
+
visitManyHasManyInverse: () => {},
|
|
60
|
+
visitOneHasOneInverse: () => {},
|
|
61
|
+
visitManyHasOne: () => {},
|
|
62
|
+
visitOneHasMany: () => {},
|
|
63
|
+
visitOneHasOneOwning: ({ relation }) => {
|
|
64
|
+
const uniqueConstraintName = NamingHelper.createUniqueConstraintName(entity.name, [relation.name])
|
|
65
|
+
const newUniqueConstraintName = NamingHelper.createUniqueConstraintName(entity.name, [this.data.newFieldName])
|
|
66
|
+
builder.renameConstraint(entity.tableName, uniqueConstraintName, newUniqueConstraintName)
|
|
67
|
+
},
|
|
68
|
+
})
|
|
69
|
+
}
|
|
70
|
+
|
|
50
71
|
this.renameColumnSubModification.createSql(builder)
|
|
51
72
|
}
|
|
52
73
|
|
|
@@ -27,6 +27,7 @@ import { getPrimaryColumnType } from '../utils/getPrimaryColumnType'
|
|
|
27
27
|
import { createJunctionTableSql } from '../utils/createJunctionTable'
|
|
28
28
|
import { normalizeManyHasManyRelation, PartialManyHasManyRelation } from './normalization'
|
|
29
29
|
import { resolveIndexName, SchemaWithMeta } from '../utils/schemaMeta'
|
|
30
|
+
import { addForeignKeyConstraint } from './helpers'
|
|
30
31
|
|
|
31
32
|
|
|
32
33
|
export class CreateRelationModificationHandler implements ModificationHandler<CreateRelationModificationData> {
|
|
@@ -50,21 +51,7 @@ export class CreateRelationModificationHandler implements ModificationHandler<Cr
|
|
|
50
51
|
notNull: !relation.nullable,
|
|
51
52
|
},
|
|
52
53
|
})
|
|
53
|
-
|
|
54
|
-
entity.tableName,
|
|
55
|
-
relation.joiningColumn.columnName,
|
|
56
|
-
targetEntity.tableName,
|
|
57
|
-
targetEntity.primaryColumn,
|
|
58
|
-
)
|
|
59
|
-
builder.addConstraint(entity.tableName, fkName, {
|
|
60
|
-
foreignKeys: {
|
|
61
|
-
columns: relation.joiningColumn.columnName,
|
|
62
|
-
references: `"${targetEntity.tableName}"("${targetEntity.primaryColumn}")`,
|
|
63
|
-
onDelete: 'NO ACTION',
|
|
64
|
-
},
|
|
65
|
-
deferrable: true,
|
|
66
|
-
deferred: false,
|
|
67
|
-
})
|
|
54
|
+
addForeignKeyConstraint({ builder, entity, targetEntity, relation })
|
|
68
55
|
}
|
|
69
56
|
acceptRelationTypeVisitor(this.schema.model, entity, this.getNormalizedOwningSide(), {
|
|
70
57
|
visitManyHasOne: ({ relation }) => {
|
|
@@ -4,11 +4,30 @@ import { SchemaUpdater, updateEntity, updateField, updateModel } from '../utils/
|
|
|
4
4
|
import { createModificationType, Differ, ModificationHandler } from '../ModificationHandler'
|
|
5
5
|
import { isIt } from '../../utils/isIt'
|
|
6
6
|
import { updateRelations } from '../utils/diffUtils'
|
|
7
|
+
import { acceptRelationTypeVisitor } from '@contember/schema-utils'
|
|
8
|
+
import { addForeignKeyConstraint } from './helpers'
|
|
7
9
|
|
|
8
10
|
export class UpdateRelationOnDeleteModificationHandler implements ModificationHandler<UpdateRelationOnDeleteModificationData> {
|
|
9
11
|
constructor(private readonly data: UpdateRelationOnDeleteModificationData, private readonly schema: Schema) {}
|
|
10
12
|
|
|
11
|
-
public createSql(builder: MigrationBuilder): void {
|
|
13
|
+
public createSql(builder: MigrationBuilder): void {
|
|
14
|
+
const entity = this.schema.model.entities[this.data.entityName]
|
|
15
|
+
if (entity.view) {
|
|
16
|
+
return
|
|
17
|
+
}
|
|
18
|
+
acceptRelationTypeVisitor(this.schema.model, entity, this.data.fieldName, {
|
|
19
|
+
visitManyHasOne: ({ entity, relation, targetEntity }) => {
|
|
20
|
+
addForeignKeyConstraint({ builder, entity, targetEntity, relation, recreate: true })
|
|
21
|
+
},
|
|
22
|
+
visitOneHasOneOwning: ({ entity, relation, targetEntity }) => {
|
|
23
|
+
addForeignKeyConstraint({ builder, entity, targetEntity, relation, recreate: true })
|
|
24
|
+
},
|
|
25
|
+
visitOneHasMany: () => {},
|
|
26
|
+
visitOneHasOneInverse: () => {},
|
|
27
|
+
visitManyHasManyOwning: () => {},
|
|
28
|
+
visitManyHasManyInverse: () => {},
|
|
29
|
+
})
|
|
30
|
+
}
|
|
12
31
|
|
|
13
32
|
public getSchemaUpdater(): SchemaUpdater {
|
|
14
33
|
const { entityName, fieldName, onDelete } = this.data
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { MigrationBuilder } from '@contember/database-migrations'
|
|
2
|
+
import { NamingHelper } from '@contember/schema-utils'
|
|
3
|
+
import { Model } from '@contember/schema'
|
|
4
|
+
|
|
5
|
+
export const addForeignKeyConstraint = ({ builder, entity, relation, targetEntity, recreate = false }: {
|
|
6
|
+
recreate?: boolean
|
|
7
|
+
builder: MigrationBuilder
|
|
8
|
+
entity: Model.Entity
|
|
9
|
+
targetEntity: Model.Entity
|
|
10
|
+
relation: Model.OneHasOneOwningRelation | Model.ManyHasOneRelation
|
|
11
|
+
}) => {
|
|
12
|
+
const fkName = NamingHelper.createForeignKeyName(
|
|
13
|
+
entity.tableName,
|
|
14
|
+
relation.joiningColumn.columnName,
|
|
15
|
+
targetEntity.tableName,
|
|
16
|
+
targetEntity.primaryColumn,
|
|
17
|
+
)
|
|
18
|
+
if (recreate) {
|
|
19
|
+
builder.dropConstraint(entity.tableName, fkName)
|
|
20
|
+
}
|
|
21
|
+
builder.addConstraint(entity.tableName, fkName, {
|
|
22
|
+
foreignKeys: {
|
|
23
|
+
columns: relation.joiningColumn.columnName,
|
|
24
|
+
references: `"${targetEntity.tableName}"("${targetEntity.primaryColumn}")`,
|
|
25
|
+
onDelete: ({
|
|
26
|
+
[Model.OnDelete.setNull]: 'SET NULL',
|
|
27
|
+
[Model.OnDelete.cascade]: 'CASCADE',
|
|
28
|
+
[Model.OnDelete.restrict]: 'NO ACTION',
|
|
29
|
+
} as const)[relation.joiningColumn.onDelete],
|
|
30
|
+
},
|
|
31
|
+
deferrable: true,
|
|
32
|
+
deferred: false,
|
|
33
|
+
})
|
|
34
|
+
}
|
package/src/tsconfig.json
CHANGED
|
@@ -6,17 +6,10 @@
|
|
|
6
6
|
"downlevelIteration": true
|
|
7
7
|
},
|
|
8
8
|
"references": [
|
|
9
|
-
{
|
|
10
|
-
|
|
11
|
-
},
|
|
12
|
-
{
|
|
13
|
-
|
|
14
|
-
},
|
|
15
|
-
{
|
|
16
|
-
"path": "../../schema/src"
|
|
17
|
-
},
|
|
18
|
-
{
|
|
19
|
-
"path": "../../schema-utils/src"
|
|
20
|
-
}
|
|
9
|
+
{ "path": "../../database/src" },
|
|
10
|
+
{ "path": "../../database-migrations/src" },
|
|
11
|
+
{ "path": "../../engine-common/src" },
|
|
12
|
+
{ "path": "../../schema/src" },
|
|
13
|
+
{ "path": "../../schema-utils/src" }
|
|
21
14
|
]
|
|
22
15
|
}
|
|
@@ -84,6 +84,6 @@ testMigrations('create many has one relation (post with author)', {
|
|
|
84
84
|
ALTER TABLE "post"
|
|
85
85
|
ADD "author_id" uuid;
|
|
86
86
|
ALTER TABLE "post"
|
|
87
|
-
ADD CONSTRAINT "fk_post_author_id_87ef9a" FOREIGN KEY ("author_id") REFERENCES "author"("id") ON DELETE
|
|
87
|
+
ADD CONSTRAINT "fk_post_author_id_87ef9a" FOREIGN KEY ("author_id") REFERENCES "author"("id") ON DELETE CASCADE DEFERRABLE INITIALLY IMMEDIATE;
|
|
88
88
|
CREATE INDEX "post_author_id_index" ON "post" ("author_id");`,
|
|
89
89
|
})
|
|
@@ -56,5 +56,5 @@ testMigrations('create inverse side relation together with changing onDelete beh
|
|
|
56
56
|
},
|
|
57
57
|
},
|
|
58
58
|
],
|
|
59
|
-
sql: SQL
|
|
59
|
+
sql: SQL`ALTER TABLE "post_locale" DROP CONSTRAINT "fk_post_locale_post_id_f3d2e5"; ALTER TABLE "post_locale" ADD CONSTRAINT "fk_post_locale_post_id_f3d2e5" FOREIGN KEY ("post_id") REFERENCES "post"("id") ON DELETE NO ACTION DEFERRABLE INITIALLY IMMEDIATE;`,
|
|
60
60
|
})
|
|
@@ -138,7 +138,7 @@ CREATE CONSTRAINT TRIGGER "log_event_trx"
|
|
|
138
138
|
ALTER TABLE "post"
|
|
139
139
|
ADD "author_id" uuid;
|
|
140
140
|
ALTER TABLE "post"
|
|
141
|
-
ADD CONSTRAINT "fk_post_author_id_87ef9a" FOREIGN KEY ("author_id") REFERENCES "author"("id") ON DELETE
|
|
141
|
+
ADD CONSTRAINT "fk_post_author_id_87ef9a" FOREIGN KEY ("author_id") REFERENCES "author"("id") ON DELETE CASCADE DEFERRABLE INITIALLY IMMEDIATE;
|
|
142
142
|
CREATE INDEX "post_author_id_index" ON "post" ("author_id");
|
|
143
143
|
ALTER TABLE "post" RENAME TO "article";
|
|
144
144
|
CREATE TABLE "post" (
|
|
@@ -156,7 +156,7 @@ CREATE CONSTRAINT TRIGGER "log_event_trx"
|
|
|
156
156
|
ALTER TABLE "post"
|
|
157
157
|
ADD "author_id" uuid;
|
|
158
158
|
ALTER TABLE "post"
|
|
159
|
-
ADD CONSTRAINT "fk_post_author_id_87ef9a" FOREIGN KEY ("author_id") REFERENCES "author"("id") ON DELETE
|
|
159
|
+
ADD CONSTRAINT "fk_post_author_id_87ef9a" FOREIGN KEY ("author_id") REFERENCES "author"("id") ON DELETE CASCADE DEFERRABLE INITIALLY IMMEDIATE;
|
|
160
160
|
CREATE INDEX "post_author_id_index1" ON "post" ("author_id");`)
|
|
161
161
|
})
|
|
162
162
|
|
|
@@ -62,6 +62,27 @@ testMigrations('rename entity with a constraint', {
|
|
|
62
62
|
noDiff: true,
|
|
63
63
|
})
|
|
64
64
|
|
|
65
|
+
testMigrations('rename entity with one-has-one (constraint)', {
|
|
66
|
+
originalSchema: new SchemaBuilder()
|
|
67
|
+
.entity('Author', e => e.oneHasOne('content', r => r.target('Content')))
|
|
68
|
+
.entity('Content', e => e.column('foo'))
|
|
69
|
+
.buildSchema(),
|
|
70
|
+
updatedSchema: new SchemaBuilder()
|
|
71
|
+
.entity('User', e => e.tableName('author').oneHasOne('content', r => r.target('Content')))
|
|
72
|
+
.entity('Content', e => e.column('foo'))
|
|
73
|
+
.buildSchema(),
|
|
74
|
+
diff: [
|
|
75
|
+
{
|
|
76
|
+
modification: 'updateEntityName',
|
|
77
|
+
entityName: 'Author',
|
|
78
|
+
newEntityName: 'User',
|
|
79
|
+
},
|
|
80
|
+
],
|
|
81
|
+
sql: SQL`ALTER TABLE "author"
|
|
82
|
+
RENAME CONSTRAINT "unique_Author_content_b64856" TO "unique_User_content_43c77f";`,
|
|
83
|
+
noDiff: true,
|
|
84
|
+
})
|
|
85
|
+
|
|
65
86
|
testMigrations('rename table with acl', {
|
|
66
87
|
originalSchema: new SchemaBuilder()
|
|
67
88
|
.entity('Site', entity => entity.column('name', c => c.type(Model.ColumnType.String)))
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { testMigrations } from '../../src/tests'
|
|
2
|
+
import { SchemaBuilder, SchemaDefinition as def } from '@contember/schema-definition'
|
|
3
|
+
import { Model } from '@contember/schema'
|
|
4
|
+
import { SQL } from '../../src/tags'
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
namespace SchemaWithoutOrderBy {
|
|
8
|
+
export class Article {
|
|
9
|
+
title = def.stringColumn()
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
namespace SchemaWithOrderBy {
|
|
14
|
+
@def.OrderBy('title', Model.OrderDirection.asc)
|
|
15
|
+
export class Article {
|
|
16
|
+
title = def.stringColumn()
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
testMigrations('update entity add order by', {
|
|
21
|
+
originalSchema: def.createModel(SchemaWithoutOrderBy),
|
|
22
|
+
updatedSchema: def.createModel(SchemaWithOrderBy),
|
|
23
|
+
diff: [
|
|
24
|
+
{
|
|
25
|
+
modification: 'updateEntityOrderBy',
|
|
26
|
+
entityName: 'Article',
|
|
27
|
+
orderBy: [{ path: ['title'], direction: 'asc' }],
|
|
28
|
+
},
|
|
29
|
+
],
|
|
30
|
+
sql: SQL``,
|
|
31
|
+
})
|
|
32
|
+
|
|
33
|
+
testMigrations('update entity remove order by', {
|
|
34
|
+
originalSchema: def.createModel(SchemaWithOrderBy),
|
|
35
|
+
updatedSchema: def.createModel(SchemaWithoutOrderBy),
|
|
36
|
+
diff: [
|
|
37
|
+
{
|
|
38
|
+
modification: 'updateEntityOrderBy',
|
|
39
|
+
entityName: 'Article',
|
|
40
|
+
},
|
|
41
|
+
],
|
|
42
|
+
sql: SQL``,
|
|
43
|
+
})
|
|
@@ -63,6 +63,28 @@ testMigrations('rename a field with a constraint', {
|
|
|
63
63
|
noDiff: true,
|
|
64
64
|
})
|
|
65
65
|
|
|
66
|
+
testMigrations('rename a field with one-has-one', {
|
|
67
|
+
originalSchema: new SchemaBuilder()
|
|
68
|
+
.entity('Author', e => e.oneHasOne('content', r => r.target('Content')))
|
|
69
|
+
.entity('Content', e => e.column('foo'))
|
|
70
|
+
.buildSchema(),
|
|
71
|
+
updatedSchema: new SchemaBuilder()
|
|
72
|
+
.entity('Author', e => e.oneHasOne('description', r => r.target('Content').joiningColumn('content_id')))
|
|
73
|
+
.entity('Content', e => e.column('foo'))
|
|
74
|
+
.buildSchema(),
|
|
75
|
+
diff: [
|
|
76
|
+
{
|
|
77
|
+
modification: 'updateFieldName',
|
|
78
|
+
entityName: 'Author',
|
|
79
|
+
fieldName: 'content',
|
|
80
|
+
newFieldName: 'description',
|
|
81
|
+
},
|
|
82
|
+
],
|
|
83
|
+
sql: SQL`ALTER TABLE "author"
|
|
84
|
+
RENAME CONSTRAINT "unique_Author_content_b64856" TO "unique_Author_description_00f1ef";`,
|
|
85
|
+
noDiff: true,
|
|
86
|
+
})
|
|
87
|
+
|
|
66
88
|
testMigrations('rename a relation', {
|
|
67
89
|
originalSchema: new SchemaBuilder()
|
|
68
90
|
.entity('Post', e => e.column('title').manyHasOne('user', r => r.target('Author').inversedBy('posts')))
|
|
@@ -26,5 +26,6 @@ testMigrations('update relation ondelete to cascade', {
|
|
|
26
26
|
onDelete: Model.OnDelete.cascade,
|
|
27
27
|
},
|
|
28
28
|
],
|
|
29
|
-
sql: SQL
|
|
29
|
+
sql: SQL`ALTER TABLE "post" DROP CONSTRAINT "fk_post_category_id_820029";
|
|
30
|
+
ALTER TABLE "post" ADD CONSTRAINT "fk_post_category_id_820029" FOREIGN KEY ("category_id") REFERENCES "category"("id") ON DELETE NO ACTION DEFERRABLE INITIALLY IMMEDIATE;`,
|
|
30
31
|
})
|
package/tests/src/tests.ts
CHANGED
|
@@ -29,8 +29,8 @@ export function testDiffSchemas(
|
|
|
29
29
|
updatedAcl: Acl.Schema = emptyAcl,
|
|
30
30
|
) {
|
|
31
31
|
const actualDiff = schemaDiffer.diffSchemas(
|
|
32
|
-
{ ...emptySchema, model: originalModel, acl: originalAcl
|
|
33
|
-
{ ...emptySchema, model: updatedModel, acl: updatedAcl
|
|
32
|
+
{ ...emptySchema, model: originalModel, acl: originalAcl },
|
|
33
|
+
{ ...emptySchema, model: updatedModel, acl: updatedAcl },
|
|
34
34
|
{ skipRecreateValidation: true },
|
|
35
35
|
)
|
|
36
36
|
try {
|
|
@@ -41,7 +41,7 @@ export function testDiffSchemas(
|
|
|
41
41
|
throw e
|
|
42
42
|
}
|
|
43
43
|
const { meta, ...schema } = schemaMigrator.applyModifications(
|
|
44
|
-
{ ...emptySchema, model: originalModel, acl: originalAcl
|
|
44
|
+
{ ...emptySchema, model: originalModel, acl: originalAcl },
|
|
45
45
|
actualDiff,
|
|
46
46
|
VERSION_LATEST,
|
|
47
47
|
) as SchemaWithMeta
|
|
@@ -49,7 +49,6 @@ export function testDiffSchemas(
|
|
|
49
49
|
...emptySchema,
|
|
50
50
|
model: updatedModel,
|
|
51
51
|
acl: updatedAcl,
|
|
52
|
-
validation: {},
|
|
53
52
|
})
|
|
54
53
|
}
|
|
55
54
|
|
|
@@ -61,7 +60,7 @@ export function testApplyDiff(
|
|
|
61
60
|
expectedAcl: Acl.Schema = emptyAcl,
|
|
62
61
|
) {
|
|
63
62
|
const { meta, ...actualSchema } = schemaMigrator.applyModifications(
|
|
64
|
-
{ ...emptySchema, model: originalModel, acl: originalAcl
|
|
63
|
+
{ ...emptySchema, model: originalModel, acl: originalAcl },
|
|
65
64
|
diff,
|
|
66
65
|
VERSION_LATEST,
|
|
67
66
|
) as SchemaWithMeta
|
|
@@ -70,12 +69,11 @@ export function testApplyDiff(
|
|
|
70
69
|
...emptySchema,
|
|
71
70
|
model: expectedModel,
|
|
72
71
|
acl: expectedAcl,
|
|
73
|
-
validation: {},
|
|
74
72
|
})
|
|
75
73
|
}
|
|
76
74
|
|
|
77
75
|
export function testGenerateSql(originalSchema: Model.Schema, diff: Migration.Modification[], expectedSql: string) {
|
|
78
|
-
let schema = { ...emptySchema, model: originalSchema, acl: emptyAcl
|
|
76
|
+
let schema = { ...emptySchema, model: originalSchema, acl: emptyAcl }
|
|
79
77
|
const builder = createMigrationBuilder()
|
|
80
78
|
for (let { modification, ...data } of diff) {
|
|
81
79
|
const modificationHandler = modificationFactory.create(modification, data, schema, { formatVersion: VERSION_LATEST, systemSchema: 'system' })
|
package/tests/tsconfig.json
CHANGED
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
export declare class MigrationVersionHelper {
|
|
2
|
-
static prefixLength: number;
|
|
3
|
-
static extractVersion(filename: string): string;
|
|
4
|
-
static createVersion(name: string, increment?: number): [string, string];
|
|
5
|
-
static extractName(filename: string): string;
|
|
6
|
-
private static createTimePrefix;
|
|
7
|
-
private static normalizeMigrationLabel;
|
|
8
|
-
}
|
|
9
|
-
//# sourceMappingURL=MigrationVersionHelper.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"MigrationVersionHelper.d.ts","sourceRoot":"","sources":["../../src/MigrationVersionHelper.ts"],"names":[],"mappings":"AAAA,qBAAa,sBAAsB;IAClC,OAAc,YAAY,SAA6B;WAEzC,cAAc,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM;WAIxC,aAAa,CAAC,IAAI,EAAE,MAAM,EAAE,SAAS,GAAE,MAAU,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC;WAMpE,WAAW,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM;IAInD,OAAO,CAAC,MAAM,CAAC,gBAAgB;IAyB/B,OAAO,CAAC,MAAM,CAAC,uBAAuB;CAGtC"}
|
|
@@ -1,45 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.MigrationVersionHelper = void 0;
|
|
4
|
-
class MigrationVersionHelper {
|
|
5
|
-
static extractVersion(filename) {
|
|
6
|
-
return filename.substring(0, this.prefixLength);
|
|
7
|
-
}
|
|
8
|
-
static createVersion(name, increment = 0) {
|
|
9
|
-
const normalizedName = MigrationVersionHelper.normalizeMigrationLabel(name);
|
|
10
|
-
const version = MigrationVersionHelper.createTimePrefix(increment);
|
|
11
|
-
return [version, `${version}-${normalizedName}`];
|
|
12
|
-
}
|
|
13
|
-
static extractName(filename) {
|
|
14
|
-
return filename.substring(0, filename.lastIndexOf('.'));
|
|
15
|
-
}
|
|
16
|
-
static createTimePrefix(increment) {
|
|
17
|
-
const now = new Date();
|
|
18
|
-
now.setSeconds(now.getSeconds() + increment);
|
|
19
|
-
const year = now.getFullYear();
|
|
20
|
-
const month = (now.getMonth() + 1).toString().padStart(2, '0');
|
|
21
|
-
const day = now //
|
|
22
|
-
.getDate()
|
|
23
|
-
.toString()
|
|
24
|
-
.padStart(2, '0');
|
|
25
|
-
const hours = now //
|
|
26
|
-
.getHours()
|
|
27
|
-
.toString()
|
|
28
|
-
.padStart(2, '0');
|
|
29
|
-
const minutes = now //
|
|
30
|
-
.getMinutes()
|
|
31
|
-
.toString()
|
|
32
|
-
.padStart(2, '0');
|
|
33
|
-
const seconds = now //
|
|
34
|
-
.getSeconds()
|
|
35
|
-
.toString()
|
|
36
|
-
.padStart(2, '0');
|
|
37
|
-
return `${year}-${month}-${day}-${hours}${minutes}${seconds}`;
|
|
38
|
-
}
|
|
39
|
-
static normalizeMigrationLabel(name) {
|
|
40
|
-
return name.toLowerCase().replace(/[^a-z0-9]+/g, '-');
|
|
41
|
-
}
|
|
42
|
-
}
|
|
43
|
-
exports.MigrationVersionHelper = MigrationVersionHelper;
|
|
44
|
-
MigrationVersionHelper.prefixLength = 'YYYY-MM-DD-HHIISS'.length;
|
|
45
|
-
//# sourceMappingURL=MigrationVersionHelper.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"MigrationVersionHelper.js","sourceRoot":"","sources":["../../src/MigrationVersionHelper.ts"],"names":[],"mappings":";;;AAAA,MAAa,sBAAsB;IAG3B,MAAM,CAAC,cAAc,CAAC,QAAgB;QAC5C,OAAO,QAAQ,CAAC,SAAS,CAAC,CAAC,EAAE,IAAI,CAAC,YAAY,CAAC,CAAA;IAChD,CAAC;IAEM,MAAM,CAAC,aAAa,CAAC,IAAY,EAAE,YAAoB,CAAC;QAC9D,MAAM,cAAc,GAAG,sBAAsB,CAAC,uBAAuB,CAAC,IAAI,CAAC,CAAA;QAC3E,MAAM,OAAO,GAAG,sBAAsB,CAAC,gBAAgB,CAAC,SAAS,CAAC,CAAA;QAClE,OAAO,CAAC,OAAO,EAAE,GAAG,OAAO,IAAI,cAAc,EAAE,CAAC,CAAA;IACjD,CAAC;IAEM,MAAM,CAAC,WAAW,CAAC,QAAgB;QACzC,OAAO,QAAQ,CAAC,SAAS,CAAC,CAAC,EAAE,QAAQ,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC,CAAA;IACxD,CAAC;IAEO,MAAM,CAAC,gBAAgB,CAAC,SAAiB;QAChD,MAAM,GAAG,GAAG,IAAI,IAAI,EAAE,CAAA;QACtB,GAAG,CAAC,UAAU,CAAC,GAAG,CAAC,UAAU,EAAE,GAAG,SAAS,CAAC,CAAA;QAC5C,MAAM,IAAI,GAAG,GAAG,CAAC,WAAW,EAAE,CAAA;QAC9B,MAAM,KAAK,GAAG,CAAC,GAAG,CAAC,QAAQ,EAAE,GAAG,CAAC,CAAC,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,CAAA;QAC9D,MAAM,GAAG,GAAG,GAAG,CAAC,EAAE;aAChB,OAAO,EAAE;aACT,QAAQ,EAAE;aACV,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,CAAA;QAClB,MAAM,KAAK,GAAG,GAAG,CAAC,EAAE;aAClB,QAAQ,EAAE;aACV,QAAQ,EAAE;aACV,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,CAAA;QAClB,MAAM,OAAO,GAAG,GAAG,CAAC,EAAE;aACpB,UAAU,EAAE;aACZ,QAAQ,EAAE;aACV,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,CAAA;QAClB,MAAM,OAAO,GAAG,GAAG,CAAC,EAAE;aACpB,UAAU,EAAE;aACZ,QAAQ,EAAE;aACV,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,CAAA;QAElB,OAAO,GAAG,IAAI,IAAI,KAAK,IAAI,GAAG,IAAI,KAAK,GAAG,OAAO,GAAG,OAAO,EAAE,CAAA;IAC9D,CAAC;IAEO,MAAM,CAAC,uBAAuB,CAAC,IAAY;QAClD,OAAO,IAAI,CAAC,WAAW,EAAE,CAAC,OAAO,CAAC,aAAa,EAAE,GAAG,CAAC,CAAA;IACtD,CAAC;;AA5CF,wDA6CC;AA5Cc,mCAAY,GAAG,mBAAmB,CAAC,MAAM,CAAA"}
|
|
@@ -1,46 +0,0 @@
|
|
|
1
|
-
export class MigrationVersionHelper {
|
|
2
|
-
public static prefixLength = 'YYYY-MM-DD-HHIISS'.length
|
|
3
|
-
|
|
4
|
-
public static extractVersion(filename: string): string {
|
|
5
|
-
return filename.substring(0, this.prefixLength)
|
|
6
|
-
}
|
|
7
|
-
|
|
8
|
-
public static createVersion(name: string, increment: number = 0): [string, string] {
|
|
9
|
-
const normalizedName = MigrationVersionHelper.normalizeMigrationLabel(name)
|
|
10
|
-
const version = MigrationVersionHelper.createTimePrefix(increment)
|
|
11
|
-
return [version, `${version}-${normalizedName}`]
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
public static extractName(filename: string): string {
|
|
15
|
-
return filename.substring(0, filename.lastIndexOf('.'))
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
private static createTimePrefix(increment: number): string {
|
|
19
|
-
const now = new Date()
|
|
20
|
-
now.setSeconds(now.getSeconds() + increment)
|
|
21
|
-
const year = now.getFullYear()
|
|
22
|
-
const month = (now.getMonth() + 1).toString().padStart(2, '0')
|
|
23
|
-
const day = now //
|
|
24
|
-
.getDate()
|
|
25
|
-
.toString()
|
|
26
|
-
.padStart(2, '0')
|
|
27
|
-
const hours = now //
|
|
28
|
-
.getHours()
|
|
29
|
-
.toString()
|
|
30
|
-
.padStart(2, '0')
|
|
31
|
-
const minutes = now //
|
|
32
|
-
.getMinutes()
|
|
33
|
-
.toString()
|
|
34
|
-
.padStart(2, '0')
|
|
35
|
-
const seconds = now //
|
|
36
|
-
.getSeconds()
|
|
37
|
-
.toString()
|
|
38
|
-
.padStart(2, '0')
|
|
39
|
-
|
|
40
|
-
return `${year}-${month}-${day}-${hours}${minutes}${seconds}`
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
private static normalizeMigrationLabel(name: string) {
|
|
44
|
-
return name.toLowerCase().replace(/[^a-z0-9]+/g, '-')
|
|
45
|
-
}
|
|
46
|
-
}
|