Skip to content

Commit 840a41a

Browse files
[rust] integration tests for MAP dt + restructure ITs for complex dts (#560)
* [rust] integration tests for MAP dt + restructure tests around complex types (#549) * address comments
1 parent a1712bb commit 840a41a

6 files changed

Lines changed: 2056 additions & 2618 deletions

File tree

crates/fluss/src/row/binary_map.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -432,6 +432,7 @@ impl FlussMapWriter {
432432
}
433433
(DataType::Array(_), Datum::Array(v)) => writer.write_array(pos, v),
434434
(DataType::Map(_), Datum::Map(v)) => writer.write_map(pos, v),
435+
(DataType::Row(_), Datum::Row(v)) => writer.write_row(pos, v.as_ref())?,
435436
_ => {
436437
return Err(IllegalArgument {
437438
message: format!("Type mismatch: expected {:?}, got {:?}", dt, datum),

crates/fluss/src/row/column.rs

Lines changed: 11 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -661,25 +661,19 @@ impl InternalRow for ColumnarRow {
661661
};
662662

663663
let column = self.column(pos)?;
664-
let element_field = match column.data_type() {
665-
ArrowDataType::List(field) => field,
664+
match column.data_type() {
665+
ArrowDataType::List(_) => {}
666666
other => {
667667
return Err(IllegalArgument {
668668
message: format!("expected List array at position {pos}, got {other:?}"),
669669
});
670670
}
671-
};
672-
673-
let actual_element_type = from_arrow_field(element_field)?;
674-
if actual_element_type != *element_fluss_type {
675-
return Err(IllegalArgument {
676-
message: format!(
677-
"Arrow list element type {:?} does not match expected Fluss type {:?}",
678-
actual_element_type, element_fluss_type
679-
),
680-
});
681671
}
682672

673+
// `to_arrow_type` is lossy (e.g. TIMESTAMP_LTZ → plain Arrow Timestamp);
674+
// trust the Fluss schema and let the per-element conversion below catch
675+
// real shape mismatches.
676+
683677
let list_arr = column
684678
.as_any()
685679
.downcast_ref::<ListArray>()
@@ -778,25 +772,9 @@ fn arrow_map_entry_to_fluss_map(
778772
});
779773
}
780774

781-
let actual_key_type = from_arrow_field(&fields[0])?;
782-
if actual_key_type != *key_type {
783-
return Err(IllegalArgument {
784-
message: format!(
785-
"Arrow map key type {:?} does not match expected Fluss type {:?}",
786-
actual_key_type, key_type
787-
),
788-
});
789-
}
790-
791-
let actual_value_type = from_arrow_field(&fields[1])?;
792-
if actual_value_type != *value_type {
793-
return Err(IllegalArgument {
794-
message: format!(
795-
"Arrow map value type {:?} does not match expected Fluss type {:?}",
796-
actual_value_type, value_type
797-
),
798-
});
799-
}
775+
// `to_arrow_type` is lossy (e.g. TIMESTAMP_LTZ → plain Arrow Timestamp);
776+
// trust the Fluss schema and let the per-element conversion below catch
777+
// real shape mismatches.
800778

801779
let keys_arrow = struct_arr.column(0);
802780
let values_arrow = struct_arr.column(1);
@@ -1443,8 +1421,7 @@ mod tests {
14431421

14441422
let err = row.get_array(0).unwrap_err();
14451423
assert!(
1446-
err.to_string()
1447-
.contains("Cannot convert Arrow type to Fluss type"),
1424+
err.to_string().contains("expected Int32Type"),
14481425
"unexpected error: {err}"
14491426
);
14501427
}
@@ -1735,7 +1712,7 @@ mod tests {
17351712
let err = row.get_map(0).expect_err("type mismatch must error");
17361713
let msg = err.to_string();
17371714
assert!(
1738-
msg.contains("does not match expected Fluss type"),
1715+
msg.contains("expected StringArray"),
17391716
"unexpected error: {msg}"
17401717
);
17411718
}

crates/fluss/src/row/column_writer.rs

Lines changed: 54 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -22,12 +22,11 @@
2222
use crate::error::Error::RowConvertError;
2323
use crate::error::{Error, Result};
2424
use crate::metadata::{DataType, RowType};
25-
use crate::row::FlussMap;
26-
use crate::row::InternalRow;
2725
use crate::row::datum::{
2826
MICROS_PER_MILLI, MILLIS_PER_SECOND, NANOS_PER_MILLI, append_decimal_to_builder,
2927
millis_nanos_to_micros, millis_nanos_to_nanos,
3028
};
29+
use crate::row::{FlussArray, FlussMap, InternalRow};
3130
use arrow::array::{
3231
ArrayBuilder, ArrayRef, BinaryBuilder, BooleanBuilder, Date32Builder, Decimal128Builder,
3332
FixedSizeBinaryBuilder, Float32Builder, Float64Builder, Int8Builder, Int16Builder,
@@ -928,8 +927,8 @@ fn write_map_into(
928927
let key_array = map.key_array();
929928
let value_array = map.value_array();
930929
for i in 0..map.size() {
931-
key_writer.write_field_at(key_array, i)?;
932-
value_writer.write_field_at(value_array, i)?;
930+
write_array_element_into_column(key_writer, key_array, i)?;
931+
write_array_element_into_column(value_writer, value_array, i)?;
933932
}
934933
let last = *offsets.last().unwrap();
935934
offsets.push(
@@ -940,6 +939,57 @@ fn write_map_into(
940939
Ok(())
941940
}
942941

942+
// FlussArray carries no schema; nested row/map elements need the typed
943+
// inherent accessors (get_row/get_map with explicit types).
944+
fn write_array_element_into_column(
945+
writer: &mut ColumnWriter,
946+
array: &FlussArray,
947+
index: usize,
948+
) -> Result<()> {
949+
match &mut writer.inner {
950+
TypedWriter::Struct {
951+
field_writers,
952+
validity,
953+
row_type,
954+
..
955+
} => {
956+
if array.is_null_at(index) {
957+
for child in field_writers.iter_mut() {
958+
child.append_null();
959+
}
960+
validity.push(false);
961+
} else {
962+
let nested = array.get_row(index, row_type)?;
963+
for (j, child) in field_writers.iter_mut().enumerate() {
964+
child.write_field_at(&nested, j)?;
965+
}
966+
validity.push(true);
967+
}
968+
Ok(())
969+
}
970+
TypedWriter::Map {
971+
key_writer,
972+
value_writer,
973+
key_type,
974+
value_type,
975+
offsets,
976+
validity,
977+
} => {
978+
if array.is_null_at(index) {
979+
validity.push(false);
980+
let last = *offsets.last().unwrap();
981+
offsets.push(last);
982+
} else {
983+
let nested = array.get_map(index, key_type, value_type)?;
984+
write_map_into(nested, key_writer, value_writer, offsets)?;
985+
validity.push(true);
986+
}
987+
Ok(())
988+
}
989+
_ => writer.write_field_at(array, index),
990+
}
991+
}
992+
943993
fn finish_struct_array(
944994
fields: arrow_schema::Fields,
945995
child_arrays: Vec<ArrayRef>,

0 commit comments

Comments
 (0)