why use ifValue instead of ifClause for switch expression

37 views
Skip to first unread message

chaojun zhang

unread,
Sep 7, 2022, 7:52:43 AM9/7/22
to substrait
 how should I convert it if my switch expression contains an expression condition?  I found  if condition in switch expression can only be a literal


Jeroen van Straten

unread,
Sep 7, 2022, 11:55:42 AM9/7/22
to Substrait
SwitchExpression models a C-style switch like this:

switch (<match>) {
  case <ifs[0].if>: return <ifs[0].then>;
  case <ifs[1].if>: return <ifs[1].then>;
  ...
  case <ifs[n].if>: return <ifs[n].then>;
  default: return <else>;
}

C also only allows the <ifs[*].if>s to be literals in this case. That being said, I see no reason why we couldn't just expand the logic to arbitrary expressions, and would be open to changing this. IfValue.if could be deprecated in favor of a new Expression field to retain backward compatibility. Semantically, you would just pick the first one that matches, so there's no need for uniqueness, and therefore no need for them to be literals for a static check.

For today's version of Substrait, you'd have to use IfThen if you need the switch cases to be non-literals. Each IfThen.ifs[i].if would then be set to an equality function binding [1] that compares the switch expression against the case expression. Borrowing C syntax again, you'd get something that looks like

if (<match> == <ifs[0].if>) return <ifs[0].then>;
else if (<match> == <ifs[1].if>) return <ifs[1].then>;
...
else if (<match> == <ifs[n].if>) return <ifs[n].then>;
else return <else>;

However, you would have to repeat the match expression for each branch, which could be a problem if the expressions have side effects, and could also be a performance issue. You can usually avoid that by inserting a project relation for the switch expression if it's nontrivial, so it just becomes a cheap FieldRef. Dealing with common subexpressions like that more elegantly is IMO an open problem. Inserting a new projection to eliminate a common subexpression is a very non-local operation, so if that's the only way I foresee a lot of spaghetti code for producers and optimizers.

[1] https://github.com/substrait-io/substrait/blob/de6bc9fad440880b6b5333cb0ee129d2c19e471c/extensions/functions_comparison.yaml#L20-L33

On Wed, 7 Sept 2022 at 13:52, chaojun zhang <zcj2...@gmail.com> wrote:
 how should I convert it if my switch expression contains an expression condition?  I found  if condition in switch expression can only be a literal


--
You received this message because you are subscribed to the Google Groups "substrait" group.
To unsubscribe from this group and stop receiving emails from it, send an email to substrait+...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/substrait/4fb4f6c7-bb96-417a-8040-a4f9272f8c1cn%40googlegroups.com.

chaojun zhang

unread,
Sep 7, 2022, 9:24:41 PM9/7/22
to substrait
Thanks, it works with ifThen. can you give me an example of how the if expression have side effects.

Jeroen van Straten

unread,
Sep 8, 2022, 3:23:03 AM9/8/22
to Substrait
You'd need something pretty contrived, like using a random() function inside the match expression. Of course, that also means you can't just repeat the expression for the IfElse without changing its behavior, because random() is also not deterministic.

I can't think of any other expressions in Substrait core that have side effects (and random() is still an open issue), but the points is that users are free to define their own function extensions, so any expression with a function in it that you don't know about could hypothetically have side effects. An example of a deterministic functions with side effects could be a function that writes its sole argument to some logging output and then returns it unchanged.

Reply all
Reply to author
Forward
0 new messages