MCPcopy Create free account
hub / github.com/apache/arrow / EvaluateStatisticsAsExpression

Method EvaluateStatisticsAsExpression

cpp/src/arrow/dataset/file_parquet.cc:368–428  ·  view source on GitHub ↗

Source from the content-addressed store, hash-verified

366} // namespace
367
368std::optional<compute::Expression> ParquetFileFragment::EvaluateStatisticsAsExpression(
369 const Field& field, const FieldRef& field_ref,
370 const parquet::Statistics& statistics) {
371 auto field_expr = compute::field_ref(field_ref);
372
373 bool may_have_null = !statistics.HasNullCount() || statistics.null_count() > 0;
374 // Optimize for corner case where all values are nulls
375 if (statistics.num_values() == 0) {
376 // If there are no non-null values, column `field_ref` in the fragment
377 // might be empty or all values are nulls. In this case, we also return
378 // a null expression.
379 return is_null(std::move(field_expr));
380 }
381
382 std::shared_ptr<Scalar> min, max;
383 if (!StatisticsAsScalars(statistics, &min, &max).ok()) {
384 return std::nullopt;
385 }
386
387 auto maybe_min = Cast(min, field.type());
388 auto maybe_max = Cast(max, field.type());
389 if (maybe_min.ok() && maybe_max.ok()) {
390 min = maybe_min.MoveValueUnsafe().scalar();
391 max = maybe_max.MoveValueUnsafe().scalar();
392
393 if (min->Equals(*max)) {
394 auto single_value = compute::equal(field_expr, compute::literal(std::move(min)));
395
396 if (!may_have_null) {
397 return single_value;
398 }
399 return compute::or_(std::move(single_value), is_null(std::move(field_expr)));
400 }
401
402 auto lower_bound = compute::greater_equal(field_expr, compute::literal(min));
403 auto upper_bound = compute::less_equal(field_expr, compute::literal(max));
404 compute::Expression in_range;
405
406 // Since the minimum & maximum values are NaN, useful statistics
407 // cannot be extracted for checking the presence of a value within
408 // range
409 if (IsNan(*min) && IsNan(*max)) {
410 return std::nullopt;
411 }
412
413 // If either minimum or maximum is NaN, it should be ignored for the
414 // range computation
415 if (IsNan(*min)) {
416 in_range = std::move(upper_bound);
417 } else if (IsNan(*max)) {
418 in_range = std::move(lower_bound);
419 } else {
420 in_range = compute::and_(std::move(lower_bound), std::move(upper_bound));
421 }
422 if (may_have_null) {
423 return compute::or_(std::move(in_range), compute::is_null(std::move(field_expr)));
424 }
425 return in_range;

Callers

nothing calls this directly

Calls 15

field_refFunction · 0.85
StatisticsAsScalarsFunction · 0.85
CastFunction · 0.85
equalFunction · 0.85
or_Function · 0.85
greater_equalFunction · 0.85
less_equalFunction · 0.85
IsNanFunction · 0.85
and_Function · 0.85
HasNullCountMethod · 0.80
MoveValueUnsafeMethod · 0.80
is_nullFunction · 0.50

Tested by

no test coverage detected