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();
+ }
}