diff --git a/core/src/main/java/org/apache/iceberg/view/ViewMetadata.java b/core/src/main/java/org/apache/iceberg/view/ViewMetadata.java index 0715b8c0c465..2764d9053985 100644 --- a/core/src/main/java/org/apache/iceberg/view/ViewMetadata.java +++ b/core/src/main/java/org/apache/iceberg/view/ViewMetadata.java @@ -19,6 +19,7 @@ package org.apache.iceberg.view; import java.io.Serializable; +import java.util.Comparator; import java.util.List; import java.util.Map; import java.util.Set; @@ -28,6 +29,7 @@ import org.apache.iceberg.Schema; import org.apache.iceberg.exceptions.ValidationException; import org.apache.iceberg.relocated.com.google.common.base.Preconditions; +import org.apache.iceberg.relocated.com.google.common.collect.ImmutableList; import org.apache.iceberg.relocated.com.google.common.collect.ImmutableMap; import org.apache.iceberg.relocated.com.google.common.collect.Lists; import org.apache.iceberg.relocated.com.google.common.collect.Maps; @@ -92,12 +94,22 @@ default ViewVersion currentVersion() { @Value.Derived default Map versionsById() { - return Builder.indexVersions(versions()); + ImmutableMap.Builder builder = ImmutableMap.builder(); + for (ViewVersion version : versions()) { + builder.put(version.versionId(), version); + } + + return builder.build(); } @Value.Derived default Map schemasById() { - return Builder.indexSchemas(schemas()); + ImmutableMap.Builder builder = ImmutableMap.builder(); + for (Schema schema : schemas()) { + builder.put(schema.schemaId(), schema); + } + + return builder.build(); } default Schema schema() { @@ -124,127 +136,126 @@ static Builder buildFrom(ViewMetadata base) { class Builder { private static final int LAST_ADDED = -1; + private final List versions; + private final List schemas; + private final List history; + private final Map properties; + private final List changes; private int formatVersion = DEFAULT_VIEW_FORMAT_VERSION; - private String location; - private List schemas = Lists.newArrayList(); private int currentVersionId; - private Integer lastAddedVersionId; - private Integer lastAddedSchemaId; - private List versions = Lists.newArrayList(); - private List history = Lists.newArrayList(); - private Map properties = Maps.newHashMap(); - private List changes = Lists.newArrayList(); + private String location; - private Builder() {} + // internal change tracking + private Integer lastAddedVersionId = null; + + // indexes + private final Map versionsById; + private final Map schemasById; + + private Builder() { + this.versions = Lists.newArrayList(); + this.versionsById = Maps.newHashMap(); + this.schemas = Lists.newArrayList(); + this.schemasById = Maps.newHashMap(); + this.history = Lists.newArrayList(); + this.properties = Maps.newHashMap(); + this.changes = Lists.newArrayList(); + } private Builder(ViewMetadata base) { - this.formatVersion = base.formatVersion(); - this.location = base.location(); - this.schemas = Lists.newArrayList(base.schemas()); - this.currentVersionId = base.currentVersionId(); this.versions = Lists.newArrayList(base.versions()); + this.versionsById = Maps.newHashMap(base.versionsById()); + this.schemas = Lists.newArrayList(base.schemas()); + this.schemasById = Maps.newHashMap(base.schemasById()); this.history = Lists.newArrayList(base.history()); this.properties = Maps.newHashMap(base.properties()); - this.changes = Lists.newArrayList(base.changes()); + this.changes = Lists.newArrayList(); + this.formatVersion = base.formatVersion(); + this.currentVersionId = base.currentVersionId(); + this.location = base.location(); } public Builder upgradeFormatVersion(int newFormatVersion) { Preconditions.checkArgument( - newFormatVersion >= this.formatVersion, + newFormatVersion >= formatVersion, "Cannot downgrade v%s view to v%s", formatVersion, newFormatVersion); - if (this.formatVersion == newFormatVersion) { + if (formatVersion == newFormatVersion) { return this; } this.formatVersion = newFormatVersion; - this.changes.add(new MetadataUpdate.UpgradeFormatVersion(newFormatVersion)); + changes.add(new MetadataUpdate.UpgradeFormatVersion(newFormatVersion)); return this; } public Builder setLocation(String newLocation) { Preconditions.checkArgument(null != newLocation, "Invalid location: null"); - if (null != this.location && this.location.equals(newLocation)) { + if (null != location && location.equals(newLocation)) { return this; } this.location = newLocation; - this.changes.add(new MetadataUpdate.SetLocation(newLocation)); + changes.add(new MetadataUpdate.SetLocation(newLocation)); return this; } public Builder setCurrentVersionId(int newVersionId) { - if (newVersionId == -1) { + if (newVersionId == LAST_ADDED) { ValidationException.check( lastAddedVersionId != null, "Cannot set last version id: no current version id has been set"); return setCurrentVersionId(lastAddedVersionId); } - if (this.currentVersionId == newVersionId) { + if (currentVersionId == newVersionId) { return this; } - checkCurrentVersionIdIsValid(newVersionId); - - // by that time, schemas are defined and the highestFieldId can be determined and schema - // changes can be added - int highestFieldId = highestFieldId(); - for (Schema schema : schemas) { - this.changes.add(new MetadataUpdate.AddSchema(schema, highestFieldId)); - } + ViewVersion version = versionsById.get(newVersionId); + Preconditions.checkArgument( + version != null, "Cannot set current version to unknown version: %s", newVersionId); this.currentVersionId = newVersionId; if (lastAddedVersionId != null && lastAddedVersionId == newVersionId) { - this.changes.add(new MetadataUpdate.SetCurrentViewVersion(LAST_ADDED)); + changes.add(new MetadataUpdate.SetCurrentViewVersion(LAST_ADDED)); } else { - this.changes.add(new MetadataUpdate.SetCurrentViewVersion(newVersionId)); + changes.add(new MetadataUpdate.SetCurrentViewVersion(newVersionId)); } return this; } - private int highestFieldId() { - return schemas.stream().map(Schema::highestFieldId).max(Integer::compareTo).orElse(0); - } - - public Builder setCurrentVersion(ViewVersion version) { - Schema schema = indexSchemas(schemas).get(version.schemaId()); + public Builder setCurrentVersion(ViewVersion version, Schema schema) { int newSchemaId = addSchemaInternal(schema); - return setCurrentVersionId( - addVersionInternal( - ImmutableViewVersion.builder().from(version).schemaId(newSchemaId).build())); + ViewVersion newVersion = + ImmutableViewVersion.builder().from(version).schemaId(newSchemaId).build(); + return setCurrentVersionId(addVersionInternal(newVersion)); } - private int reuseOrCreateNewViewVersionId(ViewVersion viewVersion) { - // if the view version already exists, use its id; otherwise use the highest id + 1 - int newVersionId = viewVersion.versionId(); - for (ViewVersion version : versions) { - if (version.equals(viewVersion)) { - return version.versionId(); - } else if (version.versionId() >= newVersionId) { - newVersionId = viewVersion.versionId() + 1; - } - } - - return newVersionId; + public Builder addVersion(ViewVersion version) { + addVersionInternal(version); + return this; } private int addVersionInternal(ViewVersion version) { int newVersionId = reuseOrCreateNewViewVersionId(version); - - if (versions.stream().anyMatch(v -> v.versionId() == newVersionId)) { - boolean isNewVersion = - lastAddedVersionId != null - && changes(MetadataUpdate.AddViewVersion.class) - .anyMatch(added -> added.viewVersion().versionId() == newVersionId); - this.lastAddedVersionId = isNewVersion ? newVersionId : null; + if (versionsById.containsKey(newVersionId)) { + boolean addedInBuilder = + changes(MetadataUpdate.AddViewVersion.class) + .anyMatch(added -> added.viewVersion().versionId() == newVersionId); + this.lastAddedVersionId = addedInBuilder ? newVersionId : null; return newVersionId; } + Preconditions.checkArgument( + schemasById.containsKey(version.schemaId()), + "Cannot add version with unknown schema: %s", + version.schemaId()); + ViewVersion newVersion; if (newVersionId != version.versionId()) { newVersion = ImmutableViewVersion.builder().from(version).versionId(newVersionId).build(); @@ -252,34 +263,43 @@ && changes(MetadataUpdate.AddViewVersion.class) newVersion = version; } - this.versions.add(newVersion); - this.changes.add(new MetadataUpdate.AddViewVersion(newVersion)); - this.history.add( + versions.add(newVersion); + versionsById.put(newVersion.versionId(), newVersion); + changes.add(new MetadataUpdate.AddViewVersion(newVersion)); + history.add( ImmutableViewHistoryEntry.builder() .timestampMillis(newVersion.timestampMillis()) .versionId(newVersion.versionId()) .build()); + this.lastAddedVersionId = newVersionId; return newVersionId; } - private int addSchemaInternal(Schema schema) { - if (schema.schemaId() == -1) { - ValidationException.check( - lastAddedSchemaId != null, "Cannot set last added schema: no schema has been added"); - - return addSchemaInternal( - new Schema(lastAddedSchemaId, schema.columns(), schema.identifierFieldIds())); + private int reuseOrCreateNewViewVersionId(ViewVersion viewVersion) { + // if the view version already exists, use its id; otherwise use the highest id + 1 + int newVersionId = viewVersion.versionId(); + for (ViewVersion version : versions) { + if (version.equals(viewVersion)) { + return version.versionId(); + } else if (version.versionId() >= newVersionId) { + newVersionId = viewVersion.versionId() + 1; + } } + return newVersionId; + } + + public Builder addSchema(Schema schema) { + addSchemaInternal(schema); + return this; + } + + private int addSchemaInternal(Schema schema) { int newSchemaId = reuseOrCreateNewSchemaId(schema); - if (schemas.stream().anyMatch(s -> s.schemaId() == newSchemaId)) { - boolean isNewSchema = - lastAddedSchemaId != null - && changes(MetadataUpdate.AddSchema.class) - .anyMatch(added -> added.schema().schemaId() == newSchemaId); - this.lastAddedSchemaId = isNewSchema ? newSchemaId : null; + if (schemasById.containsKey(newSchemaId)) { + // this schema existed or was already added in the builder return newSchemaId; } @@ -290,14 +310,18 @@ && changes(MetadataUpdate.AddSchema.class) newSchema = schema; } - this.schemas.add(newSchema); - // AddSchema changes can only be added once all schemas are known, thus this is done in - // setCurrentVersionId(..) - this.lastAddedSchemaId = newSchemaId; + int highestFieldId = Math.max(highestFieldId(), newSchema.highestFieldId()); + schemas.add(newSchema); + schemasById.put(newSchema.schemaId(), newSchema); + changes.add(new MetadataUpdate.AddSchema(newSchema, highestFieldId)); return newSchemaId; } + private int highestFieldId() { + return schemas.stream().map(Schema::highestFieldId).max(Integer::compareTo).orElse(0); + } + private int reuseOrCreateNewSchemaId(Schema newSchema) { // if the schema already exists, use its id; otherwise use the highest id + 1 int newSchemaId = newSchema.schemaId(); @@ -312,23 +336,13 @@ private int reuseOrCreateNewSchemaId(Schema newSchema) { return newSchemaId; } - public Builder addSchema(Schema schema) { - addSchemaInternal(schema); - return this; - } - - public Builder addVersion(ViewVersion version) { - addVersionInternal(version); - return this; - } - public Builder setProperties(Map updated) { if (updated.isEmpty()) { return this; } - this.properties.putAll(updated); - this.changes.add(new MetadataUpdate.SetProperties(updated)); + properties.putAll(updated); + changes.add(new MetadataUpdate.SetProperties(updated)); return this; } @@ -337,95 +351,80 @@ public Builder removeProperties(Set propertiesToRemove) { return this; } - propertiesToRemove.forEach(this.properties::remove); - this.changes.add(new MetadataUpdate.RemoveProperties(propertiesToRemove)); + propertiesToRemove.forEach(properties::remove); + changes.add(new MetadataUpdate.RemoveProperties(propertiesToRemove)); return this; } - private static Map indexVersions(List versionsToIndex) { - ImmutableMap.Builder builder = ImmutableMap.builder(); - for (ViewVersion version : versionsToIndex) { - builder.put(version.versionId(), version); - } - - return builder.build(); - } - - private static Map indexSchemas(List schemasToIndex) { - ImmutableMap.Builder builder = ImmutableMap.builder(); - for (Schema schema : schemasToIndex) { - builder.put(schema.schemaId(), schema); - } - - return builder.build(); - } - public ViewMetadata build() { Preconditions.checkArgument(null != location, "Invalid location: null"); Preconditions.checkArgument(versions.size() > 0, "Invalid view: no versions were added"); - checkCurrentVersionIdIsValid(currentVersionId); - - int versionHistorySizeToKeep = + int historySize = PropertyUtil.propertyAsInt( properties, ViewProperties.VERSION_HISTORY_SIZE, ViewProperties.VERSION_HISTORY_SIZE_DEFAULT); Preconditions.checkArgument( - versionHistorySizeToKeep > 0, + historySize > 0, "%s must be positive but was %s", ViewProperties.VERSION_HISTORY_SIZE, - versionHistorySizeToKeep); - - if (versions.size() > versionHistorySizeToKeep) { - List versionsToKeep = - versions.subList(versions.size() - versionHistorySizeToKeep, versions.size()); - List historyToKeep = - history.subList(history.size() - versionHistorySizeToKeep, history.size()); - List changesToKeep = Lists.newArrayList(changes); - Set toRemove = - changesToKeep.stream() - .filter(update -> update instanceof MetadataUpdate.AddViewVersion) - .map(update -> (MetadataUpdate.AddViewVersion) update) - .filter( - update -> - update.viewVersion().versionId() != currentVersionId - && !versionsToKeep.contains(update.viewVersion())) - .collect(Collectors.toSet()); - changesToKeep.removeAll(toRemove); - - versions = versionsToKeep; - history = historyToKeep; - changes = changesToKeep; + historySize); + + // expire old versions, but keep at least the versions added in this builder + int numAddedVersions = (int) changes(MetadataUpdate.AddViewVersion.class).count(); + int numVersionsToKeep = Math.max(numAddedVersions, historySize); + + List retainedVersions; + List retainedHistory; + if (versions.size() > numVersionsToKeep) { + retainedVersions = expireVersions(versionsById, numVersionsToKeep); + Set retainedVersionIds = + retainedVersions.stream().map(ViewVersion::versionId).collect(Collectors.toSet()); + retainedHistory = updateHistory(history, retainedVersionIds); + } else { + retainedVersions = versions; + retainedHistory = history; } return ImmutableViewMetadata.of( formatVersion, location, - schemas, + ImmutableList.copyOf(schemas), currentVersionId, - versions, - history, - properties, - changes); + ImmutableList.copyOf(retainedVersions), + ImmutableList.copyOf(retainedHistory), + ImmutableMap.copyOf(properties), + ImmutableList.copyOf(changes)); } - private void checkCurrentVersionIdIsValid(int versionId) { - Map versionsById = indexVersions(versions); - Preconditions.checkArgument( - versionsById.containsKey(versionId), - "Cannot find current version %s in view versions: %s", - versionId, - versionsById.keySet()); + static List expireVersions( + Map versionsById, int numVersionsToKeep) { + // version ids are assigned sequentially. keep the latest versions by ID. + List ids = Lists.newArrayList(versionsById.keySet()); + ids.sort(Comparator.reverseOrder()); - int currentSchemaId = versionsById.get(versionId).schemaId(); - Map schemasById = indexSchemas(schemas); - Preconditions.checkArgument( - schemasById.containsKey(currentSchemaId), - "Cannot find current schema with id %s in schemas: %s", - currentSchemaId, - schemasById.keySet()); + List retainedVersions = Lists.newArrayList(); + for (int idToKeep : ids.subList(0, numVersionsToKeep)) { + retainedVersions.add(versionsById.get(idToKeep)); + } + + return retainedVersions; + } + + static List updateHistory(List history, Set ids) { + List retainedHistory = Lists.newArrayList(); + for (ViewHistoryEntry entry : history) { + if (ids.contains(entry.versionId())) { + retainedHistory.add(entry); + } else { + // clear history past any unknown version + retainedHistory.clear(); + } + } + + return retainedHistory; } private Stream changes(Class updateClass) { diff --git a/core/src/test/java/org/apache/iceberg/view/TestViewMetadata.java b/core/src/test/java/org/apache/iceberg/view/TestViewMetadata.java index 015de78b7ead..34ecbab48380 100644 --- a/core/src/test/java/org/apache/iceberg/view/TestViewMetadata.java +++ b/core/src/test/java/org/apache/iceberg/view/TestViewMetadata.java @@ -21,8 +21,11 @@ import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatThrownBy; +import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableSet; import java.util.List; import java.util.Map; +import java.util.Set; import org.apache.iceberg.MetadataUpdate; import org.apache.iceberg.Schema; import org.apache.iceberg.catalog.Namespace; @@ -33,6 +36,47 @@ public class TestViewMetadata { + private ViewVersion newViewVersion(int id, String sql) { + return ImmutableViewVersion.builder() + .versionId(id) + .timestampMillis(System.currentTimeMillis()) + .defaultCatalog("prod") + .defaultNamespace(Namespace.of("default")) + .summary(ImmutableMap.of("operation", "create")) + .schemaId(1) + .build(); + } + + @Test + public void testExpiration() { + // purposely use versions and timestamps that do not match to check that version ID is used + ViewVersion v1 = newViewVersion(1, "select 1 as count"); + ViewVersion v3 = newViewVersion(3, "select count from t1"); + ViewVersion v2 = newViewVersion(2, "select count(1) as count from t2"); + Map versionsById = ImmutableMap.of(1, v1, 2, v2, 3, v3); + + List retainedVersions = ViewMetadata.Builder.expireVersions(versionsById, 2); + assertThat(retainedVersions).hasSameElementsAs(ImmutableList.of(v2, v3)); + } + + @Test + public void testUpdateHistory() { + ViewVersion v1 = newViewVersion(1, "select 1 as count"); + ViewVersion v2 = newViewVersion(2, "select count(1) as count from t2"); + ViewVersion v3 = newViewVersion(3, "select count from t1"); + + Set versionsById = ImmutableSet.of(2, 3); + + List history = ImmutableList.of( + ImmutableViewHistoryEntry.builder().versionId(v1.versionId()).timestampMillis(v1.timestampMillis()).build(), + ImmutableViewHistoryEntry.builder().versionId(v2.versionId()).timestampMillis(v2.timestampMillis()).build(), + ImmutableViewHistoryEntry.builder().versionId(v3.versionId()).timestampMillis(v3.timestampMillis()).build() + ); + + List retainedHistory = ViewMetadata.Builder.updateHistory(history, versionsById); + assertThat(retainedHistory).hasSameElementsAs(history.subList(1, 3)); + } + @Test public void nullAndMissingFields() { assertThatThrownBy(() -> ViewMetadata.builder().build()) @@ -46,7 +90,7 @@ public void nullAndMissingFields() { assertThatThrownBy( () -> ViewMetadata.builder().setLocation("location").setCurrentVersionId(1).build()) .isInstanceOf(IllegalArgumentException.class) - .hasMessage("Cannot find current version 1 in view versions: []"); + .hasMessage("Cannot set current version to unknown version: 1"); } @Test @@ -56,6 +100,8 @@ public void unsupportedFormatVersion() { ViewMetadata.builder() .upgradeFormatVersion(23) .setLocation("location") + .addSchema( + new Schema(1, Types.NestedField.required(1, "x", Types.LongType.get()))) .addVersion( ImmutableViewVersion.builder() .schemaId(1) @@ -64,8 +110,6 @@ public void unsupportedFormatVersion() { .putSummary("operation", "op") .defaultNamespace(Namespace.of("ns")) .build()) - .addSchema( - new Schema(1, Types.NestedField.required(1, "x", Types.LongType.get()))) .setCurrentVersionId(1) .build()) .isInstanceOf(IllegalArgumentException.class) @@ -87,7 +131,7 @@ public void emptyViewVersion() { assertThatThrownBy( () -> ViewMetadata.builder().setLocation("location").setCurrentVersionId(1).build()) .isInstanceOf(IllegalArgumentException.class) - .hasMessage("Cannot find current version 1 in view versions: []"); + .hasMessage("Cannot set current version to unknown version: 1"); } @Test @@ -107,7 +151,7 @@ public void emptySchemas() { .setCurrentVersionId(1) .build()) .isInstanceOf(IllegalArgumentException.class) - .hasMessage("Cannot find current schema with id 1 in schemas: []"); + .hasMessage("Cannot add version with unknown schema: 1"); } @Test @@ -116,6 +160,8 @@ public void invalidCurrentVersionId() { () -> ViewMetadata.builder() .setLocation("location") + .addSchema( + new Schema(1, Types.NestedField.required(1, "x", Types.LongType.get()))) .addVersion( ImmutableViewVersion.builder() .schemaId(1) @@ -124,12 +170,10 @@ public void invalidCurrentVersionId() { .putSummary("operation", "op") .defaultNamespace(Namespace.of("ns")) .build()) - .addSchema( - new Schema(1, Types.NestedField.required(1, "x", Types.LongType.get()))) .setCurrentVersionId(23) .build()) .isInstanceOf(IllegalArgumentException.class) - .hasMessage("Cannot find current version 23 in view versions: [1]"); + .hasMessage("Cannot set current version to unknown version: 23"); } @Test @@ -138,6 +182,8 @@ public void invalidCurrentSchemaId() { () -> ViewMetadata.builder() .setLocation("location") + .addSchema( + new Schema(1, Types.NestedField.required(1, "x", Types.LongType.get()))) .addVersion( ImmutableViewVersion.builder() .schemaId(23) @@ -146,12 +192,10 @@ public void invalidCurrentSchemaId() { .timestampMillis(23L) .putSummary("operation", "op") .build()) - .addSchema( - new Schema(1, Types.NestedField.required(1, "x", Types.LongType.get()))) .setCurrentVersionId(1) .build()) .isInstanceOf(IllegalArgumentException.class) - .hasMessage("Cannot find current schema with id 23 in schemas: [1]"); + .hasMessage("Cannot add version with unknown schema: 23"); } @Test @@ -161,6 +205,8 @@ public void invalidVersionHistorySizeToKeep() { ViewMetadata.builder() .setProperties(ImmutableMap.of(ViewProperties.VERSION_HISTORY_SIZE, "0")) .setLocation("location") + .addSchema( + new Schema(1, Types.NestedField.required(1, "x", Types.LongType.get()))) .addVersion( ImmutableViewVersion.builder() .schemaId(1) @@ -185,8 +231,6 @@ public void invalidVersionHistorySizeToKeep() { .putSummary("operation", "c") .defaultNamespace(Namespace.of("ns")) .build()) - .addSchema( - new Schema(1, Types.NestedField.required(1, "x", Types.LongType.get()))) .setCurrentVersionId(3) .build()) .isInstanceOf(IllegalArgumentException.class) @@ -221,24 +265,30 @@ public void viewHistoryNormalization() { .defaultNamespace(Namespace.of("ns")) .build(); - ViewMetadata viewMetadata = + ViewMetadata originalViewMetadata = ViewMetadata.builder() .setProperties(properties) .setLocation("location") + .addSchema(new Schema(1, Types.NestedField.required(1, "x", Types.LongType.get()))) .addVersion(viewVersionOne) .addVersion(viewVersionTwo) .addVersion(viewVersionThree) - .addSchema(new Schema(1, Types.NestedField.required(1, "x", Types.LongType.get()))) .setCurrentVersionId(3) .build(); + // the first build will not expire versions that were added in the builder + assertThat(originalViewMetadata.versions()).hasSize(3); + assertThat(originalViewMetadata.history()).hasSize(3); + + // rebuild the metadata to expire older versions + ViewMetadata viewMetadata = ViewMetadata.buildFrom(originalViewMetadata).build(); assertThat(viewMetadata.versions()).hasSize(2); assertThat(viewMetadata.history()).hasSize(2); // make sure that metadata changes reflect the current state after the history was adjusted, // meaning that the first view version shouldn't be included - List changes = viewMetadata.changes(); - assertThat(changes).hasSize(6); + List changes = originalViewMetadata.changes(); + assertThat(changes).hasSize(7); assertThat(changes) .element(0) .isInstanceOf(MetadataUpdate.SetProperties.class) @@ -255,28 +305,35 @@ public void viewHistoryNormalization() { assertThat(changes) .element(2) - .isInstanceOf(MetadataUpdate.AddViewVersion.class) - .asInstanceOf(InstanceOfAssertFactories.type(MetadataUpdate.AddViewVersion.class)) - .extracting(MetadataUpdate.AddViewVersion::viewVersion) - .isEqualTo(viewVersionTwo); + .isInstanceOf(MetadataUpdate.AddSchema.class) + .asInstanceOf(InstanceOfAssertFactories.type(MetadataUpdate.AddSchema.class)) + .extracting(MetadataUpdate.AddSchema::schema) + .extracting(Schema::schemaId) + .isEqualTo(1); assertThat(changes) .element(3) .isInstanceOf(MetadataUpdate.AddViewVersion.class) .asInstanceOf(InstanceOfAssertFactories.type(MetadataUpdate.AddViewVersion.class)) .extracting(MetadataUpdate.AddViewVersion::viewVersion) - .isEqualTo(viewVersionThree); + .isEqualTo(viewVersionOne); assertThat(changes) .element(4) - .isInstanceOf(MetadataUpdate.AddSchema.class) - .asInstanceOf(InstanceOfAssertFactories.type(MetadataUpdate.AddSchema.class)) - .extracting(MetadataUpdate.AddSchema::schema) - .extracting(Schema::schemaId) - .isEqualTo(1); + .isInstanceOf(MetadataUpdate.AddViewVersion.class) + .asInstanceOf(InstanceOfAssertFactories.type(MetadataUpdate.AddViewVersion.class)) + .extracting(MetadataUpdate.AddViewVersion::viewVersion) + .isEqualTo(viewVersionTwo); assertThat(changes) .element(5) + .isInstanceOf(MetadataUpdate.AddViewVersion.class) + .asInstanceOf(InstanceOfAssertFactories.type(MetadataUpdate.AddViewVersion.class)) + .extracting(MetadataUpdate.AddViewVersion::viewVersion) + .isEqualTo(viewVersionThree); + + assertThat(changes) + .element(6) .isInstanceOf(MetadataUpdate.SetCurrentViewVersion.class) .asInstanceOf(InstanceOfAssertFactories.type(MetadataUpdate.SetCurrentViewVersion.class)) .extracting(MetadataUpdate.SetCurrentViewVersion::versionId) @@ -317,11 +374,11 @@ public void viewMetadataAndMetadataChanges() { ViewMetadata.builder() .setLocation("custom-location") .setProperties(properties) + .addSchema(schemaOne) + .addSchema(schemaTwo) .addVersion(viewVersionOne) .addVersion(viewVersionTwo) .addVersion(viewVersionThree) - .addSchema(schemaOne) - .addSchema(schemaTwo) .setCurrentVersionId(3) .build(); @@ -356,41 +413,41 @@ public void viewMetadataAndMetadataChanges() { assertThat(changes) .element(2) + .isInstanceOf(MetadataUpdate.AddSchema.class) + .asInstanceOf(InstanceOfAssertFactories.type(MetadataUpdate.AddSchema.class)) + .extracting(MetadataUpdate.AddSchema::schema) + .extracting(Schema::schemaId) + .isEqualTo(1); + + assertThat(changes) + .element(3) + .isInstanceOf(MetadataUpdate.AddSchema.class) + .asInstanceOf(InstanceOfAssertFactories.type(MetadataUpdate.AddSchema.class)) + .extracting(MetadataUpdate.AddSchema::schema) + .extracting(Schema::schemaId) + .isEqualTo(2); + + assertThat(changes) + .element(4) .isInstanceOf(MetadataUpdate.AddViewVersion.class) .asInstanceOf(InstanceOfAssertFactories.type(MetadataUpdate.AddViewVersion.class)) .extracting(MetadataUpdate.AddViewVersion::viewVersion) .isEqualTo(viewVersionOne); assertThat(changes) - .element(3) + .element(5) .isInstanceOf(MetadataUpdate.AddViewVersion.class) .asInstanceOf(InstanceOfAssertFactories.type(MetadataUpdate.AddViewVersion.class)) .extracting(MetadataUpdate.AddViewVersion::viewVersion) .isEqualTo(viewVersionTwo); assertThat(changes) - .element(4) + .element(6) .isInstanceOf(MetadataUpdate.AddViewVersion.class) .asInstanceOf(InstanceOfAssertFactories.type(MetadataUpdate.AddViewVersion.class)) .extracting(MetadataUpdate.AddViewVersion::viewVersion) .isEqualTo(viewVersionThree); - assertThat(changes) - .element(5) - .isInstanceOf(MetadataUpdate.AddSchema.class) - .asInstanceOf(InstanceOfAssertFactories.type(MetadataUpdate.AddSchema.class)) - .extracting(MetadataUpdate.AddSchema::schema) - .extracting(Schema::schemaId) - .isEqualTo(1); - - assertThat(changes) - .element(6) - .isInstanceOf(MetadataUpdate.AddSchema.class) - .asInstanceOf(InstanceOfAssertFactories.type(MetadataUpdate.AddSchema.class)) - .extracting(MetadataUpdate.AddSchema::schema) - .extracting(Schema::schemaId) - .isEqualTo(2); - assertThat(changes) .element(7) .isInstanceOf(MetadataUpdate.SetCurrentViewVersion.class)