Skip to content

Commit

Permalink
feat(spanner/spansql): add support for if expressions (#6341)
Browse files Browse the repository at this point in the history
Co-authored-by: rahul2393 <rahulyadavsep92@gmail.com>
  • Loading branch information
neglect-yp and rahul2393 committed Jul 19, 2022
1 parent 882b325 commit 56c858c
Show file tree
Hide file tree
Showing 5 changed files with 77 additions and 0 deletions.
35 changes: 35 additions & 0 deletions spanner/spansql/parser.go
Original file line number Diff line number Diff line change
Expand Up @@ -3007,6 +3007,9 @@ func (p *parser) parseLit() (Expr, *parseError) {
case tok.caseEqual("CASE"):
p.back()
return p.parseCaseExpr()
case tok.caseEqual("IF"):
p.back()
return p.parseIfExpr()
}

// Handle typed literals.
Expand Down Expand Up @@ -3117,6 +3120,38 @@ func (p *parser) parseWhenClause() (WhenClause, *parseError) {
return WhenClause{Cond: cond, Result: result}, nil
}

func (p *parser) parseIfExpr() (If, *parseError) {
if err := p.expect("IF", "("); err != nil {
return If{}, err
}

expr, err := p.parseBoolExpr()
if err != nil {
return If{}, err
}
if err := p.expect(","); err != nil {
return If{}, err
}

trueResult, err := p.parseExpr()
if err != nil {
return If{}, err
}
if err := p.expect(","); err != nil {
return If{}, err
}

elseResult, err := p.parseExpr()
if err != nil {
return If{}, err
}
if err := p.expect(")"); err != nil {
return If{}, err
}

return If{Expr: expr, TrueResult: trueResult, ElseResult: elseResult}, nil
}

func (p *parser) parseArrayLit() (Array, *parseError) {
// ARRAY keyword is optional.
// TODO: If it is present, consume any <T> after it.
Expand Down
7 changes: 7 additions & 0 deletions spanner/spansql/parser_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -411,6 +411,13 @@ func TestParseExpr(t *testing.T) {
},
},
},
{`IF(A < B, TRUE, FALSE)`,
If{
Expr: ComparisonOp{LHS: ID("A"), Op: Lt, RHS: ID("B")},
TrueResult: True,
ElseResult: False,
},
},

// String literal:
// Accept double quote and single quote.
Expand Down
11 changes: 11 additions & 0 deletions spanner/spansql/sql.go
Original file line number Diff line number Diff line change
Expand Up @@ -733,6 +733,17 @@ func (c Case) addSQL(sb *strings.Builder) {
sb.WriteString("END")
}

func (i If) SQL() string { return buildSQL(i) }
func (i If) addSQL(sb *strings.Builder) {
sb.WriteString("IF(")
i.Expr.addSQL(sb)
sb.WriteString(", ")
i.TrueResult.addSQL(sb)
sb.WriteString(", ")
i.ElseResult.addSQL(sb)
sb.WriteString(")")
}

func (b BoolLiteral) SQL() string { return buildSQL(b) }
func (b BoolLiteral) addSQL(sb *strings.Builder) {
if b {
Expand Down
15 changes: 15 additions & 0 deletions spanner/spansql/sql_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -656,6 +656,21 @@ func TestSQL(t *testing.T) {
`SELECT CASE WHEN TRUE THEN "X" WHEN FALSE THEN "Y" END`,
reparseQuery,
},
{
Query{
Select: Select{
List: []Expr{
If{
Expr: ComparisonOp{LHS: IntegerLiteral(1), Op: Lt, RHS: IntegerLiteral(2)},
TrueResult: True,
ElseResult: False,
},
},
},
},
`SELECT IF(1 < 2, TRUE, FALSE)`,
reparseQuery,
},
}
for _, test := range tests {
sql := test.data.SQL()
Expand Down
9 changes: 9 additions & 0 deletions spanner/spansql/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -738,6 +738,15 @@ type WhenClause struct {
Result Expr
}

type If struct {
Expr Expr
TrueResult Expr
ElseResult Expr
}

func (If) isBoolExpr() {} // possibly bool
func (If) isExpr() {}

type BoolLiteral bool

const (
Expand Down

0 comments on commit 56c858c

Please sign in to comment.