Skip to content

Commit

Permalink
Support function hints (#207)
Browse files Browse the repository at this point in the history
* Implement function hints

* Update testdata

* Fix CallExpr.SQL()
  • Loading branch information
apstndb authored Dec 18, 2024
1 parent bbd31cf commit f155be3
Show file tree
Hide file tree
Showing 7 changed files with 384 additions and 3 deletions.
4 changes: 3 additions & 1 deletion ast/ast.go
Original file line number Diff line number Diff line change
Expand Up @@ -1145,9 +1145,10 @@ type SubscriptSpecifierKeyword struct {
// {{.NullHandling | sqlOpt}}
// {{.Having | sqlOpt}}
// )
// {{.Hint | sqlOpt}}
type CallExpr struct {
// pos = Func.pos
// end = Rparen + 1
// end = Hint.end || Rparen + 1

Rparen token.Pos // position of ")"

Expand All @@ -1157,6 +1158,7 @@ type CallExpr struct {
NamedArgs []*NamedArg
NullHandling NullHandlingModifier // optional
Having HavingModifier // optional
Hint *Hint // optional
}

// ExprArg is argument of the generic function call.
Expand Down
2 changes: 1 addition & 1 deletion ast/pos.go

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

3 changes: 2 additions & 1 deletion ast/sql.go
Original file line number Diff line number Diff line change
Expand Up @@ -503,7 +503,8 @@ func (c *CallExpr) SQL() string {
sqlJoin(c.NamedArgs, ", ") +
sqlOpt(" ", c.NullHandling, "") +
sqlOpt(" ", c.Having, "") +
")"
")" +
sqlOpt(" ", c.Hint, "")
}

func (l *LambdaArg) SQL() string {
Expand Down
3 changes: 3 additions & 0 deletions parser.go
Original file line number Diff line number Diff line change
Expand Up @@ -1553,6 +1553,8 @@ func (p *Parser) parseCall(id token.Token) ast.Expr {
having := p.tryParseHavingModifier()

rparen := p.expect(")").Pos
hint := p.tryParseHint()

return &ast.CallExpr{
Rparen: rparen,
Func: fn,
Expand All @@ -1561,6 +1563,7 @@ func (p *Parser) parseCall(id token.Token) ast.Expr {
NamedArgs: namedArgs,
NullHandling: nullHandling,
Having: having,
Hint: hint,
}
}

Expand Down
5 changes: 5 additions & 0 deletions testdata/input/query/select_function_hints.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
-- https://cloud.google.com/spanner/docs/reference/standard-sql/functions-reference#function_hints
SELECT
SUBSTRING(CAST(x AS STRING), 2, 5) AS w,
SUBSTRING(CAST(x AS STRING), 3, 7) AS y
FROM (SELECT SHA512(z) @{DISABLE_INLINE = TRUE} AS x FROM t)
185 changes: 185 additions & 0 deletions testdata/result/query/select_function_hints.sql.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,185 @@
--- select_function_hints.sql
-- https://cloud.google.com/spanner/docs/reference/standard-sql/functions-reference#function_hints
SELECT
SUBSTRING(CAST(x AS STRING), 2, 5) AS w,
SUBSTRING(CAST(x AS STRING), 3, 7) AS y
FROM (SELECT SHA512(z) @{DISABLE_INLINE = TRUE} AS x FROM t)
--- AST
&ast.QueryStatement{
Query: &ast.Select{
Select: 99,
Results: []ast.SelectItem{
&ast.Alias{
Expr: &ast.CallExpr{
Rparen: 143,
Func: &ast.Ident{
NamePos: 110,
NameEnd: 119,
Name: "SUBSTRING",
},
Args: []ast.Arg{
&ast.ExprArg{
Expr: &ast.CastExpr{
Cast: 120,
Rparen: 136,
Expr: &ast.Ident{
NamePos: 125,
NameEnd: 126,
Name: "x",
},
Type: &ast.SimpleType{
NamePos: 130,
Name: "STRING",
},
},
},
&ast.ExprArg{
Expr: &ast.IntLiteral{
ValuePos: 139,
ValueEnd: 140,
Base: 10,
Value: "2",
},
},
&ast.ExprArg{
Expr: &ast.IntLiteral{
ValuePos: 142,
ValueEnd: 143,
Base: 10,
Value: "5",
},
},
},
},
As: &ast.AsAlias{
As: 145,
Alias: &ast.Ident{
NamePos: 148,
NameEnd: 149,
Name: "w",
},
},
},
&ast.Alias{
Expr: &ast.CallExpr{
Rparen: 188,
Func: &ast.Ident{
NamePos: 155,
NameEnd: 164,
Name: "SUBSTRING",
},
Args: []ast.Arg{
&ast.ExprArg{
Expr: &ast.CastExpr{
Cast: 165,
Rparen: 181,
Expr: &ast.Ident{
NamePos: 170,
NameEnd: 171,
Name: "x",
},
Type: &ast.SimpleType{
NamePos: 175,
Name: "STRING",
},
},
},
&ast.ExprArg{
Expr: &ast.IntLiteral{
ValuePos: 184,
ValueEnd: 185,
Base: 10,
Value: "3",
},
},
&ast.ExprArg{
Expr: &ast.IntLiteral{
ValuePos: 187,
ValueEnd: 188,
Base: 10,
Value: "7",
},
},
},
},
As: &ast.AsAlias{
As: 190,
Alias: &ast.Ident{
NamePos: 193,
NameEnd: 194,
Name: "y",
},
},
},
},
From: &ast.From{
From: 195,
Source: &ast.SubQueryTableExpr{
Lparen: 200,
Rparen: 254,
Query: &ast.Select{
Select: 201,
Results: []ast.SelectItem{
&ast.Alias{
Expr: &ast.CallExpr{
Rparen: 216,
Func: &ast.Ident{
NamePos: 208,
NameEnd: 214,
Name: "SHA512",
},
Args: []ast.Arg{
&ast.ExprArg{
Expr: &ast.Ident{
NamePos: 215,
NameEnd: 216,
Name: "z",
},
},
},
Hint: &ast.Hint{
Atmark: 218,
Rbrace: 241,
Records: []*ast.HintRecord{
&ast.HintRecord{
Key: &ast.Ident{
NamePos: 220,
NameEnd: 234,
Name: "DISABLE_INLINE",
},
Value: &ast.BoolLiteral{
ValuePos: 237,
Value: true,
},
},
},
},
},
As: &ast.AsAlias{
As: 243,
Alias: &ast.Ident{
NamePos: 246,
NameEnd: 247,
Name: "x",
},
},
},
},
From: &ast.From{
From: 248,
Source: &ast.TableName{
Table: &ast.Ident{
NamePos: 253,
NameEnd: 254,
Name: "t",
},
},
},
},
},
},
},
}

--- SQL
SELECT SUBSTRING(CAST(x AS STRING), 2, 5) AS w, SUBSTRING(CAST(x AS STRING), 3, 7) AS y FROM (SELECT SHA512(z) @{DISABLE_INLINE=TRUE} AS x FROM t)
Loading

0 comments on commit f155be3

Please sign in to comment.