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
40 changes: 28 additions & 12 deletions parser/column_modifiers_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,11 @@ func TestParser_ColumnModifierOrder(t *testing.T) {
{"ttl", "comment", "codec"},
{"ttl", "codec", "comment"},
}
forms := []struct{ name, query string }{
{"create", "CREATE TABLE db.example (event_time DateTime, %s) ENGINE = MergeTree ORDER BY event_time"},
{"add", "ALTER TABLE db.example ADD COLUMN %s"},
{"modify", "ALTER TABLE db.example MODIFY COLUMN %s"},
forms := []struct{ name, query, columnType string }{
{"create", "CREATE TABLE db.example (event_time DateTime, %s) ENGINE = MergeTree ORDER BY event_time", "String"},
{"add", "ALTER TABLE db.example ADD COLUMN %s", "String"},
{"modify", "ALTER TABLE db.example MODIFY COLUMN %s", "String"},
{"modify without type", "ALTER TABLE db.example MODIFY COLUMN %s", ""},
}
for _, form := range forms {
for _, order := range orders {
Expand All @@ -34,17 +35,22 @@ func TestParser_ColumnModifierOrder(t *testing.T) {
for _, name := range order {
clauses = append(clauses, modifiers[name])
}
declaration := "value String " + strings.Join(clauses, " ")
nameAndType := strings.TrimSpace("value " + form.columnType)
declaration := nameAndType + " " + strings.Join(clauses, " ")
query := fmt.Sprintf(form.query, declaration)
statements, err := NewParser(query).ParseStmts()
require.NoError(t, err)
require.Len(t, statements, 1)
column := modifierTestColumn(t, statements[0])
require.Equal(t, form.columnType, Format(column.Type))
if form.columnType == "" {
require.Nil(t, column.Type)
}
require.NotNil(t, column.Comment)
require.NotNil(t, column.Codec)
require.NotNil(t, column.TTL)
require.Equal(t, Pos(strings.Index(query, declaration)+len(declaration)), column.End())
canonical := "value String COMMENT 'example' CODEC(ZSTD(1)) TTL event_time + INTERVAL 1 DAY"
canonical := nameAndType + " COMMENT 'example' CODEC(ZSTD(1)) TTL event_time + INTERVAL 1 DAY"
require.Equal(t, canonical, Format(column))
for _, beautify := range []bool{false, true} {
formatter := NewFormatter()
Expand All @@ -55,7 +61,13 @@ func TestParser_ColumnModifierOrder(t *testing.T) {
reparsed, err := NewParser(formatter.String()).ParseStmts()
require.NoError(t, err)
require.Len(t, reparsed, 1)
require.Equal(t, canonical, Format(modifierTestColumn(t, reparsed[0])))
reparsedColumn := modifierTestColumn(t, reparsed[0])
require.Equal(t, column.Type == nil, reparsedColumn.Type == nil)
require.Equal(t, form.columnType, Format(reparsedColumn.Type))
require.NotNil(t, reparsedColumn.Comment)
require.NotNil(t, reparsedColumn.Codec)
require.NotNil(t, reparsedColumn.TTL)
require.Equal(t, canonical, Format(reparsedColumn))
}
validFormatSQL(t, Format(statements[0])+";\n")
})
Expand All @@ -76,11 +88,15 @@ func TestParser_InvalidColumnModifiers(t *testing.T) {
{"missing ttl", "TTL", ""},
} {
t.Run(tc.name, func(t *testing.T) {
query := "CREATE TABLE db.example (event_time DateTime, value String " + tc.modifiers + ") ENGINE = MergeTree ORDER BY event_time"
_, err := NewParser(query).ParseStmts()
require.Error(t, err)
if tc.errorText != "" {
require.ErrorContains(t, err, tc.errorText)
for _, query := range []string{
"CREATE TABLE db.example (event_time DateTime, value String " + tc.modifiers + ") ENGINE = MergeTree ORDER BY event_time",
"ALTER TABLE db.example MODIFY COLUMN value " + tc.modifiers,
} {
_, err := NewParser(query).ParseStmts()
require.Error(t, err, query)
if tc.errorText != "" {
require.ErrorContains(t, err, tc.errorText, query)
}
}
})
}
Expand Down
2 changes: 1 addition & 1 deletion parser/parser_table.go
Original file line number Diff line number Diff line change
Expand Up @@ -693,7 +693,7 @@ func (p *Parser) parseTableColumnExpr(pos Pos) (*ColumnDef, error) {
column.Name = name
columnEnd := name.End()

if p.matchTokenKind(TokenKindIdent) && !p.matchKeyword(KeywordRemove) {
if p.matchTokenKind(TokenKindIdent) && !p.matchOneOfKeywords(KeywordRemove, KeywordComment, KeywordCodec, KeywordTtl) {
columnType, err := p.parseColumnType(p.Pos())
if err != nil {
return nil, err
Expand Down
3 changes: 3 additions & 0 deletions parser/testdata/ddl/alter_modify_column_modifiers.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
ALTER TABLE t MODIFY COLUMN x CODEC(LZ4) COMMENT 'example' TTL ts;
ALTER TABLE t MODIFY COLUMN x COMMENT 'example' CODEC(LZ4) TTL ts;
ALTER TABLE t MODIFY COLUMN x CODEC(LZ4) TTL ts COMMENT 'example';
10 changes: 10 additions & 0 deletions parser/testdata/ddl/format/alter_modify_column_modifiers.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
-- Origin SQL:
ALTER TABLE t MODIFY COLUMN x CODEC(LZ4) COMMENT 'example' TTL ts;
ALTER TABLE t MODIFY COLUMN x COMMENT 'example' CODEC(LZ4) TTL ts;
ALTER TABLE t MODIFY COLUMN x CODEC(LZ4) TTL ts COMMENT 'example';


-- Format SQL:
ALTER TABLE t MODIFY COLUMN x COMMENT 'example' CODEC(LZ4) TTL ts;
ALTER TABLE t MODIFY COLUMN x COMMENT 'example' CODEC(LZ4) TTL ts;
ALTER TABLE t MODIFY COLUMN x COMMENT 'example' CODEC(LZ4) TTL ts;
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
-- Origin SQL:
ALTER TABLE t MODIFY COLUMN x CODEC(LZ4) COMMENT 'example' TTL ts;
ALTER TABLE t MODIFY COLUMN x COMMENT 'example' CODEC(LZ4) TTL ts;
ALTER TABLE t MODIFY COLUMN x CODEC(LZ4) TTL ts COMMENT 'example';


-- Beautify SQL:
ALTER TABLE t
MODIFY COLUMN x COMMENT 'example' CODEC(LZ4) TTL ts;
ALTER TABLE t
MODIFY COLUMN x COMMENT 'example' CODEC(LZ4) TTL ts;
ALTER TABLE t
MODIFY COLUMN x COMMENT 'example' CODEC(LZ4) TTL ts;
Original file line number Diff line number Diff line change
@@ -0,0 +1,233 @@
[
{
"AlterPos": 0,
"StatementEnd": 65,
"TableIdentifier": {
"Database": null,
"Table": {
"Name": "t",
"QuoteType": 1,
"NamePos": 12,
"NameEnd": 13
}
},
"OnCluster": null,
"AlterExprs": [
{
"ModifyPos": 14,
"StatementEnd": 65,
"IfExists": false,
"Column": {
"NamePos": 28,
"ColumnEnd": 65,
"Name": {
"Ident": {
"Name": "x",
"QuoteType": 1,
"NamePos": 28,
"NameEnd": 29
},
"DotIdent": null
},
"Type": null,
"NotNull": null,
"Nullable": null,
"DefaultExpr": null,
"MaterializedExpr": null,
"AliasExpr": null,
"Codec": {
"CodecPos": 30,
"RightParenPos": 40,
"Type": null,
"TypeLevel": null,
"Name": {
"Name": "LZ4",
"QuoteType": 1,
"NamePos": 36,
"NameEnd": 39
},
"Level": null
},
"TTL": {
"TTLPos": 59,
"ListEnd": 65,
"Items": [
{
"TTLPos": 59,
"Expr": {
"Name": "ts",
"QuoteType": 1,
"NamePos": 63,
"NameEnd": 65
},
"Policy": null
}
]
},
"Comment": {
"LiteralPos": 41,
"LiteralEnd": 58,
"Literal": "example"
},
"CompressionCodec": null
},
"RemovePropertyType": null
}
],
"Settings": null
},
{
"AlterPos": 67,
"StatementEnd": 132,
"TableIdentifier": {
"Database": null,
"Table": {
"Name": "t",
"QuoteType": 1,
"NamePos": 79,
"NameEnd": 80
}
},
"OnCluster": null,
"AlterExprs": [
{
"ModifyPos": 81,
"StatementEnd": 132,
"IfExists": false,
"Column": {
"NamePos": 95,
"ColumnEnd": 132,
"Name": {
"Ident": {
"Name": "x",
"QuoteType": 1,
"NamePos": 95,
"NameEnd": 96
},
"DotIdent": null
},
"Type": null,
"NotNull": null,
"Nullable": null,
"DefaultExpr": null,
"MaterializedExpr": null,
"AliasExpr": null,
"Codec": {
"CodecPos": 115,
"RightParenPos": 125,
"Type": null,
"TypeLevel": null,
"Name": {
"Name": "LZ4",
"QuoteType": 1,
"NamePos": 121,
"NameEnd": 124
},
"Level": null
},
"TTL": {
"TTLPos": 126,
"ListEnd": 132,
"Items": [
{
"TTLPos": 126,
"Expr": {
"Name": "ts",
"QuoteType": 1,
"NamePos": 130,
"NameEnd": 132
},
"Policy": null
}
]
},
"Comment": {
"LiteralPos": 97,
"LiteralEnd": 114,
"Literal": "example"
},
"CompressionCodec": null
},
"RemovePropertyType": null
}
],
"Settings": null
},
{
"AlterPos": 134,
"StatementEnd": 199,
"TableIdentifier": {
"Database": null,
"Table": {
"Name": "t",
"QuoteType": 1,
"NamePos": 146,
"NameEnd": 147
}
},
"OnCluster": null,
"AlterExprs": [
{
"ModifyPos": 148,
"StatementEnd": 199,
"IfExists": false,
"Column": {
"NamePos": 162,
"ColumnEnd": 199,
"Name": {
"Ident": {
"Name": "x",
"QuoteType": 1,
"NamePos": 162,
"NameEnd": 163
},
"DotIdent": null
},
"Type": null,
"NotNull": null,
"Nullable": null,
"DefaultExpr": null,
"MaterializedExpr": null,
"AliasExpr": null,
"Codec": {
"CodecPos": 164,
"RightParenPos": 174,
"Type": null,
"TypeLevel": null,
"Name": {
"Name": "LZ4",
"QuoteType": 1,
"NamePos": 170,
"NameEnd": 173
},
"Level": null
},
"TTL": {
"TTLPos": 175,
"ListEnd": 181,
"Items": [
{
"TTLPos": 175,
"Expr": {
"Name": "ts",
"QuoteType": 1,
"NamePos": 179,
"NameEnd": 181
},
"Policy": null
}
]
},
"Comment": {
"LiteralPos": 182,
"LiteralEnd": 199,
"Literal": "example"
},
"CompressionCodec": null
},
"RemovePropertyType": null
}
],
"Settings": null
}
]
Loading