namanjain24-sudo commented on issue #25190:
URL: https://github.com/apache/datafusion/issues/25190#issuecomment-5641220048

   Yes, compatibility, and this one reproduces on a DataFusion plan with 
nothing worked around. The
   engine is substrait-java `io.substrait:core:0.103.0`.
   
   `SELECT CASE a WHEN 1 THEN 'x' WHEN 2 THEN 'y' ELSE 'z' END FROM data`, one 
nullable `i64` column,
   through `to_substrait_plan`, produces an `IfThen` shaped like this:
   
   ```
   clause 0:  if = SELECTION (column a)   then = <unset>
   clause 1:  if = LITERAL i64 1          then = "x"
   clause 2:  if = LITERAL i64 2          then = "y"
   else                                          "z"
   ```
   
   Handing that protobuf straight to `ProtoPlanConverter`:
   
   ```
   java.lang.IllegalArgumentException: Unknown type: REXTYPE_NOT_SET
     at 
io.substrait.expression.proto.ProtoExpressionConverter.from(ProtoExpressionConverter.java:364)
     at 
io.substrait.expression.proto.ProtoExpressionConverter.lambda$from$1(ProtoExpressionConverter.java:212)
   ```
   
   Line 212 is `ExpressionCreator.ifThenClause(from(t.getIf()), 
from(t.getThen()))`. It converts `then`
   unconditionally and clause 0 does not have one. This plan registers no 
functions at all, so unlike
   #25049 there is no extension-URN problem in the way: it is a straight 
failure on what we emit today.
   
   Two things are wrong here and only one of them throws, which is worth 
separating:
   
   1. **Clause 0 carries the base expression with no `then`.** That is the hard 
failure above.
   2. **The conditions are not boolean.** They are `a`, then `1`, then `2`, all 
`i64`. The spec's if
      expression is `if <boolean expression> then ...`. I checked whether 
substrait-java objects to
      that on its own — drop clause 0 and feed it the remaining two clauses, 
and it **accepts** them.
      It does not type-check `if`. So that half is a silent divergence, not an 
error, which is also why
      no round trip anywhere would surface it.
   
   With #25191 every clause becomes `equal(a, <value>)` carrying `output_type: 
bool` and a `then`, and
   the same query is accepted, giving `Struct{nullable=false, 
fields=[Str{nullable=false}]}`. That plan
   does need the #11545 workaround, because it now registers the `equal` 
function and we still write
   `extension_urn_reference: u32::MAX`.
   
   On `SwitchExpression`, since it is the obvious alternative and I should say 
why I did not use it:
   `SwitchExpression.IfValue.if` is a `Literal`, so it cannot express `CASE a 
WHEN b + 1`, and our own
   consumer answers `not_impl_err!("Switch expression not supported")`
   (`logical_plan/consumer/substrait_consumer.rs:348`). Emitting it would need 
consumer work first and
   would still need this desugaring as the fallback, so I left it as a 
follow-up rather than folding it
   into the same change.


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