@contember/schema-migrations 2.1.0-beta.2 → 2.2.0-alpha.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/development/index.cjs +3 -0
- package/dist/development/index.cjs.map +1 -1
- package/dist/development/index.js +3 -0
- package/dist/development/index.js.map +1 -1
- package/dist/development/src/MigrationDescriber.cjs.map +1 -1
- package/dist/development/src/MigrationDescriber.js.map +1 -1
- package/dist/development/src/SchemaDiffer.cjs +27 -12
- package/dist/development/src/SchemaDiffer.cjs.map +1 -1
- package/dist/development/src/SchemaDiffer.js +27 -12
- package/dist/development/src/SchemaDiffer.js.map +1 -1
- package/dist/development/src/SchemaMigrator.cjs.map +1 -1
- package/dist/development/src/SchemaMigrator.js.map +1 -1
- package/dist/development/src/modifications/ModificationHandler.cjs.map +1 -1
- package/dist/development/src/modifications/ModificationHandler.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/NoopModification.cjs.map +1 -1
- package/dist/development/src/modifications/NoopModification.js.map +1 -1
- package/dist/development/src/modifications/acl/PatchAclSchemaModification.cjs.map +1 -1
- package/dist/development/src/modifications/acl/PatchAclSchemaModification.js.map +1 -1
- package/dist/development/src/modifications/acl/UpdateAclSchemaModification.cjs.map +1 -1
- package/dist/development/src/modifications/acl/UpdateAclSchemaModification.js.map +1 -1
- package/dist/development/src/modifications/actions/CreateTargetModification.cjs.map +1 -1
- package/dist/development/src/modifications/actions/CreateTargetModification.js.map +1 -1
- package/dist/development/src/modifications/actions/CreateTriggerModification.cjs.map +1 -1
- package/dist/development/src/modifications/actions/CreateTriggerModification.js.map +1 -1
- package/dist/development/src/modifications/actions/PatchTriggerModification.cjs.map +1 -1
- package/dist/development/src/modifications/actions/PatchTriggerModification.js.map +1 -1
- package/dist/development/src/modifications/actions/RemoveTargetModification.cjs.map +1 -1
- package/dist/development/src/modifications/actions/RemoveTargetModification.js.map +1 -1
- package/dist/development/src/modifications/actions/RemoveTriggerModification.cjs.map +1 -1
- package/dist/development/src/modifications/actions/RemoveTriggerModification.js.map +1 -1
- package/dist/development/src/modifications/actions/UpdateTargetModification.cjs.map +1 -1
- package/dist/development/src/modifications/actions/UpdateTargetModification.js.map +1 -1
- package/dist/development/src/modifications/actions/UpdateTriggerModification.cjs.map +1 -1
- package/dist/development/src/modifications/actions/UpdateTriggerModification.js.map +1 -1
- package/dist/development/src/modifications/columns/CreateColumnModification.cjs.map +1 -1
- package/dist/development/src/modifications/columns/CreateColumnModification.js.map +1 -1
- package/dist/development/src/modifications/columns/UpdateColumnDefinitionModification.cjs.map +1 -1
- package/dist/development/src/modifications/columns/UpdateColumnDefinitionModification.js.map +1 -1
- package/dist/development/src/modifications/columns/UpdateColumnNameModification.cjs.map +1 -1
- package/dist/development/src/modifications/columns/UpdateColumnNameModification.js.map +1 -1
- package/dist/development/src/modifications/columns/columnUtils.cjs.map +1 -1
- package/dist/development/src/modifications/columns/columnUtils.js.map +1 -1
- package/dist/development/src/modifications/constraints/CreateUniqueConstraintModification.cjs.map +1 -1
- package/dist/development/src/modifications/constraints/CreateUniqueConstraintModification.js.map +1 -1
- package/dist/development/src/modifications/constraints/RemoveUniqueConstraintModification.cjs.map +1 -1
- package/dist/development/src/modifications/constraints/RemoveUniqueConstraintModification.js.map +1 -1
- package/dist/development/src/modifications/differs/RemoveChangedFieldDiffer.cjs.map +1 -1
- package/dist/development/src/modifications/differs/RemoveChangedFieldDiffer.js.map +1 -1
- package/dist/development/src/modifications/differs/RemoveViewDiffer.cjs +4 -1
- package/dist/development/src/modifications/differs/RemoveViewDiffer.cjs.map +1 -1
- package/dist/development/src/modifications/differs/RemoveViewDiffer.js +5 -2
- package/dist/development/src/modifications/differs/RemoveViewDiffer.js.map +1 -1
- package/dist/development/src/modifications/differs/UpdateViewDiffer.cjs +45 -0
- package/dist/development/src/modifications/differs/UpdateViewDiffer.cjs.map +1 -0
- package/dist/development/src/modifications/differs/UpdateViewDiffer.js +45 -0
- package/dist/development/src/modifications/differs/UpdateViewDiffer.js.map +1 -0
- package/dist/development/src/modifications/entities/CreateEntityModification.cjs.map +1 -1
- package/dist/development/src/modifications/entities/CreateEntityModification.js.map +1 -1
- package/dist/development/src/modifications/entities/CreateViewModification.cjs.map +1 -1
- package/dist/development/src/modifications/entities/CreateViewModification.js.map +1 -1
- package/dist/development/src/modifications/entities/RemoveEntityModification.cjs.map +1 -1
- package/dist/development/src/modifications/entities/RemoveEntityModification.js.map +1 -1
- package/dist/development/src/modifications/entities/ToggleEventLogModification.cjs.map +1 -1
- package/dist/development/src/modifications/entities/ToggleEventLogModification.js.map +1 -1
- package/dist/development/src/modifications/entities/UpdateEntityNameModification.cjs.map +1 -1
- package/dist/development/src/modifications/entities/UpdateEntityNameModification.js.map +1 -1
- package/dist/development/src/modifications/entities/UpdateEntityOrderByModification.cjs.map +1 -1
- package/dist/development/src/modifications/entities/UpdateEntityOrderByModification.js.map +1 -1
- package/dist/development/src/modifications/entities/UpdateEntityTableNameModification.cjs.map +1 -1
- package/dist/development/src/modifications/entities/UpdateEntityTableNameModification.js.map +1 -1
- package/dist/development/src/modifications/entities/UpdateViewModification.cjs.map +1 -1
- package/dist/development/src/modifications/entities/UpdateViewModification.js.map +1 -1
- package/dist/development/src/modifications/enums/CreateEnumModification.cjs.map +1 -1
- package/dist/development/src/modifications/enums/CreateEnumModification.js.map +1 -1
- package/dist/development/src/modifications/enums/RemoveEnumModification.cjs.map +1 -1
- package/dist/development/src/modifications/enums/RemoveEnumModification.js.map +1 -1
- package/dist/development/src/modifications/enums/UpdateEnumModification.cjs.map +1 -1
- package/dist/development/src/modifications/enums/UpdateEnumModification.js.map +1 -1
- package/dist/development/src/modifications/enums/enumUtils.cjs.map +1 -1
- package/dist/development/src/modifications/enums/enumUtils.js.map +1 -1
- package/dist/development/src/modifications/fields/RemoveFieldModification.cjs.map +1 -1
- package/dist/development/src/modifications/fields/RemoveFieldModification.js.map +1 -1
- package/dist/development/src/modifications/fields/UpdateFieldNameModification.cjs +10 -4
- package/dist/development/src/modifications/fields/UpdateFieldNameModification.cjs.map +1 -1
- package/dist/development/src/modifications/fields/UpdateFieldNameModification.js +10 -4
- package/dist/development/src/modifications/fields/UpdateFieldNameModification.js.map +1 -1
- package/dist/development/src/modifications/indexes/CreateIndexModification.cjs +23 -7
- package/dist/development/src/modifications/indexes/CreateIndexModification.cjs.map +1 -1
- package/dist/development/src/modifications/indexes/CreateIndexModification.js +23 -7
- package/dist/development/src/modifications/indexes/CreateIndexModification.js.map +1 -1
- package/dist/development/src/modifications/indexes/RemoveIndexModification.cjs +52 -17
- package/dist/development/src/modifications/indexes/RemoveIndexModification.cjs.map +1 -1
- package/dist/development/src/modifications/indexes/RemoveIndexModification.js +52 -17
- package/dist/development/src/modifications/indexes/RemoveIndexModification.js.map +1 -1
- package/dist/development/src/modifications/relations/ConvertManyHasManyToJoiningEntityModification.cjs +140 -0
- package/dist/development/src/modifications/relations/ConvertManyHasManyToJoiningEntityModification.cjs.map +1 -0
- package/dist/development/src/modifications/relations/ConvertManyHasManyToJoiningEntityModification.js +140 -0
- package/dist/development/src/modifications/relations/ConvertManyHasManyToJoiningEntityModification.js.map +1 -0
- package/dist/development/src/modifications/relations/ConvertOneHasManyToManyHasManyRelationModification.cjs.map +1 -1
- package/dist/development/src/modifications/relations/ConvertOneHasManyToManyHasManyRelationModification.js.map +1 -1
- package/dist/development/src/modifications/relations/ConvertOneHasManyToOneHasOneRelationModification.cjs.map +1 -1
- package/dist/development/src/modifications/relations/ConvertOneHasManyToOneHasOneRelationModification.js.map +1 -1
- package/dist/development/src/modifications/relations/ConvertOneToManyRelationModification.cjs.map +1 -1
- package/dist/development/src/modifications/relations/ConvertOneToManyRelationModification.js.map +1 -1
- package/dist/development/src/modifications/relations/CreateRelationInverseSideModification.cjs.map +1 -1
- package/dist/development/src/modifications/relations/CreateRelationInverseSideModification.js.map +1 -1
- package/dist/development/src/modifications/relations/CreateRelationModification.cjs.map +1 -1
- package/dist/development/src/modifications/relations/CreateRelationModification.js.map +1 -1
- package/dist/development/src/modifications/relations/DisableOrphanRemovalModification.cjs.map +1 -1
- package/dist/development/src/modifications/relations/DisableOrphanRemovalModification.js.map +1 -1
- package/dist/development/src/modifications/relations/EnableOrphanRemovalModification.cjs.map +1 -1
- package/dist/development/src/modifications/relations/EnableOrphanRemovalModification.js.map +1 -1
- package/dist/development/src/modifications/relations/MakeRelationNotNullModification.cjs.map +1 -1
- package/dist/development/src/modifications/relations/MakeRelationNotNullModification.js.map +1 -1
- package/dist/development/src/modifications/relations/MakeRelationNullableModification.cjs.map +1 -1
- package/dist/development/src/modifications/relations/MakeRelationNullableModification.js.map +1 -1
- package/dist/development/src/modifications/relations/ToggleJunctionEventLogModification.cjs.map +1 -1
- package/dist/development/src/modifications/relations/ToggleJunctionEventLogModification.js.map +1 -1
- package/dist/development/src/modifications/relations/UpdateRelationOnDeleteModification.cjs.map +1 -1
- package/dist/development/src/modifications/relations/UpdateRelationOnDeleteModification.js.map +1 -1
- package/dist/development/src/modifications/relations/UpdateRelationOrderByModification.cjs.map +1 -1
- package/dist/development/src/modifications/relations/UpdateRelationOrderByModification.js.map +1 -1
- package/dist/development/src/modifications/relations/helpers.cjs.map +1 -1
- package/dist/development/src/modifications/relations/helpers.js.map +1 -1
- package/dist/development/src/modifications/settings/UpdateSettingsModification.cjs.map +1 -1
- package/dist/development/src/modifications/settings/UpdateSettingsModification.js.map +1 -1
- package/dist/development/src/modifications/upgrade/RemoveIndexNamesModification.cjs.map +1 -1
- package/dist/development/src/modifications/upgrade/RemoveIndexNamesModification.js.map +1 -1
- package/dist/development/src/modifications/utils/createJunctionTable.cjs.map +1 -1
- package/dist/development/src/modifications/utils/createJunctionTable.js.map +1 -1
- package/dist/development/src/modifications/utils/diffUtils.cjs.map +1 -1
- package/dist/development/src/modifications/utils/diffUtils.js.map +1 -1
- package/dist/development/src/modifications/utils/schemaUpdateUtils.cjs.map +1 -1
- package/dist/development/src/modifications/utils/schemaUpdateUtils.js.map +1 -1
- package/dist/development/src/modifications/utils/viewDependencies.cjs +15 -1
- package/dist/development/src/modifications/utils/viewDependencies.cjs.map +1 -1
- package/dist/development/src/modifications/utils/viewDependencies.js +16 -2
- package/dist/development/src/modifications/utils/viewDependencies.js.map +1 -1
- package/dist/development/src/modifications/validation/PatchValidationSchemaModification.cjs.map +1 -1
- package/dist/development/src/modifications/validation/PatchValidationSchemaModification.js.map +1 -1
- package/dist/development/src/modifications/validation/UpdateValidationSchemaModification.cjs.map +1 -1
- package/dist/development/src/modifications/validation/UpdateValidationSchemaModification.js.map +1 -1
- package/dist/production/index.cjs +3 -0
- package/dist/production/index.cjs.map +1 -1
- package/dist/production/index.js +3 -0
- package/dist/production/index.js.map +1 -1
- package/dist/production/src/MigrationDescriber.cjs.map +1 -1
- package/dist/production/src/MigrationDescriber.js.map +1 -1
- package/dist/production/src/SchemaDiffer.cjs +27 -12
- package/dist/production/src/SchemaDiffer.cjs.map +1 -1
- package/dist/production/src/SchemaDiffer.js +27 -12
- package/dist/production/src/SchemaDiffer.js.map +1 -1
- package/dist/production/src/SchemaMigrator.cjs.map +1 -1
- package/dist/production/src/SchemaMigrator.js.map +1 -1
- package/dist/production/src/modifications/ModificationHandler.cjs.map +1 -1
- package/dist/production/src/modifications/ModificationHandler.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/NoopModification.cjs.map +1 -1
- package/dist/production/src/modifications/NoopModification.js.map +1 -1
- package/dist/production/src/modifications/acl/PatchAclSchemaModification.cjs.map +1 -1
- package/dist/production/src/modifications/acl/PatchAclSchemaModification.js.map +1 -1
- package/dist/production/src/modifications/acl/UpdateAclSchemaModification.cjs.map +1 -1
- package/dist/production/src/modifications/acl/UpdateAclSchemaModification.js.map +1 -1
- package/dist/production/src/modifications/actions/CreateTargetModification.cjs.map +1 -1
- package/dist/production/src/modifications/actions/CreateTargetModification.js.map +1 -1
- package/dist/production/src/modifications/actions/CreateTriggerModification.cjs.map +1 -1
- package/dist/production/src/modifications/actions/CreateTriggerModification.js.map +1 -1
- package/dist/production/src/modifications/actions/PatchTriggerModification.cjs.map +1 -1
- package/dist/production/src/modifications/actions/PatchTriggerModification.js.map +1 -1
- package/dist/production/src/modifications/actions/RemoveTargetModification.cjs.map +1 -1
- package/dist/production/src/modifications/actions/RemoveTargetModification.js.map +1 -1
- package/dist/production/src/modifications/actions/RemoveTriggerModification.cjs.map +1 -1
- package/dist/production/src/modifications/actions/RemoveTriggerModification.js.map +1 -1
- package/dist/production/src/modifications/actions/UpdateTargetModification.cjs.map +1 -1
- package/dist/production/src/modifications/actions/UpdateTargetModification.js.map +1 -1
- package/dist/production/src/modifications/actions/UpdateTriggerModification.cjs.map +1 -1
- package/dist/production/src/modifications/actions/UpdateTriggerModification.js.map +1 -1
- package/dist/production/src/modifications/columns/CreateColumnModification.cjs.map +1 -1
- package/dist/production/src/modifications/columns/CreateColumnModification.js.map +1 -1
- package/dist/production/src/modifications/columns/UpdateColumnDefinitionModification.cjs.map +1 -1
- package/dist/production/src/modifications/columns/UpdateColumnDefinitionModification.js.map +1 -1
- package/dist/production/src/modifications/columns/UpdateColumnNameModification.cjs.map +1 -1
- package/dist/production/src/modifications/columns/UpdateColumnNameModification.js.map +1 -1
- package/dist/production/src/modifications/columns/columnUtils.cjs.map +1 -1
- package/dist/production/src/modifications/columns/columnUtils.js.map +1 -1
- package/dist/production/src/modifications/constraints/CreateUniqueConstraintModification.cjs.map +1 -1
- package/dist/production/src/modifications/constraints/CreateUniqueConstraintModification.js.map +1 -1
- package/dist/production/src/modifications/constraints/RemoveUniqueConstraintModification.cjs.map +1 -1
- package/dist/production/src/modifications/constraints/RemoveUniqueConstraintModification.js.map +1 -1
- package/dist/production/src/modifications/differs/RemoveChangedFieldDiffer.cjs.map +1 -1
- package/dist/production/src/modifications/differs/RemoveChangedFieldDiffer.js.map +1 -1
- package/dist/production/src/modifications/differs/RemoveViewDiffer.cjs +4 -1
- package/dist/production/src/modifications/differs/RemoveViewDiffer.cjs.map +1 -1
- package/dist/production/src/modifications/differs/RemoveViewDiffer.js +5 -2
- package/dist/production/src/modifications/differs/RemoveViewDiffer.js.map +1 -1
- package/dist/production/src/modifications/differs/UpdateViewDiffer.cjs +45 -0
- package/dist/production/src/modifications/differs/UpdateViewDiffer.cjs.map +1 -0
- package/dist/production/src/modifications/differs/UpdateViewDiffer.js +45 -0
- package/dist/production/src/modifications/differs/UpdateViewDiffer.js.map +1 -0
- package/dist/production/src/modifications/entities/CreateEntityModification.cjs.map +1 -1
- package/dist/production/src/modifications/entities/CreateEntityModification.js.map +1 -1
- package/dist/production/src/modifications/entities/CreateViewModification.cjs.map +1 -1
- package/dist/production/src/modifications/entities/CreateViewModification.js.map +1 -1
- package/dist/production/src/modifications/entities/RemoveEntityModification.cjs.map +1 -1
- package/dist/production/src/modifications/entities/RemoveEntityModification.js.map +1 -1
- package/dist/production/src/modifications/entities/ToggleEventLogModification.cjs.map +1 -1
- package/dist/production/src/modifications/entities/ToggleEventLogModification.js.map +1 -1
- package/dist/production/src/modifications/entities/UpdateEntityNameModification.cjs.map +1 -1
- package/dist/production/src/modifications/entities/UpdateEntityNameModification.js.map +1 -1
- package/dist/production/src/modifications/entities/UpdateEntityOrderByModification.cjs.map +1 -1
- package/dist/production/src/modifications/entities/UpdateEntityOrderByModification.js.map +1 -1
- package/dist/production/src/modifications/entities/UpdateEntityTableNameModification.cjs.map +1 -1
- package/dist/production/src/modifications/entities/UpdateEntityTableNameModification.js.map +1 -1
- package/dist/production/src/modifications/entities/UpdateViewModification.cjs.map +1 -1
- package/dist/production/src/modifications/entities/UpdateViewModification.js.map +1 -1
- package/dist/production/src/modifications/enums/CreateEnumModification.cjs.map +1 -1
- package/dist/production/src/modifications/enums/CreateEnumModification.js.map +1 -1
- package/dist/production/src/modifications/enums/RemoveEnumModification.cjs.map +1 -1
- package/dist/production/src/modifications/enums/RemoveEnumModification.js.map +1 -1
- package/dist/production/src/modifications/enums/UpdateEnumModification.cjs.map +1 -1
- package/dist/production/src/modifications/enums/UpdateEnumModification.js.map +1 -1
- package/dist/production/src/modifications/enums/enumUtils.cjs.map +1 -1
- package/dist/production/src/modifications/enums/enumUtils.js.map +1 -1
- package/dist/production/src/modifications/fields/RemoveFieldModification.cjs.map +1 -1
- package/dist/production/src/modifications/fields/RemoveFieldModification.js.map +1 -1
- package/dist/production/src/modifications/fields/UpdateFieldNameModification.cjs +10 -4
- package/dist/production/src/modifications/fields/UpdateFieldNameModification.cjs.map +1 -1
- package/dist/production/src/modifications/fields/UpdateFieldNameModification.js +10 -4
- package/dist/production/src/modifications/fields/UpdateFieldNameModification.js.map +1 -1
- package/dist/production/src/modifications/indexes/CreateIndexModification.cjs +23 -7
- package/dist/production/src/modifications/indexes/CreateIndexModification.cjs.map +1 -1
- package/dist/production/src/modifications/indexes/CreateIndexModification.js +23 -7
- package/dist/production/src/modifications/indexes/CreateIndexModification.js.map +1 -1
- package/dist/production/src/modifications/indexes/RemoveIndexModification.cjs +52 -17
- package/dist/production/src/modifications/indexes/RemoveIndexModification.cjs.map +1 -1
- package/dist/production/src/modifications/indexes/RemoveIndexModification.js +52 -17
- package/dist/production/src/modifications/indexes/RemoveIndexModification.js.map +1 -1
- package/dist/production/src/modifications/relations/ConvertManyHasManyToJoiningEntityModification.cjs +140 -0
- package/dist/production/src/modifications/relations/ConvertManyHasManyToJoiningEntityModification.cjs.map +1 -0
- package/dist/production/src/modifications/relations/ConvertManyHasManyToJoiningEntityModification.js +140 -0
- package/dist/production/src/modifications/relations/ConvertManyHasManyToJoiningEntityModification.js.map +1 -0
- package/dist/production/src/modifications/relations/ConvertOneHasManyToManyHasManyRelationModification.cjs.map +1 -1
- package/dist/production/src/modifications/relations/ConvertOneHasManyToManyHasManyRelationModification.js.map +1 -1
- package/dist/production/src/modifications/relations/ConvertOneHasManyToOneHasOneRelationModification.cjs.map +1 -1
- package/dist/production/src/modifications/relations/ConvertOneHasManyToOneHasOneRelationModification.js.map +1 -1
- package/dist/production/src/modifications/relations/ConvertOneToManyRelationModification.cjs.map +1 -1
- package/dist/production/src/modifications/relations/ConvertOneToManyRelationModification.js.map +1 -1
- package/dist/production/src/modifications/relations/CreateRelationInverseSideModification.cjs.map +1 -1
- package/dist/production/src/modifications/relations/CreateRelationInverseSideModification.js.map +1 -1
- package/dist/production/src/modifications/relations/CreateRelationModification.cjs.map +1 -1
- package/dist/production/src/modifications/relations/CreateRelationModification.js.map +1 -1
- package/dist/production/src/modifications/relations/DisableOrphanRemovalModification.cjs.map +1 -1
- package/dist/production/src/modifications/relations/DisableOrphanRemovalModification.js.map +1 -1
- package/dist/production/src/modifications/relations/EnableOrphanRemovalModification.cjs.map +1 -1
- package/dist/production/src/modifications/relations/EnableOrphanRemovalModification.js.map +1 -1
- package/dist/production/src/modifications/relations/MakeRelationNotNullModification.cjs.map +1 -1
- package/dist/production/src/modifications/relations/MakeRelationNotNullModification.js.map +1 -1
- package/dist/production/src/modifications/relations/MakeRelationNullableModification.cjs.map +1 -1
- package/dist/production/src/modifications/relations/MakeRelationNullableModification.js.map +1 -1
- package/dist/production/src/modifications/relations/ToggleJunctionEventLogModification.cjs.map +1 -1
- package/dist/production/src/modifications/relations/ToggleJunctionEventLogModification.js.map +1 -1
- package/dist/production/src/modifications/relations/UpdateRelationOnDeleteModification.cjs.map +1 -1
- package/dist/production/src/modifications/relations/UpdateRelationOnDeleteModification.js.map +1 -1
- package/dist/production/src/modifications/relations/UpdateRelationOrderByModification.cjs.map +1 -1
- package/dist/production/src/modifications/relations/UpdateRelationOrderByModification.js.map +1 -1
- package/dist/production/src/modifications/relations/helpers.cjs.map +1 -1
- package/dist/production/src/modifications/relations/helpers.js.map +1 -1
- package/dist/production/src/modifications/settings/UpdateSettingsModification.cjs.map +1 -1
- package/dist/production/src/modifications/settings/UpdateSettingsModification.js.map +1 -1
- package/dist/production/src/modifications/upgrade/RemoveIndexNamesModification.cjs.map +1 -1
- package/dist/production/src/modifications/upgrade/RemoveIndexNamesModification.js.map +1 -1
- package/dist/production/src/modifications/utils/createJunctionTable.cjs.map +1 -1
- package/dist/production/src/modifications/utils/createJunctionTable.js.map +1 -1
- package/dist/production/src/modifications/utils/diffUtils.cjs.map +1 -1
- package/dist/production/src/modifications/utils/diffUtils.js.map +1 -1
- package/dist/production/src/modifications/utils/schemaUpdateUtils.cjs.map +1 -1
- package/dist/production/src/modifications/utils/schemaUpdateUtils.js.map +1 -1
- package/dist/production/src/modifications/utils/viewDependencies.cjs +15 -1
- package/dist/production/src/modifications/utils/viewDependencies.cjs.map +1 -1
- package/dist/production/src/modifications/utils/viewDependencies.js +16 -2
- package/dist/production/src/modifications/utils/viewDependencies.js.map +1 -1
- package/dist/production/src/modifications/validation/PatchValidationSchemaModification.cjs.map +1 -1
- package/dist/production/src/modifications/validation/PatchValidationSchemaModification.js.map +1 -1
- package/dist/production/src/modifications/validation/UpdateValidationSchemaModification.cjs.map +1 -1
- package/dist/production/src/modifications/validation/UpdateValidationSchemaModification.js.map +1 -1
- package/dist/tests/cases/integration/convertManyHasManyToJoiningEntity.test.d.ts +2 -0
- package/dist/tests/cases/integration/convertManyHasManyToJoiningEntity.test.d.ts.map +1 -0
- package/dist/tests/cases/integration/skipNonModelDiffers.test.d.ts +2 -0
- package/dist/tests/cases/integration/skipNonModelDiffers.test.d.ts.map +1 -0
- package/dist/tests/src/tests.d.ts +4 -3
- package/dist/tests/src/tests.d.ts.map +1 -1
- package/dist/tests/tsconfig.tsbuildinfo +1 -1
- package/dist/types/MigrationDescriber.d.ts +2 -2
- package/dist/types/MigrationDescriber.d.ts.map +1 -1
- package/dist/types/SchemaDiffer.d.ts +12 -5
- package/dist/types/SchemaDiffer.d.ts.map +1 -1
- package/dist/types/SchemaMigrator.d.ts +2 -2
- package/dist/types/SchemaMigrator.d.ts.map +1 -1
- package/dist/types/index.d.ts +6 -6
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/modifications/ModificationHandler.d.ts +2 -2
- package/dist/types/modifications/ModificationHandler.d.ts.map +1 -1
- package/dist/types/modifications/ModificationHandlerFactory.d.ts +1 -1
- package/dist/types/modifications/ModificationHandlerFactory.d.ts.map +1 -1
- package/dist/types/modifications/NoopModification.d.ts +2 -2
- package/dist/types/modifications/NoopModification.d.ts.map +1 -1
- package/dist/types/modifications/acl/PatchAclSchemaModification.d.ts +3 -3
- package/dist/types/modifications/acl/PatchAclSchemaModification.d.ts.map +1 -1
- package/dist/types/modifications/acl/UpdateAclSchemaModification.d.ts +4 -4
- package/dist/types/modifications/acl/UpdateAclSchemaModification.d.ts.map +1 -1
- package/dist/types/modifications/acl/index.d.ts +2 -2
- package/dist/types/modifications/acl/index.d.ts.map +1 -1
- package/dist/types/modifications/actions/CreateTargetModification.d.ts +4 -4
- package/dist/types/modifications/actions/CreateTargetModification.d.ts.map +1 -1
- package/dist/types/modifications/actions/CreateTriggerModification.d.ts +4 -4
- package/dist/types/modifications/actions/CreateTriggerModification.d.ts.map +1 -1
- package/dist/types/modifications/actions/PatchTriggerModification.d.ts +3 -3
- package/dist/types/modifications/actions/PatchTriggerModification.d.ts.map +1 -1
- package/dist/types/modifications/actions/RemoveTargetModification.d.ts +4 -4
- package/dist/types/modifications/actions/RemoveTargetModification.d.ts.map +1 -1
- package/dist/types/modifications/actions/RemoveTriggerModification.d.ts +4 -4
- package/dist/types/modifications/actions/RemoveTriggerModification.d.ts.map +1 -1
- package/dist/types/modifications/actions/UpdateTargetModification.d.ts +4 -4
- package/dist/types/modifications/actions/UpdateTargetModification.d.ts.map +1 -1
- package/dist/types/modifications/actions/UpdateTriggerModification.d.ts +4 -4
- package/dist/types/modifications/actions/UpdateTriggerModification.d.ts.map +1 -1
- package/dist/types/modifications/actions/index.d.ts +4 -4
- package/dist/types/modifications/actions/index.d.ts.map +1 -1
- package/dist/types/modifications/columns/CreateColumnModification.d.ts +4 -4
- package/dist/types/modifications/columns/CreateColumnModification.d.ts.map +1 -1
- package/dist/types/modifications/columns/UpdateColumnDefinitionModification.d.ts +4 -4
- package/dist/types/modifications/columns/UpdateColumnDefinitionModification.d.ts.map +1 -1
- package/dist/types/modifications/columns/UpdateColumnNameModification.d.ts +4 -4
- package/dist/types/modifications/columns/UpdateColumnNameModification.d.ts.map +1 -1
- package/dist/types/modifications/columns/index.d.ts +3 -3
- package/dist/types/modifications/columns/index.d.ts.map +1 -1
- package/dist/types/modifications/constraints/CreateUniqueConstraintModification.d.ts +4 -4
- package/dist/types/modifications/constraints/CreateUniqueConstraintModification.d.ts.map +1 -1
- package/dist/types/modifications/constraints/RemoveUniqueConstraintModification.d.ts +4 -4
- package/dist/types/modifications/constraints/RemoveUniqueConstraintModification.d.ts.map +1 -1
- package/dist/types/modifications/constraints/index.d.ts +3 -3
- package/dist/types/modifications/constraints/index.d.ts.map +1 -1
- package/dist/types/modifications/differs/RemoveChangedFieldDiffer.d.ts +2 -2
- package/dist/types/modifications/differs/RemoveChangedFieldDiffer.d.ts.map +1 -1
- package/dist/types/modifications/differs/RemoveViewDiffer.d.ts +14 -3
- package/dist/types/modifications/differs/RemoveViewDiffer.d.ts.map +1 -1
- package/dist/types/modifications/differs/UpdateViewDiffer.d.ts +19 -0
- package/dist/types/modifications/differs/UpdateViewDiffer.d.ts.map +1 -0
- package/dist/types/modifications/differs/index.d.ts +3 -2
- package/dist/types/modifications/differs/index.d.ts.map +1 -1
- package/dist/types/modifications/entities/CreateEntityModification.d.ts +4 -4
- package/dist/types/modifications/entities/CreateEntityModification.d.ts.map +1 -1
- package/dist/types/modifications/entities/CreateViewModification.d.ts +4 -4
- package/dist/types/modifications/entities/CreateViewModification.d.ts.map +1 -1
- package/dist/types/modifications/entities/RemoveEntityModification.d.ts +4 -4
- package/dist/types/modifications/entities/RemoveEntityModification.d.ts.map +1 -1
- package/dist/types/modifications/entities/ToggleEventLogModification.d.ts +4 -4
- package/dist/types/modifications/entities/ToggleEventLogModification.d.ts.map +1 -1
- package/dist/types/modifications/entities/UpdateEntityNameModification.d.ts +3 -3
- package/dist/types/modifications/entities/UpdateEntityNameModification.d.ts.map +1 -1
- package/dist/types/modifications/entities/UpdateEntityOrderByModification.d.ts +4 -4
- package/dist/types/modifications/entities/UpdateEntityOrderByModification.d.ts.map +1 -1
- package/dist/types/modifications/entities/UpdateEntityTableNameModification.d.ts +4 -4
- package/dist/types/modifications/entities/UpdateEntityTableNameModification.d.ts.map +1 -1
- package/dist/types/modifications/entities/UpdateViewModification.d.ts +3 -3
- package/dist/types/modifications/entities/UpdateViewModification.d.ts.map +1 -1
- package/dist/types/modifications/entities/index.d.ts +7 -7
- package/dist/types/modifications/entities/index.d.ts.map +1 -1
- package/dist/types/modifications/enums/CreateEnumModification.d.ts +4 -4
- package/dist/types/modifications/enums/CreateEnumModification.d.ts.map +1 -1
- package/dist/types/modifications/enums/RemoveEnumModification.d.ts +4 -4
- package/dist/types/modifications/enums/RemoveEnumModification.d.ts.map +1 -1
- package/dist/types/modifications/enums/UpdateEnumModification.d.ts +4 -4
- package/dist/types/modifications/enums/UpdateEnumModification.d.ts.map +1 -1
- package/dist/types/modifications/enums/index.d.ts +3 -3
- package/dist/types/modifications/enums/index.d.ts.map +1 -1
- package/dist/types/modifications/fields/RemoveFieldModification.d.ts +4 -4
- package/dist/types/modifications/fields/RemoveFieldModification.d.ts.map +1 -1
- package/dist/types/modifications/fields/UpdateFieldNameModification.d.ts +3 -3
- package/dist/types/modifications/fields/UpdateFieldNameModification.d.ts.map +1 -1
- package/dist/types/modifications/fields/index.d.ts +2 -2
- package/dist/types/modifications/fields/index.d.ts.map +1 -1
- package/dist/types/modifications/index.d.ts +13 -13
- package/dist/types/modifications/index.d.ts.map +1 -1
- package/dist/types/modifications/indexes/CreateIndexModification.d.ts +4 -4
- package/dist/types/modifications/indexes/CreateIndexModification.d.ts.map +1 -1
- package/dist/types/modifications/indexes/RemoveIndexModification.d.ts +18 -6
- package/dist/types/modifications/indexes/RemoveIndexModification.d.ts.map +1 -1
- package/dist/types/modifications/indexes/index.d.ts +2 -2
- package/dist/types/modifications/indexes/index.d.ts.map +1 -1
- package/dist/types/modifications/relations/ConvertManyHasManyToJoiningEntityModification.d.ts +52 -0
- package/dist/types/modifications/relations/ConvertManyHasManyToJoiningEntityModification.d.ts.map +1 -0
- package/dist/types/modifications/relations/ConvertOneHasManyToManyHasManyRelationModification.d.ts +5 -5
- package/dist/types/modifications/relations/ConvertOneHasManyToManyHasManyRelationModification.d.ts.map +1 -1
- package/dist/types/modifications/relations/ConvertOneHasManyToOneHasOneRelationModification.d.ts +4 -4
- package/dist/types/modifications/relations/ConvertOneHasManyToOneHasOneRelationModification.d.ts.map +1 -1
- package/dist/types/modifications/relations/ConvertOneToManyRelationModification.d.ts +4 -4
- package/dist/types/modifications/relations/ConvertOneToManyRelationModification.d.ts.map +1 -1
- package/dist/types/modifications/relations/CreateRelationInverseSideModification.d.ts +4 -4
- package/dist/types/modifications/relations/CreateRelationInverseSideModification.d.ts.map +1 -1
- package/dist/types/modifications/relations/CreateRelationModification.d.ts +5 -5
- package/dist/types/modifications/relations/CreateRelationModification.d.ts.map +1 -1
- package/dist/types/modifications/relations/DisableOrphanRemovalModification.d.ts +4 -4
- package/dist/types/modifications/relations/DisableOrphanRemovalModification.d.ts.map +1 -1
- package/dist/types/modifications/relations/EnableOrphanRemovalModification.d.ts +4 -4
- package/dist/types/modifications/relations/EnableOrphanRemovalModification.d.ts.map +1 -1
- package/dist/types/modifications/relations/MakeRelationNotNullModification.d.ts +4 -4
- package/dist/types/modifications/relations/MakeRelationNotNullModification.d.ts.map +1 -1
- package/dist/types/modifications/relations/MakeRelationNullableModification.d.ts +4 -4
- package/dist/types/modifications/relations/MakeRelationNullableModification.d.ts.map +1 -1
- package/dist/types/modifications/relations/ToggleJunctionEventLogModification.d.ts +4 -4
- package/dist/types/modifications/relations/ToggleJunctionEventLogModification.d.ts.map +1 -1
- package/dist/types/modifications/relations/UpdateRelationOnDeleteModification.d.ts +4 -4
- package/dist/types/modifications/relations/UpdateRelationOnDeleteModification.d.ts.map +1 -1
- package/dist/types/modifications/relations/UpdateRelationOrderByModification.d.ts +4 -4
- package/dist/types/modifications/relations/UpdateRelationOrderByModification.d.ts.map +1 -1
- package/dist/types/modifications/relations/index.d.ts +12 -11
- package/dist/types/modifications/relations/index.d.ts.map +1 -1
- package/dist/types/modifications/settings/UpdateSettingsModification.d.ts +4 -4
- package/dist/types/modifications/settings/UpdateSettingsModification.d.ts.map +1 -1
- package/dist/types/modifications/settings/index.d.ts +1 -1
- package/dist/types/modifications/settings/index.d.ts.map +1 -1
- package/dist/types/modifications/upgrade/RemoveIndexNamesModification.d.ts +3 -3
- package/dist/types/modifications/upgrade/RemoveIndexNamesModification.d.ts.map +1 -1
- package/dist/types/modifications/utils/diffUtils.d.ts +1 -1
- package/dist/types/modifications/utils/diffUtils.d.ts.map +1 -1
- package/dist/types/modifications/utils/viewDependencies.d.ts +11 -1
- package/dist/types/modifications/utils/viewDependencies.d.ts.map +1 -1
- package/dist/types/modifications/validation/PatchValidationSchemaModification.d.ts +3 -3
- package/dist/types/modifications/validation/PatchValidationSchemaModification.d.ts.map +1 -1
- package/dist/types/modifications/validation/UpdateValidationSchemaModification.d.ts +4 -4
- package/dist/types/modifications/validation/UpdateValidationSchemaModification.d.ts.map +1 -1
- package/dist/types/modifications/validation/index.d.ts +2 -2
- package/dist/types/modifications/validation/index.d.ts.map +1 -1
- package/dist/types/tsconfig.tsbuildinfo +1 -1
- package/package.json +7 -7
- package/src/MigrationDescriber.ts +2 -2
- package/src/SchemaDiffer.ts +52 -25
- package/src/SchemaMigrator.ts +2 -2
- package/src/index.ts +6 -6
- package/src/modifications/ModificationHandler.ts +2 -2
- package/src/modifications/ModificationHandlerFactory.ts +21 -19
- package/src/modifications/NoopModification.ts +2 -2
- package/src/modifications/acl/PatchAclSchemaModification.ts +3 -3
- package/src/modifications/acl/UpdateAclSchemaModification.ts +3 -3
- package/src/modifications/acl/index.ts +2 -2
- package/src/modifications/actions/CreateTargetModification.ts +2 -2
- package/src/modifications/actions/CreateTriggerModification.ts +2 -2
- package/src/modifications/actions/PatchTriggerModification.ts +3 -3
- package/src/modifications/actions/RemoveTargetModification.ts +2 -2
- package/src/modifications/actions/RemoveTriggerModification.ts +2 -2
- package/src/modifications/actions/UpdateTargetModification.ts +2 -2
- package/src/modifications/actions/UpdateTriggerModification.ts +3 -3
- package/src/modifications/actions/index.ts +4 -4
- package/src/modifications/columns/CreateColumnModification.ts +5 -5
- package/src/modifications/columns/UpdateColumnDefinitionModification.ts +6 -6
- package/src/modifications/columns/UpdateColumnNameModification.ts +3 -3
- package/src/modifications/columns/columnUtils.ts +1 -1
- package/src/modifications/columns/index.ts +3 -3
- package/src/modifications/constraints/CreateUniqueConstraintModification.ts +4 -4
- package/src/modifications/constraints/RemoveUniqueConstraintModification.ts +4 -4
- package/src/modifications/constraints/index.ts +3 -3
- package/src/modifications/differs/RemoveChangedFieldDiffer.ts +3 -3
- package/src/modifications/differs/RemoveViewDiffer.ts +17 -5
- package/src/modifications/differs/UpdateViewDiffer.ts +58 -0
- package/src/modifications/differs/index.ts +3 -2
- package/src/modifications/entities/CreateEntityModification.ts +5 -5
- package/src/modifications/entities/CreateViewModification.ts +3 -3
- package/src/modifications/entities/RemoveEntityModification.ts +4 -4
- package/src/modifications/entities/ToggleEventLogModification.ts +3 -3
- package/src/modifications/entities/UpdateEntityNameModification.ts +12 -7
- package/src/modifications/entities/UpdateEntityOrderByModification.ts +2 -2
- package/src/modifications/entities/UpdateEntityTableNameModification.ts +2 -2
- package/src/modifications/entities/UpdateViewModification.ts +2 -2
- package/src/modifications/entities/index.ts +7 -7
- package/src/modifications/enums/CreateEnumModification.ts +3 -3
- package/src/modifications/enums/RemoveEnumModification.ts +2 -2
- package/src/modifications/enums/UpdateEnumModification.ts +4 -4
- package/src/modifications/enums/enumUtils.ts +1 -1
- package/src/modifications/enums/index.ts +3 -3
- package/src/modifications/fields/RemoveFieldModification.ts +3 -3
- package/src/modifications/fields/UpdateFieldNameModification.ts +26 -10
- package/src/modifications/fields/index.ts +2 -2
- package/src/modifications/index.ts +13 -13
- package/src/modifications/indexes/CreateIndexModification.ts +47 -11
- package/src/modifications/indexes/RemoveIndexModification.ts +92 -23
- package/src/modifications/indexes/index.ts +2 -2
- package/src/modifications/relations/ConvertManyHasManyToJoiningEntityModification.ts +218 -0
- package/src/modifications/relations/ConvertOneHasManyToManyHasManyRelationModification.ts +7 -7
- package/src/modifications/relations/ConvertOneHasManyToOneHasOneRelationModification.ts +6 -6
- package/src/modifications/relations/ConvertOneToManyRelationModification.ts +6 -6
- package/src/modifications/relations/CreateRelationInverseSideModification.ts +3 -3
- package/src/modifications/relations/CreateRelationModification.ts +9 -9
- package/src/modifications/relations/DisableOrphanRemovalModification.ts +3 -3
- package/src/modifications/relations/EnableOrphanRemovalModification.ts +3 -3
- package/src/modifications/relations/MakeRelationNotNullModification.ts +4 -4
- package/src/modifications/relations/MakeRelationNullableModification.ts +4 -4
- package/src/modifications/relations/ToggleJunctionEventLogModification.ts +5 -5
- package/src/modifications/relations/UpdateRelationOnDeleteModification.ts +5 -5
- package/src/modifications/relations/UpdateRelationOrderByModification.ts +3 -3
- package/src/modifications/relations/helpers.ts +1 -1
- package/src/modifications/relations/index.ts +12 -11
- package/src/modifications/settings/UpdateSettingsModification.ts +2 -2
- package/src/modifications/settings/index.ts +1 -1
- package/src/modifications/upgrade/RemoveIndexNamesModification.ts +2 -2
- package/src/modifications/utils/createJunctionTable.ts +3 -3
- package/src/modifications/utils/diffUtils.ts +2 -2
- package/src/modifications/utils/schemaUpdateUtils.ts +3 -3
- package/src/modifications/utils/viewDependencies.ts +26 -2
- package/src/modifications/validation/PatchValidationSchemaModification.ts +3 -3
- package/src/modifications/validation/UpdateValidationSchemaModification.ts +3 -3
- package/src/modifications/validation/index.ts +2 -2
- package/tests/cases/integration/convertManyHasManyToJoiningEntity.test.ts +339 -0
- package/tests/cases/integration/convertManyHasOneToOneHasOneRelation.test.ts +2 -2
- package/tests/cases/integration/convertOneHasManyToManyHasManyRelation.test.ts +2 -2
- package/tests/cases/integration/convertOneToManyRelation.test.ts +2 -2
- package/tests/cases/integration/createAndDropIndex.test.ts +482 -3
- package/tests/cases/integration/createColumn.test.ts +29 -2
- package/tests/cases/integration/createEntity.test.ts +2 -2
- package/tests/cases/integration/createEnum.test.ts +2 -2
- package/tests/cases/integration/createManyHasMany.test.ts +2 -2
- package/tests/cases/integration/createManyHasOne.test.ts +2 -2
- package/tests/cases/integration/createOneHasMany.test.ts +2 -2
- package/tests/cases/integration/createOneHasOne.test.ts +2 -2
- package/tests/cases/integration/createRelationInverseSide.test.ts +2 -2
- package/tests/cases/integration/createUnique.test.ts +3 -3
- package/tests/cases/integration/disableOrphanRemoval.test.ts +2 -2
- package/tests/cases/integration/enableOrphanRemoval.test.ts +2 -2
- package/tests/cases/integration/makeColumnNotNull.test.ts +2 -2
- package/tests/cases/integration/makeRelationNotNull.test.ts +2 -2
- package/tests/cases/integration/makeRelationNullable.test.ts +2 -2
- package/tests/cases/integration/patchAclSchema.test.ts +2 -2
- package/tests/cases/integration/patchTrigger.test.ts +1 -1
- package/tests/cases/integration/removeEntity.test.ts +2 -2
- package/tests/cases/integration/removeEnum.test.ts +2 -2
- package/tests/cases/integration/removeField.test.ts +3 -3
- package/tests/cases/integration/skipNonModelDiffers.test.ts +97 -0
- package/tests/cases/integration/toggleEventLog.test.ts +2 -2
- package/tests/cases/integration/toggleJunctionEventLog.test.ts +2 -2
- package/tests/cases/integration/updateColumnDefinition.test.ts +3 -3
- package/tests/cases/integration/updateEntityName.test.ts +2 -2
- package/tests/cases/integration/updateEntityOrderBy.test.ts +2 -2
- package/tests/cases/integration/updateEnum.test.ts +2 -2
- package/tests/cases/integration/updateFieldName.test.ts +38 -3
- package/tests/cases/integration/updateRelationOnDelete.test.ts +2 -2
- package/tests/cases/integration/updateRelationOrderBy.test.ts +2 -2
- package/tests/cases/integration/updateView.test.ts +221 -233
- package/tests/src/tests.ts +6 -4
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"RemoveIndexModification.cjs","sources":["../../../../../../packages/schema-migrations/src/modifications/indexes/RemoveIndexModification.ts"],"sourcesContent":["import { MigrationBuilder } from '@contember/database-migrations'\nimport { Schema } from '@contember/schema'\nimport { SchemaUpdater, updateEntity, updateModel } from '../utils/schemaUpdateUtils'\nimport { createModificationType, Differ, ModificationHandler, ModificationHandlerCreateSqlOptions } from '../ModificationHandler'\nimport deepEqual from 'fast-deep-equal'\nimport { getIndexColumns } from './utils'\nimport { wrapIdentifier } from '../../utils/dbHelpers'\n\nexport class RemoveIndexModificationHandler implements ModificationHandler<RemoveIndexModificationData> {\n\tconstructor(private readonly data: RemoveIndexModificationData, private readonly schema: Schema) {}\n\n\tpublic createSql(builder: MigrationBuilder, { databaseMetadata, invalidateDatabaseMetadata }: ModificationHandlerCreateSqlOptions): void {\n\t\tconst entity = this.schema.model.entities[this.data.entityName]\n\t\tif (entity.view && !entity.view.materialized) {\n\t\t\treturn\n\t\t}\n\t\tconst fields = this.getFields()\n\n\t\tconst columns = getIndexColumns({\n\t\t\tentity,\n\t\t\tfields,\n\t\t\tmodel: this.schema.model,\n\t\t})\n\n\t\tconst indexNames = databaseMetadata.indexes.filter({ tableName: entity.tableName, columnNames: columns, unique: false }).getNames()\n\n\t\tfor (const name of indexNames) {\n\t\t\tbuilder.sql(`DROP INDEX ${wrapIdentifier(name)}`)\n\t\t}\n\t\tinvalidateDatabaseMetadata()\n\t}\n\n\tpublic getSchemaUpdater(): SchemaUpdater {\n\t\tconst fields = this.getFields()\n\t\treturn updateModel(\n\t\t\tupdateEntity(this.data.entityName, ({ entity }) => {\n\t\t\t\tconst indexes = entity.indexes.filter(it => !deepEqual(it.fields, fields))\n\t\t\t\treturn {\n\t\t\t\t\t...entity,\n\t\t\t\t\tindexes,\n\t\t\t\t}\n\t\t\t}),\n\t\t)\n\t}\n\n\tdescribe() {\n\t\tconst fields = this.getFields()\n\t\treturn { message: `Remove index (${fields.join(', ')}) on entity ${this.data.entityName}` }\n\t}\n\n\tgetFields() {\n\t\tconst entity = this.schema.model.entities[this.data.entityName]\n\t\tconst fields = 'indexName' in this.data\n\t\t\t? entity.indexes.find(it => it.name === this.data.indexName)?.fields\n\t\t\t: this.data.fields\n\t\tif (!fields) {\n\t\t\tthrow new Error()\n\t\t}\n\t\treturn fields\n\t}\n}\n\nexport const removeIndexModification = createModificationType({\n\tid: 'removeIndex',\n\thandler: RemoveIndexModificationHandler,\n})\n\nexport type RemoveIndexModificationData =\n\t| {\n\t\tentityName: string\n\t\tindexName: string\n\t\tfields?: never\n\t}\n\t| {\n\t\tentityName: string\n\t\tfields: readonly string[]\n\t\tindexName?: never\n\t}\n\nexport class RemoveIndexDiffer implements Differ {\n\tcreateDiff(originalSchema: Schema, updatedSchema: Schema) {\n\t\treturn Object.values(originalSchema.model.entities).flatMap(entity =>\n\t\t\tentity.indexes\n\t\t\t\t.filter(\n\t\t\t\t\tit => {\n\t\t\t\t\t\tconst updatedEntity = updatedSchema.model.entities[entity.name]\n\t\t\t\t\t\tif (!updatedEntity) {\n\t\t\t\t\t\t\treturn false\n\t\t\t\t\t\t}\n\t\t\t\t\t\treturn !updatedEntity.indexes.find(index => deepEqual(index, it))\n\t\t\t\t\t},\n\t\t\t\t)\n\t\t\t\t.map(index =>\n\t\t\t\t\tremoveIndexModification.createModification({\n\t\t\t\t\t\tentityName: entity.name,\n\t\t\t\t\t\tfields: index.fields,\n\t\t\t\t\t})\n\t\t\t\t)\n\t\t)\n\t}\n}\n"],"names":["getIndexColumns","wrapIdentifier","updateModel","updateEntity","createModificationType"],"mappings":";;;;;;;AAQO,MAAM,+BAA2F;AAAA,EACvG,YAA6B,MAAoD,QAAgB;AAApE,SAAA,OAAA;AAAoD,SAAA,SAAA;AAAA,EAAiB;AAAA,EAE3F,UAAU,SAA2B,EAAE,kBAAkB,8BAAyE;AACxI,UAAM,SAAS,KAAK,OAAO,MAAM,SAAS,KAAK,KAAK,UAAU;AAC9D,QAAI,OAAO,QAAQ,CAAC,OAAO,KAAK,cAAc;AAC7C;AAAA,IACD;AACA,UAAM,SAAS,KAAK,UAAA;AAEpB,UAAM,UAAUA,MAAAA,gBAAgB;AAAA,MAC/B;AAAA,MACA;AAAA,MACA,OAAO,KAAK,OAAO;AAAA,IAAA,CACnB;AAED,UAAM,aAAa,iBAAiB,QAAQ,OAAO,EAAE,WAAW,OAAO,WAAW,aAAa,SAAS,QAAQ,MAAA,CAAO,EAAE,SAAA;AAEzH,eAAW,QAAQ,YAAY;AAC9B,cAAQ,IAAI,cAAcC,UAAAA,eAAe,IAAI,CAAC,EAAE;AAAA,IACjD;AACA,+BAAA;AAAA,EACD;AAAA,EAEO,mBAAkC;AACxC,UAAM,SAAS,KAAK,UAAA;AACpB,WAAOC,kBAAAA;AAAAA,MACNC,kBAAAA,aAAa,KAAK,KAAK,YAAY,CAAC,EAAE,aAAa;AAClD,cAAM,UAAU,OAAO,QAAQ,OAAO,CAAA,OAAM,CAAC,UAAU,GAAG,QAAQ,MAAM,CAAC;AACzE,eAAO;AAAA,UACN,GAAG;AAAA,UACH;AAAA,QAAA;AAAA,MAEF,CAAC;AAAA,IAAA;AAAA,EAEH;AAAA,EAEA,WAAW;AACV,UAAM,SAAS,KAAK,UAAA;AACpB,WAAO,EAAE,SAAS,iBAAiB,OAAO,KAAK,IAAI,CAAC,eAAe,KAAK,KAAK,UAAU,GAAA;AAAA,EACxF;AAAA,EAEA,YAAY;AACX,UAAM,SAAS,KAAK,OAAO,MAAM,SAAS,KAAK,KAAK,UAAU;AAC9D,UAAM,SAAS,eAAe,KAAK,OAChC,OAAO,QAAQ,KAAK,CAAA,OAAM,GAAG,SAAS,KAAK,KAAK,SAAS,GAAG,SAC5D,KAAK,KAAK;AACb,QAAI,CAAC,QAAQ;AACZ,YAAM,IAAI,MAAA;AAAA,IACX;AACA,WAAO;AAAA,EACR;AACD;AAEO,MAAM,0BAA0BC,oBAAAA,uBAAuB;AAAA,EAC7D,IAAI;AAAA,EACJ,SAAS;AACV,CAAC;AAcM,MAAM,kBAAoC;AAAA,EAChD,WAAW,gBAAwB,eAAuB;AACzD,WAAO,OAAO,OAAO,eAAe,MAAM,QAAQ,EAAE;AAAA,MAAQ,CAAA,WAC3D,OAAO,QACL;AAAA,QACA,CAAA,OAAM;AACL,gBAAM,gBAAgB,cAAc,MAAM,SAAS,OAAO,IAAI;AAC9D,cAAI,CAAC,eAAe;AACnB,mBAAO;AAAA,UACR;AACA,iBAAO,CAAC,cAAc,QAAQ,KAAK,WAAS,UAAU,OAAO,EAAE,CAAC;AAAA,QACjE;AAAA,MAAA,EAEA;AAAA,QAAI,CAAA,UACJ,wBAAwB,mBAAmB;AAAA,UAC1C,YAAY,OAAO;AAAA,UACnB,QAAQ,MAAM;AAAA,QAAA,CACd;AAAA,MAAA;AAAA,IACF;AAAA,EAEH;AACD;;;;"}
|
|
1
|
+
{"version":3,"file":"RemoveIndexModification.cjs","sources":["../../../../../../packages/schema-migrations/src/modifications/indexes/RemoveIndexModification.ts"],"sourcesContent":["import { MigrationBuilder } from '@contember/database-migrations'\nimport { Model, Schema } from '@contember/schema'\nimport { SchemaUpdater, updateEntity, updateModel } from '../utils/schemaUpdateUtils.js'\nimport { createModificationType, Differ, ModificationHandler, ModificationHandlerCreateSqlOptions } from '../ModificationHandler.js'\nimport deepEqual from 'fast-deep-equal'\nimport { getIndexColumns } from './utils.js'\nimport { wrapIdentifier } from '../../utils/dbHelpers.js'\n\ntype IndexIdentity = Pick<Model.Index, 'fields' | 'where' | 'include' | 'columnOptions' | 'method' | 'opClass'>\nconst indexIdentityEquals = (a: IndexIdentity, b: IndexIdentity) =>\n\tdeepEqual(a.fields, b.fields)\n\t&& (a.where ?? undefined) === (b.where ?? undefined)\n\t&& deepEqual(a.include ?? undefined, b.include ?? undefined)\n\t&& deepEqual(a.columnOptions ?? undefined, b.columnOptions ?? undefined)\n\t&& (a.method ?? undefined) === (b.method ?? undefined)\n\t&& (a.opClass ?? undefined) === (b.opClass ?? undefined)\n\nexport class RemoveIndexModificationHandler implements ModificationHandler<RemoveIndexModificationData> {\n\tconstructor(private readonly data: RemoveIndexModificationData, private readonly schema: Schema) {}\n\n\tpublic createSql(builder: MigrationBuilder, { databaseMetadata, invalidateDatabaseMetadata }: ModificationHandlerCreateSqlOptions): void {\n\t\tconst entity = this.schema.model.entities[this.data.entityName]\n\t\tif (entity.view && !entity.view.materialized) {\n\t\t\treturn\n\t\t}\n\t\tconst index = this.getIndex()\n\n\t\t// The DB-metadata layer (DatabaseMetadataResolver) exposes only table + columns (as an unordered\n\t\t// set) + uniqueness, so the physical DROP is matched by table + columns. Postgres' pg_index.indkey\n\t\t// includes the INCLUDE columns alongside the key columns, so a covering index's metadata lists both —\n\t\t// we match the same combined set here. Everything else that distinguishes two indexes on the same\n\t\t// column set — the partial WHERE predicate, per-column options (sort order / NULLS / operator class),\n\t\t// key-column ORDER (the set comparison is order-insensitive), the index method, and the index-level\n\t\t// operator class — is invisible to the metadata, so such siblings are indistinguishable here. We\n\t\t// detect that ambiguity below and fail loudly rather than DROP a sibling the schema still expects to\n\t\t// keep. Schema-level identity (see getSchemaUpdater) IS fully aware of these discriminators, so the\n\t\t// diff itself never conflates them.\n\t\tconst columns = [\n\t\t\t...getIndexColumns({ entity, fields: index.fields, model: this.schema.model }),\n\t\t\t...(index.include ? getIndexColumns({ entity, fields: index.include, model: this.schema.model }) : []),\n\t\t]\n\n\t\tconst indexNames = databaseMetadata.indexes.filter({ tableName: entity.tableName, columnNames: columns, unique: false }).getNames()\n\n\t\t// If more than one physical index matches these columns we cannot tell which one this modification\n\t\t// targets (the metadata hides the predicate / per-column options / column order / index method /\n\t\t// index-level operator class that distinguish them). Dropping every match would silently take out an\n\t\t// index the schema still expects — refuse instead, so the obsolete one can be dropped by hand.\n\t\tif (indexNames.length > 1) {\n\t\t\tthrow new Error(\n\t\t\t\t`Cannot unambiguously drop index on entity ${this.data.entityName} (${index.fields.join(', ')}): `\n\t\t\t\t\t+ `${indexNames.length} indexes match these columns and the database metadata does not expose the predicate (where), `\n\t\t\t\t\t+ `per-column options (sort order / NULLS / operator class), column order, index method or index-level operator class that distinguish them. `\n\t\t\t\t\t+ `Drop the obsolete index manually.`,\n\t\t\t)\n\t\t}\n\n\t\tfor (const name of indexNames) {\n\t\t\tbuilder.sql(`DROP INDEX ${wrapIdentifier(name)}`)\n\t\t}\n\t\tinvalidateDatabaseMetadata()\n\t}\n\n\tpublic getSchemaUpdater(): SchemaUpdater {\n\t\tconst index = this.getIndex()\n\t\treturn updateModel(\n\t\t\tupdateEntity(this.data.entityName, ({ entity }) => {\n\t\t\t\tconst indexes = entity.indexes.filter(it => !indexIdentityEquals(it, index))\n\t\t\t\treturn {\n\t\t\t\t\t...entity,\n\t\t\t\t\tindexes,\n\t\t\t\t}\n\t\t\t}),\n\t\t)\n\t}\n\n\tdescribe() {\n\t\tconst index = this.getIndex()\n\t\treturn { message: `Remove index (${index.fields.join(', ')}) on entity ${this.data.entityName}` }\n\t}\n\n\tprivate getIndex(): IndexIdentity {\n\t\tconst { entityName } = this.data\n\t\tconst entity = this.schema.model.entities[entityName]\n\t\tif ('indexName' in this.data && this.data.indexName !== undefined) {\n\t\t\tconst index = entity.indexes.find(it => it.name === this.data.indexName)\n\t\t\tif (!index) {\n\t\t\t\tthrow new Error(`Index named \"${this.data.indexName}\" not found on entity ${entityName}`)\n\t\t\t}\n\t\t\treturn {\n\t\t\t\tfields: index.fields,\n\t\t\t\twhere: index.where,\n\t\t\t\tinclude: index.include,\n\t\t\t\tcolumnOptions: index.columnOptions,\n\t\t\t\tmethod: index.method,\n\t\t\t\topClass: index.opClass,\n\t\t\t}\n\t\t}\n\t\tif (!this.data.fields) {\n\t\t\tthrow new Error(`removeIndex modification on entity ${entityName} requires either \"indexName\" or \"fields\"`)\n\t\t}\n\t\treturn {\n\t\t\tfields: this.data.fields,\n\t\t\twhere: this.data.where,\n\t\t\tinclude: this.data.include,\n\t\t\tcolumnOptions: this.data.columnOptions,\n\t\t\tmethod: this.data.method,\n\t\t\topClass: this.data.opClass,\n\t\t}\n\t}\n}\n\nexport const removeIndexModification = createModificationType({\n\tid: 'removeIndex',\n\thandler: RemoveIndexModificationHandler,\n})\n\nexport type RemoveIndexModificationData =\n\t| {\n\t\tentityName: string\n\t\tindexName: string\n\t\tfields?: never\n\t\twhere?: never\n\t\tinclude?: never\n\t\tcolumnOptions?: never\n\t\tmethod?: never\n\t\topClass?: never\n\t}\n\t| {\n\t\tentityName: string\n\t\tfields: readonly string[]\n\t\twhere?: string\n\t\tinclude?: readonly string[]\n\t\tcolumnOptions?: { readonly [field: string]: Model.IndexColumnOptions }\n\t\tmethod?: Model.IndexMethod\n\t\topClass?: string\n\t\tindexName?: never\n\t}\n\nexport class RemoveIndexDiffer implements Differ {\n\tcreateDiff(originalSchema: Schema, updatedSchema: Schema) {\n\t\treturn Object.values(originalSchema.model.entities).flatMap(entity =>\n\t\t\tentity.indexes\n\t\t\t\t.filter(\n\t\t\t\t\tit => {\n\t\t\t\t\t\tconst updatedEntity = updatedSchema.model.entities[entity.name]\n\t\t\t\t\t\tif (!updatedEntity) {\n\t\t\t\t\t\t\treturn false\n\t\t\t\t\t\t}\n\t\t\t\t\t\treturn !updatedEntity.indexes.find(index => deepEqual(index, it))\n\t\t\t\t\t},\n\t\t\t\t)\n\t\t\t\t.map(index =>\n\t\t\t\t\tremoveIndexModification.createModification({\n\t\t\t\t\t\tentityName: entity.name,\n\t\t\t\t\t\tfields: index.fields,\n\t\t\t\t\t\t// keep every identity-bearing option (WHERE/INCLUDE/columnOptions/method/opClass) in the\n\t\t\t\t\t\t// modification so indexes that share the same key columns but differ by any of them are\n\t\t\t\t\t\t// removed individually; omit the keys when absent to keep legacy migration JSON\n\t\t\t\t\t\t// byte-for-byte identical.\n\t\t\t\t\t\t...(index.where !== undefined ? { where: index.where } : {}),\n\t\t\t\t\t\t...(index.include !== undefined ? { include: index.include } : {}),\n\t\t\t\t\t\t...(index.columnOptions !== undefined ? { columnOptions: index.columnOptions } : {}),\n\t\t\t\t\t\t...(index.method !== undefined ? { method: index.method } : {}),\n\t\t\t\t\t\t...(index.opClass !== undefined ? { opClass: index.opClass } : {}),\n\t\t\t\t\t})\n\t\t\t\t)\n\t\t)\n\t}\n}\n"],"names":["getIndexColumns","wrapIdentifier","updateModel","updateEntity","createModificationType"],"mappings":"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"}
|
|
@@ -3,6 +3,7 @@ import { createModificationType } from "../ModificationHandler.js";
|
|
|
3
3
|
import deepEqual from "fast-deep-equal";
|
|
4
4
|
import { getIndexColumns } from "./utils.js";
|
|
5
5
|
import { wrapIdentifier } from "../../utils/dbHelpers.js";
|
|
6
|
+
const indexIdentityEquals = (a, b) => deepEqual(a.fields, b.fields) && (a.where ?? void 0) === (b.where ?? void 0) && deepEqual(a.include ?? void 0, b.include ?? void 0) && deepEqual(a.columnOptions ?? void 0, b.columnOptions ?? void 0) && (a.method ?? void 0) === (b.method ?? void 0) && (a.opClass ?? void 0) === (b.opClass ?? void 0);
|
|
6
7
|
class RemoveIndexModificationHandler {
|
|
7
8
|
constructor(data, schema) {
|
|
8
9
|
this.data = data;
|
|
@@ -13,23 +14,27 @@ class RemoveIndexModificationHandler {
|
|
|
13
14
|
if (entity.view && !entity.view.materialized) {
|
|
14
15
|
return;
|
|
15
16
|
}
|
|
16
|
-
const
|
|
17
|
-
const columns =
|
|
18
|
-
entity,
|
|
19
|
-
fields,
|
|
20
|
-
|
|
21
|
-
});
|
|
17
|
+
const index = this.getIndex();
|
|
18
|
+
const columns = [
|
|
19
|
+
...getIndexColumns({ entity, fields: index.fields, model: this.schema.model }),
|
|
20
|
+
...index.include ? getIndexColumns({ entity, fields: index.include, model: this.schema.model }) : []
|
|
21
|
+
];
|
|
22
22
|
const indexNames = databaseMetadata.indexes.filter({ tableName: entity.tableName, columnNames: columns, unique: false }).getNames();
|
|
23
|
+
if (indexNames.length > 1) {
|
|
24
|
+
throw new Error(
|
|
25
|
+
`Cannot unambiguously drop index on entity ${this.data.entityName} (${index.fields.join(", ")}): ${indexNames.length} indexes match these columns and the database metadata does not expose the predicate (where), per-column options (sort order / NULLS / operator class), column order, index method or index-level operator class that distinguish them. Drop the obsolete index manually.`
|
|
26
|
+
);
|
|
27
|
+
}
|
|
23
28
|
for (const name of indexNames) {
|
|
24
29
|
builder.sql(`DROP INDEX ${wrapIdentifier(name)}`);
|
|
25
30
|
}
|
|
26
31
|
invalidateDatabaseMetadata();
|
|
27
32
|
}
|
|
28
33
|
getSchemaUpdater() {
|
|
29
|
-
const
|
|
34
|
+
const index = this.getIndex();
|
|
30
35
|
return updateModel(
|
|
31
36
|
updateEntity(this.data.entityName, ({ entity }) => {
|
|
32
|
-
const indexes = entity.indexes.filter((it) => !
|
|
37
|
+
const indexes = entity.indexes.filter((it) => !indexIdentityEquals(it, index));
|
|
33
38
|
return {
|
|
34
39
|
...entity,
|
|
35
40
|
indexes
|
|
@@ -38,16 +43,37 @@ class RemoveIndexModificationHandler {
|
|
|
38
43
|
);
|
|
39
44
|
}
|
|
40
45
|
describe() {
|
|
41
|
-
const
|
|
42
|
-
return { message: `Remove index (${fields.join(", ")}) on entity ${this.data.entityName}` };
|
|
46
|
+
const index = this.getIndex();
|
|
47
|
+
return { message: `Remove index (${index.fields.join(", ")}) on entity ${this.data.entityName}` };
|
|
43
48
|
}
|
|
44
|
-
|
|
45
|
-
const
|
|
46
|
-
const
|
|
47
|
-
if (
|
|
48
|
-
|
|
49
|
+
getIndex() {
|
|
50
|
+
const { entityName } = this.data;
|
|
51
|
+
const entity = this.schema.model.entities[entityName];
|
|
52
|
+
if ("indexName" in this.data && this.data.indexName !== void 0) {
|
|
53
|
+
const index = entity.indexes.find((it) => it.name === this.data.indexName);
|
|
54
|
+
if (!index) {
|
|
55
|
+
throw new Error(`Index named "${this.data.indexName}" not found on entity ${entityName}`);
|
|
56
|
+
}
|
|
57
|
+
return {
|
|
58
|
+
fields: index.fields,
|
|
59
|
+
where: index.where,
|
|
60
|
+
include: index.include,
|
|
61
|
+
columnOptions: index.columnOptions,
|
|
62
|
+
method: index.method,
|
|
63
|
+
opClass: index.opClass
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
if (!this.data.fields) {
|
|
67
|
+
throw new Error(`removeIndex modification on entity ${entityName} requires either "indexName" or "fields"`);
|
|
49
68
|
}
|
|
50
|
-
return
|
|
69
|
+
return {
|
|
70
|
+
fields: this.data.fields,
|
|
71
|
+
where: this.data.where,
|
|
72
|
+
include: this.data.include,
|
|
73
|
+
columnOptions: this.data.columnOptions,
|
|
74
|
+
method: this.data.method,
|
|
75
|
+
opClass: this.data.opClass
|
|
76
|
+
};
|
|
51
77
|
}
|
|
52
78
|
}
|
|
53
79
|
const removeIndexModification = createModificationType({
|
|
@@ -68,7 +94,16 @@ class RemoveIndexDiffer {
|
|
|
68
94
|
).map(
|
|
69
95
|
(index) => removeIndexModification.createModification({
|
|
70
96
|
entityName: entity.name,
|
|
71
|
-
fields: index.fields
|
|
97
|
+
fields: index.fields,
|
|
98
|
+
// keep every identity-bearing option (WHERE/INCLUDE/columnOptions/method/opClass) in the
|
|
99
|
+
// modification so indexes that share the same key columns but differ by any of them are
|
|
100
|
+
// removed individually; omit the keys when absent to keep legacy migration JSON
|
|
101
|
+
// byte-for-byte identical.
|
|
102
|
+
...index.where !== void 0 ? { where: index.where } : {},
|
|
103
|
+
...index.include !== void 0 ? { include: index.include } : {},
|
|
104
|
+
...index.columnOptions !== void 0 ? { columnOptions: index.columnOptions } : {},
|
|
105
|
+
...index.method !== void 0 ? { method: index.method } : {},
|
|
106
|
+
...index.opClass !== void 0 ? { opClass: index.opClass } : {}
|
|
72
107
|
})
|
|
73
108
|
)
|
|
74
109
|
);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"RemoveIndexModification.js","sources":["../../../../../../packages/schema-migrations/src/modifications/indexes/RemoveIndexModification.ts"],"sourcesContent":["import { MigrationBuilder } from '@contember/database-migrations'\nimport { Schema } from '@contember/schema'\nimport { SchemaUpdater, updateEntity, updateModel } from '../utils/schemaUpdateUtils'\nimport { createModificationType, Differ, ModificationHandler, ModificationHandlerCreateSqlOptions } from '../ModificationHandler'\nimport deepEqual from 'fast-deep-equal'\nimport { getIndexColumns } from './utils'\nimport { wrapIdentifier } from '../../utils/dbHelpers'\n\nexport class RemoveIndexModificationHandler implements ModificationHandler<RemoveIndexModificationData> {\n\tconstructor(private readonly data: RemoveIndexModificationData, private readonly schema: Schema) {}\n\n\tpublic createSql(builder: MigrationBuilder, { databaseMetadata, invalidateDatabaseMetadata }: ModificationHandlerCreateSqlOptions): void {\n\t\tconst entity = this.schema.model.entities[this.data.entityName]\n\t\tif (entity.view && !entity.view.materialized) {\n\t\t\treturn\n\t\t}\n\t\tconst fields = this.getFields()\n\n\t\tconst columns = getIndexColumns({\n\t\t\tentity,\n\t\t\tfields,\n\t\t\tmodel: this.schema.model,\n\t\t})\n\n\t\tconst indexNames = databaseMetadata.indexes.filter({ tableName: entity.tableName, columnNames: columns, unique: false }).getNames()\n\n\t\tfor (const name of indexNames) {\n\t\t\tbuilder.sql(`DROP INDEX ${wrapIdentifier(name)}`)\n\t\t}\n\t\tinvalidateDatabaseMetadata()\n\t}\n\n\tpublic getSchemaUpdater(): SchemaUpdater {\n\t\tconst fields = this.getFields()\n\t\treturn updateModel(\n\t\t\tupdateEntity(this.data.entityName, ({ entity }) => {\n\t\t\t\tconst indexes = entity.indexes.filter(it => !deepEqual(it.fields, fields))\n\t\t\t\treturn {\n\t\t\t\t\t...entity,\n\t\t\t\t\tindexes,\n\t\t\t\t}\n\t\t\t}),\n\t\t)\n\t}\n\n\tdescribe() {\n\t\tconst fields = this.getFields()\n\t\treturn { message: `Remove index (${fields.join(', ')}) on entity ${this.data.entityName}` }\n\t}\n\n\tgetFields() {\n\t\tconst entity = this.schema.model.entities[this.data.entityName]\n\t\tconst fields = 'indexName' in this.data\n\t\t\t? entity.indexes.find(it => it.name === this.data.indexName)?.fields\n\t\t\t: this.data.fields\n\t\tif (!fields) {\n\t\t\tthrow new Error()\n\t\t}\n\t\treturn fields\n\t}\n}\n\nexport const removeIndexModification = createModificationType({\n\tid: 'removeIndex',\n\thandler: RemoveIndexModificationHandler,\n})\n\nexport type RemoveIndexModificationData =\n\t| {\n\t\tentityName: string\n\t\tindexName: string\n\t\tfields?: never\n\t}\n\t| {\n\t\tentityName: string\n\t\tfields: readonly string[]\n\t\tindexName?: never\n\t}\n\nexport class RemoveIndexDiffer implements Differ {\n\tcreateDiff(originalSchema: Schema, updatedSchema: Schema) {\n\t\treturn Object.values(originalSchema.model.entities).flatMap(entity =>\n\t\t\tentity.indexes\n\t\t\t\t.filter(\n\t\t\t\t\tit => {\n\t\t\t\t\t\tconst updatedEntity = updatedSchema.model.entities[entity.name]\n\t\t\t\t\t\tif (!updatedEntity) {\n\t\t\t\t\t\t\treturn false\n\t\t\t\t\t\t}\n\t\t\t\t\t\treturn !updatedEntity.indexes.find(index => deepEqual(index, it))\n\t\t\t\t\t},\n\t\t\t\t)\n\t\t\t\t.map(index =>\n\t\t\t\t\tremoveIndexModification.createModification({\n\t\t\t\t\t\tentityName: entity.name,\n\t\t\t\t\t\tfields: index.fields,\n\t\t\t\t\t})\n\t\t\t\t)\n\t\t)\n\t}\n}\n"],"names":[],"mappings":";;;;;AAQO,MAAM,+BAA2F;AAAA,EACvG,YAA6B,MAAoD,QAAgB;AAApE,SAAA,OAAA;AAAoD,SAAA,SAAA;AAAA,EAAiB;AAAA,EAE3F,UAAU,SAA2B,EAAE,kBAAkB,8BAAyE;AACxI,UAAM,SAAS,KAAK,OAAO,MAAM,SAAS,KAAK,KAAK,UAAU;AAC9D,QAAI,OAAO,QAAQ,CAAC,OAAO,KAAK,cAAc;AAC7C;AAAA,IACD;AACA,UAAM,SAAS,KAAK,UAAA;AAEpB,UAAM,UAAU,gBAAgB;AAAA,MAC/B;AAAA,MACA;AAAA,MACA,OAAO,KAAK,OAAO;AAAA,IAAA,CACnB;AAED,UAAM,aAAa,iBAAiB,QAAQ,OAAO,EAAE,WAAW,OAAO,WAAW,aAAa,SAAS,QAAQ,MAAA,CAAO,EAAE,SAAA;AAEzH,eAAW,QAAQ,YAAY;AAC9B,cAAQ,IAAI,cAAc,eAAe,IAAI,CAAC,EAAE;AAAA,IACjD;AACA,+BAAA;AAAA,EACD;AAAA,EAEO,mBAAkC;AACxC,UAAM,SAAS,KAAK,UAAA;AACpB,WAAO;AAAA,MACN,aAAa,KAAK,KAAK,YAAY,CAAC,EAAE,aAAa;AAClD,cAAM,UAAU,OAAO,QAAQ,OAAO,CAAA,OAAM,CAAC,UAAU,GAAG,QAAQ,MAAM,CAAC;AACzE,eAAO;AAAA,UACN,GAAG;AAAA,UACH;AAAA,QAAA;AAAA,MAEF,CAAC;AAAA,IAAA;AAAA,EAEH;AAAA,EAEA,WAAW;AACV,UAAM,SAAS,KAAK,UAAA;AACpB,WAAO,EAAE,SAAS,iBAAiB,OAAO,KAAK,IAAI,CAAC,eAAe,KAAK,KAAK,UAAU,GAAA;AAAA,EACxF;AAAA,EAEA,YAAY;AACX,UAAM,SAAS,KAAK,OAAO,MAAM,SAAS,KAAK,KAAK,UAAU;AAC9D,UAAM,SAAS,eAAe,KAAK,OAChC,OAAO,QAAQ,KAAK,CAAA,OAAM,GAAG,SAAS,KAAK,KAAK,SAAS,GAAG,SAC5D,KAAK,KAAK;AACb,QAAI,CAAC,QAAQ;AACZ,YAAM,IAAI,MAAA;AAAA,IACX;AACA,WAAO;AAAA,EACR;AACD;AAEO,MAAM,0BAA0B,uBAAuB;AAAA,EAC7D,IAAI;AAAA,EACJ,SAAS;AACV,CAAC;AAcM,MAAM,kBAAoC;AAAA,EAChD,WAAW,gBAAwB,eAAuB;AACzD,WAAO,OAAO,OAAO,eAAe,MAAM,QAAQ,EAAE;AAAA,MAAQ,CAAA,WAC3D,OAAO,QACL;AAAA,QACA,CAAA,OAAM;AACL,gBAAM,gBAAgB,cAAc,MAAM,SAAS,OAAO,IAAI;AAC9D,cAAI,CAAC,eAAe;AACnB,mBAAO;AAAA,UACR;AACA,iBAAO,CAAC,cAAc,QAAQ,KAAK,WAAS,UAAU,OAAO,EAAE,CAAC;AAAA,QACjE;AAAA,MAAA,EAEA;AAAA,QAAI,CAAA,UACJ,wBAAwB,mBAAmB;AAAA,UAC1C,YAAY,OAAO;AAAA,UACnB,QAAQ,MAAM;AAAA,QAAA,CACd;AAAA,MAAA;AAAA,IACF;AAAA,EAEH;AACD;"}
|
|
1
|
+
{"version":3,"file":"RemoveIndexModification.js","sources":["../../../../../../packages/schema-migrations/src/modifications/indexes/RemoveIndexModification.ts"],"sourcesContent":["import { MigrationBuilder } from '@contember/database-migrations'\nimport { Model, Schema } from '@contember/schema'\nimport { SchemaUpdater, updateEntity, updateModel } from '../utils/schemaUpdateUtils.js'\nimport { createModificationType, Differ, ModificationHandler, ModificationHandlerCreateSqlOptions } from '../ModificationHandler.js'\nimport deepEqual from 'fast-deep-equal'\nimport { getIndexColumns } from './utils.js'\nimport { wrapIdentifier } from '../../utils/dbHelpers.js'\n\ntype IndexIdentity = Pick<Model.Index, 'fields' | 'where' | 'include' | 'columnOptions' | 'method' | 'opClass'>\nconst indexIdentityEquals = (a: IndexIdentity, b: IndexIdentity) =>\n\tdeepEqual(a.fields, b.fields)\n\t&& (a.where ?? undefined) === (b.where ?? undefined)\n\t&& deepEqual(a.include ?? undefined, b.include ?? undefined)\n\t&& deepEqual(a.columnOptions ?? undefined, b.columnOptions ?? undefined)\n\t&& (a.method ?? undefined) === (b.method ?? undefined)\n\t&& (a.opClass ?? undefined) === (b.opClass ?? undefined)\n\nexport class RemoveIndexModificationHandler implements ModificationHandler<RemoveIndexModificationData> {\n\tconstructor(private readonly data: RemoveIndexModificationData, private readonly schema: Schema) {}\n\n\tpublic createSql(builder: MigrationBuilder, { databaseMetadata, invalidateDatabaseMetadata }: ModificationHandlerCreateSqlOptions): void {\n\t\tconst entity = this.schema.model.entities[this.data.entityName]\n\t\tif (entity.view && !entity.view.materialized) {\n\t\t\treturn\n\t\t}\n\t\tconst index = this.getIndex()\n\n\t\t// The DB-metadata layer (DatabaseMetadataResolver) exposes only table + columns (as an unordered\n\t\t// set) + uniqueness, so the physical DROP is matched by table + columns. Postgres' pg_index.indkey\n\t\t// includes the INCLUDE columns alongside the key columns, so a covering index's metadata lists both —\n\t\t// we match the same combined set here. Everything else that distinguishes two indexes on the same\n\t\t// column set — the partial WHERE predicate, per-column options (sort order / NULLS / operator class),\n\t\t// key-column ORDER (the set comparison is order-insensitive), the index method, and the index-level\n\t\t// operator class — is invisible to the metadata, so such siblings are indistinguishable here. We\n\t\t// detect that ambiguity below and fail loudly rather than DROP a sibling the schema still expects to\n\t\t// keep. Schema-level identity (see getSchemaUpdater) IS fully aware of these discriminators, so the\n\t\t// diff itself never conflates them.\n\t\tconst columns = [\n\t\t\t...getIndexColumns({ entity, fields: index.fields, model: this.schema.model }),\n\t\t\t...(index.include ? getIndexColumns({ entity, fields: index.include, model: this.schema.model }) : []),\n\t\t]\n\n\t\tconst indexNames = databaseMetadata.indexes.filter({ tableName: entity.tableName, columnNames: columns, unique: false }).getNames()\n\n\t\t// If more than one physical index matches these columns we cannot tell which one this modification\n\t\t// targets (the metadata hides the predicate / per-column options / column order / index method /\n\t\t// index-level operator class that distinguish them). Dropping every match would silently take out an\n\t\t// index the schema still expects — refuse instead, so the obsolete one can be dropped by hand.\n\t\tif (indexNames.length > 1) {\n\t\t\tthrow new Error(\n\t\t\t\t`Cannot unambiguously drop index on entity ${this.data.entityName} (${index.fields.join(', ')}): `\n\t\t\t\t\t+ `${indexNames.length} indexes match these columns and the database metadata does not expose the predicate (where), `\n\t\t\t\t\t+ `per-column options (sort order / NULLS / operator class), column order, index method or index-level operator class that distinguish them. `\n\t\t\t\t\t+ `Drop the obsolete index manually.`,\n\t\t\t)\n\t\t}\n\n\t\tfor (const name of indexNames) {\n\t\t\tbuilder.sql(`DROP INDEX ${wrapIdentifier(name)}`)\n\t\t}\n\t\tinvalidateDatabaseMetadata()\n\t}\n\n\tpublic getSchemaUpdater(): SchemaUpdater {\n\t\tconst index = this.getIndex()\n\t\treturn updateModel(\n\t\t\tupdateEntity(this.data.entityName, ({ entity }) => {\n\t\t\t\tconst indexes = entity.indexes.filter(it => !indexIdentityEquals(it, index))\n\t\t\t\treturn {\n\t\t\t\t\t...entity,\n\t\t\t\t\tindexes,\n\t\t\t\t}\n\t\t\t}),\n\t\t)\n\t}\n\n\tdescribe() {\n\t\tconst index = this.getIndex()\n\t\treturn { message: `Remove index (${index.fields.join(', ')}) on entity ${this.data.entityName}` }\n\t}\n\n\tprivate getIndex(): IndexIdentity {\n\t\tconst { entityName } = this.data\n\t\tconst entity = this.schema.model.entities[entityName]\n\t\tif ('indexName' in this.data && this.data.indexName !== undefined) {\n\t\t\tconst index = entity.indexes.find(it => it.name === this.data.indexName)\n\t\t\tif (!index) {\n\t\t\t\tthrow new Error(`Index named \"${this.data.indexName}\" not found on entity ${entityName}`)\n\t\t\t}\n\t\t\treturn {\n\t\t\t\tfields: index.fields,\n\t\t\t\twhere: index.where,\n\t\t\t\tinclude: index.include,\n\t\t\t\tcolumnOptions: index.columnOptions,\n\t\t\t\tmethod: index.method,\n\t\t\t\topClass: index.opClass,\n\t\t\t}\n\t\t}\n\t\tif (!this.data.fields) {\n\t\t\tthrow new Error(`removeIndex modification on entity ${entityName} requires either \"indexName\" or \"fields\"`)\n\t\t}\n\t\treturn {\n\t\t\tfields: this.data.fields,\n\t\t\twhere: this.data.where,\n\t\t\tinclude: this.data.include,\n\t\t\tcolumnOptions: this.data.columnOptions,\n\t\t\tmethod: this.data.method,\n\t\t\topClass: this.data.opClass,\n\t\t}\n\t}\n}\n\nexport const removeIndexModification = createModificationType({\n\tid: 'removeIndex',\n\thandler: RemoveIndexModificationHandler,\n})\n\nexport type RemoveIndexModificationData =\n\t| {\n\t\tentityName: string\n\t\tindexName: string\n\t\tfields?: never\n\t\twhere?: never\n\t\tinclude?: never\n\t\tcolumnOptions?: never\n\t\tmethod?: never\n\t\topClass?: never\n\t}\n\t| {\n\t\tentityName: string\n\t\tfields: readonly string[]\n\t\twhere?: string\n\t\tinclude?: readonly string[]\n\t\tcolumnOptions?: { readonly [field: string]: Model.IndexColumnOptions }\n\t\tmethod?: Model.IndexMethod\n\t\topClass?: string\n\t\tindexName?: never\n\t}\n\nexport class RemoveIndexDiffer implements Differ {\n\tcreateDiff(originalSchema: Schema, updatedSchema: Schema) {\n\t\treturn Object.values(originalSchema.model.entities).flatMap(entity =>\n\t\t\tentity.indexes\n\t\t\t\t.filter(\n\t\t\t\t\tit => {\n\t\t\t\t\t\tconst updatedEntity = updatedSchema.model.entities[entity.name]\n\t\t\t\t\t\tif (!updatedEntity) {\n\t\t\t\t\t\t\treturn false\n\t\t\t\t\t\t}\n\t\t\t\t\t\treturn !updatedEntity.indexes.find(index => deepEqual(index, it))\n\t\t\t\t\t},\n\t\t\t\t)\n\t\t\t\t.map(index =>\n\t\t\t\t\tremoveIndexModification.createModification({\n\t\t\t\t\t\tentityName: entity.name,\n\t\t\t\t\t\tfields: index.fields,\n\t\t\t\t\t\t// keep every identity-bearing option (WHERE/INCLUDE/columnOptions/method/opClass) in the\n\t\t\t\t\t\t// modification so indexes that share the same key columns but differ by any of them are\n\t\t\t\t\t\t// removed individually; omit the keys when absent to keep legacy migration JSON\n\t\t\t\t\t\t// byte-for-byte identical.\n\t\t\t\t\t\t...(index.where !== undefined ? { where: index.where } : {}),\n\t\t\t\t\t\t...(index.include !== undefined ? { include: index.include } : {}),\n\t\t\t\t\t\t...(index.columnOptions !== undefined ? { columnOptions: index.columnOptions } : {}),\n\t\t\t\t\t\t...(index.method !== undefined ? { method: index.method } : {}),\n\t\t\t\t\t\t...(index.opClass !== undefined ? { opClass: index.opClass } : {}),\n\t\t\t\t\t})\n\t\t\t\t)\n\t\t)\n\t}\n}\n"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
3
|
+
const schema = require("@contember/schema");
|
|
4
|
+
const schemaUpdateUtils = require("../utils/schemaUpdateUtils.cjs");
|
|
5
|
+
const ModificationHandler = require("../ModificationHandler.cjs");
|
|
6
|
+
const sqlUpdateUtils = require("../utils/sqlUpdateUtils.cjs");
|
|
7
|
+
const columnUtils = require("../utils/columnUtils.cjs");
|
|
8
|
+
const dbHelpers = require("../../utils/dbHelpers.cjs");
|
|
9
|
+
const ModificationVersions = require("../ModificationVersions.cjs");
|
|
10
|
+
class ConvertManyHasManyToJoiningEntityModificationHandler {
|
|
11
|
+
constructor(data, schema2, options) {
|
|
12
|
+
this.data = data;
|
|
13
|
+
this.schema = schema2;
|
|
14
|
+
this.options = options;
|
|
15
|
+
}
|
|
16
|
+
createSql(builder, { systemSchema }) {
|
|
17
|
+
const { relation } = this.getRelation();
|
|
18
|
+
const joiningTable = relation.joiningTable;
|
|
19
|
+
const tableName = joiningTable.tableName;
|
|
20
|
+
const tableNameId = dbHelpers.wrapIdentifier(tableName);
|
|
21
|
+
const joiningEntity = this.data.joiningEntity;
|
|
22
|
+
const primaryColumn = joiningEntity.fields[joiningEntity.primary];
|
|
23
|
+
const primaryColumnName = primaryColumn.columnName;
|
|
24
|
+
const primaryColumnNameId = dbHelpers.wrapIdentifier(primaryColumnName);
|
|
25
|
+
const primaryColumnType = columnUtils.getColumnSqlType(primaryColumn);
|
|
26
|
+
if (joiningTable.eventLog.enabled) {
|
|
27
|
+
sqlUpdateUtils.dropEventTrigger(builder, tableName);
|
|
28
|
+
sqlUpdateUtils.dropEventTrxTrigger(builder, tableName);
|
|
29
|
+
}
|
|
30
|
+
builder.sql(`ALTER TABLE ${tableNameId} ADD COLUMN ${primaryColumnNameId} ${primaryColumnType}`);
|
|
31
|
+
builder.sql(ensureUuidGenerator(systemSchema));
|
|
32
|
+
builder.sql(`UPDATE ${tableNameId} SET ${primaryColumnNameId} = ${uuidGenerator(systemSchema)}`);
|
|
33
|
+
builder.sql(`ALTER TABLE ${tableNameId} ALTER COLUMN ${primaryColumnNameId} SET NOT NULL`);
|
|
34
|
+
builder.sql(`ALTER TABLE ${tableNameId} DROP CONSTRAINT ${dbHelpers.wrapIdentifier(`${tableName}_pkey`)}`);
|
|
35
|
+
builder.sql(`ALTER TABLE ${tableNameId} ADD PRIMARY KEY (${primaryColumnNameId})`);
|
|
36
|
+
builder.sql(
|
|
37
|
+
`ALTER TABLE ${tableNameId} ADD UNIQUE (${dbHelpers.wrapIdentifier(joiningTable.joiningColumn.columnName)}, ${dbHelpers.wrapIdentifier(joiningTable.inverseJoiningColumn.columnName)})`
|
|
38
|
+
);
|
|
39
|
+
if (joiningEntity.eventLog?.enabled !== false) {
|
|
40
|
+
sqlUpdateUtils.createEventTrigger(builder, systemSchema, tableName, [primaryColumnName]);
|
|
41
|
+
sqlUpdateUtils.createEventTrxTrigger(builder, systemSchema, tableName);
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
getSchemaUpdater() {
|
|
45
|
+
const { entity, relation } = this.getRelation();
|
|
46
|
+
const version = this.options.formatVersion ?? ModificationVersions.VERSION_LATEST;
|
|
47
|
+
const joiningEntity = this.data.joiningEntity;
|
|
48
|
+
const joinUniqueConstraint = this.getJoinUniqueConstraint();
|
|
49
|
+
return schemaUpdateUtils.updateSchema(
|
|
50
|
+
// remove the original many-has-many (owning side + inverse side)
|
|
51
|
+
schemaUpdateUtils.removeField(entity.name, relation.name, version),
|
|
52
|
+
// register the new joining entity reusing the junction table
|
|
53
|
+
schemaUpdateUtils.updateModel(({ model }) => ({
|
|
54
|
+
...model,
|
|
55
|
+
entities: {
|
|
56
|
+
...model.entities,
|
|
57
|
+
[joiningEntity.name]: {
|
|
58
|
+
eventLog: { enabled: true },
|
|
59
|
+
...joiningEntity,
|
|
60
|
+
// Keep the schema in sync with the join-uniqueness constraint emitted by createSql.
|
|
61
|
+
unique: [...Object.values(joiningEntity.unique ?? []), joinUniqueConstraint],
|
|
62
|
+
indexes: Object.values(joiningEntity.indexes ?? [])
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
})),
|
|
66
|
+
// add inverse one-has-many relations on both connected entities
|
|
67
|
+
this.data.sourceInverseSide ? schemaUpdateUtils.updateModel(schemaUpdateUtils.updateEntity(entity.name, schemaUpdateUtils.addField(this.data.sourceInverseSide))) : void 0,
|
|
68
|
+
this.data.targetInverseSide ? schemaUpdateUtils.updateModel(schemaUpdateUtils.updateEntity(relation.target, schemaUpdateUtils.addField(this.data.targetInverseSide))) : void 0
|
|
69
|
+
);
|
|
70
|
+
}
|
|
71
|
+
describe() {
|
|
72
|
+
return {
|
|
73
|
+
message: `Converts ManyHasMany relation ${this.data.entityName}.${this.data.fieldName} to a joining entity ${this.data.joiningEntity.name}`
|
|
74
|
+
};
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* The join-uniqueness constraint (relationA, relationB) that replaces the dropped composite
|
|
78
|
+
* primary key. The field names are resolved from the joining entity's two many-has-one relations
|
|
79
|
+
* by matching their joining columns against the original junction columns, so the constraint
|
|
80
|
+
* references schema field names (not raw column names).
|
|
81
|
+
*/
|
|
82
|
+
getJoinUniqueConstraint() {
|
|
83
|
+
const { relation } = this.getRelation();
|
|
84
|
+
const joiningTable = relation.joiningTable;
|
|
85
|
+
const joiningEntity = this.data.joiningEntity;
|
|
86
|
+
const findRelationField = (columnName) => {
|
|
87
|
+
const field = Object.values(joiningEntity.fields).find(
|
|
88
|
+
(it) => "joiningColumn" in it && it.joiningColumn.columnName === columnName
|
|
89
|
+
);
|
|
90
|
+
if (!field) {
|
|
91
|
+
throw new Error(
|
|
92
|
+
`Joining entity ${joiningEntity.name} has no many-has-one relation mapped to column ${columnName}`
|
|
93
|
+
);
|
|
94
|
+
}
|
|
95
|
+
return field.name;
|
|
96
|
+
};
|
|
97
|
+
return {
|
|
98
|
+
fields: [
|
|
99
|
+
findRelationField(joiningTable.joiningColumn.columnName),
|
|
100
|
+
findRelationField(joiningTable.inverseJoiningColumn.columnName)
|
|
101
|
+
]
|
|
102
|
+
};
|
|
103
|
+
}
|
|
104
|
+
getRelation() {
|
|
105
|
+
const entity = this.schema.model.entities[this.data.entityName];
|
|
106
|
+
const relation = entity.fields[this.data.fieldName];
|
|
107
|
+
if (!relation || relation.type !== schema.Model.RelationType.ManyHasMany || !("joiningTable" in relation)) {
|
|
108
|
+
throw new Error(`${this.data.entityName}.${this.data.fieldName} is not a many-has-many owning relation`);
|
|
109
|
+
}
|
|
110
|
+
return { entity, relation };
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
const uuidGenerator = (systemSchema) => `${dbHelpers.wrapIdentifier(systemSchema)}."uuid_generate_v4"()`;
|
|
114
|
+
const ensureUuidGenerator = (systemSchema) => {
|
|
115
|
+
const systemSchemaId = dbHelpers.wrapIdentifier(systemSchema);
|
|
116
|
+
return `DO $ensure_uuid$
|
|
117
|
+
BEGIN
|
|
118
|
+
IF NOT EXISTS(
|
|
119
|
+
SELECT FROM pg_proc
|
|
120
|
+
JOIN pg_namespace ON pg_proc.pronamespace = pg_namespace.oid
|
|
121
|
+
WHERE pg_namespace.nspname = ${quoteLiteral(systemSchema)} AND pg_proc.proname = 'uuid_generate_v4'
|
|
122
|
+
) THEN
|
|
123
|
+
CREATE FUNCTION ${systemSchemaId}."uuid_generate_v4"() RETURNS "uuid"
|
|
124
|
+
LANGUAGE "sql"
|
|
125
|
+
AS $ensure_uuid_body$
|
|
126
|
+
SELECT OVERLAY(OVERLAY(md5(random()::TEXT || ':' || clock_timestamp()::TEXT) PLACING '4' FROM 13) PLACING
|
|
127
|
+
to_hex(floor(random() * (11 - 8 + 1) + 8)::INT)::TEXT FROM 17)::UUID;
|
|
128
|
+
$ensure_uuid_body$;
|
|
129
|
+
END IF;
|
|
130
|
+
END
|
|
131
|
+
$ensure_uuid$;`;
|
|
132
|
+
};
|
|
133
|
+
const quoteLiteral = (value) => `'${value.replace(/'/g, "''")}'`;
|
|
134
|
+
const convertManyHasManyToJoiningEntityModification = ModificationHandler.createModificationType({
|
|
135
|
+
id: "convertManyHasManyToJoiningEntity",
|
|
136
|
+
handler: ConvertManyHasManyToJoiningEntityModificationHandler
|
|
137
|
+
});
|
|
138
|
+
exports.ConvertManyHasManyToJoiningEntityModificationHandler = ConvertManyHasManyToJoiningEntityModificationHandler;
|
|
139
|
+
exports.convertManyHasManyToJoiningEntityModification = convertManyHasManyToJoiningEntityModification;
|
|
140
|
+
//# sourceMappingURL=ConvertManyHasManyToJoiningEntityModification.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ConvertManyHasManyToJoiningEntityModification.cjs","sources":["../../../../../../packages/schema-migrations/src/modifications/relations/ConvertManyHasManyToJoiningEntityModification.ts"],"sourcesContent":["import { MigrationBuilder } from '@contember/database-migrations'\nimport { Model, Schema } from '@contember/schema'\nimport { addField, removeField, SchemaUpdater, updateEntity, updateModel, updateSchema } from '../utils/schemaUpdateUtils.js'\nimport {\n\tcreateModificationType,\n\tModificationHandler,\n\tModificationHandlerCreateSqlOptions,\n\tModificationHandlerOptions,\n} from '../ModificationHandler.js'\nimport { createEventTrigger, createEventTrxTrigger, dropEventTrigger, dropEventTrxTrigger } from '../utils/sqlUpdateUtils.js'\nimport { getColumnSqlType } from '../utils/columnUtils.js'\nimport { wrapIdentifier } from '../../utils/dbHelpers.js'\nimport { VERSION_LATEST } from '../ModificationVersions.js'\nimport { PossibleEntityShapeInMigrations } from '../../utils/PartialEntity.js'\n\n/**\n * Promotes an implicit many-has-many relation (backed by a junction table with a composite primary key)\n * into an explicit joining entity, while preserving all existing rows in the junction table.\n *\n * The junction table is reused in place — no data is copied:\n * - a surrogate `id` (uuid) primary key column is added and back-filled (see {@link uuidGenerator}),\n * - the original composite primary key is dropped and the new `id` becomes the primary key,\n * - both foreign-key columns are kept and become two many-has-one relations of the new entity,\n * - the `log_event` trigger is re-pointed from the two foreign-key columns onto the new `id` column\n * (both event-log triggers are dropped up-front and re-created afterwards).\n *\n * The original many-has-many owning relation (and its inverse side, if any) is removed from the schema.\n *\n * Limitations / requirements:\n * - The junction table is assumed to use the standard composite primary key produced by Contember.\n * - UUID back-filling uses a pure-SQL `uuid_generate_v4()` function in the project's system schema,\n * which the migration creates on the fly if missing (see {@link ensureUuidGenerator}). No\n * PostgreSQL extension is created by this migration.\n */\nexport class ConvertManyHasManyToJoiningEntityModificationHandler implements ModificationHandler<ConvertManyHasManyToJoiningEntityModificationData> {\n\tconstructor(\n\t\tprivate readonly data: ConvertManyHasManyToJoiningEntityModificationData,\n\t\tprivate readonly schema: Schema,\n\t\tprivate readonly options: ModificationHandlerOptions,\n\t) {}\n\n\tpublic createSql(builder: MigrationBuilder, { systemSchema }: ModificationHandlerCreateSqlOptions): void {\n\t\tconst { relation } = this.getRelation()\n\t\tconst joiningTable = relation.joiningTable\n\t\tconst tableName = joiningTable.tableName\n\t\tconst tableNameId = wrapIdentifier(tableName)\n\n\t\tconst joiningEntity = this.data.joiningEntity\n\t\tconst primaryColumn = joiningEntity.fields[joiningEntity.primary] as Model.AnyColumn\n\t\tconst primaryColumnName = primaryColumn.columnName\n\t\tconst primaryColumnNameId = wrapIdentifier(primaryColumnName)\n\t\tconst primaryColumnType = getColumnSqlType(primaryColumn)\n\n\t\t// Drop BOTH event-log triggers before touching the table.\n\t\t// The deferred `log_event_trx` constraint trigger must go too: otherwise the back-fill UPDATE\n\t\t// below queues pending deferred trigger events, and PostgreSQL then rejects the subsequent\n\t\t// `ALTER TABLE` with \"cannot ALTER TABLE because it has pending trigger events\". Both are\n\t\t// re-created at the end, so there is no duplicate-trigger conflict either.\n\t\tif (joiningTable.eventLog.enabled) {\n\t\t\tdropEventTrigger(builder, tableName)\n\t\t\tdropEventTrxTrigger(builder, tableName)\n\t\t}\n\n\t\t// Add the surrogate primary key and back-fill it for existing rows.\n\t\tbuilder.sql(`ALTER TABLE ${tableNameId} ADD COLUMN ${primaryColumnNameId} ${primaryColumnType}`)\n\t\tbuilder.sql(ensureUuidGenerator(systemSchema))\n\t\tbuilder.sql(`UPDATE ${tableNameId} SET ${primaryColumnNameId} = ${uuidGenerator(systemSchema)}`)\n\t\tbuilder.sql(`ALTER TABLE ${tableNameId} ALTER COLUMN ${primaryColumnNameId} SET NOT NULL`)\n\n\t\t// Replace the composite primary key with the surrogate one.\n\t\tbuilder.sql(`ALTER TABLE ${tableNameId} DROP CONSTRAINT ${wrapIdentifier(`${tableName}_pkey`)}`)\n\t\tbuilder.sql(`ALTER TABLE ${tableNameId} ADD PRIMARY KEY (${primaryColumnNameId})`)\n\n\t\t// The original join uniqueness is no longer enforced by the (now surrogate) primary key.\n\t\tbuilder.sql(\n\t\t\t`ALTER TABLE ${tableNameId} ADD UNIQUE (${wrapIdentifier(joiningTable.joiningColumn.columnName)}, ${\n\t\t\t\twrapIdentifier(joiningTable.inverseJoiningColumn.columnName)\n\t\t\t})`,\n\t\t)\n\n\t\t// Re-create both triggers: `log_event` is now re-pointed onto the surrogate primary key,\n\t\t// `log_event_trx` is restored unchanged (it takes no column params).\n\t\tif (joiningEntity.eventLog?.enabled !== false) {\n\t\t\tcreateEventTrigger(builder, systemSchema, tableName, [primaryColumnName])\n\t\t\tcreateEventTrxTrigger(builder, systemSchema, tableName)\n\t\t}\n\t}\n\n\tpublic getSchemaUpdater(): SchemaUpdater {\n\t\tconst { entity, relation } = this.getRelation()\n\t\tconst version = this.options.formatVersion ?? VERSION_LATEST\n\t\tconst joiningEntity = this.data.joiningEntity\n\t\tconst joinUniqueConstraint = this.getJoinUniqueConstraint()\n\n\t\treturn updateSchema(\n\t\t\t// remove the original many-has-many (owning side + inverse side)\n\t\t\tremoveField(entity.name, relation.name, version),\n\t\t\t// register the new joining entity reusing the junction table\n\t\t\tupdateModel(({ model }) => ({\n\t\t\t\t...model,\n\t\t\t\tentities: {\n\t\t\t\t\t...model.entities,\n\t\t\t\t\t[joiningEntity.name]: {\n\t\t\t\t\t\teventLog: { enabled: true },\n\t\t\t\t\t\t...joiningEntity,\n\t\t\t\t\t\t// Keep the schema in sync with the join-uniqueness constraint emitted by createSql.\n\t\t\t\t\t\tunique: [...Object.values(joiningEntity.unique ?? []), joinUniqueConstraint],\n\t\t\t\t\t\tindexes: Object.values(joiningEntity.indexes ?? []),\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t})),\n\t\t\t// add inverse one-has-many relations on both connected entities\n\t\t\tthis.data.sourceInverseSide\n\t\t\t\t? updateModel(updateEntity(entity.name, addField(this.data.sourceInverseSide)))\n\t\t\t\t: undefined,\n\t\t\tthis.data.targetInverseSide\n\t\t\t\t? updateModel(updateEntity(relation.target, addField(this.data.targetInverseSide)))\n\t\t\t\t: undefined,\n\t\t)\n\t}\n\n\tdescribe() {\n\t\treturn {\n\t\t\tmessage: `Converts ManyHasMany relation ${this.data.entityName}.${this.data.fieldName} to a joining entity ${this.data.joiningEntity.name}`,\n\t\t}\n\t}\n\n\t/**\n\t * The join-uniqueness constraint (relationA, relationB) that replaces the dropped composite\n\t * primary key. The field names are resolved from the joining entity's two many-has-one relations\n\t * by matching their joining columns against the original junction columns, so the constraint\n\t * references schema field names (not raw column names).\n\t */\n\tprivate getJoinUniqueConstraint(): Model.UniqueConstraint {\n\t\tconst { relation } = this.getRelation()\n\t\tconst joiningTable = relation.joiningTable\n\t\tconst joiningEntity = this.data.joiningEntity\n\n\t\tconst findRelationField = (columnName: string): string => {\n\t\t\tconst field = Object.values(joiningEntity.fields).find((it): it is Model.AnyRelation & Model.JoiningColumnRelation =>\n\t\t\t\t'joiningColumn' in it && (it as Model.JoiningColumnRelation).joiningColumn.columnName === columnName\n\t\t\t)\n\t\t\tif (!field) {\n\t\t\t\tthrow new Error(\n\t\t\t\t\t`Joining entity ${joiningEntity.name} has no many-has-one relation mapped to column ${columnName}`,\n\t\t\t\t)\n\t\t\t}\n\t\t\treturn field.name\n\t\t}\n\n\t\treturn {\n\t\t\tfields: [\n\t\t\t\tfindRelationField(joiningTable.joiningColumn.columnName),\n\t\t\t\tfindRelationField(joiningTable.inverseJoiningColumn.columnName),\n\t\t\t],\n\t\t}\n\t}\n\n\tprivate getRelation(): { entity: Model.Entity; relation: Model.ManyHasManyOwningRelation } {\n\t\tconst entity = this.schema.model.entities[this.data.entityName]\n\t\tconst relation = entity.fields[this.data.fieldName]\n\t\tif (!relation || relation.type !== Model.RelationType.ManyHasMany || !('joiningTable' in relation)) {\n\t\t\tthrow new Error(`${this.data.entityName}.${this.data.fieldName} is not a many-has-many owning relation`)\n\t\t}\n\t\treturn { entity, relation: relation as Model.ManyHasManyOwningRelation }\n\t}\n}\n\n/**\n * UUIDs are back-filled with a pure-SQL `uuid_generate_v4()` function kept in the project's system\n * schema, so no PostgreSQL extension is ever created. The function cannot be assumed to exist:\n * Contember's system migrations only materialize it on databases where `pg_catalog.gen_random_uuid`\n * is unavailable (i.e. PostgreSQL < 13), so on modern servers `system.uuid_generate_v4()` is absent.\n * {@link ensureUuidGenerator} therefore (idempotently) creates it in the system schema up-front. It\n * must be referenced through the system schema — it is not in `public` nor on the stage search_path.\n */\nconst uuidGenerator = (systemSchema: string) => `${wrapIdentifier(systemSchema)}.\"uuid_generate_v4\"()`\n\n/**\n * Idempotently materialize the pure-SQL `uuid_generate_v4()` function in the system schema. The body\n * matches the one Contember's `trigger-event-function` system migration installs, so the same\n * extension-free UUID generator is reused everywhere. Wrapped in a guard so re-running (or running on\n * a database where it already exists) is a no-op.\n */\nconst ensureUuidGenerator = (systemSchema: string) => {\n\tconst systemSchemaId = wrapIdentifier(systemSchema)\n\treturn `DO $ensure_uuid$\nBEGIN\n\tIF NOT EXISTS(\n\t\tSELECT FROM pg_proc\n\t\tJOIN pg_namespace ON pg_proc.pronamespace = pg_namespace.oid\n\t\tWHERE pg_namespace.nspname = ${quoteLiteral(systemSchema)} AND pg_proc.proname = 'uuid_generate_v4'\n\t) THEN\n\t\tCREATE FUNCTION ${systemSchemaId}.\"uuid_generate_v4\"() RETURNS \"uuid\"\n\t\tLANGUAGE \"sql\"\n\t\tAS $ensure_uuid_body$\n\t\t\tSELECT OVERLAY(OVERLAY(md5(random()::TEXT || ':' || clock_timestamp()::TEXT) PLACING '4' FROM 13) PLACING\n\t\t\t\tto_hex(floor(random() * (11 - 8 + 1) + 8)::INT)::TEXT FROM 17)::UUID;\n\t\t$ensure_uuid_body$;\n\tEND IF;\nEND\n$ensure_uuid$;`\n}\n\nconst quoteLiteral = (value: string) => `'${value.replace(/'/g, \"''\")}'`\n\nexport const convertManyHasManyToJoiningEntityModification = createModificationType({\n\tid: 'convertManyHasManyToJoiningEntity',\n\thandler: ConvertManyHasManyToJoiningEntityModificationHandler,\n})\n\nexport interface ConvertManyHasManyToJoiningEntityModificationData {\n\tentityName: string\n\tfieldName: string\n\tjoiningEntity: PossibleEntityShapeInMigrations\n\tsourceInverseSide?: Model.OneHasManyRelation\n\ttargetInverseSide?: Model.OneHasManyRelation\n}\n"],"names":["schema","wrapIdentifier","getColumnSqlType","dropEventTrigger","dropEventTrxTrigger","createEventTrigger","createEventTrxTrigger","VERSION_LATEST","updateSchema","removeField","updateModel","updateEntity","addField","Model","createModificationType"],"mappings":";;;;;;;;;AAkCO,MAAM,qDAAuI;AAAA,EACnJ,YACkB,MACAA,SACA,SAChB;AAHgB,SAAA,OAAA;AACA,SAAA,SAAAA;AACA,SAAA,UAAA;AAAA,EACf;AAAA,EAEI,UAAU,SAA2B,EAAE,gBAA2D;AACxG,UAAM,EAAE,SAAA,IAAa,KAAK,YAAA;AAC1B,UAAM,eAAe,SAAS;AAC9B,UAAM,YAAY,aAAa;AAC/B,UAAM,cAAcC,UAAAA,eAAe,SAAS;AAE5C,UAAM,gBAAgB,KAAK,KAAK;AAChC,UAAM,gBAAgB,cAAc,OAAO,cAAc,OAAO;AAChE,UAAM,oBAAoB,cAAc;AACxC,UAAM,sBAAsBA,UAAAA,eAAe,iBAAiB;AAC5D,UAAM,oBAAoBC,YAAAA,iBAAiB,aAAa;AAOxD,QAAI,aAAa,SAAS,SAAS;AAClCC,qBAAAA,iBAAiB,SAAS,SAAS;AACnCC,qBAAAA,oBAAoB,SAAS,SAAS;AAAA,IACvC;AAGA,YAAQ,IAAI,eAAe,WAAW,eAAe,mBAAmB,IAAI,iBAAiB,EAAE;AAC/F,YAAQ,IAAI,oBAAoB,YAAY,CAAC;AAC7C,YAAQ,IAAI,UAAU,WAAW,QAAQ,mBAAmB,MAAM,cAAc,YAAY,CAAC,EAAE;AAC/F,YAAQ,IAAI,eAAe,WAAW,iBAAiB,mBAAmB,eAAe;AAGzF,YAAQ,IAAI,eAAe,WAAW,oBAAoBH,yBAAe,GAAG,SAAS,OAAO,CAAC,EAAE;AAC/F,YAAQ,IAAI,eAAe,WAAW,qBAAqB,mBAAmB,GAAG;AAGjF,YAAQ;AAAA,MACP,eAAe,WAAW,gBAAgBA,UAAAA,eAAe,aAAa,cAAc,UAAU,CAAC,KAC9FA,UAAAA,eAAe,aAAa,qBAAqB,UAAU,CAC5D;AAAA,IAAA;AAKD,QAAI,cAAc,UAAU,YAAY,OAAO;AAC9CI,qBAAAA,mBAAmB,SAAS,cAAc,WAAW,CAAC,iBAAiB,CAAC;AACxEC,2CAAsB,SAAS,cAAc,SAAS;AAAA,IACvD;AAAA,EACD;AAAA,EAEO,mBAAkC;AACxC,UAAM,EAAE,QAAQ,aAAa,KAAK,YAAA;AAClC,UAAM,UAAU,KAAK,QAAQ,iBAAiBC,qBAAAA;AAC9C,UAAM,gBAAgB,KAAK,KAAK;AAChC,UAAM,uBAAuB,KAAK,wBAAA;AAElC,WAAOC,kBAAAA;AAAAA;AAAAA,MAENC,kBAAAA,YAAY,OAAO,MAAM,SAAS,MAAM,OAAO;AAAA;AAAA,MAE/CC,8BAAY,CAAC,EAAE,aAAa;AAAA,QAC3B,GAAG;AAAA,QACH,UAAU;AAAA,UACT,GAAG,MAAM;AAAA,UACT,CAAC,cAAc,IAAI,GAAG;AAAA,YACrB,UAAU,EAAE,SAAS,KAAA;AAAA,YACrB,GAAG;AAAA;AAAA,YAEH,QAAQ,CAAC,GAAG,OAAO,OAAO,cAAc,UAAU,CAAA,CAAE,GAAG,oBAAoB;AAAA,YAC3E,SAAS,OAAO,OAAO,cAAc,WAAW,CAAA,CAAE;AAAA,UAAA;AAAA,QACnD;AAAA,MACD,EACC;AAAA;AAAA,MAEF,KAAK,KAAK,oBACPA,kBAAAA,YAAYC,kBAAAA,aAAa,OAAO,MAAMC,kBAAAA,SAAS,KAAK,KAAK,iBAAiB,CAAC,CAAC,IAC5E;AAAA,MACH,KAAK,KAAK,oBACPF,kBAAAA,YAAYC,kBAAAA,aAAa,SAAS,QAAQC,kBAAAA,SAAS,KAAK,KAAK,iBAAiB,CAAC,CAAC,IAChF;AAAA,IAAA;AAAA,EAEL;AAAA,EAEA,WAAW;AACV,WAAO;AAAA,MACN,SAAS,iCAAiC,KAAK,KAAK,UAAU,IAAI,KAAK,KAAK,SAAS,wBAAwB,KAAK,KAAK,cAAc,IAAI;AAAA,IAAA;AAAA,EAE3I;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQQ,0BAAkD;AACzD,UAAM,EAAE,SAAA,IAAa,KAAK,YAAA;AAC1B,UAAM,eAAe,SAAS;AAC9B,UAAM,gBAAgB,KAAK,KAAK;AAEhC,UAAM,oBAAoB,CAAC,eAA+B;AACzD,YAAM,QAAQ,OAAO,OAAO,cAAc,MAAM,EAAE;AAAA,QAAK,CAAC,OACvD,mBAAmB,MAAO,GAAmC,cAAc,eAAe;AAAA,MAAA;AAE3F,UAAI,CAAC,OAAO;AACX,cAAM,IAAI;AAAA,UACT,kBAAkB,cAAc,IAAI,kDAAkD,UAAU;AAAA,QAAA;AAAA,MAElG;AACA,aAAO,MAAM;AAAA,IACd;AAEA,WAAO;AAAA,MACN,QAAQ;AAAA,QACP,kBAAkB,aAAa,cAAc,UAAU;AAAA,QACvD,kBAAkB,aAAa,qBAAqB,UAAU;AAAA,MAAA;AAAA,IAC/D;AAAA,EAEF;AAAA,EAEQ,cAAmF;AAC1F,UAAM,SAAS,KAAK,OAAO,MAAM,SAAS,KAAK,KAAK,UAAU;AAC9D,UAAM,WAAW,OAAO,OAAO,KAAK,KAAK,SAAS;AAClD,QAAI,CAAC,YAAY,SAAS,SAASC,OAAAA,MAAM,aAAa,eAAe,EAAE,kBAAkB,WAAW;AACnG,YAAM,IAAI,MAAM,GAAG,KAAK,KAAK,UAAU,IAAI,KAAK,KAAK,SAAS,yCAAyC;AAAA,IACxG;AACA,WAAO,EAAE,QAAQ,SAAA;AAAA,EAClB;AACD;AAUA,MAAM,gBAAgB,CAAC,iBAAyB,GAAGZ,UAAAA,eAAe,YAAY,CAAC;AAQ/E,MAAM,sBAAsB,CAAC,iBAAyB;AACrD,QAAM,iBAAiBA,UAAAA,eAAe,YAAY;AAClD,SAAO;AAAA;AAAA;AAAA;AAAA;AAAA,iCAKyB,aAAa,YAAY,CAAC;AAAA;AAAA,oBAEvC,cAAc;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AASlC;AAEA,MAAM,eAAe,CAAC,UAAkB,IAAI,MAAM,QAAQ,MAAM,IAAI,CAAC;AAE9D,MAAM,gDAAgDa,oBAAAA,uBAAuB;AAAA,EACnF,IAAI;AAAA,EACJ,SAAS;AACV,CAAC;;;"}
|
package/dist/production/src/modifications/relations/ConvertManyHasManyToJoiningEntityModification.js
ADDED
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
import { Model } from "@contember/schema";
|
|
2
|
+
import { updateSchema, updateModel, updateEntity, addField, removeField } from "../utils/schemaUpdateUtils.js";
|
|
3
|
+
import { createModificationType } from "../ModificationHandler.js";
|
|
4
|
+
import { dropEventTrigger, dropEventTrxTrigger, createEventTrigger, createEventTrxTrigger } from "../utils/sqlUpdateUtils.js";
|
|
5
|
+
import { getColumnSqlType } from "../utils/columnUtils.js";
|
|
6
|
+
import { wrapIdentifier } from "../../utils/dbHelpers.js";
|
|
7
|
+
import { VERSION_LATEST } from "../ModificationVersions.js";
|
|
8
|
+
class ConvertManyHasManyToJoiningEntityModificationHandler {
|
|
9
|
+
constructor(data, schema, options) {
|
|
10
|
+
this.data = data;
|
|
11
|
+
this.schema = schema;
|
|
12
|
+
this.options = options;
|
|
13
|
+
}
|
|
14
|
+
createSql(builder, { systemSchema }) {
|
|
15
|
+
const { relation } = this.getRelation();
|
|
16
|
+
const joiningTable = relation.joiningTable;
|
|
17
|
+
const tableName = joiningTable.tableName;
|
|
18
|
+
const tableNameId = wrapIdentifier(tableName);
|
|
19
|
+
const joiningEntity = this.data.joiningEntity;
|
|
20
|
+
const primaryColumn = joiningEntity.fields[joiningEntity.primary];
|
|
21
|
+
const primaryColumnName = primaryColumn.columnName;
|
|
22
|
+
const primaryColumnNameId = wrapIdentifier(primaryColumnName);
|
|
23
|
+
const primaryColumnType = getColumnSqlType(primaryColumn);
|
|
24
|
+
if (joiningTable.eventLog.enabled) {
|
|
25
|
+
dropEventTrigger(builder, tableName);
|
|
26
|
+
dropEventTrxTrigger(builder, tableName);
|
|
27
|
+
}
|
|
28
|
+
builder.sql(`ALTER TABLE ${tableNameId} ADD COLUMN ${primaryColumnNameId} ${primaryColumnType}`);
|
|
29
|
+
builder.sql(ensureUuidGenerator(systemSchema));
|
|
30
|
+
builder.sql(`UPDATE ${tableNameId} SET ${primaryColumnNameId} = ${uuidGenerator(systemSchema)}`);
|
|
31
|
+
builder.sql(`ALTER TABLE ${tableNameId} ALTER COLUMN ${primaryColumnNameId} SET NOT NULL`);
|
|
32
|
+
builder.sql(`ALTER TABLE ${tableNameId} DROP CONSTRAINT ${wrapIdentifier(`${tableName}_pkey`)}`);
|
|
33
|
+
builder.sql(`ALTER TABLE ${tableNameId} ADD PRIMARY KEY (${primaryColumnNameId})`);
|
|
34
|
+
builder.sql(
|
|
35
|
+
`ALTER TABLE ${tableNameId} ADD UNIQUE (${wrapIdentifier(joiningTable.joiningColumn.columnName)}, ${wrapIdentifier(joiningTable.inverseJoiningColumn.columnName)})`
|
|
36
|
+
);
|
|
37
|
+
if (joiningEntity.eventLog?.enabled !== false) {
|
|
38
|
+
createEventTrigger(builder, systemSchema, tableName, [primaryColumnName]);
|
|
39
|
+
createEventTrxTrigger(builder, systemSchema, tableName);
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
getSchemaUpdater() {
|
|
43
|
+
const { entity, relation } = this.getRelation();
|
|
44
|
+
const version = this.options.formatVersion ?? VERSION_LATEST;
|
|
45
|
+
const joiningEntity = this.data.joiningEntity;
|
|
46
|
+
const joinUniqueConstraint = this.getJoinUniqueConstraint();
|
|
47
|
+
return updateSchema(
|
|
48
|
+
// remove the original many-has-many (owning side + inverse side)
|
|
49
|
+
removeField(entity.name, relation.name, version),
|
|
50
|
+
// register the new joining entity reusing the junction table
|
|
51
|
+
updateModel(({ model }) => ({
|
|
52
|
+
...model,
|
|
53
|
+
entities: {
|
|
54
|
+
...model.entities,
|
|
55
|
+
[joiningEntity.name]: {
|
|
56
|
+
eventLog: { enabled: true },
|
|
57
|
+
...joiningEntity,
|
|
58
|
+
// Keep the schema in sync with the join-uniqueness constraint emitted by createSql.
|
|
59
|
+
unique: [...Object.values(joiningEntity.unique ?? []), joinUniqueConstraint],
|
|
60
|
+
indexes: Object.values(joiningEntity.indexes ?? [])
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
})),
|
|
64
|
+
// add inverse one-has-many relations on both connected entities
|
|
65
|
+
this.data.sourceInverseSide ? updateModel(updateEntity(entity.name, addField(this.data.sourceInverseSide))) : void 0,
|
|
66
|
+
this.data.targetInverseSide ? updateModel(updateEntity(relation.target, addField(this.data.targetInverseSide))) : void 0
|
|
67
|
+
);
|
|
68
|
+
}
|
|
69
|
+
describe() {
|
|
70
|
+
return {
|
|
71
|
+
message: `Converts ManyHasMany relation ${this.data.entityName}.${this.data.fieldName} to a joining entity ${this.data.joiningEntity.name}`
|
|
72
|
+
};
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* The join-uniqueness constraint (relationA, relationB) that replaces the dropped composite
|
|
76
|
+
* primary key. The field names are resolved from the joining entity's two many-has-one relations
|
|
77
|
+
* by matching their joining columns against the original junction columns, so the constraint
|
|
78
|
+
* references schema field names (not raw column names).
|
|
79
|
+
*/
|
|
80
|
+
getJoinUniqueConstraint() {
|
|
81
|
+
const { relation } = this.getRelation();
|
|
82
|
+
const joiningTable = relation.joiningTable;
|
|
83
|
+
const joiningEntity = this.data.joiningEntity;
|
|
84
|
+
const findRelationField = (columnName) => {
|
|
85
|
+
const field = Object.values(joiningEntity.fields).find(
|
|
86
|
+
(it) => "joiningColumn" in it && it.joiningColumn.columnName === columnName
|
|
87
|
+
);
|
|
88
|
+
if (!field) {
|
|
89
|
+
throw new Error(
|
|
90
|
+
`Joining entity ${joiningEntity.name} has no many-has-one relation mapped to column ${columnName}`
|
|
91
|
+
);
|
|
92
|
+
}
|
|
93
|
+
return field.name;
|
|
94
|
+
};
|
|
95
|
+
return {
|
|
96
|
+
fields: [
|
|
97
|
+
findRelationField(joiningTable.joiningColumn.columnName),
|
|
98
|
+
findRelationField(joiningTable.inverseJoiningColumn.columnName)
|
|
99
|
+
]
|
|
100
|
+
};
|
|
101
|
+
}
|
|
102
|
+
getRelation() {
|
|
103
|
+
const entity = this.schema.model.entities[this.data.entityName];
|
|
104
|
+
const relation = entity.fields[this.data.fieldName];
|
|
105
|
+
if (!relation || relation.type !== Model.RelationType.ManyHasMany || !("joiningTable" in relation)) {
|
|
106
|
+
throw new Error(`${this.data.entityName}.${this.data.fieldName} is not a many-has-many owning relation`);
|
|
107
|
+
}
|
|
108
|
+
return { entity, relation };
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
const uuidGenerator = (systemSchema) => `${wrapIdentifier(systemSchema)}."uuid_generate_v4"()`;
|
|
112
|
+
const ensureUuidGenerator = (systemSchema) => {
|
|
113
|
+
const systemSchemaId = wrapIdentifier(systemSchema);
|
|
114
|
+
return `DO $ensure_uuid$
|
|
115
|
+
BEGIN
|
|
116
|
+
IF NOT EXISTS(
|
|
117
|
+
SELECT FROM pg_proc
|
|
118
|
+
JOIN pg_namespace ON pg_proc.pronamespace = pg_namespace.oid
|
|
119
|
+
WHERE pg_namespace.nspname = ${quoteLiteral(systemSchema)} AND pg_proc.proname = 'uuid_generate_v4'
|
|
120
|
+
) THEN
|
|
121
|
+
CREATE FUNCTION ${systemSchemaId}."uuid_generate_v4"() RETURNS "uuid"
|
|
122
|
+
LANGUAGE "sql"
|
|
123
|
+
AS $ensure_uuid_body$
|
|
124
|
+
SELECT OVERLAY(OVERLAY(md5(random()::TEXT || ':' || clock_timestamp()::TEXT) PLACING '4' FROM 13) PLACING
|
|
125
|
+
to_hex(floor(random() * (11 - 8 + 1) + 8)::INT)::TEXT FROM 17)::UUID;
|
|
126
|
+
$ensure_uuid_body$;
|
|
127
|
+
END IF;
|
|
128
|
+
END
|
|
129
|
+
$ensure_uuid$;`;
|
|
130
|
+
};
|
|
131
|
+
const quoteLiteral = (value) => `'${value.replace(/'/g, "''")}'`;
|
|
132
|
+
const convertManyHasManyToJoiningEntityModification = createModificationType({
|
|
133
|
+
id: "convertManyHasManyToJoiningEntity",
|
|
134
|
+
handler: ConvertManyHasManyToJoiningEntityModificationHandler
|
|
135
|
+
});
|
|
136
|
+
export {
|
|
137
|
+
ConvertManyHasManyToJoiningEntityModificationHandler,
|
|
138
|
+
convertManyHasManyToJoiningEntityModification
|
|
139
|
+
};
|
|
140
|
+
//# sourceMappingURL=ConvertManyHasManyToJoiningEntityModification.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ConvertManyHasManyToJoiningEntityModification.js","sources":["../../../../../../packages/schema-migrations/src/modifications/relations/ConvertManyHasManyToJoiningEntityModification.ts"],"sourcesContent":["import { MigrationBuilder } from '@contember/database-migrations'\nimport { Model, Schema } from '@contember/schema'\nimport { addField, removeField, SchemaUpdater, updateEntity, updateModel, updateSchema } from '../utils/schemaUpdateUtils.js'\nimport {\n\tcreateModificationType,\n\tModificationHandler,\n\tModificationHandlerCreateSqlOptions,\n\tModificationHandlerOptions,\n} from '../ModificationHandler.js'\nimport { createEventTrigger, createEventTrxTrigger, dropEventTrigger, dropEventTrxTrigger } from '../utils/sqlUpdateUtils.js'\nimport { getColumnSqlType } from '../utils/columnUtils.js'\nimport { wrapIdentifier } from '../../utils/dbHelpers.js'\nimport { VERSION_LATEST } from '../ModificationVersions.js'\nimport { PossibleEntityShapeInMigrations } from '../../utils/PartialEntity.js'\n\n/**\n * Promotes an implicit many-has-many relation (backed by a junction table with a composite primary key)\n * into an explicit joining entity, while preserving all existing rows in the junction table.\n *\n * The junction table is reused in place — no data is copied:\n * - a surrogate `id` (uuid) primary key column is added and back-filled (see {@link uuidGenerator}),\n * - the original composite primary key is dropped and the new `id` becomes the primary key,\n * - both foreign-key columns are kept and become two many-has-one relations of the new entity,\n * - the `log_event` trigger is re-pointed from the two foreign-key columns onto the new `id` column\n * (both event-log triggers are dropped up-front and re-created afterwards).\n *\n * The original many-has-many owning relation (and its inverse side, if any) is removed from the schema.\n *\n * Limitations / requirements:\n * - The junction table is assumed to use the standard composite primary key produced by Contember.\n * - UUID back-filling uses a pure-SQL `uuid_generate_v4()` function in the project's system schema,\n * which the migration creates on the fly if missing (see {@link ensureUuidGenerator}). No\n * PostgreSQL extension is created by this migration.\n */\nexport class ConvertManyHasManyToJoiningEntityModificationHandler implements ModificationHandler<ConvertManyHasManyToJoiningEntityModificationData> {\n\tconstructor(\n\t\tprivate readonly data: ConvertManyHasManyToJoiningEntityModificationData,\n\t\tprivate readonly schema: Schema,\n\t\tprivate readonly options: ModificationHandlerOptions,\n\t) {}\n\n\tpublic createSql(builder: MigrationBuilder, { systemSchema }: ModificationHandlerCreateSqlOptions): void {\n\t\tconst { relation } = this.getRelation()\n\t\tconst joiningTable = relation.joiningTable\n\t\tconst tableName = joiningTable.tableName\n\t\tconst tableNameId = wrapIdentifier(tableName)\n\n\t\tconst joiningEntity = this.data.joiningEntity\n\t\tconst primaryColumn = joiningEntity.fields[joiningEntity.primary] as Model.AnyColumn\n\t\tconst primaryColumnName = primaryColumn.columnName\n\t\tconst primaryColumnNameId = wrapIdentifier(primaryColumnName)\n\t\tconst primaryColumnType = getColumnSqlType(primaryColumn)\n\n\t\t// Drop BOTH event-log triggers before touching the table.\n\t\t// The deferred `log_event_trx` constraint trigger must go too: otherwise the back-fill UPDATE\n\t\t// below queues pending deferred trigger events, and PostgreSQL then rejects the subsequent\n\t\t// `ALTER TABLE` with \"cannot ALTER TABLE because it has pending trigger events\". Both are\n\t\t// re-created at the end, so there is no duplicate-trigger conflict either.\n\t\tif (joiningTable.eventLog.enabled) {\n\t\t\tdropEventTrigger(builder, tableName)\n\t\t\tdropEventTrxTrigger(builder, tableName)\n\t\t}\n\n\t\t// Add the surrogate primary key and back-fill it for existing rows.\n\t\tbuilder.sql(`ALTER TABLE ${tableNameId} ADD COLUMN ${primaryColumnNameId} ${primaryColumnType}`)\n\t\tbuilder.sql(ensureUuidGenerator(systemSchema))\n\t\tbuilder.sql(`UPDATE ${tableNameId} SET ${primaryColumnNameId} = ${uuidGenerator(systemSchema)}`)\n\t\tbuilder.sql(`ALTER TABLE ${tableNameId} ALTER COLUMN ${primaryColumnNameId} SET NOT NULL`)\n\n\t\t// Replace the composite primary key with the surrogate one.\n\t\tbuilder.sql(`ALTER TABLE ${tableNameId} DROP CONSTRAINT ${wrapIdentifier(`${tableName}_pkey`)}`)\n\t\tbuilder.sql(`ALTER TABLE ${tableNameId} ADD PRIMARY KEY (${primaryColumnNameId})`)\n\n\t\t// The original join uniqueness is no longer enforced by the (now surrogate) primary key.\n\t\tbuilder.sql(\n\t\t\t`ALTER TABLE ${tableNameId} ADD UNIQUE (${wrapIdentifier(joiningTable.joiningColumn.columnName)}, ${\n\t\t\t\twrapIdentifier(joiningTable.inverseJoiningColumn.columnName)\n\t\t\t})`,\n\t\t)\n\n\t\t// Re-create both triggers: `log_event` is now re-pointed onto the surrogate primary key,\n\t\t// `log_event_trx` is restored unchanged (it takes no column params).\n\t\tif (joiningEntity.eventLog?.enabled !== false) {\n\t\t\tcreateEventTrigger(builder, systemSchema, tableName, [primaryColumnName])\n\t\t\tcreateEventTrxTrigger(builder, systemSchema, tableName)\n\t\t}\n\t}\n\n\tpublic getSchemaUpdater(): SchemaUpdater {\n\t\tconst { entity, relation } = this.getRelation()\n\t\tconst version = this.options.formatVersion ?? VERSION_LATEST\n\t\tconst joiningEntity = this.data.joiningEntity\n\t\tconst joinUniqueConstraint = this.getJoinUniqueConstraint()\n\n\t\treturn updateSchema(\n\t\t\t// remove the original many-has-many (owning side + inverse side)\n\t\t\tremoveField(entity.name, relation.name, version),\n\t\t\t// register the new joining entity reusing the junction table\n\t\t\tupdateModel(({ model }) => ({\n\t\t\t\t...model,\n\t\t\t\tentities: {\n\t\t\t\t\t...model.entities,\n\t\t\t\t\t[joiningEntity.name]: {\n\t\t\t\t\t\teventLog: { enabled: true },\n\t\t\t\t\t\t...joiningEntity,\n\t\t\t\t\t\t// Keep the schema in sync with the join-uniqueness constraint emitted by createSql.\n\t\t\t\t\t\tunique: [...Object.values(joiningEntity.unique ?? []), joinUniqueConstraint],\n\t\t\t\t\t\tindexes: Object.values(joiningEntity.indexes ?? []),\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t})),\n\t\t\t// add inverse one-has-many relations on both connected entities\n\t\t\tthis.data.sourceInverseSide\n\t\t\t\t? updateModel(updateEntity(entity.name, addField(this.data.sourceInverseSide)))\n\t\t\t\t: undefined,\n\t\t\tthis.data.targetInverseSide\n\t\t\t\t? updateModel(updateEntity(relation.target, addField(this.data.targetInverseSide)))\n\t\t\t\t: undefined,\n\t\t)\n\t}\n\n\tdescribe() {\n\t\treturn {\n\t\t\tmessage: `Converts ManyHasMany relation ${this.data.entityName}.${this.data.fieldName} to a joining entity ${this.data.joiningEntity.name}`,\n\t\t}\n\t}\n\n\t/**\n\t * The join-uniqueness constraint (relationA, relationB) that replaces the dropped composite\n\t * primary key. The field names are resolved from the joining entity's two many-has-one relations\n\t * by matching their joining columns against the original junction columns, so the constraint\n\t * references schema field names (not raw column names).\n\t */\n\tprivate getJoinUniqueConstraint(): Model.UniqueConstraint {\n\t\tconst { relation } = this.getRelation()\n\t\tconst joiningTable = relation.joiningTable\n\t\tconst joiningEntity = this.data.joiningEntity\n\n\t\tconst findRelationField = (columnName: string): string => {\n\t\t\tconst field = Object.values(joiningEntity.fields).find((it): it is Model.AnyRelation & Model.JoiningColumnRelation =>\n\t\t\t\t'joiningColumn' in it && (it as Model.JoiningColumnRelation).joiningColumn.columnName === columnName\n\t\t\t)\n\t\t\tif (!field) {\n\t\t\t\tthrow new Error(\n\t\t\t\t\t`Joining entity ${joiningEntity.name} has no many-has-one relation mapped to column ${columnName}`,\n\t\t\t\t)\n\t\t\t}\n\t\t\treturn field.name\n\t\t}\n\n\t\treturn {\n\t\t\tfields: [\n\t\t\t\tfindRelationField(joiningTable.joiningColumn.columnName),\n\t\t\t\tfindRelationField(joiningTable.inverseJoiningColumn.columnName),\n\t\t\t],\n\t\t}\n\t}\n\n\tprivate getRelation(): { entity: Model.Entity; relation: Model.ManyHasManyOwningRelation } {\n\t\tconst entity = this.schema.model.entities[this.data.entityName]\n\t\tconst relation = entity.fields[this.data.fieldName]\n\t\tif (!relation || relation.type !== Model.RelationType.ManyHasMany || !('joiningTable' in relation)) {\n\t\t\tthrow new Error(`${this.data.entityName}.${this.data.fieldName} is not a many-has-many owning relation`)\n\t\t}\n\t\treturn { entity, relation: relation as Model.ManyHasManyOwningRelation }\n\t}\n}\n\n/**\n * UUIDs are back-filled with a pure-SQL `uuid_generate_v4()` function kept in the project's system\n * schema, so no PostgreSQL extension is ever created. The function cannot be assumed to exist:\n * Contember's system migrations only materialize it on databases where `pg_catalog.gen_random_uuid`\n * is unavailable (i.e. PostgreSQL < 13), so on modern servers `system.uuid_generate_v4()` is absent.\n * {@link ensureUuidGenerator} therefore (idempotently) creates it in the system schema up-front. It\n * must be referenced through the system schema — it is not in `public` nor on the stage search_path.\n */\nconst uuidGenerator = (systemSchema: string) => `${wrapIdentifier(systemSchema)}.\"uuid_generate_v4\"()`\n\n/**\n * Idempotently materialize the pure-SQL `uuid_generate_v4()` function in the system schema. The body\n * matches the one Contember's `trigger-event-function` system migration installs, so the same\n * extension-free UUID generator is reused everywhere. Wrapped in a guard so re-running (or running on\n * a database where it already exists) is a no-op.\n */\nconst ensureUuidGenerator = (systemSchema: string) => {\n\tconst systemSchemaId = wrapIdentifier(systemSchema)\n\treturn `DO $ensure_uuid$\nBEGIN\n\tIF NOT EXISTS(\n\t\tSELECT FROM pg_proc\n\t\tJOIN pg_namespace ON pg_proc.pronamespace = pg_namespace.oid\n\t\tWHERE pg_namespace.nspname = ${quoteLiteral(systemSchema)} AND pg_proc.proname = 'uuid_generate_v4'\n\t) THEN\n\t\tCREATE FUNCTION ${systemSchemaId}.\"uuid_generate_v4\"() RETURNS \"uuid\"\n\t\tLANGUAGE \"sql\"\n\t\tAS $ensure_uuid_body$\n\t\t\tSELECT OVERLAY(OVERLAY(md5(random()::TEXT || ':' || clock_timestamp()::TEXT) PLACING '4' FROM 13) PLACING\n\t\t\t\tto_hex(floor(random() * (11 - 8 + 1) + 8)::INT)::TEXT FROM 17)::UUID;\n\t\t$ensure_uuid_body$;\n\tEND IF;\nEND\n$ensure_uuid$;`\n}\n\nconst quoteLiteral = (value: string) => `'${value.replace(/'/g, \"''\")}'`\n\nexport const convertManyHasManyToJoiningEntityModification = createModificationType({\n\tid: 'convertManyHasManyToJoiningEntity',\n\thandler: ConvertManyHasManyToJoiningEntityModificationHandler,\n})\n\nexport interface ConvertManyHasManyToJoiningEntityModificationData {\n\tentityName: string\n\tfieldName: string\n\tjoiningEntity: PossibleEntityShapeInMigrations\n\tsourceInverseSide?: Model.OneHasManyRelation\n\ttargetInverseSide?: Model.OneHasManyRelation\n}\n"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ConvertOneHasManyToManyHasManyRelationModification.cjs","sources":["../../../../../../packages/schema-migrations/src/modifications/relations/ConvertOneHasManyToManyHasManyRelationModification.ts"],"sourcesContent":["import { MigrationBuilder } from '@contember/database-migrations'\nimport { Model, Schema } from '@contember/schema'\nimport { addField, SchemaUpdater, updateEntity, updateModel, updateSchema } from '../utils/schemaUpdateUtils'\nimport {\n\tcreateModificationType,\n\tDiffer,\n\tModificationHandler,\n\tModificationHandlerCreateSqlOptions,\n\tModificationHandlerOptions,\n} from '../ModificationHandler'\nimport { isInverseRelation, isOwningRelation } from '@contember/schema-utils'\nimport { updateRelations } from '../utils/diffUtils'\nimport { createJunctionTableSql } from '../utils/createJunctionTable'\nimport { wrapIdentifier } from '../../utils/dbHelpers'\nimport { normalizeManyHasManyRelation, PartialManyHasManyRelation } from './normalization'\nimport { updateFieldNameModification } from '../fields'\n\nexport class ConvertOneHasManyToManyHasManyRelationModificationHandler\n\timplements ModificationHandler<ConvertOneHasManyToManyHasManyRelationModificationData>\n{\n\tprivate subModification: ModificationHandler<any>\n\n\tconstructor(\n\t\tprivate readonly data: ConvertOneHasManyToManyHasManyRelationModificationData,\n\t\tprivate readonly schema: Schema,\n\t\tprivate readonly options: ModificationHandlerOptions,\n\t) {\n\t\tthis.subModification = updateFieldNameModification.createHandler(\n\t\t\t{\n\t\t\t\tentityName: this.data.entityName,\n\t\t\t\tfieldName: this.data.fieldName,\n\t\t\t\tnewFieldName: this.data.owningSide.name,\n\t\t\t},\n\t\t\tschema,\n\t\t\tthis.options,\n\t\t)\n\t}\n\n\tpublic createSql(builder: MigrationBuilder, { systemSchema }: ModificationHandlerCreateSqlOptions): void {\n\t\tconst targetEntity = this.schema.model.entities[this.data.owningSide.target]\n\t\tconst { relation: oldRelation } = this.getRelation()\n\t\tconst entity = this.schema.model.entities[this.data.entityName]\n\n\t\tcreateJunctionTableSql(builder, systemSchema, this.schema, entity, targetEntity, normalizeManyHasManyRelation(this.data.owningSide))\n\t\tconst joiningTable = this.data.owningSide.joiningTable\n\t\tbuilder.sql(`\n\t\t\tINSERT INTO ${wrapIdentifier(joiningTable.tableName)} (\n\t\t\t\t${wrapIdentifier(joiningTable.joiningColumn.columnName)},\n\t\t\t\t${wrapIdentifier(joiningTable.inverseJoiningColumn.columnName)}\n\t\t\t\t)\n\t\t\tSELECT ${wrapIdentifier(entity.primaryColumn)}, ${wrapIdentifier(oldRelation.joiningColumn.columnName)}\n\t\t\tFROM ${wrapIdentifier(entity.tableName)}\n\t\t\tWHERE ${wrapIdentifier(oldRelation.joiningColumn.columnName)} IS NOT NULL`)\n\n\t\tbuilder.dropColumn(entity.tableName, oldRelation.joiningColumn.columnName)\n\t}\n\n\tpublic getSchemaUpdater(): SchemaUpdater {\n\t\tconst { entityName } = this.data\n\t\treturn updateSchema(\n\t\t\tthis.subModification.getSchemaUpdater(),\n\t\t\tupdateModel(updateEntity(entityName, addField(normalizeManyHasManyRelation(this.data.owningSide)))),\n\t\t\tthis.data.inverseSide ? updateModel(updateEntity(this.data.owningSide.target, addField(this.data.inverseSide))) : undefined,\n\t\t)\n\t}\n\n\tdescribe() {\n\t\treturn {\n\t\t\tmessage: `Converts OneHasMany relation to ManyHasMany on ${this.data.entityName}.${this.data.fieldName}`,\n\t\t}\n\t}\n\n\tprivate getRelation(): { entity: Model.Entity; relation: Model.ManyHasOneRelation } {\n\t\tconst entity = this.schema.model.entities[this.data.entityName]\n\t\tconst relation = entity.fields[this.data.fieldName]\n\t\tif (relation.type !== Model.RelationType.ManyHasOne) {\n\t\t\tthrow new Error()\n\t\t}\n\t\treturn { entity, relation }\n\t}\n}\n\nexport const convertOneHasManyToManyHasManyRelationModification = createModificationType({\n\tid: 'convertOneHasManyToManyHasManyRelation',\n\thandler: ConvertOneHasManyToManyHasManyRelationModificationHandler,\n})\n\nexport interface ConvertOneHasManyToManyHasManyRelationModificationData {\n\tentityName: string\n\tfieldName: string\n\towningSide: PartialManyHasManyRelation\n\tinverseSide?: Model.ManyHasManyInverseRelation\n}\n\nexport class ConvertOneHasManyToManyHasManyRelationDiffer implements Differ {\n\tcreateDiff(originalSchema: Schema, updatedSchema: Schema) {\n\t\treturn updateRelations(originalSchema, updatedSchema, ({ originalRelation, updatedRelation, updatedEntity }) => {\n\t\t\tif (\n\t\t\t\tisInverseRelation(originalRelation)\n\t\t\t\t&& isInverseRelation(updatedRelation)\n\t\t\t\t&& originalRelation.type === Model.RelationType.OneHasMany\n\t\t\t\t&& updatedRelation.type === Model.RelationType.ManyHasMany\n\t\t\t) {\n\t\t\t\tconst owningOldName = originalRelation.ownedBy\n\t\t\t\tconst owningNewName = updatedRelation.ownedBy\n\t\t\t\tconst owningSide = updatedSchema.model.entities[updatedRelation.target].fields[owningNewName]\n\t\t\t\tif (owningSide.type !== Model.RelationType.ManyHasMany || !isOwningRelation(owningSide)) {\n\t\t\t\t\tthrow new Error()\n\t\t\t\t}\n\t\t\t\treturn convertOneHasManyToManyHasManyRelationModification.createModification({\n\t\t\t\t\tentityName: updatedRelation.target,\n\t\t\t\t\tfieldName: owningOldName,\n\t\t\t\t\towningSide,\n\t\t\t\t\tinverseSide: updatedRelation,\n\t\t\t\t})\n\t\t\t}\n\t\t\treturn undefined\n\t\t})\n\t}\n}\n"],"names":["schema","updateFieldNameModification","createJunctionTableSql","normalizeManyHasManyRelation","wrapIdentifier","updateSchema","updateModel","updateEntity","addField","Model","createModificationType","updateRelations","isInverseRelation","isOwningRelation"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"ConvertOneHasManyToManyHasManyRelationModification.cjs","sources":["../../../../../../packages/schema-migrations/src/modifications/relations/ConvertOneHasManyToManyHasManyRelationModification.ts"],"sourcesContent":["import { MigrationBuilder } from '@contember/database-migrations'\nimport { Model, Schema } from '@contember/schema'\nimport { addField, SchemaUpdater, updateEntity, updateModel, updateSchema } from '../utils/schemaUpdateUtils.js'\nimport {\n\tcreateModificationType,\n\tDiffer,\n\tModificationHandler,\n\tModificationHandlerCreateSqlOptions,\n\tModificationHandlerOptions,\n} from '../ModificationHandler.js'\nimport { isInverseRelation, isOwningRelation } from '@contember/schema-utils'\nimport { updateRelations } from '../utils/diffUtils.js'\nimport { createJunctionTableSql } from '../utils/createJunctionTable.js'\nimport { wrapIdentifier } from '../../utils/dbHelpers.js'\nimport { normalizeManyHasManyRelation, PartialManyHasManyRelation } from './normalization.js'\nimport { updateFieldNameModification } from '../fields/index.js'\n\nexport class ConvertOneHasManyToManyHasManyRelationModificationHandler\n\timplements ModificationHandler<ConvertOneHasManyToManyHasManyRelationModificationData>\n{\n\tprivate subModification: ModificationHandler<any>\n\n\tconstructor(\n\t\tprivate readonly data: ConvertOneHasManyToManyHasManyRelationModificationData,\n\t\tprivate readonly schema: Schema,\n\t\tprivate readonly options: ModificationHandlerOptions,\n\t) {\n\t\tthis.subModification = updateFieldNameModification.createHandler(\n\t\t\t{\n\t\t\t\tentityName: this.data.entityName,\n\t\t\t\tfieldName: this.data.fieldName,\n\t\t\t\tnewFieldName: this.data.owningSide.name,\n\t\t\t},\n\t\t\tschema,\n\t\t\tthis.options,\n\t\t)\n\t}\n\n\tpublic createSql(builder: MigrationBuilder, { systemSchema }: ModificationHandlerCreateSqlOptions): void {\n\t\tconst targetEntity = this.schema.model.entities[this.data.owningSide.target]\n\t\tconst { relation: oldRelation } = this.getRelation()\n\t\tconst entity = this.schema.model.entities[this.data.entityName]\n\n\t\tcreateJunctionTableSql(builder, systemSchema, this.schema, entity, targetEntity, normalizeManyHasManyRelation(this.data.owningSide))\n\t\tconst joiningTable = this.data.owningSide.joiningTable\n\t\tbuilder.sql(`\n\t\t\tINSERT INTO ${wrapIdentifier(joiningTable.tableName)} (\n\t\t\t\t${wrapIdentifier(joiningTable.joiningColumn.columnName)},\n\t\t\t\t${wrapIdentifier(joiningTable.inverseJoiningColumn.columnName)}\n\t\t\t\t)\n\t\t\tSELECT ${wrapIdentifier(entity.primaryColumn)}, ${wrapIdentifier(oldRelation.joiningColumn.columnName)}\n\t\t\tFROM ${wrapIdentifier(entity.tableName)}\n\t\t\tWHERE ${wrapIdentifier(oldRelation.joiningColumn.columnName)} IS NOT NULL`)\n\n\t\tbuilder.dropColumn(entity.tableName, oldRelation.joiningColumn.columnName)\n\t}\n\n\tpublic getSchemaUpdater(): SchemaUpdater {\n\t\tconst { entityName } = this.data\n\t\treturn updateSchema(\n\t\t\tthis.subModification.getSchemaUpdater(),\n\t\t\tupdateModel(updateEntity(entityName, addField(normalizeManyHasManyRelation(this.data.owningSide)))),\n\t\t\tthis.data.inverseSide ? updateModel(updateEntity(this.data.owningSide.target, addField(this.data.inverseSide))) : undefined,\n\t\t)\n\t}\n\n\tdescribe() {\n\t\treturn {\n\t\t\tmessage: `Converts OneHasMany relation to ManyHasMany on ${this.data.entityName}.${this.data.fieldName}`,\n\t\t}\n\t}\n\n\tprivate getRelation(): { entity: Model.Entity; relation: Model.ManyHasOneRelation } {\n\t\tconst entity = this.schema.model.entities[this.data.entityName]\n\t\tconst relation = entity.fields[this.data.fieldName]\n\t\tif (relation.type !== Model.RelationType.ManyHasOne) {\n\t\t\tthrow new Error()\n\t\t}\n\t\treturn { entity, relation }\n\t}\n}\n\nexport const convertOneHasManyToManyHasManyRelationModification = createModificationType({\n\tid: 'convertOneHasManyToManyHasManyRelation',\n\thandler: ConvertOneHasManyToManyHasManyRelationModificationHandler,\n})\n\nexport interface ConvertOneHasManyToManyHasManyRelationModificationData {\n\tentityName: string\n\tfieldName: string\n\towningSide: PartialManyHasManyRelation\n\tinverseSide?: Model.ManyHasManyInverseRelation\n}\n\nexport class ConvertOneHasManyToManyHasManyRelationDiffer implements Differ {\n\tcreateDiff(originalSchema: Schema, updatedSchema: Schema) {\n\t\treturn updateRelations(originalSchema, updatedSchema, ({ originalRelation, updatedRelation, updatedEntity }) => {\n\t\t\tif (\n\t\t\t\tisInverseRelation(originalRelation)\n\t\t\t\t&& isInverseRelation(updatedRelation)\n\t\t\t\t&& originalRelation.type === Model.RelationType.OneHasMany\n\t\t\t\t&& updatedRelation.type === Model.RelationType.ManyHasMany\n\t\t\t) {\n\t\t\t\tconst owningOldName = originalRelation.ownedBy\n\t\t\t\tconst owningNewName = updatedRelation.ownedBy\n\t\t\t\tconst owningSide = updatedSchema.model.entities[updatedRelation.target].fields[owningNewName]\n\t\t\t\tif (owningSide.type !== Model.RelationType.ManyHasMany || !isOwningRelation(owningSide)) {\n\t\t\t\t\tthrow new Error()\n\t\t\t\t}\n\t\t\t\treturn convertOneHasManyToManyHasManyRelationModification.createModification({\n\t\t\t\t\tentityName: updatedRelation.target,\n\t\t\t\t\tfieldName: owningOldName,\n\t\t\t\t\towningSide,\n\t\t\t\t\tinverseSide: updatedRelation,\n\t\t\t\t})\n\t\t\t}\n\t\t\treturn undefined\n\t\t})\n\t}\n}\n"],"names":["schema","updateFieldNameModification","createJunctionTableSql","normalizeManyHasManyRelation","wrapIdentifier","updateSchema","updateModel","updateEntity","addField","Model","createModificationType","updateRelations","isInverseRelation","isOwningRelation"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ConvertOneHasManyToManyHasManyRelationModification.js","sources":["../../../../../../packages/schema-migrations/src/modifications/relations/ConvertOneHasManyToManyHasManyRelationModification.ts"],"sourcesContent":["import { MigrationBuilder } from '@contember/database-migrations'\nimport { Model, Schema } from '@contember/schema'\nimport { addField, SchemaUpdater, updateEntity, updateModel, updateSchema } from '../utils/schemaUpdateUtils'\nimport {\n\tcreateModificationType,\n\tDiffer,\n\tModificationHandler,\n\tModificationHandlerCreateSqlOptions,\n\tModificationHandlerOptions,\n} from '../ModificationHandler'\nimport { isInverseRelation, isOwningRelation } from '@contember/schema-utils'\nimport { updateRelations } from '../utils/diffUtils'\nimport { createJunctionTableSql } from '../utils/createJunctionTable'\nimport { wrapIdentifier } from '../../utils/dbHelpers'\nimport { normalizeManyHasManyRelation, PartialManyHasManyRelation } from './normalization'\nimport { updateFieldNameModification } from '../fields'\n\nexport class ConvertOneHasManyToManyHasManyRelationModificationHandler\n\timplements ModificationHandler<ConvertOneHasManyToManyHasManyRelationModificationData>\n{\n\tprivate subModification: ModificationHandler<any>\n\n\tconstructor(\n\t\tprivate readonly data: ConvertOneHasManyToManyHasManyRelationModificationData,\n\t\tprivate readonly schema: Schema,\n\t\tprivate readonly options: ModificationHandlerOptions,\n\t) {\n\t\tthis.subModification = updateFieldNameModification.createHandler(\n\t\t\t{\n\t\t\t\tentityName: this.data.entityName,\n\t\t\t\tfieldName: this.data.fieldName,\n\t\t\t\tnewFieldName: this.data.owningSide.name,\n\t\t\t},\n\t\t\tschema,\n\t\t\tthis.options,\n\t\t)\n\t}\n\n\tpublic createSql(builder: MigrationBuilder, { systemSchema }: ModificationHandlerCreateSqlOptions): void {\n\t\tconst targetEntity = this.schema.model.entities[this.data.owningSide.target]\n\t\tconst { relation: oldRelation } = this.getRelation()\n\t\tconst entity = this.schema.model.entities[this.data.entityName]\n\n\t\tcreateJunctionTableSql(builder, systemSchema, this.schema, entity, targetEntity, normalizeManyHasManyRelation(this.data.owningSide))\n\t\tconst joiningTable = this.data.owningSide.joiningTable\n\t\tbuilder.sql(`\n\t\t\tINSERT INTO ${wrapIdentifier(joiningTable.tableName)} (\n\t\t\t\t${wrapIdentifier(joiningTable.joiningColumn.columnName)},\n\t\t\t\t${wrapIdentifier(joiningTable.inverseJoiningColumn.columnName)}\n\t\t\t\t)\n\t\t\tSELECT ${wrapIdentifier(entity.primaryColumn)}, ${wrapIdentifier(oldRelation.joiningColumn.columnName)}\n\t\t\tFROM ${wrapIdentifier(entity.tableName)}\n\t\t\tWHERE ${wrapIdentifier(oldRelation.joiningColumn.columnName)} IS NOT NULL`)\n\n\t\tbuilder.dropColumn(entity.tableName, oldRelation.joiningColumn.columnName)\n\t}\n\n\tpublic getSchemaUpdater(): SchemaUpdater {\n\t\tconst { entityName } = this.data\n\t\treturn updateSchema(\n\t\t\tthis.subModification.getSchemaUpdater(),\n\t\t\tupdateModel(updateEntity(entityName, addField(normalizeManyHasManyRelation(this.data.owningSide)))),\n\t\t\tthis.data.inverseSide ? updateModel(updateEntity(this.data.owningSide.target, addField(this.data.inverseSide))) : undefined,\n\t\t)\n\t}\n\n\tdescribe() {\n\t\treturn {\n\t\t\tmessage: `Converts OneHasMany relation to ManyHasMany on ${this.data.entityName}.${this.data.fieldName}`,\n\t\t}\n\t}\n\n\tprivate getRelation(): { entity: Model.Entity; relation: Model.ManyHasOneRelation } {\n\t\tconst entity = this.schema.model.entities[this.data.entityName]\n\t\tconst relation = entity.fields[this.data.fieldName]\n\t\tif (relation.type !== Model.RelationType.ManyHasOne) {\n\t\t\tthrow new Error()\n\t\t}\n\t\treturn { entity, relation }\n\t}\n}\n\nexport const convertOneHasManyToManyHasManyRelationModification = createModificationType({\n\tid: 'convertOneHasManyToManyHasManyRelation',\n\thandler: ConvertOneHasManyToManyHasManyRelationModificationHandler,\n})\n\nexport interface ConvertOneHasManyToManyHasManyRelationModificationData {\n\tentityName: string\n\tfieldName: string\n\towningSide: PartialManyHasManyRelation\n\tinverseSide?: Model.ManyHasManyInverseRelation\n}\n\nexport class ConvertOneHasManyToManyHasManyRelationDiffer implements Differ {\n\tcreateDiff(originalSchema: Schema, updatedSchema: Schema) {\n\t\treturn updateRelations(originalSchema, updatedSchema, ({ originalRelation, updatedRelation, updatedEntity }) => {\n\t\t\tif (\n\t\t\t\tisInverseRelation(originalRelation)\n\t\t\t\t&& isInverseRelation(updatedRelation)\n\t\t\t\t&& originalRelation.type === Model.RelationType.OneHasMany\n\t\t\t\t&& updatedRelation.type === Model.RelationType.ManyHasMany\n\t\t\t) {\n\t\t\t\tconst owningOldName = originalRelation.ownedBy\n\t\t\t\tconst owningNewName = updatedRelation.ownedBy\n\t\t\t\tconst owningSide = updatedSchema.model.entities[updatedRelation.target].fields[owningNewName]\n\t\t\t\tif (owningSide.type !== Model.RelationType.ManyHasMany || !isOwningRelation(owningSide)) {\n\t\t\t\t\tthrow new Error()\n\t\t\t\t}\n\t\t\t\treturn convertOneHasManyToManyHasManyRelationModification.createModification({\n\t\t\t\t\tentityName: updatedRelation.target,\n\t\t\t\t\tfieldName: owningOldName,\n\t\t\t\t\towningSide,\n\t\t\t\t\tinverseSide: updatedRelation,\n\t\t\t\t})\n\t\t\t}\n\t\t\treturn undefined\n\t\t})\n\t}\n}\n"],"names":[],"mappings":";;;;;;;;;;;;AAiBO,MAAM,0DAEb;AAAA,EAGC,YACkB,MACA,QACA,SAChB;AAHgB,SAAA,OAAA;AACA,SAAA,SAAA;AACA,SAAA,UAAA;AALlB,kBAAA,MAAQ,iBAAA;AAOP,SAAK,kBAAkB,4BAA4B;AAAA,MAClD;AAAA,QACC,YAAY,KAAK,KAAK;AAAA,QACtB,WAAW,KAAK,KAAK;AAAA,QACrB,cAAc,KAAK,KAAK,WAAW;AAAA,MAAA;AAAA,MAEpC;AAAA,MACA,KAAK;AAAA,IAAA;AAAA,EAEP;AAAA,EAEO,UAAU,SAA2B,EAAE,gBAA2D;AACxG,UAAM,eAAe,KAAK,OAAO,MAAM,SAAS,KAAK,KAAK,WAAW,MAAM;AAC3E,UAAM,EAAE,UAAU,gBAAgB,KAAK,YAAA;AACvC,UAAM,SAAS,KAAK,OAAO,MAAM,SAAS,KAAK,KAAK,UAAU;AAE9D,2BAAuB,SAAS,cAAc,KAAK,QAAQ,QAAQ,cAAc,6BAA6B,KAAK,KAAK,UAAU,CAAC;AACnI,UAAM,eAAe,KAAK,KAAK,WAAW;AAC1C,YAAQ,IAAI;AAAA,iBACG,eAAe,aAAa,SAAS,CAAC;AAAA,MACjD,eAAe,aAAa,cAAc,UAAU,CAAC;AAAA,MACrD,eAAe,aAAa,qBAAqB,UAAU,CAAC;AAAA;AAAA,YAEtD,eAAe,OAAO,aAAa,CAAC,KAAK,eAAe,YAAY,cAAc,UAAU,CAAC;AAAA,UAC/F,eAAe,OAAO,SAAS,CAAC;AAAA,WAC/B,eAAe,YAAY,cAAc,UAAU,CAAC,cAAc;AAE3E,YAAQ,WAAW,OAAO,WAAW,YAAY,cAAc,UAAU;AAAA,EAC1E;AAAA,EAEO,mBAAkC;AACxC,UAAM,EAAE,eAAe,KAAK;AAC5B,WAAO;AAAA,MACN,KAAK,gBAAgB,iBAAA;AAAA,MACrB,YAAY,aAAa,YAAY,SAAS,6BAA6B,KAAK,KAAK,UAAU,CAAC,CAAC,CAAC;AAAA,MAClG,KAAK,KAAK,cAAc,YAAY,aAAa,KAAK,KAAK,WAAW,QAAQ,SAAS,KAAK,KAAK,WAAW,CAAC,CAAC,IAAI;AAAA,IAAA;AAAA,EAEpH;AAAA,EAEA,WAAW;AACV,WAAO;AAAA,MACN,SAAS,kDAAkD,KAAK,KAAK,UAAU,IAAI,KAAK,KAAK,SAAS;AAAA,IAAA;AAAA,EAExG;AAAA,EAEQ,cAA4E;AACnF,UAAM,SAAS,KAAK,OAAO,MAAM,SAAS,KAAK,KAAK,UAAU;AAC9D,UAAM,WAAW,OAAO,OAAO,KAAK,KAAK,SAAS;AAClD,QAAI,SAAS,SAAS,MAAM,aAAa,YAAY;AACpD,YAAM,IAAI,MAAA;AAAA,IACX;AACA,WAAO,EAAE,QAAQ,SAAA;AAAA,EAClB;AACD;AAEO,MAAM,qDAAqD,uBAAuB;AAAA,EACxF,IAAI;AAAA,EACJ,SAAS;AACV,CAAC;AASM,MAAM,6CAA+D;AAAA,EAC3E,WAAW,gBAAwB,eAAuB;AACzD,WAAO,gBAAgB,gBAAgB,eAAe,CAAC,EAAE,kBAAkB,iBAAiB,oBAAoB;AAC/G,UACC,kBAAkB,gBAAgB,KAC/B,kBAAkB,eAAe,KACjC,iBAAiB,SAAS,MAAM,aAAa,cAC7C,gBAAgB,SAAS,MAAM,aAAa,aAC9C;AACD,cAAM,gBAAgB,iBAAiB;AACvC,cAAM,gBAAgB,gBAAgB;AACtC,cAAM,aAAa,cAAc,MAAM,SAAS,gBAAgB,MAAM,EAAE,OAAO,aAAa;AAC5F,YAAI,WAAW,SAAS,MAAM,aAAa,eAAe,CAAC,iBAAiB,UAAU,GAAG;AACxF,gBAAM,IAAI,MAAA;AAAA,QACX;AACA,eAAO,mDAAmD,mBAAmB;AAAA,UAC5E,YAAY,gBAAgB;AAAA,UAC5B,WAAW;AAAA,UACX;AAAA,UACA,aAAa;AAAA,QAAA,CACb;AAAA,MACF;AACA,aAAO;AAAA,IACR,CAAC;AAAA,EACF;AACD;"}
|
|
1
|
+
{"version":3,"file":"ConvertOneHasManyToManyHasManyRelationModification.js","sources":["../../../../../../packages/schema-migrations/src/modifications/relations/ConvertOneHasManyToManyHasManyRelationModification.ts"],"sourcesContent":["import { MigrationBuilder } from '@contember/database-migrations'\nimport { Model, Schema } from '@contember/schema'\nimport { addField, SchemaUpdater, updateEntity, updateModel, updateSchema } from '../utils/schemaUpdateUtils.js'\nimport {\n\tcreateModificationType,\n\tDiffer,\n\tModificationHandler,\n\tModificationHandlerCreateSqlOptions,\n\tModificationHandlerOptions,\n} from '../ModificationHandler.js'\nimport { isInverseRelation, isOwningRelation } from '@contember/schema-utils'\nimport { updateRelations } from '../utils/diffUtils.js'\nimport { createJunctionTableSql } from '../utils/createJunctionTable.js'\nimport { wrapIdentifier } from '../../utils/dbHelpers.js'\nimport { normalizeManyHasManyRelation, PartialManyHasManyRelation } from './normalization.js'\nimport { updateFieldNameModification } from '../fields/index.js'\n\nexport class ConvertOneHasManyToManyHasManyRelationModificationHandler\n\timplements ModificationHandler<ConvertOneHasManyToManyHasManyRelationModificationData>\n{\n\tprivate subModification: ModificationHandler<any>\n\n\tconstructor(\n\t\tprivate readonly data: ConvertOneHasManyToManyHasManyRelationModificationData,\n\t\tprivate readonly schema: Schema,\n\t\tprivate readonly options: ModificationHandlerOptions,\n\t) {\n\t\tthis.subModification = updateFieldNameModification.createHandler(\n\t\t\t{\n\t\t\t\tentityName: this.data.entityName,\n\t\t\t\tfieldName: this.data.fieldName,\n\t\t\t\tnewFieldName: this.data.owningSide.name,\n\t\t\t},\n\t\t\tschema,\n\t\t\tthis.options,\n\t\t)\n\t}\n\n\tpublic createSql(builder: MigrationBuilder, { systemSchema }: ModificationHandlerCreateSqlOptions): void {\n\t\tconst targetEntity = this.schema.model.entities[this.data.owningSide.target]\n\t\tconst { relation: oldRelation } = this.getRelation()\n\t\tconst entity = this.schema.model.entities[this.data.entityName]\n\n\t\tcreateJunctionTableSql(builder, systemSchema, this.schema, entity, targetEntity, normalizeManyHasManyRelation(this.data.owningSide))\n\t\tconst joiningTable = this.data.owningSide.joiningTable\n\t\tbuilder.sql(`\n\t\t\tINSERT INTO ${wrapIdentifier(joiningTable.tableName)} (\n\t\t\t\t${wrapIdentifier(joiningTable.joiningColumn.columnName)},\n\t\t\t\t${wrapIdentifier(joiningTable.inverseJoiningColumn.columnName)}\n\t\t\t\t)\n\t\t\tSELECT ${wrapIdentifier(entity.primaryColumn)}, ${wrapIdentifier(oldRelation.joiningColumn.columnName)}\n\t\t\tFROM ${wrapIdentifier(entity.tableName)}\n\t\t\tWHERE ${wrapIdentifier(oldRelation.joiningColumn.columnName)} IS NOT NULL`)\n\n\t\tbuilder.dropColumn(entity.tableName, oldRelation.joiningColumn.columnName)\n\t}\n\n\tpublic getSchemaUpdater(): SchemaUpdater {\n\t\tconst { entityName } = this.data\n\t\treturn updateSchema(\n\t\t\tthis.subModification.getSchemaUpdater(),\n\t\t\tupdateModel(updateEntity(entityName, addField(normalizeManyHasManyRelation(this.data.owningSide)))),\n\t\t\tthis.data.inverseSide ? updateModel(updateEntity(this.data.owningSide.target, addField(this.data.inverseSide))) : undefined,\n\t\t)\n\t}\n\n\tdescribe() {\n\t\treturn {\n\t\t\tmessage: `Converts OneHasMany relation to ManyHasMany on ${this.data.entityName}.${this.data.fieldName}`,\n\t\t}\n\t}\n\n\tprivate getRelation(): { entity: Model.Entity; relation: Model.ManyHasOneRelation } {\n\t\tconst entity = this.schema.model.entities[this.data.entityName]\n\t\tconst relation = entity.fields[this.data.fieldName]\n\t\tif (relation.type !== Model.RelationType.ManyHasOne) {\n\t\t\tthrow new Error()\n\t\t}\n\t\treturn { entity, relation }\n\t}\n}\n\nexport const convertOneHasManyToManyHasManyRelationModification = createModificationType({\n\tid: 'convertOneHasManyToManyHasManyRelation',\n\thandler: ConvertOneHasManyToManyHasManyRelationModificationHandler,\n})\n\nexport interface ConvertOneHasManyToManyHasManyRelationModificationData {\n\tentityName: string\n\tfieldName: string\n\towningSide: PartialManyHasManyRelation\n\tinverseSide?: Model.ManyHasManyInverseRelation\n}\n\nexport class ConvertOneHasManyToManyHasManyRelationDiffer implements Differ {\n\tcreateDiff(originalSchema: Schema, updatedSchema: Schema) {\n\t\treturn updateRelations(originalSchema, updatedSchema, ({ originalRelation, updatedRelation, updatedEntity }) => {\n\t\t\tif (\n\t\t\t\tisInverseRelation(originalRelation)\n\t\t\t\t&& isInverseRelation(updatedRelation)\n\t\t\t\t&& originalRelation.type === Model.RelationType.OneHasMany\n\t\t\t\t&& updatedRelation.type === Model.RelationType.ManyHasMany\n\t\t\t) {\n\t\t\t\tconst owningOldName = originalRelation.ownedBy\n\t\t\t\tconst owningNewName = updatedRelation.ownedBy\n\t\t\t\tconst owningSide = updatedSchema.model.entities[updatedRelation.target].fields[owningNewName]\n\t\t\t\tif (owningSide.type !== Model.RelationType.ManyHasMany || !isOwningRelation(owningSide)) {\n\t\t\t\t\tthrow new Error()\n\t\t\t\t}\n\t\t\t\treturn convertOneHasManyToManyHasManyRelationModification.createModification({\n\t\t\t\t\tentityName: updatedRelation.target,\n\t\t\t\t\tfieldName: owningOldName,\n\t\t\t\t\towningSide,\n\t\t\t\t\tinverseSide: updatedRelation,\n\t\t\t\t})\n\t\t\t}\n\t\t\treturn undefined\n\t\t})\n\t}\n}\n"],"names":[],"mappings":"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"}
|