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

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


The following commit(s) were added to refs/heads/main by this push:
     new aca0281  test(datafusion): cover SQL schema evolution reads (#391)
aca0281 is described below

commit aca02811122b1102104eaaf810012ea5b2479148
Author: Jiwen liu <[email protected]>
AuthorDate: Sat Jun 20 19:11:30 2026 +0800

    test(datafusion): cover SQL schema evolution reads (#391)
---
 .../integrations/datafusion/tests/read_tables.rs   | 145 ++++++++++++++++++++-
 1 file changed, 142 insertions(+), 3 deletions(-)

diff --git a/crates/integrations/datafusion/tests/read_tables.rs 
b/crates/integrations/datafusion/tests/read_tables.rs
index 30760d2..5faa232 100644
--- a/crates/integrations/datafusion/tests/read_tables.rs
+++ b/crates/integrations/datafusion/tests/read_tables.rs
@@ -19,6 +19,8 @@ use std::collections::HashMap;
 use std::sync::Arc;
 
 use datafusion::arrow::array::{Array, Int32Array, StringArray};
+use datafusion::arrow::record_batch::RecordBatch;
+use datafusion::arrow::util::display::array_value_to_string;
 use datafusion::catalog::CatalogProvider;
 use datafusion::datasource::TableProvider;
 use datafusion::logical_expr::{col, lit, TableProviderFilterPushDown};
@@ -91,13 +93,42 @@ async fn read_rows(table_name: &str) -> Vec<(i32, String)> {
     actual_rows
 }
 
-async fn collect_query(
-    sql: &str,
-) -> 
datafusion::error::Result<Vec<datafusion::arrow::record_batch::RecordBatch>> {
+async fn collect_query(sql: &str) -> 
datafusion::error::Result<Vec<RecordBatch>> {
     let ctx = create_context().await;
     ctx.sql(sql).await?.collect().await
 }
 
+fn collect_rows(batches: &[RecordBatch]) -> Vec<Vec<String>> {
+    let mut rows = Vec::new();
+    for batch in batches {
+        for row_index in 0..batch.num_rows() {
+            let mut row = Vec::with_capacity(batch.num_columns());
+            for column in batch.columns() {
+                if column.is_null(row_index) {
+                    row.push("NULL".to_string());
+                } else {
+                    row.push(
+                        array_value_to_string(column.as_ref(), row_index)
+                            .expect("query result value should format"),
+                    );
+                }
+            }
+            rows.push(row);
+        }
+    }
+    rows
+}
+
+async fn assert_sql_rows(sql: &str, expected: &[&[&str]]) {
+    let batches = collect_query(sql).await.expect("query should succeed");
+    let actual = collect_rows(&batches);
+    let expected: Vec<Vec<String>> = expected
+        .iter()
+        .map(|row| row.iter().map(|value| value.to_string()).collect())
+        .collect();
+    assert_eq!(actual, expected, "unexpected result for SQL: {sql}");
+}
+
 async fn create_physical_plan(sql: &str) -> datafusion::error::Result<Arc<dyn 
ExecutionPlan>> {
     let ctx = create_context().await;
     ctx.sql(sql).await?.create_physical_plan().await
@@ -742,6 +773,114 @@ async fn test_data_evolution_drop_column_null_fill() {
     );
 }
 
+#[tokio::test]
+async fn test_sql_read_format_schema_evolution_add_column() {
+    assert_sql_rows(
+        "SELECT id, name, age FROM 
paimon.default.format_schema_evolution_add_column ORDER BY id",
+        &[
+            &["1", "alice", "NULL"],
+            &["2", "bob", "NULL"],
+            &["3", "carol", "30"],
+            &["4", "dave", "40"],
+            &["5", "eve", "50"],
+            &["6", "frank", "60"],
+        ],
+    )
+    .await;
+
+    assert_sql_rows(
+        "SELECT id, age FROM paimon.default.format_schema_evolution_add_column 
WHERE age IS NULL ORDER BY id",
+        &[&["1", "NULL"], &["2", "NULL"]],
+    )
+    .await;
+}
+
+#[tokio::test]
+async fn test_sql_read_format_schema_evolution_type_promotion() {
+    assert_sql_rows(
+        "SELECT id, value FROM 
paimon.default.format_schema_evolution_type_promotion ORDER BY id",
+        &[
+            &["1", "100"],
+            &["2", "200"],
+            &["3", "3000000000"],
+            &["4", "4000000000"],
+            &["5", "5000000000"],
+            &["6", "6000000000"],
+        ],
+    )
+    .await;
+
+    assert_sql_rows(
+        "SELECT id, value FROM 
paimon.default.format_schema_evolution_type_promotion WHERE value > 3000000000 
ORDER BY id",
+        &[&["4", "4000000000"], &["5", "5000000000"], &["6", "6000000000"]],
+    )
+    .await;
+}
+
+#[tokio::test]
+async fn test_sql_read_schema_evolution_rename_column() {
+    assert_sql_rows(
+        "SELECT id, renamed_payload FROM 
paimon.default.schema_evolution_rename_column ORDER BY id",
+        &[
+            &["1", "parquet-old"],
+            &["2", "parquet-old-2"],
+            &["3", "orc-new"],
+            &["4", "avro-new"],
+        ],
+    )
+    .await;
+
+    assert_sql_rows(
+        "SELECT id, renamed_payload FROM 
paimon.default.schema_evolution_rename_column WHERE renamed_payload LIKE '%new' 
ORDER BY id",
+        &[&["3", "orc-new"], &["4", "avro-new"]],
+    )
+    .await;
+}
+
+#[tokio::test]
+async fn test_sql_read_mixed_format_schema_evolution_drop_column() {
+    assert_sql_rows(
+        "SELECT id, name FROM 
paimon.default.mixed_format_schema_evolution_drop_column ORDER BY id",
+        &[
+            &["1", "parquet-alice"],
+            &["2", "parquet-bob"],
+            &["3", "orc-carol"],
+            &["4", "orc-dave"],
+            &["5", "avro-eve"],
+            &["6", "avro-frank"],
+        ],
+    )
+    .await;
+
+    assert_sql_rows(
+        "SELECT id, name FROM 
paimon.default.mixed_format_schema_evolution_drop_column WHERE name LIKE 
'avro-%' ORDER BY id",
+        &[&["5", "avro-eve"], &["6", "avro-frank"]],
+    )
+    .await;
+}
+
+#[tokio::test]
+async fn test_sql_read_mixed_format_schema_evolution_reorder_move_column() {
+    assert_sql_rows(
+        "SELECT right_value, left_value, id FROM 
paimon.default.mixed_format_schema_evolution_reorder_move_column ORDER BY id",
+        &[
+            &["parquet-right-1", "parquet-left-1", "1"],
+            &["parquet-right-2", "parquet-left-2", "2"],
+            &["orc-right-3", "orc-left-3", "3"],
+            &["orc-right-4", "orc-left-4", "4"],
+            &["avro-right-5", "avro-left-5", "5"],
+            &["avro-right-6", "avro-left-6", "6"],
+        ],
+    )
+    .await;
+
+    assert_sql_rows(
+        "SELECT id, right_value FROM 
paimon.default.mixed_format_schema_evolution_reorder_move_column WHERE 
right_value LIKE 'orc-%' ORDER BY id",
+        &[&["3", "orc-right-3"], &["4", "orc-right-4"]],
+    )
+    .await;
+}
+
 // ======================= Complex Type Tests =======================
 
 #[tokio::test]

Reply via email to