Commit 1064661
fix: preserve the error type of a failing parquet row filter predicate (#24638)
## Which issue does this PR close?
No existing issue tracks this; happy to file one if the project prefers
that first.
## Rationale for this change
`ArrowPredicate::evaluate` must return an `ArrowError`, so
`DatafusionArrowPredicate::evaluate` built one by `Debug`-formatting the
`DataFusionError` it received:
```rust
.map_err(|e| {
ArrowError::ComputeError(format!("Error evaluating filter predicate: {e:?}"))
})
```
Formatting the error discards its type. Every failure inside a predicate
pushed
into the parquet decoder reaches the caller as the same untyped
`ArrowError::ComputeError` carrying a `Debug` string, so a user error
such as a
failed cast is indistinguishable from an internal engine failure. Any
embedder
that classifies errors by variant, for example to decide whether a query
failed
because of the input or because of a bug, cannot do so for this path. It
also
reads badly, because the nested error is rendered with `Debug` rather
than
`Display`.
Reproduction with `datafusion-cli`:
```sql
COPY (SELECT 'not_an_int' AS s) TO 't.parquet' STORED AS PARQUET;
CREATE EXTERNAL TABLE t STORED AS PARQUET LOCATION 't.parquet';
SET datafusion.execution.parquet.pushdown_filters = true;
SELECT * FROM t WHERE CAST(s AS INT) = 1;
```
Before:
```
Error: Parquet error: External: Compute error: Error evaluating filter predicate: ArrowError(CastError("Cannot cast string 'not_an_int' to value of Int32 type"), Some(""))
```
After:
```
Error: Parquet error: External: External error: Error evaluating filter predicate
caused by
Arrow error: Cast error: Cannot cast string 'not_an_int' to value of Int32 type
```
## What changes are included in this PR?
`DatafusionArrowPredicate::evaluate` now converts the error instead of
formatting it:
```rust
.map_err(|e| e.context("Error evaluating filter predicate").into())
```
`From<DataFusionError> for ArrowError` is the conversion DataFusion
already
documents for this boundary. It leaves the original error in the
`Error::source`
chain, and the parquet decoder propagates it as
`ParquetError::External`, which
is also source preserving, so `DataFusionError::find_root` recovers the
original
variant at the top of the stack. Wrapping the error in a
`DataFusionError::Context` first keeps the description of where the
failure
happened, which the old string also carried.
One consequence worth calling out: because the context has to live
somewhere,
the returned `ArrowError` variant is `ExternalError` rather than the
original
Arrow variant. Callers that want the type use `find_root` (or walk
`Error::source`), which is the existing way to recover an error across
an
`ArrowError` boundary in DataFusion and is used the same way in
`datafusion/common/src/scalar/mod.rs` and `datafusion/physical-plan`.
Dropping
the context would yield a bare `ArrowError::CastError` here, at the cost
of no
longer saying which stage failed.
## Are these changes tested?
Yes. Two new tests, both of which fail without the change:
* `datafusion/datasource-parquet/src/row_filter.rs`:
`evaluate_reports_the_original_error` evaluates a predicate that fails
to cast
and asserts `find_root` returns the `CastError`, and that the message
still
names the predicate. Without the change it observes
`ArrowError(ComputeError("Error evaluating filter predicate:
ArrowError(CastError(...))"))`.
* `datafusion/core/tests/parquet/filter_pushdown.rs`:
`pushed_down_predicate_reports_the_original_error` runs the same failure
through a full parquet scan. It first asserts the predicate really is
pushed
into the scan and not left in a `FilterExec`, so the test cannot pass
vacuously, then asserts the same about the error the query returns.
Existing suites run locally: `cargo test -p
datafusion-datasource-parquet`,
`cargo test -p datafusion --test parquet_integration`, and the full
`sqllogictest` suite, all passing. No test expectation elsewhere
depended on the
old string.
## Are there any user-facing changes?
The text of the error raised when a pushed down parquet predicate fails
changes,
as shown above. There is no public API change.
---------
Co-authored-by: Claude Opus 5 <noreply@anthropic.com>1 parent 63f5b55 commit 1064661
2 files changed
Lines changed: 147 additions & 5 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
26 | 26 | | |
27 | 27 | | |
28 | 28 | | |
| 29 | + | |
29 | 30 | | |
| 31 | + | |
30 | 32 | | |
31 | | - | |
32 | 33 | | |
| 34 | + | |
33 | 35 | | |
34 | 36 | | |
35 | 37 | | |
36 | 38 | | |
37 | 39 | | |
38 | 40 | | |
39 | 41 | | |
| 42 | + | |
40 | 43 | | |
41 | 44 | | |
42 | 45 | | |
| 46 | + | |
43 | 47 | | |
| 48 | + | |
| 49 | + | |
44 | 50 | | |
45 | 51 | | |
46 | 52 | | |
| |||
746 | 752 | | |
747 | 753 | | |
748 | 754 | | |
| 755 | + | |
| 756 | + | |
| 757 | + | |
| 758 | + | |
| 759 | + | |
| 760 | + | |
| 761 | + | |
| 762 | + | |
| 763 | + | |
| 764 | + | |
| 765 | + | |
| 766 | + | |
| 767 | + | |
| 768 | + | |
| 769 | + | |
| 770 | + | |
| 771 | + | |
| 772 | + | |
| 773 | + | |
| 774 | + | |
| 775 | + | |
| 776 | + | |
| 777 | + | |
| 778 | + | |
| 779 | + | |
| 780 | + | |
| 781 | + | |
| 782 | + | |
| 783 | + | |
| 784 | + | |
| 785 | + | |
| 786 | + | |
| 787 | + | |
| 788 | + | |
| 789 | + | |
| 790 | + | |
| 791 | + | |
| 792 | + | |
| 793 | + | |
| 794 | + | |
| 795 | + | |
| 796 | + | |
| 797 | + | |
| 798 | + | |
| 799 | + | |
| 800 | + | |
| 801 | + | |
| 802 | + | |
| 803 | + | |
| 804 | + | |
| 805 | + | |
| 806 | + | |
| 807 | + | |
| 808 | + | |
| 809 | + | |
| 810 | + | |
| 811 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
166 | 166 | | |
167 | 167 | | |
168 | 168 | | |
| 169 | + | |
| 170 | + | |
| 171 | + | |
169 | 172 | | |
170 | | - | |
171 | | - | |
| 173 | + | |
| 174 | + | |
172 | 175 | | |
173 | 176 | | |
174 | 177 | | |
| |||
545 | 548 | | |
546 | 549 | | |
547 | 550 | | |
548 | | - | |
| 551 | + | |
549 | 552 | | |
550 | 553 | | |
551 | 554 | | |
552 | 555 | | |
553 | 556 | | |
554 | | - | |
| 557 | + | |
555 | 558 | | |
556 | 559 | | |
557 | 560 | | |
| |||
692 | 695 | | |
693 | 696 | | |
694 | 697 | | |
| 698 | + | |
| 699 | + | |
| 700 | + | |
| 701 | + | |
| 702 | + | |
| 703 | + | |
| 704 | + | |
| 705 | + | |
| 706 | + | |
| 707 | + | |
| 708 | + | |
| 709 | + | |
| 710 | + | |
| 711 | + | |
| 712 | + | |
| 713 | + | |
| 714 | + | |
| 715 | + | |
| 716 | + | |
| 717 | + | |
| 718 | + | |
| 719 | + | |
| 720 | + | |
| 721 | + | |
| 722 | + | |
| 723 | + | |
| 724 | + | |
| 725 | + | |
| 726 | + | |
| 727 | + | |
| 728 | + | |
| 729 | + | |
| 730 | + | |
| 731 | + | |
| 732 | + | |
| 733 | + | |
| 734 | + | |
| 735 | + | |
| 736 | + | |
| 737 | + | |
| 738 | + | |
| 739 | + | |
| 740 | + | |
| 741 | + | |
| 742 | + | |
| 743 | + | |
| 744 | + | |
| 745 | + | |
| 746 | + | |
| 747 | + | |
| 748 | + | |
| 749 | + | |
| 750 | + | |
| 751 | + | |
| 752 | + | |
| 753 | + | |
| 754 | + | |
| 755 | + | |
| 756 | + | |
| 757 | + | |
| 758 | + | |
| 759 | + | |
| 760 | + | |
| 761 | + | |
| 762 | + | |
| 763 | + | |
| 764 | + | |
| 765 | + | |
| 766 | + | |
| 767 | + | |
| 768 | + | |
| 769 | + | |
| 770 | + | |
| 771 | + | |
| 772 | + | |
| 773 | + | |
695 | 774 | | |
696 | 775 | | |
697 | 776 | | |
| |||
0 commit comments