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]
