From d35708ebdcfaf96607221d594364b5e78e3b6f7f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Novotn=C3=BD?= Date: Wed, 6 Dec 2023 22:15:00 +0100 Subject: [PATCH] fix: updating global attribute schema should affect all entity attribute schemas that use it --- .../builder/GlobalAttributeSchemaBuilder.java | 4 +- .../builder/InternalCatalogSchemaBuilder.java | 6 +- .../mutation/CatalogSchemaMutation.java | 21 +++++- .../mutation/LocalCatalogSchemaMutation.java | 6 +- .../CreateGlobalAttributeSchemaMutation.java | 66 ++++++++++--------- .../GlobalAttributeSchemaMutation.java | 49 +++++++++----- ...fyAttributeSchemaDefaultValueMutation.java | 4 +- ...ributeSchemaDeprecationNoticeMutation.java | 4 +- ...ifyAttributeSchemaDescriptionMutation.java | 4 +- .../ModifyAttributeSchemaNameMutation.java | 4 +- .../ModifyAttributeSchemaTypeMutation.java | 4 +- .../RemoveAttributeSchemaMutation.java | 46 ++++++++----- .../SetAttributeSchemaFilterableMutation.java | 4 +- ...AttributeSchemaGloballyUniqueMutation.java | 6 +- .../SetAttributeSchemaLocalizedMutation.java | 4 +- .../SetAttributeSchemaNullableMutation.java | 4 +- ...AttributeSchemaRepresentativeMutation.java | 4 +- .../SetAttributeSchemaSortableMutation.java | 4 +- .../SetAttributeSchemaUniqueMutation.java | 4 +- .../UseGlobalAttributeSchemaMutation.java | 29 ++++++++ ...wEvolutionModeInCatalogSchemaMutation.java | 30 +++++---- .../catalog/CreateCatalogSchemaMutation.java | 16 +++-- .../catalog/CreateEntitySchemaMutation.java | 4 +- ...wEvolutionModeInCatalogSchemaMutation.java | 28 ++++---- ...odifyCatalogSchemaDescriptionMutation.java | 22 ++++--- .../catalog/ModifyCatalogSchemaMutation.java | 15 +++-- .../ModifyCatalogSchemaNameMutation.java | 22 ++++--- .../catalog/ModifyEntitySchemaMutation.java | 6 +- .../ModifyEntitySchemaNameMutation.java | 4 +- .../catalog/RemoveCatalogSchemaMutation.java | 2 +- .../catalog/RemoveEntitySchemaMutation.java | 4 +- .../java/io/evitadb/utils/ArrayUtils.java | 4 +- .../main/java/io/evitadb/core/Catalog.java | 26 ++++++-- .../src/main/java/io/evitadb/core/Evita.java | 7 +- .../test/java/io/evitadb/core/EvitaTest.java | 43 ++++++++++++ .../query/parser/grammar/EvitaQLLexer.java | 37 +++-------- 36 files changed, 343 insertions(+), 204 deletions(-) diff --git a/evita_api/src/main/java/io/evitadb/api/requestResponse/schema/builder/GlobalAttributeSchemaBuilder.java b/evita_api/src/main/java/io/evitadb/api/requestResponse/schema/builder/GlobalAttributeSchemaBuilder.java index b6f5e7c494..00be7af1ca 100644 --- a/evita_api/src/main/java/io/evitadb/api/requestResponse/schema/builder/GlobalAttributeSchemaBuilder.java +++ b/evita_api/src/main/java/io/evitadb/api/requestResponse/schema/builder/GlobalAttributeSchemaBuilder.java @@ -99,7 +99,7 @@ protected Class getAttributeSchemaType() { @Override @Nonnull public GlobalAttributeSchemaBuilder uniqueGlobally() { - this.mutations.add( + this.updatedSchemaDirty = addMutations( new SetAttributeSchemaGloballyUniqueMutation( toInstance().getName(), GlobalAttributeUniquenessType.UNIQUE_WITHIN_CATALOG @@ -111,7 +111,7 @@ public GlobalAttributeSchemaBuilder uniqueGlobally() { @Override @Nonnull public GlobalAttributeSchemaBuilder uniqueGloballyWithinLocale() { - this.mutations.add( + this.updatedSchemaDirty = addMutations( new SetAttributeSchemaGloballyUniqueMutation( toInstance().getName(), GlobalAttributeUniquenessType.UNIQUE_WITHIN_CATALOG_LOCALE diff --git a/evita_api/src/main/java/io/evitadb/api/requestResponse/schema/builder/InternalCatalogSchemaBuilder.java b/evita_api/src/main/java/io/evitadb/api/requestResponse/schema/builder/InternalCatalogSchemaBuilder.java index a0c893fc60..0cd0c6e5d8 100644 --- a/evita_api/src/main/java/io/evitadb/api/requestResponse/schema/builder/InternalCatalogSchemaBuilder.java +++ b/evita_api/src/main/java/io/evitadb/api/requestResponse/schema/builder/InternalCatalogSchemaBuilder.java @@ -35,6 +35,7 @@ import io.evitadb.api.requestResponse.schema.SealedCatalogSchema; import io.evitadb.api.requestResponse.schema.dto.EntitySchema; import io.evitadb.api.requestResponse.schema.dto.EntitySchemaProvider; +import io.evitadb.api.requestResponse.schema.mutation.CatalogSchemaMutation.CatalogSchemaWithImpactOnEntitySchemas; import io.evitadb.api.requestResponse.schema.mutation.LocalCatalogSchemaMutation; import io.evitadb.api.requestResponse.schema.mutation.attribute.RemoveAttributeSchemaMutation; import io.evitadb.api.requestResponse.schema.mutation.catalog.AllowEvolutionModeInCatalogSchemaMutation; @@ -331,10 +332,11 @@ public CatalogSchemaContract toInstance() { // apply the mutations not reflected in the schema for (int i = lastMutationReflectedInSchema + 1; i < this.mutations.size(); i++) { final LocalCatalogSchemaMutation mutation = this.mutations.get(i); - currentSchema = mutation.mutate(currentSchema, updatedEntitySchemaAccessor); - if (currentSchema == null) { + final CatalogSchemaWithImpactOnEntitySchemas mutationImpact = mutation.mutate(currentSchema, updatedEntitySchemaAccessor); + if (mutationImpact == null || mutationImpact.updatedCatalogSchema() == null) { throw new EvitaInternalError("Catalog schema unexpectedly removed from inside!"); } + currentSchema = mutationImpact.updatedCatalogSchema(); } this.updatedSchema = currentSchema; this.updatedSchemaDirty = MutationImpact.NO_IMPACT; diff --git a/evita_api/src/main/java/io/evitadb/api/requestResponse/schema/mutation/CatalogSchemaMutation.java b/evita_api/src/main/java/io/evitadb/api/requestResponse/schema/mutation/CatalogSchemaMutation.java index 956eee1e5a..2881be124d 100644 --- a/evita_api/src/main/java/io/evitadb/api/requestResponse/schema/mutation/CatalogSchemaMutation.java +++ b/evita_api/src/main/java/io/evitadb/api/requestResponse/schema/mutation/CatalogSchemaMutation.java @@ -24,7 +24,9 @@ package io.evitadb.api.requestResponse.schema.mutation; import io.evitadb.api.requestResponse.schema.CatalogSchemaContract; +import io.evitadb.api.requestResponse.schema.mutation.catalog.ModifyEntitySchemaMutation; +import javax.annotation.Nonnull; import javax.annotation.Nullable; import javax.annotation.concurrent.Immutable; import javax.annotation.concurrent.ThreadSafe; @@ -46,6 +48,23 @@ public interface CatalogSchemaMutation extends SchemaMutation { * @param catalogSchema current version of the schema as an input to mutate */ @Nullable - CatalogSchemaContract mutate(@Nullable CatalogSchemaContract catalogSchema); + CatalogSchemaWithImpactOnEntitySchemas mutate(@Nullable CatalogSchemaContract catalogSchema); + + /** + * Result object of the {@link #mutate(CatalogSchemaContract)} method allowing to return both the modified catalog + * schema and the list of entity schema mutations that were caused by the catalog schema mutation and needs to be + * propagated to the entity schemas. + * + * @param updatedCatalogSchema modified catalog schema + * @param entitySchemaMutations list of entity schema mutations that were caused by the catalog schema mutation + */ + record CatalogSchemaWithImpactOnEntitySchemas( + @Nonnull CatalogSchemaContract updatedCatalogSchema, + @Nullable ModifyEntitySchemaMutation[] entitySchemaMutations + ) { + public CatalogSchemaWithImpactOnEntitySchemas(@Nonnull CatalogSchemaContract updatedCatalogSchema) { + this(updatedCatalogSchema, null); + } + } } diff --git a/evita_api/src/main/java/io/evitadb/api/requestResponse/schema/mutation/LocalCatalogSchemaMutation.java b/evita_api/src/main/java/io/evitadb/api/requestResponse/schema/mutation/LocalCatalogSchemaMutation.java index 1689bf2853..1e674ea06a 100644 --- a/evita_api/src/main/java/io/evitadb/api/requestResponse/schema/mutation/LocalCatalogSchemaMutation.java +++ b/evita_api/src/main/java/io/evitadb/api/requestResponse/schema/mutation/LocalCatalogSchemaMutation.java @@ -42,7 +42,7 @@ public interface LocalCatalogSchemaMutation extends CatalogSchemaMutation { @Nullable @Override - default CatalogSchemaContract mutate(@Nullable CatalogSchemaContract catalogSchema) { + default CatalogSchemaWithImpactOnEntitySchemas mutate(@Nullable CatalogSchemaContract catalogSchema) { return mutate(catalogSchema, MutationEntitySchemaAccessor.INSTANCE); } @@ -52,9 +52,9 @@ default CatalogSchemaContract mutate(@Nullable CatalogSchemaContract catalogSche * operation produces the opposite. Modification operations always accept and produce non-NULL values. * * @param catalogSchema current version of the schema as an input to mutate - * @param entitySchemaAccessor + * @param entitySchemaAccessor entity schema provider allowing to access list of entity schemas in the catalog */ @Nullable - CatalogSchemaContract mutate(@Nullable CatalogSchemaContract catalogSchema, @Nonnull EntitySchemaProvider entitySchemaAccessor); + CatalogSchemaWithImpactOnEntitySchemas mutate(@Nullable CatalogSchemaContract catalogSchema, @Nonnull EntitySchemaProvider entitySchemaAccessor); } diff --git a/evita_api/src/main/java/io/evitadb/api/requestResponse/schema/mutation/attribute/CreateGlobalAttributeSchemaMutation.java b/evita_api/src/main/java/io/evitadb/api/requestResponse/schema/mutation/attribute/CreateGlobalAttributeSchemaMutation.java index c1f29e48a6..1ee5633f16 100644 --- a/evita_api/src/main/java/io/evitadb/api/requestResponse/schema/mutation/attribute/CreateGlobalAttributeSchemaMutation.java +++ b/evita_api/src/main/java/io/evitadb/api/requestResponse/schema/mutation/attribute/CreateGlobalAttributeSchemaMutation.java @@ -87,6 +87,18 @@ public class CreateGlobalAttributeSchemaMutation @Getter @Nullable private final Serializable defaultValue; @Getter private final int indexedDecimalPlaces; + @Nullable + private static LocalCatalogSchemaMutation makeMutationIfDifferent( + @Nonnull GlobalAttributeSchemaContract createdVersion, + @Nonnull GlobalAttributeSchemaContract existingVersion, + @Nonnull Function propertyRetriever, + @Nonnull Function mutationCreator + ) { + final T newValue = propertyRetriever.apply(createdVersion); + return Objects.equals(propertyRetriever.apply(existingVersion), newValue) ? + null : mutationCreator.apply(newValue); + } + public CreateGlobalAttributeSchemaMutation( @Nonnull String name, @Nullable String description, @@ -140,7 +152,7 @@ public MutationCombinationResult combineWith(@Nonnul makeMutationIfDifferent( createdVersion, existingVersion, NamedSchemaWithDeprecationContract::getDeprecationNotice, - newValue -> new ModifyAttributeSchemaDeprecationNoticeMutation( name, newValue) + newValue -> new ModifyAttributeSchemaDeprecationNoticeMutation(name, newValue) ), makeMutationIfDifferent( createdVersion, existingVersion, @@ -196,18 +208,6 @@ public MutationCombinationResult combineWith(@Nonnul } } - @Nullable - private static LocalCatalogSchemaMutation makeMutationIfDifferent( - @Nonnull GlobalAttributeSchemaContract createdVersion, - @Nonnull GlobalAttributeSchemaContract existingVersion, - @Nonnull Function propertyRetriever, - @Nonnull Function mutationCreator - ) { - final T newValue = propertyRetriever.apply(createdVersion); - return Objects.equals(propertyRetriever.apply(existingVersion), newValue) ? - null : mutationCreator.apply(newValue); - } - @Nonnull @Override public S mutate(@Nullable CatalogSchemaContract catalogSchema, @Nullable S attributeSchema, @Nonnull Class schemaType) { @@ -215,39 +215,41 @@ public S mutate(@Nullable CatalogSchemaContr return (S) GlobalAttributeSchema._internalBuild( name, description, deprecationNotice, unique, uniqueGlobally, filterable, sortable, localized, nullable, representative, - (Class)type, defaultValue, + (Class) type, defaultValue, indexedDecimalPlaces ); } @Nullable @Override - public CatalogSchemaContract mutate(@Nullable CatalogSchemaContract catalogSchema, @Nonnull EntitySchemaProvider entitySchemaAccessor) { + public CatalogSchemaWithImpactOnEntitySchemas mutate(@Nullable CatalogSchemaContract catalogSchema, @Nonnull EntitySchemaProvider entitySchemaAccessor) { Assert.isPremiseValid(catalogSchema != null, "Catalog schema is mandatory!"); final GlobalAttributeSchemaContract newAttributeSchema = mutate(catalogSchema, null, GlobalAttributeSchemaContract.class); final GlobalAttributeSchemaContract existingAttributeSchema = catalogSchema.getAttribute(name).orElse(null); if (existingAttributeSchema == null) { - return CatalogSchema._internalBuild( - catalogSchema.getVersion() + 1, - catalogSchema.getName(), - catalogSchema.getNameVariants(), - catalogSchema.getDescription(), - catalogSchema.getCatalogEvolutionMode(), - Stream.concat( - catalogSchema.getAttributes().values().stream(), - Stream.of(newAttributeSchema) - ) - .collect( - Collectors.toMap( - GlobalAttributeSchemaContract::getName, - Function.identity() + return new CatalogSchemaWithImpactOnEntitySchemas( + CatalogSchema._internalBuild( + catalogSchema.getVersion() + 1, + catalogSchema.getName(), + catalogSchema.getNameVariants(), + catalogSchema.getDescription(), + catalogSchema.getCatalogEvolutionMode(), + Stream.concat( + catalogSchema.getAttributes().values().stream(), + Stream.of(newAttributeSchema) ) - ), - entitySchemaAccessor + .collect( + Collectors.toMap( + GlobalAttributeSchemaContract::getName, + Function.identity() + ) + ), + entitySchemaAccessor + ) ); } else if (existingAttributeSchema.equals(newAttributeSchema)) { // the mutation must have been applied previously - return the schema we don't need to alter - return catalogSchema; + return new CatalogSchemaWithImpactOnEntitySchemas(catalogSchema); } else { // ups, there is conflict in attribute settings throw new InvalidSchemaMutationException( diff --git a/evita_api/src/main/java/io/evitadb/api/requestResponse/schema/mutation/attribute/GlobalAttributeSchemaMutation.java b/evita_api/src/main/java/io/evitadb/api/requestResponse/schema/mutation/attribute/GlobalAttributeSchemaMutation.java index 3bc98a9874..af0a3eaffd 100644 --- a/evita_api/src/main/java/io/evitadb/api/requestResponse/schema/mutation/attribute/GlobalAttributeSchemaMutation.java +++ b/evita_api/src/main/java/io/evitadb/api/requestResponse/schema/mutation/attribute/GlobalAttributeSchemaMutation.java @@ -30,6 +30,7 @@ import io.evitadb.api.requestResponse.schema.dto.EntitySchemaProvider; import io.evitadb.api.requestResponse.schema.mutation.AttributeSchemaMutation; import io.evitadb.api.requestResponse.schema.mutation.CatalogSchemaMutation; +import io.evitadb.api.requestResponse.schema.mutation.catalog.ModifyEntitySchemaMutation; import javax.annotation.Nonnull; import java.util.function.Function; @@ -48,33 +49,45 @@ public interface GlobalAttributeSchemaMutation extends AttributeSchemaMutation, * the non-changed, original catalog schema is returned. */ @Nonnull - default CatalogSchemaContract replaceAttributeIfDifferent( + default CatalogSchemaWithImpactOnEntitySchemas replaceAttributeIfDifferent( @Nonnull CatalogSchemaContract catalogSchema, @Nonnull GlobalAttributeSchemaContract existingAttributeSchema, @Nonnull GlobalAttributeSchemaContract updatedAttributeSchema, - @Nonnull EntitySchemaProvider entitySchemaAccessor + @Nonnull EntitySchemaProvider entitySchemaAccessor, + @Nonnull EntityAttributeSchemaMutation attributeSchemaMutation ) { if (existingAttributeSchema.equals(updatedAttributeSchema)) { // we don't need to update entity schema - the associated data already contains the requested change - return catalogSchema; + return new CatalogSchemaWithImpactOnEntitySchemas(catalogSchema); } else { - return CatalogSchema._internalBuild( - catalogSchema.getVersion() + 1, - catalogSchema.getName(), - catalogSchema.getNameVariants(), - catalogSchema.getDescription(), - catalogSchema.getCatalogEvolutionMode(), - Stream.concat( - catalogSchema.getAttributes().values().stream().filter(it -> !updatedAttributeSchema.getName().equals(it.getName())), - Stream.of(updatedAttributeSchema) - ) - .collect( - Collectors.toMap( - AttributeSchemaContract::getName, - Function.identity() + return new CatalogSchemaWithImpactOnEntitySchemas( + CatalogSchema._internalBuild( + catalogSchema.getVersion() + 1, + catalogSchema.getName(), + catalogSchema.getNameVariants(), + catalogSchema.getDescription(), + catalogSchema.getCatalogEvolutionMode(), + Stream.concat( + catalogSchema.getAttributes().values().stream().filter(it -> !updatedAttributeSchema.getName().equals(it.getName())), + Stream.of(updatedAttributeSchema) ) - ), + .collect( + Collectors.toMap( + AttributeSchemaContract::getName, + Function.identity() + ) + ), + entitySchemaAccessor + ), entitySchemaAccessor + .getEntitySchemas() + .stream() + .filter(it -> it.getAttributes().containsKey(existingAttributeSchema.getName())) + .map(it -> new ModifyEntitySchemaMutation( + it.getName(), + attributeSchemaMutation + )) + .toArray(ModifyEntitySchemaMutation[]::new) ); } } diff --git a/evita_api/src/main/java/io/evitadb/api/requestResponse/schema/mutation/attribute/ModifyAttributeSchemaDefaultValueMutation.java b/evita_api/src/main/java/io/evitadb/api/requestResponse/schema/mutation/attribute/ModifyAttributeSchemaDefaultValueMutation.java index e2e7d168e3..7823f16859 100644 --- a/evita_api/src/main/java/io/evitadb/api/requestResponse/schema/mutation/attribute/ModifyAttributeSchemaDefaultValueMutation.java +++ b/evita_api/src/main/java/io/evitadb/api/requestResponse/schema/mutation/attribute/ModifyAttributeSchemaDefaultValueMutation.java @@ -160,7 +160,7 @@ public S mutate(@Nullable CatalogSchemaContr @Nullable @Override - public CatalogSchemaContract mutate(@Nullable CatalogSchemaContract catalogSchema, @Nonnull EntitySchemaProvider entitySchemaAccessor) { + public CatalogSchemaWithImpactOnEntitySchemas mutate(@Nullable CatalogSchemaContract catalogSchema, @Nonnull EntitySchemaProvider entitySchemaAccessor) { Assert.isPremiseValid(catalogSchema != null, "Catalog schema is mandatory!"); final GlobalAttributeSchemaContract existingAttributeSchema = catalogSchema.getAttribute(name) .orElseThrow(() -> new InvalidSchemaMutationException( @@ -170,7 +170,7 @@ public CatalogSchemaContract mutate(@Nullable CatalogSchemaContract catalogSchem try { final GlobalAttributeSchemaContract updatedAttributeSchema = mutate(catalogSchema, existingAttributeSchema, GlobalAttributeSchemaContract.class); return replaceAttributeIfDifferent( - catalogSchema, existingAttributeSchema, updatedAttributeSchema, entitySchemaAccessor + catalogSchema, existingAttributeSchema, updatedAttributeSchema, entitySchemaAccessor, this ); } catch (UnsupportedDataTypeException ex) { throw new InvalidSchemaMutationException( diff --git a/evita_api/src/main/java/io/evitadb/api/requestResponse/schema/mutation/attribute/ModifyAttributeSchemaDeprecationNoticeMutation.java b/evita_api/src/main/java/io/evitadb/api/requestResponse/schema/mutation/attribute/ModifyAttributeSchemaDeprecationNoticeMutation.java index 57bec7b536..86c83e8f56 100644 --- a/evita_api/src/main/java/io/evitadb/api/requestResponse/schema/mutation/attribute/ModifyAttributeSchemaDeprecationNoticeMutation.java +++ b/evita_api/src/main/java/io/evitadb/api/requestResponse/schema/mutation/attribute/ModifyAttributeSchemaDeprecationNoticeMutation.java @@ -154,7 +154,7 @@ public S mutate(@Nullable CatalogSchemaContr @Nullable @Override - public CatalogSchemaContract mutate(@Nullable CatalogSchemaContract catalogSchema, @Nonnull EntitySchemaProvider entitySchemaAccessor) { + public CatalogSchemaWithImpactOnEntitySchemas mutate(@Nullable CatalogSchemaContract catalogSchema, @Nonnull EntitySchemaProvider entitySchemaAccessor) { Assert.isPremiseValid(catalogSchema != null, "Catalog schema is mandatory!"); final GlobalAttributeSchemaContract existingAttributeSchema = catalogSchema.getAttribute(name) .orElseThrow(() -> new InvalidSchemaMutationException( @@ -164,7 +164,7 @@ public CatalogSchemaContract mutate(@Nullable CatalogSchemaContract catalogSchem final GlobalAttributeSchemaContract updatedAttributeSchema = mutate(catalogSchema, existingAttributeSchema, GlobalAttributeSchemaContract.class); return replaceAttributeIfDifferent( - catalogSchema, existingAttributeSchema, updatedAttributeSchema, entitySchemaAccessor + catalogSchema, existingAttributeSchema, updatedAttributeSchema, entitySchemaAccessor, this ); } diff --git a/evita_api/src/main/java/io/evitadb/api/requestResponse/schema/mutation/attribute/ModifyAttributeSchemaDescriptionMutation.java b/evita_api/src/main/java/io/evitadb/api/requestResponse/schema/mutation/attribute/ModifyAttributeSchemaDescriptionMutation.java index f2203f2e95..388fa41a08 100644 --- a/evita_api/src/main/java/io/evitadb/api/requestResponse/schema/mutation/attribute/ModifyAttributeSchemaDescriptionMutation.java +++ b/evita_api/src/main/java/io/evitadb/api/requestResponse/schema/mutation/attribute/ModifyAttributeSchemaDescriptionMutation.java @@ -154,7 +154,7 @@ public S mutate(@Nullable CatalogSchemaContr @Nullable @Override - public CatalogSchemaContract mutate(@Nullable CatalogSchemaContract catalogSchema, @Nonnull EntitySchemaProvider entitySchemaAccessor) { + public CatalogSchemaWithImpactOnEntitySchemas mutate(@Nullable CatalogSchemaContract catalogSchema, @Nonnull EntitySchemaProvider entitySchemaAccessor) { Assert.isPremiseValid(catalogSchema != null, "Catalog schema is mandatory!"); final GlobalAttributeSchemaContract existingAttributeSchema = catalogSchema.getAttribute(name) .orElseThrow(() -> new InvalidSchemaMutationException( @@ -163,7 +163,7 @@ public CatalogSchemaContract mutate(@Nullable CatalogSchemaContract catalogSchem final GlobalAttributeSchemaContract updatedAttributeSchema = mutate(catalogSchema, existingAttributeSchema, GlobalAttributeSchemaContract.class); return replaceAttributeIfDifferent( - catalogSchema, existingAttributeSchema, updatedAttributeSchema, entitySchemaAccessor + catalogSchema, existingAttributeSchema, updatedAttributeSchema, entitySchemaAccessor, this ); } diff --git a/evita_api/src/main/java/io/evitadb/api/requestResponse/schema/mutation/attribute/ModifyAttributeSchemaNameMutation.java b/evita_api/src/main/java/io/evitadb/api/requestResponse/schema/mutation/attribute/ModifyAttributeSchemaNameMutation.java index 12c223843c..98bdfe7baf 100644 --- a/evita_api/src/main/java/io/evitadb/api/requestResponse/schema/mutation/attribute/ModifyAttributeSchemaNameMutation.java +++ b/evita_api/src/main/java/io/evitadb/api/requestResponse/schema/mutation/attribute/ModifyAttributeSchemaNameMutation.java @@ -154,7 +154,7 @@ public S mutate(@Nullable CatalogSchemaContr @Nullable @Override - public CatalogSchemaContract mutate(@Nullable CatalogSchemaContract catalogSchema, @Nonnull EntitySchemaProvider entitySchemaAccessor) { + public CatalogSchemaWithImpactOnEntitySchemas mutate(@Nullable CatalogSchemaContract catalogSchema, @Nonnull EntitySchemaProvider entitySchemaAccessor) { Assert.isPremiseValid(catalogSchema != null, "Catalog schema is mandatory!"); final GlobalAttributeSchemaContract existingAttributeSchema = catalogSchema.getAttribute(name) .orElseThrow(() -> new InvalidSchemaMutationException( @@ -163,7 +163,7 @@ public CatalogSchemaContract mutate(@Nullable CatalogSchemaContract catalogSchem final GlobalAttributeSchemaContract updatedAttributeSchema = mutate(catalogSchema, existingAttributeSchema, GlobalAttributeSchemaContract.class); return replaceAttributeIfDifferent( - catalogSchema, existingAttributeSchema, updatedAttributeSchema, entitySchemaAccessor + catalogSchema, existingAttributeSchema, updatedAttributeSchema, entitySchemaAccessor, this ); } diff --git a/evita_api/src/main/java/io/evitadb/api/requestResponse/schema/mutation/attribute/ModifyAttributeSchemaTypeMutation.java b/evita_api/src/main/java/io/evitadb/api/requestResponse/schema/mutation/attribute/ModifyAttributeSchemaTypeMutation.java index e376a3f656..393eaec182 100644 --- a/evita_api/src/main/java/io/evitadb/api/requestResponse/schema/mutation/attribute/ModifyAttributeSchemaTypeMutation.java +++ b/evita_api/src/main/java/io/evitadb/api/requestResponse/schema/mutation/attribute/ModifyAttributeSchemaTypeMutation.java @@ -193,7 +193,7 @@ public S mutate(@Nullable CatalogSchemaContr @Nullable @Override - public CatalogSchemaContract mutate(@Nullable CatalogSchemaContract catalogSchema, @Nonnull EntitySchemaProvider entitySchemaAccessor) { + public CatalogSchemaWithImpactOnEntitySchemas mutate(@Nullable CatalogSchemaContract catalogSchema, @Nonnull EntitySchemaProvider entitySchemaAccessor) { Assert.isPremiseValid(catalogSchema != null, "Catalog schema is mandatory!"); final GlobalAttributeSchemaContract existingAttributeSchema = catalogSchema.getAttribute(name) .orElseThrow(() -> new InvalidSchemaMutationException( @@ -203,7 +203,7 @@ public CatalogSchemaContract mutate(@Nullable CatalogSchemaContract catalogSchem final GlobalAttributeSchemaContract updatedAttributeSchema = mutate(catalogSchema, existingAttributeSchema, GlobalAttributeSchemaContract.class); return replaceAttributeIfDifferent( - catalogSchema, existingAttributeSchema, updatedAttributeSchema, entitySchemaAccessor + catalogSchema, existingAttributeSchema, updatedAttributeSchema, entitySchemaAccessor, this ); } diff --git a/evita_api/src/main/java/io/evitadb/api/requestResponse/schema/mutation/attribute/RemoveAttributeSchemaMutation.java b/evita_api/src/main/java/io/evitadb/api/requestResponse/schema/mutation/attribute/RemoveAttributeSchemaMutation.java index 1903feb843..528b8ce782 100644 --- a/evita_api/src/main/java/io/evitadb/api/requestResponse/schema/mutation/attribute/RemoveAttributeSchemaMutation.java +++ b/evita_api/src/main/java/io/evitadb/api/requestResponse/schema/mutation/attribute/RemoveAttributeSchemaMutation.java @@ -40,6 +40,7 @@ import io.evitadb.api.requestResponse.schema.mutation.EntitySchemaMutation; import io.evitadb.api.requestResponse.schema.mutation.LocalCatalogSchemaMutation; import io.evitadb.api.requestResponse.schema.mutation.SchemaMutation; +import io.evitadb.api.requestResponse.schema.mutation.catalog.ModifyEntitySchemaMutation; import io.evitadb.api.requestResponse.schema.mutation.reference.ModifyReferenceAttributeSchemaMutation; import io.evitadb.utils.Assert; import lombok.EqualsAndHashCode; @@ -115,30 +116,41 @@ public S mutate(@Nullable CatalogSchemaContr @Nullable @Override - public CatalogSchemaContract mutate(@Nullable CatalogSchemaContract catalogSchema, @Nonnull EntitySchemaProvider entitySchemaAccessor) { + public CatalogSchemaWithImpactOnEntitySchemas mutate(@Nullable CatalogSchemaContract catalogSchema, @Nonnull EntitySchemaProvider entitySchemaAccessor) { Assert.isPremiseValid(catalogSchema != null, "Catalog schema is mandatory!"); final Optional existingAttributeSchema = catalogSchema.getAttribute(name); if (existingAttributeSchema.isEmpty()) { // the attribute schema was already removed - or just doesn't exist, // so we can simply return current schema - return catalogSchema; + return new CatalogSchemaWithImpactOnEntitySchemas(catalogSchema); } else { - return CatalogSchema._internalBuild( - catalogSchema.getVersion() + 1, - catalogSchema.getName(), - catalogSchema.getNameVariants(), - catalogSchema.getDescription(), - catalogSchema.getCatalogEvolutionMode(), - catalogSchema.getAttributes().values() - .stream() - .filter(it -> !it.getName().equals(name)) - .collect( - Collectors.toMap( - AttributeSchemaContract::getName, - Function.identity() - ) - ), + return new CatalogSchemaWithImpactOnEntitySchemas( + CatalogSchema._internalBuild( + catalogSchema.getVersion() + 1, + catalogSchema.getName(), + catalogSchema.getNameVariants(), + catalogSchema.getDescription(), + catalogSchema.getCatalogEvolutionMode(), + catalogSchema.getAttributes().values() + .stream() + .filter(it -> !it.getName().equals(name)) + .collect( + Collectors.toMap( + AttributeSchemaContract::getName, + Function.identity() + ) + ), + entitySchemaAccessor + ), entitySchemaAccessor + .getEntitySchemas() + .stream() + .filter(it -> it.getAttributes().containsKey(name)) + .map(it -> new ModifyEntitySchemaMutation( + it.getName(), + this + )) + .toArray(ModifyEntitySchemaMutation[]::new) ); } } diff --git a/evita_api/src/main/java/io/evitadb/api/requestResponse/schema/mutation/attribute/SetAttributeSchemaFilterableMutation.java b/evita_api/src/main/java/io/evitadb/api/requestResponse/schema/mutation/attribute/SetAttributeSchemaFilterableMutation.java index 5cbc06764c..23f32cdde5 100644 --- a/evita_api/src/main/java/io/evitadb/api/requestResponse/schema/mutation/attribute/SetAttributeSchemaFilterableMutation.java +++ b/evita_api/src/main/java/io/evitadb/api/requestResponse/schema/mutation/attribute/SetAttributeSchemaFilterableMutation.java @@ -156,7 +156,7 @@ public S mutate(@Nullable CatalogSchemaContr @Nullable @Override - public CatalogSchemaContract mutate(@Nullable CatalogSchemaContract catalogSchema, @Nonnull EntitySchemaProvider entitySchemaAccessor) { + public CatalogSchemaWithImpactOnEntitySchemas mutate(@Nullable CatalogSchemaContract catalogSchema, @Nonnull EntitySchemaProvider entitySchemaAccessor) { Assert.isPremiseValid(catalogSchema != null, "Catalog schema is mandatory!"); final GlobalAttributeSchemaContract existingAttributeSchema = catalogSchema.getAttribute(name) .orElseThrow(() -> new InvalidSchemaMutationException( @@ -165,7 +165,7 @@ public CatalogSchemaContract mutate(@Nullable CatalogSchemaContract catalogSchem final GlobalAttributeSchemaContract updatedAttributeSchema = mutate(catalogSchema, existingAttributeSchema, GlobalAttributeSchemaContract.class); return replaceAttributeIfDifferent( - catalogSchema, existingAttributeSchema, updatedAttributeSchema, entitySchemaAccessor + catalogSchema, existingAttributeSchema, updatedAttributeSchema, entitySchemaAccessor, this ); } diff --git a/evita_api/src/main/java/io/evitadb/api/requestResponse/schema/mutation/attribute/SetAttributeSchemaGloballyUniqueMutation.java b/evita_api/src/main/java/io/evitadb/api/requestResponse/schema/mutation/attribute/SetAttributeSchemaGloballyUniqueMutation.java index 9445db6afa..273cb32516 100644 --- a/evita_api/src/main/java/io/evitadb/api/requestResponse/schema/mutation/attribute/SetAttributeSchemaGloballyUniqueMutation.java +++ b/evita_api/src/main/java/io/evitadb/api/requestResponse/schema/mutation/attribute/SetAttributeSchemaGloballyUniqueMutation.java @@ -110,7 +110,7 @@ public S mutate(@Nullable CatalogSchemaContr @Nullable @Override - public CatalogSchemaContract mutate(@Nullable CatalogSchemaContract catalogSchema, @Nonnull EntitySchemaProvider entitySchemaAccessor) { + public CatalogSchemaWithImpactOnEntitySchemas mutate(@Nullable CatalogSchemaContract catalogSchema, @Nonnull EntitySchemaProvider entitySchemaAccessor) { Assert.isPremiseValid(catalogSchema != null, "Catalog schema is mandatory!"); final GlobalAttributeSchemaContract existingAttributeSchema = catalogSchema.getAttribute(name) .orElseThrow(() -> new InvalidSchemaMutationException( @@ -119,7 +119,9 @@ public CatalogSchemaContract mutate(@Nullable CatalogSchemaContract catalogSchem final GlobalAttributeSchemaContract updatedAttributeSchema = mutate(catalogSchema, existingAttributeSchema, GlobalAttributeSchemaContract.class); return replaceAttributeIfDifferent( - catalogSchema, existingAttributeSchema, updatedAttributeSchema, entitySchemaAccessor + catalogSchema, existingAttributeSchema, updatedAttributeSchema, entitySchemaAccessor, + // this leads to refresh of the attribute schema + new UseGlobalAttributeSchemaMutation(name) ); } diff --git a/evita_api/src/main/java/io/evitadb/api/requestResponse/schema/mutation/attribute/SetAttributeSchemaLocalizedMutation.java b/evita_api/src/main/java/io/evitadb/api/requestResponse/schema/mutation/attribute/SetAttributeSchemaLocalizedMutation.java index aac599f4e5..ccb24e6c46 100644 --- a/evita_api/src/main/java/io/evitadb/api/requestResponse/schema/mutation/attribute/SetAttributeSchemaLocalizedMutation.java +++ b/evita_api/src/main/java/io/evitadb/api/requestResponse/schema/mutation/attribute/SetAttributeSchemaLocalizedMutation.java @@ -156,7 +156,7 @@ public S mutate(@Nullable CatalogSchemaContr @Nullable @Override - public CatalogSchemaContract mutate(@Nullable CatalogSchemaContract catalogSchema, @Nonnull EntitySchemaProvider entitySchemaAccessor) { + public CatalogSchemaWithImpactOnEntitySchemas mutate(@Nullable CatalogSchemaContract catalogSchema, @Nonnull EntitySchemaProvider entitySchemaAccessor) { Assert.isPremiseValid(catalogSchema != null, "Catalog schema is mandatory!"); final GlobalAttributeSchemaContract existingAttributeSchema = catalogSchema.getAttribute(name) .orElseThrow(() -> new InvalidSchemaMutationException( @@ -165,7 +165,7 @@ public CatalogSchemaContract mutate(@Nullable CatalogSchemaContract catalogSchem final GlobalAttributeSchemaContract updatedAttributeSchema = mutate(catalogSchema, existingAttributeSchema, GlobalAttributeSchemaContract.class); return replaceAttributeIfDifferent( - catalogSchema, existingAttributeSchema, updatedAttributeSchema, entitySchemaAccessor + catalogSchema, existingAttributeSchema, updatedAttributeSchema, entitySchemaAccessor, this ); } diff --git a/evita_api/src/main/java/io/evitadb/api/requestResponse/schema/mutation/attribute/SetAttributeSchemaNullableMutation.java b/evita_api/src/main/java/io/evitadb/api/requestResponse/schema/mutation/attribute/SetAttributeSchemaNullableMutation.java index 58ee709440..cbbed75e0d 100644 --- a/evita_api/src/main/java/io/evitadb/api/requestResponse/schema/mutation/attribute/SetAttributeSchemaNullableMutation.java +++ b/evita_api/src/main/java/io/evitadb/api/requestResponse/schema/mutation/attribute/SetAttributeSchemaNullableMutation.java @@ -156,7 +156,7 @@ public S mutate(@Nullable CatalogSchemaContr @Nullable @Override - public CatalogSchemaContract mutate(@Nullable CatalogSchemaContract catalogSchema, @Nonnull EntitySchemaProvider entitySchemaAccessor) { + public CatalogSchemaWithImpactOnEntitySchemas mutate(@Nullable CatalogSchemaContract catalogSchema, @Nonnull EntitySchemaProvider entitySchemaAccessor) { Assert.isPremiseValid(catalogSchema != null, "Catalog schema is mandatory!"); final GlobalAttributeSchemaContract existingAttributeSchema = catalogSchema.getAttribute(name) .orElseThrow(() -> new InvalidSchemaMutationException( @@ -165,7 +165,7 @@ public CatalogSchemaContract mutate(@Nullable CatalogSchemaContract catalogSchem final GlobalAttributeSchemaContract updatedAttributeSchema = mutate(catalogSchema, existingAttributeSchema, GlobalAttributeSchemaContract.class); return replaceAttributeIfDifferent( - catalogSchema, existingAttributeSchema, updatedAttributeSchema, entitySchemaAccessor + catalogSchema, existingAttributeSchema, updatedAttributeSchema, entitySchemaAccessor, this ); } diff --git a/evita_api/src/main/java/io/evitadb/api/requestResponse/schema/mutation/attribute/SetAttributeSchemaRepresentativeMutation.java b/evita_api/src/main/java/io/evitadb/api/requestResponse/schema/mutation/attribute/SetAttributeSchemaRepresentativeMutation.java index f26f6c84b6..ecf06a5590 100644 --- a/evita_api/src/main/java/io/evitadb/api/requestResponse/schema/mutation/attribute/SetAttributeSchemaRepresentativeMutation.java +++ b/evita_api/src/main/java/io/evitadb/api/requestResponse/schema/mutation/attribute/SetAttributeSchemaRepresentativeMutation.java @@ -141,7 +141,7 @@ public S mutate(@Nullable CatalogSchemaContr @Nullable @Override - public CatalogSchemaContract mutate(@Nullable CatalogSchemaContract catalogSchema, @Nonnull EntitySchemaProvider entitySchemaAccessor) { + public CatalogSchemaWithImpactOnEntitySchemas mutate(@Nullable CatalogSchemaContract catalogSchema, @Nonnull EntitySchemaProvider entitySchemaAccessor) { Assert.isPremiseValid(catalogSchema != null, "Catalog schema is mandatory!"); final GlobalAttributeSchemaContract existingAttributeSchema = catalogSchema.getAttribute(name) .orElseThrow(() -> new InvalidSchemaMutationException( @@ -150,7 +150,7 @@ public CatalogSchemaContract mutate(@Nullable CatalogSchemaContract catalogSchem final GlobalAttributeSchemaContract updatedAttributeSchema = mutate(catalogSchema, existingAttributeSchema, GlobalAttributeSchemaContract.class); return replaceAttributeIfDifferent( - catalogSchema, existingAttributeSchema, updatedAttributeSchema, entitySchemaAccessor + catalogSchema, existingAttributeSchema, updatedAttributeSchema, entitySchemaAccessor, this ); } diff --git a/evita_api/src/main/java/io/evitadb/api/requestResponse/schema/mutation/attribute/SetAttributeSchemaSortableMutation.java b/evita_api/src/main/java/io/evitadb/api/requestResponse/schema/mutation/attribute/SetAttributeSchemaSortableMutation.java index 4c50dbf08d..8c1959753a 100644 --- a/evita_api/src/main/java/io/evitadb/api/requestResponse/schema/mutation/attribute/SetAttributeSchemaSortableMutation.java +++ b/evita_api/src/main/java/io/evitadb/api/requestResponse/schema/mutation/attribute/SetAttributeSchemaSortableMutation.java @@ -156,7 +156,7 @@ public S mutate(@Nullable CatalogSchemaContr @Nullable @Override - public CatalogSchemaContract mutate(@Nullable CatalogSchemaContract catalogSchema, @Nonnull EntitySchemaProvider entitySchemaAccessor) { + public CatalogSchemaWithImpactOnEntitySchemas mutate(@Nullable CatalogSchemaContract catalogSchema, @Nonnull EntitySchemaProvider entitySchemaAccessor) { Assert.isPremiseValid(catalogSchema != null, "Catalog schema is mandatory!"); final GlobalAttributeSchemaContract existingAttributeSchema = catalogSchema.getAttribute(name) .orElseThrow(() -> new InvalidSchemaMutationException( @@ -165,7 +165,7 @@ public CatalogSchemaContract mutate(@Nullable CatalogSchemaContract catalogSchem final GlobalAttributeSchemaContract updatedAttributeSchema = mutate(catalogSchema, existingAttributeSchema, GlobalAttributeSchemaContract.class); return replaceAttributeIfDifferent( - catalogSchema, existingAttributeSchema, updatedAttributeSchema, entitySchemaAccessor + catalogSchema, existingAttributeSchema, updatedAttributeSchema, entitySchemaAccessor, this ); } diff --git a/evita_api/src/main/java/io/evitadb/api/requestResponse/schema/mutation/attribute/SetAttributeSchemaUniqueMutation.java b/evita_api/src/main/java/io/evitadb/api/requestResponse/schema/mutation/attribute/SetAttributeSchemaUniqueMutation.java index c185d3a854..4d019de3e5 100644 --- a/evita_api/src/main/java/io/evitadb/api/requestResponse/schema/mutation/attribute/SetAttributeSchemaUniqueMutation.java +++ b/evita_api/src/main/java/io/evitadb/api/requestResponse/schema/mutation/attribute/SetAttributeSchemaUniqueMutation.java @@ -157,7 +157,7 @@ public S mutate(@Nullable CatalogSchemaContr @Nullable @Override - public CatalogSchemaContract mutate(@Nullable CatalogSchemaContract catalogSchema, @Nonnull EntitySchemaProvider entitySchemaAccessor) { + public CatalogSchemaWithImpactOnEntitySchemas mutate(@Nullable CatalogSchemaContract catalogSchema, @Nonnull EntitySchemaProvider entitySchemaAccessor) { Assert.isPremiseValid(catalogSchema != null, "Catalog schema is mandatory!"); final GlobalAttributeSchemaContract existingAttributeSchema = catalogSchema.getAttribute(name) .orElseThrow(() -> new InvalidSchemaMutationException( @@ -166,7 +166,7 @@ public CatalogSchemaContract mutate(@Nullable CatalogSchemaContract catalogSchem final GlobalAttributeSchemaContract updatedAttributeSchema = mutate(catalogSchema, existingAttributeSchema, GlobalAttributeSchemaContract.class); return replaceAttributeIfDifferent( - catalogSchema, existingAttributeSchema, updatedAttributeSchema, entitySchemaAccessor + catalogSchema, existingAttributeSchema, updatedAttributeSchema, entitySchemaAccessor, this ); } diff --git a/evita_api/src/main/java/io/evitadb/api/requestResponse/schema/mutation/attribute/UseGlobalAttributeSchemaMutation.java b/evita_api/src/main/java/io/evitadb/api/requestResponse/schema/mutation/attribute/UseGlobalAttributeSchemaMutation.java index ffaf35e8b9..69024cf744 100644 --- a/evita_api/src/main/java/io/evitadb/api/requestResponse/schema/mutation/attribute/UseGlobalAttributeSchemaMutation.java +++ b/evita_api/src/main/java/io/evitadb/api/requestResponse/schema/mutation/attribute/UseGlobalAttributeSchemaMutation.java @@ -30,6 +30,7 @@ import io.evitadb.api.requestResponse.schema.EntitySchemaContract; import io.evitadb.api.requestResponse.schema.GlobalAttributeSchemaContract; import io.evitadb.api.requestResponse.schema.dto.EntitySchema; +import io.evitadb.api.requestResponse.schema.dto.GlobalAttributeSchema; import io.evitadb.exception.EvitaInvalidUsageException; import io.evitadb.utils.Assert; import lombok.AllArgsConstructor; @@ -110,6 +111,34 @@ public EntitySchemaContract mutate(@Nonnull CatalogSchemaContract catalogSchema, entitySchema.getEvolutionMode(), entitySchema.getSortableAttributeCompounds() ); + } else if (existingAttributeSchema instanceof GlobalAttributeSchema) { + return EntitySchema._internalBuild( + entitySchema.version() + 1, + entitySchema.getName(), + entitySchema.getNameVariants(), + entitySchema.getDescription(), + entitySchema.getDeprecationNotice(), + entitySchema.isWithGeneratedPrimaryKey(), + entitySchema.isWithHierarchy(), + entitySchema.isWithPrice(), + entitySchema.getIndexedPricePlaces(), + entitySchema.getLocales(), + entitySchema.getCurrencies(), + Stream.concat( + entitySchema.getAttributes().values().stream().filter(it -> !it.getName().equals(name)), + Stream.of(newAttributeSchema) + ) + .collect( + Collectors.toMap( + AttributeSchemaContract::getName, + Function.identity() + ) + ), + entitySchema.getAssociatedData(), + entitySchema.getReferences(), + entitySchema.getEvolutionMode(), + entitySchema.getSortableAttributeCompounds() + ); } else if (existingAttributeSchema.equals(newAttributeSchema)) { // the mutation must have been applied previously - return the schema we don't need to alter return entitySchema; diff --git a/evita_api/src/main/java/io/evitadb/api/requestResponse/schema/mutation/catalog/AllowEvolutionModeInCatalogSchemaMutation.java b/evita_api/src/main/java/io/evitadb/api/requestResponse/schema/mutation/catalog/AllowEvolutionModeInCatalogSchemaMutation.java index ae6f361217..658dff406e 100644 --- a/evita_api/src/main/java/io/evitadb/api/requestResponse/schema/mutation/catalog/AllowEvolutionModeInCatalogSchemaMutation.java +++ b/evita_api/src/main/java/io/evitadb/api/requestResponse/schema/mutation/catalog/AllowEvolutionModeInCatalogSchemaMutation.java @@ -64,24 +64,26 @@ public AllowEvolutionModeInCatalogSchemaMutation(@Nonnull CatalogEvolutionMode.. @Nullable @Override - public CatalogSchemaContract mutate(@Nullable CatalogSchemaContract catalogSchema, @Nonnull EntitySchemaProvider entitySchemaAccessor) { + public CatalogSchemaWithImpactOnEntitySchemas mutate(@Nullable CatalogSchemaContract catalogSchema, @Nonnull EntitySchemaProvider entitySchemaAccessor) { Assert.isPremiseValid(catalogSchema != null, "Catalog schema is mandatory!"); if (catalogSchema.getCatalogEvolutionMode().containsAll(List.of(evolutionModes))) { // no need to change the schema - return catalogSchema; + return new CatalogSchemaWithImpactOnEntitySchemas(catalogSchema); } else { - return CatalogSchema._internalBuild( - catalogSchema.getVersion() + 1, - catalogSchema.getName(), - catalogSchema.getNameVariants(), - catalogSchema.getDescription(), - Stream.concat( - catalogSchema.getCatalogEvolutionMode().stream(), - Arrays.stream(evolutionModes) - ) - .collect(Collectors.toSet()), - catalogSchema.getAttributes(), - entitySchemaAccessor + return new CatalogSchemaWithImpactOnEntitySchemas( + CatalogSchema._internalBuild( + catalogSchema.getVersion() + 1, + catalogSchema.getName(), + catalogSchema.getNameVariants(), + catalogSchema.getDescription(), + Stream.concat( + catalogSchema.getCatalogEvolutionMode().stream(), + Arrays.stream(evolutionModes) + ) + .collect(Collectors.toSet()), + catalogSchema.getAttributes(), + entitySchemaAccessor + ) ); } } diff --git a/evita_api/src/main/java/io/evitadb/api/requestResponse/schema/mutation/catalog/CreateCatalogSchemaMutation.java b/evita_api/src/main/java/io/evitadb/api/requestResponse/schema/mutation/catalog/CreateCatalogSchemaMutation.java index 5e75a884eb..c804fcb21f 100644 --- a/evita_api/src/main/java/io/evitadb/api/requestResponse/schema/mutation/catalog/CreateCatalogSchemaMutation.java +++ b/evita_api/src/main/java/io/evitadb/api/requestResponse/schema/mutation/catalog/CreateCatalogSchemaMutation.java @@ -63,16 +63,18 @@ public CreateCatalogSchemaMutation(@Nonnull String catalogName) { @Nullable @Override - public CatalogSchemaContract mutate(@Nullable CatalogSchemaContract catalogSchema) { + public CatalogSchemaWithImpactOnEntitySchemas mutate(@Nullable CatalogSchemaContract catalogSchema) { Assert.isTrue( catalogSchema == null, () -> new InvalidSchemaMutationException("Catalog `" + catalogName + "` already exists!") ); - return CatalogSchema._internalBuild( - catalogName, - NamingConvention.generate(catalogName), - EnumSet.allOf(CatalogEvolutionMode.class), - MutationEntitySchemaAccessor.INSTANCE + return new CatalogSchemaWithImpactOnEntitySchemas( + CatalogSchema._internalBuild( + catalogName, + NamingConvention.generate(catalogName), + EnumSet.allOf(CatalogEvolutionMode.class), + MutationEntitySchemaAccessor.INSTANCE + ) ); } @@ -81,5 +83,5 @@ public String toString() { return "Create catalog: " + "catalogName='" + catalogName + '\''; } - + } diff --git a/evita_api/src/main/java/io/evitadb/api/requestResponse/schema/mutation/catalog/CreateEntitySchemaMutation.java b/evita_api/src/main/java/io/evitadb/api/requestResponse/schema/mutation/catalog/CreateEntitySchemaMutation.java index 2aac169879..5070a59789 100644 --- a/evita_api/src/main/java/io/evitadb/api/requestResponse/schema/mutation/catalog/CreateEntitySchemaMutation.java +++ b/evita_api/src/main/java/io/evitadb/api/requestResponse/schema/mutation/catalog/CreateEntitySchemaMutation.java @@ -64,11 +64,11 @@ public CreateEntitySchemaMutation(@Nonnull String name) { @Nullable @Override - public CatalogSchemaContract mutate(@Nullable CatalogSchemaContract catalogSchema, @Nonnull EntitySchemaProvider entitySchemaAccessor) { + public CatalogSchemaWithImpactOnEntitySchemas mutate(@Nullable CatalogSchemaContract catalogSchema, @Nonnull EntitySchemaProvider entitySchemaAccessor) { if (entitySchemaAccessor instanceof MutationEntitySchemaAccessor mutationEntitySchemaAccessor) { mutationEntitySchemaAccessor.addUpsertedEntitySchema(EntitySchema._internalBuild(name)); } - return catalogSchema; + return new CatalogSchemaWithImpactOnEntitySchemas(catalogSchema); } @Override diff --git a/evita_api/src/main/java/io/evitadb/api/requestResponse/schema/mutation/catalog/DisallowEvolutionModeInCatalogSchemaMutation.java b/evita_api/src/main/java/io/evitadb/api/requestResponse/schema/mutation/catalog/DisallowEvolutionModeInCatalogSchemaMutation.java index e81759aaf6..5e1c7f494a 100644 --- a/evita_api/src/main/java/io/evitadb/api/requestResponse/schema/mutation/catalog/DisallowEvolutionModeInCatalogSchemaMutation.java +++ b/evita_api/src/main/java/io/evitadb/api/requestResponse/schema/mutation/catalog/DisallowEvolutionModeInCatalogSchemaMutation.java @@ -70,23 +70,25 @@ public DisallowEvolutionModeInCatalogSchemaMutation(@Nonnull CatalogEvolutionMod @Nullable @Override - public CatalogSchemaContract mutate(@Nullable CatalogSchemaContract catalogSchema, @Nonnull EntitySchemaProvider entitySchemaAccessor) { + public CatalogSchemaWithImpactOnEntitySchemas mutate(@Nullable CatalogSchemaContract catalogSchema, @Nonnull EntitySchemaProvider entitySchemaAccessor) { Assert.isPremiseValid(catalogSchema != null, "Catalog schema is mandatory!"); if (catalogSchema.getCatalogEvolutionMode().stream().noneMatch(evolutionModes::contains)) { // no need to change the schema - return catalogSchema; + return new CatalogSchemaWithImpactOnEntitySchemas(catalogSchema); } else { - return CatalogSchema._internalBuild( - catalogSchema.getVersion() + 1, - catalogSchema.getName(), - catalogSchema.getNameVariants(), - catalogSchema.getDescription(), - catalogSchema.getCatalogEvolutionMode() - .stream() - .filter(it -> !this.evolutionModes.contains(it)) - .collect(Collectors.toSet()), - catalogSchema.getAttributes(), - entitySchemaAccessor + return new CatalogSchemaWithImpactOnEntitySchemas( + CatalogSchema._internalBuild( + catalogSchema.getVersion() + 1, + catalogSchema.getName(), + catalogSchema.getNameVariants(), + catalogSchema.getDescription(), + catalogSchema.getCatalogEvolutionMode() + .stream() + .filter(it -> !this.evolutionModes.contains(it)) + .collect(Collectors.toSet()), + catalogSchema.getAttributes(), + entitySchemaAccessor + ) ); } } diff --git a/evita_api/src/main/java/io/evitadb/api/requestResponse/schema/mutation/catalog/ModifyCatalogSchemaDescriptionMutation.java b/evita_api/src/main/java/io/evitadb/api/requestResponse/schema/mutation/catalog/ModifyCatalogSchemaDescriptionMutation.java index b1533e0ed5..488c925924 100644 --- a/evita_api/src/main/java/io/evitadb/api/requestResponse/schema/mutation/catalog/ModifyCatalogSchemaDescriptionMutation.java +++ b/evita_api/src/main/java/io/evitadb/api/requestResponse/schema/mutation/catalog/ModifyCatalogSchemaDescriptionMutation.java @@ -72,23 +72,25 @@ public MutationCombinationResult combineWith(@Nonnul @Nullable @Override - public CatalogSchemaContract mutate(@Nullable CatalogSchemaContract catalogSchema, @Nonnull EntitySchemaProvider entitySchemaAccessor) { + public CatalogSchemaWithImpactOnEntitySchemas mutate(@Nullable CatalogSchemaContract catalogSchema, @Nonnull EntitySchemaProvider entitySchemaAccessor) { Assert.notNull( catalogSchema, () -> new InvalidSchemaMutationException("Catalog doesn't exist!") ); if (Objects.equals(description, catalogSchema.getDescription())) { // nothing has changed - we can return existing schema - return catalogSchema; + return new CatalogSchemaWithImpactOnEntitySchemas(catalogSchema); } else { - return CatalogSchema._internalBuild( - catalogSchema.getVersion() + 1, - catalogSchema.getName(), - catalogSchema.getNameVariants(), - description, - catalogSchema.getCatalogEvolutionMode(), - catalogSchema.getAttributes(), - entitySchemaAccessor + return new CatalogSchemaWithImpactOnEntitySchemas( + CatalogSchema._internalBuild( + catalogSchema.getVersion() + 1, + catalogSchema.getName(), + catalogSchema.getNameVariants(), + description, + catalogSchema.getCatalogEvolutionMode(), + catalogSchema.getAttributes(), + entitySchemaAccessor + ) ); } } diff --git a/evita_api/src/main/java/io/evitadb/api/requestResponse/schema/mutation/catalog/ModifyCatalogSchemaMutation.java b/evita_api/src/main/java/io/evitadb/api/requestResponse/schema/mutation/catalog/ModifyCatalogSchemaMutation.java index a719e6a493..df4d03a8e2 100644 --- a/evita_api/src/main/java/io/evitadb/api/requestResponse/schema/mutation/catalog/ModifyCatalogSchemaMutation.java +++ b/evita_api/src/main/java/io/evitadb/api/requestResponse/schema/mutation/catalog/ModifyCatalogSchemaMutation.java @@ -26,6 +26,7 @@ import io.evitadb.api.requestResponse.schema.CatalogSchemaContract; import io.evitadb.api.requestResponse.schema.mutation.LocalCatalogSchemaMutation; import io.evitadb.api.requestResponse.schema.mutation.TopLevelCatalogSchemaMutation; +import io.evitadb.utils.ArrayUtils; import lombok.EqualsAndHashCode; import lombok.Getter; @@ -58,12 +59,18 @@ public ModifyCatalogSchemaMutation(@Nonnull String catalogName, @Nonnull LocalCa @Nullable @Override - public CatalogSchemaContract mutate(@Nullable CatalogSchemaContract catalogSchema) { - CatalogSchemaContract alteredSchema = catalogSchema; + public CatalogSchemaWithImpactOnEntitySchemas mutate(@Nullable CatalogSchemaContract catalogSchema) { + CatalogSchemaWithImpactOnEntitySchemas alteredSchema = new CatalogSchemaWithImpactOnEntitySchemas(catalogSchema); + ModifyEntitySchemaMutation[] aggregatedMutations = null; for (LocalCatalogSchemaMutation schemaMutation : schemaMutations) { - alteredSchema = schemaMutation.mutate(alteredSchema); + alteredSchema = schemaMutation.mutate(alteredSchema.updatedCatalogSchema(), catalogSchema); + if (alteredSchema.entitySchemaMutations() != null) { + aggregatedMutations = aggregatedMutations == null ? + alteredSchema.entitySchemaMutations() : + ArrayUtils.mergeArrays(aggregatedMutations, alteredSchema.entitySchemaMutations()); + } } - return alteredSchema; + return new CatalogSchemaWithImpactOnEntitySchemas(alteredSchema.updatedCatalogSchema(), aggregatedMutations); } @Override diff --git a/evita_api/src/main/java/io/evitadb/api/requestResponse/schema/mutation/catalog/ModifyCatalogSchemaNameMutation.java b/evita_api/src/main/java/io/evitadb/api/requestResponse/schema/mutation/catalog/ModifyCatalogSchemaNameMutation.java index 2f02d7de82..503dcc6094 100644 --- a/evita_api/src/main/java/io/evitadb/api/requestResponse/schema/mutation/catalog/ModifyCatalogSchemaNameMutation.java +++ b/evita_api/src/main/java/io/evitadb/api/requestResponse/schema/mutation/catalog/ModifyCatalogSchemaNameMutation.java @@ -61,23 +61,25 @@ public class ModifyCatalogSchemaNameMutation implements TopLevelCatalogSchemaMut @Nullable @Override - public CatalogSchemaContract mutate(@Nullable CatalogSchemaContract catalogSchema) { + public CatalogSchemaWithImpactOnEntitySchemas mutate(@Nullable CatalogSchemaContract catalogSchema) { Assert.notNull( catalogSchema, () -> new InvalidSchemaMutationException("Catalog doesn't exist!") ); if (newCatalogName.equals(catalogSchema.getName())) { // nothing has changed - we can return existing schema - return catalogSchema; + return new CatalogSchemaWithImpactOnEntitySchemas(catalogSchema); } else { - return CatalogSchema._internalBuild( - catalogSchema.getVersion() + 1, - newCatalogName, - NamingConvention.generate(newCatalogName), - catalogSchema.getDescription(), - catalogSchema.getCatalogEvolutionMode(), - catalogSchema.getAttributes(), - MutationEntitySchemaAccessor.INSTANCE + return new CatalogSchemaWithImpactOnEntitySchemas( + CatalogSchema._internalBuild( + catalogSchema.getVersion() + 1, + newCatalogName, + NamingConvention.generate(newCatalogName), + catalogSchema.getDescription(), + catalogSchema.getCatalogEvolutionMode(), + catalogSchema.getAttributes(), + MutationEntitySchemaAccessor.INSTANCE + ) ); } } diff --git a/evita_api/src/main/java/io/evitadb/api/requestResponse/schema/mutation/catalog/ModifyEntitySchemaMutation.java b/evita_api/src/main/java/io/evitadb/api/requestResponse/schema/mutation/catalog/ModifyEntitySchemaMutation.java index 03b92483ea..785caa6150 100644 --- a/evita_api/src/main/java/io/evitadb/api/requestResponse/schema/mutation/catalog/ModifyEntitySchemaMutation.java +++ b/evita_api/src/main/java/io/evitadb/api/requestResponse/schema/mutation/catalog/ModifyEntitySchemaMutation.java @@ -93,7 +93,7 @@ public MutationCombinationResult combineWith(@Nonnul @Nullable @Override - public CatalogSchemaContract mutate(@Nullable CatalogSchemaContract catalogSchema, @Nonnull EntitySchemaProvider entitySchemaAccessor) { + public CatalogSchemaWithImpactOnEntitySchemas mutate(@Nullable CatalogSchemaContract catalogSchema, @Nonnull EntitySchemaProvider entitySchemaAccessor) { if (entitySchemaAccessor instanceof MutationEntitySchemaAccessor mutationEntitySchemaAccessor) { mutationEntitySchemaAccessor .getEntitySchema(entityType).map(it -> mutate(catalogSchema, it)) @@ -105,7 +105,9 @@ public CatalogSchemaContract mutate(@Nullable CatalogSchemaContract catalogSchem ); } // do nothing - we alter only the entity schema - return catalogSchema; + return new CatalogSchemaWithImpactOnEntitySchemas( + catalogSchema + ); } @Nullable diff --git a/evita_api/src/main/java/io/evitadb/api/requestResponse/schema/mutation/catalog/ModifyEntitySchemaNameMutation.java b/evita_api/src/main/java/io/evitadb/api/requestResponse/schema/mutation/catalog/ModifyEntitySchemaNameMutation.java index 5d52538736..798fb25b35 100644 --- a/evita_api/src/main/java/io/evitadb/api/requestResponse/schema/mutation/catalog/ModifyEntitySchemaNameMutation.java +++ b/evita_api/src/main/java/io/evitadb/api/requestResponse/schema/mutation/catalog/ModifyEntitySchemaNameMutation.java @@ -68,7 +68,7 @@ public class ModifyEntitySchemaNameMutation implements LocalCatalogSchemaMutatio @Nullable @Override - public CatalogSchemaContract mutate(@Nullable CatalogSchemaContract catalogSchema, @Nonnull EntitySchemaProvider entitySchemaAccessor) { + public CatalogSchemaWithImpactOnEntitySchemas mutate(@Nullable CatalogSchemaContract catalogSchema, @Nonnull EntitySchemaProvider entitySchemaAccessor) { if (entitySchemaAccessor instanceof MutationEntitySchemaAccessor mutationEntitySchemaAccessor) { mutationEntitySchemaAccessor .getEntitySchema(name).map(it -> mutate(catalogSchema, it)) @@ -80,7 +80,7 @@ public CatalogSchemaContract mutate(@Nullable CatalogSchemaContract catalogSchem ); } // do nothing - we alter only the entity schema - return catalogSchema; + return new CatalogSchemaWithImpactOnEntitySchemas(catalogSchema); } @Nullable diff --git a/evita_api/src/main/java/io/evitadb/api/requestResponse/schema/mutation/catalog/RemoveCatalogSchemaMutation.java b/evita_api/src/main/java/io/evitadb/api/requestResponse/schema/mutation/catalog/RemoveCatalogSchemaMutation.java index 5ea185e756..cff482b920 100644 --- a/evita_api/src/main/java/io/evitadb/api/requestResponse/schema/mutation/catalog/RemoveCatalogSchemaMutation.java +++ b/evita_api/src/main/java/io/evitadb/api/requestResponse/schema/mutation/catalog/RemoveCatalogSchemaMutation.java @@ -54,7 +54,7 @@ public class RemoveCatalogSchemaMutation implements TopLevelCatalogSchemaMutatio @Nullable @Override - public CatalogSchemaContract mutate(@Nullable CatalogSchemaContract catalogSchema) { + public CatalogSchemaWithImpactOnEntitySchemas mutate(@Nullable CatalogSchemaContract catalogSchema) { Assert.notNull( catalogSchema, () -> new InvalidSchemaMutationException("Catalog `" + catalogName + "` doesn't exist!") diff --git a/evita_api/src/main/java/io/evitadb/api/requestResponse/schema/mutation/catalog/RemoveEntitySchemaMutation.java b/evita_api/src/main/java/io/evitadb/api/requestResponse/schema/mutation/catalog/RemoveEntitySchemaMutation.java index dcf496efac..facce38562 100644 --- a/evita_api/src/main/java/io/evitadb/api/requestResponse/schema/mutation/catalog/RemoveEntitySchemaMutation.java +++ b/evita_api/src/main/java/io/evitadb/api/requestResponse/schema/mutation/catalog/RemoveEntitySchemaMutation.java @@ -58,7 +58,7 @@ public class RemoveEntitySchemaMutation implements LocalCatalogSchemaMutation, C @Nullable @Override - public CatalogSchemaContract mutate(@Nullable CatalogSchemaContract catalogSchema, @Nonnull EntitySchemaProvider entitySchemaAccessor) { + public CatalogSchemaWithImpactOnEntitySchemas mutate(@Nullable CatalogSchemaContract catalogSchema, @Nonnull EntitySchemaProvider entitySchemaAccessor) { if (entitySchemaAccessor instanceof MutationEntitySchemaAccessor mutationEntitySchemaAccessor) { mutationEntitySchemaAccessor .getEntitySchema(name) @@ -70,7 +70,7 @@ public CatalogSchemaContract mutate(@Nullable CatalogSchemaContract catalogSchem ); } // do nothing - we alter only the entity schema - return catalogSchema; + return new CatalogSchemaWithImpactOnEntitySchemas(catalogSchema); } @Override diff --git a/evita_common/src/main/java/io/evitadb/utils/ArrayUtils.java b/evita_common/src/main/java/io/evitadb/utils/ArrayUtils.java index 20aa27f039..474e5bb9a1 100644 --- a/evita_common/src/main/java/io/evitadb/utils/ArrayUtils.java +++ b/evita_common/src/main/java/io/evitadb/utils/ArrayUtils.java @@ -803,8 +803,8 @@ public static T[] mergeArrays(@Nonnull T[]... array) { throw new IllegalArgumentException("Empty argument is not allowed!"); } int resultSize = 0; - for (T[] configItem : array) { - resultSize = resultSize + configItem.length; + for (T[] arrayItem : array) { + resultSize = resultSize + arrayItem.length; } int offset = 0; @SuppressWarnings({"unchecked"}) diff --git a/evita_engine/src/main/java/io/evitadb/core/Catalog.java b/evita_engine/src/main/java/io/evitadb/core/Catalog.java index bf9fef648b..0548619911 100644 --- a/evita_engine/src/main/java/io/evitadb/core/Catalog.java +++ b/evita_engine/src/main/java/io/evitadb/core/Catalog.java @@ -50,6 +50,7 @@ import io.evitadb.api.requestResponse.schema.dto.EntitySchema; import io.evitadb.api.requestResponse.schema.dto.EntitySchemaProvider; import io.evitadb.api.requestResponse.schema.mutation.CatalogSchemaMutation; +import io.evitadb.api.requestResponse.schema.mutation.CatalogSchemaMutation.CatalogSchemaWithImpactOnEntitySchemas; import io.evitadb.api.requestResponse.schema.mutation.LocalCatalogSchemaMutation; import io.evitadb.api.requestResponse.schema.mutation.catalog.CreateEntitySchemaMutation; import io.evitadb.api.requestResponse.schema.mutation.catalog.ModifyEntitySchemaMutation; @@ -89,6 +90,7 @@ import io.evitadb.store.spi.operation.RemoveCollectionOperation; import io.evitadb.store.spi.operation.RemoveStoragePartOperation; import io.evitadb.store.spi.operation.RenameCollectionOperation; +import io.evitadb.utils.ArrayUtils; import io.evitadb.utils.Assert; import io.evitadb.utils.ClassUtils; import io.evitadb.utils.ReflectionLookup; @@ -400,6 +402,7 @@ public SealedCatalogSchema getSchema() { public CatalogSchemaContract updateSchema(@Nonnull EvitaSessionContract session, @Nonnull LocalCatalogSchemaMutation... schemaMutation) throws SchemaAlteringException { // internal schema is expected to be produced on the server side final CatalogSchema currentSchema = getInternalSchema(); + ModifyEntitySchemaMutation[] modifyEntitySchemaMutations = null; CatalogSchemaContract updatedSchema = currentSchema; for (CatalogSchemaMutation theMutation : schemaMutation) { // if the mutation implements entity schema mutation apply it on the appropriate schema @@ -449,12 +452,21 @@ public CatalogSchemaContract updateSchema(@Nonnull EvitaSessionContract session, updatedSchema, getEntitySchemaAccessor() ); - } else if (theMutation instanceof LocalCatalogSchemaMutation localCatalogSchemaMutation) { - updatedSchema = Objects.requireNonNull( - localCatalogSchemaMutation.mutate(updatedSchema, getEntitySchemaAccessor()) - ); } else { - updatedSchema = Objects.requireNonNull(theMutation.mutate(updatedSchema)); + final CatalogSchemaWithImpactOnEntitySchemas schemaWithImpactOnEntitySchemas; + if (theMutation instanceof LocalCatalogSchemaMutation localCatalogSchemaMutation) { + schemaWithImpactOnEntitySchemas = localCatalogSchemaMutation.mutate(updatedSchema, getEntitySchemaAccessor()); + } else { + schemaWithImpactOnEntitySchemas = theMutation.mutate(updatedSchema); + } + Assert.isPremiseValid( + schemaWithImpactOnEntitySchemas != null && schemaWithImpactOnEntitySchemas.updatedCatalogSchema() != null, + "Catalog schema mutation is expected to produce CatalogSchema instance!" + ); + updatedSchema = schemaWithImpactOnEntitySchemas.updatedCatalogSchema(); + modifyEntitySchemaMutations = modifyEntitySchemaMutations == null || ArrayUtils.isEmpty(schemaWithImpactOnEntitySchemas.entitySchemaMutations()) ? + schemaWithImpactOnEntitySchemas.entitySchemaMutations() : + ArrayUtils.mergeArrays(modifyEntitySchemaMutations, schemaWithImpactOnEntitySchemas.entitySchemaMutations()); } } final CatalogSchemaContract nextSchema = updatedSchema; @@ -472,6 +484,10 @@ public CatalogSchemaContract updateSchema(@Nonnull EvitaSessionContract session, ); this.dataStoreBuffer.update(new CatalogSchemaStoragePart(updatedInternalSchema)); } + // alter affected entity schemas + if (modifyEntitySchemaMutations != null) { + updateSchema(session, modifyEntitySchemaMutations); + } return getSchema(); } diff --git a/evita_engine/src/main/java/io/evitadb/core/Evita.java b/evita_engine/src/main/java/io/evitadb/core/Evita.java index 0f95979eed..3018609ed4 100644 --- a/evita_engine/src/main/java/io/evitadb/core/Evita.java +++ b/evita_engine/src/main/java/io/evitadb/core/Evita.java @@ -504,7 +504,9 @@ public CatalogContract getCatalogInstanceOrThrowException(@Nonnull String catalo */ private void createCatalogInternal(@Nonnull CreateCatalogSchemaMutation createCatalogSchema) { final String catalogName = createCatalogSchema.getCatalogName(); - final CatalogSchemaContract catalogSchema = Objects.requireNonNull(createCatalogSchema.mutate(null)); + final CatalogSchemaContract catalogSchema = Objects.requireNonNull(createCatalogSchema.mutate(null)) + .updatedCatalogSchema(); + this.catalogs.compute( catalogName, (theCatalogName, existingCatalog) -> { @@ -590,7 +592,8 @@ private void doReplaceCatalogInternal( ) { try { final CatalogContract replacedCatalog = catalogToBeReplacedWith.replace( - modifyCatalogSchemaName.mutate(catalogToBeReplacedWith.getSchema()), + modifyCatalogSchemaName.mutate(catalogToBeReplacedWith.getSchema()) + .updatedCatalogSchema(), catalogToBeReplaced ); // now rewrite the original catalog with renamed contents so that the observers could access it diff --git a/evita_functional_tests/src/test/java/io/evitadb/core/EvitaTest.java b/evita_functional_tests/src/test/java/io/evitadb/core/EvitaTest.java index 58fadb8f4c..e6ba9a9239 100644 --- a/evita_functional_tests/src/test/java/io/evitadb/core/EvitaTest.java +++ b/evita_functional_tests/src/test/java/io/evitadb/core/EvitaTest.java @@ -49,7 +49,12 @@ import io.evitadb.api.requestResponse.schema.AttributeSchemaContract; import io.evitadb.api.requestResponse.schema.AttributeSchemaEditor; import io.evitadb.api.requestResponse.schema.Cardinality; +import io.evitadb.api.requestResponse.schema.EntityAttributeSchemaContract; +import io.evitadb.api.requestResponse.schema.GlobalAttributeSchemaContract; +import io.evitadb.api.requestResponse.schema.GlobalAttributeSchemaEditor; +import io.evitadb.api.requestResponse.schema.SealedCatalogSchema; import io.evitadb.api.requestResponse.schema.SealedEntitySchema; +import io.evitadb.api.requestResponse.schema.dto.GlobalAttributeUniquenessType; import io.evitadb.api.requestResponse.schema.mutation.catalog.ModifyEntitySchemaMutation; import io.evitadb.core.exception.AttributeNotFilterableException; import io.evitadb.core.exception.AttributeNotSortableException; @@ -803,6 +808,44 @@ void shouldCreateAndDropCollectionsInTransaction() { }); } + @Test + void shouldUpdateEntitySchemaAttributeDefinitionsReferingToGlobalOnes() { + evita.updateCatalog( + TEST_CATALOG, + session -> { + session.getCatalogSchema() + .openForWrite() + .withAttribute(ATTRIBUTE_URL, String.class, whichIs -> whichIs.localized().uniqueGlobally()) + .updateVia(session); + + session + .defineEntitySchema(Entities.PRODUCT) + .withGlobalAttribute(ATTRIBUTE_URL) + .withAttribute(ATTRIBUTE_NAME, String.class, AttributeSchemaEditor::localized) + .updateVia(session); + + final EntityAttributeSchemaContract firstAttribute = session.getEntitySchemaOrThrow(Entities.PRODUCT).getAttribute(ATTRIBUTE_URL).orElseThrow(); + assertTrue(firstAttribute instanceof GlobalAttributeSchemaContract); + assertTrue(firstAttribute.isLocalized()); + assertEquals(GlobalAttributeUniquenessType.UNIQUE_WITHIN_CATALOG, ((GlobalAttributeSchemaContract)firstAttribute).getGlobalUniquenessType()); + + session.getCatalogSchema() + .openForWrite() + .withAttribute(ATTRIBUTE_URL, String.class, GlobalAttributeSchemaEditor::uniqueGloballyWithinLocale) + .updateVia(session); + + final SealedCatalogSchema catalogSchema = session.getCatalogSchema(); + assertTrue(catalogSchema.getAttribute(ATTRIBUTE_URL).isPresent()); + assertEquals(GlobalAttributeUniquenessType.UNIQUE_WITHIN_CATALOG_LOCALE, catalogSchema.getAttribute(ATTRIBUTE_URL).orElseThrow().getGlobalUniquenessType()); + + final EntityAttributeSchemaContract secondAttribute = session.getEntitySchemaOrThrow(Entities.PRODUCT).getAttribute(ATTRIBUTE_URL).orElseThrow(); + assertTrue(secondAttribute instanceof GlobalAttributeSchemaContract); + assertTrue(secondAttribute.isLocalized()); + assertEquals(GlobalAttributeUniquenessType.UNIQUE_WITHIN_CATALOG_LOCALE, ((GlobalAttributeSchemaContract)secondAttribute).getGlobalUniquenessType()); + } + ); + } + @Test void shouldFetchEntityByLocalizedGlobalAttributeAutomaticallySelectingProperLocale() { evita.updateCatalog( diff --git a/evita_query/src/main/java/io/evitadb/api/query/parser/grammar/EvitaQLLexer.java b/evita_query/src/main/java/io/evitadb/api/query/parser/grammar/EvitaQLLexer.java index a1ba7492b9..d72609559c 100644 --- a/evita_query/src/main/java/io/evitadb/api/query/parser/grammar/EvitaQLLexer.java +++ b/evita_query/src/main/java/io/evitadb/api/query/parser/grammar/EvitaQLLexer.java @@ -1,38 +1,17 @@ -/* - * - * _ _ ____ ____ - * _____ _(_) |_ __ _| _ \| __ ) - * / _ \ \ / / | __/ _` | | | | _ \ - * | __/\ V /| | || (_| | |_| | |_) | - * \___| \_/ |_|\__\__,_|____/|____/ - * - * Copyright (c) 2023 - * - * Licensed under the Business Source License, Version 1.1 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://github.com/FgForrest/evitaDB/blob/main/LICENSE - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - // Generated from EvitaQL.g4 by ANTLR 4.9.2 package io.evitadb.api.query.parser.grammar; -import org.antlr.v4.runtime.Lexer; import org.antlr.v4.runtime.CharStream; -import org.antlr.v4.runtime.Token; -import org.antlr.v4.runtime.TokenStream; -import org.antlr.v4.runtime.*; -import org.antlr.v4.runtime.atn.*; +import org.antlr.v4.runtime.Lexer; +import org.antlr.v4.runtime.RuntimeMetaData; +import org.antlr.v4.runtime.Vocabulary; +import org.antlr.v4.runtime.VocabularyImpl; +import org.antlr.v4.runtime.atn.ATN; +import org.antlr.v4.runtime.atn.ATNDeserializer; +import org.antlr.v4.runtime.atn.LexerATNSimulator; +import org.antlr.v4.runtime.atn.PredictionContextCache; import org.antlr.v4.runtime.dfa.DFA; -import org.antlr.v4.runtime.misc.*; @SuppressWarnings({"all", "warnings", "unchecked", "unused", "cast"}) public class EvitaQLLexer extends Lexer {