You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@polaris.apache.org by di...@apache.org on 2026/08/12 22:49:06 UTC
(polaris) branch main updated: Avoid re-reading view metadata from storage after a commit (#5238)
This is an automated email from the ASF dual-hosted git repository.
dimas-b pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/polaris.git
The following commit(s) were added to refs/heads/main by this push:
new 0ead1daed4 Avoid re-reading view metadata from storage after a commit (#5238)
0ead1daed4 is described below
commit 0ead1daed4fe722c74c6132de45b48b3555e1332
Author: Ayush Saxena <ay...@apache.org>
AuthorDate: Thu Aug 13 04:18:59 2026 +0530
Avoid re-reading view metadata from storage after a commit (#5238)
---
.../core/config/BehaviorChangeConfiguration.java | 11 +++++
.../catalog/iceberg/LocalIcebergCatalog.java | 20 ++++++++-
.../iceberg/AbstractLocalIcebergCatalogTest.java | 48 ++++++++++++++++++++++
.../flags-polaris_behavior_changes.md | 9 ++++
4 files changed, 86 insertions(+), 2 deletions(-)
diff --git a/polaris-core/src/main/java/org/apache/polaris/core/config/BehaviorChangeConfiguration.java b/polaris-core/src/main/java/org/apache/polaris/core/config/BehaviorChangeConfiguration.java
index 0a9e5bde3b..a4171236f1 100644
--- a/polaris-core/src/main/java/org/apache/polaris/core/config/BehaviorChangeConfiguration.java
+++ b/polaris-core/src/main/java/org/apache/polaris/core/config/BehaviorChangeConfiguration.java
@@ -75,6 +75,17 @@ public class BehaviorChangeConfiguration<T> extends PolarisConfiguration<T> {
.defaultValue(true)
.buildBehaviorChangeConfiguration();
+ public static final BehaviorChangeConfiguration<Boolean>
+ VIEW_OPERATIONS_MAKE_METADATA_CURRENT_ON_COMMIT =
+ PolarisConfiguration.<Boolean>builder()
+ .key("VIEW_OPERATIONS_MAKE_METADATA_CURRENT_ON_COMMIT")
+ .description(
+ "If true, BasePolarisViewOperations should mark the metadata that is passed into"
+ + " `commit` as current, and reuse it to skip a trip to object storage to re-construct"
+ + " the committed metadata again.")
+ .defaultValue(true)
+ .buildBehaviorChangeConfiguration();
+
public static final BehaviorChangeConfiguration<Boolean> ALLOW_NAMESPACE_CUSTOM_LOCATION =
PolarisConfiguration.<Boolean>builder()
.key("ALLOW_NAMESPACE_CUSTOM_LOCATION")
diff --git a/runtime/service/src/main/java/org/apache/polaris/service/catalog/iceberg/LocalIcebergCatalog.java b/runtime/service/src/main/java/org/apache/polaris/service/catalog/iceberg/LocalIcebergCatalog.java
index 1cea9890c3..2f3d998879 100644
--- a/runtime/service/src/main/java/org/apache/polaris/service/catalog/iceberg/LocalIcebergCatalog.java
+++ b/runtime/service/src/main/java/org/apache/polaris/service/catalog/iceberg/LocalIcebergCatalog.java
@@ -1023,9 +1023,17 @@ public class LocalIcebergCatalog extends BaseMetastoreViewCatalog
}
@VisibleForTesting
+ public ViewOperations newViewOps(
+ TableIdentifier identifier, boolean makeMetadataCurrentOnCommit) {
+ return new BasePolarisViewOperations(catalogFileIO, identifier, makeMetadataCurrentOnCommit);
+ }
+
@Override
protected ViewOperations newViewOps(TableIdentifier identifier) {
- return new BasePolarisViewOperations(catalogFileIO, identifier);
+ boolean makeMetadataCurrentOnCommit =
+ realmConfig.getConfig(
+ BehaviorChangeConfiguration.VIEW_OPERATIONS_MAKE_METADATA_CURRENT_ON_COMMIT);
+ return newViewOps(identifier, makeMetadataCurrentOnCommit);
}
/**
@@ -2218,12 +2226,15 @@ public class LocalIcebergCatalog extends BaseMetastoreViewCatalog
implements ViewOperations {
private final TableIdentifier identifier;
private final String fullViewName;
+ private final boolean makeMetadataCurrentOnCommit;
private FileIO viewFileIO;
- BasePolarisViewOperations(FileIO defaultFileIO, TableIdentifier identifier) {
+ BasePolarisViewOperations(
+ FileIO defaultFileIO, TableIdentifier identifier, boolean makeMetadataCurrentOnCommit) {
this.viewFileIO = defaultFileIO;
this.identifier = identifier;
this.fullViewName = ViewUtil.fullViewName(catalogName, identifier);
+ this.makeMetadataCurrentOnCommit = makeMetadataCurrentOnCommit;
}
@Override
@@ -2459,6 +2470,11 @@ public class LocalIcebergCatalog extends BaseMetastoreViewCatalog
} else {
updateTableLike(identifier, entity, true);
}
+ if (makeMetadataCurrentOnCommit) {
+ currentMetadata =
+ ViewMetadata.buildFrom(metadata).setMetadataLocation(newLocation).build();
+ currentMetadataLocation = newLocation;
+ }
writeSucceeded = true;
} finally {
if (!writeSucceeded && writeResult.written()) {
diff --git a/runtime/service/src/test/java/org/apache/polaris/service/catalog/iceberg/AbstractLocalIcebergCatalogTest.java b/runtime/service/src/test/java/org/apache/polaris/service/catalog/iceberg/AbstractLocalIcebergCatalogTest.java
index 8da58c833c..d5ec17e1f9 100644
--- a/runtime/service/src/test/java/org/apache/polaris/service/catalog/iceberg/AbstractLocalIcebergCatalogTest.java
+++ b/runtime/service/src/test/java/org/apache/polaris/service/catalog/iceberg/AbstractLocalIcebergCatalogTest.java
@@ -102,6 +102,7 @@ import org.apache.iceberg.exceptions.ValidationException;
import org.apache.iceberg.inmemory.InMemoryFileIO;
import org.apache.iceberg.io.CloseableIterable;
import org.apache.iceberg.io.FileIO;
+import org.apache.iceberg.io.InputFile;
import org.apache.iceberg.rest.requests.UpdateTableRequest;
import org.apache.iceberg.types.Types;
import org.apache.iceberg.util.CharSequenceSet;
@@ -110,6 +111,7 @@ import org.apache.iceberg.view.ImmutableSQLViewRepresentation;
import org.apache.iceberg.view.ImmutableViewVersion;
import org.apache.iceberg.view.ViewMetadata;
import org.apache.iceberg.view.ViewMetadataParser;
+import org.apache.iceberg.view.ViewOperations;
import org.apache.polaris.core.PolarisCallContext;
import org.apache.polaris.core.PolarisDiagnostics;
import org.apache.polaris.core.admin.model.AwsStorageConfigInfo;
@@ -3053,6 +3055,52 @@ public abstract class AbstractLocalIcebergCatalogTest extends CatalogTests<Local
}
}
+ @ParameterizedTest
+ @ValueSource(booleans = {false, true})
+ public void testViewOperationsDoesNotRefreshAfterCommit(boolean updateMetadataOnCommit) {
+ Assumptions.assumeTrue(
+ requiresNamespaceCreate(),
+ "Only applicable if namespaces must be created before adding children");
+
+ catalog.createNamespace(NS);
+ catalog
+ .buildView(TABLE)
+ .withSchema(SCHEMA)
+ .withDefaultNamespace(NS)
+ .withQuery("spark", VIEW_QUERY)
+ .create();
+
+ ViewOperations ops = catalog.newViewOps(TABLE, updateMetadataOnCommit);
+
+ try (MockedStatic<ViewMetadataParser> mocked =
+ Mockito.mockStatic(ViewMetadataParser.class, Mockito.CALLS_REAL_METHODS)) {
+ ViewMetadata base1 = ops.current();
+ mocked.verify(() -> ViewMetadataParser.read(Mockito.any(InputFile.class)), Mockito.times(1));
+
+ ViewMetadata base2 = ops.refresh();
+ mocked.verify(() -> ViewMetadataParser.read(Mockito.any(InputFile.class)), Mockito.times(1));
+
+ Assertions.assertThat(base1.metadataFileLocation()).isEqualTo(base2.metadataFileLocation());
+
+ ViewMetadata newMetadata =
+ ViewMetadata.buildFrom(base2).setProperties(Map.of("new_prop", "new_value")).build();
+ ops.commit(base2, newMetadata);
+ mocked.verify(() -> ViewMetadataParser.read(Mockito.any(InputFile.class)), Mockito.times(1));
+
+ ops.current();
+ int expectedReads = updateMetadataOnCommit ? 1 : 2;
+ mocked.verify(
+ () -> ViewMetadataParser.read(Mockito.any(InputFile.class)),
+ Mockito.times(expectedReads));
+ ops.refresh();
+ mocked.verify(
+ () -> ViewMetadataParser.read(Mockito.any(InputFile.class)),
+ Mockito.times(expectedReads));
+ } finally {
+ catalog.dropView(TABLE);
+ }
+ }
+
private boolean metadataFileExists(String location) {
try {
return fileIO.newInputFile(location).exists();
diff --git a/site/content/in-dev/unreleased/configuration/config-sections/flags-polaris_behavior_changes.md b/site/content/in-dev/unreleased/configuration/config-sections/flags-polaris_behavior_changes.md
index b25475e8b8..68c1b177d9 100644
--- a/site/content/in-dev/unreleased/configuration/config-sections/flags-polaris_behavior_changes.md
+++ b/site/content/in-dev/unreleased/configuration/config-sections/flags-polaris_behavior_changes.md
@@ -79,3 +79,12 @@ If true, validate that view locations don't overlap when views are created
- **Default:** `true`
---
+
+##### `polaris.behavior-changes."VIEW_OPERATIONS_MAKE_METADATA_CURRENT_ON_COMMIT"`
+
+If true, BasePolarisViewOperations should mark the metadata that is passed into `commit` as current, and reuse it to skip a trip to object storage to re-construct the committed metadata again.
+
+- **Type:** `Boolean`
+- **Default:** `true`
+
+---