Skip to content

Commit 6ff715e

Browse files
author
wenchao.wu
committed
[python] Support UpdateColumnDefaultValue in SchemaManager
Apply UpdateColumnDefaultValue when committing schema changes, so a column default can be set, changed and cleared through the Python SchemaManager. Validate the value against the target type before storing it, mirroring the Java DefaultValueUtils string casts for booleans, numbers, dates, times and timestamps. Widen new_default_value to Optional[str], matching the @nullable contract on the Java side, where None clears the default. ARRAY, MAP and ROW defaults are accepted by Java but are not parsed here yet, so they are rejected with an explicit message.
1 parent 65c5dd7 commit 6ff715e

7 files changed

Lines changed: 763 additions & 5 deletions

File tree

‎paimon-core/src/test/java/org/apache/paimon/JavaPyE2ETest.java‎

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@
3737
import org.apache.paimon.data.InternalArray;
3838
import org.apache.paimon.data.InternalMap;
3939
import org.apache.paimon.data.InternalRow;
40+
import org.apache.paimon.data.Timestamp;
4041
import org.apache.paimon.data.serializer.InternalRowSerializer;
4142
import org.apache.paimon.data.variant.GenericVariant;
4243
import org.apache.paimon.data.variant.GenericVariantBuilder;
@@ -85,6 +86,7 @@
8586
import org.apache.paimon.table.source.ReadBuilder;
8687
import org.apache.paimon.table.source.Split;
8788
import org.apache.paimon.table.source.TableRead;
89+
import org.apache.paimon.types.DataField;
8890
import org.apache.paimon.types.DataType;
8991
import org.apache.paimon.types.DataTypes;
9092
import org.apache.paimon.types.RowKind;
@@ -107,6 +109,7 @@
107109
import java.time.Instant;
108110
import java.time.LocalDate;
109111
import java.time.LocalDateTime;
112+
import java.time.ZoneId;
110113
import java.time.ZoneOffset;
111114
import java.util.ArrayList;
112115
import java.util.Arrays;
@@ -732,6 +735,70 @@ public void testReadPythonDynamicBucketHashIndex() throws Exception {
732735
"hello-java, 42, java-new", "python-only, 7, python-only");
733736
}
734737

738+
@Test
739+
@EnabledIfSystemProperty(named = "run.e2e.tests", matches = "true")
740+
public void testReadPythonColumnDefaultValues() throws Exception {
741+
FileStoreTable table =
742+
(FileStoreTable) catalog.getTable(identifier("column_defaults_python_to_java"));
743+
assertThat(table.rowType().getFields())
744+
.extracting(DataField::defaultValue)
745+
.containsExactly(
746+
null,
747+
"12:30+01",
748+
"2024-02-31 24:00:00",
749+
"+12345-01-01",
750+
"2024-01-01T24:00",
751+
"0e-2147483645",
752+
"12345678901",
753+
"1700000000000",
754+
"''");
755+
756+
// Opening the writer casts every default; null fields take their default.
757+
BatchWriteBuilder writeBuilder = table.newBatchWriteBuilder();
758+
try (BatchTableWrite write = writeBuilder.newWrite();
759+
BatchTableCommit commit = writeBuilder.newCommit()) {
760+
write.write(GenericRow.of(1, null, null, null, null, null, null, null, null));
761+
commit.commit(write.prepareCommit());
762+
}
763+
764+
List<String> result =
765+
getResult(
766+
table.newRead(),
767+
table.newScan().plan().splits(),
768+
row ->
769+
row.getInt(0)
770+
+ ", "
771+
+ row.getInt(1)
772+
+ ", "
773+
+ row.getTimestamp(2, 3)
774+
+ ", "
775+
+ row.getTimestamp(3, 3)
776+
+ ", "
777+
+ row.getTimestamp(4, 3)
778+
+ ", "
779+
+ row.getDecimal(5, 10, 2)
780+
+ ", "
781+
+ row.isNullAt(6)
782+
+ ", "
783+
+ row.getTimestamp(7, 3)
784+
+ ", ["
785+
+ row.getString(8)
786+
+ "]");
787+
Timestamp nextLocalMidnight =
788+
Timestamp.fromInstant(
789+
LocalDateTime.of(2024, 1, 2, 0, 0)
790+
.atZone(ZoneId.systemDefault())
791+
.toInstant());
792+
// parseTime adds a '+hh' offset to the hour, so 12:30+01 is 13:30.
793+
assertThat(result)
794+
.containsExactly(
795+
"1, "
796+
+ (13 * 3600 + 30 * 60) * 1000
797+
+ ", 2024-03-01T00:00, +12345-01-01T00:00, "
798+
+ nextLocalMidnight
799+
+ ", 0.00, true, 2023-11-14T22:13:20, []");
800+
}
801+
735802
private int assignDynamicBucket(FileStoreTable table, InternalRow row) {
736803
InternalRowSerializer serializer =
737804
new InternalRowSerializer(DataTypes.STRING(), DataTypes.BIGINT());

‎paimon-python/dev/run_mixed_tests.sh‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -248,7 +248,7 @@ run_python_write_test() {
248248

249249
# Run the parameterized Python test method for writing data (pk table, includes bucket num assertion)
250250
echo "Running Python test for JavaPyReadWriteTest (test_py_write_read_pk_table)..."
251-
if python -m pytest java_py_read_write_test.py::JavaPyReadWriteTest -k "test_py_write_read_pk_table or test_py_write_read_append_table or test_py_write_dynamic_bucket_hash_index or test_py_write_floating_sequence" -v; then
251+
if python -m pytest java_py_read_write_test.py::JavaPyReadWriteTest -k "test_py_write_read_pk_table or test_py_write_read_append_table or test_py_write_dynamic_bucket_hash_index or test_py_write_floating_sequence or test_py_write_column_default_values" -v; then
252252
echo -e "${GREEN}✓ Python write test completed successfully${NC}"
253253
return 0
254254
else
@@ -267,7 +267,7 @@ run_java_read_test() {
267267
echo "Running Maven test for JavaPyE2ETest.testReadPkTable (Java Read Parquet/Orc/Avro)..."
268268
echo "Note: Maven may download dependencies on first run, this may take a while..."
269269
local parquet_result=0
270-
if mvn test -Dtest=org.apache.paimon.JavaPyE2ETest#testReadPkTable+testReadAppendTable+testReadPythonDynamicBucketHashIndex+testReadPythonFloatingSequence -pl paimon-core -Drun.e2e.tests=true -Dpython.version="$PYTHON_VERSION"; then
270+
if mvn test -Dtest=org.apache.paimon.JavaPyE2ETest#testReadPkTable+testReadAppendTable+testReadPythonDynamicBucketHashIndex+testReadPythonFloatingSequence+testReadPythonColumnDefaultValues -pl paimon-core -Drun.e2e.tests=true -Dpython.version="$PYTHON_VERSION"; then
271271
echo -e "${GREEN}✓ Java read Parquet/Orc/Avro test completed successfully${NC}"
272272
else
273273
echo -e "${RED}✗ Java read Parquet/Orc/Avro test failed${NC}"

0 commit comments

Comments
 (0)