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

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 33 additions & 0 deletions parser/ast.go
Original file line number Diff line number Diff line change
Expand Up @@ -3446,6 +3446,39 @@ func (s *TypeWithParams) Type() string {
return s.Name.Name
}

type TypeWithNamedParams struct {
LeftParenPos Pos
RightParenPos Pos
Name *Ident
Params []*NamedParameterExpr
}

func (s *TypeWithNamedParams) Pos() Pos {
return s.Name.NamePos
}

func (s *TypeWithNamedParams) End() Pos {
return s.RightParenPos
}

func (s *TypeWithNamedParams) Accept(visitor ASTVisitor) error {
visitor.Enter(s)
defer visitor.Leave(s)
if err := s.Name.Accept(visitor); err != nil {
return err
}
for _, param := range s.Params {
if err := param.Accept(visitor); err != nil {
return err
}
}
return visitor.VisitTypeWithNamedParams(s)
}

func (s *TypeWithNamedParams) Type() string {
return s.Name.Name
}

type ComplexType struct {
LeftParenPos Pos
RightParenPos Pos
Expand Down
8 changes: 8 additions & 0 deletions parser/ast_visitor.go
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,7 @@ type ASTVisitor interface {
VisitJSONType(expr *JSONType) error
VisitPropertyType(expr *PropertyType) error
VisitTypeWithParams(expr *TypeWithParams) error
VisitTypeWithNamedParams(expr *TypeWithNamedParams) error
VisitComplexType(expr *ComplexType) error
VisitNestedType(expr *NestedType) error
VisitCompressionCodec(expr *CompressionCodec) error
Expand Down Expand Up @@ -901,6 +902,13 @@ func (v *DefaultASTVisitor) VisitTypeWithParams(expr *TypeWithParams) error {
return nil
}

func (v *DefaultASTVisitor) VisitTypeWithNamedParams(expr *TypeWithNamedParams) error {
if v.Visit != nil {
return v.Visit(expr)
}
return nil
}

func (v *DefaultASTVisitor) VisitComplexType(expr *ComplexType) error {
if v.Visit != nil {
return v.Visit(expr)
Expand Down
12 changes: 12 additions & 0 deletions parser/format.go
Original file line number Diff line number Diff line change
Expand Up @@ -2769,6 +2769,18 @@ func (s *TypeWithParams) FormatSQL(formatter *Formatter) {
formatter.WriteByte(')')
}

func (s *TypeWithNamedParams) FormatSQL(formatter *Formatter) {
formatter.WriteExpr(s.Name)
formatter.WriteByte('(')
for i, param := range s.Params {
if i > 0 {
formatter.WriteString(", ")
}
formatter.WriteExpr(param)
}
formatter.WriteByte(')')
}

func (t *TypedPlaceholder) FormatSQL(formatter *Formatter) {
formatter.WriteString("{")
formatter.WriteExpr(t.Name)
Expand Down
51 changes: 51 additions & 0 deletions parser/parser_column.go
Original file line number Diff line number Diff line change
Expand Up @@ -1323,9 +1323,16 @@ func (p *Parser) parseColumnTypeArgs(ident *Ident) (ColumnType, error) { // noli
return p.parseColumnTypeWithParams(ident, p.Pos())
case strings.EqualFold(ident.Name, "Tuple"):
return p.parseNestedType(ident, p.Pos())
case p.matchNamedTypeParam():
return p.parseColumnTypeWithNamedParams(ident, lParen.Pos)
default:
return p.parseComplexType(ident, p.Pos())
}
case p.matchTokenKind(TokenKindKeyword):
if p.matchNamedTypeParam() {
return p.parseColumnTypeWithNamedParams(ident, lParen.Pos)
}
return nil, fmt.Errorf("unexpected token kind: %v", p.currentTokenKind())
case p.matchTokenKind(TokenKindString):
if peekToken, err := p.lexer.peekToken(); err == nil && peekToken.Kind == TokenKindSingleEQ {
// enum values
Expand Down Expand Up @@ -1440,6 +1447,50 @@ func (p *Parser) parseColumnTypeWithParams(name *Ident, pos Pos) (*TypeWithParam
}, nil
}

func (p *Parser) matchNamedTypeParam() bool {
if !p.matchTokenKind(TokenKindIdent, TokenKindKeyword) {
return false
}
peekToken, err := p.lexer.peekToken()
return err == nil && peekToken != nil && peekToken.Kind == TokenKindSingleEQ
}

func (p *Parser) parseColumnTypeWithNamedParams(name *Ident, leftParenPos Pos) (*TypeWithNamedParams, error) {
params := make([]*NamedParameterExpr, 0)
for !p.lexer.isEOF() {
paramName, err := p.parseAnyKeyword()
if err != nil {
return nil, err
}
if err := p.expectTokenKind(TokenKindSingleEQ); err != nil {
return nil, err
}
value, err := p.parseLiteral(p.Pos())
if err != nil {
return nil, err
}
params = append(params, &NamedParameterExpr{
NamePos: paramName.NamePos,
Name: paramName,
Value: value,
})
if p.tryConsumeTokenKind(TokenKindComma) == nil {
break
}
}

rightParenPos := p.Pos()
if err := p.expectTokenKind(TokenKindRParen); err != nil {
return nil, err
}
return &TypeWithNamedParams{
Name: name,
LeftParenPos: leftParenPos,
RightParenPos: rightParenPos,
Params: params,
}, nil
}

func (p *Parser) parseJSONPath() (*JSONPath, error) {
idents := make([]*Ident, 0)
ident, err := p.parseIdent()
Expand Down
6 changes: 6 additions & 0 deletions parser/testdata/ddl/create_table_dynamic_type.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
CREATE TABLE t
(
`value_1` Dynamic(max_types = 16),
`value_2` Dynamic(max_types = 16)
)
ENGINE = Memory;
16 changes: 16 additions & 0 deletions parser/testdata/ddl/format/beautify/create_table_dynamic_type.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
-- Origin SQL:
CREATE TABLE t
(
`value_1` Dynamic(max_types = 16),
`value_2` Dynamic(max_types = 16)
)
ENGINE = Memory;


-- Beautify SQL:
CREATE TABLE t
(
`value_1` Dynamic(max_types=16),
`value_2` Dynamic(max_types=16)
)
ENGINE = Memory;
11 changes: 11 additions & 0 deletions parser/testdata/ddl/format/create_table_dynamic_type.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
-- Origin SQL:
CREATE TABLE t
(
`value_1` Dynamic(max_types = 16),
`value_2` Dynamic(max_types = 16)
)
ENGINE = Memory;


-- Format SQL:
CREATE TABLE t (`value_1` Dynamic(max_types=16), `value_2` Dynamic(max_types=16)) ENGINE = Memory;
141 changes: 141 additions & 0 deletions parser/testdata/ddl/output/create_table_dynamic_type.sql.golden.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,141 @@
[
{
"CreatePos": 0,
"StatementEnd": 111,
"OrReplace": false,
"Name": {
"Database": null,
"Table": {
"Name": "t",
"QuoteType": 1,
"NamePos": 13,
"NameEnd": 14
}
},
"IfNotExists": false,
"UUID": null,
"OnCluster": null,
"TableSchema": {
"SchemaPos": 15,
"SchemaEnd": 94,
"Columns": [
{
"NamePos": 22,
"ColumnEnd": 53,
"Name": {
"Ident": {
"Name": "value_1",
"QuoteType": 3,
"NamePos": 22,
"NameEnd": 29
},
"DotIdent": null
},
"Type": {
"LeftParenPos": 38,
"RightParenPos": 53,
"Name": {
"Name": "Dynamic",
"QuoteType": 1,
"NamePos": 31,
"NameEnd": 38
},
"Params": [
{
"NamePos": 39,
"Name": {
"Name": "max_types",
"QuoteType": 1,
"NamePos": 39,
"NameEnd": 48
},
"Value": {
"NumPos": 51,
"NumEnd": 53,
"Literal": "16",
"Base": 10
}
}
]
},
"NotNull": null,
"Nullable": null,
"DefaultExpr": null,
"MaterializedExpr": null,
"AliasExpr": null,
"Codec": null,
"TTL": null,
"Comment": null,
"CompressionCodec": null
},
{
"NamePos": 61,
"ColumnEnd": 92,
"Name": {
"Ident": {
"Name": "value_2",
"QuoteType": 3,
"NamePos": 61,
"NameEnd": 68
},
"DotIdent": null
},
"Type": {
"LeftParenPos": 77,
"RightParenPos": 92,
"Name": {
"Name": "Dynamic",
"QuoteType": 1,
"NamePos": 70,
"NameEnd": 77
},
"Params": [
{
"NamePos": 78,
"Name": {
"Name": "max_types",
"QuoteType": 1,
"NamePos": 78,
"NameEnd": 87
},
"Value": {
"NumPos": 90,
"NumEnd": 92,
"Literal": "16",
"Base": 10
}
}
]
},
"NotNull": null,
"Nullable": null,
"DefaultExpr": null,
"MaterializedExpr": null,
"AliasExpr": null,
"Codec": null,
"TTL": null,
"Comment": null,
"CompressionCodec": null
}
],
"AliasTable": null,
"TableFunction": null
},
"Engine": {
"EnginePos": 96,
"EngineEnd": 111,
"Name": "Memory",
"Params": null,
"PrimaryKey": null,
"PartitionBy": null,
"SampleBy": null,
"TTL": null,
"Settings": null,
"OrderBy": null
},
"SubQuery": null,
"TableFunction": null,
"HasTemporary": false,
"Comment": null
}
]
9 changes: 9 additions & 0 deletions parser/walk.go
Original file line number Diff line number Diff line change
Expand Up @@ -1099,6 +1099,15 @@ func Walk(node Expr, fn WalkFunc) bool {
return false
}
}
case *TypeWithNamedParams:
if !Walk(n.Name, fn) {
return false
}
for _, param := range n.Params {
if !Walk(param, fn) {
return false
}
}
case *ComplexType:
if !Walk(n.Name, fn) {
return false
Expand Down
Loading