Skip to content

Commit d3fa083

Browse files
Weijun-Halamb
andauthored
refactor: handle LargeUtf8 statistics and add tests for UTF8 and LargeUTF8 (#10762)
Co-authored-by: Andrew Lamb <andrew@nerdnetworks.org>
1 parent e4f7b98 commit d3fa083

3 files changed

Lines changed: 69 additions & 9 deletions

File tree

datafusion/core/src/datasource/physical_plan/parquet/statistics.rs

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -152,16 +152,18 @@ macro_rules! get_statistic {
152152
Some(DataType::Binary) => {
153153
Some(ScalarValue::Binary(Some(s.$bytes_func().to_vec())))
154154
}
155-
_ => {
156-
let s = std::str::from_utf8(s.$bytes_func())
155+
Some(DataType::LargeUtf8) | _ => {
156+
let utf8_value = std::str::from_utf8(s.$bytes_func())
157157
.map(|s| s.to_string())
158158
.ok();
159-
if s.is_none() {
160-
log::debug!(
161-
"Utf8 statistics is a non-UTF8 value, ignoring it."
162-
);
159+
if utf8_value.is_none() {
160+
log::debug!("Utf8 statistics is a non-UTF8 value, ignoring it.");
161+
}
162+
163+
match $target_arrow_type {
164+
Some(DataType::LargeUtf8) => Some(ScalarValue::LargeUtf8(utf8_value)),
165+
_ => Some(ScalarValue::Utf8(utf8_value)),
163166
}
164-
Some(ScalarValue::Utf8(s))
165167
}
166168
}
167169
}

datafusion/core/tests/parquet/arrow_statistics.rs

Lines changed: 33 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ use arrow::datatypes::{
2929
use arrow_array::{
3030
make_array, Array, ArrayRef, BinaryArray, BooleanArray, Date32Array, Date64Array,
3131
Decimal128Array, FixedSizeBinaryArray, Float32Array, Float64Array, Int16Array,
32-
Int32Array, Int64Array, Int8Array, RecordBatch, StringArray,
32+
Int32Array, Int64Array, Int8Array, LargeStringArray, RecordBatch, StringArray,
3333
TimestampMicrosecondArray, TimestampMillisecondArray, TimestampNanosecondArray,
3434
TimestampSecondArray, UInt16Array, UInt32Array, UInt64Array, UInt8Array,
3535
};
@@ -1447,6 +1447,38 @@ async fn test_struct() {
14471447
}
14481448
.run();
14491449
}
1450+
1451+
// UTF8
1452+
#[tokio::test]
1453+
async fn test_utf8() {
1454+
let reader = TestReader {
1455+
scenario: Scenario::UTF8,
1456+
row_per_group: 5,
1457+
};
1458+
1459+
// test for utf8
1460+
Test {
1461+
reader: reader.build().await,
1462+
expected_min: Arc::new(StringArray::from(vec!["a", "e"])),
1463+
expected_max: Arc::new(StringArray::from(vec!["d", "i"])),
1464+
expected_null_counts: UInt64Array::from(vec![1, 0]),
1465+
expected_row_counts: UInt64Array::from(vec![5, 5]),
1466+
column_name: "utf8",
1467+
}
1468+
.run();
1469+
1470+
// test for large_utf8
1471+
Test {
1472+
reader: reader.build().await,
1473+
expected_min: Arc::new(LargeStringArray::from(vec!["a", "e"])),
1474+
expected_max: Arc::new(LargeStringArray::from(vec!["d", "i"])),
1475+
expected_null_counts: UInt64Array::from(vec![1, 0]),
1476+
expected_row_counts: UInt64Array::from(vec![5, 5]),
1477+
column_name: "large_utf8",
1478+
}
1479+
.run();
1480+
}
1481+
14501482
////// Files with missing statistics ///////
14511483

14521484
#[tokio::test]

datafusion/core/tests/parquet/mod.rs

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,10 @@ use arrow::{
2929
util::pretty::pretty_format_batches,
3030
};
3131
use arrow_array::types::{Int32Type, Int8Type};
32-
use arrow_array::{make_array, BooleanArray, DictionaryArray, Float32Array, StructArray};
32+
use arrow_array::{
33+
make_array, BooleanArray, DictionaryArray, Float32Array, LargeStringArray,
34+
StructArray,
35+
};
3336
use chrono::{Datelike, Duration, TimeDelta};
3437
use datafusion::{
3538
datasource::{physical_plan::ParquetExec, provider_as_source, TableProvider},
@@ -90,6 +93,7 @@ enum Scenario {
9093
WithNullValues,
9194
WithNullValuesPageLevel,
9295
StructArray,
96+
UTF8,
9397
}
9498

9599
enum Unit {
@@ -787,6 +791,16 @@ fn make_numeric_limit_batch() -> RecordBatch {
787791
.unwrap()
788792
}
789793

794+
fn make_utf8_batch(value: Vec<Option<&str>>) -> RecordBatch {
795+
let utf8 = StringArray::from(value.clone());
796+
let large_utf8 = LargeStringArray::from(value);
797+
RecordBatch::try_from_iter(vec![
798+
("utf8", Arc::new(utf8) as _),
799+
("large_utf8", Arc::new(large_utf8) as _),
800+
])
801+
.unwrap()
802+
}
803+
790804
fn make_dict_batch() -> RecordBatch {
791805
let values = [
792806
Some("abc"),
@@ -1044,6 +1058,18 @@ fn create_data_batch(scenario: Scenario) -> Vec<RecordBatch> {
10441058
)]));
10451059
vec![RecordBatch::try_new(schema, vec![struct_array_data]).unwrap()]
10461060
}
1061+
Scenario::UTF8 => {
1062+
vec![
1063+
make_utf8_batch(vec![Some("a"), Some("b"), Some("c"), Some("d"), None]),
1064+
make_utf8_batch(vec![
1065+
Some("e"),
1066+
Some("f"),
1067+
Some("g"),
1068+
Some("h"),
1069+
Some("i"),
1070+
]),
1071+
]
1072+
}
10471073
}
10481074
}
10491075

0 commit comments

Comments
 (0)