Skip to content

Commit 039f21a

Browse files
committed
[core] Skip schema update when no changes detected.
1 parent 0605cc5 commit 039f21a

3 files changed

Lines changed: 53 additions & 0 deletions

File tree

paimon-api/src/main/java/org/apache/paimon/schema/TableSchema.java

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -342,6 +342,7 @@ public boolean equals(Object o) {
342342
}
343343
TableSchema tableSchema = (TableSchema) o;
344344
return version == tableSchema.version
345+
&& highestFieldId == tableSchema.highestFieldId
345346
&& Objects.equals(fields, tableSchema.fields)
346347
&& Objects.equals(partitionKeys, tableSchema.partitionKeys)
347348
&& Objects.equals(primaryKeys, tableSchema.primaryKeys)
@@ -356,6 +357,16 @@ public int hashCode() {
356357
version, fields, partitionKeys, primaryKeys, options, comment, timeMillis);
357358
}
358359

360+
/** Checks if two schemas have the same content, ignoring version and timeMillis. */
361+
public boolean sameContent(TableSchema other) {
362+
return Objects.equals(fields, other.fields)
363+
&& highestFieldId == other.highestFieldId
364+
&& Objects.equals(partitionKeys, other.partitionKeys)
365+
&& Objects.equals(primaryKeys, other.primaryKeys)
366+
&& Objects.equals(options, other.options)
367+
&& Objects.equals(comment, other.comment);
368+
}
369+
359370
public static List<DataField> newFields(RowType rowType) {
360371
return rowType.getFields();
361372
}

paimon-core/src/main/java/org/apache/paimon/schema/SchemaManager.java

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,9 @@
5959
import org.apache.paimon.shade.guava30.com.google.common.collect.Maps;
6060
import org.apache.paimon.shade.guava30.com.google.common.collect.Streams;
6161

62+
import org.slf4j.Logger;
63+
import org.slf4j.LoggerFactory;
64+
6265
import javax.annotation.Nullable;
6366
import javax.annotation.concurrent.ThreadSafe;
6467

@@ -108,6 +111,7 @@
108111
@ThreadSafe
109112
public class SchemaManager implements Serializable {
110113

114+
private static final Logger LOG = LoggerFactory.getLogger(SchemaManager.class);
111115
private static final String SCHEMA_PREFIX = "schema-";
112116

113117
private final FileIO fileIO;
@@ -266,6 +270,12 @@ public TableSchema commitChanges(List<SchemaChange> changes)
266270
new LazyField<>(() -> identifierFromPath(tableRoot.toString(), true, branch));
267271
TableSchema newTableSchema =
268272
generateTableSchema(oldTableSchema, changes, hasSnapshots, lazyIdentifier);
273+
if (oldTableSchema.sameContent(newTableSchema)) {
274+
LOG.info(
275+
"No schema change detected for table {}. Skipping schema update.",
276+
lazyIdentifier.get());
277+
return oldTableSchema;
278+
}
269279
try {
270280
boolean success = commit(newTableSchema);
271281
if (success) {

paimon-core/src/test/java/org/apache/paimon/schema/SchemaManagerTest.java

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -894,4 +894,36 @@ public void testRollbackSchemaNotExist() throws Exception {
894894
new ChangelogManager(LocalFileIO.create(), path, null)))
895895
.hasMessageContaining("Schema 999 does not exist");
896896
}
897+
898+
@Test
899+
public void testNoChangeCommitDoesNotCreateNewSchema() throws Exception {
900+
// Create table with an initial option foo=bar
901+
Map<String, String> initialOptions = new HashMap<>();
902+
initialOptions.put("foo", "bar");
903+
Schema schemaWithOption =
904+
new Schema(
905+
rowType.getFields(),
906+
Collections.emptyList(),
907+
Collections.emptyList(),
908+
initialOptions,
909+
"");
910+
SchemaManager manager = new SchemaManager(LocalFileIO.create(), path);
911+
manager.createTable(schemaWithOption);
912+
913+
long initialSchemaId = manager.latest().get().id();
914+
assertThat(manager.latest().get().options()).containsEntry("foo", "bar");
915+
916+
// Set option foo=bar again (no actual change)
917+
manager.commitChanges(SchemaChange.setOption("foo", "bar"));
918+
919+
// Verify no new schema is created when value didn't change
920+
long newSchemaId = manager.latest().get().id();
921+
assertThat(newSchemaId).isEqualTo(initialSchemaId);
922+
assertThat(manager.latest().get().options()).containsEntry("foo", "bar");
923+
924+
// Also test with UpdateComment when comment is unchanged
925+
String initialComment = manager.latest().get().comment();
926+
manager.commitChanges(SchemaChange.updateComment(initialComment));
927+
assertThat(manager.latest().get().id()).isEqualTo(initialSchemaId);
928+
}
897929
}

0 commit comments

Comments
 (0)