@contember/schema-migrations 1.3.4 → 1.4.0-alpha.1
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/modifications/ModificationHandler.d.ts +2 -2
- package/dist/src/modifications/ModificationHandler.d.ts.map +1 -1
- package/dist/src/modifications/constraints/CreateUniqueConstraintModification.d.ts.map +1 -1
- package/dist/src/modifications/constraints/CreateUniqueConstraintModification.js +8 -1
- package/dist/src/modifications/constraints/CreateUniqueConstraintModification.js.map +1 -1
- package/dist/src/modifications/constraints/RemoveUniqueConstraintModification.d.ts.map +1 -1
- package/dist/src/modifications/constraints/RemoveUniqueConstraintModification.js +2 -2
- package/dist/src/modifications/constraints/RemoveUniqueConstraintModification.js.map +1 -1
- package/dist/src/modifications/indexes/RemoveIndexModification.js +1 -1
- package/dist/src/modifications/indexes/RemoveIndexModification.js.map +1 -1
- package/dist/src/modifications/relations/ConvertOneToManyRelationModification.d.ts.map +1 -1
- package/dist/src/modifications/relations/ConvertOneToManyRelationModification.js +3 -3
- package/dist/src/modifications/relations/ConvertOneToManyRelationModification.js.map +1 -1
- package/dist/src/modifications/relations/helpers.d.ts +2 -2
- package/dist/src/modifications/relations/helpers.d.ts.map +1 -1
- package/dist/src/modifications/relations/helpers.js +2 -2
- package/dist/src/modifications/relations/helpers.js.map +1 -1
- package/dist/src/tsconfig.tsbuildinfo +1 -1
- package/dist/tests/cases/integration/convertOneToManyRelation.test.js +23 -0
- package/dist/tests/cases/integration/convertOneToManyRelation.test.js.map +1 -1
- package/dist/tests/cases/integration/createAndDropIndex.test.js +10 -0
- package/dist/tests/cases/integration/createAndDropIndex.test.js.map +1 -1
- package/dist/tests/cases/integration/createRelationInverseSide.test.js +17 -0
- package/dist/tests/cases/integration/createRelationInverseSide.test.js.map +1 -1
- package/dist/tests/cases/integration/createUnique.test.d.ts +2 -0
- package/dist/tests/cases/integration/createUnique.test.d.ts.map +1 -0
- package/dist/tests/cases/integration/createUnique.test.js +168 -0
- package/dist/tests/cases/integration/createUnique.test.js.map +1 -0
- package/dist/tests/cases/integration/removeField.test.js +12 -0
- package/dist/tests/cases/integration/removeField.test.js.map +1 -1
- package/dist/tests/cases/integration/updateRelationOnDelete.test.js +17 -0
- package/dist/tests/cases/integration/updateRelationOnDelete.test.js.map +1 -1
- package/dist/tests/src/tests.d.ts +4 -2
- package/dist/tests/src/tests.d.ts.map +1 -1
- package/dist/tests/src/tests.js +5 -4
- package/dist/tests/src/tests.js.map +1 -1
- package/dist/tests/tsconfig.tsbuildinfo +1 -1
- package/package.json +7 -6
- package/src/modifications/ModificationHandler.ts +2 -2
- package/src/modifications/constraints/CreateUniqueConstraintModification.ts +8 -1
- package/src/modifications/constraints/RemoveUniqueConstraintModification.ts +8 -10
- package/src/modifications/indexes/RemoveIndexModification.ts +1 -1
- package/src/modifications/relations/ConvertOneToManyRelationModification.ts +4 -3
- package/src/modifications/relations/helpers.ts +4 -4
- package/src/tsconfig.json +1 -0
- package/tests/cases/integration/convertOneToManyRelation.test.ts +23 -0
- package/tests/cases/integration/createAndDropIndex.test.ts +10 -0
- package/tests/cases/integration/createRelationInverseSide.test.ts +17 -0
- package/tests/cases/integration/createUnique.test.ts +146 -0
- package/tests/cases/integration/removeField.test.ts +12 -0
- package/tests/cases/integration/updateRelationOnDelete.test.ts +17 -0
- package/tests/src/tests.ts +12 -5
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@contember/schema-migrations",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.4.0-alpha.1",
|
|
4
4
|
"license": "Apache-2.0",
|
|
5
5
|
"main": "dist/src/index.js",
|
|
6
6
|
"typings": "dist/src/index.d.ts",
|
|
@@ -12,15 +12,16 @@
|
|
|
12
12
|
"test": "vitest --dir ./tests/cases"
|
|
13
13
|
},
|
|
14
14
|
"dependencies": {
|
|
15
|
-
"@contember/database
|
|
16
|
-
"@contember/
|
|
17
|
-
"@contember/
|
|
18
|
-
"@contember/schema
|
|
15
|
+
"@contember/database": "1.4.0-alpha.1",
|
|
16
|
+
"@contember/database-migrations": "1.4.0-alpha.1",
|
|
17
|
+
"@contember/engine-common": "1.4.0-alpha.1",
|
|
18
|
+
"@contember/schema": "1.4.0-alpha.1",
|
|
19
|
+
"@contember/schema-utils": "1.4.0-alpha.1",
|
|
19
20
|
"fast-deep-equal": "^3.1.3",
|
|
20
21
|
"rfc6902": "^5.0.1"
|
|
21
22
|
},
|
|
22
23
|
"devDependencies": {
|
|
23
|
-
"@contember/schema-definition": "1.
|
|
24
|
+
"@contember/schema-definition": "1.4.0-alpha.1"
|
|
24
25
|
},
|
|
25
26
|
"peerDependencies": {
|
|
26
27
|
"pg": "^8.9.0"
|
|
@@ -2,7 +2,7 @@ import { MigrationBuilder } from '@contember/database-migrations'
|
|
|
2
2
|
import { SchemaUpdater } from './utils/schemaUpdateUtils'
|
|
3
3
|
import { Schema } from '@contember/schema'
|
|
4
4
|
import { Migration } from '../Migration'
|
|
5
|
-
import {
|
|
5
|
+
import { DatabaseMetadata } from '@contember/database'
|
|
6
6
|
|
|
7
7
|
export interface ModificationDescription {
|
|
8
8
|
message: string
|
|
@@ -23,7 +23,7 @@ export interface ModificationHandler<Data> {
|
|
|
23
23
|
|
|
24
24
|
export interface ModificationHandlerCreateSqlOptions {
|
|
25
25
|
systemSchema: string
|
|
26
|
-
databaseMetadata:
|
|
26
|
+
databaseMetadata: DatabaseMetadata
|
|
27
27
|
invalidateDatabaseMetadata: () => void
|
|
28
28
|
}
|
|
29
29
|
|
|
@@ -30,7 +30,14 @@ export class CreateUniqueConstraintModificationHandler implements ModificationHa
|
|
|
30
30
|
const tableNameId = wrapIdentifier(entity.tableName)
|
|
31
31
|
const columnNameIds = columns.map(wrapIdentifier)
|
|
32
32
|
|
|
33
|
-
|
|
33
|
+
let checkModifier = ''
|
|
34
|
+
if (this.data.unique.timing === 'deferred') {
|
|
35
|
+
checkModifier = ' INITIALLY DEFERRED'
|
|
36
|
+
} else if (this.data.unique.timing === 'deferrable') {
|
|
37
|
+
checkModifier = ' DEFERRABLE'
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
builder.sql(`ALTER TABLE ${tableNameId} ADD UNIQUE (${columnNameIds.join(', ')})${checkModifier}`)
|
|
34
41
|
|
|
35
42
|
invalidateDatabaseMetadata()
|
|
36
43
|
}
|
|
@@ -29,7 +29,7 @@ export class RemoveUniqueConstraintModificationHandler implements ModificationHa
|
|
|
29
29
|
model: this.schema.model,
|
|
30
30
|
})
|
|
31
31
|
|
|
32
|
-
const constraintNames = databaseMetadata.
|
|
32
|
+
const constraintNames = databaseMetadata.uniqueConstraints.filter({ tableName: entity.tableName, columnNames: columns }).getNames()
|
|
33
33
|
|
|
34
34
|
for (const name of constraintNames) {
|
|
35
35
|
builder.sql(`ALTER TABLE ${wrapIdentifier(entity.tableName)} DROP CONSTRAINT ${wrapIdentifier(name)}`)
|
|
@@ -91,15 +91,13 @@ export class RemoveUniqueConstraintDiffer implements Differ {
|
|
|
91
91
|
createDiff(originalSchema: Schema, updatedSchema: Schema) {
|
|
92
92
|
return Object.values(originalSchema.model.entities).flatMap(entity =>
|
|
93
93
|
entity.unique
|
|
94
|
-
.filter(
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
},
|
|
102
|
-
)
|
|
94
|
+
.filter(it => {
|
|
95
|
+
const updatedEntity = updatedSchema.model.entities[entity.name]
|
|
96
|
+
if (!updatedEntity) {
|
|
97
|
+
return false
|
|
98
|
+
}
|
|
99
|
+
return !updatedEntity.unique.find(uniq => deepEqual(uniq.fields, it.fields) && it.timing === uniq.timing)
|
|
100
|
+
})
|
|
103
101
|
.map(unique =>
|
|
104
102
|
removeUniqueConstraintModification.createModification({
|
|
105
103
|
entityName: entity.name,
|
|
@@ -27,7 +27,7 @@ export class RemoveIndexModificationHandler implements ModificationHandler<Remov
|
|
|
27
27
|
model: this.schema.model,
|
|
28
28
|
})
|
|
29
29
|
|
|
30
|
-
const indexNames = databaseMetadata.
|
|
30
|
+
const indexNames = databaseMetadata.indexes.filter({ tableName: entity.tableName, columnNames: columns }).getNames()
|
|
31
31
|
|
|
32
32
|
for (const name of indexNames) {
|
|
33
33
|
builder.sql(`DROP INDEX ${wrapIdentifier(name)}`)
|
|
@@ -44,10 +44,11 @@ export class ConvertOneToManyRelationModificationHandler implements Modification
|
|
|
44
44
|
const columnNameId = wrapIdentifier(columnName)
|
|
45
45
|
builder.sql(`CREATE INDEX ON ${tableNameId} (${columnNameId})`)
|
|
46
46
|
|
|
47
|
-
const uniqueConstraintNames = options.databaseMetadata.
|
|
47
|
+
const uniqueConstraintNames = options.databaseMetadata.uniqueConstraints.filter({
|
|
48
48
|
tableName: entity.tableName,
|
|
49
|
-
columnNames: [
|
|
50
|
-
})
|
|
49
|
+
columnNames: [columnName],
|
|
50
|
+
}).getNames()
|
|
51
|
+
|
|
51
52
|
for (const name of uniqueConstraintNames) {
|
|
52
53
|
builder.sql(`ALTER TABLE ${wrapIdentifier(entity.tableName)} DROP CONSTRAINT ${wrapIdentifier(name)}`)
|
|
53
54
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { MigrationBuilder } from '@contember/database-migrations'
|
|
2
2
|
import { Model } from '@contember/schema'
|
|
3
3
|
import { wrapIdentifier } from '../../utils/dbHelpers'
|
|
4
|
-
import {
|
|
4
|
+
import { DatabaseMetadata } from '@contember/database'
|
|
5
5
|
|
|
6
6
|
export const addForeignKeyConstraint = ({ builder, entity, relation, targetEntity, recreate = false, databaseMetadata, invalidateDatabaseMetadata }: {
|
|
7
7
|
recreate?: boolean
|
|
@@ -9,18 +9,18 @@ export const addForeignKeyConstraint = ({ builder, entity, relation, targetEntit
|
|
|
9
9
|
entity: Model.Entity
|
|
10
10
|
targetEntity: Model.Entity
|
|
11
11
|
relation: Model.OneHasOneOwningRelation | Model.ManyHasOneRelation
|
|
12
|
-
databaseMetadata:
|
|
12
|
+
databaseMetadata: DatabaseMetadata
|
|
13
13
|
invalidateDatabaseMetadata: () => void
|
|
14
14
|
}) => {
|
|
15
15
|
if (recreate) {
|
|
16
|
-
const fkNames = databaseMetadata.
|
|
16
|
+
const fkNames = databaseMetadata.foreignKeys.filter(
|
|
17
17
|
{
|
|
18
18
|
fromTable: entity.tableName,
|
|
19
19
|
fromColumn: relation.joiningColumn.columnName,
|
|
20
20
|
toTable: targetEntity.tableName,
|
|
21
21
|
toColumn: targetEntity.primaryColumn,
|
|
22
22
|
},
|
|
23
|
-
)
|
|
23
|
+
).getNames()
|
|
24
24
|
for (const name of fkNames) {
|
|
25
25
|
builder.sql(`ALTER TABLE ${wrapIdentifier(entity.tableName)} DROP CONSTRAINT ${wrapIdentifier(name)}`)
|
|
26
26
|
}
|
package/src/tsconfig.json
CHANGED
|
@@ -2,6 +2,7 @@ import { testMigrations } from '../../src/tests'
|
|
|
2
2
|
import { SchemaBuilder } from '@contember/schema-definition'
|
|
3
3
|
import { Model } from '@contember/schema'
|
|
4
4
|
import { SQL } from '../../src/tags'
|
|
5
|
+
import { createDatabaseMetadata } from '@contember/database'
|
|
5
6
|
|
|
6
7
|
testMigrations('convert one has one to many has one relation without inverse side', {
|
|
7
8
|
original: {
|
|
@@ -31,6 +32,17 @@ testMigrations('convert one has one to many has one relation without inverse sid
|
|
|
31
32
|
CREATE INDEX ON "post" ("image_id");
|
|
32
33
|
ALTER TABLE "post" DROP CONSTRAINT "uniq_post_image_id";
|
|
33
34
|
`,
|
|
35
|
+
databaseMetadata: createDatabaseMetadata({
|
|
36
|
+
foreignKeys: [],
|
|
37
|
+
indexes: [],
|
|
38
|
+
uniqueConstraints: [{
|
|
39
|
+
constraintName: 'uniq_post_image_id',
|
|
40
|
+
columnNames: ['image_id'],
|
|
41
|
+
tableName: 'post',
|
|
42
|
+
deferred: false,
|
|
43
|
+
deferrable: false,
|
|
44
|
+
}],
|
|
45
|
+
}),
|
|
34
46
|
})
|
|
35
47
|
|
|
36
48
|
|
|
@@ -63,5 +75,16 @@ testMigrations('convert one has one to many has one relation with inverse side',
|
|
|
63
75
|
CREATE INDEX ON "post" ("image_id");
|
|
64
76
|
ALTER TABLE "post" DROP CONSTRAINT "uniq_post_image_id";
|
|
65
77
|
`,
|
|
78
|
+
databaseMetadata: createDatabaseMetadata({
|
|
79
|
+
foreignKeys: [],
|
|
80
|
+
indexes: [],
|
|
81
|
+
uniqueConstraints: [{
|
|
82
|
+
constraintName: 'uniq_post_image_id',
|
|
83
|
+
columnNames: ['image_id'],
|
|
84
|
+
tableName: 'post',
|
|
85
|
+
deferred: false,
|
|
86
|
+
deferrable: false,
|
|
87
|
+
}],
|
|
88
|
+
}),
|
|
66
89
|
})
|
|
67
90
|
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { testMigrations } from '../../src/tests'
|
|
2
2
|
import { SQL } from '../../src/tags'
|
|
3
3
|
import { createSchema, SchemaDefinition as def } from '@contember/schema-definition'
|
|
4
|
+
import { createDatabaseMetadata } from '@contember/database'
|
|
4
5
|
|
|
5
6
|
namespace SchemaWithoutIndex {
|
|
6
7
|
export class Article {
|
|
@@ -41,4 +42,13 @@ testMigrations('drop index', {
|
|
|
41
42
|
},
|
|
42
43
|
],
|
|
43
44
|
sql: SQL`DROP INDEX "idx_article_title";`,
|
|
45
|
+
databaseMetadata: createDatabaseMetadata({
|
|
46
|
+
foreignKeys: [],
|
|
47
|
+
indexes: [{
|
|
48
|
+
tableName: 'article',
|
|
49
|
+
columnNames: ['title'],
|
|
50
|
+
indexName: 'idx_article_title',
|
|
51
|
+
}],
|
|
52
|
+
uniqueConstraints: [],
|
|
53
|
+
}),
|
|
44
54
|
})
|
|
@@ -2,6 +2,7 @@ import { testMigrations } from '../../src/tests'
|
|
|
2
2
|
import { Model } from '@contember/schema'
|
|
3
3
|
import { SQL } from '../../src/tags'
|
|
4
4
|
import { SchemaBuilder } from '@contember/schema-definition'
|
|
5
|
+
import { createDatabaseMetadata, ForeignKeyDeleteAction } from '@contember/database'
|
|
5
6
|
|
|
6
7
|
testMigrations('create inverse side relation (post with locales)', {
|
|
7
8
|
original: {
|
|
@@ -65,4 +66,20 @@ testMigrations('create inverse side relation together with changing onDelete beh
|
|
|
65
66
|
},
|
|
66
67
|
],
|
|
67
68
|
sql: SQL`ALTER TABLE "post_locale" DROP CONSTRAINT "fk_post_locale_post_id_post_id"; ALTER TABLE "post_locale" ADD FOREIGN KEY ("post_id") REFERENCES "post"("id") ON DELETE CASCADE DEFERRABLE INITIALLY IMMEDIATE;`,
|
|
69
|
+
databaseMetadata: createDatabaseMetadata({
|
|
70
|
+
foreignKeys: [
|
|
71
|
+
{
|
|
72
|
+
constraintName: 'fk_post_locale_post_id_post_id',
|
|
73
|
+
deleteAction: ForeignKeyDeleteAction.cascade,
|
|
74
|
+
fromColumn: 'post_id',
|
|
75
|
+
fromTable: 'post_locale',
|
|
76
|
+
toColumn: 'id',
|
|
77
|
+
toTable: 'post',
|
|
78
|
+
deferred: false,
|
|
79
|
+
deferrable: false,
|
|
80
|
+
},
|
|
81
|
+
],
|
|
82
|
+
indexes: [],
|
|
83
|
+
uniqueConstraints: [],
|
|
84
|
+
}),
|
|
68
85
|
})
|
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
import { c, createSchema } from '@contember/schema-definition'
|
|
2
|
+
import { SQL } from '../../src/tags'
|
|
3
|
+
import { testMigrations } from '../../src/tests'
|
|
4
|
+
import { createUniqueConstraintModification, removeUniqueConstraintModification } from '../../../src'
|
|
5
|
+
import { createDatabaseMetadata } from '@contember/database'
|
|
6
|
+
|
|
7
|
+
testMigrations('create unique (immediate)', {
|
|
8
|
+
original: createSchema({
|
|
9
|
+
Author: class Author {
|
|
10
|
+
email = c.stringColumn()
|
|
11
|
+
},
|
|
12
|
+
}),
|
|
13
|
+
updated: createSchema({
|
|
14
|
+
Author: class Author {
|
|
15
|
+
email = c.stringColumn().unique()
|
|
16
|
+
},
|
|
17
|
+
}),
|
|
18
|
+
diff: [
|
|
19
|
+
createUniqueConstraintModification.createModification({
|
|
20
|
+
entityName: 'Author',
|
|
21
|
+
unique: {
|
|
22
|
+
fields: ['email'],
|
|
23
|
+
},
|
|
24
|
+
}),
|
|
25
|
+
],
|
|
26
|
+
sql: SQL`ALTER TABLE "author" ADD UNIQUE ("email");`,
|
|
27
|
+
})
|
|
28
|
+
|
|
29
|
+
testMigrations('create unique (deferrable)', {
|
|
30
|
+
original: createSchema({
|
|
31
|
+
Author: class Author {
|
|
32
|
+
email = c.stringColumn()
|
|
33
|
+
},
|
|
34
|
+
}),
|
|
35
|
+
updated: createSchema({
|
|
36
|
+
Author: class Author {
|
|
37
|
+
email = c.stringColumn().unique({ timing: 'deferrable' })
|
|
38
|
+
},
|
|
39
|
+
}),
|
|
40
|
+
diff: [
|
|
41
|
+
createUniqueConstraintModification.createModification({
|
|
42
|
+
entityName: 'Author',
|
|
43
|
+
unique: {
|
|
44
|
+
fields: ['email'],
|
|
45
|
+
timing: 'deferrable',
|
|
46
|
+
},
|
|
47
|
+
}),
|
|
48
|
+
],
|
|
49
|
+
sql: SQL`ALTER TABLE "author"
|
|
50
|
+
ADD UNIQUE ("email") DEFERRABLE;`,
|
|
51
|
+
})
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
testMigrations('create unique (deferred)', {
|
|
55
|
+
original: createSchema({
|
|
56
|
+
Author: class Author {
|
|
57
|
+
email = c.stringColumn()
|
|
58
|
+
},
|
|
59
|
+
}),
|
|
60
|
+
updated: createSchema({
|
|
61
|
+
Author: class Author {
|
|
62
|
+
email = c.stringColumn().unique({ timing: 'deferred' })
|
|
63
|
+
},
|
|
64
|
+
}),
|
|
65
|
+
diff: [
|
|
66
|
+
|
|
67
|
+
createUniqueConstraintModification.createModification({
|
|
68
|
+
entityName: 'Author',
|
|
69
|
+
unique: {
|
|
70
|
+
fields: ['email'],
|
|
71
|
+
timing: 'deferred',
|
|
72
|
+
},
|
|
73
|
+
}),
|
|
74
|
+
],
|
|
75
|
+
sql: SQL`ALTER TABLE "author"
|
|
76
|
+
ADD UNIQUE ("email") INITIALLY DEFERRED;`,
|
|
77
|
+
})
|
|
78
|
+
|
|
79
|
+
|
|
80
|
+
testMigrations('change unique timing', {
|
|
81
|
+
original: createSchema({
|
|
82
|
+
Author: class Author {
|
|
83
|
+
email = c.stringColumn().unique()
|
|
84
|
+
},
|
|
85
|
+
}),
|
|
86
|
+
updated: createSchema({
|
|
87
|
+
Author: class Author {
|
|
88
|
+
email = c.stringColumn().unique({ timing: 'deferrable' })
|
|
89
|
+
},
|
|
90
|
+
}),
|
|
91
|
+
diff: [
|
|
92
|
+
removeUniqueConstraintModification.createModification({
|
|
93
|
+
entityName: 'Author',
|
|
94
|
+
fields: ['email'],
|
|
95
|
+
}),
|
|
96
|
+
createUniqueConstraintModification.createModification({
|
|
97
|
+
entityName: 'Author',
|
|
98
|
+
unique: {
|
|
99
|
+
fields: ['email'],
|
|
100
|
+
timing: 'deferrable',
|
|
101
|
+
},
|
|
102
|
+
}),
|
|
103
|
+
],
|
|
104
|
+
sql: SQL`ALTER TABLE "author" DROP CONSTRAINT "uniq_author_email";
|
|
105
|
+
ALTER TABLE "author" ADD UNIQUE ("email") DEFERRABLE;`,
|
|
106
|
+
databaseMetadata: createDatabaseMetadata({
|
|
107
|
+
foreignKeys: [],
|
|
108
|
+
indexes: [],
|
|
109
|
+
uniqueConstraints: [{
|
|
110
|
+
constraintName: 'uniq_author_email',
|
|
111
|
+
columnNames: ['email'],
|
|
112
|
+
tableName: 'author',
|
|
113
|
+
deferred: false,
|
|
114
|
+
deferrable: false,
|
|
115
|
+
}],
|
|
116
|
+
}),
|
|
117
|
+
})
|
|
118
|
+
|
|
119
|
+
|
|
120
|
+
namespace SchemaWithUniqueDecorator {
|
|
121
|
+
|
|
122
|
+
@c.Unique({ fields: ['email'], timing: 'deferred' })
|
|
123
|
+
export class Author {
|
|
124
|
+
email = c.stringColumn()
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
testMigrations('create unique using decorator', {
|
|
129
|
+
original: createSchema({
|
|
130
|
+
Author: class Author {
|
|
131
|
+
email = c.stringColumn()
|
|
132
|
+
},
|
|
133
|
+
}),
|
|
134
|
+
updated: createSchema(SchemaWithUniqueDecorator),
|
|
135
|
+
diff: [
|
|
136
|
+
createUniqueConstraintModification.createModification({
|
|
137
|
+
entityName: 'Author',
|
|
138
|
+
unique: {
|
|
139
|
+
fields: ['email'],
|
|
140
|
+
timing: 'deferred',
|
|
141
|
+
},
|
|
142
|
+
}),
|
|
143
|
+
],
|
|
144
|
+
sql: SQL`ALTER TABLE "author"
|
|
145
|
+
ADD UNIQUE ("email") INITIALLY DEFERRED;`,
|
|
146
|
+
})
|
|
@@ -3,6 +3,7 @@ import { createSchema, SchemaBuilder } from '@contember/schema-definition'
|
|
|
3
3
|
import { Model } from '@contember/schema'
|
|
4
4
|
import { SQL } from '../../src/tags'
|
|
5
5
|
import { SchemaDefinition as def } from '@contember/schema-definition'
|
|
6
|
+
import { createDatabaseMetadata } from '@contember/database'
|
|
6
7
|
|
|
7
8
|
|
|
8
9
|
testMigrations('remove relation (many has one)', {
|
|
@@ -67,6 +68,17 @@ testMigrations('remove relation (one has many)', {
|
|
|
67
68
|
],
|
|
68
69
|
sql: SQL`ALTER TABLE "post_locale" DROP CONSTRAINT "uniq_post_locale_post_id_locale";
|
|
69
70
|
ALTER TABLE "post_locale" DROP "post_id";`,
|
|
71
|
+
databaseMetadata: createDatabaseMetadata({
|
|
72
|
+
foreignKeys: [],
|
|
73
|
+
indexes: [],
|
|
74
|
+
uniqueConstraints: [{
|
|
75
|
+
constraintName: 'uniq_post_locale_post_id_locale',
|
|
76
|
+
columnNames: ['post_id', 'locale'],
|
|
77
|
+
tableName: 'post_locale',
|
|
78
|
+
deferrable: false,
|
|
79
|
+
deferred: false,
|
|
80
|
+
}],
|
|
81
|
+
}),
|
|
70
82
|
})
|
|
71
83
|
|
|
72
84
|
testMigrations('remove relation (many has many)', {
|
|
@@ -2,6 +2,7 @@ import { testMigrations } from '../../src/tests'
|
|
|
2
2
|
import { SchemaBuilder } from '@contember/schema-definition'
|
|
3
3
|
import { Model } from '@contember/schema'
|
|
4
4
|
import { SQL } from '../../src/tags'
|
|
5
|
+
import { ForeignKeyDeleteAction, createDatabaseMetadata } from '@contember/database'
|
|
5
6
|
|
|
6
7
|
testMigrations('update relation ondelete to cascade', {
|
|
7
8
|
original: {
|
|
@@ -32,4 +33,20 @@ testMigrations('update relation ondelete to cascade', {
|
|
|
32
33
|
],
|
|
33
34
|
sql: SQL`ALTER TABLE "post" DROP CONSTRAINT "fk_post_category_id_category_id";
|
|
34
35
|
ALTER TABLE "post" ADD FOREIGN KEY ("category_id") REFERENCES "category"("id") ON DELETE CASCADE DEFERRABLE INITIALLY IMMEDIATE;`,
|
|
36
|
+
databaseMetadata: createDatabaseMetadata({
|
|
37
|
+
foreignKeys: [
|
|
38
|
+
{
|
|
39
|
+
constraintName: 'fk_post_category_id_category_id',
|
|
40
|
+
deleteAction: ForeignKeyDeleteAction.cascade,
|
|
41
|
+
fromColumn: 'category_id',
|
|
42
|
+
fromTable: 'post',
|
|
43
|
+
toColumn: 'id',
|
|
44
|
+
toTable: 'category',
|
|
45
|
+
deferred: false,
|
|
46
|
+
deferrable: false,
|
|
47
|
+
},
|
|
48
|
+
],
|
|
49
|
+
indexes: [],
|
|
50
|
+
uniqueConstraints: [],
|
|
51
|
+
}),
|
|
35
52
|
})
|
package/tests/src/tests.ts
CHANGED
|
@@ -2,7 +2,8 @@ import { Migration, ModificationHandlerFactory, SchemaDiffer, SchemaMigrator, VE
|
|
|
2
2
|
import { Schema } from '@contember/schema'
|
|
3
3
|
import { createMigrationBuilder } from '@contember/database-migrations'
|
|
4
4
|
import { assert, describe, it } from 'vitest'
|
|
5
|
-
import {
|
|
5
|
+
import { emptySchema } from '@contember/schema-utils'
|
|
6
|
+
import { DatabaseMetadata, emptyDatabaseMetadata } from '@contember/database'
|
|
6
7
|
|
|
7
8
|
const modificationFactory = new ModificationHandlerFactory(ModificationHandlerFactory.defaultFactoryMap)
|
|
8
9
|
const schemaMigrator = new SchemaMigrator(modificationFactory)
|
|
@@ -14,6 +15,7 @@ export interface TestContext {
|
|
|
14
15
|
updated: Partial<Schema>
|
|
15
16
|
sql: string
|
|
16
17
|
noDiff?: boolean
|
|
18
|
+
databaseMetadata?: DatabaseMetadata
|
|
17
19
|
}
|
|
18
20
|
|
|
19
21
|
export function testDiffSchemas(
|
|
@@ -61,7 +63,12 @@ export function testApplyDiff(
|
|
|
61
63
|
})
|
|
62
64
|
}
|
|
63
65
|
|
|
64
|
-
export function testGenerateSql(
|
|
66
|
+
export function testGenerateSql(
|
|
67
|
+
original: Partial<Schema>,
|
|
68
|
+
diff: Migration.Modification[],
|
|
69
|
+
expectedSql: string,
|
|
70
|
+
databaseMetadata: DatabaseMetadata = emptyDatabaseMetadata,
|
|
71
|
+
) {
|
|
65
72
|
let schema = { ...emptySchema, ...original }
|
|
66
73
|
const builder = createMigrationBuilder()
|
|
67
74
|
for (let { modification, ...data } of diff) {
|
|
@@ -70,7 +77,7 @@ export function testGenerateSql(original: Partial<Schema>, diff: Migration.Modif
|
|
|
70
77
|
})
|
|
71
78
|
modificationHandler.createSql(builder, {
|
|
72
79
|
systemSchema: 'system',
|
|
73
|
-
databaseMetadata
|
|
80
|
+
databaseMetadata,
|
|
74
81
|
invalidateDatabaseMetadata: () => null,
|
|
75
82
|
})
|
|
76
83
|
schema = modificationHandler.getSchemaUpdater()({ schema })
|
|
@@ -79,7 +86,7 @@ export function testGenerateSql(original: Partial<Schema>, diff: Migration.Modif
|
|
|
79
86
|
assert.equal(actual, expectedSql)
|
|
80
87
|
}
|
|
81
88
|
|
|
82
|
-
export function testMigrations(title: string, { original, updated, diff, noDiff, sql }: TestContext) {
|
|
89
|
+
export function testMigrations(title: string, { original, updated, diff, noDiff, sql, databaseMetadata }: TestContext) {
|
|
83
90
|
describe(title, () => {
|
|
84
91
|
it('diff schemas', () => {
|
|
85
92
|
if (noDiff) {
|
|
@@ -91,7 +98,7 @@ export function testMigrations(title: string, { original, updated, diff, noDiff,
|
|
|
91
98
|
testApplyDiff(original, updated, diff)
|
|
92
99
|
})
|
|
93
100
|
it('generate sql', () => {
|
|
94
|
-
testGenerateSql(original, diff, sql)
|
|
101
|
+
testGenerateSql(original, diff, sql, databaseMetadata)
|
|
95
102
|
})
|
|
96
103
|
})
|
|
97
104
|
}
|