Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 15 additions & 15 deletions book/src/super-sql/expressions/match.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,15 @@ A match expression is a multi-way [type assertion](type-assertions.md)
that selects a result according to the type of a value and has the form
```
match [<name>:=]<expr> [ with <assignments> ]
case <type-1> [then] <result-1>
[ case <type-2> [then] <result-2> ]
when <type-1> [then] <result-1>
[ when <type-2> [then] <result-2> ]
...
[ else <else-result> ]
[ end ]
```
where `<expr>` is any [expression](intro.md) and each `<type-n>` is any
[type](../types/intro.md). The value of `<expr>` is compared with each type
in turn and the result of the first matching `case` becomes the value of the
in turn and the result of the first matching `when` becomes the value of the
match expression. A value matches a type by the same rules as a
[type assertion](type-assertions.md), so a value of a
[union](../types/union.md), option, or fusion type matches the type of
Expand All @@ -26,9 +26,9 @@ unless a case has its type.

A result is evaluated with `this` bound to the value of `<expr>` asserted to
the type of its case, i.e., `<expr>.(<type>)`, so `this` in
`match x case int64 this+1` is an `int64`. The else result is evaluated
`match x when int64 this+1` is an `int64`. The else result is evaluated
with `this` bound to the value of `<expr>`. To keep the rest of a record,
use a [spread](../types/record.md), e.g., `{...this,x:match x case int64 this+1 else 0}`.
use a [spread](../types/record.md), e.g., `{...this,x:match x when int64 this+1 else 0}`.

To refer to other values in a result, give the match a name with `:=` or
list the values in a `with` clause. Then `this` in a result is a record
Expand All @@ -37,12 +37,12 @@ are the `with` values, where each field's name is given with `:=` or, as for
[put](../operators/put.md), derived from its expression (e.g., `upper(s)` is
named `upper` and `this` is named `that`). For example,
```
match s:=upper(s) with that:=this case string s||that.suffix
match s:=upper(s) with that:=this when string s||that.suffix
```
evaluates its result on `{s:upper(s).(string),that:this}`.

The `then` and `end` keywords are optional. Without `end`, a nested match
extends as far as possible, i.e., any `case` or `else` that follows belongs to
extends as far as possible, i.e., any `when` or `else` that follows belongs to
the innermost match, so a nested match should be parenthesized or ended with
`end`.

Expand All @@ -55,8 +55,8 @@ _Dispatch on the type of a value_
```mdtest-spq
# spq
values match this
case int64 this+1
case string upper(this)
when int64 this+1
when string upper(this)
else "other"
# input
1
Expand All @@ -78,8 +78,8 @@ type Push = {ref:string}
type Watch = {action:string}
values cast(this, <Push|Watch>)
| values match this
case Push "push to "||ref
case Watch "watch "||action
when Push "push to "||ref
when Watch "watch "||action
# input
{ref:"main"}
{action:"started"}
Expand All @@ -94,7 +94,7 @@ _Refer to other values with a with clause_

```mdtest-spq
# spq
values match x with y case int64 x+y case string x else y
values match x with y when int64 x+y when string x else y
# input
{x:1,y:10}
{x:"a",y:20}
Expand All @@ -111,7 +111,7 @@ _Without an else, an unmatched value is none_

```mdtest-spq
# spq
values {n:match x case int64 this*2}
values {n:match x when int64 this*2}
# input
{x:1}
{x:"a"}
Expand All @@ -127,8 +127,8 @@ _Errors pass through unless a case has an error type_
```mdtest-spq
# spq
values {
passed: match this case int64 this else 0,
caught: match this case int64 this case error(string) "caught" else 0
passed: match this when int64 this else 0,
caught: match this when int64 this when error(string) "caught" else 0
}
# input
1
Expand Down
2 changes: 1 addition & 1 deletion compiler/parser/parser.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion compiler/parser/parser.peg
Original file line number Diff line number Diff line change
Expand Up @@ -1363,7 +1363,7 @@ MatchExpr
}

MatchCase
= _ CASE _ typ:Type (_ THEN)? _ expr:Expr {
= _ WHEN _ typ:Type (_ THEN)? _ expr:Expr {
return ast.MatchCase{
Type: typ.(ast.Type),
Expr: expr.(ast.Expr),
Expand Down
2 changes: 1 addition & 1 deletion compiler/parser/valid.spq
Original file line number Diff line number Diff line change
Expand Up @@ -47,4 +47,4 @@ insert into "t" from 'x.json' | where a > 1;
const x = 1; values x
insert into baz (values 1,2|{x:this,y:this*2}); insert into baz (select 5, 6)
values a.(string) ?? "x", b.(int64|string), this.({x:int64}).x, c.d.(foo)?.e
values match x case int64 this+1 case string then upper(this) else 0 end, match this case {a:int64} a case Push ref, match s:=upper(s) with that:=this, n case string that.n else 0
values match x when int64 this+1 when string then upper(this) else 0 end, match this when {a:int64} a when Push ref, match s:=upper(s) with that:=this, n when string that.n else 0
2 changes: 1 addition & 1 deletion compiler/sfmt/ast.go
Original file line number Diff line number Diff line change
Expand Up @@ -161,7 +161,7 @@ func (c *canon) expr(e ast.Expr, parent string) {
c.assignments(e.With)
}
for _, mc := range e.Cases {
c.write(" case ")
c.write(" when ")
c.typ(mc.Type)
c.write(" then ")
c.expr(mc.Expr, "")
Expand Down
2 changes: 1 addition & 1 deletion compiler/sfmt/dag.go
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,7 @@ func (c *canonDAG) expr(e dag.Expr, parent string) {
c.write("match ")
c.expr(e.Expr, "")
for _, mc := range e.Cases {
c.write(" case ")
c.write(" when ")
c.expr(mc.Type, "")
if _, ok := mc.Input.(*dag.RecordExpr); ok {
c.write(" input ")
Expand Down
2 changes: 1 addition & 1 deletion runtime/ztests/expr/derive-name-noneish.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
# from it (e.g., by put, aggregate, a record expression, or match).
spq: |
put o?.y
| values this, {p.o?.y}, match o?.y with o?.z case int64 y+(z ?? 0) else 0
| values this, {p.o?.y}, match o?.y with o?.z when int64 y+(z ?? 0) else 0

input: |
{o:some({y:1,z:2}),p:{o:some({y:3})}}
Expand Down
44 changes: 22 additions & 22 deletions runtime/ztests/expr/match.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,9 @@
# result on the matched value.
spq: |
values match this
case int64 then this+1
case string upper(this)
case {a:int64} a
when int64 then this+1
when string upper(this)
when {a:int64} a
else "other"
end

Expand All @@ -25,7 +25,7 @@ output: |

# Unions, options, and fusions match their underlying values. (An option
# may be none, which no case matches, so an else is needed.)
spq: values match x case int64 this+1 case string this||"!" else "none"
spq: values match x when int64 this+1 when string this||"!" else "none"

input: |
{x:1::(int64|string)}
Expand All @@ -40,7 +40,7 @@ output: |
---

# Any expression may be matched and an unmatched value is none.
spq: values {v:match a.b case int64 this*10}
spq: values {v:match a.b when int64 this*10}

input: |
{a:{b:1}}
Expand All @@ -53,7 +53,7 @@ output: |
---

# A union-type case matches any of its members.
spq: values match this case int64|string "scalar" else "other"
spq: values match this when int64|string "scalar" else "other"

input: |
1
Expand All @@ -69,8 +69,8 @@ output: |

# Errors and missing pass through unless a case has an error type.
spq: |
values match this case int64 this,
match this case error(string) "caught" else "ok"
values match this when int64 this,
match this when error(string) "caught" else "ok"

input: |
1
Expand All @@ -87,7 +87,7 @@ output: |
# A match covering all members of a union has no none in its type.
spq: |
values cast(this, <int64|string>)
| values typeof(match this case int64 "i" case string "s")
| values typeof(match this when int64 "i" when string "s")

input: |
1
Expand All @@ -98,7 +98,7 @@ output: |
---

# Without end, else belongs to the innermost match.
spq: values match this case int64 match this case int64 "inner" else "x" case string "s"
spq: values match this when int64 match this when int64 "inner" else "x" when string "s"

input: |
1
Expand All @@ -111,11 +111,11 @@ output: |
---

# A match without an else may be none, which must be handled.
spq: values (match this case int64 this) + 1
spq: values (match this when int64 this) + 1

error: |
int64|none: none not handled (consider ?? or ?.) at line 1, column 9:
values (match this case int64 this) + 1
values (match this when int64 this) + 1
~~~~~~~~~~~~~~~~~~~~~~~~~~

---
Expand All @@ -135,9 +135,9 @@ output: |
# (including an option's none) matches its option type, and the first case
# whose type the value has wins.
spq: |
values match this case option(int64) "option" case int64 "int64" else "other",
match this case int64 "member" case int64|string "union" else "other",
match this case int64|string "union" case int64 "member" else "other"
values match this when option(int64) "option" when int64 "int64" else "other",
match this when int64 "member" when int64|string "union" else "other",
match this when int64|string "union" when int64 "member" else "other"

input: |
some(1)
Expand All @@ -158,7 +158,7 @@ output: |
---

# A subquery in a case has the case's input as its input.
spq: values match x case int64 then (values this+1) else 0
spq: values match x when int64 then (values this+1) else 0

input: |
{x:1::(int64|string)}
Expand All @@ -175,7 +175,7 @@ output: |
# A match with a with clause has a record input whose first field is the
# (asserted) matched value and whose other fields are the with values.
# Names are derived from the expressions as for put.
spq: values match x with y case int64 x+y case string x else y
spq: values match x with y when int64 x+y when string x else y

input: |
{x:1,y:10}
Expand All @@ -192,9 +192,9 @@ output: |
# A derived name for a function call is the function's name and for this is
# "that", and a name may be given with :=.
spq: |
values match upper(s) with this case string upper||"/"||that.s else "",
match s:=upper(s) with that:=this case string s||"/"||that.s else "",
match s:=upper(s) case string s||"!" else ""
values match upper(s) with this when string upper||"/"||that.s else "",
match s:=upper(s) with that:=this when string s||"/"||that.s else "",
match s:=upper(s) when string s||"!" else ""

input: |
{s:"a"}
Expand All @@ -207,12 +207,12 @@ output: |
---

# The field names of a match's input must be unique.
spq: values match x with x case int64 1 else 0
spq: values match x with x when int64 1 else 0

input: |
{x:1}

error: |
match: duplicate field name "x" at line 1, column 21:
values match x with x case int64 1 else 0
values match x with x when int64 1 else 0
~
Loading