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

   ### Describe the bug
   
   Unparsing the optimized plan of a simple `count(*)` query with a filter 
produces `SELECT FROM ...` (an empty select list), even for dialects whose 
`supports_empty_select_list()` is `false`. Engines that don't accept an empty 
select list reject the generated SQL. For example, BigQuery fails with:
   
   ```
   SELECT list must not be empty
   ```
   
   The column used in the filter isn't needed above the `Filter`, so 
`optimize_projections` prunes it and leaves a `Projection` with no expressions:
   
   ```
   Projection: count(Int64(1)) AS count(*)
     Aggregate: groupBy=[[]], aggr=[[count(Int64(1))]]
       Projection:
         Filter: t.id > Int32(10)
           TableScan: t projection=[id]
   ```
   
   #19221 (closing #18991) added `Dialect::supports_empty_select_list` and a 
`SELECT 1` fallback, but only the `TableScan` path checks it (the case where 
the scan has `projection=[]`, as in `select count(*) from t` with no filter). 
An empty `Projection` node goes through `reconstruct_select_statement`, which 
uses `p.expr` as is.
   
   ### To Reproduce
   
   ```rust
   use datafusion::prelude::SessionContext;
   use datafusion::sql::unparser::plan_to_sql;
   
   let ctx = SessionContext::new();
   ctx.sql("create table t (id int)").await?.collect().await?;
   let plan = ctx
       .sql("select count(*) from t where id > 10")
       .await?
       .into_optimized_plan()?;
   println!("{}", plan_to_sql(&plan)?);
   ```
   
   Output (default dialect):
   
   ```sql
   SELECT count(1) AS "count(*)" FROM (SELECT FROM t WHERE (t.id > 10))
   ```
   
   `BigQueryDialect` produces the same thing with backtick quoting.
   
   ### Expected behavior
   
   An empty `Projection` should get the same dialect-dependent fallback as an 
empty `TableScan` projection:
   
   - Dialects with `supports_empty_select_list() == false` (default, BigQuery, 
...):
     ```sql
     SELECT count(1) AS "count(*)" FROM (SELECT 1 FROM t WHERE (t.id > 10))
     ```
   - Dialects that support it (PostgreSQL): unchanged, `SELECT FROM ...`
   
   ### Additional context
   
   The fix is small: in `reconstruct_select_statement` 
(`datafusion/sql/src/unparser/plan.rs`), use `self.empty_projection_fallback()` 
when `p.expr` is empty. I'll open a PR with the fix and tests.
   


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