Skip to content

Commit caf3402

Browse files
committed
address bloom filter decimal review suggestions
1 parent 892f162 commit caf3402

1 file changed

Lines changed: 73 additions & 17 deletions

File tree

datafusion/datasource-parquet/src/bloom_filter.rs

Lines changed: 73 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -34,13 +34,18 @@ use parquet::data_type::Decimal;
3434
/// Parquet row groups and data pages based on the query predicate.
3535
#[derive(Debug, Clone, Default)]
3636
pub(crate) struct BloomFilterStatistics {
37-
/// Per-column Bloom filters
38-
/// Key: predicate column name
39-
/// Value:
40-
/// * [`Sbbf`] (Bloom filter),
41-
/// * Parquet physical [`Type`] needed to evaluate literals against the filter
42-
/// * Type length from the Parquet column descriptor
43-
column_sbbf: HashMap<String, (Sbbf, Type, i32)>,
37+
/// Per-column Bloom filters keyed by predicate column name.
38+
column_sbbf: HashMap<String, ColumnBloomFilter>,
39+
}
40+
41+
#[derive(Debug, Clone)]
42+
struct ColumnBloomFilter {
43+
/// [`Sbbf`] (Bloom filter).
44+
sbbf: Sbbf,
45+
/// Parquet physical [`Type`] needed to evaluate literals against the filter.
46+
physical_type: Type,
47+
/// Type length from the Parquet column descriptor.
48+
type_length: i32,
4449
}
4550

4651
impl BloomFilterStatistics {
@@ -64,8 +69,14 @@ impl BloomFilterStatistics {
6469
ty: Type,
6570
type_length: i32,
6671
) {
67-
self.column_sbbf
68-
.insert(column.into(), (sbbf, ty, type_length));
72+
self.column_sbbf.insert(
73+
column.into(),
74+
ColumnBloomFilter {
75+
sbbf,
76+
physical_type: ty,
77+
type_length,
78+
},
79+
);
6980
}
7081

7182
/// Helper function for checking if [`Sbbf`] filter contains [`ScalarValue`].
@@ -186,8 +197,7 @@ impl PruningStatistics for BloomFilterStatistics {
186197
column: &Column,
187198
values: &HashSet<ScalarValue>,
188199
) -> Option<BooleanArray> {
189-
let (sbbf, parquet_type, type_length) =
190-
self.column_sbbf.get(column.name.as_str())?;
200+
let column_bloom_filter = self.column_sbbf.get(column.name.as_str())?;
191201

192202
// Bloom filters are probabilistic data structures that can return false
193203
// positives (i.e. it might return true even if the value is not
@@ -198,10 +208,10 @@ impl PruningStatistics for BloomFilterStatistics {
198208
.iter()
199209
.map(|value| {
200210
BloomFilterStatistics::check_scalar(
201-
sbbf,
211+
&column_bloom_filter.sbbf,
202212
value,
203-
parquet_type,
204-
*type_length,
213+
&column_bloom_filter.physical_type,
214+
column_bloom_filter.type_length,
205215
)
206216
})
207217
// The row group doesn't contain any of the values if
@@ -413,7 +423,11 @@ mod tests {
413423
async fn test_row_group_bloom_filter_pruning_predicate_decimal128() {
414424
for precision in [19, 20, 21, 28, 38] {
415425
let scale = 2;
416-
let data = parquet_decimal128_with_bloom_filter(precision, scale);
426+
let data = parquet_decimal128_with_bloom_filter(
427+
precision,
428+
scale,
429+
vec![100, 200, 300, 400, 500, 600],
430+
);
417431
let schema = Schema::new(vec![Field::new(
418432
"decimal_col",
419433
DataType::Decimal128(precision, scale),
@@ -443,6 +457,44 @@ mod tests {
443457
}
444458
}
445459

460+
#[tokio::test]
461+
async fn test_row_group_bloom_filter_pruning_predicate_negative_decimal128() {
462+
for precision in [19, 20, 21, 28, 38] {
463+
let scale = 2;
464+
let data = parquet_decimal128_with_bloom_filter(
465+
precision,
466+
scale,
467+
vec![-100, -200, -300, -400, -500, -600],
468+
);
469+
let schema = Schema::new(vec![Field::new(
470+
"decimal_col",
471+
DataType::Decimal128(precision, scale),
472+
true,
473+
)]);
474+
let expr = col("decimal_col").eq(Expr::Literal(
475+
ScalarValue::Decimal128(Some(-500), precision, scale),
476+
None,
477+
));
478+
let expr = logical2physical(&expr, &schema);
479+
let pruning_predicate =
480+
PruningPredicate::try_new(expr, Arc::new(schema)).unwrap();
481+
482+
let pruned_row_groups = test_row_group_bloom_filter_pruning_predicate(
483+
&format!("negative-decimal128-{precision}.parquet"),
484+
data,
485+
&pruning_predicate,
486+
)
487+
.await
488+
.unwrap();
489+
490+
assert_eq!(
491+
pruned_row_groups.access_plan().row_group_indexes(),
492+
vec![2],
493+
"precision {precision}"
494+
);
495+
}
496+
}
497+
446498
struct BloomFilterTest {
447499
file_name: String,
448500
schema: Schema,
@@ -535,14 +587,18 @@ mod tests {
535587
}
536588
}
537589

538-
fn parquet_decimal128_with_bloom_filter(precision: u8, scale: i8) -> bytes::Bytes {
590+
fn parquet_decimal128_with_bloom_filter(
591+
precision: u8,
592+
scale: i8,
593+
values: Vec<i128>,
594+
) -> bytes::Bytes {
539595
let schema = Arc::new(Schema::new(vec![Field::new(
540596
"decimal_col",
541597
DataType::Decimal128(precision, scale),
542598
true,
543599
)]));
544600
let array = Arc::new(
545-
Decimal128Array::from(vec![100, 200, 300, 400, 500, 600])
601+
Decimal128Array::from(values)
546602
.with_precision_and_scale(precision, scale)
547603
.unwrap(),
548604
) as ArrayRef;

0 commit comments

Comments
 (0)