Braedon-Wooding-Displayr opened a new issue, #24042:
URL: https://github.com/apache/datafusion/issues/24042

   ### Describe the bug
   
   If the same expression is written in both the SELECT list and the GROUP BY, 
and it
   contains a placeholder, the two do not compare equal in the logical plan. The
   grouping key is therefore not recognised as covering the SELECT expression, 
and any
   column inside it is reported as ungrouped. Replacing the placeholder with a 
literal
   makes the identical query plan fine.
   
   The cause is that the two clauses are planned by different entry points.
   `sql_to_expr`, used for the SELECT list, ends with a call to
   `Expr::infer_placeholder_types`. The GROUP BY clause is planned by
   `sql_expr_to_logical_expr` (`sql/src/select.rs`), which does not. So the 
projection
   holds `Placeholder { field: Some(..) }` and the grouping key holds
   `Placeholder { field: None }`, and `Expr` equality fails on the `field`.
   
   HAVING, QUALIFY (both in `select.rs`) and ORDER BY 
(`sql/src/expr/order_by.rs`) are
   planned the same way and have the same problem. DISTINCT ON and DISTRIBUTE 
BY also
   skip inference, though nothing compares those against the SELECT list.
   
   `PREPARE` is unaffected when the parameter type is declared, since the type 
is then
   known at parse time in both positions.
   
   ### To Reproduce
   
   Against a table `t(x bigint)`:
   
   ```sql
   -- fails to plan
   SELECT CASE WHEN x < $1 THEN 'low' ELSE 'high' END, count(*)
   FROM t
   GROUP BY CASE WHEN x < $1 THEN 'low' ELSE 'high' END;
   ```
   
   ```
   Error during planning: Column in SELECT must be in GROUP BY or an aggregate 
function:
   While expanding wildcard, column "t.x" must appear in the GROUP BY clause or 
must be
   part of an aggregate function, currently only "CASE WHEN t.x < $1 THEN 
Utf8("low")
   ELSE Utf8("high") END, count(Int64(1))" appears in the SELECT clause 
satisfies this
   requirement
   ```
   
   Note that the error lists the CASE as satisfying the requirement while still 
rejecting the column inside it.
   
   Both of these plan without complaint:
   
   ```sql
   -- literal instead of the placeholder
   SELECT CASE WHEN x < 3 THEN 'low' ELSE 'high' END, count(*)
   FROM t
   GROUP BY CASE WHEN x < 3 THEN 'low' ELSE 'high' END;
   
   -- placeholder, but with a declared type
   PREPARE p(BIGINT) AS
   SELECT CASE WHEN x < $1 THEN 'low' ELSE 'high' END, count(*)
   FROM t
   GROUP BY CASE WHEN x < $1 THEN 'low' ELSE 'high' END;
   ```
   
   Reproduced on main.
   
   ### Expected behavior
   
   The placeholder version should plan the same as the literal version. 
Identical text in the SELECT list and the GROUP BY should produce one 
expression, so the CASE covers `x` and no further grouping is required.
   
   Calling `infer_placeholder_types` on the planned GROUP BY, HAVING, QUALIFY 
and ORDER BY expressions, as `sql_to_expr` already does for the SELECT list, is 
enough to fix it.
   
   ### Additional context
   
   Somewhat vaguely similar to #19321 though that's related to typing and this 
is just a parsing bug.


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