From f6c72dd97a1c65907b097ad1ad1eb3772f40aa09 Mon Sep 17 00:00:00 2001 From: Sharad Gaur Date: Tue, 27 Oct 2026 20:11:25 -0400 Subject: [PATCH] Allow COMMENT, CODEC and TTL in any order --- parser/column_modifiers_test.go | 100 ++ parser/format.go | 8 +- parser/parser_table.go | 62 +- parser/testdata/ddl/column_modifiers.sql | 17 + .../ddl/format/beautify/column_modifiers.sql | 40 + .../testdata/ddl/format/column_modifiers.sql | 24 + .../output/column_modifiers.sql.golden.json | 964 ++++++++++++++++++ 7 files changed, 1185 insertions(+), 30 deletions(-) create mode 100644 parser/column_modifiers_test.go create mode 100644 parser/testdata/ddl/column_modifiers.sql create mode 100644 parser/testdata/ddl/format/beautify/column_modifiers.sql create mode 100644 parser/testdata/ddl/format/column_modifiers.sql create mode 100644 parser/testdata/ddl/output/column_modifiers.sql.golden.json diff --git a/parser/column_modifiers_test.go b/parser/column_modifiers_test.go new file mode 100644 index 0000000..5daeae4 --- /dev/null +++ b/parser/column_modifiers_test.go @@ -0,0 +1,100 @@ +package parser + +import ( + "fmt" + "strings" + "testing" + + "github.com/stretchr/testify/require" +) + +func TestParser_ColumnModifierOrder(t *testing.T) { + modifiers := map[string]string{ + "comment": "cOmMeNt 'example'", + "codec": "cOdEc(ZSTD(1))", + "ttl": "tTl event_time + INTERVAL 1 DAY", + } + orders := [][]string{ + {"comment", "codec", "ttl"}, + {"comment", "ttl", "codec"}, + {"codec", "comment", "ttl"}, + {"codec", "ttl", "comment"}, + {"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"}, + } + for _, form := range forms { + for _, order := range orders { + t.Run(form.name+"/"+strings.Join(order, "_"), func(t *testing.T) { + var clauses []string + for _, name := range order { + clauses = append(clauses, modifiers[name]) + } + declaration := "value String " + 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.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" + require.Equal(t, canonical, Format(column)) + for _, beautify := range []bool{false, true} { + formatter := NewFormatter() + if beautify { + formatter.WithBeautify() + } + statements[0].FormatSQL(formatter) + reparsed, err := NewParser(formatter.String()).ParseStmts() + require.NoError(t, err) + require.Len(t, reparsed, 1) + require.Equal(t, canonical, Format(modifierTestColumn(t, reparsed[0]))) + } + validFormatSQL(t, Format(statements[0])+";\n") + }) + } + } +} + +func TestParser_InvalidColumnModifiers(t *testing.T) { + for _, tc := range []struct{ name, modifiers, errorText string }{ + {"comment twice", "COMMENT '' COMMENT 'example'", "duplicate COMMENT"}, + {"separated comments", "COMMENT 'first' CODEC(ZSTD(1)) COMMENT 'second'", "duplicate COMMENT"}, + {"codec twice", "CODEC(ZSTD(1)) CODEC(LZ4)", "duplicate CODEC"}, + {"separated codecs", "CODEC(ZSTD(1)) COMMENT 'example' CODEC(LZ4)", "duplicate CODEC"}, + {"ttl twice", "TTL event_time + INTERVAL 1 DAY TTL event_time + INTERVAL 2 DAY", "duplicate TTL"}, + {"separated ttls", "TTL event_time + INTERVAL 1 DAY COMMENT 'example' TTL event_time + INTERVAL 2 DAY", "duplicate TTL"}, + {"missing comment", "COMMENT", ""}, + {"incomplete codec", "CODEC(", ""}, + {"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) + } + }) + } +} + +func modifierTestColumn(t *testing.T, expression Expr) *ColumnDef { + t.Helper() + var columns []*ColumnDef + Walk(expression, func(node Expr) bool { + if column, ok := node.(*ColumnDef); ok && Format(column.Name) == "value" { + columns = append(columns, column) + } + return true + }) + require.Len(t, columns, 1) + return columns[0] +} diff --git a/parser/format.go b/parser/format.go index 14c4d13..78fe256 100644 --- a/parser/format.go +++ b/parser/format.go @@ -673,6 +673,10 @@ func (c *ColumnDef) FormatSQL(formatter *Formatter) { formatter.WriteString(" ALIAS ") formatter.WriteExpr(c.AliasExpr) } + if c.Comment != nil { + formatter.WriteString(" COMMENT ") + formatter.WriteExpr(c.Comment) + } if c.Codec != nil { formatter.WriteByte(whitespace) formatter.WriteExpr(c.Codec) @@ -681,10 +685,6 @@ func (c *ColumnDef) FormatSQL(formatter *Formatter) { formatter.WriteByte(whitespace) formatter.WriteExpr(c.TTL) } - if c.Comment != nil { - formatter.WriteString(" COMMENT ") - formatter.WriteExpr(c.Comment) - } } func (c *ColumnExpr) FormatSQL(formatter *Formatter) { diff --git a/parser/parser_table.go b/parser/parser_table.go index 30ef6bc..28db5f7 100644 --- a/parser/parser_table.go +++ b/parser/parser_table.go @@ -733,38 +733,48 @@ func (p *Parser) parseTableColumnExpr(pos Pos) (*ColumnDef, error) { columnEnd = valueExpr.End() } - comment, err := p.tryParseColumnComment(p.Pos()) - if err != nil { - return nil, err - } - if comment != nil { - columnEnd = comment.End() - } - - codec, err := p.tryParseCompressionCodecs(p.Pos()) - if err != nil { - return nil, err - } - if codec != nil { - columnEnd = codec.End() - } - ttl, err := p.tryParseTTLClause(p.Pos(), false) - if err != nil { - return nil, err - } - if ttl != nil { - columnEnd = ttl.End() - } - column.TTL = ttl - column.ColumnEnd = columnEnd - column.Comment = comment - column.Codec = codec column.Nullable = nullable column.NotNull = notNull + if err := p.parseColumnModifiers(column); err != nil { + return nil, err + } return column, nil } +func (p *Parser) parseColumnModifiers(column *ColumnDef) error { + for { + var modifier Expr + var err error + switch { + case p.matchKeyword(KeywordComment): + if column.Comment != nil { + return fmt.Errorf("duplicate COMMENT clause") + } + column.Comment, err = p.tryParseColumnComment(p.Pos()) + modifier = column.Comment + case p.matchKeyword(KeywordCodec): + if column.Codec != nil { + return fmt.Errorf("duplicate CODEC clause") + } + column.Codec, err = p.tryParseCompressionCodecs(p.Pos()) + modifier = column.Codec + case p.matchKeyword(KeywordTtl): + if column.TTL != nil { + return fmt.Errorf("duplicate TTL clause") + } + column.TTL, err = p.tryParseTTLClause(p.Pos(), false) + modifier = column.TTL + default: + return nil + } + if err != nil { + return err + } + column.ColumnEnd = modifier.End() + } +} + func (p *Parser) parseTableArgExpr(pos Pos) (Expr, error) { expr, err := p.parseTableArgPrimaryExpr(pos) if err != nil { diff --git a/parser/testdata/ddl/column_modifiers.sql b/parser/testdata/ddl/column_modifiers.sql new file mode 100644 index 0000000..c7a2cf7 --- /dev/null +++ b/parser/testdata/ddl/column_modifiers.sql @@ -0,0 +1,17 @@ +CREATE TABLE db.example +( + event_time DateTime, + value_a String COMMENT 'example' CODEC(ZSTD(1)) TTL event_time + INTERVAL 1 DAY, + value_b String COMMENT 'example' TTL event_time + INTERVAL 1 DAY CODEC(ZSTD(1)), + value_c String CODEC(ZSTD(1)) COMMENT 'example' TTL event_time + INTERVAL 1 DAY, + value_d String CODEC(ZSTD(1)) TTL event_time + INTERVAL 1 DAY COMMENT 'example', + value_e String TTL event_time + INTERVAL 1 DAY COMMENT 'example' CODEC(ZSTD(1)), + value_f String TTL event_time + INTERVAL 1 DAY CODEC(ZSTD(1)) COMMENT 'example', + value_g String COMMENT 'example' CODEC(ZSTD(1)), + value_h String CODEC(ZSTD(1)) COMMENT 'example' +) +ENGINE = MergeTree +ORDER BY event_time; + +ALTER TABLE db.example ADD COLUMN extra String DEFAULT 'value' TTL event_time + INTERVAL 1 DAY CODEC(LZ4) COMMENT 'example'; +ALTER TABLE db.example MODIFY COLUMN extra String MATERIALIZED toString(event_time) CODEC(LZ4) COMMENT 'example' TTL event_time + INTERVAL 1 DAY; diff --git a/parser/testdata/ddl/format/beautify/column_modifiers.sql b/parser/testdata/ddl/format/beautify/column_modifiers.sql new file mode 100644 index 0000000..f79aef8 --- /dev/null +++ b/parser/testdata/ddl/format/beautify/column_modifiers.sql @@ -0,0 +1,40 @@ +-- Origin SQL: +CREATE TABLE db.example +( + event_time DateTime, + value_a String COMMENT 'example' CODEC(ZSTD(1)) TTL event_time + INTERVAL 1 DAY, + value_b String COMMENT 'example' TTL event_time + INTERVAL 1 DAY CODEC(ZSTD(1)), + value_c String CODEC(ZSTD(1)) COMMENT 'example' TTL event_time + INTERVAL 1 DAY, + value_d String CODEC(ZSTD(1)) TTL event_time + INTERVAL 1 DAY COMMENT 'example', + value_e String TTL event_time + INTERVAL 1 DAY COMMENT 'example' CODEC(ZSTD(1)), + value_f String TTL event_time + INTERVAL 1 DAY CODEC(ZSTD(1)) COMMENT 'example', + value_g String COMMENT 'example' CODEC(ZSTD(1)), + value_h String CODEC(ZSTD(1)) COMMENT 'example' +) +ENGINE = MergeTree +ORDER BY event_time; + +ALTER TABLE db.example ADD COLUMN extra String DEFAULT 'value' TTL event_time + INTERVAL 1 DAY CODEC(LZ4) COMMENT 'example'; +ALTER TABLE db.example MODIFY COLUMN extra String MATERIALIZED toString(event_time) CODEC(LZ4) COMMENT 'example' TTL event_time + INTERVAL 1 DAY; + + +-- Beautify SQL: +CREATE TABLE db.example +( + event_time DateTime, + value_a String COMMENT 'example' CODEC(ZSTD(1)) TTL event_time + INTERVAL 1 DAY, + value_b String COMMENT 'example' CODEC(ZSTD(1)) TTL event_time + INTERVAL 1 DAY, + value_c String COMMENT 'example' CODEC(ZSTD(1)) TTL event_time + INTERVAL 1 DAY, + value_d String COMMENT 'example' CODEC(ZSTD(1)) TTL event_time + INTERVAL 1 DAY, + value_e String COMMENT 'example' CODEC(ZSTD(1)) TTL event_time + INTERVAL 1 DAY, + value_f String COMMENT 'example' CODEC(ZSTD(1)) TTL event_time + INTERVAL 1 DAY, + value_g String COMMENT 'example' CODEC(ZSTD(1)), + value_h String COMMENT 'example' CODEC(ZSTD(1)) +) +ENGINE = MergeTree +ORDER BY + event_time; +ALTER TABLE db.example +ADD COLUMN extra String DEFAULT 'value' COMMENT 'example' CODEC(LZ4) TTL event_time + INTERVAL 1 DAY; +ALTER TABLE db.example +MODIFY COLUMN extra String MATERIALIZED toString(event_time) COMMENT 'example' CODEC(LZ4) TTL event_time + INTERVAL 1 DAY; diff --git a/parser/testdata/ddl/format/column_modifiers.sql b/parser/testdata/ddl/format/column_modifiers.sql new file mode 100644 index 0000000..a8eec49 --- /dev/null +++ b/parser/testdata/ddl/format/column_modifiers.sql @@ -0,0 +1,24 @@ +-- Origin SQL: +CREATE TABLE db.example +( + event_time DateTime, + value_a String COMMENT 'example' CODEC(ZSTD(1)) TTL event_time + INTERVAL 1 DAY, + value_b String COMMENT 'example' TTL event_time + INTERVAL 1 DAY CODEC(ZSTD(1)), + value_c String CODEC(ZSTD(1)) COMMENT 'example' TTL event_time + INTERVAL 1 DAY, + value_d String CODEC(ZSTD(1)) TTL event_time + INTERVAL 1 DAY COMMENT 'example', + value_e String TTL event_time + INTERVAL 1 DAY COMMENT 'example' CODEC(ZSTD(1)), + value_f String TTL event_time + INTERVAL 1 DAY CODEC(ZSTD(1)) COMMENT 'example', + value_g String COMMENT 'example' CODEC(ZSTD(1)), + value_h String CODEC(ZSTD(1)) COMMENT 'example' +) +ENGINE = MergeTree +ORDER BY event_time; + +ALTER TABLE db.example ADD COLUMN extra String DEFAULT 'value' TTL event_time + INTERVAL 1 DAY CODEC(LZ4) COMMENT 'example'; +ALTER TABLE db.example MODIFY COLUMN extra String MATERIALIZED toString(event_time) CODEC(LZ4) COMMENT 'example' TTL event_time + INTERVAL 1 DAY; + + +-- Format SQL: +CREATE TABLE db.example (event_time DateTime, value_a String COMMENT 'example' CODEC(ZSTD(1)) TTL event_time + INTERVAL 1 DAY, value_b String COMMENT 'example' CODEC(ZSTD(1)) TTL event_time + INTERVAL 1 DAY, value_c String COMMENT 'example' CODEC(ZSTD(1)) TTL event_time + INTERVAL 1 DAY, value_d String COMMENT 'example' CODEC(ZSTD(1)) TTL event_time + INTERVAL 1 DAY, value_e String COMMENT 'example' CODEC(ZSTD(1)) TTL event_time + INTERVAL 1 DAY, value_f String COMMENT 'example' CODEC(ZSTD(1)) TTL event_time + INTERVAL 1 DAY, value_g String COMMENT 'example' CODEC(ZSTD(1)), value_h String COMMENT 'example' CODEC(ZSTD(1))) ENGINE = MergeTree ORDER BY event_time; +ALTER TABLE db.example ADD COLUMN extra String DEFAULT 'value' COMMENT 'example' CODEC(LZ4) TTL event_time + INTERVAL 1 DAY; +ALTER TABLE db.example MODIFY COLUMN extra String MATERIALIZED toString(event_time) COMMENT 'example' CODEC(LZ4) TTL event_time + INTERVAL 1 DAY; diff --git a/parser/testdata/ddl/output/column_modifiers.sql.golden.json b/parser/testdata/ddl/output/column_modifiers.sql.golden.json new file mode 100644 index 0000000..2b7dc76 --- /dev/null +++ b/parser/testdata/ddl/output/column_modifiers.sql.golden.json @@ -0,0 +1,964 @@ +[ + { + "CreatePos": 0, + "StatementEnd": 706, + "OrReplace": false, + "Name": { + "Database": { + "Name": "db", + "QuoteType": 1, + "NamePos": 13, + "NameEnd": 15 + }, + "Table": { + "Name": "example", + "QuoteType": 1, + "NamePos": 16, + "NameEnd": 23 + } + }, + "IfNotExists": false, + "UUID": null, + "OnCluster": null, + "TableSchema": { + "SchemaPos": 24, + "SchemaEnd": 666, + "Columns": [ + { + "NamePos": 30, + "ColumnEnd": 49, + "Name": { + "Ident": { + "Name": "event_time", + "QuoteType": 1, + "NamePos": 30, + "NameEnd": 40 + }, + "DotIdent": null + }, + "Type": { + "Name": { + "Name": "DateTime", + "QuoteType": 1, + "NamePos": 41, + "NameEnd": 49 + } + }, + "NotNull": null, + "Nullable": null, + "DefaultExpr": null, + "MaterializedExpr": null, + "AliasExpr": null, + "Codec": null, + "TTL": null, + "Comment": null, + "CompressionCodec": null + }, + { + "NamePos": 55, + "ColumnEnd": 134, + "Name": { + "Ident": { + "Name": "value_a", + "QuoteType": 1, + "NamePos": 55, + "NameEnd": 62 + }, + "DotIdent": null + }, + "Type": { + "Name": { + "Name": "String", + "QuoteType": 1, + "NamePos": 63, + "NameEnd": 69 + } + }, + "NotNull": null, + "Nullable": null, + "DefaultExpr": null, + "MaterializedExpr": null, + "AliasExpr": null, + "Codec": { + "CodecPos": 88, + "RightParenPos": 102, + "Type": null, + "TypeLevel": null, + "Name": { + "Name": "ZSTD", + "QuoteType": 1, + "NamePos": 94, + "NameEnd": 98 + }, + "Level": { + "NumPos": 98, + "NumEnd": 100, + "Literal": "1", + "Base": 10 + } + }, + "TTL": { + "TTLPos": 103, + "ListEnd": 134, + "Items": [ + { + "TTLPos": 103, + "Expr": { + "LeftExpr": { + "Name": "event_time", + "QuoteType": 1, + "NamePos": 107, + "NameEnd": 117 + }, + "Operation": "+", + "RightExpr": { + "IntervalPos": 120, + "Expr": { + "NumPos": 129, + "NumEnd": 130, + "Literal": "1", + "Base": 10 + }, + "Unit": { + "Name": "DAY", + "QuoteType": 1, + "NamePos": 131, + "NameEnd": 134 + } + }, + "HasGlobal": false, + "HasNot": false + }, + "Policy": null + } + ] + }, + "Comment": { + "LiteralPos": 70, + "LiteralEnd": 87, + "Literal": "example" + }, + "CompressionCodec": null + }, + { + "NamePos": 140, + "ColumnEnd": 219, + "Name": { + "Ident": { + "Name": "value_b", + "QuoteType": 1, + "NamePos": 140, + "NameEnd": 147 + }, + "DotIdent": null + }, + "Type": { + "Name": { + "Name": "String", + "QuoteType": 1, + "NamePos": 148, + "NameEnd": 154 + } + }, + "NotNull": null, + "Nullable": null, + "DefaultExpr": null, + "MaterializedExpr": null, + "AliasExpr": null, + "Codec": { + "CodecPos": 205, + "RightParenPos": 219, + "Type": null, + "TypeLevel": null, + "Name": { + "Name": "ZSTD", + "QuoteType": 1, + "NamePos": 211, + "NameEnd": 215 + }, + "Level": { + "NumPos": 215, + "NumEnd": 217, + "Literal": "1", + "Base": 10 + } + }, + "TTL": { + "TTLPos": 173, + "ListEnd": 204, + "Items": [ + { + "TTLPos": 173, + "Expr": { + "LeftExpr": { + "Name": "event_time", + "QuoteType": 1, + "NamePos": 177, + "NameEnd": 187 + }, + "Operation": "+", + "RightExpr": { + "IntervalPos": 190, + "Expr": { + "NumPos": 199, + "NumEnd": 200, + "Literal": "1", + "Base": 10 + }, + "Unit": { + "Name": "DAY", + "QuoteType": 1, + "NamePos": 201, + "NameEnd": 204 + } + }, + "HasGlobal": false, + "HasNot": false + }, + "Policy": null + } + ] + }, + "Comment": { + "LiteralPos": 155, + "LiteralEnd": 172, + "Literal": "example" + }, + "CompressionCodec": null + }, + { + "NamePos": 225, + "ColumnEnd": 304, + "Name": { + "Ident": { + "Name": "value_c", + "QuoteType": 1, + "NamePos": 225, + "NameEnd": 232 + }, + "DotIdent": null + }, + "Type": { + "Name": { + "Name": "String", + "QuoteType": 1, + "NamePos": 233, + "NameEnd": 239 + } + }, + "NotNull": null, + "Nullable": null, + "DefaultExpr": null, + "MaterializedExpr": null, + "AliasExpr": null, + "Codec": { + "CodecPos": 240, + "RightParenPos": 254, + "Type": null, + "TypeLevel": null, + "Name": { + "Name": "ZSTD", + "QuoteType": 1, + "NamePos": 246, + "NameEnd": 250 + }, + "Level": { + "NumPos": 250, + "NumEnd": 252, + "Literal": "1", + "Base": 10 + } + }, + "TTL": { + "TTLPos": 273, + "ListEnd": 304, + "Items": [ + { + "TTLPos": 273, + "Expr": { + "LeftExpr": { + "Name": "event_time", + "QuoteType": 1, + "NamePos": 277, + "NameEnd": 287 + }, + "Operation": "+", + "RightExpr": { + "IntervalPos": 290, + "Expr": { + "NumPos": 299, + "NumEnd": 300, + "Literal": "1", + "Base": 10 + }, + "Unit": { + "Name": "DAY", + "QuoteType": 1, + "NamePos": 301, + "NameEnd": 304 + } + }, + "HasGlobal": false, + "HasNot": false + }, + "Policy": null + } + ] + }, + "Comment": { + "LiteralPos": 255, + "LiteralEnd": 272, + "Literal": "example" + }, + "CompressionCodec": null + }, + { + "NamePos": 310, + "ColumnEnd": 389, + "Name": { + "Ident": { + "Name": "value_d", + "QuoteType": 1, + "NamePos": 310, + "NameEnd": 317 + }, + "DotIdent": null + }, + "Type": { + "Name": { + "Name": "String", + "QuoteType": 1, + "NamePos": 318, + "NameEnd": 324 + } + }, + "NotNull": null, + "Nullable": null, + "DefaultExpr": null, + "MaterializedExpr": null, + "AliasExpr": null, + "Codec": { + "CodecPos": 325, + "RightParenPos": 339, + "Type": null, + "TypeLevel": null, + "Name": { + "Name": "ZSTD", + "QuoteType": 1, + "NamePos": 331, + "NameEnd": 335 + }, + "Level": { + "NumPos": 335, + "NumEnd": 337, + "Literal": "1", + "Base": 10 + } + }, + "TTL": { + "TTLPos": 340, + "ListEnd": 371, + "Items": [ + { + "TTLPos": 340, + "Expr": { + "LeftExpr": { + "Name": "event_time", + "QuoteType": 1, + "NamePos": 344, + "NameEnd": 354 + }, + "Operation": "+", + "RightExpr": { + "IntervalPos": 357, + "Expr": { + "NumPos": 366, + "NumEnd": 367, + "Literal": "1", + "Base": 10 + }, + "Unit": { + "Name": "DAY", + "QuoteType": 1, + "NamePos": 368, + "NameEnd": 371 + } + }, + "HasGlobal": false, + "HasNot": false + }, + "Policy": null + } + ] + }, + "Comment": { + "LiteralPos": 372, + "LiteralEnd": 389, + "Literal": "example" + }, + "CompressionCodec": null + }, + { + "NamePos": 395, + "ColumnEnd": 474, + "Name": { + "Ident": { + "Name": "value_e", + "QuoteType": 1, + "NamePos": 395, + "NameEnd": 402 + }, + "DotIdent": null + }, + "Type": { + "Name": { + "Name": "String", + "QuoteType": 1, + "NamePos": 403, + "NameEnd": 409 + } + }, + "NotNull": null, + "Nullable": null, + "DefaultExpr": null, + "MaterializedExpr": null, + "AliasExpr": null, + "Codec": { + "CodecPos": 460, + "RightParenPos": 474, + "Type": null, + "TypeLevel": null, + "Name": { + "Name": "ZSTD", + "QuoteType": 1, + "NamePos": 466, + "NameEnd": 470 + }, + "Level": { + "NumPos": 470, + "NumEnd": 472, + "Literal": "1", + "Base": 10 + } + }, + "TTL": { + "TTLPos": 410, + "ListEnd": 441, + "Items": [ + { + "TTLPos": 410, + "Expr": { + "LeftExpr": { + "Name": "event_time", + "QuoteType": 1, + "NamePos": 414, + "NameEnd": 424 + }, + "Operation": "+", + "RightExpr": { + "IntervalPos": 427, + "Expr": { + "NumPos": 436, + "NumEnd": 437, + "Literal": "1", + "Base": 10 + }, + "Unit": { + "Name": "DAY", + "QuoteType": 1, + "NamePos": 438, + "NameEnd": 441 + } + }, + "HasGlobal": false, + "HasNot": false + }, + "Policy": null + } + ] + }, + "Comment": { + "LiteralPos": 442, + "LiteralEnd": 459, + "Literal": "example" + }, + "CompressionCodec": null + }, + { + "NamePos": 480, + "ColumnEnd": 559, + "Name": { + "Ident": { + "Name": "value_f", + "QuoteType": 1, + "NamePos": 480, + "NameEnd": 487 + }, + "DotIdent": null + }, + "Type": { + "Name": { + "Name": "String", + "QuoteType": 1, + "NamePos": 488, + "NameEnd": 494 + } + }, + "NotNull": null, + "Nullable": null, + "DefaultExpr": null, + "MaterializedExpr": null, + "AliasExpr": null, + "Codec": { + "CodecPos": 527, + "RightParenPos": 541, + "Type": null, + "TypeLevel": null, + "Name": { + "Name": "ZSTD", + "QuoteType": 1, + "NamePos": 533, + "NameEnd": 537 + }, + "Level": { + "NumPos": 537, + "NumEnd": 539, + "Literal": "1", + "Base": 10 + } + }, + "TTL": { + "TTLPos": 495, + "ListEnd": 526, + "Items": [ + { + "TTLPos": 495, + "Expr": { + "LeftExpr": { + "Name": "event_time", + "QuoteType": 1, + "NamePos": 499, + "NameEnd": 509 + }, + "Operation": "+", + "RightExpr": { + "IntervalPos": 512, + "Expr": { + "NumPos": 521, + "NumEnd": 522, + "Literal": "1", + "Base": 10 + }, + "Unit": { + "Name": "DAY", + "QuoteType": 1, + "NamePos": 523, + "NameEnd": 526 + } + }, + "HasGlobal": false, + "HasNot": false + }, + "Policy": null + } + ] + }, + "Comment": { + "LiteralPos": 542, + "LiteralEnd": 559, + "Literal": "example" + }, + "CompressionCodec": null + }, + { + "NamePos": 565, + "ColumnEnd": 612, + "Name": { + "Ident": { + "Name": "value_g", + "QuoteType": 1, + "NamePos": 565, + "NameEnd": 572 + }, + "DotIdent": null + }, + "Type": { + "Name": { + "Name": "String", + "QuoteType": 1, + "NamePos": 573, + "NameEnd": 579 + } + }, + "NotNull": null, + "Nullable": null, + "DefaultExpr": null, + "MaterializedExpr": null, + "AliasExpr": null, + "Codec": { + "CodecPos": 598, + "RightParenPos": 612, + "Type": null, + "TypeLevel": null, + "Name": { + "Name": "ZSTD", + "QuoteType": 1, + "NamePos": 604, + "NameEnd": 608 + }, + "Level": { + "NumPos": 608, + "NumEnd": 610, + "Literal": "1", + "Base": 10 + } + }, + "TTL": null, + "Comment": { + "LiteralPos": 580, + "LiteralEnd": 597, + "Literal": "example" + }, + "CompressionCodec": null + }, + { + "NamePos": 618, + "ColumnEnd": 665, + "Name": { + "Ident": { + "Name": "value_h", + "QuoteType": 1, + "NamePos": 618, + "NameEnd": 625 + }, + "DotIdent": null + }, + "Type": { + "Name": { + "Name": "String", + "QuoteType": 1, + "NamePos": 626, + "NameEnd": 632 + } + }, + "NotNull": null, + "Nullable": null, + "DefaultExpr": null, + "MaterializedExpr": null, + "AliasExpr": null, + "Codec": { + "CodecPos": 633, + "RightParenPos": 647, + "Type": null, + "TypeLevel": null, + "Name": { + "Name": "ZSTD", + "QuoteType": 1, + "NamePos": 639, + "NameEnd": 643 + }, + "Level": { + "NumPos": 643, + "NumEnd": 645, + "Literal": "1", + "Base": 10 + } + }, + "TTL": null, + "Comment": { + "LiteralPos": 648, + "LiteralEnd": 665, + "Literal": "example" + }, + "CompressionCodec": null + } + ], + "AliasTable": null, + "TableFunction": null + }, + "Engine": { + "EnginePos": 668, + "EngineEnd": 706, + "Name": "MergeTree", + "Params": null, + "PrimaryKey": null, + "PartitionBy": null, + "SampleBy": null, + "TTL": null, + "Settings": null, + "OrderBy": { + "OrderPos": 687, + "ListEnd": 706, + "Items": [ + { + "OrderPos": 687, + "Expr": { + "Name": "event_time", + "QuoteType": 1, + "NamePos": 696, + "NameEnd": 706 + }, + "Alias": null, + "Direction": "", + "Fill": null + } + ], + "Interpolate": null + } + }, + "SubQuery": null, + "TableFunction": null, + "HasTemporary": false, + "Comment": null + }, + { + "AlterPos": 709, + "StatementEnd": 832, + "TableIdentifier": { + "Database": { + "Name": "db", + "QuoteType": 1, + "NamePos": 721, + "NameEnd": 723 + }, + "Table": { + "Name": "example", + "QuoteType": 1, + "NamePos": 724, + "NameEnd": 731 + } + }, + "OnCluster": null, + "AlterExprs": [ + { + "AddPos": 732, + "StatementEnd": 832, + "Column": { + "NamePos": 743, + "ColumnEnd": 832, + "Name": { + "Ident": { + "Name": "extra", + "QuoteType": 1, + "NamePos": 743, + "NameEnd": 748 + }, + "DotIdent": null + }, + "Type": { + "Name": { + "Name": "String", + "QuoteType": 1, + "NamePos": 749, + "NameEnd": 755 + } + }, + "NotNull": null, + "Nullable": null, + "DefaultExpr": { + "LiteralPos": 764, + "LiteralEnd": 771, + "Literal": "value" + }, + "MaterializedExpr": null, + "AliasExpr": null, + "Codec": { + "CodecPos": 804, + "RightParenPos": 814, + "Type": null, + "TypeLevel": null, + "Name": { + "Name": "LZ4", + "QuoteType": 1, + "NamePos": 810, + "NameEnd": 813 + }, + "Level": null + }, + "TTL": { + "TTLPos": 772, + "ListEnd": 803, + "Items": [ + { + "TTLPos": 772, + "Expr": { + "LeftExpr": { + "Name": "event_time", + "QuoteType": 1, + "NamePos": 776, + "NameEnd": 786 + }, + "Operation": "+", + "RightExpr": { + "IntervalPos": 789, + "Expr": { + "NumPos": 798, + "NumEnd": 799, + "Literal": "1", + "Base": 10 + }, + "Unit": { + "Name": "DAY", + "QuoteType": 1, + "NamePos": 800, + "NameEnd": 803 + } + }, + "HasGlobal": false, + "HasNot": false + }, + "Policy": null + } + ] + }, + "Comment": { + "LiteralPos": 815, + "LiteralEnd": 832, + "Literal": "example" + }, + "CompressionCodec": null + }, + "IfNotExists": false, + "After": null + } + ], + "Settings": null + }, + { + "AlterPos": 834, + "StatementEnd": 978, + "TableIdentifier": { + "Database": { + "Name": "db", + "QuoteType": 1, + "NamePos": 846, + "NameEnd": 848 + }, + "Table": { + "Name": "example", + "QuoteType": 1, + "NamePos": 849, + "NameEnd": 856 + } + }, + "OnCluster": null, + "AlterExprs": [ + { + "ModifyPos": 857, + "StatementEnd": 978, + "IfExists": false, + "Column": { + "NamePos": 871, + "ColumnEnd": 978, + "Name": { + "Ident": { + "Name": "extra", + "QuoteType": 1, + "NamePos": 871, + "NameEnd": 876 + }, + "DotIdent": null + }, + "Type": { + "Name": { + "Name": "String", + "QuoteType": 1, + "NamePos": 877, + "NameEnd": 883 + } + }, + "NotNull": null, + "Nullable": null, + "DefaultExpr": null, + "MaterializedExpr": { + "Name": { + "Name": "toString", + "QuoteType": 1, + "NamePos": 897, + "NameEnd": 905 + }, + "Params": { + "LeftParenPos": 905, + "RightParenPos": 916, + "Items": { + "ListPos": 906, + "ListEnd": 916, + "HasDistinct": false, + "Items": [ + { + "Expr": { + "Name": "event_time", + "QuoteType": 1, + "NamePos": 906, + "NameEnd": 916 + }, + "Alias": null + } + ] + }, + "ColumnArgList": null + } + }, + "AliasExpr": null, + "Codec": { + "CodecPos": 918, + "RightParenPos": 928, + "Type": null, + "TypeLevel": null, + "Name": { + "Name": "LZ4", + "QuoteType": 1, + "NamePos": 924, + "NameEnd": 927 + }, + "Level": null + }, + "TTL": { + "TTLPos": 947, + "ListEnd": 978, + "Items": [ + { + "TTLPos": 947, + "Expr": { + "LeftExpr": { + "Name": "event_time", + "QuoteType": 1, + "NamePos": 951, + "NameEnd": 961 + }, + "Operation": "+", + "RightExpr": { + "IntervalPos": 964, + "Expr": { + "NumPos": 973, + "NumEnd": 974, + "Literal": "1", + "Base": 10 + }, + "Unit": { + "Name": "DAY", + "QuoteType": 1, + "NamePos": 975, + "NameEnd": 978 + } + }, + "HasGlobal": false, + "HasNot": false + }, + "Policy": null + } + ] + }, + "Comment": { + "LiteralPos": 929, + "LiteralEnd": 946, + "Literal": "example" + }, + "CompressionCodec": null + }, + "RemovePropertyType": null + } + ], + "Settings": null + } +] \ No newline at end of file