adriangb opened a new issue, #26910:
URL: https://github.com/apache/datafusion/issues/26910

   ### Describe the bug
   
   The preimage rewrite in the expression simplifier copies the argument of the 
function. When the argument is volatile, the copy makes the query evaluate it 
two times per row, and the query returns wrong results.
   
   `floor(random() * 10) = 3` becomes `random() * 10 >= 3 AND random() * 10 < 
4`. Each `random()` draws a new value, so about 28% of rows pass (0.7 × 0.4), 
not 10%.
   
   ### To Reproduce
   
   In `datafusion-cli`:
   
   ```sql
   SELECT count(*) FROM generate_series(1, 1000000) WHERE floor(random() * 10) 
= 3;
   -- 279881  (expected about 100000)
   
   EXPLAIN SELECT count(*) FROM generate_series(1, 1000000) WHERE 
floor(random() * 10) = 3;
   -- FilterExec predicate: random() * 10 >= 3 AND random() * 10 < 4
   ```
   
   For comparison, a filter the rewrite does not touch gives the expected count:
   
   ```sql
   SELECT count(*) FROM (SELECT floor(random() * 10) AS f FROM 
generate_series(1, 1000000)) WHERE f + 0 = 3;
   -- 99997
   ```
   
   ### Expected behavior
   
   The rewrite does not apply when an argument is volatile. `get_preimage` in 
`expr_simplifier.rs` already checks that the function is immutable. It must 
also check `args.iter().any(Expr::is_volatile)`.
   
   ### Additional context
   
   Found while working on #25459. The same fix is in the combined draft #26873, 
with sqllogictest cases in `floor_preimage.slt`. Related: #25457 (the same kind 
of copy in `BETWEEN`).
   


-- 
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