Repository: cloudspannerecosystem/memefish
Pull request #308 (2025-05-04 15:16:41)

Fix comment about AsString in TokenParam
This PR includes a minor update to the `Token` struct in `token/token.go`. The change updates the comment for the `AsString` field to indicate that it is now also applicable to `TokenParam`.

* [`token/token.go`](diffhunk://#diff-33bf6304dd970a085d3e7819ae65390a9c7fd1fe65eee30f0dc82021ff6975e0L12-R12): Updated the comment for the `AsString` field in the `Token` struct to include `TokenParam` as one of the applicable token types.


Patch:
diff --git a/ast/ast.go b/ast/ast.go
index bd4dc9e..5cdeefa 100644
--- a/ast/ast.go
+++ b/ast/ast.go
@@ -235,6 +235,8 @@ func (DateLiteral) isExpr()           {}
 func (TimestampLiteral) isExpr()      {}
 func (NumericLiteral) isExpr()        {}
 func (JSONLiteral) isExpr()           {}
+func (IntervalLiteralSingle) isExpr() {}
+func (IntervalLiteralRange) isExpr()  {}
 func (NewConstructor) isExpr()        {}
 func (BracedNewConstructor) isExpr()  {}
 func (BracedConstructor) isExpr()     {}
@@ -255,7 +257,6 @@ type Arg interface {
 }
 
 func (ExprArg) isArg()     {}
-func (IntervalArg) isArg() {}
 func (SequenceArg) isArg() {}
 func (LambdaArg) isArg()   {}
 
@@ -1438,6 +1439,7 @@ type SubscriptSpecifierKeyword struct {
 }
 
 // CallExpr is function call expression node.
+// It can represent both regular function calls and aggregate function calls.
 //
 //	{{.Func | sql}}(
 //		{{if .Distinct}}DISTINCT{{end}}
@@ -1446,6 +1448,8 @@ type SubscriptSpecifierKeyword struct {
 //		{{.NamedArgs | sqlJoin ", "}}
 //		{{.NullHandling | sqlOpt}}
 //		{{.Having | sqlOpt}}
+//		{{.OrderBy | sqlOpt}}
+//		{{.Limit | sqlOpt}}
 //	)
 //	{{.Hint | sqlOpt}}
 type CallExpr struct {
@@ -1460,6 +1464,8 @@ type CallExpr struct {
 	NamedArgs    []*NamedArg
 	NullHandling NullHandlingModifier // optional
 	Having       HavingModifier       // optional
+	OrderBy      *OrderBy             // optional
+	Limit        *Limit               // optional
 	Hint         *Hint                // optional
 }
 
@@ -1495,19 +1501,6 @@ type ExprArg struct {
 	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
-	Unit *Ident // optional
-}
-
 // SequenceArg is argument of sequence function call.
 //
 //	SEQUENCE {{.Expr | sql}}
@@ -2039,6 +2032,37 @@ type JSONLiteral struct {
 	Value *StringLiteral
 }
 
+// IntervalLiteralSingle represents an interval literal with a single datetime part.
+//
+//	INTERVAL {{.Value}} {{.DateTimePart | sql}}
+type IntervalLiteralSingle struct {
+	// pos = Interval
+	// end = DateTimePartEnd
+
+	Interval        token.Pos // position of "INTERVAL" keyword
+	DateTimePartEnd token.Pos
+
+	Value IntValue
+
+	DateTimePart DateTimePart
+}
+
+// IntervalLiteralRange represents an interval literal with a datetime part range.
+//
+//	INTERVAL {{.Value}} {{.StartingDateTimePart | sql}} TO {{.EndingDateTimePart | sql}}
+type IntervalLiteralRange struct {
+	// pos = Interval
+	// end = EndingDateTimePartEnd
+
+	Interval              token.Pos // position of "INTERVAL" keyword
+	EndingDateTimePartEnd token.Pos
+
+	Value *StringLiteral
+
+	StartingDateTimePart DateTimePart
+	EndingDateTimePart   DateTimePart
+}
+
 // ================================================================================
 //
 // NEW constructors
@@ -3835,14 +3859,17 @@ type PropertyGraphElementList struct {
 //
 //	{{.Name | sql}} {{if .Alias | isnil | not)}}AS {{.Alias | sql}}{{end}}
 //	{{.Keys | sqlOpt}} {{.Properties | sqlOpt}}
+//	{{.DynamicLabel | sqlOpt}} {{.DynamicProperties | sqlOpt}}
 type PropertyGraphElement struct {
 	// pos = Name.pos
-	// end = (Properties ?? Keys ?? Alias ?? Name).end
+	// end = (DynamicProperties ?? DynamicLabel ?? Properties ?? Keys ?? Alias ?? Name).end
 
-	Name       *Ident
-	Alias      *Ident                          // optional
-	Keys       PropertyGraphElementKeys        // optional
-	Properties PropertyGraphLabelsOrProperties // optional
+	Name              *Ident
+	Alias             *Ident                          // optional
+	Keys              PropertyGraphElementKeys        // optional
+	Properties        PropertyGraphLabelsOrProperties // optional
+	DynamicLabel      *PropertyGraphDynamicLabel      // optional
+	DynamicProperties *PropertyGraphDynamicProperties // optional
 }
 
 // PropertyGraphSingleProperties is wrapper node for PropertyGraphElementProperties in PropertyGraphElement.
@@ -4021,6 +4048,32 @@ type PropertyGraphDerivedProperty struct {
 	Alias *Ident // optional
 }
 
+// DynamicLabel represents DYNAMIC LABEL clause in CREATE PROPERTY GRAPH statement.
+//
+//	DYNAMIC LABEL ({{.ColumnName | sql}})
+type PropertyGraphDynamicLabel struct {
+	// pos = Dynamic
+	// end = Rparen + 1
+
+	Dynamic token.Pos // position of "DYNAMIC"
+	Rparen  token.Pos // position of ")"
+
+	ColumnName *Ident
+}
+
+// DynamicProperties represents DYNAMIC PROPERTIES clause in CREATE PROPERTY GRAPH statement.
+//
+//	DYNAMIC PROPERTIES ({{.ColumnName | sql}})
+type PropertyGraphDynamicProperties struct {
+	// pos = Dynamic
+	// end = Rparen + 1
+
+	Dynamic token.Pos // position of "DYNAMIC"
+	Rparen  token.Pos // position of ")"
+
+	ColumnName *Ident
+}
+
 // DropPropertyGraph is DROP PROPERTY GRAPH statement node.
 //
 //	DROP PROPERTY GRAPH {{if .IfExists}}IF EXISTS{{end}} {{.Name | sql}}
diff --git a/ast/ast_const.go b/ast/ast_const.go
index 3a29eaa..450a940 100644
--- a/ast/ast_const.go
+++ b/ast/ast_const.go
@@ -121,6 +121,7 @@ const (
 	NumericTypeName   ScalarTypeName = "NUMERIC"
 	JSONTypeName      ScalarTypeName = "JSON"
 	TokenListTypeName ScalarTypeName = "TOKENLIST"
+	IntervalTypeName  ScalarTypeName = "INTERVAL"
 )
 
 type OnDeleteAction string
@@ -150,3 +151,42 @@ const (
 	InsertOrTypeUpdate InsertOrType = "UPDATE"
 	InsertOrTypeIgnore InsertOrType = "IGNORE"
 )
+
+// DateTimePart is used for:
+//
+//	- INTERVAL literals
+//	- EXTRACT for DATE, TIMESTAMP, INTERVAL (TODO)
+//	- DATE_TRUNC, TIMESTAMP_TRUNC (TODO)
+type DateTimePart string
+
+// Definition of all enum values (including values not used in Spanner)
+// https://github.com/google/zetasql/blob/2025.03.1/zetasql/public/functions/datetime.proto#L26
+const (
+	DateTimePartYear        DateTimePart = "YEAR"
+	DateTimePartMonth       DateTimePart = "MONTH"
+	DateTimePartDay         DateTimePart = "DAY"
+	DateTimePartDayOfWeek   DateTimePart = "DAYOFWEEK"
+	DateTimePartDayOfYear   DateTimePart = "DAYOFYEAR"
+	DateTimePartQuarter     DateTimePart = "QUARTER"
+	DateTimePartHour        DateTimePart = "HOUR"
+	DateTimePartMinute      DateTimePart = "MINUTE"
+	DateTimePartSecond      DateTimePart = "SECOND"
+	DateTimePartMillisecond DateTimePart = "MILLISECOND"
+	DateTimePartMicrosecond DateTimePart = "MICROSECOND"
+	DateTimePartNanosecond  DateTimePart = "NANOSECOND"
+	DateTimePartWeek        DateTimePart = "WEEK"
+	DateTimePartISOYear     DateTimePart = "ISOYEAR"
+	DateTimePartISOWeek     DateTimePart = "ISOWEEK"
+	DateTimePartDate        DateTimePart = "DATE"
+
+	// Not yet used in Spanner?
+
+	DateTimePartDateTime      DateTimePart = "DATETIME"
+	DateTimePartTime          DateTimePart = "TIME"
+	DateTimePartWeekMonday    DateTimePart = "WEEK(MONDAY)"
+	DateTimePartWeekTuesday   DateTimePart = "WEEK(TUESDAY)"
+	DateTimePartWeekWednesday DateTimePart = "WEEK(WEDNESDAY)"
+	DateTimePartWeekThursday  DateTimePart = "WEEK(THURSDAY)"
+	DateTimePartWeekFriday    DateTimePart = "WEEK(FRIDAY)"
+	DateTimePartWeekSaturday  DateTimePart = "WEEK(SATURDAY)"
+)
diff --git a/ast/pos.go b/ast/pos.go
index 3a87678..0863a6c 100644
--- a/ast/pos.go
+++ b/ast/pos.go
@@ -534,14 +534,6 @@ func (e *ExprArg) End() token.Pos {
 	return nodeEnd(wrapNode(e.Expr))
 }
 
-func (i *IntervalArg) Pos() token.Pos {
-	return i.Interval
-}
-
-func (i *IntervalArg) End() token.Pos {
-	return nodeEnd(nodeChoice(wrapNode(i.Unit), wrapNode(i.Expr)))
-}
-
 func (s *SequenceArg) Pos() token.Pos {
 	return s.Sequence
 }
@@ -878,6 +870,22 @@ func (j *JSONLiteral) End() token.Pos {
 	return nodeEnd(wrapNode(j.Value))
 }
 
+func (i *IntervalLiteralSingle) Pos() token.Pos {
+	return i.Interval
+}
+
+func (i *IntervalLiteralSingle) End() token.Pos {
+	return i.DateTimePartEnd
+}
+
+func (i *IntervalLiteralRange) Pos() token.Pos {
+	return i.Interval
+}
+
+func (i *IntervalLiteralRange) End() token.Pos {
+	return i.EndingDateTimePartEnd
+}
+
 func (n *NewConstructor) Pos() token.Pos {
 	return n.New
 }
@@ -1907,7 +1915,7 @@ func (p *PropertyGraphElement) Pos() token.Pos {
 }
 
 func (p *PropertyGraphElement) End() token.Pos {
-	return nodeEnd(nodeChoice(wrapNode(p.Properties), wrapNode(p.Keys), wrapNode(p.Alias), wrapNode(p.Name)))
+	return nodeEnd(nodeChoice(wrapNode(p.DynamicProperties), wrapNode(p.DynamicLabel), wrapNode(p.Properties), wrapNode(p.Keys), wrapNode(p.Alias), wrapNode(p.Name)))
 }
 
 func (p *PropertyGraphSingleProperties) Pos() token.Pos {
@@ -2030,6 +2038,22 @@ func (p *PropertyGraphDerivedProperty) End() token.Pos {
 	return nodeEnd(nodeChoice(wrapNode(p.Alias), wrapNode(p.Expr)))
 }
 
+func (p *PropertyGraphDynamicLabel) Pos() token.Pos {
+	return p.Dynamic
+}
+
+func (p *PropertyGraphDynamicLabel) End() token.Pos {
+	return posAdd(p.Rparen, 1)
+}
+
+func (p *PropertyGraphDynamicProperties) Pos() token.Pos {
+	return p.Dynamic
+}
+
+func (p *PropertyGraphDynamicProperties) End() token.Pos {
+	return posAdd(p.Rparen, 1)
+}
+
 func (d *DropPropertyGraph) Pos() token.Pos {
 	return d.Drop
 }
diff --git a/ast/sql.go b/ast/sql.go
index c0fcff3..1ccdf5b 100644
--- a/ast/sql.go
+++ b/ast/sql.go
@@ -471,6 +471,8 @@ func (c *CallExpr) SQL() string {
 		sqlJoin(c.NamedArgs, ", ") +
 		sqlOpt(" ", c.NullHandling, "") +
 		sqlOpt(" ", c.Having, "") +
+		sqlOpt(" ", c.OrderBy, "") +
+		sqlOpt(" ", c.Limit, "") +
 		")" +
 		sqlOpt(" ", c.Hint, "")
 }
@@ -507,10 +509,6 @@ func (s *ExprArg) SQL() string {
 	return s.Expr.SQL()
 }
 
-func (i *IntervalArg) SQL() string {
-	return "INTERVAL " + i.Expr.SQL() + sqlOpt(" ", i.Unit, "")
-}
-
 func (s *SequenceArg) SQL() string {
 	return "SEQUENCE " + s.Expr.SQL()
 }
@@ -659,6 +657,14 @@ func (t *JSONLiteral) SQL() string {
 	return "JSON " + t.Value.SQL()
 }
 
+func (n *IntervalLiteralSingle) SQL() string {
+	return "INTERVAL " + n.Value.SQL() + " " + string(n.DateTimePart)
+}
+
+func (n *IntervalLiteralRange) SQL() string {
+	return "INTERVAL " + n.Value.SQL() + " " + string(n.StartingDateTimePart) + " TO " + string(n.EndingDateTimePart)
+}
+
 // ================================================================================
 //
 // NEW constructors
@@ -1209,7 +1215,9 @@ func (p *PropertyGraphElement) SQL() string {
 	return p.Name.SQL() +
 		sqlOpt(" AS ", p.Alias, "") +
 		sqlOpt(" ", p.Keys, "") +
-		sqlOpt(" ", p.Properties, "")
+		sqlOpt(" ", p.Properties, "") +
+		sqlOpt(" ", p.DynamicLabel, "") +
+		sqlOpt(" ", p.DynamicProperties, "")
 }
 
 func (p *PropertyGraphSingleProperties) SQL() string { return p.Properties.SQL() }
@@ -1267,6 +1275,14 @@ func (p *PropertyGraphDerivedProperty) SQL() string {
 	return p.Expr.SQL() + sqlOpt(" AS ", p.Alias, "")
 }
 
+func (p *PropertyGraphDynamicLabel) SQL() string {
+	return "DYNAMIC LABEL (" + p.ColumnName.SQL() + ")"
+}
+
+func (p *PropertyGraphDynamicProperties) SQL() string {
+	return "DYNAMIC PROPERTIES (" + p.ColumnName.SQL() + ")"
+}
+
 func (g *DropPropertyGraph) SQL() string {
 	return "DROP PROPERTY GRAPH " +
 		strOpt(g.IfExists, "IF EXISTS ") +
diff --git a/ast/walk_internal.go b/ast/walk_internal.go
index 594fa9a..61b3ad1 100644
--- a/ast/walk_internal.go
+++ b/ast/walk_internal.go
@@ -242,6 +242,8 @@ func walkInternal(node Node, v Visitor, stack []*stackItem) []*stackItem {
 
 	case *CallExpr:
 		stack = append(stack, &stackItem{node: wrapNode(n.Hint), visitor: v.Field("Hint")})
+		stack = append(stack, &stackItem{node: wrapNode(n.Limit), visitor: v.Field("Limit")})
+		stack = append(stack, &stackItem{node: wrapNode(n.OrderBy), visitor: v.Field("OrderBy")})
 		stack = append(stack, &stackItem{node: wrapNode(n.Having), visitor: v.Field("Having")})
 		stack = append(stack, &stackItem{node: wrapNode(n.NullHandling), visitor: v.Field("NullHandling")})
 		stack = append(stack, &stackItem{nodes: wrapNodes(n.NamedArgs), visitor: v.Field("NamedArgs")})
@@ -258,10 +260,6 @@ func walkInternal(node Node, v Visitor, stack []*stackItem) []*stackItem {
 	case *ExprArg:
 		stack = append(stack, &stackItem{node: wrapNode(n.Expr), visitor: v.Field("Expr")})
 
-	case *IntervalArg:
-		stack = append(stack, &stackItem{node: wrapNode(n.Unit), visitor: v.Field("Unit")})
-		stack = append(stack, &stackItem{node: wrapNode(n.Expr), visitor: v.Field("Expr")})
-
 	case *SequenceArg:
 		stack = append(stack, &stackItem{node: wrapNode(n.Expr), visitor: v.Field("Expr")})
 
@@ -405,6 +403,12 @@ func walkInternal(node Node, v Visitor, stack []*stackItem) []*stackItem {
 	case *JSONLiteral:
 		stack = append(stack, &stackItem{node: wrapNode(n.Value), visitor: v.Field("Value")})
 
+	case *IntervalLiteralSingle:
+		stack = append(stack, &stackItem{node: wrapNode(n.Value), visitor: v.Field("Value")})
+
+	case *IntervalLiteralRange:
+		stack = append(stack, &stackItem{node: wrapNode(n.Value), visitor: v.Field("Value")})
+
 	case *NewConstructor:
 		stack = append(stack, &stackItem{nodes: wrapNodes(n.Args), visitor: v.Field("Args")})
 		stack = append(stack, &stackItem{node: wrapNode(n.Type), visitor: v.Field("Type")})
@@ -866,6 +870,8 @@ func walkInternal(node Node, v Visitor, stack []*stackItem) []*stackItem {
 		stack = append(stack, &stackItem{nodes: wrapNodes(n.Elements), visitor: v.Field("Elements")})
 
 	case *PropertyGraphElement:
+		stack = append(stack, &stackItem{node: wrapNode(n.DynamicProperties), visitor: v.Field("DynamicProperties")})
+		stack = append(stack, &stackItem{node: wrapNode(n.DynamicLabel), visitor: v.Field("DynamicLabel")})
 		stack = append(stack, &stackItem{node: wrapNode(n.Properties), visitor: v.Field("Properties")})
 		stack = append(stack, &stackItem{node: wrapNode(n.Keys), visitor: v.Field("Keys")})
 		stack = append(stack, &stackItem{node: wrapNode(n.Alias), visitor: v.Field("Alias")})
@@ -924,6 +930,12 @@ func walkInternal(node Node, v Visitor, stack []*stackItem) []*stackItem {
 		stack = append(stack, &stackItem{node: wrapNode(n.Alias), visitor: v.Field("Alias")})
 		stack = append(stack, &stackItem{node: wrapNode(n.Expr), visitor: v.Field("Expr")})
 
+	case *PropertyGraphDynamicLabel:
+		stack = append(stack, &stackItem{node: wrapNode(n.ColumnName), visitor: v.Field("ColumnName")})
+
+	case *PropertyGraphDynamicProperties:
+		stack = append(stack, &stackItem{node: wrapNode(n.ColumnName), visitor: v.Field("ColumnName")})
+
 	case *DropPropertyGraph:
 		stack = append(stack, &stackItem{node: wrapNode(n.Name), visitor: v.Field("Name")})
 
diff --git a/go.mod b/go.mod
index e5561b8..00ddf4d 100644
--- a/go.mod
+++ b/go.mod
@@ -6,7 +6,7 @@ toolchain go1.23.5
 
 require (
 	github.com/MakeNowJust/heredoc/v2 v2.0.1
-	github.com/google/go-cmp v0.6.0
+	github.com/google/go-cmp v0.7.0
 	github.com/k0kubun/pp/v3 v3.4.1
 	github.com/pmezard/go-difflib v1.0.0
 )
diff --git a/go.sum b/go.sum
index 4a48df6..6e31b4d 100644
--- a/go.sum
+++ b/go.sum
@@ -2,6 +2,8 @@ github.com/MakeNowJust/heredoc/v2 v2.0.1 h1:rlCHh70XXXv7toz95ajQWOWQnN4WNLt0TdpZ
 github.com/MakeNowJust/heredoc/v2 v2.0.1/go.mod h1:6/2Abh5s+hc3g9nbWLe9ObDIOhaRrqsyY9MWy+4JdRM=
 github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
 github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
+github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8=
+github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU=
 github.com/k0kubun/pp/v3 v3.4.1 h1:1WdFZDRRqe8UsR61N/2RoOZ3ziTEqgTPVqKrHeb779Y=
 github.com/k0kubun/pp/v3 v3.4.1/go.mod h1:+SiNiqKnBfw1Nkj82Lh5bIeKQOAkPy6Xw9CAZUZ8npI=
 github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA=
diff --git a/parser.go b/parser.go
index b987989..5685765 100644
--- a/parser.go
+++ b/parser.go
@@ -1777,6 +1777,8 @@ func (p *Parser) parseLit() ast.Expr {
 	// In parser level, it is a valid ast.Expr, but it is semantically valid only in ast.BracedConstructorFieldExpr.
 	case "{":
 		return p.parseBracedConstructor()
+	case "INTERVAL":
+		return p.parseIntervalLiteral()
 	case token.TokenIdent:
 		id := p.Token
 		switch {
@@ -1887,6 +1889,8 @@ func (p *Parser) parseCallLike() ast.Expr {
 
 	nullHandling := p.tryParseNullHandlingModifier()
 	having := p.tryParseHavingModifier()
+	orderBy := p.tryParseOrderBy()
+	limit := p.tryParseLimit()
 
 	rparen := p.expect(")").Pos
 	hint := p.tryParseHint()
@@ -1899,6 +1903,8 @@ func (p *Parser) parseCallLike() ast.Expr {
 		NamedArgs:    namedArgs,
 		NullHandling: nullHandling,
 		Having:       having,
+		OrderBy:      orderBy,
+		Limit:        limit,
 		Hint:         hint,
 	}
 }
@@ -1993,9 +1999,6 @@ func (p *Parser) parseLambdaArg() *ast.LambdaArg {
 }
 
 func (p *Parser) parseArg() ast.Arg {
-	if i := p.tryParseIntervalArg(); i != nil {
-		return i
-	}
 	if s := p.tryParseSequenceArg(); s != nil {
 		return s
 	}
@@ -2005,22 +2008,6 @@ func (p *Parser) parseArg() ast.Arg {
 	return p.parseExprArg()
 }
 
-func (p *Parser) tryParseIntervalArg() *ast.IntervalArg {
-	if p.Token.Kind != "INTERVAL" {
-		return nil
-	}
-
-	pos := p.Token.Pos
-	p.nextToken()
-	e := p.parseExpr()
-	unit := p.parseIdent()
-	return &ast.IntervalArg{
-		Interval: pos,
-		Expr:     e,
-		Unit:     unit,
-	}
-}
-
 func (p *Parser) tryParseSequenceArg() *ast.SequenceArg {
 	if !p.Token.IsKeywordLike("SEQUENCE") {
 		return nil
@@ -2498,6 +2485,78 @@ func (p *Parser) parseJSONLiteral(id token.Token) *ast.JSONLiteral {
 	}
 }
 
+var validDateTimePartNames = []ast.DateTimePart{
+	ast.DateTimePartYear,
+	ast.DateTimePartMonth,
+	ast.DateTimePartDay,
+	ast.DateTimePartDayOfWeek,
+	ast.DateTimePartDayOfYear,
+	ast.DateTimePartQuarter,
+	ast.DateTimePartHour,
+	ast.DateTimePartMinute,
+	ast.DateTimePartSecond,
+	ast.DateTimePartMillisecond,
+	ast.DateTimePartMicrosecond,
+	ast.DateTimePartNanosecond,
+	ast.DateTimePartWeek,
+	ast.DateTimePartISOYear,
+	ast.DateTimePartISOWeek,
+	ast.DateTimePartDate,
+	ast.DateTimePartDateTime,
+	ast.DateTimePartTime,
+}
+
+func (p *Parser) parseDateTimePart() (part ast.DateTimePart, pos, end token.Pos) {
+	// Note: This function will support WEEKDAY(weekday) when it is released in Spanner
+
+	ident := p.parseIdent()
+
+	for _, dateTimePart := range validDateTimePartNames {
+		if char.EqualFold(ident.Name, string(dateTimePart)) {
+			return dateTimePart, ident.Pos(), ident.End()
+		}
+	}
+
+	panic(p.errorfAtPosition(ident.Pos(), ident.End(), "invalid date time part: %s", ident.Name))
+}
+
+func (p *Parser) parseIntervalLiteral() ast.Expr {
+	interval := p.expect("INTERVAL").Pos
+	expr := p.parseExpr()
+
+	// string parameter is not supported, so ast.Param will be caught as ast.IntValue.
+	switch e := expr.(type) {
+	case ast.IntValue:
+		unit, _, end := p.parseDateTimePart()
+
+		return &ast.IntervalLiteralSingle{
+			Interval:        interval,
+			Value:           e,
+			DateTimePart:    unit,
+			DateTimePartEnd: end,
+		}
+	case *ast.StringLiteral:
+		starting, _, _ := p.parseDateTimePart()
+
+		var ending ast.DateTimePart
+		var endingEnd token.Pos
+		if p.Token.Kind == "TO" {
+			p.nextToken()
+			ending, _, endingEnd = p.parseDateTimePart()
+		}
+
+		return &ast.IntervalLiteralRange{
+			Interval:              interval,
+			Value:                 e,
+			StartingDateTimePart:  starting,
+			EndingDateTimePart:    ending,
+			EndingDateTimePartEnd: endingEnd,
+		}
+	default:
+		panic(p.errorfAtToken(&p.Token, `expect int64_expression or datetime_parts_string, but: %v`, p.Token.Kind))
+	}
+}
+
 func (p *Parser) lookaheadSubQuery() bool {
 	lexer := p.Lexer.Clone()
 	defer func() {
@@ -2569,7 +2628,7 @@ func (p *Parser) parseType() (t ast.Type) {
 	}()
 
 	switch p.Token.Kind {
-	case token.TokenIdent:
+	case token.TokenIdent, "INTERVAL":
 		if !p.lookaheadSimpleType() {
 			return p.parseNamedType()
 		}
@@ -2595,9 +2654,20 @@ var simpleTypes = []string{
 	"BYTES",
 	"JSON",
 	"TOKENLIST",
+	"INTERVAL",
 }
 
 func (p *Parser) parseSimpleType() *ast.SimpleType {
+	// Only INTERVAL is a keyword.
+	if p.Token.Kind == "INTERVAL" {
+		pos := p.expect("INTERVAL").Pos
+
+		return &ast.SimpleType{
+			NamePos: pos,
+			Name:    ast.IntervalTypeName,
+		}
+	}
+
 	id := p.expect(token.TokenIdent)
 	for _, typeName := range simpleTypes {
 		if id.IsIdent(typeName) {
@@ -2795,10 +2865,14 @@ func (p *Parser) parseFieldType() *ast.StructField {
 }
 
 func (p *Parser) lookaheadType() bool {
-	return p.Token.Kind == token.TokenIdent || p.Token.Kind == "ARRAY" || p.Token.Kind == "STRUCT"
+	return p.Token.Kind == token.TokenIdent || p.Token.Kind == "INTERVAL" || p.Token.Kind == "ARRAY" || p.Token.Kind == "STRUCT"
 }
 
 func (p *Parser) lookaheadSimpleType() bool {
+	if p.Token.Kind == "INTERVAL" {
+		return true
+	}
+
 	if p.Token.Kind != token.TokenIdent {
 		return false
 	}
@@ -4748,12 +4822,16 @@ func (p *Parser) parsePropertyGraphElement() *ast.PropertyGraphElement {
 
 	keys := p.tryParsePropertyGraphElementKeys()
 	properties := p.tryParsePropertyGraphLabelsOrProperties()
+	dynamicLabel := p.tryParsePropertyGraphDynamicLabel()
+	dynamicProperties := p.tryParsePropertyGraphDynamicProperties()
 
 	return &ast.PropertyGraphElement{
-		Name:       name,
-		Alias:      alias,
-		Keys:       keys,
-		Properties: properties,
+		Name:              name,
+		Alias:             alias,
+		Keys:              keys,
+		Properties:        properties,
+		DynamicLabel:      dynamicLabel,
+		DynamicProperties: dynamicProperties,
 	}
 }
 
@@ -4965,6 +5043,70 @@ func (p *Parser) tryParsePropertyGraphColumnNameList() *ast.PropertyGraphColumnN
 	return p.parsePropertyGraphColumnNameList()
 }
 
+func (p *Parser) lookaheadPropertyGraphDynamicLabel() bool {
+	lexer := p.Lexer.Clone()
+	defer func() {
+		p.Lexer = lexer
+	}()
+
+	if !p.Token.IsKeywordLike("DYNAMIC") {
+		return false
+	}
+	p.nextToken()
+
+	return p.Token.IsKeywordLike("LABEL")
+}
+
+func (p *Parser) tryParsePropertyGraphDynamicLabel() *ast.PropertyGraphDynamicLabel {
+	if !p.lookaheadPropertyGraphDynamicLabel() {
+		return nil
+	}
+
+	dynamic := p.expectKeywordLike("DYNAMIC").Pos
+	p.expectKeywordLike("LABEL")
+	p.expect("(")
+	name := p.parseIdent()
+	rparen := p.expect(")").Pos
+
+	return &ast.PropertyGraphDynamicLabel{
+		Dynamic:    dynamic,
+		Rparen:     rparen,
+		ColumnName: name,
+	}
+}
+
+func (p *Parser) lookaheadPropertyGraphDynamicProperties() bool {
+	lexer := p.Lexer.Clone()
+	defer func() {
+		p.Lexer = lexer
+	}()
+
+	if !p.Token.IsKeywordLike("DYNAMIC") {
+		return false
+	}
+	p.nextToken()
+
+	return p.Token.IsKeywordLike("PROPERTIES")
+}
+
+func (p *Parser) tryParsePropertyGraphDynamicProperties() *ast.PropertyGraphDynamicProperties {
+	if !p.lookaheadPropertyGraphDynamicProperties() {
+		return nil
+	}
+
+	dynamic := p.expectKeywordLike("DYNAMIC").Pos
+	p.expectKeywordLike("PROPERTIES")
+	p.expect("(")
+	name := p.parseIdent()
+	rparen := p.expect(")").Pos
+
+	return &ast.PropertyGraphDynamicProperties{
+		Dynamic:    dynamic,
+		Rparen:     rparen,
+		ColumnName: name,
+	}
+}
+
 // end CREATE PROPERTY GRAPH
 
 func (p *Parser) parseDropPropertyGraph(pos token.Pos) *ast.DropPropertyGraph {
@@ -5113,6 +5255,8 @@ func (p *Parser) parseDropModel(pos token.Pos) *ast.DropModel {
 	}
 }
 
+// Usually, you don't need to update scalarSchemaTypes because NamedType can handle types.
+// It is maintained for compatibility.
 var scalarSchemaTypes = []string{
 	"BOOL",
 	"INT64",
diff --git a/token/token.go b/token/token.go
index a953117..111131f 100644
--- a/token/token.go
+++ b/token/token.go
@@ -9,7 +9,7 @@ type Token struct {
 	Comments []TokenComment
 	Space    string
 	Raw      string
-	AsString string // available for TokenIdent, TokenString and TokenBytes
+	AsString string // available for TokenIdent, TokenParam, TokenString and TokenBytes
 	Base     int    // 10 or 16 on TokenInt
 	Pos, End Pos
 }


Test patch:
diff --git a/testdata/input/ddl/create_property_graph_schemaless.sql b/testdata/input/ddl/create_property_graph_schemaless.sql
new file mode 100644
index 0000000..afdc141
--- /dev/null
+++ b/testdata/input/ddl/create_property_graph_schemaless.sql
@@ -0,0 +1,13 @@
+CREATE PROPERTY GRAPH FinGraph
+  NODE TABLES (
+    GraphNode
+      DYNAMIC LABEL (label)
+      DYNAMIC PROPERTIES (properties)
+  )
+  EDGE TABLES (
+    GraphEdge
+      SOURCE KEY (id) REFERENCES GraphNode(id)
+      DESTINATION KEY (dest_id) REFERENCES GraphNode(id)
+      DYNAMIC LABEL (label)
+      DYNAMIC PROPERTIES (properties)
+  )
diff --git a/testdata/input/query/aggregate_functions.sql b/testdata/input/query/aggregate_functions.sql
new file mode 100644
index 0000000..fe589cd
--- /dev/null
+++ b/testdata/input/query/aggregate_functions.sql
@@ -0,0 +1,15 @@
+SELECT
+  COUNT(x),
+  COUNT(DISTINCT x),
+  COUNT(x IGNORE NULLS),
+  COUNT(x RESPECT NULLS),
+  ANY_VALUE(x HAVING MAX y),
+  ANY_VALUE(x HAVING MIN y),
+  ARRAY_AGG(x ORDER BY y ASC),
+  ARRAY_AGG(x ORDER BY y DESC),
+  ARRAY_AGG(x ORDER BY y DESC, z ASC),
+  ARRAY_AGG(x LIMIT 10),
+  ARRAY_AGG(DISTINCT x ORDER BY x LIMIT 5),
+  STRING_AGG(x HAVING MAX y ORDER BY z),
+  STRING_AGG(x IGNORE NULLS LIMIT 100),
+  ARRAY_AGG(DISTINCT x HAVING MIN y ORDER BY z DESC LIMIT 1)
diff --git a/testdata/input/query/select_interval_values.sql b/testdata/input/query/select_interval_values.sql
new file mode 100644
index 0000000..2ca353d
--- /dev/null
+++ b/testdata/input/query/select_interval_values.sql
@@ -0,0 +1,45 @@
+SELECT
+  -- Single datetime part
+  INTERVAL 1 YEAR,
+  INTERVAL -5 DAY,
+  INTERVAL 90 SECOND,
+  INTERVAL 1 QUARTER,
+  INTERVAL 6 WEEK,
+  INTERVAL 25 HOUR,
+  INTERVAL 1500 MINUTE,
+  INTERVAL 90000 SECOND,
+  INTERVAL 90 MINUTE,
+  INTERVAL -25 MONTH,
+  INTERVAL -90 MINUTE,
+  INTERVAL @param YEAR,
+
+  -- Datetime part range
+  INTERVAL '2-11' YEAR TO MONTH,
+  INTERVAL '2-11 28' YEAR TO DAY,
+  INTERVAL '2-11 28 16' YEAR TO HOUR,
+  INTERVAL '2-11 28 16:15' YEAR TO MINUTE,
+  INTERVAL '2-11 28 16:15:14' YEAR TO SECOND,
+  INTERVAL '11 28' MONTH TO DAY,
+  INTERVAL '11 28 16' MONTH TO HOUR,
+  INTERVAL '11 28 16:15' MONTH TO MINUTE,
+  INTERVAL '11 28 16:15:14' MONTH TO SECOND,
+  INTERVAL '28 16' DAY TO HOUR,
+  INTERVAL '28 16:15' DAY TO MINUTE,
+  INTERVAL '28 16:15:14' DAY TO SECOND,
+  INTERVAL '16:15' HOUR TO MINUTE,
+  INTERVAL '16:15:14' HOUR TO SECOND,
+  INTERVAL '15:14' MINUTE TO SECOND,
+  INTERVAL '10:20:30.52' HOUR TO SECOND,
+  INTERVAL '1-2' YEAR TO MONTH,
+  INTERVAL '1 -15' MONTH TO DAY,
+  INTERVAL '1 5:30' DAY TO MINUTE,
+  INTERVAL '-23-2 10 -12:30' YEAR TO MINUTE,
+  INTERVAL '-0-2 10 0:30' MONTH TO MINUTE,
+  INTERVAL '-30:10' MINUTE TO SECOND,
+
+  -- INTERVAL as typename
+  CAST("P1D" AS INTERVAL),
+  ARRAY<INTERVAL>[],
+  ARRAY<INTERVAL>[INTERVAL 1 DAY],
+  STRUCT<value INTERVAL>(INTERVAL 1 DAY),
+
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 d1abf5b..c69a4fc 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
@@ -80,18 +80,17 @@ ALTER TABLE foo ADD COLUMN expired_at TIMESTAMP AS (IF (status != "OPEN" AND sta
                   Name:    "updated_at",
                 },
               },
-              &ast.IntervalArg{
-                Interval: 127,
-                Expr:     &ast.IntLiteral{
-                  ValuePos: 136,
-                  ValueEnd: 139,
-                  Base:     10,
-                  Value:    "120",
-                },
-                Unit: &ast.Ident{
-                  NamePos: 140,
-                  NameEnd: 143,
-                  Name:    "DAY",
+              &ast.ExprArg{
+                Expr: &ast.IntervalLiteralSingle{
+                  Interval:        127,
+                  DateTimePartEnd: 143,
+                  Value:           &ast.IntLiteral{
+                    ValuePos: 136,
+                    ValueEnd: 139,
+                    Base:     10,
+                    Value:    "120",
+                  },
+                  DateTimePart: "DAY",
                 },
               },
             },
diff --git a/testdata/result/ddl/create_property_graph_schemaless.sql.txt b/testdata/result/ddl/create_property_graph_schemaless.sql.txt
new file mode 100644
index 0000000..2fdfcb4
--- /dev/null
+++ b/testdata/result/ddl/create_property_graph_schemaless.sql.txt
@@ -0,0 +1,158 @@
+--- create_property_graph_schemaless.sql
+CREATE PROPERTY GRAPH FinGraph
+  NODE TABLES (
+    GraphNode
+      DYNAMIC LABEL (label)
+      DYNAMIC PROPERTIES (properties)
+  )
+  EDGE TABLES (
+    GraphEdge
+      SOURCE KEY (id) REFERENCES GraphNode(id)
+      DESTINATION KEY (dest_id) REFERENCES GraphNode(id)
+      DYNAMIC LABEL (label)
+      DYNAMIC PROPERTIES (properties)
+  )
+
+--- AST
+&ast.CreatePropertyGraph{
+  Name: &ast.Ident{
+    NamePos: 22,
+    NameEnd: 30,
+    Name:    "FinGraph",
+  },
+  Content: &ast.PropertyGraphContent{
+    NodeTables: &ast.PropertyGraphNodeTables{
+      Node:   33,
+      Tables: &ast.PropertyGraphElementList{
+        Lparen:   45,
+        Rparen:   129,
+        Elements: []*ast.PropertyGraphElement{
+          &ast.PropertyGraphElement{
+            Name: &ast.Ident{
+              NamePos: 51,
+              NameEnd: 60,
+              Name:    "GraphNode",
+            },
+            DynamicLabel: &ast.PropertyGraphDynamicLabel{
+              Dynamic:    67,
+              Rparen:     87,
+              ColumnName: &ast.Ident{
+                NamePos: 82,
+                NameEnd: 87,
+                Name:    "label",
+              },
+            },
+            DynamicProperties: &ast.PropertyGraphDynamicProperties{
+              Dynamic:    95,
+              Rparen:     125,
+              ColumnName: &ast.Ident{
+                NamePos: 115,
+                NameEnd: 125,
+                Name:    "properties",
+              },
+            },
+          },
+        },
+      },
+    },
+    EdgeTables: &ast.PropertyGraphEdgeTables{
+      Edge:   133,
+      Tables: &ast.PropertyGraphElementList{
+        Lparen:   145,
+        Rparen:   333,
+        Elements: []*ast.PropertyGraphElement{
+          &ast.PropertyGraphElement{
+            Name: &ast.Ident{
+              NamePos: 151,
+              NameEnd: 160,
+              Name:    "GraphEdge",
+            },
+            Keys: &ast.PropertyGraphEdgeElementKeys{
+              Source: &ast.PropertyGraphSourceKey{
+                Source: 167,
+                Keys:   &ast.PropertyGraphColumnNameList{
+                  Lparen:         178,
+                  Rparen:         181,
+                  ColumnNameList: []*ast.Ident{
+                    &ast.Ident{
+                      NamePos: 179,
+                      NameEnd: 181,
+                      Name:    "id",
+                    },
+                  },
+                },
+                ElementReference: &ast.Ident{
+                  NamePos: 194,
+                  NameEnd: 203,
+                  Name:    "GraphNode",
+                },
+                ReferenceColumns: &ast.PropertyGraphColumnNameList{
+                  Lparen:         203,
+                  Rparen:         206,
+                  ColumnNameList: []*ast.Ident{
+                    &ast.Ident{
+                      NamePos: 204,
+                      NameEnd: 206,
+                      Name:    "id",
+                    },
+                  },
+                },
+              },
+              Destination: &ast.PropertyGraphDestinationKey{
+                Destination: 214,
+                Keys:        &ast.PropertyGraphColumnNameList{
+                  Lparen:         230,
+                  Rparen:         238,
+                  ColumnNameList: []*ast.Ident{
+                    &ast.Ident{
+                      NamePos: 231,
+                      NameEnd: 238,
+                      Name:    "dest_id",
+                    },
+                  },
+                },
+                ElementReference: &ast.Ident{
+                  NamePos: 251,
+                  NameEnd: 260,
+                  Name:    "GraphNode",
+                },
+                ReferenceColumns: &ast.PropertyGraphColumnNameList{
+                  Lparen:         260,
+                  Rparen:         263,
+                  ColumnNameList: []*ast.Ident{
+                    &ast.Ident{
+                      NamePos: 261,
+                      NameEnd: 263,
+                      Name:    "id",
+                    },
+                  },
+                },
+              },
+            },
+            DynamicLabel: &ast.PropertyGraphDynamicLabel{
+              Dynamic:    271,
+              Rparen:     291,
+              ColumnName: &ast.Ident{
+                NamePos: 286,
+                NameEnd: 291,
+                Name:    "label",
+              },
+            },
+            DynamicProperties: &ast.PropertyGraphDynamicProperties{
+              Dynamic:    299,
+              Rparen:     329,
+              ColumnName: &ast.Ident{
+                NamePos: 319,
+                NameEnd: 329,
+                Name:    "properties",
+              },
+            },
+          },
+        },
+      },
+    },
+  },
+}
+
+--- SQL
+CREATE PROPERTY GRAPH FinGraph NODE TABLES (GraphNode DYNAMIC LABEL (label) DYNAMIC PROPERTIES (properties)) EDGE TABLES (GraphEdge SOURCE KEY (id) REFERENCES GraphNode (id) DESTINATION KEY (dest_id) REFERENCES GraphNode (id) DYNAMIC LABEL (label) DYNAMIC PROPERTIES (properties))
diff --git a/testdata/result/query/aggregate_functions.sql.txt b/testdata/result/query/aggregate_functions.sql.txt
new file mode 100644
index 0000000..ec5f907
--- /dev/null
+++ b/testdata/result/query/aggregate_functions.sql.txt
@@ -0,0 +1,523 @@
+--- aggregate_functions.sql
+SELECT
+  COUNT(x),
+  COUNT(DISTINCT x),
+  COUNT(x IGNORE NULLS),
+  COUNT(x RESPECT NULLS),
+  ANY_VALUE(x HAVING MAX y),
+  ANY_VALUE(x HAVING MIN y),
+  ARRAY_AGG(x ORDER BY y ASC),
+  ARRAY_AGG(x ORDER BY y DESC),
+  ARRAY_AGG(x ORDER BY y DESC, z ASC),
+  ARRAY_AGG(x LIMIT 10),
+  ARRAY_AGG(DISTINCT x ORDER BY x LIMIT 5),
+  STRING_AGG(x HAVING MAX y ORDER BY z),
+  STRING_AGG(x IGNORE NULLS LIMIT 100),
+  ARRAY_AGG(DISTINCT x HAVING MIN y ORDER BY z DESC LIMIT 1)
+
+--- AST
+&ast.QueryStatement{
+  Query: &ast.Select{
+    Results: []ast.SelectItem{
+      &ast.ExprSelectItem{
+        Expr: &ast.CallExpr{
+          Rparen: 16,
+          Func:   &ast.Path{
+            Idents: []*ast.Ident{
+              &ast.Ident{
+                NamePos: 9,
+                NameEnd: 14,
+                Name:    "COUNT",
+              },
+            },
+          },
+          Args: []ast.Arg{
+            &ast.ExprArg{
+              Expr: &ast.Ident{
+                NamePos: 15,
+                NameEnd: 16,
+                Name:    "x",
+              },
+            },
+          },
+        },
+      },
+      &ast.ExprSelectItem{
+        Expr: &ast.CallExpr{
+          Rparen: 37,
+          Func:   &ast.Path{
+            Idents: []*ast.Ident{
+              &ast.Ident{
+                NamePos: 21,
+                NameEnd: 26,
+                Name:    "COUNT",
+              },
+            },
+          },
+          Distinct: true,
+          Args:     []ast.Arg{
+            &ast.ExprArg{
+              Expr: &ast.Ident{
+                NamePos: 36,
+                NameEnd: 37,
+                Name:    "x",
+              },
+            },
+          },
+        },
+      },
+      &ast.ExprSelectItem{
+        Expr: &ast.CallExpr{
+          Rparen: 62,
+          Func:   &ast.Path{
+            Idents: []*ast.Ident{
+              &ast.Ident{
+                NamePos: 42,
+                NameEnd: 47,
+                Name:    "COUNT",
+              },
+            },
+          },
+          Args: []ast.Arg{
+            &ast.ExprArg{
+              Expr: &ast.Ident{
+                NamePos: 48,
+                NameEnd: 49,
+                Name:    "x",
+              },
+            },
+          },
+          NullHandling: &ast.IgnoreNulls{
+            Ignore: 50,
+            Nulls:  57,
+          },
+        },
+      },
+      &ast.ExprSelectItem{
+        Expr: &ast.CallExpr{
+          Rparen: 88,
+          Func:   &ast.Path{
+            Idents: []*ast.Ident{
+              &ast.Ident{
+                NamePos: 67,
+                NameEnd: 72,
+                Name:    "COUNT",
+              },
+            },
+          },
+          Args: []ast.Arg{
+            &ast.ExprArg{
+              Expr: &ast.Ident{
+                NamePos: 73,
+                NameEnd: 74,
+                Name:    "x",
+              },
+            },
+          },
+          NullHandling: &ast.RespectNulls{
+            Respect: 75,
+            Nulls:   83,
+          },
+        },
+      },
+      &ast.ExprSelectItem{
+        Expr: &ast.CallExpr{
+          Rparen: 117,
+          Func:   &ast.Path{
+            Idents: []*ast.Ident{
+              &ast.Ident{
+                NamePos: 93,
+                NameEnd: 102,
+                Name:    "ANY_VALUE",
+              },
+            },
+          },
+          Args: []ast.Arg{
+            &ast.ExprArg{
+              Expr: &ast.Ident{
+                NamePos: 103,
+                NameEnd: 104,
+                Name:    "x",
+              },
+            },
+          },
+          Having: &ast.HavingMax{
+            Having: 105,
+            Expr:   &ast.Ident{
+              NamePos: 116,
+              NameEnd: 117,
+              Name:    "y",
+            },
+          },
+        },
+      },
+      &ast.ExprSelectItem{
+        Expr: &ast.CallExpr{
+          Rparen: 146,
+          Func:   &ast.Path{
+            Idents: []*ast.Ident{
+              &ast.Ident{
+                NamePos: 122,
+                NameEnd: 131,
+                Name:    "ANY_VALUE",
+              },
+            },
+          },
+          Args: []ast.Arg{
+            &ast.ExprArg{
+              Expr: &ast.Ident{
+                NamePos: 132,
+                NameEnd: 133,
+                Name:    "x",
+              },
+            },
+          },
+          Having: &ast.HavingMin{
+            Having: 134,
+            Expr:   &ast.Ident{
+              NamePos: 145,
+              NameEnd: 146,
+              Name:    "y",
+            },
+          },
+        },
+      },
+      &ast.ExprSelectItem{
+        Expr: &ast.CallExpr{
+          Rparen: 177,
+          Func:   &ast.Path{
+            Idents: []*ast.Ident{
+              &ast.Ident{
+                NamePos: 151,
+                NameEnd: 160,
+                Name:    "ARRAY_AGG",
+              },
+            },
+          },
+          Args: []ast.Arg{
+            &ast.ExprArg{
+              Expr: &ast.Ident{
+                NamePos: 161,
+                NameEnd: 162,
+                Name:    "x",
+              },
+            },
+          },
+          OrderBy: &ast.OrderBy{
+            Order: 163,
+            Items: []*ast.OrderByItem{
+              &ast.OrderByItem{
+                DirPos: 174,
+                Expr:   &ast.Ident{
+                  NamePos: 172,
+                  NameEnd: 173,
+                  Name:    "y",
+                },
+                Dir: "ASC",
+              },
+            },
+          },
+        },
+      },
+      &ast.ExprSelectItem{
+        Expr: &ast.CallExpr{
+          Rparen: 209,
+          Func:   &ast.Path{
+            Idents: []*ast.Ident{
+              &ast.Ident{
+                NamePos: 182,
+                NameEnd: 191,
+                Name:    "ARRAY_AGG",
+              },
+            },
+          },
+          Args: []ast.Arg{
+            &ast.ExprArg{
+              Expr: &ast.Ident{
+                NamePos: 192,
+                NameEnd: 193,
+                Name:    "x",
+              },
+            },
+          },
+          OrderBy: &ast.OrderBy{
+            Order: 194,
+            Items: []*ast.OrderByItem{
+              &ast.OrderByItem{
+                DirPos: 205,
+                Expr:   &ast.Ident{
+                  NamePos: 203,
+                  NameEnd: 204,
+                  Name:    "y",
+                },
+                Dir: "DESC",
+              },
+            },
+          },
+        },
+      },
+      &ast.ExprSelectItem{
+        Expr: &ast.CallExpr{
+          Rparen: 248,
+          Func:   &ast.Path{
+            Idents: []*ast.Ident{
+              &ast.Ident{
+                NamePos: 214,
+                NameEnd: 223,
+                Name:    "ARRAY_AGG",
+              },
+            },
+          },
+          Args: []ast.Arg{
+            &ast.ExprArg{
+              Expr: &ast.Ident{
+                NamePos: 224,
+                NameEnd: 225,
+                Name:    "x",
+              },
+            },
+          },
+          OrderBy: &ast.OrderBy{
+            Order: 226,
+            Items: []*ast.OrderByItem{
+              &ast.OrderByItem{
+                DirPos: 237,
+                Expr:   &ast.Ident{
+                  NamePos: 235,
+                  NameEnd: 236,
+                  Name:    "y",
+                },
+                Dir: "DESC",
+              },
+              &ast.OrderByItem{
+                DirPos: 245,
+                Expr:   &ast.Ident{
+                  NamePos: 243,
+                  NameEnd: 244,
+                  Name:    "z",
+                },
+                Dir: "ASC",
+              },
+            },
+          },
+        },
+      },
+      &ast.ExprSelectItem{
+        Expr: &ast.CallExpr{
+          Rparen: 273,
+          Func:   &ast.Path{
+            Idents: []*ast.Ident{
+              &ast.Ident{
+                NamePos: 253,
+                NameEnd: 262,
+                Name:    "ARRAY_AGG",
+              },
+            },
+          },
+          Args: []ast.Arg{
+            &ast.ExprArg{
+              Expr: &ast.Ident{
+                NamePos: 263,
+                NameEnd: 264,
+                Name:    "x",
+              },
+            },
+          },
+          Limit: &ast.Limit{
+            Limit: 265,
+            Count: &ast.IntLiteral{
+              ValuePos: 271,
+              ValueEnd: 273,
+              Base:     10,
+              Value:    "10",
+            },
+          },
+        },
+      },
+      &ast.ExprSelectItem{
+        Expr: &ast.CallExpr{
+          Rparen: 317,
+          Func:   &ast.Path{
+            Idents: []*ast.Ident{
+              &ast.Ident{
+                NamePos: 278,
+                NameEnd: 287,
+                Name:    "ARRAY_AGG",
+              },
+            },
+          },
+          Distinct: true,
+          Args:     []ast.Arg{
+            &ast.ExprArg{
+              Expr: &ast.Ident{
+                NamePos: 297,
+                NameEnd: 298,
+                Name:    "x",
+              },
+            },
+          },
+          OrderBy: &ast.OrderBy{
+            Order: 299,
+            Items: []*ast.OrderByItem{
+              &ast.OrderByItem{
+                DirPos: -1,
+                Expr:   &ast.Ident{
+                  NamePos: 308,
+                  NameEnd: 309,
+                  Name:    "x",
+                },
+              },
+            },
+          },
+          Limit: &ast.Limit{
+            Limit: 310,
+            Count: &ast.IntLiteral{
+              ValuePos: 316,
+              ValueEnd: 317,
+              Base:     10,
+              Value:    "5",
+            },
+          },
+        },
+      },
+      &ast.ExprSelectItem{
+        Expr: &ast.CallExpr{
+          Rparen: 358,
+          Func:   &ast.Path{
+            Idents: []*ast.Ident{
+              &ast.Ident{
+                NamePos: 322,
+                NameEnd: 332,
+                Name:    "STRING_AGG",
+              },
+            },
+          },
+          Args: []ast.Arg{
+            &ast.ExprArg{
+              Expr: &ast.Ident{
+                NamePos: 333,
+                NameEnd: 334,
+                Name:    "x",
+              },
+            },
+          },
+          Having: &ast.HavingMax{
+            Having: 335,
+            Expr:   &ast.Ident{
+              NamePos: 346,
+              NameEnd: 347,
+              Name:    "y",
+            },
+          },
+          OrderBy: &ast.OrderBy{
+            Order: 348,
+            Items: []*ast.OrderByItem{
+              &ast.OrderByItem{
+                DirPos: -1,
+                Expr:   &ast.Ident{
+                  NamePos: 357,
+                  NameEnd: 358,
+                  Name:    "z",
+                },
+              },
+            },
+          },
+        },
+      },
+      &ast.ExprSelectItem{
+        Expr: &ast.CallExpr{
+          Rparen: 398,
+          Func:   &ast.Path{
+            Idents: []*ast.Ident{
+              &ast.Ident{
+                NamePos: 363,
+                NameEnd: 373,
+                Name:    "STRING_AGG",
+              },
+            },
+          },
+          Args: []ast.Arg{
+            &ast.ExprArg{
+              Expr: &ast.Ident{
+                NamePos: 374,
+                NameEnd: 375,
+                Name:    "x",
+              },
+            },
+          },
+          NullHandling: &ast.IgnoreNulls{
+            Ignore: 376,
+            Nulls:  383,
+          },
+          Limit: &ast.Limit{
+            Limit: 389,
+            Count: &ast.IntLiteral{
+              ValuePos: 395,
+              ValueEnd: 398,
+              Base:     10,
+              Value:    "100",
+            },
+          },
+        },
+      },
+      &ast.ExprSelectItem{
+        Expr: &ast.CallExpr{
+          Rparen: 460,
+          Func:   &ast.Path{
+            Idents: []*ast.Ident{
+              &ast.Ident{
+                NamePos: 403,
+                NameEnd: 412,
+                Name:    "ARRAY_AGG",
+              },
+            },
+          },
+          Distinct: true,
+          Args:     []ast.Arg{
+            &ast.ExprArg{
+              Expr: &ast.Ident{
+                NamePos: 422,
+                NameEnd: 423,
+                Name:    "x",
+              },
+            },
+          },
+          Having: &ast.HavingMin{
+            Having: 424,
+            Expr:   &ast.Ident{
+              NamePos: 435,
+              NameEnd: 436,
+              Name:    "y",
+            },
+          },
+          OrderBy: &ast.OrderBy{
+            Order: 437,
+            Items: []*ast.OrderByItem{
+              &ast.OrderByItem{
+                DirPos: 448,
+                Expr:   &ast.Ident{
+                  NamePos: 446,
+                  NameEnd: 447,
+                  Name:    "z",
+                },
+                Dir: "DESC",
+              },
+            },
+          },
+          Limit: &ast.Limit{
+            Limit: 453,
+            Count: &ast.IntLiteral{
+              ValuePos: 459,
+              ValueEnd: 460,
+              Base:     10,
+              Value:    "1",
+            },
+          },
+        },
+      },
+    },
+  },
+}
+
+--- SQL
+SELECT COUNT(x), COUNT(DISTINCT x), COUNT(x IGNORE NULLS), COUNT(x RESPECT NULLS), ANY_VALUE(x HAVING MAX y), ANY_VALUE(x HAVING MIN y), ARRAY_AGG(x ORDER BY y ASC), ARRAY_AGG(x ORDER BY y DESC), ARRAY_AGG(x ORDER BY y DESC, z ASC), ARRAY_AGG(x LIMIT 10), ARRAY_AGG(DISTINCT x ORDER BY x LIMIT 5), STRING_AGG(x HAVING MAX y ORDER BY z), STRING_AGG(x IGNORE NULLS LIMIT 100), ARRAY_AGG(DISTINCT x HAVING MIN y ORDER BY z DESC LIMIT 1)
diff --git a/testdata/result/query/select_expr.sql.txt b/testdata/result/query/select_expr.sql.txt
index 392a6cc..6108393 100644
--- a/testdata/result/query/select_expr.sql.txt
+++ b/testdata/result/query/select_expr.sql.txt
@@ -600,18 +600,17 @@ select 1 + 2, 1 - 2,
                 },
               },
             },
-            &ast.IntervalArg{
-              Interval: 542,
-              Expr:     &ast.IntLiteral{
-                ValuePos: 551,
-                ValueEnd: 552,
-                Base:     10,
-                Value:    "5",
-              },
-              Unit: &ast.Ident{
-                NamePos: 553,
-                NameEnd: 556,
-                Name:    "day",
+            &ast.ExprArg{
+              Expr: &ast.IntervalLiteralSingle{
+                Interval:        542,
+                DateTimePartEnd: 556,
+                Value:           &ast.IntLiteral{
+                  ValuePos: 551,
+                  ValueEnd: 552,
+                  Base:     10,
+                  Value:    "5",
+                },
+                DateTimePart: "DAY",
               },
             },
           },
@@ -640,18 +639,17 @@ select 1 + 2, 1 - 2,
                 },
               },
             },
-            &ast.IntervalArg{
-              Interval: 613,
-              Expr:     &ast.IntLiteral{
-                ValuePos: 622,
-                ValueEnd: 623,
-                Base:     10,
-                Value:    "5",
-              },
-              Unit: &ast.Ident{
-                NamePos: 624,
-                NameEnd: 628,
-                Name:    "hour",
+            &ast.ExprArg{
+              Expr: &ast.IntervalLiteralSingle{
+                Interval:        613,
+                DateTimePartEnd: 628,
+                Value:           &ast.IntLiteral{
+                  ValuePos: 622,
+                  ValueEnd: 623,
+                  Base:     10,
+                  Value:    "5",
+                },
+                DateTimePart: "HOUR",
               },
             },
           },
@@ -875,4 +873,4 @@ select 1 + 2, 1 - 2,
 }
 
 --- SQL
-SELECT 1 + 2, 1 - 2, 1 * 2, 2 / 2, +1 + +1, -1 + -1, +1.2, -3.4, ~1 ^ ~1, 1 ^ 2, 2 & 1, 2 | 1, 1 << 2, 2 >> 1, foo.bar * +foo.bar * -foo.bar, (SELECT 1 `1`).`1`, NOT NOT TRUE, [1, 2, 3][OFFSET(1)], [1, 2, 3][OFFSET(1)], [1, 2, 3][ORDINAL(1)], CASE WHEN 1 = 1 THEN "1 = 1" ELSE "else" END, CASE 1 WHEN 1 THEN "1" WHEN 2 THEN "2" ELSE "other" END, date_add(DATE "2019-09-01", INTERVAL 5 day), timestamp_add(TIMESTAMP "2019-09-01 08:11:22", INTERVAL 5 hour), 1 IN (1, 2, 3), 2 IN UNNEST([1, 2, 3]), 3 IN (SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3), [1] || [2], IF(1 > 1, 1, 2) + 1 AS result
+SELECT 1 + 2, 1 - 2, 1 * 2, 2 / 2, +1 + +1, -1 + -1, +1.2, -3.4, ~1 ^ ~1, 1 ^ 2, 2 & 1, 2 | 1, 1 << 2, 2 >> 1, foo.bar * +foo.bar * -foo.bar, (SELECT 1 `1`).`1`, NOT NOT TRUE, [1, 2, 3][OFFSET(1)], [1, 2, 3][OFFSET(1)], [1, 2, 3][ORDINAL(1)], CASE WHEN 1 = 1 THEN "1 = 1" ELSE "else" END, CASE 1 WHEN 1 THEN "1" WHEN 2 THEN "2" ELSE "other" END, date_add(DATE "2019-09-01", INTERVAL 5 DAY), timestamp_add(TIMESTAMP "2019-09-01 08:11:22", INTERVAL 5 HOUR), 1 IN (1, 2, 3), 2 IN UNNEST([1, 2, 3]), 3 IN (SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3), [1] || [2], IF(1 > 1, 1, 2) + 1 AS result
diff --git a/testdata/result/query/select_interval_values.sql.txt b/testdata/result/query/select_interval_values.sql.txt
new file mode 100644
index 0000000..cc4705e
--- /dev/null
+++ b/testdata/result/query/select_interval_values.sql.txt
@@ -0,0 +1,579 @@
+--- select_interval_values.sql
+SELECT
+  -- Single datetime part
+  INTERVAL 1 YEAR,
+  INTERVAL -5 DAY,
+  INTERVAL 90 SECOND,
+  INTERVAL 1 QUARTER,
+  INTERVAL 6 WEEK,
+  INTERVAL 25 HOUR,
+  INTERVAL 1500 MINUTE,
+  INTERVAL 90000 SECOND,
+  INTERVAL 90 MINUTE,
+  INTERVAL -25 MONTH,
+  INTERVAL -90 MINUTE,
+  INTERVAL @param YEAR,
+
+  -- Datetime part range
+  INTERVAL '2-11' YEAR TO MONTH,
+  INTERVAL '2-11 28' YEAR TO DAY,
+  INTERVAL '2-11 28 16' YEAR TO HOUR,
+  INTERVAL '2-11 28 16:15' YEAR TO MINUTE,
+  INTERVAL '2-11 28 16:15:14' YEAR TO SECOND,
+  INTERVAL '11 28' MONTH TO DAY,
+  INTERVAL '11 28 16' MONTH TO HOUR,
+  INTERVAL '11 28 16:15' MONTH TO MINUTE,
+  INTERVAL '11 28 16:15:14' MONTH TO SECOND,
+  INTERVAL '28 16' DAY TO HOUR,
+  INTERVAL '28 16:15' DAY TO MINUTE,
+  INTERVAL '28 16:15:14' DAY TO SECOND,
+  INTERVAL '16:15' HOUR TO MINUTE,
+  INTERVAL '16:15:14' HOUR TO SECOND,
+  INTERVAL '15:14' MINUTE TO SECOND,
+  INTERVAL '10:20:30.52' HOUR TO SECOND,
+  INTERVAL '1-2' YEAR TO MONTH,
+  INTERVAL '1 -15' MONTH TO DAY,
+  INTERVAL '1 5:30' DAY TO MINUTE,
+  INTERVAL '-23-2 10 -12:30' YEAR TO MINUTE,
+  INTERVAL '-0-2 10 0:30' MONTH TO MINUTE,
+  INTERVAL '-30:10' MINUTE TO SECOND,
+
+  -- INTERVAL as typename
+  CAST("P1D" AS INTERVAL),
+  ARRAY<INTERVAL>[],
+  ARRAY<INTERVAL>[INTERVAL 1 DAY],
+  STRUCT<value INTERVAL>(INTERVAL 1 DAY),
+
+
+--- AST
+&ast.QueryStatement{
+  Query: &ast.Select{
+    Results: []ast.SelectItem{
+      &ast.ExprSelectItem{
+        Expr: &ast.IntervalLiteralSingle{
+          Interval:        35,
+          DateTimePartEnd: 50,
+          Value:           &ast.IntLiteral{
+            ValuePos: 44,
+            ValueEnd: 45,
+            Base:     10,
+            Value:    "1",
+          },
+          DateTimePart: "YEAR",
+        },
+      },
+      &ast.ExprSelectItem{
+        Expr: &ast.IntervalLiteralSingle{
+          Interval:        54,
+          DateTimePartEnd: 69,
+          Value:           &ast.IntLiteral{
+            ValuePos: 63,
+            ValueEnd: 65,
+            Base:     10,
+            Value:    "-5",
+          },
+          DateTimePart: "DAY",
+        },
+      },
+      &ast.ExprSelectItem{
+        Expr: &ast.IntervalLiteralSingle{
+          Interval:        73,
+          DateTimePartEnd: 91,
+          Value:           &ast.IntLiteral{
+            ValuePos: 82,
+            ValueEnd: 84,
+            Base:     10,
+            Value:    "90",
+          },
+          DateTimePart: "SECOND",
+        },
+      },
+      &ast.ExprSelectItem{
+        Expr: &ast.IntervalLiteralSingle{
+          Interval:        95,
+          DateTimePartEnd: 113,
+          Value:           &ast.IntLiteral{
+            ValuePos: 104,
+            ValueEnd: 105,
+            Base:     10,
+            Value:    "1",
+          },
+          DateTimePart: "QUARTER",
+        },
+      },
+      &ast.ExprSelectItem{
+        Expr: &ast.IntervalLiteralSingle{
+          Interval:        117,
+          DateTimePartEnd: 132,
+          Value:           &ast.IntLiteral{
+            ValuePos: 126,
+            ValueEnd: 127,
+            Base:     10,
+            Value:    "6",
+          },
+          DateTimePart: "WEEK",
+        },
+      },
+      &ast.ExprSelectItem{
+        Expr: &ast.IntervalLiteralSingle{
+          Interval:        136,
+          DateTimePartEnd: 152,
+          Value:           &ast.IntLiteral{
+            ValuePos: 145,
+            ValueEnd: 147,
+            Base:     10,
+            Value:    "25",
+          },
+          DateTimePart: "HOUR",
+        },
+      },
+      &ast.ExprSelectItem{
+        Expr: &ast.IntervalLiteralSingle{
+          Interval:        156,
+          DateTimePartEnd: 176,
+          Value:           &ast.IntLiteral{
+            ValuePos: 165,
+            ValueEnd: 169,
+            Base:     10,
+            Value:    "1500",
+          },
+          DateTimePart: "MINUTE",
+        },
+      },
+      &ast.ExprSelectItem{
+        Expr: &ast.IntervalLiteralSingle{
+          Interval:        180,
+          DateTimePartEnd: 201,
+          Value:           &ast.IntLiteral{
+            ValuePos: 189,
+            ValueEnd: 194,
+            Base:     10,
+            Value:    "90000",
+          },
+          DateTimePart: "SECOND",
+        },
+      },
+      &ast.ExprSelectItem{
+        Expr: &ast.IntervalLiteralSingle{
+          Interval:        205,
+          DateTimePartEnd: 223,
+          Value:           &ast.IntLiteral{
+            ValuePos: 214,
+            ValueEnd: 216,
+            Base:     10,
+            Value:    "90",
+          },
+          DateTimePart: "MINUTE",
+        },
+      },
+      &ast.ExprSelectItem{
+        Expr: &ast.IntervalLiteralSingle{
+          Interval:        227,
+          DateTimePartEnd: 245,
+          Value:           &ast.IntLiteral{
+            ValuePos: 236,
+            ValueEnd: 239,
+            Base:     10,
+            Value:    "-25",
+          },
+          DateTimePart: "MONTH",
+        },
+      },
+      &ast.ExprSelectItem{
+        Expr: &ast.IntervalLiteralSingle{
+          Interval:        249,
+          DateTimePartEnd: 268,
+          Value:           &ast.IntLiteral{
+            ValuePos: 258,
+            ValueEnd: 261,
+            Base:     10,
+            Value:    "-90",
+          },
+          DateTimePart: "MINUTE",
+        },
+      },
+      &ast.ExprSelectItem{
+        Expr: &ast.IntervalLiteralSingle{
+          Interval:        272,
+          DateTimePartEnd: 292,
+          Value:           &ast.Param{
+            Atmark: 281,
+            Name:   "param",
+          },
+          DateTimePart: "YEAR",
+        },
+      },
+      &ast.ExprSelectItem{
+        Expr: &ast.IntervalLiteralRange{
+          Interval:              322,
+          EndingDateTimePartEnd: 351,
+          Value:                 &ast.StringLiteral{
+            ValuePos: 331,
+            ValueEnd: 337,
+            Value:    "2-11",
+          },
+          StartingDateTimePart: "YEAR",
+          EndingDateTimePart:   "MONTH",
+        },
+      },
+      &ast.ExprSelectItem{
+        Expr: &ast.IntervalLiteralRange{
+          Interval:              355,
+          EndingDateTimePartEnd: 385,
+          Value:                 &ast.StringLiteral{
+            ValuePos: 364,
+            ValueEnd: 373,
+            Value:    "2-11 28",
+          },
+          StartingDateTimePart: "YEAR",
+          EndingDateTimePart:   "DAY",
+        },
+      },
+      &ast.ExprSelectItem{
+        Expr: &ast.IntervalLiteralRange{
+          Interval:              389,
+          EndingDateTimePartEnd: 423,
+          Value:                 &ast.StringLiteral{
+            ValuePos: 398,
+            ValueEnd: 410,
+            Value:    "2-11 28 16",
+          },
+          StartingDateTimePart: "YEAR",
+          EndingDateTimePart:   "HOUR",
+        },
+      },
+      &ast.ExprSelectItem{
+        Expr: &ast.IntervalLiteralRange{
+          Interval:              427,
+          EndingDateTimePartEnd: 466,
+          Value:                 &ast.StringLiteral{
+            ValuePos: 436,
+            ValueEnd: 451,
+            Value:    "2-11 28 16:15",
+          },
+          StartingDateTimePart: "YEAR",
+          EndingDateTimePart:   "MINUTE",
+        },
+      },
+      &ast.ExprSelectItem{
+        Expr: &ast.IntervalLiteralRange{
+          Interval:              470,
+          EndingDateTimePartEnd: 512,
+          Value:                 &ast.StringLiteral{
+            ValuePos: 479,
+            ValueEnd: 497,
+            Value:    "2-11 28 16:15:14",
+          },
+          StartingDateTimePart: "YEAR",
+          EndingDateTimePart:   "SECOND",
+        },
+      },
+      &ast.ExprSelectItem{
+        Expr: &ast.IntervalLiteralRange{
+          Interval:              516,
+          EndingDateTimePartEnd: 545,
+          Value:                 &ast.StringLiteral{
+            ValuePos: 525,
+            ValueEnd: 532,
+            Value:    "11 28",
+          },
+          StartingDateTimePart: "MONTH",
+          EndingDateTimePart:   "DAY",
+        },
+      },
+      &ast.ExprSelectItem{
+        Expr: &ast.IntervalLiteralRange{
+          Interval:              549,
+          EndingDateTimePartEnd: 582,
+          Value:                 &ast.StringLiteral{
+            ValuePos: 558,
+            ValueEnd: 568,
+            Value:    "11 28 16",
+          },
+          StartingDateTimePart: "MONTH",
+          EndingDateTimePart:   "HOUR",
+        },
+      },
+      &ast.ExprSelectItem{
+        Expr: &ast.IntervalLiteralRange{
+          Interval:              586,
+          EndingDateTimePartEnd: 624,
+          Value:                 &ast.StringLiteral{
+            ValuePos: 595,
+            ValueEnd: 608,
+            Value:    "11 28 16:15",
+          },
+          StartingDateTimePart: "MONTH",
+          EndingDateTimePart:   "MINUTE",
+        },
+      },
+      &ast.ExprSelectItem{
+        Expr: &ast.IntervalLiteralRange{
+          Interval:              628,
+          EndingDateTimePartEnd: 669,
+          Value:                 &ast.StringLiteral{
+            ValuePos: 637,
+            ValueEnd: 653,
+            Value:    "11 28 16:15:14",
+          },
+          StartingDateTimePart: "MONTH",
+          EndingDateTimePart:   "SECOND",
+        },
+      },
+      &ast.ExprSelectItem{
+        Expr: &ast.IntervalLiteralRange{
+          Interval:              673,
+          EndingDateTimePartEnd: 701,
+          Value:                 &ast.StringLiteral{
+            ValuePos: 682,
+            ValueEnd: 689,
+            Value:    "28 16",
+          },
+          StartingDateTimePart: "DAY",
+          EndingDateTimePart:   "HOUR",
+        },
+      },
+      &ast.ExprSelectItem{
+        Expr: &ast.IntervalLiteralRange{
+          Interval:              705,
+          EndingDateTimePartEnd: 738,
+          Value:                 &ast.StringLiteral{
+            ValuePos: 714,
+            ValueEnd: 724,
+            Value:    "28 16:15",
+          },
+          StartingDateTimePart: "DAY",
+          EndingDateTimePart:   "MINUTE",
+        },
+      },
+      &ast.ExprSelectItem{
+        Expr: &ast.IntervalLiteralRange{
+          Interval:              742,
+          EndingDateTimePartEnd: 778,
+          Value:                 &ast.StringLiteral{
+            ValuePos: 751,
+            ValueEnd: 764,
+            Value:    "28 16:15:14",
+          },
+          StartingDateTimePart: "DAY",
+          EndingDateTimePart:   "SECOND",
+        },
+      },
+      &ast.ExprSelectItem{
+        Expr: &ast.IntervalLiteralRange{
+          Interval:              782,
+          EndingDateTimePartEnd: 813,
+          Value:                 &ast.StringLiteral{
+            ValuePos: 791,
+            ValueEnd: 798,
+            Value:    "16:15",
+          },
+          StartingDateTimePart: "HOUR",
+          EndingDateTimePart:   "MINUTE",
+        },
+      },
+      &ast.ExprSelectItem{
+        Expr: &ast.IntervalLiteralRange{
+          Interval:              817,
+          EndingDateTimePartEnd: 851,
+          Value:                 &ast.StringLiteral{
+            ValuePos: 826,
+            ValueEnd: 836,
+            Value:    "16:15:14",
+          },
+          StartingDateTimePart: "HOUR",
+          EndingDateTimePart:   "SECOND",
+        },
+      },
+      &ast.ExprSelectItem{
+        Expr: &ast.IntervalLiteralRange{
+          Interval:              855,
+          EndingDateTimePartEnd: 888,
+          Value:                 &ast.StringLiteral{
+            ValuePos: 864,
+            ValueEnd: 871,
+            Value:    "15:14",
+          },
+          StartingDateTimePart: "MINUTE",
+          EndingDateTimePart:   "SECOND",
+        },
+      },
+      &ast.ExprSelectItem{
+        Expr: &ast.IntervalLiteralRange{
+          Interval:              892,
+          EndingDateTimePartEnd: 929,
+          Value:                 &ast.StringLiteral{
+            ValuePos: 901,
+            ValueEnd: 914,
+            Value:    "10:20:30.52",
+          },
+          StartingDateTimePart: "HOUR",
+          EndingDateTimePart:   "SECOND",
+        },
+      },
+      &ast.ExprSelectItem{
+        Expr: &ast.IntervalLiteralRange{
+          Interval:              933,
+          EndingDateTimePartEnd: 961,
+          Value:                 &ast.StringLiteral{
+            ValuePos: 942,
+            ValueEnd: 947,
+            Value:    "1-2",
+          },
+          StartingDateTimePart: "YEAR",
+          EndingDateTimePart:   "MONTH",
+        },
+      },
+      &ast.ExprSelectItem{
+        Expr: &ast.IntervalLiteralRange{
+          Interval:              965,
+          EndingDateTimePartEnd: 994,
+          Value:                 &ast.StringLiteral{
+            ValuePos: 974,
+            ValueEnd: 981,
+            Value:    "1 -15",
+          },
+          StartingDateTimePart: "MONTH",
+          EndingDateTimePart:   "DAY",
+        },
+      },
+      &ast.ExprSelectItem{
+        Expr: &ast.IntervalLiteralRange{
+          Interval:              998,
+          EndingDateTimePartEnd: 1029,
+          Value:                 &ast.StringLiteral{
+            ValuePos: 1007,
+            ValueEnd: 1015,
+            Value:    "1 5:30",
+          },
+          StartingDateTimePart: "DAY",
+          EndingDateTimePart:   "MINUTE",
+        },
+      },
+      &ast.ExprSelectItem{
+        Expr: &ast.IntervalLiteralRange{
+          Interval:              1033,
+          EndingDateTimePartEnd: 1074,
+          Value:                 &ast.StringLiteral{
+            ValuePos: 1042,
+            ValueEnd: 1059,
+            Value:    "-23-2 10 -12:30",
+          },
+          StartingDateTimePart: "YEAR",
+          EndingDateTimePart:   "MINUTE",
+        },
+      },
+      &ast.ExprSelectItem{
+        Expr: &ast.IntervalLiteralRange{
+          Interval:              1078,
+          EndingDateTimePartEnd: 1117,
+          Value:                 &ast.StringLiteral{
+            ValuePos: 1087,
+            ValueEnd: 1101,
+            Value:    "-0-2 10 0:30",
+          },
+          StartingDateTimePart: "MONTH",
+          EndingDateTimePart:   "MINUTE",
+        },
+      },
+      &ast.ExprSelectItem{
+        Expr: &ast.IntervalLiteralRange{
+          Interval:              1121,
+          EndingDateTimePartEnd: 1155,
+          Value:                 &ast.StringLiteral{
+            ValuePos: 1130,
+            ValueEnd: 1138,
+            Value:    "-30:10",
+          },
+          StartingDateTimePart: "MINUTE",
+          EndingDateTimePart:   "SECOND",
+        },
+      },
+      &ast.ExprSelectItem{
+        Expr: &ast.CastExpr{
+          Cast:   1186,
+          Rparen: 1208,
+          Expr:   &ast.StringLiteral{
+            ValuePos: 1191,
+            ValueEnd: 1196,
+            Value:    "P1D",
+          },
+          Type: &ast.SimpleType{
+            NamePos: 1200,
+            Name:    "INTERVAL",
+          },
+        },
+      },
+      &ast.ExprSelectItem{
+        Expr: &ast.ArrayLiteral{
+          Array:  1213,
+          Lbrack: 1228,
+          Rbrack: 1229,
+          Type:   &ast.SimpleType{
+            NamePos: 1219,
+            Name:    "INTERVAL",
+          },
+        },
+      },
+      &ast.ExprSelectItem{
+        Expr: &ast.ArrayLiteral{
+          Array:  1234,
+          Lbrack: 1249,
+          Rbrack: 1264,
+          Type:   &ast.SimpleType{
+            NamePos: 1240,
+            Name:    "INTERVAL",
+          },
+          Values: []ast.Expr{
+            &ast.IntervalLiteralSingle{
+              Interval:        1250,
+              DateTimePartEnd: 1264,
+              Value:           &ast.IntLiteral{
+                ValuePos: 1259,
+                ValueEnd: 1260,
+                Base:     10,
+                Value:    "1",
+              },
+              DateTimePart: "DAY",
+            },
+          },
+        },
+      },
+      &ast.ExprSelectItem{
+        Expr: &ast.TypedStructLiteral{
+          Struct: 1269,
+          Rparen: 1306,
+          Fields: []*ast.StructField{
+            &ast.StructField{
+              Ident: &ast.Ident{
+                NamePos: 1276,
+                NameEnd: 1281,
+                Name:    "value",
+              },
+              Type: &ast.SimpleType{
+                NamePos: 1282,
+                Name:    "INTERVAL",
+              },
+            },
+          },
+          Values: []ast.Expr{
+            &ast.IntervalLiteralSingle{
+              Interval:        1292,
+              DateTimePartEnd: 1306,
+              Value:           &ast.IntLiteral{
+                ValuePos: 1301,
+                ValueEnd: 1302,
+                Base:     10,
+                Value:    "1",
+              },
+              DateTimePart: "DAY",
+            },
+          },
+        },
+      },
+    },
+  },
+}
+
+--- SQL
+SELECT INTERVAL 1 YEAR, INTERVAL -5 DAY, INTERVAL 90 SECOND, INTERVAL 1 QUARTER, INTERVAL 6 WEEK, INTERVAL 25 HOUR, INTERVAL 1500 MINUTE, INTERVAL 90000 SECOND, INTERVAL 90 MINUTE, INTERVAL -25 MONTH, INTERVAL -90 MINUTE, INTERVAL @param YEAR, INTERVAL "2-11" YEAR TO MONTH, INTERVAL "2-11 28" YEAR TO DAY, INTERVAL "2-11 28 16" YEAR TO HOUR, INTERVAL "2-11 28 16:15" YEAR TO MINUTE, INTERVAL "2-11 28 16:15:14" YEAR TO SECOND, INTERVAL "11 28" MONTH TO DAY, INTERVAL "11 28 16" MONTH TO HOUR, INTERVAL "11 28 16:15" MONTH TO MINUTE, INTERVAL "11 28 16:15:14" MONTH TO SECOND, INTERVAL "28 16" DAY TO HOUR, INTERVAL "28 16:15" DAY TO MINUTE, INTERVAL "28 16:15:14" DAY TO SECOND, INTERVAL "16:15" HOUR TO MINUTE, INTERVAL "16:15:14" HOUR TO SECOND, INTERVAL "15:14" MINUTE TO SECOND, INTERVAL "10:20:30.52" HOUR TO SECOND, INTERVAL "1-2" YEAR TO MONTH, INTERVAL "1 -15" MONTH TO DAY, INTERVAL "1 5:30" DAY TO MINUTE, INTERVAL "-23-2 10 -12:30" YEAR TO MINUTE, INTERVAL "-0-2 10 0:30" MONTH TO MINUTE, INTERVAL "-30:10" MINUTE TO SECOND, CAST("P1D" AS INTERVAL), ARRAY<INTERVAL>[], ARRAY<INTERVAL>[INTERVAL 1 DAY], STRUCT<value INTERVAL>(INTERVAL 1 DAY)
diff --git a/testdata/result/statement/aggregate_functions.sql.txt b/testdata/result/statement/aggregate_functions.sql.txt
new file mode 100644
index 0000000..ec5f907
--- /dev/null
+++ b/testdata/result/statement/aggregate_functions.sql.txt
@@ -0,0 +1,523 @@
+--- aggregate_functions.sql
+SELECT
+  COUNT(x),
+  COUNT(DISTINCT x),
+  COUNT(x IGNORE NULLS),
+  COUNT(x RESPECT NULLS),
+  ANY_VALUE(x HAVING MAX y),
+  ANY_VALUE(x HAVING MIN y),
+  ARRAY_AGG(x ORDER BY y ASC),
+  ARRAY_AGG(x ORDER BY y DESC),
+  ARRAY_AGG(x ORDER BY y DESC, z ASC),
+  ARRAY_AGG(x LIMIT 10),
+  ARRAY_AGG(DISTINCT x ORDER BY x LIMIT 5),
+  STRING_AGG(x HAVING MAX y ORDER BY z),
+  STRING_AGG(x IGNORE NULLS LIMIT 100),
+  ARRAY_AGG(DISTINCT x HAVING MIN y ORDER BY z DESC LIMIT 1)
+
+--- AST
+&ast.QueryStatement{
+  Query: &ast.Select{
+    Results: []ast.SelectItem{
+      &ast.ExprSelectItem{
+        Expr: &ast.CallExpr{
+          Rparen: 16,
+          Func:   &ast.Path{
+            Idents: []*ast.Ident{
+              &ast.Ident{
+                NamePos: 9,
+                NameEnd: 14,
+                Name:    "COUNT",
+              },
+            },
+          },
+          Args: []ast.Arg{
+            &ast.ExprArg{
+              Expr: &ast.Ident{
+                NamePos: 15,
+                NameEnd: 16,
+                Name:    "x",
+              },
+            },
+          },
+        },
+      },
+      &ast.ExprSelectItem{
+        Expr: &ast.CallExpr{
+          Rparen: 37,
+          Func:   &ast.Path{
+            Idents: []*ast.Ident{
+              &ast.Ident{
+                NamePos: 21,
+                NameEnd: 26,
+                Name:    "COUNT",
+              },
+            },
+          },
+          Distinct: true,
+          Args:     []ast.Arg{
+            &ast.ExprArg{
+              Expr: &ast.Ident{
+                NamePos: 36,
+                NameEnd: 37,
+                Name:    "x",
+              },
+            },
+          },
+        },
+      },
+      &ast.ExprSelectItem{
+        Expr: &ast.CallExpr{
+          Rparen: 62,
+          Func:   &ast.Path{
+            Idents: []*ast.Ident{
+              &ast.Ident{
+                NamePos: 42,
+                NameEnd: 47,
+                Name:    "COUNT",
+              },
+            },
+          },
+          Args: []ast.Arg{
+            &ast.ExprArg{
+              Expr: &ast.Ident{
+                NamePos: 48,
+                NameEnd: 49,
+                Name:    "x",
+              },
+            },
+          },
+          NullHandling: &ast.IgnoreNulls{
+            Ignore: 50,
+            Nulls:  57,
+          },
+        },
+      },
+      &ast.ExprSelectItem{
+        Expr: &ast.CallExpr{
+          Rparen: 88,
+          Func:   &ast.Path{
+            Idents: []*ast.Ident{
+              &ast.Ident{
+                NamePos: 67,
+                NameEnd: 72,
+                Name:    "COUNT",
+              },
+            },
+          },
+          Args: []ast.Arg{
+            &ast.ExprArg{
+              Expr: &ast.Ident{
+                NamePos: 73,
+                NameEnd: 74,
+                Name:    "x",
+              },
+            },
+          },
+          NullHandling: &ast.RespectNulls{
+            Respect: 75,
+            Nulls:   83,
+          },
+        },
+      },
+      &ast.ExprSelectItem{
+        Expr: &ast.CallExpr{
+          Rparen: 117,
+          Func:   &ast.Path{
+            Idents: []*ast.Ident{
+              &ast.Ident{
+                NamePos: 93,
+                NameEnd: 102,
+                Name:    "ANY_VALUE",
+              },
+            },
+          },
+          Args: []ast.Arg{
+            &ast.ExprArg{
+              Expr: &ast.Ident{
+                NamePos: 103,
+                NameEnd: 104,
+                Name:    "x",
+              },
+            },
+          },
+          Having: &ast.HavingMax{
+            Having: 105,
+            Expr:   &ast.Ident{
+              NamePos: 116,
+              NameEnd: 117,
+              Name:    "y",
+            },
+          },
+        },
+      },
+      &ast.ExprSelectItem{
+        Expr: &ast.CallExpr{
+          Rparen: 146,
+          Func:   &ast.Path{
+            Idents: []*ast.Ident{
+              &ast.Ident{
+                NamePos: 122,
+                NameEnd: 131,
+                Name:    "ANY_VALUE",
+              },
+            },
+          },
+          Args: []ast.Arg{
+            &ast.ExprArg{
+              Expr: &ast.Ident{
+                NamePos: 132,
+                NameEnd: 133,
+                Name:    "x",
+              },
+            },
+          },
+          Having: &ast.HavingMin{
+            Having: 134,
+            Expr:   &ast.Ident{
+              NamePos: 145,
+              NameEnd: 146,
+              Name:    "y",
+            },
+          },
+        },
+      },
+      &ast.ExprSelectItem{
+        Expr: &ast.CallExpr{
+          Rparen: 177,
+          Func:   &ast.Path{
+            Idents: []*ast.Ident{
+              &ast.Ident{
+                NamePos: 151,
+                NameEnd: 160,
+                Name:    "ARRAY_AGG",
+              },
+            },
+          },
+          Args: []ast.Arg{
+            &ast.ExprArg{
+              Expr: &ast.Ident{
+                NamePos: 161,
+                NameEnd: 162,
+                Name:    "x",
+              },
+            },
+          },
+          OrderBy: &ast.OrderBy{
+            Order: 163,
+            Items: []*ast.OrderByItem{
+              &ast.OrderByItem{
+                DirPos: 174,
+                Expr:   &ast.Ident{
+                  NamePos: 172,
+                  NameEnd: 173,
+                  Name:    "y",
+                },
+                Dir: "ASC",
+              },
+            },
+          },
+        },
+      },
+      &ast.ExprSelectItem{
+        Expr: &ast.CallExpr{
+          Rparen: 209,
+          Func:   &ast.Path{
+            Idents: []*ast.Ident{
+              &ast.Ident{
+                NamePos: 182,
+                NameEnd: 191,
+                Name:    "ARRAY_AGG",
+              },
+            },
+          },
+          Args: []ast.Arg{
+            &ast.ExprArg{
+              Expr: &ast.Ident{
+                NamePos: 192,
+                NameEnd: 193,
+                Name:    "x",
+              },
+            },
+          },
+          OrderBy: &ast.OrderBy{
+            Order: 194,
+            Items: []*ast.OrderByItem{
+              &ast.OrderByItem{
+                DirPos: 205,
+                Expr:   &ast.Ident{
+                  NamePos: 203,
+                  NameEnd: 204,
+                  Name:    "y",
+                },
+                Dir: "DESC",
+              },
+            },
+          },
+        },
+      },
+      &ast.ExprSelectItem{
+        Expr: &ast.CallExpr{
+          Rparen: 248,
+          Func:   &ast.Path{
+            Idents: []*ast.Ident{
+              &ast.Ident{
+                NamePos: 214,
+                NameEnd: 223,
+                Name:    "ARRAY_AGG",
+              },
+            },
+          },
+          Args: []ast.Arg{
+            &ast.ExprArg{
+              Expr: &ast.Ident{
+                NamePos: 224,
+                NameEnd: 225,
+                Name:    "x",
+              },
+            },
+          },
+          OrderBy: &ast.OrderBy{
+            Order: 226,
+            Items: []*ast.OrderByItem{
+              &ast.OrderByItem{
+                DirPos: 237,
+                Expr:   &ast.Ident{
+                  NamePos: 235,
+                  NameEnd: 236,
+                  Name:    "y",
+                },
+                Dir: "DESC",
+              },
+              &ast.OrderByItem{
+                DirPos: 245,
+                Expr:   &ast.Ident{
+                  NamePos: 243,
+                  NameEnd: 244,
+                  Name:    "z",
+                },
+                Dir: "ASC",
+              },
+            },
+          },
+        },
+      },
+      &ast.ExprSelectItem{
+        Expr: &ast.CallExpr{
+          Rparen: 273,
+          Func:   &ast.Path{
+            Idents: []*ast.Ident{
+              &ast.Ident{
+                NamePos: 253,
+                NameEnd: 262,
+                Name:    "ARRAY_AGG",
+              },
+            },
+          },
+          Args: []ast.Arg{
+            &ast.ExprArg{
+              Expr: &ast.Ident{
+                NamePos: 263,
+                NameEnd: 264,
+                Name:    "x",
+              },
+            },
+          },
+          Limit: &ast.Limit{
+            Limit: 265,
+            Count: &ast.IntLiteral{
+              ValuePos: 271,
+              ValueEnd: 273,
+              Base:     10,
+              Value:    "10",
+            },
+          },
+        },
+      },
+      &ast.ExprSelectItem{
+        Expr: &ast.CallExpr{
+          Rparen: 317,
+          Func:   &ast.Path{
+            Idents: []*ast.Ident{
+              &ast.Ident{
+                NamePos: 278,
+                NameEnd: 287,
+                Name:    "ARRAY_AGG",
+              },
+            },
+          },
+          Distinct: true,
+          Args:     []ast.Arg{
+            &ast.ExprArg{
+              Expr: &ast.Ident{
+                NamePos: 297,
+                NameEnd: 298,
+                Name:    "x",
+              },
+            },
+          },
+          OrderBy: &ast.OrderBy{
+            Order: 299,
+            Items: []*ast.OrderByItem{
+              &ast.OrderByItem{
+                DirPos: -1,
+                Expr:   &ast.Ident{
+                  NamePos: 308,
+                  NameEnd: 309,
+                  Name:    "x",
+                },
+              },
+            },
+          },
+          Limit: &ast.Limit{
+            Limit: 310,
+            Count: &ast.IntLiteral{
+              ValuePos: 316,
+              ValueEnd: 317,
+              Base:     10,
+              Value:    "5",
+            },
+          },
+        },
+      },
+      &ast.ExprSelectItem{
+        Expr: &ast.CallExpr{
+          Rparen: 358,
+          Func:   &ast.Path{
+            Idents: []*ast.Ident{
+              &ast.Ident{
+                NamePos: 322,
+                NameEnd: 332,
+                Name:    "STRING_AGG",
+              },
+            },
+          },
+          Args: []ast.Arg{
+            &ast.ExprArg{
+              Expr: &ast.Ident{
+                NamePos: 333,
+                NameEnd: 334,
+                Name:    "x",
+              },
+            },
+          },
+          Having: &ast.HavingMax{
+            Having: 335,
+            Expr:   &ast.Ident{
+              NamePos: 346,
+              NameEnd: 347,
+              Name:    "y",
+            },
+          },
+          OrderBy: &ast.OrderBy{
+            Order: 348,
+            Items: []*ast.OrderByItem{
+              &ast.OrderByItem{
+                DirPos: -1,
+                Expr:   &ast.Ident{
+                  NamePos: 357,
+                  NameEnd: 358,
+                  Name:    "z",
+                },
+              },
+            },
+          },
+        },
+      },
+      &ast.ExprSelectItem{
+        Expr: &ast.CallExpr{
+          Rparen: 398,
+          Func:   &ast.Path{
+            Idents: []*ast.Ident{
+              &ast.Ident{
+                NamePos: 363,
+                NameEnd: 373,
+                Name:    "STRING_AGG",
+              },
+            },
+          },
+          Args: []ast.Arg{
+            &ast.ExprArg{
+              Expr: &ast.Ident{
+                NamePos: 374,
+                NameEnd: 375,
+                Name:    "x",
+              },
+            },
+          },
+          NullHandling: &ast.IgnoreNulls{
+            Ignore: 376,
+            Nulls:  383,
+          },
+          Limit: &ast.Limit{
+            Limit: 389,
+            Count: &ast.IntLiteral{
+              ValuePos: 395,
+              ValueEnd: 398,
+              Base:     10,
+              Value:    "100",
+            },
+          },
+        },
+      },
+      &ast.ExprSelectItem{
+        Expr: &ast.CallExpr{
+          Rparen: 460,
+          Func:   &ast.Path{
+            Idents: []*ast.Ident{
+              &ast.Ident{
+                NamePos: 403,
+                NameEnd: 412,
+                Name:    "ARRAY_AGG",
+              },
+            },
+          },
+          Distinct: true,
+          Args:     []ast.Arg{
+            &ast.ExprArg{
+              Expr: &ast.Ident{
+                NamePos: 422,
+                NameEnd: 423,
+                Name:    "x",
+              },
+            },
+          },
+          Having: &ast.HavingMin{
+            Having: 424,
+            Expr:   &ast.Ident{
+              NamePos: 435,
+              NameEnd: 436,
+              Name:    "y",
+            },
+          },
+          OrderBy: &ast.OrderBy{
+            Order: 437,
+            Items: []*ast.OrderByItem{
+              &ast.OrderByItem{
+                DirPos: 448,
+                Expr:   &ast.Ident{
+                  NamePos: 446,
+                  NameEnd: 447,
+                  Name:    "z",
+                },
+                Dir: "DESC",
+              },
+            },
+          },
+          Limit: &ast.Limit{
+            Limit: 453,
+            Count: &ast.IntLiteral{
+              ValuePos: 459,
+              ValueEnd: 460,
+              Base:     10,
+              Value:    "1",
+            },
+          },
+        },
+      },
+    },
+  },
+}
+
+--- SQL
+SELECT COUNT(x), COUNT(DISTINCT x), COUNT(x IGNORE NULLS), COUNT(x RESPECT NULLS), ANY_VALUE(x HAVING MAX y), ANY_VALUE(x HAVING MIN y), ARRAY_AGG(x ORDER BY y ASC), ARRAY_AGG(x ORDER BY y DESC), ARRAY_AGG(x ORDER BY y DESC, z ASC), ARRAY_AGG(x LIMIT 10), ARRAY_AGG(DISTINCT x ORDER BY x LIMIT 5), STRING_AGG(x HAVING MAX y ORDER BY z), STRING_AGG(x IGNORE NULLS LIMIT 100), ARRAY_AGG(DISTINCT x HAVING MIN y ORDER BY z DESC LIMIT 1)
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 d1abf5b..c69a4fc 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
@@ -80,18 +80,17 @@ ALTER TABLE foo ADD COLUMN expired_at TIMESTAMP AS (IF (status != "OPEN" AND sta
                   Name:    "updated_at",
                 },
               },
-              &ast.IntervalArg{
-                Interval: 127,
-                Expr:     &ast.IntLiteral{
-                  ValuePos: 136,
-                  ValueEnd: 139,
-                  Base:     10,
-                  Value:    "120",
-                },
-                Unit: &ast.Ident{
-                  NamePos: 140,
-                  NameEnd: 143,
-                  Name:    "DAY",
+              &ast.ExprArg{
+                Expr: &ast.IntervalLiteralSingle{
+                  Interval:        127,
+                  DateTimePartEnd: 143,
+                  Value:           &ast.IntLiteral{
+                    ValuePos: 136,
+                    ValueEnd: 139,
+                    Base:     10,
+                    Value:    "120",
+                  },
+                  DateTimePart: "DAY",
                 },
               },
             },
diff --git a/testdata/result/statement/create_property_graph_schemaless.sql.txt b/testdata/result/statement/create_property_graph_schemaless.sql.txt
new file mode 100644
index 0000000..2fdfcb4
--- /dev/null
+++ b/testdata/result/statement/create_property_graph_schemaless.sql.txt
@@ -0,0 +1,158 @@
+--- create_property_graph_schemaless.sql
+CREATE PROPERTY GRAPH FinGraph
+  NODE TABLES (
+    GraphNode
+      DYNAMIC LABEL (label)
+      DYNAMIC PROPERTIES (properties)
+  )
+  EDGE TABLES (
+    GraphEdge
+      SOURCE KEY (id) REFERENCES GraphNode(id)
+      DESTINATION KEY (dest_id) REFERENCES GraphNode(id)
+      DYNAMIC LABEL (label)
+      DYNAMIC PROPERTIES (properties)
+  )
+
+--- AST
+&ast.CreatePropertyGraph{
+  Name: &ast.Ident{
+    NamePos: 22,
+    NameEnd: 30,
+    Name:    "FinGraph",
+  },
+  Content: &ast.PropertyGraphContent{
+    NodeTables: &ast.PropertyGraphNodeTables{
+      Node:   33,
+      Tables: &ast.PropertyGraphElementList{
+        Lparen:   45,
+        Rparen:   129,
+        Elements: []*ast.PropertyGraphElement{
+          &ast.PropertyGraphElement{
+            Name: &ast.Ident{
+              NamePos: 51,
+              NameEnd: 60,
+              Name:    "GraphNode",
+            },
+            DynamicLabel: &ast.PropertyGraphDynamicLabel{
+              Dynamic:    67,
+              Rparen:     87,
+              ColumnName: &ast.Ident{
+                NamePos: 82,
+                NameEnd: 87,
+                Name:    "label",
+              },
+            },
+            DynamicProperties: &ast.PropertyGraphDynamicProperties{
+              Dynamic:    95,
+              Rparen:     125,
+              ColumnName: &ast.Ident{
+                NamePos: 115,
+                NameEnd: 125,
+                Name:    "properties",
+              },
+            },
+          },
+        },
+      },
+    },
+    EdgeTables: &ast.PropertyGraphEdgeTables{
+      Edge:   133,
+      Tables: &ast.PropertyGraphElementList{
+        Lparen:   145,
+        Rparen:   333,
+        Elements: []*ast.PropertyGraphElement{
+          &ast.PropertyGraphElement{
+            Name: &ast.Ident{
+              NamePos: 151,
+              NameEnd: 160,
+              Name:    "GraphEdge",
+            },
+            Keys: &ast.PropertyGraphEdgeElementKeys{
+              Source: &ast.PropertyGraphSourceKey{
+                Source: 167,
+                Keys:   &ast.PropertyGraphColumnNameList{
+                  Lparen:         178,
+                  Rparen:         181,
+                  ColumnNameList: []*ast.Ident{
+                    &ast.Ident{
+                      NamePos: 179,
+                      NameEnd: 181,
+                      Name:    "id",
+                    },
+                  },
+                },
+                ElementReference: &ast.Ident{
+                  NamePos: 194,
+                  NameEnd: 203,
+                  Name:    "GraphNode",
+                },
+                ReferenceColumns: &ast.PropertyGraphColumnNameList{
+                  Lparen:         203,
+                  Rparen:         206,
+                  ColumnNameList: []*ast.Ident{
+                    &ast.Ident{
+                      NamePos: 204,
+                      NameEnd: 206,
+                      Name:    "id",
+                    },
+                  },
+                },
+              },
+              Destination: &ast.PropertyGraphDestinationKey{
+                Destination: 214,
+                Keys:        &ast.PropertyGraphColumnNameList{
+                  Lparen:         230,
+                  Rparen:         238,
+                  ColumnNameList: []*ast.Ident{
+                    &ast.Ident{
+                      NamePos: 231,
+                      NameEnd: 238,
+                      Name:    "dest_id",
+                    },
+                  },
+                },
+                ElementReference: &ast.Ident{
+                  NamePos: 251,
+                  NameEnd: 260,
+                  Name:    "GraphNode",
+                },
+                ReferenceColumns: &ast.PropertyGraphColumnNameList{
+                  Lparen:         260,
+                  Rparen:         263,
+                  ColumnNameList: []*ast.Ident{
+                    &ast.Ident{
+                      NamePos: 261,
+                      NameEnd: 263,
+                      Name:    "id",
+                    },
+                  },
+                },
+              },
+            },
+            DynamicLabel: &ast.PropertyGraphDynamicLabel{
+              Dynamic:    271,
+              Rparen:     291,
+              ColumnName: &ast.Ident{
+                NamePos: 286,
+                NameEnd: 291,
+                Name:    "label",
+              },
+            },
+            DynamicProperties: &ast.PropertyGraphDynamicProperties{
+              Dynamic:    299,
+              Rparen:     329,
+              ColumnName: &ast.Ident{
+                NamePos: 319,
+                NameEnd: 329,
+                Name:    "properties",
+              },
+            },
+          },
+        },
+      },
+    },
+  },
+}
+
+--- SQL
+CREATE PROPERTY GRAPH FinGraph NODE TABLES (GraphNode DYNAMIC LABEL (label) DYNAMIC PROPERTIES (properties)) EDGE TABLES (GraphEdge SOURCE KEY (id) REFERENCES GraphNode (id) DESTINATION KEY (dest_id) REFERENCES GraphNode (id) DYNAMIC LABEL (label) DYNAMIC PROPERTIES (properties))
diff --git a/testdata/result/statement/select_expr.sql.txt b/testdata/result/statement/select_expr.sql.txt
index 392a6cc..6108393 100644
--- a/testdata/result/statement/select_expr.sql.txt
+++ b/testdata/result/statement/select_expr.sql.txt
@@ -600,18 +600,17 @@ select 1 + 2, 1 - 2,
                 },
               },
             },
-            &ast.IntervalArg{
-              Interval: 542,
-              Expr:     &ast.IntLiteral{
-                ValuePos: 551,
-                ValueEnd: 552,
-                Base:     10,
-                Value:    "5",
-              },
-              Unit: &ast.Ident{
-                NamePos: 553,
-                NameEnd: 556,
-                Name:    "day",
+            &ast.ExprArg{
+              Expr: &ast.IntervalLiteralSingle{
+                Interval:        542,
+                DateTimePartEnd: 556,
+                Value:           &ast.IntLiteral{
+                  ValuePos: 551,
+                  ValueEnd: 552,
+                  Base:     10,
+                  Value:    "5",
+                },
+                DateTimePart: "DAY",
               },
             },
           },
@@ -640,18 +639,17 @@ select 1 + 2, 1 - 2,
                 },
               },
             },
-            &ast.IntervalArg{
-              Interval: 613,
-              Expr:     &ast.IntLiteral{
-                ValuePos: 622,
-                ValueEnd: 623,
-                Base:     10,
-                Value:    "5",
-              },
-              Unit: &ast.Ident{
-                NamePos: 624,
-                NameEnd: 628,
-                Name:    "hour",
+            &ast.ExprArg{
+              Expr: &ast.IntervalLiteralSingle{
+                Interval:        613,
+                DateTimePartEnd: 628,
+                Value:           &ast.IntLiteral{
+                  ValuePos: 622,
+                  ValueEnd: 623,
+                  Base:     10,
+                  Value:    "5",
+                },
+                DateTimePart: "HOUR",
               },
             },
           },
@@ -875,4 +873,4 @@ select 1 + 2, 1 - 2,
 }
 
 --- SQL
-SELECT 1 + 2, 1 - 2, 1 * 2, 2 / 2, +1 + +1, -1 + -1, +1.2, -3.4, ~1 ^ ~1, 1 ^ 2, 2 & 1, 2 | 1, 1 << 2, 2 >> 1, foo.bar * +foo.bar * -foo.bar, (SELECT 1 `1`).`1`, NOT NOT TRUE, [1, 2, 3][OFFSET(1)], [1, 2, 3][OFFSET(1)], [1, 2, 3][ORDINAL(1)], CASE WHEN 1 = 1 THEN "1 = 1" ELSE "else" END, CASE 1 WHEN 1 THEN "1" WHEN 2 THEN "2" ELSE "other" END, date_add(DATE "2019-09-01", INTERVAL 5 day), timestamp_add(TIMESTAMP "2019-09-01 08:11:22", INTERVAL 5 hour), 1 IN (1, 2, 3), 2 IN UNNEST([1, 2, 3]), 3 IN (SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3), [1] || [2], IF(1 > 1, 1, 2) + 1 AS result
+SELECT 1 + 2, 1 - 2, 1 * 2, 2 / 2, +1 + +1, -1 + -1, +1.2, -3.4, ~1 ^ ~1, 1 ^ 2, 2 & 1, 2 | 1, 1 << 2, 2 >> 1, foo.bar * +foo.bar * -foo.bar, (SELECT 1 `1`).`1`, NOT NOT TRUE, [1, 2, 3][OFFSET(1)], [1, 2, 3][OFFSET(1)], [1, 2, 3][ORDINAL(1)], CASE WHEN 1 = 1 THEN "1 = 1" ELSE "else" END, CASE 1 WHEN 1 THEN "1" WHEN 2 THEN "2" ELSE "other" END, date_add(DATE "2019-09-01", INTERVAL 5 DAY), timestamp_add(TIMESTAMP "2019-09-01 08:11:22", INTERVAL 5 HOUR), 1 IN (1, 2, 3), 2 IN UNNEST([1, 2, 3]), 3 IN (SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3), [1] || [2], IF(1 > 1, 1, 2) + 1 AS result
diff --git a/testdata/result/statement/select_interval_values.sql.txt b/testdata/result/statement/select_interval_values.sql.txt
new file mode 100644
index 0000000..cc4705e
--- /dev/null
+++ b/testdata/result/statement/select_interval_values.sql.txt
@@ -0,0 +1,579 @@
+--- select_interval_values.sql
+SELECT
+  -- Single datetime part
+  INTERVAL 1 YEAR,
+  INTERVAL -5 DAY,
+  INTERVAL 90 SECOND,
+  INTERVAL 1 QUARTER,
+  INTERVAL 6 WEEK,
+  INTERVAL 25 HOUR,
+  INTERVAL 1500 MINUTE,
+  INTERVAL 90000 SECOND,
+  INTERVAL 90 MINUTE,
+  INTERVAL -25 MONTH,
+  INTERVAL -90 MINUTE,
+  INTERVAL @param YEAR,
+
+  -- Datetime part range
+  INTERVAL '2-11' YEAR TO MONTH,
+  INTERVAL '2-11 28' YEAR TO DAY,
+  INTERVAL '2-11 28 16' YEAR TO HOUR,
+  INTERVAL '2-11 28 16:15' YEAR TO MINUTE,
+  INTERVAL '2-11 28 16:15:14' YEAR TO SECOND,
+  INTERVAL '11 28' MONTH TO DAY,
+  INTERVAL '11 28 16' MONTH TO HOUR,
+  INTERVAL '11 28 16:15' MONTH TO MINUTE,
+  INTERVAL '11 28 16:15:14' MONTH TO SECOND,
+  INTERVAL '28 16' DAY TO HOUR,
+  INTERVAL '28 16:15' DAY TO MINUTE,
+  INTERVAL '28 16:15:14' DAY TO SECOND,
+  INTERVAL '16:15' HOUR TO MINUTE,
+  INTERVAL '16:15:14' HOUR TO SECOND,
+  INTERVAL '15:14' MINUTE TO SECOND,
+  INTERVAL '10:20:30.52' HOUR TO SECOND,
+  INTERVAL '1-2' YEAR TO MONTH,
+  INTERVAL '1 -15' MONTH TO DAY,
+  INTERVAL '1 5:30' DAY TO MINUTE,
+  INTERVAL '-23-2 10 -12:30' YEAR TO MINUTE,
+  INTERVAL '-0-2 10 0:30' MONTH TO MINUTE,
+  INTERVAL '-30:10' MINUTE TO SECOND,
+
+  -- INTERVAL as typename
+  CAST("P1D" AS INTERVAL),
+  ARRAY<INTERVAL>[],
+  ARRAY<INTERVAL>[INTERVAL 1 DAY],
+  STRUCT<value INTERVAL>(INTERVAL 1 DAY),
+
+
+--- AST
+&ast.QueryStatement{
+  Query: &ast.Select{
+    Results: []ast.SelectItem{
+      &ast.ExprSelectItem{
+        Expr: &ast.IntervalLiteralSingle{
+          Interval:        35,
+          DateTimePartEnd: 50,
+          Value:           &ast.IntLiteral{
+            ValuePos: 44,
+            ValueEnd: 45,
+            Base:     10,
+            Value:    "1",
+          },
+          DateTimePart: "YEAR",
+        },
+      },
+      &ast.ExprSelectItem{
+        Expr: &ast.IntervalLiteralSingle{
+          Interval:        54,
+          DateTimePartEnd: 69,
+          Value:           &ast.IntLiteral{
+            ValuePos: 63,
+            ValueEnd: 65,
+            Base:     10,
+            Value:    "-5",
+          },
+          DateTimePart: "DAY",
+        },
+      },
+      &ast.ExprSelectItem{
+        Expr: &ast.IntervalLiteralSingle{
+          Interval:        73,
+          DateTimePartEnd: 91,
+          Value:           &ast.IntLiteral{
+            ValuePos: 82,
+            ValueEnd: 84,
+            Base:     10,
+            Value:    "90",
+          },
+          DateTimePart: "SECOND",
+        },
+      },
+      &ast.ExprSelectItem{
+        Expr: &ast.IntervalLiteralSingle{
+          Interval:        95,
+          DateTimePartEnd: 113,
+          Value:           &ast.IntLiteral{
+            ValuePos: 104,
+            ValueEnd: 105,
+            Base:     10,
+            Value:    "1",
+          },
+          DateTimePart: "QUARTER",
+        },
+      },
+      &ast.ExprSelectItem{
+        Expr: &ast.IntervalLiteralSingle{
+          Interval:        117,
+          DateTimePartEnd: 132,
+          Value:           &ast.IntLiteral{
+            ValuePos: 126,
+            ValueEnd: 127,
+            Base:     10,
+            Value:    "6",
+          },
+          DateTimePart: "WEEK",
+        },
+      },
+      &ast.ExprSelectItem{
+        Expr: &ast.IntervalLiteralSingle{
+          Interval:        136,
+          DateTimePartEnd: 152,
+          Value:           &ast.IntLiteral{
+            ValuePos: 145,
+            ValueEnd: 147,
+            Base:     10,
+            Value:    "25",
+          },
+          DateTimePart: "HOUR",
+        },
+      },
+      &ast.ExprSelectItem{
+        Expr: &ast.IntervalLiteralSingle{
+          Interval:        156,
+          DateTimePartEnd: 176,
+          Value:           &ast.IntLiteral{
+            ValuePos: 165,
+            ValueEnd: 169,
+            Base:     10,
+            Value:    "1500",
+          },
+          DateTimePart: "MINUTE",
+        },
+      },
+      &ast.ExprSelectItem{
+        Expr: &ast.IntervalLiteralSingle{
+          Interval:        180,
+          DateTimePartEnd: 201,
+          Value:           &ast.IntLiteral{
+            ValuePos: 189,
+            ValueEnd: 194,
+            Base:     10,
+            Value:    "90000",
+          },
+          DateTimePart: "SECOND",
+        },
+      },
+      &ast.ExprSelectItem{
+        Expr: &ast.IntervalLiteralSingle{
+          Interval:        205,
+          DateTimePartEnd: 223,
+          Value:           &ast.IntLiteral{
+            ValuePos: 214,
+            ValueEnd: 216,
+            Base:     10,
+            Value:    "90",
+          },
+          DateTimePart: "MINUTE",
+        },
+      },
+      &ast.ExprSelectItem{
+        Expr: &ast.IntervalLiteralSingle{
+          Interval:        227,
+          DateTimePartEnd: 245,
+          Value:           &ast.IntLiteral{
+            ValuePos: 236,
+            ValueEnd: 239,
+            Base:     10,
+            Value:    "-25",
+          },
+          DateTimePart: "MONTH",
+        },
+      },
+      &ast.ExprSelectItem{
+        Expr: &ast.IntervalLiteralSingle{
+          Interval:        249,
+          DateTimePartEnd: 268,
+          Value:           &ast.IntLiteral{
+            ValuePos: 258,
+            ValueEnd: 261,
+            Base:     10,
+            Value:    "-90",
+          },
+          DateTimePart: "MINUTE",
+        },
+      },
+      &ast.ExprSelectItem{
+        Expr: &ast.IntervalLiteralSingle{
+          Interval:        272,
+          DateTimePartEnd: 292,
+          Value:           &ast.Param{
+            Atmark: 281,
+            Name:   "param",
+          },
+          DateTimePart: "YEAR",
+        },
+      },
+      &ast.ExprSelectItem{
+        Expr: &ast.IntervalLiteralRange{
+          Interval:              322,
+          EndingDateTimePartEnd: 351,
+          Value:                 &ast.StringLiteral{
+            ValuePos: 331,
+            ValueEnd: 337,
+            Value:    "2-11",
+          },
+          StartingDateTimePart: "YEAR",
+          EndingDateTimePart:   "MONTH",
+        },
+      },
+      &ast.ExprSelectItem{
+        Expr: &ast.IntervalLiteralRange{
+          Interval:              355,
+          EndingDateTimePartEnd: 385,
+          Value:                 &ast.StringLiteral{
+            ValuePos: 364,
+            ValueEnd: 373,
+            Value:    "2-11 28",
+          },
+          StartingDateTimePart: "YEAR",
+          EndingDateTimePart:   "DAY",
+        },
+      },
+      &ast.ExprSelectItem{
+        Expr: &ast.IntervalLiteralRange{
+          Interval:              389,
+          EndingDateTimePartEnd: 423,
+          Value:                 &ast.StringLiteral{
+            ValuePos: 398,
+            ValueEnd: 410,
+            Value:    "2-11 28 16",
+          },
+          StartingDateTimePart: "YEAR",
+          EndingDateTimePart:   "HOUR",
+        },
+      },
+      &ast.ExprSelectItem{
+        Expr: &ast.IntervalLiteralRange{
+          Interval:              427,
+          EndingDateTimePartEnd: 466,
+          Value:                 &ast.StringLiteral{
+            ValuePos: 436,
+            ValueEnd: 451,
+            Value:    "2-11 28 16:15",
+          },
+          StartingDateTimePart: "YEAR",
+          EndingDateTimePart:   "MINUTE",
+        },
+      },
+      &ast.ExprSelectItem{
+        Expr: &ast.IntervalLiteralRange{
+          Interval:              470,
+          EndingDateTimePartEnd: 512,
+          Value:                 &ast.StringLiteral{
+            ValuePos: 479,
+            ValueEnd: 497,
+            Value:    "2-11 28 16:15:14",
+          },
+          StartingDateTimePart: "YEAR",
+          EndingDateTimePart:   "SECOND",
+        },
+      },
+      &ast.ExprSelectItem{
+        Expr: &ast.IntervalLiteralRange{
+          Interval:              516,
+          EndingDateTimePartEnd: 545,
+          Value:                 &ast.StringLiteral{
+            ValuePos: 525,
+            ValueEnd: 532,
+            Value:    "11 28",
+          },
+          StartingDateTimePart: "MONTH",
+          EndingDateTimePart:   "DAY",
+        },
+      },
+      &ast.ExprSelectItem{
+        Expr: &ast.IntervalLiteralRange{
+          Interval:              549,
+          EndingDateTimePartEnd: 582,
+          Value:                 &ast.StringLiteral{
+            ValuePos: 558,
+            ValueEnd: 568,
+            Value:    "11 28 16",
+          },
+          StartingDateTimePart: "MONTH",
+          EndingDateTimePart:   "HOUR",
+        },
+      },
+      &ast.ExprSelectItem{
+        Expr: &ast.IntervalLiteralRange{
+          Interval:              586,
+          EndingDateTimePartEnd: 624,
+          Value:                 &ast.StringLiteral{
+            ValuePos: 595,
+            ValueEnd: 608,
+            Value:    "11 28 16:15",
+          },
+          StartingDateTimePart: "MONTH",
+          EndingDateTimePart:   "MINUTE",
+        },
+      },
+      &ast.ExprSelectItem{
+        Expr: &ast.IntervalLiteralRange{
+          Interval:              628,
+          EndingDateTimePartEnd: 669,
+          Value:                 &ast.StringLiteral{
+            ValuePos: 637,
+            ValueEnd: 653,
+            Value:    "11 28 16:15:14",
+          },
+          StartingDateTimePart: "MONTH",
+          EndingDateTimePart:   "SECOND",
+        },
+      },
+      &ast.ExprSelectItem{
+        Expr: &ast.IntervalLiteralRange{
+          Interval:              673,
+          EndingDateTimePartEnd: 701,
+          Value:                 &ast.StringLiteral{
+            ValuePos: 682,
+            ValueEnd: 689,
+            Value:    "28 16",
+          },
+          StartingDateTimePart: "DAY",
+          EndingDateTimePart:   "HOUR",
+        },
+      },
+      &ast.ExprSelectItem{
+        Expr: &ast.IntervalLiteralRange{
+          Interval:              705,
+          EndingDateTimePartEnd: 738,
+          Value:                 &ast.StringLiteral{
+            ValuePos: 714,
+            ValueEnd: 724,
+            Value:    "28 16:15",
+          },
+          StartingDateTimePart: "DAY",
+          EndingDateTimePart:   "MINUTE",
+        },
+      },
+      &ast.ExprSelectItem{
+        Expr: &ast.IntervalLiteralRange{
+          Interval:              742,
+          EndingDateTimePartEnd: 778,
+          Value:                 &ast.StringLiteral{
+            ValuePos: 751,
+            ValueEnd: 764,
+            Value:    "28 16:15:14",
+          },
+          StartingDateTimePart: "DAY",
+          EndingDateTimePart:   "SECOND",
+        },
+      },
+      &ast.ExprSelectItem{
+        Expr: &ast.IntervalLiteralRange{
+          Interval:              782,
+          EndingDateTimePartEnd: 813,
+          Value:                 &ast.StringLiteral{
+            ValuePos: 791,
+            ValueEnd: 798,
+            Value:    "16:15",
+          },
+          StartingDateTimePart: "HOUR",
+          EndingDateTimePart:   "MINUTE",
+        },
+      },
+      &ast.ExprSelectItem{
+        Expr: &ast.IntervalLiteralRange{
+          Interval:              817,
+          EndingDateTimePartEnd: 851,
+          Value:                 &ast.StringLiteral{
+            ValuePos: 826,
+            ValueEnd: 836,
+            Value:    "16:15:14",
+          },
+          StartingDateTimePart: "HOUR",
+          EndingDateTimePart:   "SECOND",
+        },
+      },
+      &ast.ExprSelectItem{
+        Expr: &ast.IntervalLiteralRange{
+          Interval:              855,
+          EndingDateTimePartEnd: 888,
+          Value:                 &ast.StringLiteral{
+            ValuePos: 864,
+            ValueEnd: 871,
+            Value:    "15:14",
+          },
+          StartingDateTimePart: "MINUTE",
+          EndingDateTimePart:   "SECOND",
+        },
+      },
+      &ast.ExprSelectItem{
+        Expr: &ast.IntervalLiteralRange{
+          Interval:              892,
+          EndingDateTimePartEnd: 929,
+          Value:                 &ast.StringLiteral{
+            ValuePos: 901,
+            ValueEnd: 914,
+            Value:    "10:20:30.52",
+          },
+          StartingDateTimePart: "HOUR",
+          EndingDateTimePart:   "SECOND",
+        },
+      },
+      &ast.ExprSelectItem{
+        Expr: &ast.IntervalLiteralRange{
+          Interval:              933,
+          EndingDateTimePartEnd: 961,
+          Value:                 &ast.StringLiteral{
+            ValuePos: 942,
+            ValueEnd: 947,
+            Value:    "1-2",
+          },
+          StartingDateTimePart: "YEAR",
+          EndingDateTimePart:   "MONTH",
+        },
+      },
+      &ast.ExprSelectItem{
+        Expr: &ast.IntervalLiteralRange{
+          Interval:              965,
+          EndingDateTimePartEnd: 994,
+          Value:                 &ast.StringLiteral{
+            ValuePos: 974,
+            ValueEnd: 981,
+            Value:    "1 -15",
+          },
+          StartingDateTimePart: "MONTH",
+          EndingDateTimePart:   "DAY",
+        },
+      },
+      &ast.ExprSelectItem{
+        Expr: &ast.IntervalLiteralRange{
+          Interval:              998,
+          EndingDateTimePartEnd: 1029,
+          Value:                 &ast.StringLiteral{
+            ValuePos: 1007,
+            ValueEnd: 1015,
+            Value:    "1 5:30",
+          },
+          StartingDateTimePart: "DAY",
+          EndingDateTimePart:   "MINUTE",
+        },
+      },
+      &ast.ExprSelectItem{
+        Expr: &ast.IntervalLiteralRange{
+          Interval:              1033,
+          EndingDateTimePartEnd: 1074,
+          Value:                 &ast.StringLiteral{
+            ValuePos: 1042,
+            ValueEnd: 1059,
+            Value:    "-23-2 10 -12:30",
+          },
+          StartingDateTimePart: "YEAR",
+          EndingDateTimePart:   "MINUTE",
+        },
+      },
+      &ast.ExprSelectItem{
+        Expr: &ast.IntervalLiteralRange{
+          Interval:              1078,
+          EndingDateTimePartEnd: 1117,
+          Value:                 &ast.StringLiteral{
+            ValuePos: 1087,
+            ValueEnd: 1101,
+            Value:    "-0-2 10 0:30",
+          },
+          StartingDateTimePart: "MONTH",
+          EndingDateTimePart:   "MINUTE",
+        },
+      },
+      &ast.ExprSelectItem{
+        Expr: &ast.IntervalLiteralRange{
+          Interval:              1121,
+          EndingDateTimePartEnd: 1155,
+          Value:                 &ast.StringLiteral{
+            ValuePos: 1130,
+            ValueEnd: 1138,
+            Value:    "-30:10",
+          },
+          StartingDateTimePart: "MINUTE",
+          EndingDateTimePart:   "SECOND",
+        },
+      },
+      &ast.ExprSelectItem{
+        Expr: &ast.CastExpr{
+          Cast:   1186,
+          Rparen: 1208,
+          Expr:   &ast.StringLiteral{
+            ValuePos: 1191,
+            ValueEnd: 1196,
+            Value:    "P1D",
+          },
+          Type: &ast.SimpleType{
+            NamePos: 1200,
+            Name:    "INTERVAL",
+          },
+        },
+      },
+      &ast.ExprSelectItem{
+        Expr: &ast.ArrayLiteral{
+          Array:  1213,
+          Lbrack: 1228,
+          Rbrack: 1229,
+          Type:   &ast.SimpleType{
+            NamePos: 1219,
+            Name:    "INTERVAL",
+          },
+        },
+      },
+      &ast.ExprSelectItem{
+        Expr: &ast.ArrayLiteral{
+          Array:  1234,
+          Lbrack: 1249,
+          Rbrack: 1264,
+          Type:   &ast.SimpleType{
+            NamePos: 1240,
+            Name:    "INTERVAL",
+          },
+          Values: []ast.Expr{
+            &ast.IntervalLiteralSingle{
+              Interval:        1250,
+              DateTimePartEnd: 1264,
+              Value:           &ast.IntLiteral{
+                ValuePos: 1259,
+                ValueEnd: 1260,
+                Base:     10,
+                Value:    "1",
+              },
+              DateTimePart: "DAY",
+            },
+          },
+        },
+      },
+      &ast.ExprSelectItem{
+        Expr: &ast.TypedStructLiteral{
+          Struct: 1269,
+          Rparen: 1306,
+          Fields: []*ast.StructField{
+            &ast.StructField{
+              Ident: &ast.Ident{
+                NamePos: 1276,
+                NameEnd: 1281,
+                Name:    "value",
+              },
+              Type: &ast.SimpleType{
+                NamePos: 1282,
+                Name:    "INTERVAL",
+              },
+            },
+          },
+          Values: []ast.Expr{
+            &ast.IntervalLiteralSingle{
+              Interval:        1292,
+              DateTimePartEnd: 1306,
+              Value:           &ast.IntLiteral{
+                ValuePos: 1301,
+                ValueEnd: 1302,
+                Base:     10,
+                Value:    "1",
+              },
+              DateTimePart: "DAY",
+            },
+          },
+        },
+      },
+    },
+  },
+}
+
+--- SQL
+SELECT INTERVAL 1 YEAR, INTERVAL -5 DAY, INTERVAL 90 SECOND, INTERVAL 1 QUARTER, INTERVAL 6 WEEK, INTERVAL 25 HOUR, INTERVAL 1500 MINUTE, INTERVAL 90000 SECOND, INTERVAL 90 MINUTE, INTERVAL -25 MONTH, INTERVAL -90 MINUTE, INTERVAL @param YEAR, INTERVAL "2-11" YEAR TO MONTH, INTERVAL "2-11 28" YEAR TO DAY, INTERVAL "2-11 28 16" YEAR TO HOUR, INTERVAL "2-11 28 16:15" YEAR TO MINUTE, INTERVAL "2-11 28 16:15:14" YEAR TO SECOND, INTERVAL "11 28" MONTH TO DAY, INTERVAL "11 28 16" MONTH TO HOUR, INTERVAL "11 28 16:15" MONTH TO MINUTE, INTERVAL "11 28 16:15:14" MONTH TO SECOND, INTERVAL "28 16" DAY TO HOUR, INTERVAL "28 16:15" DAY TO MINUTE, INTERVAL "28 16:15:14" DAY TO SECOND, INTERVAL "16:15" HOUR TO MINUTE, INTERVAL "16:15:14" HOUR TO SECOND, INTERVAL "15:14" MINUTE TO SECOND, INTERVAL "10:20:30.52" HOUR TO SECOND, INTERVAL "1-2" YEAR TO MONTH, INTERVAL "1 -15" MONTH TO DAY, INTERVAL "1 5:30" DAY TO MINUTE, INTERVAL "-23-2 10 -12:30" YEAR TO MINUTE, INTERVAL "-0-2 10 0:30" MONTH TO MINUTE, INTERVAL "-30:10" MINUTE TO SECOND, CAST("P1D" AS INTERVAL), ARRAY<INTERVAL>[], ARRAY<INTERVAL>[INTERVAL 1 DAY], STRUCT<value INTERVAL>(INTERVAL 1 DAY)