@contember/schema-migrations 2.1.0-alpha.3 → 2.1.0-alpha.30
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/development/src/SchemaDiffer.cjs +1 -1
- package/dist/development/src/SchemaDiffer.cjs.map +1 -1
- package/dist/development/src/SchemaDiffer.js +1 -1
- package/dist/development/src/SchemaDiffer.js.map +1 -1
- package/dist/development/src/modifications/ModificationHandlerFactory.cjs +2 -0
- package/dist/development/src/modifications/ModificationHandlerFactory.cjs.map +1 -1
- package/dist/development/src/modifications/ModificationHandlerFactory.js +2 -0
- package/dist/development/src/modifications/ModificationHandlerFactory.js.map +1 -1
- package/dist/development/src/modifications/acl/UpdateAclSchemaModification.cjs +1 -1
- package/dist/development/src/modifications/acl/UpdateAclSchemaModification.cjs.map +1 -1
- package/dist/development/src/modifications/acl/UpdateAclSchemaModification.js +1 -1
- package/dist/development/src/modifications/acl/UpdateAclSchemaModification.js.map +1 -1
- package/dist/development/src/modifications/actions/PatchTriggerModification.cjs +44 -0
- package/dist/development/src/modifications/actions/PatchTriggerModification.cjs.map +1 -0
- package/dist/development/src/modifications/actions/PatchTriggerModification.js +44 -0
- package/dist/development/src/modifications/actions/PatchTriggerModification.js.map +1 -0
- package/dist/development/src/modifications/actions/UpdateTriggerModification.cjs +16 -1
- package/dist/development/src/modifications/actions/UpdateTriggerModification.cjs.map +1 -1
- package/dist/development/src/modifications/actions/UpdateTriggerModification.js +16 -1
- package/dist/development/src/modifications/actions/UpdateTriggerModification.js.map +1 -1
- package/dist/development/src/modifications/columns/UpdateColumnDefinitionModification.cjs +1 -1
- package/dist/development/src/modifications/columns/UpdateColumnDefinitionModification.cjs.map +1 -1
- package/dist/development/src/modifications/columns/UpdateColumnDefinitionModification.js +1 -1
- package/dist/development/src/modifications/columns/UpdateColumnDefinitionModification.js.map +1 -1
- package/dist/development/src/modifications/constraints/CreateUniqueConstraintModification.cjs +3 -2
- package/dist/development/src/modifications/constraints/CreateUniqueConstraintModification.cjs.map +1 -1
- package/dist/development/src/modifications/constraints/CreateUniqueConstraintModification.js +3 -2
- package/dist/development/src/modifications/constraints/CreateUniqueConstraintModification.js.map +1 -1
- package/dist/development/src/modifications/entities/RemoveEntityModification.cjs +5 -1
- package/dist/development/src/modifications/entities/RemoveEntityModification.cjs.map +1 -1
- package/dist/development/src/modifications/entities/RemoveEntityModification.js +5 -1
- package/dist/development/src/modifications/entities/RemoveEntityModification.js.map +1 -1
- package/dist/development/src/modifications/enums/UpdateEnumModification.cjs +36 -8
- package/dist/development/src/modifications/enums/UpdateEnumModification.cjs.map +1 -1
- package/dist/development/src/modifications/enums/UpdateEnumModification.js +34 -6
- package/dist/development/src/modifications/enums/UpdateEnumModification.js.map +1 -1
- package/dist/development/src/modifications/indexes/CreateIndexModification.cjs +4 -2
- package/dist/development/src/modifications/indexes/CreateIndexModification.cjs.map +1 -1
- package/dist/development/src/modifications/indexes/CreateIndexModification.js +4 -2
- package/dist/development/src/modifications/indexes/CreateIndexModification.js.map +1 -1
- package/dist/production/src/SchemaDiffer.cjs +1 -1
- package/dist/production/src/SchemaDiffer.cjs.map +1 -1
- package/dist/production/src/SchemaDiffer.js +1 -1
- package/dist/production/src/SchemaDiffer.js.map +1 -1
- package/dist/production/src/modifications/ModificationHandlerFactory.cjs +2 -0
- package/dist/production/src/modifications/ModificationHandlerFactory.cjs.map +1 -1
- package/dist/production/src/modifications/ModificationHandlerFactory.js +2 -0
- package/dist/production/src/modifications/ModificationHandlerFactory.js.map +1 -1
- package/dist/production/src/modifications/acl/UpdateAclSchemaModification.cjs +1 -1
- package/dist/production/src/modifications/acl/UpdateAclSchemaModification.cjs.map +1 -1
- package/dist/production/src/modifications/acl/UpdateAclSchemaModification.js +1 -1
- package/dist/production/src/modifications/acl/UpdateAclSchemaModification.js.map +1 -1
- package/dist/production/src/modifications/actions/PatchTriggerModification.cjs +44 -0
- package/dist/production/src/modifications/actions/PatchTriggerModification.cjs.map +1 -0
- package/dist/production/src/modifications/actions/PatchTriggerModification.js +44 -0
- package/dist/production/src/modifications/actions/PatchTriggerModification.js.map +1 -0
- package/dist/production/src/modifications/actions/UpdateTriggerModification.cjs +16 -1
- package/dist/production/src/modifications/actions/UpdateTriggerModification.cjs.map +1 -1
- package/dist/production/src/modifications/actions/UpdateTriggerModification.js +16 -1
- package/dist/production/src/modifications/actions/UpdateTriggerModification.js.map +1 -1
- package/dist/production/src/modifications/columns/UpdateColumnDefinitionModification.cjs +1 -1
- package/dist/production/src/modifications/columns/UpdateColumnDefinitionModification.cjs.map +1 -1
- package/dist/production/src/modifications/columns/UpdateColumnDefinitionModification.js +1 -1
- package/dist/production/src/modifications/columns/UpdateColumnDefinitionModification.js.map +1 -1
- package/dist/production/src/modifications/constraints/CreateUniqueConstraintModification.cjs +3 -2
- package/dist/production/src/modifications/constraints/CreateUniqueConstraintModification.cjs.map +1 -1
- package/dist/production/src/modifications/constraints/CreateUniqueConstraintModification.js +3 -2
- package/dist/production/src/modifications/constraints/CreateUniqueConstraintModification.js.map +1 -1
- package/dist/production/src/modifications/entities/RemoveEntityModification.cjs +5 -1
- package/dist/production/src/modifications/entities/RemoveEntityModification.cjs.map +1 -1
- package/dist/production/src/modifications/entities/RemoveEntityModification.js +5 -1
- package/dist/production/src/modifications/entities/RemoveEntityModification.js.map +1 -1
- package/dist/production/src/modifications/enums/UpdateEnumModification.cjs +36 -8
- package/dist/production/src/modifications/enums/UpdateEnumModification.cjs.map +1 -1
- package/dist/production/src/modifications/enums/UpdateEnumModification.js +34 -6
- package/dist/production/src/modifications/enums/UpdateEnumModification.js.map +1 -1
- package/dist/production/src/modifications/indexes/CreateIndexModification.cjs +4 -2
- package/dist/production/src/modifications/indexes/CreateIndexModification.cjs.map +1 -1
- package/dist/production/src/modifications/indexes/CreateIndexModification.js +4 -2
- package/dist/production/src/modifications/indexes/CreateIndexModification.js.map +1 -1
- package/dist/tests/cases/integration/patchTrigger.test.d.ts +2 -0
- package/dist/tests/cases/integration/patchTrigger.test.d.ts.map +1 -0
- package/dist/tests/tsconfig.tsbuildinfo +1 -1
- package/dist/types/modifications/ModificationHandlerFactory.d.ts.map +1 -1
- package/dist/types/modifications/actions/PatchTriggerModification.d.ts +18 -0
- package/dist/types/modifications/actions/PatchTriggerModification.d.ts.map +1 -0
- package/dist/types/modifications/actions/UpdateTriggerModification.d.ts +5 -1
- package/dist/types/modifications/actions/UpdateTriggerModification.d.ts.map +1 -1
- package/dist/types/modifications/actions/index.d.ts +1 -0
- package/dist/types/modifications/actions/index.d.ts.map +1 -1
- package/dist/types/modifications/columns/UpdateColumnDefinitionModification.d.ts.map +1 -1
- package/dist/types/modifications/constraints/CreateUniqueConstraintModification.d.ts.map +1 -1
- package/dist/types/modifications/entities/RemoveEntityModification.d.ts.map +1 -1
- package/dist/types/modifications/enums/UpdateEnumModification.d.ts +1 -0
- package/dist/types/modifications/enums/UpdateEnumModification.d.ts.map +1 -1
- package/dist/types/modifications/indexes/CreateIndexModification.d.ts.map +1 -1
- package/dist/types/tsconfig.tsbuildinfo +1 -1
- package/package.json +7 -7
- package/src/SchemaDiffer.ts +1 -1
- package/src/modifications/ModificationHandlerFactory.ts +2 -1
- package/src/modifications/acl/UpdateAclSchemaModification.ts +1 -1
- package/src/modifications/actions/PatchTriggerModification.ts +51 -0
- package/src/modifications/actions/UpdateTriggerModification.ts +22 -1
- package/src/modifications/actions/index.ts +1 -0
- package/src/modifications/columns/UpdateColumnDefinitionModification.ts +3 -1
- package/src/modifications/constraints/CreateUniqueConstraintModification.ts +3 -2
- package/src/modifications/entities/RemoveEntityModification.ts +5 -1
- package/src/modifications/enums/UpdateEnumModification.ts +44 -7
- package/src/modifications/indexes/CreateIndexModification.ts +4 -2
- package/tests/cases/integration/createAndDropIndex.test.ts +100 -0
- package/tests/cases/integration/createUnique.test.ts +154 -2
- package/tests/cases/integration/patchTrigger.test.ts +184 -0
- package/tests/cases/integration/updateColumnDefinition.test.ts +28 -1
- package/tests/cases/integration/updateEnum.test.ts +43 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@contember/schema-migrations",
|
|
3
|
-
"version": "2.1.0-alpha.
|
|
3
|
+
"version": "2.1.0-alpha.30",
|
|
4
4
|
"license": "Apache-2.0",
|
|
5
5
|
"main": "./dist/production/index.js",
|
|
6
6
|
"typings": "./dist/types/index.d.ts",
|
|
@@ -23,16 +23,16 @@
|
|
|
23
23
|
}
|
|
24
24
|
},
|
|
25
25
|
"dependencies": {
|
|
26
|
-
"@contember/database": "2.1.0-alpha.
|
|
27
|
-
"@contember/database-migrations": "2.1.0-alpha.
|
|
28
|
-
"@contember/engine-common": "2.1.0-alpha.
|
|
29
|
-
"@contember/schema": "2.1.0-alpha.
|
|
30
|
-
"@contember/schema-utils": "2.1.0-alpha.
|
|
26
|
+
"@contember/database": "2.1.0-alpha.30",
|
|
27
|
+
"@contember/database-migrations": "2.1.0-alpha.30",
|
|
28
|
+
"@contember/engine-common": "2.1.0-alpha.30",
|
|
29
|
+
"@contember/schema": "2.1.0-alpha.30",
|
|
30
|
+
"@contember/schema-utils": "2.1.0-alpha.30",
|
|
31
31
|
"fast-deep-equal": "^3.1.3",
|
|
32
32
|
"rfc6902": "^5.1.1"
|
|
33
33
|
},
|
|
34
34
|
"devDependencies": {
|
|
35
|
-
"@contember/schema-definition": "2.1.0-alpha.
|
|
35
|
+
"@contember/schema-definition": "2.1.0-alpha.30"
|
|
36
36
|
},
|
|
37
37
|
"peerDependencies": {
|
|
38
38
|
"pg": "^8.9.0"
|
package/src/SchemaDiffer.ts
CHANGED
|
@@ -109,7 +109,7 @@ export class SchemaDiffer {
|
|
|
109
109
|
new UpdateEntityOrderByDiffer(),
|
|
110
110
|
new UpdateTargetDiffer(),
|
|
111
111
|
new CreateTargetDiffer(),
|
|
112
|
-
new UpdateTriggerDiffer(),
|
|
112
|
+
new UpdateTriggerDiffer(this.options),
|
|
113
113
|
new CreateTriggerDiffer(),
|
|
114
114
|
new RemoveTriggerDiffer(),
|
|
115
115
|
new RemoveTargetDiffer(),
|
|
@@ -30,7 +30,7 @@ import {
|
|
|
30
30
|
import { patchValidationSchemaModification, updateValidationSchemaModification } from './validation'
|
|
31
31
|
import { createIndexModification, removeIndexModification } from './indexes'
|
|
32
32
|
import { updateSettingsModification } from './settings'
|
|
33
|
-
import { createTriggerModification, removeTriggerModification, updateTriggerModification } from './actions'
|
|
33
|
+
import { createTriggerModification, patchTriggerModification, removeTriggerModification, updateTriggerModification } from './actions'
|
|
34
34
|
import { createTargetModification } from './actions/CreateTargetModification'
|
|
35
35
|
import { removeTargetModification } from './actions/RemoveTargetModification'
|
|
36
36
|
import { updateTargetModification } from './actions/UpdateTargetModification'
|
|
@@ -94,6 +94,7 @@ namespace ModificationHandlerFactory {
|
|
|
94
94
|
updateEntityOrderByModification,
|
|
95
95
|
createTriggerModification,
|
|
96
96
|
updateTriggerModification,
|
|
97
|
+
patchTriggerModification,
|
|
97
98
|
removeTriggerModification,
|
|
98
99
|
createTargetModification,
|
|
99
100
|
updateTargetModification,
|
|
@@ -44,7 +44,7 @@ export class UpdateAclSchemaDiffer implements Differ {
|
|
|
44
44
|
return []
|
|
45
45
|
}
|
|
46
46
|
const patch = createPatch(originalSchema.acl, updatedSchema.acl)
|
|
47
|
-
if (patch.length <= (this.options?.maxPatchSize ??
|
|
47
|
+
if (patch.length <= (this.options?.maxPatchSize ?? 1000)) {
|
|
48
48
|
return [patchAclSchemaModification.createModification({ patch })]
|
|
49
49
|
}
|
|
50
50
|
return [updateAclSchemaModification.createModification({ schema: updatedSchema.acl })]
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import { Actions } from '@contember/schema'
|
|
2
|
+
import { SchemaUpdater } from '../utils/schemaUpdateUtils'
|
|
3
|
+
import { createModificationType, ModificationHandler } from '../ModificationHandler'
|
|
4
|
+
import { applyPatch, Operation } from 'rfc6902'
|
|
5
|
+
import deepCopy from '../../utils/deepCopy'
|
|
6
|
+
|
|
7
|
+
export class PatchTriggerModificationHandler implements ModificationHandler<PatchTriggerModificationData> {
|
|
8
|
+
constructor(private readonly data: PatchTriggerModificationData) {}
|
|
9
|
+
|
|
10
|
+
public createSql(): void {}
|
|
11
|
+
|
|
12
|
+
public getSchemaUpdater(): SchemaUpdater {
|
|
13
|
+
return ({ schema }) => {
|
|
14
|
+
const trigger = deepCopy(schema.actions.triggers[this.data.triggerName])
|
|
15
|
+
|
|
16
|
+
if (!trigger) {
|
|
17
|
+
throw new Error(`Trigger ${this.data.triggerName} not found`)
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
const result = applyPatch(trigger, this.data.patch).filter(it => it !== null)
|
|
21
|
+
if (result.length > 0) {
|
|
22
|
+
throw result[0]
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
return {
|
|
26
|
+
...schema,
|
|
27
|
+
actions: {
|
|
28
|
+
...schema.actions,
|
|
29
|
+
triggers: {
|
|
30
|
+
...schema.actions.triggers,
|
|
31
|
+
[this.data.triggerName]: trigger,
|
|
32
|
+
},
|
|
33
|
+
},
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
describe() {
|
|
39
|
+
return { message: `Patch trigger ${this.data.triggerName}` }
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
export interface PatchTriggerModificationData {
|
|
44
|
+
triggerName: string
|
|
45
|
+
patch: Operation[]
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
export const patchTriggerModification = createModificationType({
|
|
49
|
+
id: 'patchTrigger',
|
|
50
|
+
handler: PatchTriggerModificationHandler,
|
|
51
|
+
})
|
|
@@ -2,6 +2,8 @@ import { Actions, Schema } from '@contember/schema'
|
|
|
2
2
|
import { SchemaUpdater } from '../utils/schemaUpdateUtils'
|
|
3
3
|
import { createModificationType, Differ, ModificationHandler } from '../ModificationHandler'
|
|
4
4
|
import deepEqual from 'fast-deep-equal'
|
|
5
|
+
import { createPatch } from 'rfc6902'
|
|
6
|
+
import { patchTriggerModification } from './PatchTriggerModification'
|
|
5
7
|
|
|
6
8
|
export class UpdateTriggerModificationHandler implements ModificationHandler<UpdateTriggerModificationData> {
|
|
7
9
|
constructor(private readonly data: UpdateTriggerModificationData) {
|
|
@@ -40,9 +42,28 @@ export const updateTriggerModification = createModificationType({
|
|
|
40
42
|
})
|
|
41
43
|
|
|
42
44
|
export class UpdateTriggerDiffer implements Differ {
|
|
45
|
+
constructor(
|
|
46
|
+
private readonly options?: {
|
|
47
|
+
maxPatchSize?: number
|
|
48
|
+
},
|
|
49
|
+
) {
|
|
50
|
+
}
|
|
51
|
+
|
|
43
52
|
createDiff(originalSchema: Schema, updatedSchema: Schema) {
|
|
44
53
|
return Object.entries(updatedSchema.actions.triggers)
|
|
45
54
|
.filter(([name, trigger]) => originalSchema.actions.triggers[name] && !deepEqual(trigger, originalSchema.actions.triggers[name]))
|
|
46
|
-
.map(([, trigger]) =>
|
|
55
|
+
.map(([name, trigger]) => {
|
|
56
|
+
const originalTrigger = originalSchema.actions.triggers[name]
|
|
57
|
+
|
|
58
|
+
const patch = createPatch(originalTrigger, trigger)
|
|
59
|
+
if (patch.length <= (this.options?.maxPatchSize ?? 1000)) {
|
|
60
|
+
return patchTriggerModification.createModification({
|
|
61
|
+
triggerName: name,
|
|
62
|
+
patch,
|
|
63
|
+
})
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
return updateTriggerModification.createModification({ trigger })
|
|
67
|
+
})
|
|
47
68
|
}
|
|
48
69
|
}
|
|
@@ -28,7 +28,9 @@ export class UpdateColumnDefinitionModificationHandler implements ModificationHa
|
|
|
28
28
|
|
|
29
29
|
const columnNameWrapped = wrapIdentifier(oldColumn.columnName)
|
|
30
30
|
const isChangedToArray = !oldColumn.list && newColumn.list
|
|
31
|
-
const usingCast =
|
|
31
|
+
const usingCast = isChangedToArray
|
|
32
|
+
? `CASE WHEN ${columnNameWrapped} IS NULL THEN ${newColumn.nullable ? 'NULL' : `ARRAY[]::${columnType}`} ELSE ARRAY[${columnNameWrapped}]::${columnType} END`
|
|
33
|
+
: `${columnNameWrapped}::${columnType}`
|
|
32
34
|
|
|
33
35
|
const seedExpression = formatSeedExpression({
|
|
34
36
|
model: this.schema.model,
|
|
@@ -34,8 +34,9 @@ export class CreateUniqueConstraintModificationHandler implements ModificationHa
|
|
|
34
34
|
const columnNameIds = columns.map(wrapIdentifier)
|
|
35
35
|
|
|
36
36
|
if ('index' in this.data.unique && this.data.unique.index) {
|
|
37
|
-
const nulls = this.data.unique.nulls === 'not distinct' ? ' NULLS NOT DISTINCT' : '
|
|
38
|
-
|
|
37
|
+
const nulls = this.data.unique.nulls === 'not distinct' ? ' NULLS NOT DISTINCT' : ''
|
|
38
|
+
const methodClause = this.data.unique.method ? ` USING ${this.data.unique.method}` : ''
|
|
39
|
+
builder.sql(`CREATE UNIQUE INDEX ON ${tableNameId}${methodClause} (${columnNameIds.join(', ')})${nulls}`)
|
|
39
40
|
} else {
|
|
40
41
|
let checkModifier = ''
|
|
41
42
|
if (this.data.unique.timing === 'deferred') {
|
|
@@ -31,7 +31,11 @@ export class RemoveEntityModificationHandler implements ModificationHandler<Remo
|
|
|
31
31
|
public createSql(builder: MigrationBuilder, options: ModificationHandlerCreateSqlOptions): void {
|
|
32
32
|
const entity = this.schema.model.entities[this.data.entityName]
|
|
33
33
|
if (entity.view) {
|
|
34
|
-
|
|
34
|
+
if (entity.view.materialized) {
|
|
35
|
+
builder.dropMaterializedView(entity.tableName)
|
|
36
|
+
} else {
|
|
37
|
+
builder.dropView(entity.tableName)
|
|
38
|
+
}
|
|
35
39
|
return
|
|
36
40
|
}
|
|
37
41
|
if (this.options.formatVersion >= VERSION_REMOVE_REFERENCING_RELATIONS) {
|
|
@@ -1,20 +1,57 @@
|
|
|
1
1
|
import { MigrationBuilder } from '@contember/database-migrations'
|
|
2
|
-
import { Schema } from '@contember/schema'
|
|
2
|
+
import { Model, Schema } from '@contember/schema'
|
|
3
3
|
import { SchemaUpdater, updateModel } from '../utils/schemaUpdateUtils'
|
|
4
4
|
import { createModificationType, Differ, ModificationHandler } from '../ModificationHandler'
|
|
5
5
|
import deepEqual from 'fast-deep-equal'
|
|
6
6
|
import { createCheck, getConstraintName } from './enumUtils'
|
|
7
|
+
import { getColumnSqlType } from '../utils/columnUtils'
|
|
7
8
|
|
|
8
9
|
export class UpdateEnumModificationHandler implements ModificationHandler<UpdateEnumModificationData> {
|
|
9
10
|
constructor(private readonly data: UpdateEnumModificationData, private readonly schema: Schema) {}
|
|
10
11
|
|
|
11
12
|
public createSql(builder: MigrationBuilder): void {
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
13
|
+
if (!this.requiresNewDomain()) {
|
|
14
|
+
builder.sql(`
|
|
15
|
+
ALTER DOMAIN "${this.data.enumName}"
|
|
16
|
+
DROP CONSTRAINT ${getConstraintName(this.data.enumName)}`)
|
|
17
|
+
builder.sql(`
|
|
18
|
+
ALTER DOMAIN "${this.data.enumName}"
|
|
19
|
+
ADD CONSTRAINT ${getConstraintName(this.data.enumName)} CHECK (${createCheck(this.data.values)})`)
|
|
20
|
+
} else {
|
|
21
|
+
/**
|
|
22
|
+
* Because postgres does not support altering domain constrains
|
|
23
|
+
* when used in composite types (like arrays) we need to:
|
|
24
|
+
* - create a new domain with the new constraint
|
|
25
|
+
* - update all the columns using the old domain to use the new domain
|
|
26
|
+
* - drop the old domain and rename the new domain to the old name
|
|
27
|
+
*/
|
|
28
|
+
const oldName = `${this.data.enumName}__old`
|
|
29
|
+
builder.renameDomain(this.data.enumName, oldName)
|
|
30
|
+
|
|
31
|
+
builder.createDomain(this.data.enumName, 'text', {
|
|
32
|
+
check: createCheck(this.data.values),
|
|
33
|
+
constraintName: getConstraintName(this.data.enumName),
|
|
34
|
+
})
|
|
35
|
+
for (const entity of Object.values(this.schema.model.entities)) {
|
|
36
|
+
for (const field of Object.values(entity.fields)) {
|
|
37
|
+
if (field.type === Model.ColumnType.Enum && field.columnType === this.data.enumName) {
|
|
38
|
+
builder.alterColumn(entity.tableName, field.columnName, {
|
|
39
|
+
type: getColumnSqlType(field),
|
|
40
|
+
})
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
builder.dropDomain(oldName)
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
private requiresNewDomain(): boolean {
|
|
50
|
+
return Object.values(this.schema.model.entities).some(it => {
|
|
51
|
+
return Object.values(it.fields).some(field => {
|
|
52
|
+
return field.type === Model.ColumnType.Enum && field.columnType === this.data.enumName && field.list
|
|
53
|
+
})
|
|
54
|
+
})
|
|
18
55
|
}
|
|
19
56
|
|
|
20
57
|
public getSchemaUpdater(): SchemaUpdater {
|
|
@@ -28,8 +28,9 @@ export class CreateIndexModificationHandler implements ModificationHandler<Creat
|
|
|
28
28
|
|
|
29
29
|
const tableNameId = wrapIdentifier(entity.tableName)
|
|
30
30
|
const columnNameIds = columns.map(wrapIdentifier)
|
|
31
|
+
const methodClause = this.data.index.method ? ` USING ${this.data.index.method}` : ''
|
|
31
32
|
|
|
32
|
-
builder.sql(`CREATE INDEX ON ${tableNameId} (${columnNameIds.join(', ')})`)
|
|
33
|
+
builder.sql(`CREATE INDEX ON ${tableNameId}${methodClause} (${columnNameIds.join(', ')})`)
|
|
33
34
|
|
|
34
35
|
invalidateDatabaseMetadata()
|
|
35
36
|
}
|
|
@@ -47,8 +48,9 @@ export class CreateIndexModificationHandler implements ModificationHandler<Creat
|
|
|
47
48
|
}
|
|
48
49
|
|
|
49
50
|
describe() {
|
|
51
|
+
const methodText = this.data.index.method ? ` using ${this.data.index.method}` : ''
|
|
50
52
|
return {
|
|
51
|
-
message: `Create index(${this.data.index.fields.join(', ')}) on entity ${this.data.entityName}`,
|
|
53
|
+
message: `Create index(${this.data.index.fields.join(', ')})${methodText} on entity ${this.data.entityName}`,
|
|
52
54
|
}
|
|
53
55
|
}
|
|
54
56
|
}
|
|
@@ -17,6 +17,34 @@ namespace SchemaWithIndex {
|
|
|
17
17
|
}
|
|
18
18
|
}
|
|
19
19
|
|
|
20
|
+
namespace SchemaWithGinIndex {
|
|
21
|
+
@def.Index({ fields: ['title'], method: 'gin' })
|
|
22
|
+
export class Article {
|
|
23
|
+
title = def.stringColumn()
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
namespace SchemaWithGistIndex {
|
|
28
|
+
@def.Index({ fields: ['title'], method: 'gist' })
|
|
29
|
+
export class Article {
|
|
30
|
+
title = def.stringColumn()
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
namespace SchemaWithBtreeIndex {
|
|
35
|
+
@def.Index({ fields: ['title'], method: 'btree' })
|
|
36
|
+
export class Article {
|
|
37
|
+
title = def.stringColumn()
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
namespace SchemaWithHashIndex {
|
|
42
|
+
@def.Index({ fields: ['title'], method: 'hash' })
|
|
43
|
+
export class Article {
|
|
44
|
+
title = def.stringColumn()
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
|
|
20
48
|
|
|
21
49
|
describe('create index', () => testMigrations({
|
|
22
50
|
original: createSchema(SchemaWithoutIndex),
|
|
@@ -54,3 +82,75 @@ describe('drop index', () => testMigrations({
|
|
|
54
82
|
uniqueConstraints: [],
|
|
55
83
|
}),
|
|
56
84
|
}))
|
|
85
|
+
|
|
86
|
+
|
|
87
|
+
describe('create index with GIN method', () => testMigrations({
|
|
88
|
+
original: createSchema(SchemaWithoutIndex),
|
|
89
|
+
updated: createSchema(SchemaWithGinIndex),
|
|
90
|
+
diff: [
|
|
91
|
+
{
|
|
92
|
+
modification: 'createIndex',
|
|
93
|
+
entityName: 'Article',
|
|
94
|
+
index: { fields: ['title'], method: 'gin' },
|
|
95
|
+
},
|
|
96
|
+
],
|
|
97
|
+
sql: SQL`CREATE INDEX ON "article" USING gin ("title");`,
|
|
98
|
+
}))
|
|
99
|
+
|
|
100
|
+
describe('change index method from btree to gin', () => testMigrations({
|
|
101
|
+
original: createSchema(SchemaWithBtreeIndex),
|
|
102
|
+
updated: createSchema(SchemaWithGinIndex),
|
|
103
|
+
diff: [
|
|
104
|
+
{
|
|
105
|
+
modification: 'removeIndex',
|
|
106
|
+
entityName: 'Article',
|
|
107
|
+
fields: ['title'],
|
|
108
|
+
},
|
|
109
|
+
{
|
|
110
|
+
modification: 'createIndex',
|
|
111
|
+
entityName: 'Article',
|
|
112
|
+
index: { fields: ['title'], method: 'gin' },
|
|
113
|
+
},
|
|
114
|
+
],
|
|
115
|
+
sql: SQL`DROP INDEX "idx_article_title";
|
|
116
|
+
CREATE INDEX ON "article" USING gin ("title");`,
|
|
117
|
+
databaseMetadata: createDatabaseMetadata({
|
|
118
|
+
foreignKeys: [],
|
|
119
|
+
indexes: [{
|
|
120
|
+
tableName: 'article',
|
|
121
|
+
columnNames: ['title'],
|
|
122
|
+
indexName: 'idx_article_title',
|
|
123
|
+
unique: false,
|
|
124
|
+
}],
|
|
125
|
+
uniqueConstraints: [],
|
|
126
|
+
}),
|
|
127
|
+
}))
|
|
128
|
+
|
|
129
|
+
describe('change from regular index to method-specific index', () => testMigrations({
|
|
130
|
+
original: createSchema(SchemaWithIndex),
|
|
131
|
+
updated: createSchema(SchemaWithHashIndex),
|
|
132
|
+
diff: [
|
|
133
|
+
{
|
|
134
|
+
modification: 'removeIndex',
|
|
135
|
+
entityName: 'Article',
|
|
136
|
+
fields: ['title'],
|
|
137
|
+
},
|
|
138
|
+
{
|
|
139
|
+
modification: 'createIndex',
|
|
140
|
+
entityName: 'Article',
|
|
141
|
+
index: { fields: ['title'], method: 'hash' },
|
|
142
|
+
},
|
|
143
|
+
],
|
|
144
|
+
sql: SQL`DROP INDEX "idx_article_title";
|
|
145
|
+
CREATE INDEX ON "article" USING hash ("title");`,
|
|
146
|
+
databaseMetadata: createDatabaseMetadata({
|
|
147
|
+
foreignKeys: [],
|
|
148
|
+
indexes: [{
|
|
149
|
+
tableName: 'article',
|
|
150
|
+
columnNames: ['title'],
|
|
151
|
+
indexName: 'idx_article_title',
|
|
152
|
+
unique: false,
|
|
153
|
+
}],
|
|
154
|
+
uniqueConstraints: [],
|
|
155
|
+
}),
|
|
156
|
+
}))
|
|
@@ -104,7 +104,7 @@ describe('change unique timing', () => testMigrations({
|
|
|
104
104
|
},
|
|
105
105
|
}),
|
|
106
106
|
],
|
|
107
|
-
sql: SQL`ALTER TABLE "author" DROP CONSTRAINT "uniq_author_email";
|
|
107
|
+
sql: SQL`ALTER TABLE "author" DROP CONSTRAINT "uniq_author_email";
|
|
108
108
|
ALTER TABLE "author" ADD UNIQUE ("email") DEFERRABLE;`,
|
|
109
109
|
databaseMetadata: createDatabaseMetadata({
|
|
110
110
|
foreignKeys: [],
|
|
@@ -233,5 +233,157 @@ describe('create unique index', () => testMigrations({
|
|
|
233
233
|
},
|
|
234
234
|
}),
|
|
235
235
|
],
|
|
236
|
-
sql: SQL`CREATE UNIQUE INDEX ON "author" ("email")
|
|
236
|
+
sql: SQL`CREATE UNIQUE INDEX ON "author" ("email");`,
|
|
237
|
+
}))
|
|
238
|
+
|
|
239
|
+
namespace AuthorWithUniqueGinIndex {
|
|
240
|
+
@c.Unique({ fields: ['email'], index: true, method: 'gin' })
|
|
241
|
+
export class Author {
|
|
242
|
+
email = c.stringColumn()
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
namespace AuthorWithUniqueGistIndex {
|
|
247
|
+
@c.Unique({ fields: ['email'], index: true, method: 'gist' })
|
|
248
|
+
export class Author {
|
|
249
|
+
email = c.stringColumn()
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
namespace AuthorWithUniqueBtreeIndex {
|
|
254
|
+
@c.Unique({ fields: ['email'], index: true, method: 'btree', nulls: 'not distinct' })
|
|
255
|
+
export class Author {
|
|
256
|
+
email = c.stringColumn()
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
describe('create unique index with GIN method', () => testMigrations({
|
|
261
|
+
original: createSchema({
|
|
262
|
+
Author: class Author {
|
|
263
|
+
email = c.stringColumn()
|
|
264
|
+
},
|
|
265
|
+
}),
|
|
266
|
+
updated: createSchema(AuthorWithUniqueGinIndex),
|
|
267
|
+
diff: [
|
|
268
|
+
createUniqueConstraintModification.createModification({
|
|
269
|
+
entityName: 'Author',
|
|
270
|
+
unique: {
|
|
271
|
+
fields: ['email'],
|
|
272
|
+
index: true,
|
|
273
|
+
method: 'gin',
|
|
274
|
+
},
|
|
275
|
+
}),
|
|
276
|
+
],
|
|
277
|
+
sql: SQL`CREATE UNIQUE INDEX ON "author" USING gin ("email");`,
|
|
278
|
+
}))
|
|
279
|
+
|
|
280
|
+
describe('create unique index with GiST method', () => testMigrations({
|
|
281
|
+
original: createSchema({
|
|
282
|
+
Author: class Author {
|
|
283
|
+
email = c.stringColumn()
|
|
284
|
+
},
|
|
285
|
+
}),
|
|
286
|
+
updated: createSchema(AuthorWithUniqueGistIndex),
|
|
287
|
+
diff: [
|
|
288
|
+
createUniqueConstraintModification.createModification({
|
|
289
|
+
entityName: 'Author',
|
|
290
|
+
unique: {
|
|
291
|
+
fields: ['email'],
|
|
292
|
+
index: true,
|
|
293
|
+
method: 'gist',
|
|
294
|
+
},
|
|
295
|
+
}),
|
|
296
|
+
],
|
|
297
|
+
sql: SQL`CREATE UNIQUE INDEX ON "author" USING gist ("email");`,
|
|
298
|
+
}))
|
|
299
|
+
|
|
300
|
+
describe('create unique index with btree method and nulls not distinct', () => testMigrations({
|
|
301
|
+
original: createSchema({
|
|
302
|
+
Author: class Author {
|
|
303
|
+
email = c.stringColumn()
|
|
304
|
+
},
|
|
305
|
+
}),
|
|
306
|
+
updated: createSchema(AuthorWithUniqueBtreeIndex),
|
|
307
|
+
diff: [
|
|
308
|
+
createUniqueConstraintModification.createModification({
|
|
309
|
+
entityName: 'Author',
|
|
310
|
+
unique: {
|
|
311
|
+
fields: ['email'],
|
|
312
|
+
index: true,
|
|
313
|
+
method: 'btree',
|
|
314
|
+
nulls: 'not distinct',
|
|
315
|
+
},
|
|
316
|
+
}),
|
|
317
|
+
],
|
|
318
|
+
sql: SQL`CREATE UNIQUE INDEX ON "author" USING btree ("email") NULLS NOT DISTINCT;`,
|
|
319
|
+
}))
|
|
320
|
+
|
|
321
|
+
describe('change unique index method from gin to gist', () => testMigrations({
|
|
322
|
+
original: createSchema(AuthorWithUniqueGinIndex),
|
|
323
|
+
updated: createSchema(AuthorWithUniqueGistIndex),
|
|
324
|
+
diff: [
|
|
325
|
+
removeUniqueConstraintModification.createModification({
|
|
326
|
+
entityName: 'Author',
|
|
327
|
+
unique: {
|
|
328
|
+
fields: ['email'],
|
|
329
|
+
index: true,
|
|
330
|
+
method: 'gin',
|
|
331
|
+
},
|
|
332
|
+
}),
|
|
333
|
+
createUniqueConstraintModification.createModification({
|
|
334
|
+
entityName: 'Author',
|
|
335
|
+
unique: {
|
|
336
|
+
fields: ['email'],
|
|
337
|
+
index: true,
|
|
338
|
+
method: 'gist',
|
|
339
|
+
},
|
|
340
|
+
}),
|
|
341
|
+
],
|
|
342
|
+
sql: SQL`DROP INDEX "uniq_author_email";
|
|
343
|
+
CREATE UNIQUE INDEX ON "author" USING gist ("email");`,
|
|
344
|
+
databaseMetadata: createDatabaseMetadata({
|
|
345
|
+
foreignKeys: [],
|
|
346
|
+
indexes: [{
|
|
347
|
+
tableName: 'author',
|
|
348
|
+
columnNames: ['email'],
|
|
349
|
+
indexName: 'uniq_author_email',
|
|
350
|
+
unique: true,
|
|
351
|
+
}],
|
|
352
|
+
uniqueConstraints: [],
|
|
353
|
+
}),
|
|
354
|
+
}))
|
|
355
|
+
|
|
356
|
+
describe('change from regular unique index to method-specific unique index', () => testMigrations({
|
|
357
|
+
original: createSchema(AuthorWithUniqueIndex),
|
|
358
|
+
updated: createSchema(AuthorWithUniqueGinIndex),
|
|
359
|
+
diff: [
|
|
360
|
+
removeUniqueConstraintModification.createModification({
|
|
361
|
+
entityName: 'Author',
|
|
362
|
+
unique: {
|
|
363
|
+
fields: ['email'],
|
|
364
|
+
index: true,
|
|
365
|
+
nulls: 'not distinct',
|
|
366
|
+
},
|
|
367
|
+
}),
|
|
368
|
+
createUniqueConstraintModification.createModification({
|
|
369
|
+
entityName: 'Author',
|
|
370
|
+
unique: {
|
|
371
|
+
fields: ['email'],
|
|
372
|
+
index: true,
|
|
373
|
+
method: 'gin',
|
|
374
|
+
},
|
|
375
|
+
}),
|
|
376
|
+
],
|
|
377
|
+
sql: SQL`DROP INDEX "uniq_author_email";
|
|
378
|
+
CREATE UNIQUE INDEX ON "author" USING gin ("email");`,
|
|
379
|
+
databaseMetadata: createDatabaseMetadata({
|
|
380
|
+
foreignKeys: [],
|
|
381
|
+
indexes: [{
|
|
382
|
+
tableName: 'author',
|
|
383
|
+
columnNames: ['email'],
|
|
384
|
+
indexName: 'uniq_author_email',
|
|
385
|
+
unique: true,
|
|
386
|
+
}],
|
|
387
|
+
uniqueConstraints: [],
|
|
388
|
+
}),
|
|
237
389
|
}))
|