This is an automated email from the ASF dual-hosted git repository.

JingsongLi pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/paimon.git


The following commit(s) were added to refs/heads/master by this push:
     new 801c1e89a1 [core] Validate the carried-over default value when a 
column type changes (#9292)
801c1e89a1 is described below

commit 801c1e89a110830a543e00c8420f7e66f3d6ae92
Author: ZIHAN DAI <[email protected]>
AuthorDate: Thu Aug 20 11:47:35 2026 +1000

    [core] Validate the carried-over default value when a column type changes 
(#9292)
---
 .../org/apache/paimon/schema/SchemaManager.java    | 14 ++++--
 .../apache/paimon/schema/SchemaManagerTest.java    | 52 ++++++++++++++++++++++
 2 files changed, 62 insertions(+), 4 deletions(-)

diff --git 
a/paimon-core/src/main/java/org/apache/paimon/schema/SchemaManager.java 
b/paimon-core/src/main/java/org/apache/paimon/schema/SchemaManager.java
index 9161d29337..73e947d9fa 100644
--- a/paimon-core/src/main/java/org/apache/paimon/schema/SchemaManager.java
+++ b/paimon-core/src/main/java/org/apache/paimon/schema/SchemaManager.java
@@ -533,14 +533,20 @@ public class SchemaManager implements Serializable {
                                     String.format(
                                             "Column type %s[%s] cannot be 
converted to %s without losing information.",
                                             field.name(), sourceRootType, 
targetRootType));
-                            return new DataField(
-                                    field.id(),
-                                    field.name(),
+                            DataType newFieldType =
                                     getArrayMapTypeWithTargetTypeRoot(
                                             field.type(),
                                             targetRootType,
                                             depth,
-                                            update.fieldNames().length),
+                                            update.fieldNames().length);
+                            // the default value is carried over unchanged, so 
it has to stay
+                            // readable as the new type -- otherwise the table 
is left with a
+                            // default that createTable and ALTER .. SET 
DEFAULT would both reject
+                            validateDefaultValue(newFieldType, 
field.defaultValue());
+                            return new DataField(
+                                    field.id(),
+                                    field.name(),
+                                    newFieldType,
                                     field.description(),
                                     field.defaultValue());
                         },
diff --git 
a/paimon-core/src/test/java/org/apache/paimon/schema/SchemaManagerTest.java 
b/paimon-core/src/test/java/org/apache/paimon/schema/SchemaManagerTest.java
index 1529f73ff4..0d8b813754 100644
--- a/paimon-core/src/test/java/org/apache/paimon/schema/SchemaManagerTest.java
+++ b/paimon-core/src/test/java/org/apache/paimon/schema/SchemaManagerTest.java
@@ -1506,4 +1506,56 @@ public class SchemaManagerTest {
                                         new 
ChangelogManager(LocalFileIO.create(), path, null)))
                 .hasMessageContaining("Schema 999 does not exist");
     }
+
+    private Schema schemaWithDefault(String defaultValue) {
+        return new Schema(
+                Arrays.asList(
+                        new DataField(0, "id", DataTypes.INT()),
+                        new DataField(1, "c", DataTypes.STRING(), null, 
defaultValue)),
+                Collections.emptyList(),
+                Collections.emptyList(),
+                Collections.singletonMap(CoreOptions.BUCKET.key(), "-1"),
+                "");
+    }
+
+    @Test
+    public void testUpdateColumnTypeRejectsADefaultValueTheNewTypeCannotRead() 
throws Exception {
+        retryArtificialException(() -> 
manager.createTable(schemaWithDefault("'abc'")));
+
+        assertThatThrownBy(
+                        () ->
+                                retryArtificialException(
+                                        () ->
+                                                manager.commitChanges(
+                                                        
SchemaChange.updateColumnType(
+                                                                "c", 
DataTypes.INT()))))
+                .rootCause()
+                .isInstanceOf(NumberFormatException.class);
+
+        // the column is untouched, so the table is still writable
+        TableSchema after = manager.latest().get();
+        assertThat(after.fields().get(1).type()).isEqualTo(DataTypes.STRING());
+        assertThatCode(
+                        () ->
+                                
FileStoreTableFactory.create(LocalFileIO.create(), path, after)
+                                        .newWrite("u"))
+                .doesNotThrowAnyException();
+    }
+
+    @Test
+    public void testUpdateColumnTypeKeepsADefaultValueTheNewTypeCanRead() 
throws Exception {
+        retryArtificialException(() -> 
manager.createTable(schemaWithDefault("'123'")));
+
+        retryArtificialException(
+                () -> manager.commitChanges(SchemaChange.updateColumnType("c", 
DataTypes.INT())));
+
+        TableSchema after = manager.latest().get();
+        assertThat(after.fields().get(1).type()).isEqualTo(DataTypes.INT());
+        assertThat(after.fields().get(1).defaultValue()).isEqualTo("'123'");
+        assertThatCode(
+                        () ->
+                                
FileStoreTableFactory.create(LocalFileIO.create(), path, after)
+                                        .newWrite("u"))
+                .doesNotThrowAnyException();
+    }
 }

Reply via email to