|
17 | 17 |
|
18 | 18 | //! Integration tests for reading Paimon tables provisioned by Spark. |
19 | 19 |
|
20 | | -use arrow_array::{Array, ArrowPrimitiveType, Int32Array, Int64Array, RecordBatch, StringArray}; |
| 20 | +use arrow_array::{ |
| 21 | + Array, ArrowPrimitiveType, Int32Array, Int64Array, ListArray, MapArray, RecordBatch, |
| 22 | + StringArray, StructArray, |
| 23 | +}; |
21 | 24 | use futures::TryStreamExt; |
22 | 25 | use paimon::api::ConfigResponse; |
23 | 26 | use paimon::catalog::{Identifier, RESTCatalog}; |
@@ -1369,3 +1372,98 @@ async fn test_read_schema_evolution_drop_column() { |
1369 | 1372 | "Old rows should be readable after DROP COLUMN, with only remaining columns" |
1370 | 1373 | ); |
1371 | 1374 | } |
| 1375 | + |
| 1376 | +// --------------------------------------------------------------------------- |
| 1377 | +// Complex type integration tests |
| 1378 | +// --------------------------------------------------------------------------- |
| 1379 | + |
| 1380 | +/// Test reading a table with complex types: ARRAY<INT>, MAP<STRING, INT>, STRUCT<name: STRING, value: INT>. |
| 1381 | +#[tokio::test] |
| 1382 | +async fn test_read_complex_type_table() { |
| 1383 | + let (_, batches) = scan_and_read_with_fs_catalog("complex_type_table", None).await; |
| 1384 | + |
| 1385 | + #[allow(clippy::type_complexity)] |
| 1386 | + let mut rows: Vec<(i32, Vec<i32>, Vec<(String, i32)>, (String, i32))> = Vec::new(); |
| 1387 | + for batch in &batches { |
| 1388 | + let id = batch |
| 1389 | + .column_by_name("id") |
| 1390 | + .and_then(|c| c.as_any().downcast_ref::<Int32Array>()) |
| 1391 | + .expect("id"); |
| 1392 | + let int_array = batch |
| 1393 | + .column_by_name("int_array") |
| 1394 | + .and_then(|c| c.as_any().downcast_ref::<ListArray>()) |
| 1395 | + .expect("int_array as ListArray"); |
| 1396 | + let string_map = batch |
| 1397 | + .column_by_name("string_map") |
| 1398 | + .and_then(|c| c.as_any().downcast_ref::<MapArray>()) |
| 1399 | + .expect("string_map as MapArray"); |
| 1400 | + let row_field = batch |
| 1401 | + .column_by_name("row_field") |
| 1402 | + .and_then(|c| c.as_any().downcast_ref::<StructArray>()) |
| 1403 | + .expect("row_field as StructArray"); |
| 1404 | + |
| 1405 | + for i in 0..batch.num_rows() { |
| 1406 | + // Extract ARRAY<INT> |
| 1407 | + let list_values = int_array.value(i); |
| 1408 | + let int_arr = list_values |
| 1409 | + .as_any() |
| 1410 | + .downcast_ref::<Int32Array>() |
| 1411 | + .expect("list element as Int32Array"); |
| 1412 | + let arr_vals: Vec<i32> = (0..int_arr.len()).map(|j| int_arr.value(j)).collect(); |
| 1413 | + |
| 1414 | + // Extract MAP<STRING, INT> |
| 1415 | + let map_val = string_map.value(i); |
| 1416 | + let map_struct = map_val |
| 1417 | + .as_any() |
| 1418 | + .downcast_ref::<StructArray>() |
| 1419 | + .expect("map entries as StructArray"); |
| 1420 | + let keys = map_struct |
| 1421 | + .column(0) |
| 1422 | + .as_any() |
| 1423 | + .downcast_ref::<StringArray>() |
| 1424 | + .expect("map keys"); |
| 1425 | + let values = map_struct |
| 1426 | + .column(1) |
| 1427 | + .as_any() |
| 1428 | + .downcast_ref::<Int32Array>() |
| 1429 | + .expect("map values"); |
| 1430 | + let mut map_entries: Vec<(String, i32)> = (0..keys.len()) |
| 1431 | + .map(|j| (keys.value(j).to_string(), values.value(j))) |
| 1432 | + .collect(); |
| 1433 | + map_entries.sort_by(|a, b| a.0.cmp(&b.0)); |
| 1434 | + |
| 1435 | + // Extract STRUCT<name: STRING, value: INT> |
| 1436 | + let struct_name = row_field |
| 1437 | + .column_by_name("name") |
| 1438 | + .and_then(|c| c.as_any().downcast_ref::<StringArray>()) |
| 1439 | + .expect("struct name"); |
| 1440 | + let struct_value = row_field |
| 1441 | + .column_by_name("value") |
| 1442 | + .and_then(|c| c.as_any().downcast_ref::<Int32Array>()) |
| 1443 | + .expect("struct value"); |
| 1444 | + |
| 1445 | + rows.push(( |
| 1446 | + id.value(i), |
| 1447 | + arr_vals, |
| 1448 | + map_entries, |
| 1449 | + (struct_name.value(i).to_string(), struct_value.value(i)), |
| 1450 | + )); |
| 1451 | + } |
| 1452 | + } |
| 1453 | + rows.sort_by_key(|(id, _, _, _)| *id); |
| 1454 | + |
| 1455 | + assert_eq!( |
| 1456 | + rows, |
| 1457 | + vec![ |
| 1458 | + ( |
| 1459 | + 1, |
| 1460 | + vec![1, 2, 3], |
| 1461 | + vec![("a".into(), 10), ("b".into(), 20)], |
| 1462 | + ("alice".into(), 100), |
| 1463 | + ), |
| 1464 | + (2, vec![4, 5], vec![("c".into(), 30)], ("bob".into(), 200),), |
| 1465 | + (3, vec![], vec![], ("carol".into(), 300),), |
| 1466 | + ], |
| 1467 | + "Complex type table should return correct ARRAY, MAP, and STRUCT values" |
| 1468 | + ); |
| 1469 | +} |
0 commit comments