You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@hudi.apache.org by da...@apache.org on 2026/01/23 06:32:54 UTC
(hudi) branch branch-0.x updated: [HUDI-9597] Do not evolve schema if reconciled schema keeps unchanged except version id (#13731) (#17849)
This is an automated email from the ASF dual-hosted git repository.
danny0405 pushed a commit to branch branch-0.x
in repository https://gitbox.apache.org/repos/asf/hudi.git
The following commit(s) were added to refs/heads/branch-0.x by this push:
new b171eb653819 [HUDI-9597] Do not evolve schema if reconciled schema keeps unchanged except version id (#13731) (#17849)
b171eb653819 is described below
commit b171eb65381912d45e29ad45e7cd0c673a880237
Author: Lin Liu <14...@users.noreply.github.com>
AuthorDate: Thu Jan 22 22:32:47 2026 -0800
[HUDI-9597] Do not evolve schema if reconciled schema keeps unchanged except version id (#13731) (#17849)
Co-authored-by: Shuo Cheng <nj...@gmail.com>
---
.../hudi/internal/schema/InternalSchema.java | 10 ++++++++++
.../schema/utils/AvroSchemaEvolutionUtils.java | 7 ++++++-
.../schema/utils/TestAvroSchemaEvolutionUtils.java | 23 ++++++++++++++++++++++
3 files changed, 39 insertions(+), 1 deletion(-)
diff --git a/hudi-common/src/main/java/org/apache/hudi/internal/schema/InternalSchema.java b/hudi-common/src/main/java/org/apache/hudi/internal/schema/InternalSchema.java
index ce5f8f259da2..99403f8b6b83 100644
--- a/hudi-common/src/main/java/org/apache/hudi/internal/schema/InternalSchema.java
+++ b/hudi-common/src/main/java/org/apache/hudi/internal/schema/InternalSchema.java
@@ -289,6 +289,16 @@ public class InternalSchema implements Serializable {
return record.equals(that.record);
}
+ public boolean equalsIgnoringVersion(Object o) {
+ if (this == o) {
+ return true;
+ } else if (!(o instanceof InternalSchema)) {
+ return false;
+ }
+ InternalSchema that = (InternalSchema) o;
+ return record.equals(that.record);
+ }
+
@Override
public int hashCode() {
return record.hashCode();
diff --git a/hudi-common/src/main/java/org/apache/hudi/internal/schema/utils/AvroSchemaEvolutionUtils.java b/hudi-common/src/main/java/org/apache/hudi/internal/schema/utils/AvroSchemaEvolutionUtils.java
index 7ca0cb7f81e4..8f0298d533ad 100644
--- a/hudi-common/src/main/java/org/apache/hudi/internal/schema/utils/AvroSchemaEvolutionUtils.java
+++ b/hudi-common/src/main/java/org/apache/hudi/internal/schema/utils/AvroSchemaEvolutionUtils.java
@@ -113,7 +113,12 @@ public class AvroSchemaEvolutionUtils {
typeChange.updateColumnType(col, inComingInternalSchema.findType(col));
});
- return SchemaChangeUtils.applyTableChanges2Schema(internalSchemaAfterAddColumns, typeChange);
+ InternalSchema evolvedSchema = SchemaChangeUtils.applyTableChanges2Schema(internalSchemaAfterAddColumns, typeChange);
+ // If evolvedSchema is exactly the same as the oldSchema, except the version number, return the old schema
+ if (evolvedSchema.equalsIgnoringVersion(oldTableSchema)) {
+ return oldTableSchema;
+ }
+ return evolvedSchema;
}
public static Schema reconcileSchema(Schema incomingSchema, Schema oldTableSchema) {
diff --git a/hudi-common/src/test/java/org/apache/hudi/internal/schema/utils/TestAvroSchemaEvolutionUtils.java b/hudi-common/src/test/java/org/apache/hudi/internal/schema/utils/TestAvroSchemaEvolutionUtils.java
index 4027bd28178f..6394e87b9b8d 100644
--- a/hudi-common/src/test/java/org/apache/hudi/internal/schema/utils/TestAvroSchemaEvolutionUtils.java
+++ b/hudi-common/src/test/java/org/apache/hudi/internal/schema/utils/TestAvroSchemaEvolutionUtils.java
@@ -537,4 +537,27 @@ public class TestAvroSchemaEvolutionUtils {
.reconcileSchema(incomingSchema, AvroInternalSchemaConverter.convert(schema)), "schemaNameFallback");
Assertions.assertEquals(simpleReconcileSchema, simpleCheckSchema);
}
+
+ @Test
+ public void testNotEvolveSchemaIfReconciledSchemaUnchanged() {
+ // a: boolean, c: long, c_1: long, d: date
+ Schema oldSchema = create("simple",
+ new Schema.Field("a", AvroInternalSchemaConverter.nullableSchema(Schema.create(Schema.Type.BOOLEAN)), null, JsonProperties.NULL_VALUE),
+ new Schema.Field("b", AvroInternalSchemaConverter.nullableSchema(Schema.create(Schema.Type.INT)), null, JsonProperties.NULL_VALUE),
+ new Schema.Field("c", AvroInternalSchemaConverter.nullableSchema(Schema.create(Schema.Type.LONG)), null, JsonProperties.NULL_VALUE),
+ new Schema.Field("d", AvroInternalSchemaConverter.nullableSchema(LogicalTypes.date().addToSchema(Schema.create(Schema.Type.INT))), null, JsonProperties.NULL_VALUE));
+ // incoming schema is part of old schema
+ // a: boolean, b: int, c: long
+ Schema incomingSchema = create("simple",
+ new Schema.Field("a", AvroInternalSchemaConverter.nullableSchema(Schema.create(Schema.Type.BOOLEAN)), null, JsonProperties.NULL_VALUE),
+ new Schema.Field("b", AvroInternalSchemaConverter.nullableSchema(Schema.create(Schema.Type.INT)), null, JsonProperties.NULL_VALUE),
+ new Schema.Field("c", AvroInternalSchemaConverter.nullableSchema(Schema.create(Schema.Type.LONG)), null, JsonProperties.NULL_VALUE));
+
+ InternalSchema oldInternalSchema = AvroInternalSchemaConverter.convert(oldSchema);
+ // set a non-default schema id for old table schema, e.g., 2.
+ oldInternalSchema.setSchemaId(2);
+ InternalSchema evolvedSchema = AvroSchemaEvolutionUtils.reconcileSchema(incomingSchema, oldInternalSchema);
+ // the evolved schema should be the old table schema, since there is no type change at all.
+ Assertions.assertEquals(oldInternalSchema, evolvedSchema);
+ }
}