LuciferYang commented on code in PR #67774:
URL: https://github.com/apache/doris/pull/67774#discussion_r3981184916


##########
be/src/exprs/function/functions_comparison.h:
##########
@@ -377,6 +436,24 @@ inline bool can_evaluate(const VExprSPtrs& arguments) {
     return true;
 }
 
+// Accept a comparison whose both operands are slot references. Kept separate 
from can_evaluate on
+// purpose: can_evaluate also gates dictionary filtering and 
can_evaluate_equality, and both of
+// those dereference extract_slot_and_literal behind a DORIS_CHECK, so 
widening it would abort on a
+// slot-vs-slot expression. Only can_evaluate_zonemap_filter ORs this in.
+inline bool can_evaluate_slot_slot(const VExprSPtrs& arguments) {
+    auto slot_slot = expr_zonemap::extract_slot_and_slot(arguments);
+    if (!slot_slot.has_value()) {
+        return false;
+    }
+    DORIS_CHECK(slot_slot->left_type != nullptr);
+    DORIS_CHECK(slot_slot->right_type != nullptr);
+    // The two zone maps' Fields are compared directly and Field comparison 
throws on mismatched

Review Comment:
   Confirmed, and thanks. I traced each step: `_type_matches` compares only 
`get_primitive_type()`, `parse_min_max_value` builds its converter with 
`col_schema->data_type` as both source and destination so the bounds land in 
the file domain, and `Field::operator<=>` for decimals compares unscaled 
payloads without aligning scale. Your example prunes a matching row group.
   
   One note on scope: this is not new in this PR. `WHERE a < 2.00` on a 
scale-mismatched v1 file already compares a literal in the expression domain 
against a bound in the file domain, so the single-column path has the same hole 
today. This PR extends the same unsound comparison to two-slot shapes, so it 
belongs here.
   
   Fixed in ece564a24ef, and not the way I first tried. My first attempt 
recorded `col_schema->data_type` in the context so that the existing 
`fetch_compatible_slot_type` check would reject the mismatch. That is worse 
than the bug: `fetch_compatible_slot_type` does 
`DORIS_CHECK(data_types_compatible(...))` rather than returning nullptr, so a 
real scale mismatch would have aborted the BE instead of degrading. I only 
found that because I wrote a test for it, which is your second comment's point 
exactly.
   
   What landed instead is your first suggestion: gate at the two v1 
context-construction sites and leave the zone map out unless 
`data_types_compatible(col_schema->data_type, slot->type())` holds. That keeps 
`ctx.data_type(cid) == slot->type()`, so the `DORIS_CHECK` invariant still 
cannot fire, and it is the same predicate `format_v2` already uses at 
`parquet_statistics.cpp:1136`, so v1 becomes consistent rather than getting a 
new rule.
   
   The gate costs pruning in three places, all now stated in the PR 
description: a DATETIMEV2 or TIMESTAMPTZ column whose declared scale differs 
from the Parquet unit loses expression zone map pruning entirely, which is the 
widest practical case; a decimal pair differing only in precision is 
domain-identical yet also skipped; and IS NULL / IS NOT NULL pruning goes with 
it, since a zone map carrying only the null flags leaves min/max at `TYPE_NULL` 
and any range predicate would then fail `range_stats_usable_for_zonemap`'s type 
check.
   
   One related hole I did not touch, because it predates this change and needs 
its own investigation: unsigned INTEGER logical types are marked 
`is_type_compatibility` in `schema_desc.cpp`, so the file type equals the 
widened table type and passes this gate, while `parse_min_max_value` 
reinterprets the statistic bytes as signed before widening.



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to