@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.
Files changed (114) hide show
  1. package/dist/development/src/SchemaDiffer.cjs +1 -1
  2. package/dist/development/src/SchemaDiffer.cjs.map +1 -1
  3. package/dist/development/src/SchemaDiffer.js +1 -1
  4. package/dist/development/src/SchemaDiffer.js.map +1 -1
  5. package/dist/development/src/modifications/ModificationHandlerFactory.cjs +2 -0
  6. package/dist/development/src/modifications/ModificationHandlerFactory.cjs.map +1 -1
  7. package/dist/development/src/modifications/ModificationHandlerFactory.js +2 -0
  8. package/dist/development/src/modifications/ModificationHandlerFactory.js.map +1 -1
  9. package/dist/development/src/modifications/acl/UpdateAclSchemaModification.cjs +1 -1
  10. package/dist/development/src/modifications/acl/UpdateAclSchemaModification.cjs.map +1 -1
  11. package/dist/development/src/modifications/acl/UpdateAclSchemaModification.js +1 -1
  12. package/dist/development/src/modifications/acl/UpdateAclSchemaModification.js.map +1 -1
  13. package/dist/development/src/modifications/actions/PatchTriggerModification.cjs +44 -0
  14. package/dist/development/src/modifications/actions/PatchTriggerModification.cjs.map +1 -0
  15. package/dist/development/src/modifications/actions/PatchTriggerModification.js +44 -0
  16. package/dist/development/src/modifications/actions/PatchTriggerModification.js.map +1 -0
  17. package/dist/development/src/modifications/actions/UpdateTriggerModification.cjs +16 -1
  18. package/dist/development/src/modifications/actions/UpdateTriggerModification.cjs.map +1 -1
  19. package/dist/development/src/modifications/actions/UpdateTriggerModification.js +16 -1
  20. package/dist/development/src/modifications/actions/UpdateTriggerModification.js.map +1 -1
  21. package/dist/development/src/modifications/columns/UpdateColumnDefinitionModification.cjs +1 -1
  22. package/dist/development/src/modifications/columns/UpdateColumnDefinitionModification.cjs.map +1 -1
  23. package/dist/development/src/modifications/columns/UpdateColumnDefinitionModification.js +1 -1
  24. package/dist/development/src/modifications/columns/UpdateColumnDefinitionModification.js.map +1 -1
  25. package/dist/development/src/modifications/constraints/CreateUniqueConstraintModification.cjs +3 -2
  26. package/dist/development/src/modifications/constraints/CreateUniqueConstraintModification.cjs.map +1 -1
  27. package/dist/development/src/modifications/constraints/CreateUniqueConstraintModification.js +3 -2
  28. package/dist/development/src/modifications/constraints/CreateUniqueConstraintModification.js.map +1 -1
  29. package/dist/development/src/modifications/entities/RemoveEntityModification.cjs +5 -1
  30. package/dist/development/src/modifications/entities/RemoveEntityModification.cjs.map +1 -1
  31. package/dist/development/src/modifications/entities/RemoveEntityModification.js +5 -1
  32. package/dist/development/src/modifications/entities/RemoveEntityModification.js.map +1 -1
  33. package/dist/development/src/modifications/enums/UpdateEnumModification.cjs +36 -8
  34. package/dist/development/src/modifications/enums/UpdateEnumModification.cjs.map +1 -1
  35. package/dist/development/src/modifications/enums/UpdateEnumModification.js +34 -6
  36. package/dist/development/src/modifications/enums/UpdateEnumModification.js.map +1 -1
  37. package/dist/development/src/modifications/indexes/CreateIndexModification.cjs +4 -2
  38. package/dist/development/src/modifications/indexes/CreateIndexModification.cjs.map +1 -1
  39. package/dist/development/src/modifications/indexes/CreateIndexModification.js +4 -2
  40. package/dist/development/src/modifications/indexes/CreateIndexModification.js.map +1 -1
  41. package/dist/production/src/SchemaDiffer.cjs +1 -1
  42. package/dist/production/src/SchemaDiffer.cjs.map +1 -1
  43. package/dist/production/src/SchemaDiffer.js +1 -1
  44. package/dist/production/src/SchemaDiffer.js.map +1 -1
  45. package/dist/production/src/modifications/ModificationHandlerFactory.cjs +2 -0
  46. package/dist/production/src/modifications/ModificationHandlerFactory.cjs.map +1 -1
  47. package/dist/production/src/modifications/ModificationHandlerFactory.js +2 -0
  48. package/dist/production/src/modifications/ModificationHandlerFactory.js.map +1 -1
  49. package/dist/production/src/modifications/acl/UpdateAclSchemaModification.cjs +1 -1
  50. package/dist/production/src/modifications/acl/UpdateAclSchemaModification.cjs.map +1 -1
  51. package/dist/production/src/modifications/acl/UpdateAclSchemaModification.js +1 -1
  52. package/dist/production/src/modifications/acl/UpdateAclSchemaModification.js.map +1 -1
  53. package/dist/production/src/modifications/actions/PatchTriggerModification.cjs +44 -0
  54. package/dist/production/src/modifications/actions/PatchTriggerModification.cjs.map +1 -0
  55. package/dist/production/src/modifications/actions/PatchTriggerModification.js +44 -0
  56. package/dist/production/src/modifications/actions/PatchTriggerModification.js.map +1 -0
  57. package/dist/production/src/modifications/actions/UpdateTriggerModification.cjs +16 -1
  58. package/dist/production/src/modifications/actions/UpdateTriggerModification.cjs.map +1 -1
  59. package/dist/production/src/modifications/actions/UpdateTriggerModification.js +16 -1
  60. package/dist/production/src/modifications/actions/UpdateTriggerModification.js.map +1 -1
  61. package/dist/production/src/modifications/columns/UpdateColumnDefinitionModification.cjs +1 -1
  62. package/dist/production/src/modifications/columns/UpdateColumnDefinitionModification.cjs.map +1 -1
  63. package/dist/production/src/modifications/columns/UpdateColumnDefinitionModification.js +1 -1
  64. package/dist/production/src/modifications/columns/UpdateColumnDefinitionModification.js.map +1 -1
  65. package/dist/production/src/modifications/constraints/CreateUniqueConstraintModification.cjs +3 -2
  66. package/dist/production/src/modifications/constraints/CreateUniqueConstraintModification.cjs.map +1 -1
  67. package/dist/production/src/modifications/constraints/CreateUniqueConstraintModification.js +3 -2
  68. package/dist/production/src/modifications/constraints/CreateUniqueConstraintModification.js.map +1 -1
  69. package/dist/production/src/modifications/entities/RemoveEntityModification.cjs +5 -1
  70. package/dist/production/src/modifications/entities/RemoveEntityModification.cjs.map +1 -1
  71. package/dist/production/src/modifications/entities/RemoveEntityModification.js +5 -1
  72. package/dist/production/src/modifications/entities/RemoveEntityModification.js.map +1 -1
  73. package/dist/production/src/modifications/enums/UpdateEnumModification.cjs +36 -8
  74. package/dist/production/src/modifications/enums/UpdateEnumModification.cjs.map +1 -1
  75. package/dist/production/src/modifications/enums/UpdateEnumModification.js +34 -6
  76. package/dist/production/src/modifications/enums/UpdateEnumModification.js.map +1 -1
  77. package/dist/production/src/modifications/indexes/CreateIndexModification.cjs +4 -2
  78. package/dist/production/src/modifications/indexes/CreateIndexModification.cjs.map +1 -1
  79. package/dist/production/src/modifications/indexes/CreateIndexModification.js +4 -2
  80. package/dist/production/src/modifications/indexes/CreateIndexModification.js.map +1 -1
  81. package/dist/tests/cases/integration/patchTrigger.test.d.ts +2 -0
  82. package/dist/tests/cases/integration/patchTrigger.test.d.ts.map +1 -0
  83. package/dist/tests/tsconfig.tsbuildinfo +1 -1
  84. package/dist/types/modifications/ModificationHandlerFactory.d.ts.map +1 -1
  85. package/dist/types/modifications/actions/PatchTriggerModification.d.ts +18 -0
  86. package/dist/types/modifications/actions/PatchTriggerModification.d.ts.map +1 -0
  87. package/dist/types/modifications/actions/UpdateTriggerModification.d.ts +5 -1
  88. package/dist/types/modifications/actions/UpdateTriggerModification.d.ts.map +1 -1
  89. package/dist/types/modifications/actions/index.d.ts +1 -0
  90. package/dist/types/modifications/actions/index.d.ts.map +1 -1
  91. package/dist/types/modifications/columns/UpdateColumnDefinitionModification.d.ts.map +1 -1
  92. package/dist/types/modifications/constraints/CreateUniqueConstraintModification.d.ts.map +1 -1
  93. package/dist/types/modifications/entities/RemoveEntityModification.d.ts.map +1 -1
  94. package/dist/types/modifications/enums/UpdateEnumModification.d.ts +1 -0
  95. package/dist/types/modifications/enums/UpdateEnumModification.d.ts.map +1 -1
  96. package/dist/types/modifications/indexes/CreateIndexModification.d.ts.map +1 -1
  97. package/dist/types/tsconfig.tsbuildinfo +1 -1
  98. package/package.json +7 -7
  99. package/src/SchemaDiffer.ts +1 -1
  100. package/src/modifications/ModificationHandlerFactory.ts +2 -1
  101. package/src/modifications/acl/UpdateAclSchemaModification.ts +1 -1
  102. package/src/modifications/actions/PatchTriggerModification.ts +51 -0
  103. package/src/modifications/actions/UpdateTriggerModification.ts +22 -1
  104. package/src/modifications/actions/index.ts +1 -0
  105. package/src/modifications/columns/UpdateColumnDefinitionModification.ts +3 -1
  106. package/src/modifications/constraints/CreateUniqueConstraintModification.ts +3 -2
  107. package/src/modifications/entities/RemoveEntityModification.ts +5 -1
  108. package/src/modifications/enums/UpdateEnumModification.ts +44 -7
  109. package/src/modifications/indexes/CreateIndexModification.ts +4 -2
  110. package/tests/cases/integration/createAndDropIndex.test.ts +100 -0
  111. package/tests/cases/integration/createUnique.test.ts +154 -2
  112. package/tests/cases/integration/patchTrigger.test.ts +184 -0
  113. package/tests/cases/integration/updateColumnDefinition.test.ts +28 -1
  114. 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",
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.3",
27
- "@contember/database-migrations": "2.1.0-alpha.3",
28
- "@contember/engine-common": "2.1.0-alpha.3",
29
- "@contember/schema": "2.1.0-alpha.3",
30
- "@contember/schema-utils": "2.1.0-alpha.3",
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.3"
35
+ "@contember/schema-definition": "2.1.0-alpha.30"
36
36
  },
37
37
  "peerDependencies": {
38
38
  "pg": "^8.9.0"
@@ -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 ?? 100)) {
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]) => updateTriggerModification.createModification({ 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
  }
@@ -1,3 +1,4 @@
1
1
  export * from './CreateTriggerModification'
2
2
  export * from './RemoveTriggerModification'
3
3
  export * from './UpdateTriggerModification'
4
+ export * from './PatchTriggerModification'
@@ -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 = (isChangedToArray ? `ARRAY[${columnNameWrapped}]` : columnNameWrapped) + `::${columnType}`
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' : ' NULLS DISTINCT'
38
- builder.sql(`CREATE UNIQUE INDEX ON ${tableNameId} (${columnNameIds.join(', ')})${nulls}`)
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
- builder.dropView(entity.tableName)
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
- builder.sql(`
13
- ALTER DOMAIN "${this.data.enumName}"
14
- DROP CONSTRAINT ${getConstraintName(this.data.enumName)}`)
15
- builder.sql(`
16
- ALTER DOMAIN "${this.data.enumName}"
17
- ADD CONSTRAINT ${getConstraintName(this.data.enumName)} CHECK (${createCheck(this.data.values)})`)
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") NULLS DISTINCT;`,
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
  }))