Repository: cloudspannerecosystem/memefish
Pull request #63 (2023-08-24 07:38:41)

Add the support of the sequence functions
For more information can refer: https://cloud.google.com/spanner/docs/reference/standard-sql/sequence_functions

git-hulk: > IMO, we should treat `SEQUENCE` expressions as argument modifiers like `INTERVAL`.
> 
> https://github.com/cloudspannerecosystem/memefish/blob/1b120de904be1345085ee862d3d061476dc2db2f/ast/ast.go#L881-L896
> 
> However, adding new fileds to `Arg` seems bad to me. We should split `Arg` to a new interface `Arg` and the following three `Arg` types are needed:
> 
> * `IntervalArg`
> * `SequenceArg`
> * `ExprArg`
> 
> @git-hulk What do you think?

Good point, SequenceArg is exactly better than SequenceExpr. I will fix it soon.
makenowjust: @git-hulk You assume all sequence functions take only one argument. It is true so far, but will it be true in the future? I think we should not accept such an assumption.

Could you check [my above comment](https://github.com/cloudspannerecosystem/memefish/pull/63#issuecomment-1695085601) again? I guess you have not understood this yet. Feel free to ask me if you have any questions/comments!
git-hulk: > @git-hulk You assume all sequence functions take only one argument. It is true so far, but will it be true in the future? I think this assumption is poorly extensible and we should not accept such an assumption.
> 
> Could you check [my above comment](https://github.com/cloudspannerecosystem/memefish/pull/63#issuecomment-1695085601) again? I guess you have not understood this yet. Feel free to ask me if you have any questions/comments!

Yes, I misunderstood your comment. What you mean is to treat the Sequence function as a normal function, and then support parsing the sequence argument in parseArg, is that right?

git-hulk: > @git-hulk Yes, that's right!

Done, a lot of sorry for misunderstanding your first comment.
makenowjust: @git-hulk Okay. We encountered the next problem: mismatching between the AST definitions and the parser structure.

- - -

For now, `parseArg` can return one of three kinds of arguments: `SEQUENCE` arguments, `INTERVAL` arguments, or usual arguments. However, the `Arg` type only supports `INTERVAL` and usual arguments, but `SEQUENCE` arguments are represented by `Arg` of `SequenceArg` expression. In other words, `parseArg` is now `parseArgOrArgOfSequenceArg`. It sounds really bad to me.

The first solution to this problem is extending `Arg` to support `SEQUENCE` argument like:

```golang
type Arg struct {
	// pos = Interval || Sequence || Expr.pos
	// end = (IntervalUnit ?? Expr).end

	Interval token.Pos // position of "INTERVAL" keyword
    Sequence token.Pos // position of "SEQUENCE" keyword

	Expr         Expr
	IntervalUnit *Ident // optional
}
```

However, **it seems wrong to me** because this `Arg` can have two states at the same time. That is, when both `Interval` and `Sequence` of `Arg` are valid, it is not possible to determine which one should be treated correctly.

- - -

So, let's make `Arg` an interface and separate the roles of `Arg` (usual, `INTERVAL`, and `SEQUENCE` arguments).

```golang
type Arg interface {
	Node
	isArg()
}

func (ExprArg)     isArg()
func (IntervalArg) isArg()
func (SequenceArg) isArg()

type ExprArg struct {
	// pos = Expr.pos
	// end = Expr.end

	Expr Expr
}

type IntervalArg struct {
	// pos = Interval
	// end = Unit.end

	Interval token.Pos // position of "INTERVAL" keyword

	Expr Expr
	Unit *Ident
}

type SequenceArg struct {
	// pos = Sequence
	// end = Expr.end

	Sequence token.Pos // position of "SEQUENCE" keyword

	Expr Expr
}
```

Then, the `parseArg` should be rewritten:

```golang
func (p *Parser) parseArg() ast.Arg {
	if i := p.tryParseIntervalArg(); i != nil {
		return i
	}
	if s := p.tryParseSequenceArg(); s != nil {
		return s
	}
	return p.parseExprArg()
}
```

Finally, by implementing `tryParseIntervalArg`, `tryParseSequenceArg`, and `parseExprArg`, the AST definitions and the parser structure are matched.

- - -

Sorry for the long comment. This is my intention for the first comment. You could also feel free to ask me.

Patch:
diff --git a/ast/ast.go b/ast/ast.go
index a333535..3f823b9 100644
--- a/ast/ast.go
+++ b/ast/ast.go
@@ -147,6 +147,16 @@ func (DateLiteral) isExpr()      {}
 func (TimestampLiteral) isExpr() {}
 func (NumericLiteral) isExpr()   {}
 
+// Arg represents argument of function call.
+type Arg interface {
+	Node
+	isArg()
+}
+
+func (ExprArg) isArg()     {}
+func (IntervalArg) isArg() {}
+func (SequenceArg) isArg() {}
+
 // InCondition is right-side value of IN operator.
 type InCondition interface {
 	Node
@@ -877,24 +887,42 @@ type CallExpr struct {
 
 	Func     *Ident
 	Distinct bool
-	Args     []*Arg
+	Args     []Arg
 }
 
-// Arg is function call argument.
+// ExprArg is argument of the generic function call.
 //
-//	{{if .IntervalUnit}}
-//	  INTERVAL {{.Expr | sql}} {{.IntervalUnit | sql}}
-//	{{else}}
-//	  {{.Expr | sql}}
-//	{{end}}
-type Arg struct {
-	// pos = Interval || Expr.pos
-	// end = (IntervalUnit ?? Expr).end
+//	{{.Expr | sql}}
+type ExprArg struct {
+	// pos = Expr.pos
+	// end = Expr.end
+
+	Expr Expr
+}
+
+// IntervalArg is argument of date function call.
+//
+//	INTERVAL {{.Expr | sql}} {{.Unit | sqlOpt}}
+type IntervalArg struct {
+	// pos = Interval
+	// end = (Unit ?? Expr).end
 
 	Interval token.Pos // position of "INTERVAL" keyword
 
-	Expr         Expr
-	IntervalUnit *Ident // optional
+	Expr Expr
+	Unit *Ident // optional
+}
+
+// SequenceArg is argument of sequence function call.
+//
+//	SEQUENCE {{.Expr | sql}}
+type SequenceArg struct {
+	// pos = Sequence
+	// end = Expr.end
+
+	Sequence token.Pos // position of "SEQUENCE" keyword
+
+	Expr Expr
 }
 
 // CountStarExpr is node just for COUNT(*).
diff --git a/ast/pos.go b/ast/pos.go
index a8085e5..b1faa55 100644
--- a/ast/pos.go
+++ b/ast/pos.go
@@ -314,20 +314,20 @@ func (i *IndexExpr) End() token.Pos { return i.Rbrack + 1 }
 func (c *CallExpr) Pos() token.Pos { return c.Func.Pos() }
 func (c *CallExpr) End() token.Pos { return c.Rparen + 1 }
 
-func (a *Arg) Pos() token.Pos {
-	if !a.Interval.Invalid() {
-		return a.Interval
-	}
-	return a.Expr.Pos()
-}
+func (e *ExprArg) Pos() token.Pos { return e.Expr.Pos() }
+func (e *ExprArg) End() token.Pos { return e.Expr.End() }
 
-func (a *Arg) End() token.Pos {
-	if a.IntervalUnit != nil {
-		return a.IntervalUnit.End()
+func (i *IntervalArg) Pos() token.Pos { return i.Interval }
+func (i *IntervalArg) End() token.Pos {
+	if i.Unit != nil {
+		return i.Unit.End()
 	}
-	return a.Expr.End()
+	return i.Expr.End()
 }
 
+func (s *SequenceArg) Pos() token.Pos { return s.Sequence }
+func (s *SequenceArg) End() token.Pos { return s.Expr.End() }
+
 func (c *CountStarExpr) Pos() token.Pos { return c.Count }
 func (c *CountStarExpr) End() token.Pos { return c.Rparen + 1 }
 
diff --git a/ast/sql.go b/ast/sql.go
index facfbcb..4d9fb95 100644
--- a/ast/sql.go
+++ b/ast/sql.go
@@ -489,11 +489,24 @@ func (c *CallExpr) SQL() string {
 	return sql
 }
 
-func (a *Arg) SQL() string {
-	if a.IntervalUnit != nil {
-		return "INTERVAL " + a.Expr.SQL() + " " + a.IntervalUnit.SQL()
+func (o *SequenceOption) SQL() string {
+	return o.Name.SQL() + " = " + o.Value.SQL()
+}
+
+func (s *ExprArg) SQL() string {
+	return s.Expr.SQL()
+}
+
+func (i *IntervalArg) SQL() string {
+	sql := "INTERVAL " + i.Expr.SQL()
+	if i.Unit != nil {
+		sql += " " + i.Unit.SQL()
 	}
-	return a.Expr.SQL()
+	return sql
+}
+
+func (s *SequenceArg) SQL() string {
+	return "SEQUENCE " + s.Expr.SQL()
 }
 
 func (*CountStarExpr) SQL() string {
@@ -1128,7 +1141,3 @@ func (u *UpdateItem) SQL() string {
 	sql += " = " + u.Expr.SQL()
 	return sql
 }
-
-func (o *SequenceOption) SQL() string {
-	return o.Name.SQL() + " = " + o.Value.SQL()
-}
diff --git a/go.mod b/go.mod
index ddd1aeb..cfc6216 100644
--- a/go.mod
+++ b/go.mod
@@ -6,16 +6,11 @@ require (
 	github.com/MakeNowJust/heredoc/v2 v2.0.1
 	github.com/google/go-cmp v0.5.9
 	github.com/k0kubun/pp v1.3.1-0.20200204103551-99835366d1cc
-	github.com/olekukonko/tablewriter v0.0.1
 	github.com/pmezard/go-difflib v1.0.0
-	gopkg.in/yaml.v2 v2.2.8
 )
 
 require (
-	github.com/kr/pretty v0.1.0 // indirect
 	github.com/mattn/go-colorable v0.1.4 // indirect
 	github.com/mattn/go-isatty v0.0.12 // indirect
-	github.com/mattn/go-runewidth v0.0.4 // indirect
 	golang.org/x/sys v0.1.0 // indirect
-	gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 // indirect
 )
diff --git a/go.sum b/go.sum
index 6129389..aef80fa 100644
--- a/go.sum
+++ b/go.sum
@@ -6,28 +6,14 @@ github.com/k0kubun/colorstring v0.0.0-20150214042306-9440f1994b88 h1:uC1QfSlInpQ
 github.com/k0kubun/colorstring v0.0.0-20150214042306-9440f1994b88/go.mod h1:3w7q1U84EfirKl04SVQ/s7nPm1ZPhiXd34z40TNz36k=
 github.com/k0kubun/pp v1.3.1-0.20200204103551-99835366d1cc h1:XLjmW07gT7cG/wb6mavIrvAIWBYaTacPo8UOnxGSspA=
 github.com/k0kubun/pp v1.3.1-0.20200204103551-99835366d1cc/go.mod h1:qK2ivXw91omfE1uXcpR5kWbAMZRdDOnGbqWlZ7reRFk=
-github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI=
-github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
-github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
-github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
-github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
 github.com/mattn/go-colorable v0.1.4 h1:snbPLB8fVfU9iwbbo30TPtbLRzwWu6aJS6Xh4eaaviA=
 github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE=
 github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
 github.com/mattn/go-isatty v0.0.12 h1:wuysRhFDzyxgEmMf5xjvJ2M9dZoWAXNNr5LSBS7uHXY=
 github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
-github.com/mattn/go-runewidth v0.0.4 h1:2BvfKmzob6Bmd4YsL0zygOqfdFnK7GR4QL06Do4/p7Y=
-github.com/mattn/go-runewidth v0.0.4/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU=
-github.com/olekukonko/tablewriter v0.0.1 h1:b3iUnf1v+ppJiOfNX4yxxqfWKMQPZR5yoh8urCTFX88=
-github.com/olekukonko/tablewriter v0.0.1/go.mod h1:vsDQFd/mU46D+Z4whnwzcISnGGzXWMclvtLoiIKAKIo=
 github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
 github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
 golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
 golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.1.0 h1:kunALQeHf1/185U1i0GOB/fy1IPRDDpuoOOqRReG57U=
 golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
-gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo=
-gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
-gopkg.in/yaml.v2 v2.2.8 h1:obN1ZagJSUGI0Ek/LBmuj4SNLPfIny3KsKFopxRdj10=
-gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
diff --git a/parser.go b/parser.go
index 60155d0..fda836a 100644
--- a/parser.go
+++ b/parser.go
@@ -99,6 +99,27 @@ func (p *Parser) ParseExpr() (expr ast.Expr, err error) {
 	return
 }
 
+// ParseType parses a type name.
+func (p *Parser) ParseType() (typ ast.Type, err error) {
+	defer func() {
+		if r := recover(); r != nil {
+			typ = nil
+			if e, ok := r.(*Error); ok {
+				err = e
+			} else {
+				panic(r)
+			}
+		}
+	}()
+
+	p.nextToken()
+	typ = p.parseType()
+	if p.Token.Kind != token.TokenEOF {
+		p.panicfAtToken(&p.Token, "expected token: <eof>, but: %s", p.Token.Kind)
+	}
+	return
+}
+
 // ParseDDL parses a CREATE/ALTER/DROP statement.
 func (p *Parser) ParseDDL() (ddl ast.DDL, err error) {
 	defer func() {
@@ -1437,7 +1458,7 @@ func (p *Parser) parseCall(id token.Token) ast.Expr {
 		distinct = true
 	}
 
-	var args []*ast.Arg
+	var args []ast.Arg
 	if p.Token.Kind != ")" {
 		for p.Token.Kind != token.TokenEOF {
 			args = append(args, p.parseArg())
@@ -1456,23 +1477,50 @@ func (p *Parser) parseCall(id token.Token) ast.Expr {
 	}
 }
 
-func (p *Parser) parseArg() *ast.Arg {
+func (p *Parser) parseArg() ast.Arg {
+	if i := p.tryParseIntervalArg(); i != nil {
+		return i
+	}
+	if s := p.tryParseSequenceArg(); s != nil {
+		return s
+	}
+	return p.parseExprArg()
+}
+
+func (p *Parser) tryParseIntervalArg() *ast.IntervalArg {
 	if p.Token.Kind != "INTERVAL" {
-		e := p.parseExpr()
-		return &ast.Arg{
-			Interval: token.InvalidPos,
-			Expr:     e,
-		}
+		return nil
 	}
 
 	pos := p.Token.Pos
 	p.nextToken()
 	e := p.parseExpr()
 	unit := p.parseIdent()
-	return &ast.Arg{
-		Interval:     pos,
-		Expr:         e,
-		IntervalUnit: unit,
+	return &ast.IntervalArg{
+		Interval: pos,
+		Expr:     e,
+		Unit:     unit,
+	}
+}
+
+func (p *Parser) tryParseSequenceArg() *ast.SequenceArg {
+	if !p.Token.IsKeywordLike("SEQUENCE") {
+		return nil
+	}
+
+	pos := p.Token.Pos
+	p.nextToken()
+	e := p.parseExpr()
+	return &ast.SequenceArg{
+		Sequence: pos,
+		Expr:     e,
+	}
+}
+
+func (p *Parser) parseExprArg() *ast.ExprArg {
+	e := p.parseExpr()
+	return &ast.ExprArg{
+		Expr: e,
 	}
 }
 
@@ -1781,26 +1829,12 @@ func (p *Parser) lookaheadSubQuery() bool {
 	return false
 }
 
-// ParseType parses a type name.
-func (p *Parser) ParseType() (typ ast.Type, err error) {
-	defer func() {
-		if r := recover(); r != nil {
-			typ = nil
-			if e, ok := r.(*Error); ok {
-				err = e
-			} else {
-				panic(r)
-			}
-		}
-	}()
+// ================================================================================
+//
+// Type
+//
+// ================================================================================
 
-	p.nextToken()
-	typ = p.parseType()
-	if p.Token.Kind != token.TokenEOF {
-		p.panicfAtToken(&p.Token, "expected token: <eof>, but: %s", p.Token.Kind)
-	}
-	return
-}
 func (p *Parser) parseType() ast.Type {
 	switch p.Token.Kind {
 	case token.TokenIdent:


Test patch:
diff --git a/ast/ast_test.go b/ast/ast_test.go
index ef603cb..c1ba561 100644
--- a/ast/ast_test.go
+++ b/ast/ast_test.go
@@ -78,6 +78,12 @@ func TestExpr(t *testing.T) {
 	Expr(&NumericLiteral{}).isExpr()
 }
 
+func TestArg(t *testing.T) {
+	Arg(&IntervalArg{}).isArg()
+	Arg(&ExprArg{}).isArg()
+	Arg(&SequenceArg{}).isArg()
+}
+
 func TestInCondition(t *testing.T) {
 	InCondition(&ValuesInCondition{}).isInCondition()
 	InCondition(&UnnestInCondition{}).isInCondition()
diff --git a/testdata/input/ddl/create_table_with_sequence_function.sql b/testdata/input/ddl/create_table_with_sequence_function.sql
new file mode 100644
index 0000000..b0a1703
--- /dev/null
+++ b/testdata/input/ddl/create_table_with_sequence_function.sql
@@ -0,0 +1,6 @@
+CREATE TABLE foo
+(
+    foo INT64 DEFAULT (GET_NEXT_SEQUENCE_VALUE(SEQUENCE foo_sequence)),
+    bar STRING( MAX),
+    id  INT64
+)PRIMARY KEY (id)
diff --git a/testdata/input/dml/insert_with_sequence_function.sql b/testdata/input/dml/insert_with_sequence_function.sql
new file mode 100644
index 0000000..d0a8d6d
--- /dev/null
+++ b/testdata/input/dml/insert_with_sequence_function.sql
@@ -0,0 +1,1 @@
+INSERT INTO foo(bar) VALUES (GET_NEXT_SEQUENCE_VALUE(SEQUENCE my_sequence))
diff --git a/testdata/input/query/select_with_sequence_function.sql b/testdata/input/query/select_with_sequence_function.sql
new file mode 100644
index 0000000..f2d7102
--- /dev/null
+++ b/testdata/input/query/select_with_sequence_function.sql
@@ -0,0 +1,1 @@
+SELECT GET_NEXT_SEQUENCE_VALUE(SEQUENCE my_sequence) as next_id
diff --git a/testdata/result/ddl/alter_table_add_column_with_if_expression.sql.txt b/testdata/result/ddl/alter_table_add_column_with_if_expression.sql.txt
index e4aabc6..be02cb2 100644
--- a/testdata/result/ddl/alter_table_add_column_with_if_expression.sql.txt
+++ b/testdata/result/ddl/alter_table_add_column_with_if_expression.sql.txt
@@ -34,10 +34,9 @@ ALTER TABLE foo ADD COLUMN expired_at TIMESTAMP AS (IF (status != "OPEN" AND sta
             Name:    "IF",
           },
           Distinct: false,
-          Args:     []*ast.Arg{
-            &ast.Arg{
-              Interval: -1,
-              Expr:     &ast.BinaryExpr{
+          Args:     []ast.Arg{
+            &ast.ExprArg{
+              Expr: &ast.BinaryExpr{
                 Op:   "AND",
                 Left: &ast.BinaryExpr{
                   Op:   "!=",
@@ -66,11 +65,9 @@ ALTER TABLE foo ADD COLUMN expired_at TIMESTAMP AS (IF (status != "OPEN" AND sta
                   },
                 },
               },
-              IntervalUnit: (*ast.Ident)(nil),
             },
-            &ast.Arg{
-              Interval: -1,
-              Expr:     &ast.CallExpr{
+            &ast.ExprArg{
+              Expr: &ast.CallExpr{
                 Rparen: 143,
                 Func:   &ast.Ident{
                   NamePos: 101,
@@ -78,17 +75,15 @@ ALTER TABLE foo ADD COLUMN expired_at TIMESTAMP AS (IF (status != "OPEN" AND sta
                   Name:    "TIMESTAMP_ADD",
                 },
                 Distinct: false,
-                Args:     []*ast.Arg{
-                  &ast.Arg{
-                    Interval: -1,
-                    Expr:     &ast.Ident{
+                Args:     []ast.Arg{
+                  &ast.ExprArg{
+                    Expr: &ast.Ident{
                       NamePos: 115,
                       NameEnd: 125,
                       Name:    "updated_at",
                     },
-                    IntervalUnit: (*ast.Ident)(nil),
                   },
-                  &ast.Arg{
+                  &ast.IntervalArg{
                     Interval: 127,
                     Expr:     &ast.IntLiteral{
                       ValuePos: 136,
@@ -96,7 +91,7 @@ ALTER TABLE foo ADD COLUMN expired_at TIMESTAMP AS (IF (status != "OPEN" AND sta
                       Base:     10,
                       Value:    "120",
                     },
-                    IntervalUnit: &ast.Ident{
+                    Unit: &ast.Ident{
                       NamePos: 140,
                       NameEnd: 143,
                       Name:    "DAY",
@@ -104,14 +99,11 @@ ALTER TABLE foo ADD COLUMN expired_at TIMESTAMP AS (IF (status != "OPEN" AND sta
                   },
                 },
               },
-              IntervalUnit: (*ast.Ident)(nil),
             },
-            &ast.Arg{
-              Interval: -1,
-              Expr:     &ast.NullLiteral{
+            &ast.ExprArg{
+              Expr: &ast.NullLiteral{
                 Null: 146,
               },
-              IntervalUnit: (*ast.Ident)(nil),
             },
           },
         },
diff --git a/testdata/result/ddl/create_table.sql.txt b/testdata/result/ddl/create_table.sql.txt
index a96ca0e..08784aa 100644
--- a/testdata/result/ddl/create_table.sql.txt
+++ b/testdata/result/ddl/create_table.sql.txt
@@ -115,24 +115,20 @@ create table foo (
             Name:    "concat",
           },
           Distinct: false,
-          Args:     []*ast.Arg{
-            &ast.Arg{
-              Interval: -1,
-              Expr:     &ast.Ident{
+          Args:     []ast.Arg{
+            &ast.ExprArg{
+              Expr: &ast.Ident{
                 NamePos: 161,
                 NameEnd: 164,
                 Name:    "baz",
               },
-              IntervalUnit: (*ast.Ident)(nil),
             },
-            &ast.Arg{
-              Interval: -1,
-              Expr:     &ast.StringLiteral{
+            &ast.ExprArg{
+              Expr: &ast.StringLiteral{
                 ValuePos: 166,
                 ValueEnd: 169,
                 Value:    "a",
               },
-              IntervalUnit: (*ast.Ident)(nil),
             },
           },
         },
@@ -178,7 +174,7 @@ create table foo (
             Name:    "current_timestamp",
           },
           Distinct: false,
-          Args:     []*ast.Arg(nil),
+          Args:     []ast.Arg(nil),
         },
       },
       GeneratedExpr: (*ast.GeneratedColumnExpr)(nil),
diff --git a/testdata/result/ddl/create_table_with_sequence_function.sql.txt b/testdata/result/ddl/create_table_with_sequence_function.sql.txt
new file mode 100644
index 0000000..af66d78
--- /dev/null
+++ b/testdata/result/ddl/create_table_with_sequence_function.sql.txt
@@ -0,0 +1,111 @@
+--- create_table_with_sequence_function.sql
+CREATE TABLE foo
+(
+    foo INT64 DEFAULT (GET_NEXT_SEQUENCE_VALUE(SEQUENCE foo_sequence)),
+    bar STRING( MAX),
+    id  INT64
+)PRIMARY KEY (id)
+
+--- AST
+&ast.CreateTable{
+  Create:      0,
+  Rparen:      143,
+  IfNotExists: false,
+  Name:        &ast.Ident{
+    NamePos: 13,
+    NameEnd: 16,
+    Name:    "foo",
+  },
+  Columns: []*ast.ColumnDef{
+    &ast.ColumnDef{
+      Null: -1,
+      Name: &ast.Ident{
+        NamePos: 23,
+        NameEnd: 26,
+        Name:    "foo",
+      },
+      Type: &ast.ScalarSchemaType{
+        NamePos: 27,
+        Name:    "INT64",
+      },
+      NotNull:     false,
+      DefaultExpr: &ast.ColumnDefaultExpr{
+        Default: 33,
+        Rparen:  88,
+        Expr:    &ast.CallExpr{
+          Rparen: 87,
+          Func:   &ast.Ident{
+            NamePos: 42,
+            NameEnd: 65,
+            Name:    "GET_NEXT_SEQUENCE_VALUE",
+          },
+          Distinct: false,
+          Args:     []ast.Arg{
+            &ast.SequenceArg{
+              Sequence: 66,
+              Expr:     &ast.Ident{
+                NamePos: 75,
+                NameEnd: 87,
+                Name:    "foo_sequence",
+              },
+            },
+          },
+        },
+      },
+      GeneratedExpr: (*ast.GeneratedColumnExpr)(nil),
+      Options:       (*ast.ColumnDefOptions)(nil),
+    },
+    &ast.ColumnDef{
+      Null: -1,
+      Name: &ast.Ident{
+        NamePos: 95,
+        NameEnd: 98,
+        Name:    "bar",
+      },
+      Type: &ast.SizedSchemaType{
+        NamePos: 99,
+        Rparen:  110,
+        Name:    "STRING",
+        Max:     true,
+        Size:    nil,
+      },
+      NotNull:       false,
+      DefaultExpr:   (*ast.ColumnDefaultExpr)(nil),
+      GeneratedExpr: (*ast.GeneratedColumnExpr)(nil),
+      Options:       (*ast.ColumnDefOptions)(nil),
+    },
+    &ast.ColumnDef{
+      Null: -1,
+      Name: &ast.Ident{
+        NamePos: 117,
+        NameEnd: 119,
+        Name:    "id",
+      },
+      Type: &ast.ScalarSchemaType{
+        NamePos: 121,
+        Name:    "INT64",
+      },
+      NotNull:       false,
+      DefaultExpr:   (*ast.ColumnDefaultExpr)(nil),
+      GeneratedExpr: (*ast.GeneratedColumnExpr)(nil),
+      Options:       (*ast.ColumnDefOptions)(nil),
+    },
+  },
+  TableConstraints: []*ast.TableConstraint(nil),
+  PrimaryKeys:      []*ast.IndexKey{
+    &ast.IndexKey{
+      DirPos: -1,
+      Name:   &ast.Ident{
+        NamePos: 141,
+        NameEnd: 143,
+        Name:    "id",
+      },
+      Dir: "",
+    },
+  },
+  Cluster:           (*ast.Cluster)(nil),
+  RowDeletionPolicy: (*ast.CreateRowDeletionPolicy)(nil),
+}
+
+--- SQL
+CREATE TABLE foo (foo INT64 DEFAULT (GET_NEXT_SEQUENCE_VALUE(SEQUENCE foo_sequence)), bar STRING(MAX), id INT64) PRIMARY KEY (id)
diff --git a/testdata/result/dml/insert_with_sequence_function.sql.txt b/testdata/result/dml/insert_with_sequence_function.sql.txt
new file mode 100644
index 0000000..b93db39
--- /dev/null
+++ b/testdata/result/dml/insert_with_sequence_function.sql.txt
@@ -0,0 +1,56 @@
+--- insert_with_sequence_function.sql
+INSERT INTO foo(bar) VALUES (GET_NEXT_SEQUENCE_VALUE(SEQUENCE my_sequence))
+
+--- AST
+&ast.Insert{
+  Insert:    0,
+  TableName: &ast.Ident{
+    NamePos: 12,
+    NameEnd: 15,
+    Name:    "foo",
+  },
+  Columns: []*ast.Ident{
+    &ast.Ident{
+      NamePos: 16,
+      NameEnd: 19,
+      Name:    "bar",
+    },
+  },
+  Input: &ast.ValuesInput{
+    Values: 21,
+    Rows:   []*ast.ValuesRow{
+      &ast.ValuesRow{
+        Lparen: 28,
+        Rparen: 74,
+        Exprs:  []*ast.DefaultExpr{
+          &ast.DefaultExpr{
+            DefaultPos: -1,
+            Default:    false,
+            Expr:       &ast.CallExpr{
+              Rparen: 73,
+              Func:   &ast.Ident{
+                NamePos: 29,
+                NameEnd: 52,
+                Name:    "GET_NEXT_SEQUENCE_VALUE",
+              },
+              Distinct: false,
+              Args:     []ast.Arg{
+                &ast.SequenceArg{
+                  Sequence: 53,
+                  Expr:     &ast.Ident{
+                    NamePos: 62,
+                    NameEnd: 73,
+                    Name:    "my_sequence",
+                  },
+                },
+              },
+            },
+          },
+        },
+      },
+    },
+  },
+}
+
+--- SQL
+INSERT INTO foo (bar) VALUES (GET_NEXT_SEQUENCE_VALUE(SEQUENCE my_sequence))
diff --git a/testdata/result/query/select_count_distinct.sql.txt b/testdata/result/query/select_count_distinct.sql.txt
index 820028a..5af2d36 100644
--- a/testdata/result/query/select_count_distinct.sql.txt
+++ b/testdata/result/query/select_count_distinct.sql.txt
@@ -18,15 +18,13 @@ select count(distinct x) from foo
             Name:    "count",
           },
           Distinct: true,
-          Args:     []*ast.Arg{
-            &ast.Arg{
-              Interval: -1,
-              Expr:     &ast.Ident{
+          Args:     []ast.Arg{
+            &ast.ExprArg{
+              Expr: &ast.Ident{
                 NamePos: 22,
                 NameEnd: 23,
                 Name:    "x",
               },
-              IntervalUnit: (*ast.Ident)(nil),
             },
           },
         },
diff --git a/testdata/result/query/select_expr.sql.txt b/testdata/result/query/select_expr.sql.txt
index 465c43c..87e68b8 100644
--- a/testdata/result/query/select_expr.sql.txt
+++ b/testdata/result/query/select_expr.sql.txt
@@ -591,10 +591,9 @@ select 1 + 2, 1 - 2,
             Name:    "date_add",
           },
           Distinct: false,
-          Args:     []*ast.Arg{
-            &ast.Arg{
-              Interval: -1,
-              Expr:     &ast.DateLiteral{
+          Args:     []ast.Arg{
+            &ast.ExprArg{
+              Expr: &ast.DateLiteral{
                 Date:  523,
                 Value: &ast.StringLiteral{
                   ValuePos: 528,
@@ -602,9 +601,8 @@ select 1 + 2, 1 - 2,
                   Value:    "2019-09-01",
                 },
               },
-              IntervalUnit: (*ast.Ident)(nil),
             },
-            &ast.Arg{
+            &ast.IntervalArg{
               Interval: 542,
               Expr:     &ast.IntLiteral{
                 ValuePos: 551,
@@ -612,7 +610,7 @@ select 1 + 2, 1 - 2,
                 Base:     10,
                 Value:    "5",
               },
-              IntervalUnit: &ast.Ident{
+              Unit: &ast.Ident{
                 NamePos: 553,
                 NameEnd: 556,
                 Name:    "day",
@@ -630,10 +628,9 @@ select 1 + 2, 1 - 2,
             Name:    "timestamp_add",
           },
           Distinct: false,
-          Args:     []*ast.Arg{
-            &ast.Arg{
-              Interval: -1,
-              Expr:     &ast.TimestampLiteral{
+          Args:     []ast.Arg{
+            &ast.ExprArg{
+              Expr: &ast.TimestampLiteral{
                 Timestamp: 580,
                 Value:     &ast.StringLiteral{
                   ValuePos: 590,
@@ -641,9 +638,8 @@ select 1 + 2, 1 - 2,
                   Value:    "2019-09-01 08:11:22",
                 },
               },
-              IntervalUnit: (*ast.Ident)(nil),
             },
-            &ast.Arg{
+            &ast.IntervalArg{
               Interval: 613,
               Expr:     &ast.IntLiteral{
                 ValuePos: 622,
@@ -651,7 +647,7 @@ select 1 + 2, 1 - 2,
                 Base:     10,
                 Value:    "5",
               },
-              IntervalUnit: &ast.Ident{
+              Unit: &ast.Ident{
                 NamePos: 624,
                 NameEnd: 628,
                 Name:    "hour",
@@ -866,10 +862,9 @@ select 1 + 2, 1 - 2,
               Name:    "IF",
             },
             Distinct: false,
-            Args:     []*ast.Arg{
-              &ast.Arg{
-                Interval: -1,
-                Expr:     &ast.BinaryExpr{
+            Args:     []ast.Arg{
+              &ast.ExprArg{
+                Expr: &ast.BinaryExpr{
                   Op:   ">",
                   Left: &ast.IntLiteral{
                     ValuePos: 777,
@@ -884,27 +879,22 @@ select 1 + 2, 1 - 2,
                     Value:    "1",
                   },
                 },
-                IntervalUnit: (*ast.Ident)(nil),
               },
-              &ast.Arg{
-                Interval: -1,
-                Expr:     &ast.IntLiteral{
+              &ast.ExprArg{
+                Expr: &ast.IntLiteral{
                   ValuePos: 784,
                   ValueEnd: 785,
                   Base:     10,
                   Value:    "1",
                 },
-                IntervalUnit: (*ast.Ident)(nil),
               },
-              &ast.Arg{
-                Interval: -1,
-                Expr:     &ast.IntLiteral{
+              &ast.ExprArg{
+                Expr: &ast.IntLiteral{
                   ValuePos: 787,
                   ValueEnd: 788,
                   Base:     10,
                   Value:    "2",
                 },
-                IntervalUnit: (*ast.Ident)(nil),
               },
             },
           },
diff --git a/testdata/result/query/select_literals_all.sql.txt b/testdata/result/query/select_literals_all.sql.txt
index d57565e..37ca4c6 100644
--- a/testdata/result/query/select_literals_all.sql.txt
+++ b/testdata/result/query/select_literals_all.sql.txt
@@ -492,15 +492,13 @@ lines''',
             Name:    "DATE",
           },
           Distinct: false,
-          Args:     []*ast.Arg{
-            &ast.Arg{
-              Interval: -1,
-              Expr:     &ast.StringLiteral{
+          Args:     []ast.Arg{
+            &ast.ExprArg{
+              Expr: &ast.StringLiteral{
                 ValuePos: 540,
                 ValueEnd: 552,
                 Value:    "2014-09-27",
               },
-              IntervalUnit: (*ast.Ident)(nil),
             },
           },
         },
@@ -544,15 +542,13 @@ lines''',
             Name:    "TIMESTAMP",
           },
           Distinct: false,
-          Args:     []*ast.Arg{
-            &ast.Arg{
-              Interval: -1,
-              Expr:     &ast.StringLiteral{
+          Args:     []ast.Arg{
+            &ast.ExprArg{
+              Expr: &ast.StringLiteral{
                 ValuePos: 691,
                 ValueEnd: 703,
                 Value:    "2014-09-27",
               },
-              IntervalUnit: (*ast.Ident)(nil),
             },
           },
         },
diff --git a/testdata/result/query/select_literals_date.sql.txt b/testdata/result/query/select_literals_date.sql.txt
index b091715..24c0089 100644
--- a/testdata/result/query/select_literals_date.sql.txt
+++ b/testdata/result/query/select_literals_date.sql.txt
@@ -39,15 +39,13 @@ SELECT
             Name:    "DATE",
           },
           Distinct: false,
-          Args:     []*ast.Arg{
-            &ast.Arg{
-              Interval: -1,
-              Expr:     &ast.StringLiteral{
+          Args:     []ast.Arg{
+            &ast.ExprArg{
+              Expr: &ast.StringLiteral{
                 ValuePos: 34,
                 ValueEnd: 46,
                 Value:    "2014-09-27",
               },
-              IntervalUnit: (*ast.Ident)(nil),
             },
           },
         },
@@ -101,15 +99,13 @@ SELECT
             Name:    "TIMESTAMP",
           },
           Distinct: false,
-          Args:     []*ast.Arg{
-            &ast.Arg{
-              Interval: -1,
-              Expr:     &ast.StringLiteral{
+          Args:     []ast.Arg{
+            &ast.ExprArg{
+              Expr: &ast.StringLiteral{
                 ValuePos: 207,
                 ValueEnd: 219,
                 Value:    "2014-09-27",
               },
-              IntervalUnit: (*ast.Ident)(nil),
             },
           },
         },
@@ -133,15 +129,13 @@ SELECT
             Name:    "DATE",
           },
           Distinct: false,
-          Args:     []*ast.Arg{
-            &ast.Arg{
-              Interval: -1,
-              Expr:     &ast.StringLiteral{
+          Args:     []ast.Arg{
+            &ast.ExprArg{
+              Expr: &ast.StringLiteral{
                 ValuePos: 256,
                 ValueEnd: 268,
                 Value:    "2014-09-27",
               },
-              IntervalUnit: (*ast.Ident)(nil),
             },
           },
         },
@@ -163,15 +157,13 @@ SELECT
             Name:    "TIMESTAMP",
           },
           Distinct: false,
-          Args:     []*ast.Arg{
-            &ast.Arg{
-              Interval: -1,
-              Expr:     &ast.StringLiteral{
+          Args:     []ast.Arg{
+            &ast.ExprArg{
+              Expr: &ast.StringLiteral{
                 ValuePos: 290,
                 ValueEnd: 302,
                 Value:    "2014-09-27",
               },
-              IntervalUnit: (*ast.Ident)(nil),
             },
           },
         },
diff --git a/testdata/result/query/select_with_sequence_function.sql.txt b/testdata/result/query/select_with_sequence_function.sql.txt
new file mode 100644
index 0000000..5d5e76e
--- /dev/null
+++ b/testdata/result/query/select_with_sequence_function.sql.txt
@@ -0,0 +1,53 @@
+--- select_with_sequence_function.sql
+SELECT GET_NEXT_SEQUENCE_VALUE(SEQUENCE my_sequence) as next_id
+
+--- AST
+&ast.QueryStatement{
+  Hint:  (*ast.Hint)(nil),
+  With:  (*ast.With)(nil),
+  Query: &ast.Select{
+    Select:   0,
+    Distinct: false,
+    AsStruct: false,
+    Results:  []ast.SelectItem{
+      &ast.Alias{
+        Expr: &ast.CallExpr{
+          Rparen: 51,
+          Func:   &ast.Ident{
+            NamePos: 7,
+            NameEnd: 30,
+            Name:    "GET_NEXT_SEQUENCE_VALUE",
+          },
+          Distinct: false,
+          Args:     []ast.Arg{
+            &ast.SequenceArg{
+              Sequence: 31,
+              Expr:     &ast.Ident{
+                NamePos: 40,
+                NameEnd: 51,
+                Name:    "my_sequence",
+              },
+            },
+          },
+        },
+        As: &ast.AsAlias{
+          As:    -1,
+          Alias: &ast.Ident{
+            NamePos: 56,
+            NameEnd: 63,
+            Name:    "next_id",
+          },
+        },
+      },
+    },
+    From:    (*ast.From)(nil),
+    Where:   (*ast.Where)(nil),
+    GroupBy: (*ast.GroupBy)(nil),
+    Having:  (*ast.Having)(nil),
+    OrderBy: (*ast.OrderBy)(nil),
+    Limit:   (*ast.Limit)(nil),
+  },
+}
+
+--- SQL
+SELECT GET_NEXT_SEQUENCE_VALUE(SEQUENCE my_sequence) AS next_id
diff --git a/testdata/result/statement/alter_table_add_column_with_if_expression.sql.txt b/testdata/result/statement/alter_table_add_column_with_if_expression.sql.txt
index e4aabc6..be02cb2 100644
--- a/testdata/result/statement/alter_table_add_column_with_if_expression.sql.txt
+++ b/testdata/result/statement/alter_table_add_column_with_if_expression.sql.txt
@@ -34,10 +34,9 @@ ALTER TABLE foo ADD COLUMN expired_at TIMESTAMP AS (IF (status != "OPEN" AND sta
             Name:    "IF",
           },
           Distinct: false,
-          Args:     []*ast.Arg{
-            &ast.Arg{
-              Interval: -1,
-              Expr:     &ast.BinaryExpr{
+          Args:     []ast.Arg{
+            &ast.ExprArg{
+              Expr: &ast.BinaryExpr{
                 Op:   "AND",
                 Left: &ast.BinaryExpr{
                   Op:   "!=",
@@ -66,11 +65,9 @@ ALTER TABLE foo ADD COLUMN expired_at TIMESTAMP AS (IF (status != "OPEN" AND sta
                   },
                 },
               },
-              IntervalUnit: (*ast.Ident)(nil),
             },
-            &ast.Arg{
-              Interval: -1,
-              Expr:     &ast.CallExpr{
+            &ast.ExprArg{
+              Expr: &ast.CallExpr{
                 Rparen: 143,
                 Func:   &ast.Ident{
                   NamePos: 101,
@@ -78,17 +75,15 @@ ALTER TABLE foo ADD COLUMN expired_at TIMESTAMP AS (IF (status != "OPEN" AND sta
                   Name:    "TIMESTAMP_ADD",
                 },
                 Distinct: false,
-                Args:     []*ast.Arg{
-                  &ast.Arg{
-                    Interval: -1,
-                    Expr:     &ast.Ident{
+                Args:     []ast.Arg{
+                  &ast.ExprArg{
+                    Expr: &ast.Ident{
                       NamePos: 115,
                       NameEnd: 125,
                       Name:    "updated_at",
                     },
-                    IntervalUnit: (*ast.Ident)(nil),
                   },
-                  &ast.Arg{
+                  &ast.IntervalArg{
                     Interval: 127,
                     Expr:     &ast.IntLiteral{
                       ValuePos: 136,
@@ -96,7 +91,7 @@ ALTER TABLE foo ADD COLUMN expired_at TIMESTAMP AS (IF (status != "OPEN" AND sta
                       Base:     10,
                       Value:    "120",
                     },
-                    IntervalUnit: &ast.Ident{
+                    Unit: &ast.Ident{
                       NamePos: 140,
                       NameEnd: 143,
                       Name:    "DAY",
@@ -104,14 +99,11 @@ ALTER TABLE foo ADD COLUMN expired_at TIMESTAMP AS (IF (status != "OPEN" AND sta
                   },
                 },
               },
-              IntervalUnit: (*ast.Ident)(nil),
             },
-            &ast.Arg{
-              Interval: -1,
-              Expr:     &ast.NullLiteral{
+            &ast.ExprArg{
+              Expr: &ast.NullLiteral{
                 Null: 146,
               },
-              IntervalUnit: (*ast.Ident)(nil),
             },
           },
         },
diff --git a/testdata/result/statement/create_table.sql.txt b/testdata/result/statement/create_table.sql.txt
index a96ca0e..08784aa 100644
--- a/testdata/result/statement/create_table.sql.txt
+++ b/testdata/result/statement/create_table.sql.txt
@@ -115,24 +115,20 @@ create table foo (
             Name:    "concat",
           },
           Distinct: false,
-          Args:     []*ast.Arg{
-            &ast.Arg{
-              Interval: -1,
-              Expr:     &ast.Ident{
+          Args:     []ast.Arg{
+            &ast.ExprArg{
+              Expr: &ast.Ident{
                 NamePos: 161,
                 NameEnd: 164,
                 Name:    "baz",
               },
-              IntervalUnit: (*ast.Ident)(nil),
             },
-            &ast.Arg{
-              Interval: -1,
-              Expr:     &ast.StringLiteral{
+            &ast.ExprArg{
+              Expr: &ast.StringLiteral{
                 ValuePos: 166,
                 ValueEnd: 169,
                 Value:    "a",
               },
-              IntervalUnit: (*ast.Ident)(nil),
             },
           },
         },
@@ -178,7 +174,7 @@ create table foo (
             Name:    "current_timestamp",
           },
           Distinct: false,
-          Args:     []*ast.Arg(nil),
+          Args:     []ast.Arg(nil),
         },
       },
       GeneratedExpr: (*ast.GeneratedColumnExpr)(nil),
diff --git a/testdata/result/statement/create_table_with_sequence_function.sql.txt b/testdata/result/statement/create_table_with_sequence_function.sql.txt
new file mode 100644
index 0000000..af66d78
--- /dev/null
+++ b/testdata/result/statement/create_table_with_sequence_function.sql.txt
@@ -0,0 +1,111 @@
+--- create_table_with_sequence_function.sql
+CREATE TABLE foo
+(
+    foo INT64 DEFAULT (GET_NEXT_SEQUENCE_VALUE(SEQUENCE foo_sequence)),
+    bar STRING( MAX),
+    id  INT64
+)PRIMARY KEY (id)
+
+--- AST
+&ast.CreateTable{
+  Create:      0,
+  Rparen:      143,
+  IfNotExists: false,
+  Name:        &ast.Ident{
+    NamePos: 13,
+    NameEnd: 16,
+    Name:    "foo",
+  },
+  Columns: []*ast.ColumnDef{
+    &ast.ColumnDef{
+      Null: -1,
+      Name: &ast.Ident{
+        NamePos: 23,
+        NameEnd: 26,
+        Name:    "foo",
+      },
+      Type: &ast.ScalarSchemaType{
+        NamePos: 27,
+        Name:    "INT64",
+      },
+      NotNull:     false,
+      DefaultExpr: &ast.ColumnDefaultExpr{
+        Default: 33,
+        Rparen:  88,
+        Expr:    &ast.CallExpr{
+          Rparen: 87,
+          Func:   &ast.Ident{
+            NamePos: 42,
+            NameEnd: 65,
+            Name:    "GET_NEXT_SEQUENCE_VALUE",
+          },
+          Distinct: false,
+          Args:     []ast.Arg{
+            &ast.SequenceArg{
+              Sequence: 66,
+              Expr:     &ast.Ident{
+                NamePos: 75,
+                NameEnd: 87,
+                Name:    "foo_sequence",
+              },
+            },
+          },
+        },
+      },
+      GeneratedExpr: (*ast.GeneratedColumnExpr)(nil),
+      Options:       (*ast.ColumnDefOptions)(nil),
+    },
+    &ast.ColumnDef{
+      Null: -1,
+      Name: &ast.Ident{
+        NamePos: 95,
+        NameEnd: 98,
+        Name:    "bar",
+      },
+      Type: &ast.SizedSchemaType{
+        NamePos: 99,
+        Rparen:  110,
+        Name:    "STRING",
+        Max:     true,
+        Size:    nil,
+      },
+      NotNull:       false,
+      DefaultExpr:   (*ast.ColumnDefaultExpr)(nil),
+      GeneratedExpr: (*ast.GeneratedColumnExpr)(nil),
+      Options:       (*ast.ColumnDefOptions)(nil),
+    },
+    &ast.ColumnDef{
+      Null: -1,
+      Name: &ast.Ident{
+        NamePos: 117,
+        NameEnd: 119,
+        Name:    "id",
+      },
+      Type: &ast.ScalarSchemaType{
+        NamePos: 121,
+        Name:    "INT64",
+      },
+      NotNull:       false,
+      DefaultExpr:   (*ast.ColumnDefaultExpr)(nil),
+      GeneratedExpr: (*ast.GeneratedColumnExpr)(nil),
+      Options:       (*ast.ColumnDefOptions)(nil),
+    },
+  },
+  TableConstraints: []*ast.TableConstraint(nil),
+  PrimaryKeys:      []*ast.IndexKey{
+    &ast.IndexKey{
+      DirPos: -1,
+      Name:   &ast.Ident{
+        NamePos: 141,
+        NameEnd: 143,
+        Name:    "id",
+      },
+      Dir: "",
+    },
+  },
+  Cluster:           (*ast.Cluster)(nil),
+  RowDeletionPolicy: (*ast.CreateRowDeletionPolicy)(nil),
+}
+
+--- SQL
+CREATE TABLE foo (foo INT64 DEFAULT (GET_NEXT_SEQUENCE_VALUE(SEQUENCE foo_sequence)), bar STRING(MAX), id INT64) PRIMARY KEY (id)
diff --git a/testdata/result/statement/insert_with_sequence_function.sql.txt b/testdata/result/statement/insert_with_sequence_function.sql.txt
new file mode 100644
index 0000000..b93db39
--- /dev/null
+++ b/testdata/result/statement/insert_with_sequence_function.sql.txt
@@ -0,0 +1,56 @@
+--- insert_with_sequence_function.sql
+INSERT INTO foo(bar) VALUES (GET_NEXT_SEQUENCE_VALUE(SEQUENCE my_sequence))
+
+--- AST
+&ast.Insert{
+  Insert:    0,
+  TableName: &ast.Ident{
+    NamePos: 12,
+    NameEnd: 15,
+    Name:    "foo",
+  },
+  Columns: []*ast.Ident{
+    &ast.Ident{
+      NamePos: 16,
+      NameEnd: 19,
+      Name:    "bar",
+    },
+  },
+  Input: &ast.ValuesInput{
+    Values: 21,
+    Rows:   []*ast.ValuesRow{
+      &ast.ValuesRow{
+        Lparen: 28,
+        Rparen: 74,
+        Exprs:  []*ast.DefaultExpr{
+          &ast.DefaultExpr{
+            DefaultPos: -1,
+            Default:    false,
+            Expr:       &ast.CallExpr{
+              Rparen: 73,
+              Func:   &ast.Ident{
+                NamePos: 29,
+                NameEnd: 52,
+                Name:    "GET_NEXT_SEQUENCE_VALUE",
+              },
+              Distinct: false,
+              Args:     []ast.Arg{
+                &ast.SequenceArg{
+                  Sequence: 53,
+                  Expr:     &ast.Ident{
+                    NamePos: 62,
+                    NameEnd: 73,
+                    Name:    "my_sequence",
+                  },
+                },
+              },
+            },
+          },
+        },
+      },
+    },
+  },
+}
+
+--- SQL
+INSERT INTO foo (bar) VALUES (GET_NEXT_SEQUENCE_VALUE(SEQUENCE my_sequence))
diff --git a/testdata/result/statement/select_count_distinct.sql.txt b/testdata/result/statement/select_count_distinct.sql.txt
index 820028a..5af2d36 100644
--- a/testdata/result/statement/select_count_distinct.sql.txt
+++ b/testdata/result/statement/select_count_distinct.sql.txt
@@ -18,15 +18,13 @@ select count(distinct x) from foo
             Name:    "count",
           },
           Distinct: true,
-          Args:     []*ast.Arg{
-            &ast.Arg{
-              Interval: -1,
-              Expr:     &ast.Ident{
+          Args:     []ast.Arg{
+            &ast.ExprArg{
+              Expr: &ast.Ident{
                 NamePos: 22,
                 NameEnd: 23,
                 Name:    "x",
               },
-              IntervalUnit: (*ast.Ident)(nil),
             },
           },
         },
diff --git a/testdata/result/statement/select_expr.sql.txt b/testdata/result/statement/select_expr.sql.txt
index 465c43c..87e68b8 100644
--- a/testdata/result/statement/select_expr.sql.txt
+++ b/testdata/result/statement/select_expr.sql.txt
@@ -591,10 +591,9 @@ select 1 + 2, 1 - 2,
             Name:    "date_add",
           },
           Distinct: false,
-          Args:     []*ast.Arg{
-            &ast.Arg{
-              Interval: -1,
-              Expr:     &ast.DateLiteral{
+          Args:     []ast.Arg{
+            &ast.ExprArg{
+              Expr: &ast.DateLiteral{
                 Date:  523,
                 Value: &ast.StringLiteral{
                   ValuePos: 528,
@@ -602,9 +601,8 @@ select 1 + 2, 1 - 2,
                   Value:    "2019-09-01",
                 },
               },
-              IntervalUnit: (*ast.Ident)(nil),
             },
-            &ast.Arg{
+            &ast.IntervalArg{
               Interval: 542,
               Expr:     &ast.IntLiteral{
                 ValuePos: 551,
@@ -612,7 +610,7 @@ select 1 + 2, 1 - 2,
                 Base:     10,
                 Value:    "5",
               },
-              IntervalUnit: &ast.Ident{
+              Unit: &ast.Ident{
                 NamePos: 553,
                 NameEnd: 556,
                 Name:    "day",
@@ -630,10 +628,9 @@ select 1 + 2, 1 - 2,
             Name:    "timestamp_add",
           },
           Distinct: false,
-          Args:     []*ast.Arg{
-            &ast.Arg{
-              Interval: -1,
-              Expr:     &ast.TimestampLiteral{
+          Args:     []ast.Arg{
+            &ast.ExprArg{
+              Expr: &ast.TimestampLiteral{
                 Timestamp: 580,
                 Value:     &ast.StringLiteral{
                   ValuePos: 590,
@@ -641,9 +638,8 @@ select 1 + 2, 1 - 2,
                   Value:    "2019-09-01 08:11:22",
                 },
               },
-              IntervalUnit: (*ast.Ident)(nil),
             },
-            &ast.Arg{
+            &ast.IntervalArg{
               Interval: 613,
               Expr:     &ast.IntLiteral{
                 ValuePos: 622,
@@ -651,7 +647,7 @@ select 1 + 2, 1 - 2,
                 Base:     10,
                 Value:    "5",
               },
-              IntervalUnit: &ast.Ident{
+              Unit: &ast.Ident{
                 NamePos: 624,
                 NameEnd: 628,
                 Name:    "hour",
@@ -866,10 +862,9 @@ select 1 + 2, 1 - 2,
               Name:    "IF",
             },
             Distinct: false,
-            Args:     []*ast.Arg{
-              &ast.Arg{
-                Interval: -1,
-                Expr:     &ast.BinaryExpr{
+            Args:     []ast.Arg{
+              &ast.ExprArg{
+                Expr: &ast.BinaryExpr{
                   Op:   ">",
                   Left: &ast.IntLiteral{
                     ValuePos: 777,
@@ -884,27 +879,22 @@ select 1 + 2, 1 - 2,
                     Value:    "1",
                   },
                 },
-                IntervalUnit: (*ast.Ident)(nil),
               },
-              &ast.Arg{
-                Interval: -1,
-                Expr:     &ast.IntLiteral{
+              &ast.ExprArg{
+                Expr: &ast.IntLiteral{
                   ValuePos: 784,
                   ValueEnd: 785,
                   Base:     10,
                   Value:    "1",
                 },
-                IntervalUnit: (*ast.Ident)(nil),
               },
-              &ast.Arg{
-                Interval: -1,
-                Expr:     &ast.IntLiteral{
+              &ast.ExprArg{
+                Expr: &ast.IntLiteral{
                   ValuePos: 787,
                   ValueEnd: 788,
                   Base:     10,
                   Value:    "2",
                 },
-                IntervalUnit: (*ast.Ident)(nil),
               },
             },
           },
diff --git a/testdata/result/statement/select_literals_all.sql.txt b/testdata/result/statement/select_literals_all.sql.txt
index d57565e..37ca4c6 100644
--- a/testdata/result/statement/select_literals_all.sql.txt
+++ b/testdata/result/statement/select_literals_all.sql.txt
@@ -492,15 +492,13 @@ lines''',
             Name:    "DATE",
           },
           Distinct: false,
-          Args:     []*ast.Arg{
-            &ast.Arg{
-              Interval: -1,
-              Expr:     &ast.StringLiteral{
+          Args:     []ast.Arg{
+            &ast.ExprArg{
+              Expr: &ast.StringLiteral{
                 ValuePos: 540,
                 ValueEnd: 552,
                 Value:    "2014-09-27",
               },
-              IntervalUnit: (*ast.Ident)(nil),
             },
           },
         },
@@ -544,15 +542,13 @@ lines''',
             Name:    "TIMESTAMP",
           },
           Distinct: false,
-          Args:     []*ast.Arg{
-            &ast.Arg{
-              Interval: -1,
-              Expr:     &ast.StringLiteral{
+          Args:     []ast.Arg{
+            &ast.ExprArg{
+              Expr: &ast.StringLiteral{
                 ValuePos: 691,
                 ValueEnd: 703,
                 Value:    "2014-09-27",
               },
-              IntervalUnit: (*ast.Ident)(nil),
             },
           },
         },
diff --git a/testdata/result/statement/select_literals_date.sql.txt b/testdata/result/statement/select_literals_date.sql.txt
index b091715..24c0089 100644
--- a/testdata/result/statement/select_literals_date.sql.txt
+++ b/testdata/result/statement/select_literals_date.sql.txt
@@ -39,15 +39,13 @@ SELECT
             Name:    "DATE",
           },
           Distinct: false,
-          Args:     []*ast.Arg{
-            &ast.Arg{
-              Interval: -1,
-              Expr:     &ast.StringLiteral{
+          Args:     []ast.Arg{
+            &ast.ExprArg{
+              Expr: &ast.StringLiteral{
                 ValuePos: 34,
                 ValueEnd: 46,
                 Value:    "2014-09-27",
               },
-              IntervalUnit: (*ast.Ident)(nil),
             },
           },
         },
@@ -101,15 +99,13 @@ SELECT
             Name:    "TIMESTAMP",
           },
           Distinct: false,
-          Args:     []*ast.Arg{
-            &ast.Arg{
-              Interval: -1,
-              Expr:     &ast.StringLiteral{
+          Args:     []ast.Arg{
+            &ast.ExprArg{
+              Expr: &ast.StringLiteral{
                 ValuePos: 207,
                 ValueEnd: 219,
                 Value:    "2014-09-27",
               },
-              IntervalUnit: (*ast.Ident)(nil),
             },
           },
         },
@@ -133,15 +129,13 @@ SELECT
             Name:    "DATE",
           },
           Distinct: false,
-          Args:     []*ast.Arg{
-            &ast.Arg{
-              Interval: -1,
-              Expr:     &ast.StringLiteral{
+          Args:     []ast.Arg{
+            &ast.ExprArg{
+              Expr: &ast.StringLiteral{
                 ValuePos: 256,
                 ValueEnd: 268,
                 Value:    "2014-09-27",
               },
-              IntervalUnit: (*ast.Ident)(nil),
             },
           },
         },
@@ -163,15 +157,13 @@ SELECT
             Name:    "TIMESTAMP",
           },
           Distinct: false,
-          Args:     []*ast.Arg{
-            &ast.Arg{
-              Interval: -1,
-              Expr:     &ast.StringLiteral{
+          Args:     []ast.Arg{
+            &ast.ExprArg{
+              Expr: &ast.StringLiteral{
                 ValuePos: 290,
                 ValueEnd: 302,
                 Value:    "2014-09-27",
               },
-              IntervalUnit: (*ast.Ident)(nil),
             },
           },
         },
diff --git a/testdata/result/statement/select_with_sequence_function.sql.txt b/testdata/result/statement/select_with_sequence_function.sql.txt
new file mode 100644
index 0000000..5d5e76e
--- /dev/null
+++ b/testdata/result/statement/select_with_sequence_function.sql.txt
@@ -0,0 +1,53 @@
+--- select_with_sequence_function.sql
+SELECT GET_NEXT_SEQUENCE_VALUE(SEQUENCE my_sequence) as next_id
+
+--- AST
+&ast.QueryStatement{
+  Hint:  (*ast.Hint)(nil),
+  With:  (*ast.With)(nil),
+  Query: &ast.Select{
+    Select:   0,
+    Distinct: false,
+    AsStruct: false,
+    Results:  []ast.SelectItem{
+      &ast.Alias{
+        Expr: &ast.CallExpr{
+          Rparen: 51,
+          Func:   &ast.Ident{
+            NamePos: 7,
+            NameEnd: 30,
+            Name:    "GET_NEXT_SEQUENCE_VALUE",
+          },
+          Distinct: false,
+          Args:     []ast.Arg{
+            &ast.SequenceArg{
+              Sequence: 31,
+              Expr:     &ast.Ident{
+                NamePos: 40,
+                NameEnd: 51,
+                Name:    "my_sequence",
+              },
+            },
+          },
+        },
+        As: &ast.AsAlias{
+          As:    -1,
+          Alias: &ast.Ident{
+            NamePos: 56,
+            NameEnd: 63,
+            Name:    "next_id",
+          },
+        },
+      },
+    },
+    From:    (*ast.From)(nil),
+    Where:   (*ast.Where)(nil),
+    GroupBy: (*ast.GroupBy)(nil),
+    Having:  (*ast.Having)(nil),
+    OrderBy: (*ast.OrderBy)(nil),
+    Limit:   (*ast.Limit)(nil),
+  },
+}
+
+--- SQL
+SELECT GET_NEXT_SEQUENCE_VALUE(SEQUENCE my_sequence) AS next_id