fordN opened a new pull request, #23395:
URL: https://github.com/apache/datafusion/pull/23395

   ## Which issue does this PR close?
   
   - Closes #23220.
   
   ## Rationale for this change
   
   The reported bug showed that when volatile (non-deterministic) expressions 
are referenced multiple times in an outer function the query results can be 
incorrect. 
   
   To produce correct results, a volatile expression (e.g. `random()`, 
`uuid()`) aliased once in a subquery and referenced multiple times must be 
evaluated once and reused. Since 52.0.0 this evaluation pattern for volatile 
functions has been broken; the physical projection-pushdown rule merges the 
outer projection into the file `DataSourceExec`, inlining the aliased volatile 
expression at each reference site. Instead of being evaluated once, the 
volatile expression is evaluated N times, so the references diverge:
   
   ```sql
   SELECT s.r AS x, s.r AS y FROM (SELECT random() AS r FROM t) AS s;  -- x != 
y on >= 52.0.0
   ```
   
   This was correct in 51.0.0 and regressed in 52.0.0/53.0.0. It reproduces on 
file scans (Parquet/CSV) but not in-memory tables, and was surfaced downstream 
in Ibis. Worth noting, #10337 appears to report the same class of bug but a 
different cause (I'll try to look into that issue soon as well).
   
   ## What changes are included in this PR?
   
   `FileScanConfig::try_swapping_with_projection` now declines to merge a 
projection into the file source when the merge would inline a volatile 
expression that the incoming projection references. The check reuses the 
existing `is_volatile()` utility from `datafusion_physical_expr_common` — the 
same volatility gate the physical `ProjectionPushdown` and `FilterPushdown` 
rules already apply — so file-source projection merging is now consistent with 
them. Deterministic expressions still merge freely.
   
   The guard blocks when a volatile inner expression is referenced at least 
once (not only more than once), because a single outer expression can itself 
duplicate the value (e.g.`r + r`).
   
   ## Are these changes tested?
   
   Yes:
   - Unit tests in `file_scan_config.rs`: 
       - volatile referenced ≥1× → blocked; 
       - deterministic computed and column-only → allowed; 
       - unreferenced volatile → allowed; 
       - single-expression self-reference (`r + r`) → blocked; 
       - volatile nested in arithmetic → blocked; 
       - empty → allowed.
   - A regression test in `projection_pushdown.slt` asserting `x = y` for the 
aliased-`random()` pattern over a Parquet scan.
   - Full `datafusion-sqllogictest` suite passes.
   
   ## Are there any user-facing changes?
   
   No API changes! Query results for the affected pattern are corrected (a 
volatile expression aliased in a subquery is no longer duplicated by projection 
pushdown into a file scan). Physical plans for such queries now retain a 
`ProjectionExec` above the scan rather than inlining the volatile expression 
into the `DataSourceExec` projection.
   


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