@contember/schema-migrations 2.0.1 → 2.1.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.
Files changed (153) hide show
  1. package/dist/development/src/MigrationDescriber.cjs +2 -1
  2. package/dist/development/src/MigrationDescriber.cjs.map +1 -1
  3. package/dist/development/src/MigrationDescriber.js +2 -1
  4. package/dist/development/src/MigrationDescriber.js.map +1 -1
  5. package/dist/development/src/modifications/columns/CreateColumnModification.cjs +2 -1
  6. package/dist/development/src/modifications/columns/CreateColumnModification.cjs.map +1 -1
  7. package/dist/development/src/modifications/columns/CreateColumnModification.js +2 -1
  8. package/dist/development/src/modifications/columns/CreateColumnModification.js.map +1 -1
  9. package/dist/development/src/modifications/columns/UpdateColumnDefinitionModification.cjs +8 -3
  10. package/dist/development/src/modifications/columns/UpdateColumnDefinitionModification.cjs.map +1 -1
  11. package/dist/development/src/modifications/columns/UpdateColumnDefinitionModification.js +8 -3
  12. package/dist/development/src/modifications/columns/UpdateColumnDefinitionModification.js.map +1 -1
  13. package/dist/development/src/modifications/constraints/CreateUniqueConstraintModification.cjs +15 -9
  14. package/dist/development/src/modifications/constraints/CreateUniqueConstraintModification.cjs.map +1 -1
  15. package/dist/development/src/modifications/constraints/CreateUniqueConstraintModification.js +15 -9
  16. package/dist/development/src/modifications/constraints/CreateUniqueConstraintModification.js.map +1 -1
  17. package/dist/development/src/modifications/constraints/RemoveUniqueConstraintModification.cjs +34 -16
  18. package/dist/development/src/modifications/constraints/RemoveUniqueConstraintModification.cjs.map +1 -1
  19. package/dist/development/src/modifications/constraints/RemoveUniqueConstraintModification.js +34 -16
  20. package/dist/development/src/modifications/constraints/RemoveUniqueConstraintModification.js.map +1 -1
  21. package/dist/development/src/modifications/entities/CreateEntityModification.cjs +2 -1
  22. package/dist/development/src/modifications/entities/CreateEntityModification.cjs.map +1 -1
  23. package/dist/development/src/modifications/entities/CreateEntityModification.js +2 -1
  24. package/dist/development/src/modifications/entities/CreateEntityModification.js.map +1 -1
  25. package/dist/development/src/modifications/entities/CreateViewModification.cjs +12 -2
  26. package/dist/development/src/modifications/entities/CreateViewModification.cjs.map +1 -1
  27. package/dist/development/src/modifications/entities/CreateViewModification.js +12 -2
  28. package/dist/development/src/modifications/entities/CreateViewModification.js.map +1 -1
  29. package/dist/development/src/modifications/indexes/CreateIndexModification.cjs +2 -2
  30. package/dist/development/src/modifications/indexes/CreateIndexModification.cjs.map +1 -1
  31. package/dist/development/src/modifications/indexes/CreateIndexModification.js +2 -2
  32. package/dist/development/src/modifications/indexes/CreateIndexModification.js.map +1 -1
  33. package/dist/development/src/modifications/indexes/RemoveIndexModification.cjs +3 -3
  34. package/dist/development/src/modifications/indexes/RemoveIndexModification.cjs.map +1 -1
  35. package/dist/development/src/modifications/indexes/RemoveIndexModification.js +3 -3
  36. package/dist/development/src/modifications/indexes/RemoveIndexModification.js.map +1 -1
  37. package/dist/development/src/modifications/upgrade/RemoveIndexNamesModification.cjs +8 -2
  38. package/dist/development/src/modifications/upgrade/RemoveIndexNamesModification.cjs.map +1 -1
  39. package/dist/development/src/modifications/upgrade/RemoveIndexNamesModification.js +8 -2
  40. package/dist/development/src/modifications/upgrade/RemoveIndexNamesModification.js.map +1 -1
  41. package/dist/development/src/modifications/utils/columnUtils.cjs +1 -1
  42. package/dist/development/src/modifications/utils/columnUtils.cjs.map +1 -1
  43. package/dist/development/src/modifications/utils/columnUtils.js +1 -1
  44. package/dist/development/src/modifications/utils/columnUtils.js.map +1 -1
  45. package/dist/development/src/modifications/utils/schemaUpdateUtils.cjs +1 -0
  46. package/dist/development/src/modifications/utils/schemaUpdateUtils.cjs.map +1 -1
  47. package/dist/development/src/modifications/utils/schemaUpdateUtils.js +1 -0
  48. package/dist/development/src/modifications/utils/schemaUpdateUtils.js.map +1 -1
  49. package/dist/production/src/MigrationDescriber.cjs +2 -1
  50. package/dist/production/src/MigrationDescriber.cjs.map +1 -1
  51. package/dist/production/src/MigrationDescriber.js +2 -1
  52. package/dist/production/src/MigrationDescriber.js.map +1 -1
  53. package/dist/production/src/modifications/columns/CreateColumnModification.cjs +2 -1
  54. package/dist/production/src/modifications/columns/CreateColumnModification.cjs.map +1 -1
  55. package/dist/production/src/modifications/columns/CreateColumnModification.js +2 -1
  56. package/dist/production/src/modifications/columns/CreateColumnModification.js.map +1 -1
  57. package/dist/production/src/modifications/columns/UpdateColumnDefinitionModification.cjs +8 -3
  58. package/dist/production/src/modifications/columns/UpdateColumnDefinitionModification.cjs.map +1 -1
  59. package/dist/production/src/modifications/columns/UpdateColumnDefinitionModification.js +8 -3
  60. package/dist/production/src/modifications/columns/UpdateColumnDefinitionModification.js.map +1 -1
  61. package/dist/production/src/modifications/constraints/CreateUniqueConstraintModification.cjs +15 -9
  62. package/dist/production/src/modifications/constraints/CreateUniqueConstraintModification.cjs.map +1 -1
  63. package/dist/production/src/modifications/constraints/CreateUniqueConstraintModification.js +15 -9
  64. package/dist/production/src/modifications/constraints/CreateUniqueConstraintModification.js.map +1 -1
  65. package/dist/production/src/modifications/constraints/RemoveUniqueConstraintModification.cjs +34 -16
  66. package/dist/production/src/modifications/constraints/RemoveUniqueConstraintModification.cjs.map +1 -1
  67. package/dist/production/src/modifications/constraints/RemoveUniqueConstraintModification.js +34 -16
  68. package/dist/production/src/modifications/constraints/RemoveUniqueConstraintModification.js.map +1 -1
  69. package/dist/production/src/modifications/entities/CreateEntityModification.cjs +2 -1
  70. package/dist/production/src/modifications/entities/CreateEntityModification.cjs.map +1 -1
  71. package/dist/production/src/modifications/entities/CreateEntityModification.js +2 -1
  72. package/dist/production/src/modifications/entities/CreateEntityModification.js.map +1 -1
  73. package/dist/production/src/modifications/entities/CreateViewModification.cjs +12 -2
  74. package/dist/production/src/modifications/entities/CreateViewModification.cjs.map +1 -1
  75. package/dist/production/src/modifications/entities/CreateViewModification.js +12 -2
  76. package/dist/production/src/modifications/entities/CreateViewModification.js.map +1 -1
  77. package/dist/production/src/modifications/indexes/CreateIndexModification.cjs +2 -2
  78. package/dist/production/src/modifications/indexes/CreateIndexModification.cjs.map +1 -1
  79. package/dist/production/src/modifications/indexes/CreateIndexModification.js +2 -2
  80. package/dist/production/src/modifications/indexes/CreateIndexModification.js.map +1 -1
  81. package/dist/production/src/modifications/indexes/RemoveIndexModification.cjs +3 -3
  82. package/dist/production/src/modifications/indexes/RemoveIndexModification.cjs.map +1 -1
  83. package/dist/production/src/modifications/indexes/RemoveIndexModification.js +3 -3
  84. package/dist/production/src/modifications/indexes/RemoveIndexModification.js.map +1 -1
  85. package/dist/production/src/modifications/upgrade/RemoveIndexNamesModification.cjs +8 -2
  86. package/dist/production/src/modifications/upgrade/RemoveIndexNamesModification.cjs.map +1 -1
  87. package/dist/production/src/modifications/upgrade/RemoveIndexNamesModification.js +8 -2
  88. package/dist/production/src/modifications/upgrade/RemoveIndexNamesModification.js.map +1 -1
  89. package/dist/production/src/modifications/utils/columnUtils.cjs +1 -1
  90. package/dist/production/src/modifications/utils/columnUtils.cjs.map +1 -1
  91. package/dist/production/src/modifications/utils/columnUtils.js +1 -1
  92. package/dist/production/src/modifications/utils/columnUtils.js.map +1 -1
  93. package/dist/production/src/modifications/utils/schemaUpdateUtils.cjs +1 -0
  94. package/dist/production/src/modifications/utils/schemaUpdateUtils.cjs.map +1 -1
  95. package/dist/production/src/modifications/utils/schemaUpdateUtils.js +1 -0
  96. package/dist/production/src/modifications/utils/schemaUpdateUtils.js.map +1 -1
  97. package/dist/tests/src/tags.d.ts.map +1 -1
  98. package/dist/tests/tsconfig.tsbuildinfo +1 -1
  99. package/dist/types/Migration.d.ts.map +1 -1
  100. package/dist/types/modifications/ModificationHandler.d.ts.map +1 -1
  101. package/dist/types/modifications/columns/CreateColumnModification.d.ts.map +1 -1
  102. package/dist/types/modifications/columns/UpdateColumnDefinitionModification.d.ts.map +1 -1
  103. package/dist/types/modifications/columns/columnUtils.d.ts.map +1 -1
  104. package/dist/types/modifications/constraints/CreateUniqueConstraintModification.d.ts +2 -2
  105. package/dist/types/modifications/constraints/CreateUniqueConstraintModification.d.ts.map +1 -1
  106. package/dist/types/modifications/constraints/RemoveUniqueConstraintModification.d.ts +7 -2
  107. package/dist/types/modifications/constraints/RemoveUniqueConstraintModification.d.ts.map +1 -1
  108. package/dist/types/modifications/constraints/utils.d.ts.map +1 -1
  109. package/dist/types/modifications/entities/CreateEntityModification.d.ts.map +1 -1
  110. package/dist/types/modifications/entities/CreateViewModification.d.ts +1 -0
  111. package/dist/types/modifications/entities/CreateViewModification.d.ts.map +1 -1
  112. package/dist/types/modifications/enums/enumUtils.d.ts.map +1 -1
  113. package/dist/types/modifications/indexes/utils.d.ts.map +1 -1
  114. package/dist/types/modifications/relations/helpers.d.ts.map +1 -1
  115. package/dist/types/modifications/relations/normalization.d.ts.map +1 -1
  116. package/dist/types/modifications/upgrade/RemoveIndexNamesModification.d.ts.map +1 -1
  117. package/dist/types/modifications/utils/columnUtils.d.ts +1 -1
  118. package/dist/types/modifications/utils/columnUtils.d.ts.map +1 -1
  119. package/dist/types/modifications/utils/createJunctionTable.d.ts.map +1 -1
  120. package/dist/types/modifications/utils/diffUtils.d.ts.map +1 -1
  121. package/dist/types/modifications/utils/getPrimaryColumnType.d.ts.map +1 -1
  122. package/dist/types/modifications/utils/schemaUpdateUtils.d.ts.map +1 -1
  123. package/dist/types/modifications/utils/sqlUpdateUtils.d.ts.map +1 -1
  124. package/dist/types/modifications/utils/stringArrayEquals.d.ts.map +1 -1
  125. package/dist/types/modifications/utils/valueUtils.d.ts.map +1 -1
  126. package/dist/types/modifications/utils/viewDependencies.d.ts.map +1 -1
  127. package/dist/types/tsconfig.tsbuildinfo +1 -1
  128. package/dist/types/utils/PartialEntity.d.ts +1 -1
  129. package/dist/types/utils/PartialEntity.d.ts.map +1 -1
  130. package/dist/types/utils/dbHelpers.d.ts.map +1 -1
  131. package/dist/types/utils/isDefined.d.ts.map +1 -1
  132. package/dist/types/utils/isIt.d.ts.map +1 -1
  133. package/package.json +7 -7
  134. package/src/MigrationDescriber.ts +2 -2
  135. package/src/modifications/columns/CreateColumnModification.ts +1 -0
  136. package/src/modifications/columns/UpdateColumnDefinitionModification.ts +8 -3
  137. package/src/modifications/constraints/CreateUniqueConstraintModification.ts +19 -10
  138. package/src/modifications/constraints/RemoveUniqueConstraintModification.ts +52 -19
  139. package/src/modifications/entities/CreateEntityModification.ts +1 -0
  140. package/src/modifications/entities/CreateViewModification.ts +13 -2
  141. package/src/modifications/indexes/CreateIndexModification.ts +2 -2
  142. package/src/modifications/indexes/RemoveIndexModification.ts +3 -3
  143. package/src/modifications/upgrade/RemoveIndexNamesModification.ts +8 -2
  144. package/src/modifications/utils/columnUtils.ts +6 -3
  145. package/src/modifications/utils/schemaUpdateUtils.ts +1 -0
  146. package/src/utils/PartialEntity.ts +1 -1
  147. package/tests/cases/integration/convertManyHasOneToOneHasOneRelation.test.ts +1 -0
  148. package/tests/cases/integration/createAndDropIndex.test.ts +1 -0
  149. package/tests/cases/integration/createColumn.test.ts +27 -0
  150. package/tests/cases/integration/createEntity.test.ts +69 -0
  151. package/tests/cases/integration/createUnique.test.ts +91 -1
  152. package/tests/cases/integration/removeField.test.ts +6 -4
  153. package/tests/cases/integration/updateColumnDefinition.test.ts +27 -0
@@ -2,6 +2,6 @@ import { Model } from '@contember/schema';
2
2
  export type PossibleEntityShapeInMigrations = Omit<Model.Entity, 'eventLog' | 'indexes' | 'unique'> & {
3
3
  eventLog?: Model.Entity['eventLog'];
4
4
  indexes?: (readonly Model.Index[]) | Readonly<Record<string, Model.Index>>;
5
- unique: (readonly Model.UniqueConstraint[]) | Readonly<Record<string, Model.UniqueConstraint>>;
5
+ unique: (readonly (Model.UniqueConstraint | Model.UniqueIndex)[]) | Readonly<Record<string, Model.UniqueConstraint>>;
6
6
  };
7
7
  //# sourceMappingURL=PartialEntity.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"PartialEntity.d.ts","sourceRoot":"","sources":["../../../src/utils/PartialEntity.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,mBAAmB,CAAA;AAIzC,MAAM,MAAM,+BAA+B,GACxC,IAAI,CAAC,KAAK,CAAC,MAAM,EAAE,UAAU,GAAG,SAAS,GAAG,QAAQ,CAAC,GACrD;IACD,QAAQ,CAAC,EAAE,KAAK,CAAC,MAAM,CAAC,UAAU,CAAC,CAAA;IACnC,OAAO,CAAC,EAAE,CAAC,SAAU,KAAK,CAAC,KAAK,EAAE,CAAC,GAAG,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,KAAK,CAAC,KAAK,CAAC,CAAC,CAAA;IAC3E,MAAM,EAAE,CAAC,SAAU,KAAK,CAAC,gBAAgB,EAAE,CAAC,GAAG,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,KAAK,CAAC,gBAAgB,CAAC,CAAC,CAAA;CAC/F,CAAA"}
1
+ {"version":3,"file":"PartialEntity.d.ts","sourceRoot":"","sources":["../../../src/utils/PartialEntity.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,mBAAmB,CAAA;AAIzC,MAAM,MAAM,+BAA+B,GACxC,IAAI,CAAC,KAAK,CAAC,MAAM,EAAE,UAAU,GAAG,SAAS,GAAG,QAAQ,CAAC,GACrD;IACD,QAAQ,CAAC,EAAE,KAAK,CAAC,MAAM,CAAC,UAAU,CAAC,CAAA;IACnC,OAAO,CAAC,EAAE,CAAC,SAAU,KAAK,CAAC,KAAK,EAAE,CAAC,GAAG,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,KAAK,CAAC,KAAK,CAAC,CAAC,CAAA;IAC3E,MAAM,EAAE,CAAC,SAAU,CAAC,KAAK,CAAC,gBAAgB,GAAG,KAAK,CAAC,WAAW,CAAC,EAAE,CAAC,GAAG,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,KAAK,CAAC,gBAAgB,CAAC,CAAC,CAAA;CACrH,CAAA"}
@@ -1 +1 @@
1
- {"version":3,"file":"dbHelpers.d.ts","sourceRoot":"","sources":["../../../src/utils/dbHelpers.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,cAAc,UAAW,MAAM,WAA0C,CAAA"}
1
+ {"version":3,"file":"dbHelpers.d.ts","sourceRoot":"","sources":["../../../src/utils/dbHelpers.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,cAAc,GAAI,OAAO,MAAM,WAA0C,CAAA"}
@@ -1 +1 @@
1
- {"version":3,"file":"isDefined.d.ts","sourceRoot":"","sources":["../../../src/utils/isDefined.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,SAAS,GAAI,CAAC,SAAS,SAAS,GAAG,CAAC,KAAG,KAAK,IAAI,CAAwB,CAAA"}
1
+ {"version":3,"file":"isDefined.d.ts","sourceRoot":"","sources":["../../../src/utils/isDefined.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,SAAS,GAAI,CAAC,EAAE,OAAO,SAAS,GAAG,CAAC,KAAG,KAAK,IAAI,CAAwB,CAAA"}
@@ -1 +1 @@
1
- {"version":3,"file":"isIt.d.ts","sourceRoot":"","sources":["../../../src/utils/isIt.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,IAAI,GAAI,CAAC,SAAS,MAAM,EAAE,CAAC,SAAS,MAAM,CAAC,iBAAiB,GAAG,YAAY,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,KAAG,GAAG,IAAI,CAKhH,CAAA"}
1
+ {"version":3,"file":"isIt.d.ts","sourceRoot":"","sources":["../../../src/utils/isIt.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,IAAI,GAAI,CAAC,SAAS,MAAM,EAAE,CAAC,SAAS,MAAM,CAAC,GAAG,MAAM,CAAC,EAAE,KAAK,GAAG,EAAE,UAAU,CAAC,EAAE,QAAQ,CAAC,CAAC,CAAC,CAAC,KAAG,GAAG,IAAI,CAKhH,CAAA"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@contember/schema-migrations",
3
- "version": "2.0.1",
3
+ "version": "2.1.0-alpha.2",
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.0.1",
27
- "@contember/database-migrations": "2.0.1",
28
- "@contember/engine-common": "2.0.1",
29
- "@contember/schema": "2.0.1",
30
- "@contember/schema-utils": "2.0.1",
26
+ "@contember/database": "2.1.0-alpha.2",
27
+ "@contember/database-migrations": "2.1.0-alpha.2",
28
+ "@contember/engine-common": "2.1.0-alpha.2",
29
+ "@contember/schema": "2.1.0-alpha.2",
30
+ "@contember/schema-utils": "2.1.0-alpha.2",
31
31
  "fast-deep-equal": "^3.1.3",
32
32
  "rfc6902": "^5.1.1"
33
33
  },
34
34
  "devDependencies": {
35
- "@contember/schema-definition": "2.0.1"
35
+ "@contember/schema-definition": "2.1.0-alpha.2"
36
36
  },
37
37
  "peerDependencies": {
38
38
  "pg": "^8.9.0"
@@ -1,5 +1,5 @@
1
1
  import {
2
- createEntityModification,
2
+ createEntityModification, createViewModification,
3
3
  emptyModificationDescriptionContext,
4
4
  ModificationDescription,
5
5
  ModificationDescriptionContext,
@@ -62,7 +62,7 @@ export class MigrationDescriber {
62
62
  const result = []
63
63
  const createdEntities = []
64
64
  for (const modification of migration.modifications) {
65
- if (modification.modification === createEntityModification.id) {
65
+ if (modification.modification === createEntityModification.id || modification.modification === createViewModification.id) {
66
66
  createdEntities.push(modification.entity.name)
67
67
  }
68
68
  const description = this.describeModification(
@@ -33,6 +33,7 @@ export class CreateColumnModificationHandler implements ModificationHandler<Crea
33
33
  type: columnType,
34
34
  notNull: !column.nullable && seedExpression === null,
35
35
  sequenceGenerated: column.sequence,
36
+ collation: column.collation,
36
37
  },
37
38
  })
38
39
 
@@ -20,11 +20,15 @@ export class UpdateColumnDefinitionModificationHandler implements ModificationHa
20
20
  const newColumn = this.data.definition
21
21
 
22
22
  const hasNewSequence = !oldColumn.sequence && newColumn.sequence
23
- const hasNewType = newColumn.columnType !== oldColumn.columnType
23
+ const oldColumnType = getColumnSqlType(oldColumn)
24
24
  const columnType = getColumnSqlType(newColumn)
25
+ const hasNewType = columnType !== oldColumnType
25
26
  const hasNullableChanged = oldColumn.nullable !== newColumn.nullable
27
+ const hasNewCollation = newColumn.collation !== oldColumn.collation
26
28
 
27
- const usingCast = `${wrapIdentifier(oldColumn.columnName)}::${columnType}`
29
+ const columnNameWrapped = wrapIdentifier(oldColumn.columnName)
30
+ const isChangedToArray = !oldColumn.list && newColumn.list
31
+ const usingCast = (isChangedToArray ? `ARRAY[${columnNameWrapped}]` : columnNameWrapped) + `::${columnType}`
28
32
 
29
33
  const seedExpression = formatSeedExpression({
30
34
  model: this.schema.model,
@@ -38,7 +42,8 @@ export class UpdateColumnDefinitionModificationHandler implements ModificationHa
38
42
  const migrateWithUpdate = hasSeed && this.data.valueMigrationStrategy !== 'using'
39
43
 
40
44
  builder.alterColumn(entity.tableName, oldColumn.columnName, {
41
- type: hasNewSequence || hasNewType || migrateWithUsing ? columnType : undefined,
45
+ collation: hasNewCollation ? wrapIdentifier(newColumn.collation || 'default') : undefined,
46
+ type: hasNewCollation || hasNewSequence || hasNewType || migrateWithUsing ? columnType : undefined,
42
47
  notNull: hasNullableChanged && (!migrateWithUpdate || newColumn.nullable) ? !newColumn.nullable : undefined,
43
48
  using: (() => {
44
49
  if (hasNewSequence) {
@@ -15,9 +15,12 @@ export class CreateUniqueConstraintModificationHandler implements ModificationHa
15
15
  constructor(private readonly data: CreateUniqueConstraintModificationData, private readonly schema: Schema) {
16
16
  }
17
17
 
18
- public createSql(builder: MigrationBuilder, { databaseMetadata, invalidateDatabaseMetadata }: ModificationHandlerCreateSqlOptions): void {
18
+ public createSql(builder: MigrationBuilder, { invalidateDatabaseMetadata }: ModificationHandlerCreateSqlOptions): void {
19
19
  const entity = this.schema.model.entities[this.data.entityName]
20
- if (entity.view) {
20
+ const shouldExecuteSql =
21
+ !entity.view
22
+ || (this.data.unique.index && entity.view.materialized)
23
+ if (!shouldExecuteSql) {
21
24
  return
22
25
  }
23
26
  const fields = this.data.unique.fields
@@ -30,14 +33,20 @@ export class CreateUniqueConstraintModificationHandler implements ModificationHa
30
33
  const tableNameId = wrapIdentifier(entity.tableName)
31
34
  const columnNameIds = columns.map(wrapIdentifier)
32
35
 
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'
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}`)
39
+ } else {
40
+ let checkModifier = ''
41
+ if (this.data.unique.timing === 'deferred') {
42
+ checkModifier = ' INITIALLY DEFERRED'
43
+ } else if (this.data.unique.timing === 'deferrable') {
44
+ checkModifier = ' DEFERRABLE'
45
+ }
46
+
47
+ builder.sql(`ALTER TABLE ${tableNameId} ADD UNIQUE (${columnNameIds.join(', ')})${checkModifier}`)
38
48
  }
39
49
 
40
- builder.sql(`ALTER TABLE ${tableNameId} ADD UNIQUE (${columnNameIds.join(', ')})${checkModifier}`)
41
50
 
42
51
  invalidateDatabaseMetadata()
43
52
  }
@@ -56,7 +65,7 @@ export class CreateUniqueConstraintModificationHandler implements ModificationHa
56
65
 
57
66
  describe({ createdEntities }: { createdEntities: string[] }) {
58
67
  return {
59
- message: `Create unique constraint (${this.data.unique.fields.join(', ')}) on entity ${this.data.entityName}`,
68
+ message: `Create unique ${this.data.unique.index ? 'index' : 'constraint'} (${this.data.unique.fields.join(', ')}) on entity ${this.data.entityName}`,
60
69
  failureWarning: !createdEntities.includes(this.data.entityName)
61
70
  ? 'Make sure no conflicting rows exists, otherwise this may fail in runtime.'
62
71
  : undefined,
@@ -72,7 +81,7 @@ export const createUniqueConstraintModification = createModificationType({
72
81
 
73
82
  export interface CreateUniqueConstraintModificationData {
74
83
  entityName: string
75
- unique: Model.UniqueConstraint
84
+ unique: Model.UniqueConstraint | Model.UniqueIndex
76
85
  }
77
86
 
78
87
  export class CreateUniqueConstraintDiffer implements Differ {
@@ -1,5 +1,5 @@
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, updateEntity, updateModel } from '../utils/schemaUpdateUtils'
4
4
  import {
5
5
  createModificationType,
@@ -17,32 +17,55 @@ export class RemoveUniqueConstraintModificationHandler implements ModificationHa
17
17
 
18
18
  public createSql(builder: MigrationBuilder, { databaseMetadata, invalidateDatabaseMetadata }: ModificationHandlerCreateSqlOptions): void {
19
19
  const entity = this.schema.model.entities[this.data.entityName]
20
- if (entity.view) {
20
+ const unique = this.getUnique()
21
+
22
+ const shouldExecuteSql =
23
+ !entity.view
24
+ || (unique.index && entity.view.materialized)
25
+
26
+ if (!shouldExecuteSql) {
21
27
  return
22
28
  }
23
29
 
24
- const fields = this.getFields()
25
30
 
26
31
  const columns = getUniqueConstraintColumns({
27
32
  entity,
28
- fields: fields,
33
+ fields: unique.fields,
29
34
  model: this.schema.model,
30
35
  })
31
36
 
32
- const constraintNames = databaseMetadata.uniqueConstraints.filter({ tableName: entity.tableName, columnNames: columns }).getNames()
37
+ if (unique.index) {
38
+ const indexNames = databaseMetadata.indexes.filter({
39
+ tableName: entity.tableName,
40
+ columnNames: columns,
41
+ unique: true,
42
+ }).getNames()
43
+
44
+ for (const name of indexNames) {
45
+ builder.sql(`DROP INDEX ${wrapIdentifier(name)}`)
46
+ }
33
47
 
34
- for (const name of constraintNames) {
35
- builder.sql(`ALTER TABLE ${wrapIdentifier(entity.tableName)} DROP CONSTRAINT ${wrapIdentifier(name)}`)
48
+ } else {
49
+
50
+ const constraintNames = databaseMetadata.uniqueConstraints.filter({
51
+ tableName: entity.tableName,
52
+ columnNames: columns,
53
+ }).getNames()
54
+
55
+ for (const name of constraintNames) {
56
+ builder.sql(`ALTER TABLE ${wrapIdentifier(entity.tableName)} DROP CONSTRAINT ${wrapIdentifier(name)}`)
57
+ }
36
58
  }
37
59
 
60
+
38
61
  invalidateDatabaseMetadata()
39
62
  }
40
63
 
41
64
  public getSchemaUpdater(): SchemaUpdater {
42
- const fields = this.getFields()
65
+ const thisUnique = this.getUnique()
43
66
  return updateModel(
44
67
  updateEntity(this.data.entityName, ({ entity }) => {
45
- const unique = entity.unique.filter(it => !deepEqual(it.fields, fields))
68
+ const unique = entity.unique.filter(it => !deepEqual(it, thisUnique))
46
69
  return {
47
70
  ...entity,
48
71
  unique,
@@ -52,20 +75,23 @@ export class RemoveUniqueConstraintModificationHandler implements ModificationHa
52
75
  }
53
76
 
54
77
  describe() {
55
- const fields = this.getFields()
56
- return { message: `Remove unique constraint (${fields.join(', ')}) on entity ${this.data.entityName}` }
78
+ const unique = this.getUnique()
79
+ return { message: `Remove unique ${unique.index ? 'index' : 'constraint'} (${unique.fields.join(', ')}) on entity ${this.data.entityName}` }
57
80
  }
58
81
 
59
- getFields() {
82
+ getUnique(): Model.Unique {
83
+ if ('unique' in this.data) {
84
+ return this.data.unique
85
+ }
60
86
  const entity = this.schema.model.entities[this.data.entityName]
61
- const fields = 'constraintName' in this.data
62
- ? entity.unique.find(it => it.name === this.data.constraintName)?.fields
63
- : this.data.fields
87
+ const unique = 'constraintName' in this.data
88
+ ? entity.unique.find(it => 'name' in it && it.name === this.data.constraintName)
89
+ : entity.unique.find(it => deepEqual(it.fields, this.data.fields))
64
90
 
65
- if (!fields) {
91
+ if (!unique) {
66
92
  throw new Error()
67
93
  }
68
- return fields
94
+ return unique
69
95
  }
70
96
  }
71
97
 
@@ -75,6 +101,13 @@ export const removeUniqueConstraintModification = createModificationType({
75
101
  })
76
102
 
77
103
  export type RemoveUniqueConstraintModificationData =
104
+ | {
105
+ entityName: string
106
+ fields?: never
107
+ constraintName?: never
108
+ unique: Model.Unique
109
+ }
110
+ // deprecated
78
111
  | {
79
112
  entityName: string
80
113
  constraintName: string
@@ -96,12 +129,12 @@ export class RemoveUniqueConstraintDiffer implements Differ {
96
129
  if (!updatedEntity) {
97
130
  return false
98
131
  }
99
- return !updatedEntity.unique.find(uniq => deepEqual(uniq.fields, it.fields) && it.timing === uniq.timing)
132
+ return !updatedEntity.unique.find(uniq => deepEqual(uniq, it))
100
133
  })
101
134
  .map(unique =>
102
135
  removeUniqueConstraintModification.createModification({
103
136
  entityName: entity.name,
104
- fields: unique.fields,
137
+ unique: unique,
105
138
  }),
106
139
  ),
107
140
  )
@@ -86,6 +86,7 @@ export class CreateEntityDiffer implements Differ {
86
86
  [entity.primary]: entity.fields[entity.primary],
87
87
  },
88
88
  unique: [],
89
+ indexes: [],
89
90
  },
90
91
  }),
91
92
  )
@@ -13,7 +13,13 @@ export class CreateViewModificationHandler implements ModificationHandler<Create
13
13
  if (!entity.view) {
14
14
  throw new Error()
15
15
  }
16
- builder.createView(entity.tableName, {}, entity.view.sql)
16
+ if (entity.view.materialized) {
17
+ builder.createMaterializedView(entity.tableName, {
18
+ data: this.data.noData !== true,
19
+ }, entity.view.sql)
20
+ } else {
21
+ builder.createView(entity.tableName, {}, entity.view.sql)
22
+ }
17
23
  }
18
24
 
19
25
  public getSchemaUpdater(): SchemaUpdater {
@@ -58,7 +64,11 @@ export class CreateViewDiffer implements Differ {
58
64
  cascadeCreate(updatedSchema.model.entities[dependency])
59
65
  }
60
66
  modifications.push(createViewModification.createModification({
61
- entity: entity,
67
+ entity: {
68
+ ...entity,
69
+ indexes: [],
70
+ unique: [],
71
+ },
62
72
  }))
63
73
  }
64
74
  for (const view of newViews) {
@@ -70,4 +80,5 @@ export class CreateViewDiffer implements Differ {
70
80
 
71
81
  export interface CreateViewModificationData {
72
82
  entity: PossibleEntityShapeInMigrations
83
+ noData?: boolean
73
84
  }
@@ -16,7 +16,7 @@ export class CreateIndexModificationHandler implements ModificationHandler<Creat
16
16
 
17
17
  public createSql(builder: MigrationBuilder, { databaseMetadata, invalidateDatabaseMetadata }: ModificationHandlerCreateSqlOptions): void {
18
18
  const entity = this.schema.model.entities[this.data.entityName]
19
- if (entity.view) {
19
+ if (entity.view && !entity.view.materialized) {
20
20
  return
21
21
  }
22
22
  const fields = this.data.index.fields
@@ -67,7 +67,7 @@ export class CreateIndexDiffer implements Differ {
67
67
  createDiff(originalSchema: Schema, updatedSchema: Schema) {
68
68
  return Object.values(updatedSchema.model.entities).flatMap(entity =>
69
69
  entity.indexes
70
- .filter(it => !originalSchema.model.entities[entity.name].indexes.find(idx => deepEqual(idx.fields, it.fields)))
70
+ .filter(it => !originalSchema.model.entities[entity.name].indexes.find(idx => deepEqual(idx, it)))
71
71
  .map(index => createIndexModification.createModification({
72
72
  entityName: entity.name,
73
73
  index,
@@ -16,7 +16,7 @@ export class RemoveIndexModificationHandler implements ModificationHandler<Remov
16
16
 
17
17
  public createSql(builder: MigrationBuilder, { databaseMetadata, invalidateDatabaseMetadata }: ModificationHandlerCreateSqlOptions): void {
18
18
  const entity = this.schema.model.entities[this.data.entityName]
19
- if (entity.view) {
19
+ if (entity.view && !entity.view.materialized) {
20
20
  return
21
21
  }
22
22
  const fields = this.getFields()
@@ -27,7 +27,7 @@ export class RemoveIndexModificationHandler implements ModificationHandler<Remov
27
27
  model: this.schema.model,
28
28
  })
29
29
 
30
- const indexNames = databaseMetadata.indexes.filter({ tableName: entity.tableName, columnNames: columns }).getNames()
30
+ const indexNames = databaseMetadata.indexes.filter({ tableName: entity.tableName, columnNames: columns, unique: false }).getNames()
31
31
 
32
32
  for (const name of indexNames) {
33
33
  builder.sql(`DROP INDEX ${wrapIdentifier(name)}`)
@@ -94,7 +94,7 @@ export class RemoveIndexDiffer implements Differ {
94
94
  if (!updatedEntity) {
95
95
  return false
96
96
  }
97
- return !updatedEntity.indexes.find(index => deepEqual(index.fields, it.fields))
97
+ return !updatedEntity.indexes.find(index => deepEqual(index, it))
98
98
  },
99
99
  )
100
100
  .map(index =>
@@ -14,7 +14,13 @@ export class RemoveIndexNamesModificationHandler implements ModificationHandler<
14
14
  return {
15
15
  ...entity,
16
16
  indexes: entity.indexes.map(({ name, ...other }) => other),
17
- unique: entity.unique.map(({ name, ...other }) => other),
17
+ unique: entity.unique.map(it => {
18
+ if ('name' in it) {
19
+ const { name, ...other } = it
20
+ return other
21
+ }
22
+ return it
23
+ }),
18
24
  }
19
25
  }),
20
26
  )
@@ -36,7 +42,7 @@ export type RemoveIndexNamesModificationData = {}
36
42
  export class RemoveIndexNamesDiffer implements Differ {
37
43
  createDiff(originalSchema: Schema) {
38
44
  const hasNames = !!Object.values(originalSchema.model.entities).find(it => {
39
- return it.indexes.find(it => !!it.name) || it.unique.find(it => !!it.name)
45
+ return it.indexes.find(it => !!it.name) || it.unique.find(it => 'name' in it && !!it.name)
40
46
  })
41
47
  if (hasNames) {
42
48
  return [removeIndexNamesModification.createModification({})]
@@ -1,5 +1,8 @@
1
1
  import { Model } from '@contember/schema'
2
2
 
3
- export const getColumnSqlType = (column: Pick<Model.AnyColumn, 'type' | 'columnType'>) => column.type === Model.ColumnType.Enum
4
- ? `"${column.columnType}"`
5
- : column.columnType
3
+ export const getColumnSqlType = (column: Pick<Model.AnyColumn, 'type' | 'columnType' | 'list'>) =>
4
+ (column.type === Model.ColumnType.Enum
5
+ ? `"${column.columnType}"`
6
+ : column.columnType
7
+ )
8
+ + (column.list ? '[]' : '')
@@ -119,6 +119,7 @@ export const updateAclFieldPermissions =
119
119
  read: value => updater(value, entityName, Acl.Operation.read),
120
120
  delete: value => value,
121
121
  customPrimary: value => value,
122
+ refreshMaterializedView: value => value,
122
123
  noRoot: value => value,
123
124
  }
124
125
  const types: (keyof Acl.EntityOperations)[] = ['create', 'update', 'read', 'delete', 'customPrimary', 'noRoot']
@@ -7,5 +7,5 @@ export type PossibleEntityShapeInMigrations =
7
7
  & {
8
8
  eventLog?: Model.Entity['eventLog']
9
9
  indexes?: (readonly Model.Index[]) | Readonly<Record<string, Model.Index>>
10
- unique: (readonly Model.UniqueConstraint[]) | Readonly<Record<string, Model.UniqueConstraint>>
10
+ unique: (readonly (Model.UniqueConstraint | Model.UniqueIndex)[]) | Readonly<Record<string, Model.UniqueConstraint>>
11
11
  }
@@ -45,6 +45,7 @@ describe('convert one has many to one has one', () => {
45
45
  indexName: 'article_review_article_id_idx',
46
46
  columnNames: ['article_id'],
47
47
  tableName: 'article_review',
48
+ unique: false,
48
49
  }],
49
50
  uniqueConstraints: [],
50
51
  }),
@@ -49,6 +49,7 @@ describe('drop index', () => testMigrations({
49
49
  tableName: 'article',
50
50
  columnNames: ['title'],
51
51
  indexName: 'idx_article_title',
52
+ unique: false,
52
53
  }],
53
54
  uniqueConstraints: [],
54
55
  }),
@@ -172,3 +172,30 @@ ALTER "active" SET NOT NULL; ALTER TABLE "author" ADD "created_at" timestamptz;
172
172
  ALTER TABLE "author" ALTER "created_at" SET DATA TYPE timestamptz USING $pga$2024-01-01 10:00$pga$, ALTER "created_at" SET NOT NULL;
173
173
  `,
174
174
  }))
175
+
176
+ describe('create list column', () => testMigrations({
177
+ original: createSchema({
178
+ Author: class Author {
179
+ },
180
+ }),
181
+ updated: createSchema({
182
+ Author: class Author {
183
+ emails = def.stringColumn().list()
184
+ },
185
+ }),
186
+ diff: [
187
+ {
188
+ modification: 'createColumn',
189
+ entityName: 'Author',
190
+ field: {
191
+ columnName: 'emails',
192
+ name: 'emails',
193
+ nullable: true,
194
+ type: Model.ColumnType.String,
195
+ columnType: 'text',
196
+ list: true,
197
+ },
198
+ },
199
+ ],
200
+ sql: SQL`ALTER TABLE "author" ADD "emails" text[];`,
201
+ }))
@@ -199,3 +199,72 @@ CREATE TRIGGER "log_event" AFTER INSERT OR UPDATE OR DELETE ON "author" FOR EACH
199
199
  CREATE CONSTRAINT TRIGGER "log_event_trx" AFTER INSERT OR UPDATE OR DELETE ON "author" DEFERRABLE INITIALLY DEFERRED FOR EACH ROW EXECUTE PROCEDURE "system"."trigger_event_commit"();
200
200
  ALTER TABLE "author" ADD "name" text;`,
201
201
  }))
202
+
203
+ namespace SchemaWithIndex {
204
+ @def.Index('name')
205
+ export class Author {
206
+ name = def.stringColumn()
207
+ }
208
+ }
209
+ describe('entity with index', () => testMigrations({
210
+ original: {},
211
+ updated: createSchema(SchemaWithIndex),
212
+ diff: [
213
+ {
214
+ modification: 'createEntity',
215
+ entity: {
216
+ fields: {
217
+ id: {
218
+ columnName: 'id',
219
+ name: 'id',
220
+ nullable: false,
221
+ type: Model.ColumnType.Uuid,
222
+ columnType: 'uuid',
223
+ },
224
+ },
225
+ name: 'Author',
226
+ primary: 'id',
227
+ primaryColumn: 'id',
228
+ tableName: 'author',
229
+ unique: [],
230
+ eventLog: {
231
+ enabled: true,
232
+ },
233
+ indexes: [],
234
+ },
235
+ },
236
+ {
237
+ modification: 'createColumn',
238
+ entityName: 'Author',
239
+ field: {
240
+ columnName: 'name',
241
+ name: 'name',
242
+ nullable: true,
243
+ type: Model.ColumnType.String,
244
+ columnType: 'text',
245
+ },
246
+ },
247
+ {
248
+ modification: 'createIndex',
249
+ entityName: 'Author',
250
+ index: { fields: ['name'] },
251
+ },
252
+ ],
253
+ sql: SQL`CREATE TABLE "author"
254
+ (
255
+ "id" uuid PRIMARY KEY NOT NULL
256
+ );
257
+ CREATE TRIGGER "log_event"
258
+ AFTER INSERT OR UPDATE OR DELETE
259
+ ON "author"
260
+ FOR EACH ROW
261
+ EXECUTE PROCEDURE "system"."trigger_event"($pga$id$pga$);
262
+ CREATE CONSTRAINT TRIGGER "log_event_trx"
263
+ AFTER INSERT OR UPDATE OR DELETE
264
+ ON "author" DEFERRABLE INITIALLY DEFERRED
265
+ FOR EACH ROW
266
+ EXECUTE PROCEDURE "system"."trigger_event_commit"();
267
+ ALTER TABLE "author"
268
+ ADD "name" text;
269
+ CREATE INDEX ON "author" ("name");`,
270
+ }))