diff --git a/parser/ast.go b/parser/ast.go index 318a7a2..b2c73b0 100644 --- a/parser/ast.go +++ b/parser/ast.go @@ -1475,7 +1475,8 @@ type CreateTable struct { OnCluster *ClusterClause TableSchema *TableSchemaClause Engine *EngineExpr - SubQuery *SubQueryClause + Alias *AliasExpr + SubQuery *SubQuery HasTemporary bool } @@ -1518,6 +1519,7 @@ func (c *CreateTable) String() string { builder.WriteString(c.Engine.String()) } if c.SubQuery != nil { + builder.WriteString(" AS ") builder.WriteString(c.SubQuery.String()) } return builder.String() @@ -1562,7 +1564,7 @@ type CreateMaterializedView struct { OnCluster *ClusterClause Engine *EngineExpr Destination *DestinationClause - SubQuery *SubQueryClause + SubQuery *SubQuery Populate bool } @@ -1604,6 +1606,7 @@ func (c *CreateMaterializedView) String() string { builder.WriteString(" POPULATE ") } if c.SubQuery != nil { + builder.WriteString(" AS ") builder.WriteString(c.SubQuery.String()) } return builder.String() @@ -1651,7 +1654,7 @@ type CreateView struct { UUID *UUID OnCluster *ClusterClause TableSchema *TableSchemaClause - SubQuery *SubQueryClause + SubQuery *SubQuery } func (c *CreateView) Pos() Pos { @@ -1689,6 +1692,7 @@ func (c *CreateView) String() string { } if c.SubQuery != nil { + builder.WriteString(" AS ") builder.WriteString(c.SubQuery.String()) } return builder.String() @@ -4113,7 +4117,7 @@ type CreateLiveView struct { Destination *DestinationClause TableSchema *TableSchemaClause WithTimeout *WithTimeoutClause - SubQuery *SubQueryClause + SubQuery *SubQuery } func (c *CreateLiveView) Type() string { @@ -4157,6 +4161,7 @@ func (c *CreateLiveView) String() string { } if c.SubQuery != nil { + builder.WriteString(" AS ") builder.WriteString(c.SubQuery.String()) } @@ -5298,28 +5303,31 @@ func (s *SelectQuery) Accept(visitor ASTVisitor) error { return visitor.VisitSelectQuery(s) } -type SubQueryClause struct { - AsPos Pos - Select *SelectQuery +type SubQuery struct { + HasParen bool + Select *SelectQuery } -func (s *SubQueryClause) Pos() Pos { - return s.AsPos +func (s *SubQuery) Pos() Pos { + return s.Select.Pos() } -func (s *SubQueryClause) End() Pos { +func (s *SubQuery) End() Pos { return s.Select.End() } -func (s *SubQueryClause) String() string { - var builder strings.Builder - builder.WriteString(" AS (") - builder.WriteString(s.Select.String()) - builder.WriteString(")") - return builder.String() +func (s *SubQuery) String() string { + if s.HasParen { + var builder strings.Builder + builder.WriteString("(") + builder.WriteString(s.Select.String()) + builder.WriteString(")") + return builder.String() + } + return s.Select.String() } -func (s *SubQueryClause) Accept(visitor ASTVisitor) error { +func (s *SubQuery) Accept(visitor ASTVisitor) error { visitor.enter(s) defer visitor.leave(s) if s.Select != nil { diff --git a/parser/ast_visitor.go b/parser/ast_visitor.go index c88631d..fad52ac 100644 --- a/parser/ast_visitor.go +++ b/parser/ast_visitor.go @@ -121,7 +121,7 @@ type ASTVisitor interface { VisitWindowFrameNumber(expr *WindowFrameNumber) error VisitArrayJoinExpr(expr *ArrayJoinClause) error VisitSelectQuery(expr *SelectQuery) error - VisitSubQueryExpr(expr *SubQueryClause) error + VisitSubQueryExpr(expr *SubQuery) error VisitNotExpr(expr *NotExpr) error VisitNegateExpr(expr *NegateExpr) error VisitGlobalInExpr(expr *GlobalInOperation) error @@ -1006,7 +1006,7 @@ func (v *DefaultASTVisitor) VisitSelectQuery(expr *SelectQuery) error { return nil } -func (v *DefaultASTVisitor) VisitSubQueryExpr(expr *SubQueryClause) error { +func (v *DefaultASTVisitor) VisitSubQueryExpr(expr *SubQuery) error { if v.Visit != nil { return v.Visit(expr) } diff --git a/parser/lexer.go b/parser/lexer.go index fc241ff..4de4d54 100644 --- a/parser/lexer.go +++ b/parser/lexer.go @@ -36,6 +36,13 @@ type Token struct { QuoteType int } +func (t *Token) ToString() string { + if t.Kind == TokenKeyword { + return strings.ToUpper(t.String) + } + return t.String +} + type Lexer struct { input string current int diff --git a/parser/parser_column.go b/parser/parser_column.go index 34210b8..86eac6d 100644 --- a/parser/parser_column.go +++ b/parser/parser_column.go @@ -5,6 +5,24 @@ import ( "strings" ) +const ( + PrecedenceUnknown = iota + PrecedenceOr + PrecedenceAnd + PrecedenceQuery + PrecedenceNot + PrecedenceGlobal + PrecedenceIs + PrecedenceCompare + PrecedenceBetweenLike + precedenceIn + PrecedenceAddSub + PrecedenceMulDivMod + PrecedenceBracket + PrecedenceArrow + PrecedenceDoubleColon +) + func (p *Parser) tryParseColumnComment(pos Pos) (*StringLiteral, error) { if p.tryConsumeKeyword(KeywordComment) == nil { return nil, nil // nolint @@ -12,25 +30,172 @@ func (p *Parser) tryParseColumnComment(pos Pos) (*StringLiteral, error) { return p.parseString(pos) } +func (p *Parser) getNextPrecedence(pos Pos) int { + switch { + case p.matchKeyword(KeywordOr): + return PrecedenceOr + case p.matchKeyword(KeywordAnd): + return PrecedenceAnd + case p.matchKeyword(KeywordIs): + return PrecedenceIs + case p.matchKeyword(KeywordNot): + return PrecedenceNot + case p.matchTokenKind(opTypeCast): + return PrecedenceDoubleColon + case p.matchTokenKind(opTypeEQ), p.matchTokenKind(opTypeLT), p.matchTokenKind(opTypeLE), + p.matchTokenKind(opTypeGE), p.matchTokenKind(opTypeGT), p.matchTokenKind(opTypeDoubleEQ), + p.matchTokenKind(opTypeNE), p.matchTokenKind("<>"): + return PrecedenceCompare + case p.matchTokenKind(opTypePlus), p.matchTokenKind(opTypeMinus): + return PrecedenceAddSub + case p.matchTokenKind(opTypeMul), p.matchTokenKind(opTypeDiv), p.matchTokenKind(opTypeMod): + return PrecedenceMulDivMod + case p.matchTokenKind(opTypeArrow): + return PrecedenceArrow + case p.matchTokenKind("("), p.matchTokenKind("["): + return PrecedenceBracket + case p.matchTokenKind(opTypeCast): + return PrecedenceDoubleColon + case p.matchKeyword(KeywordBetween), p.matchKeyword(KeywordLike), p.matchKeyword(KeywordIlike): + return PrecedenceBetweenLike + case p.matchKeyword(KeywordIn): + return precedenceIn + case p.matchKeyword(KeywordGlobal): + return PrecedenceGlobal + case p.matchTokenKind(opTypeQuery): + return PrecedenceQuery + default: + return PrecedenceUnknown + } +} + +func (p *Parser) parseInfix(expr Expr, precedence int) (Expr, error) { + switch { + case p.matchTokenKind(opTypeEQ), p.matchTokenKind(opTypeLT), p.matchTokenKind(opTypeLE), + p.matchTokenKind(opTypeGE), p.matchTokenKind(opTypeGT), + p.matchTokenKind(opTypeNE), p.matchTokenKind("<>"), + p.matchTokenKind(opTypeMinus), p.matchTokenKind(opTypePlus), p.matchTokenKind(opTypeMul), + p.matchTokenKind(opTypeDiv), p.matchTokenKind(opTypeMod), + p.matchKeyword(KeywordIn), p.matchKeyword(KeywordLike), + p.matchKeyword(KeywordIlike), p.matchKeyword(KeywordAnd), p.matchKeyword(KeywordOr), + p.matchTokenKind(opTypeCast), p.matchTokenKind(opTypeArrow), p.matchTokenKind(opTypeDoubleEQ): + op := p.last().ToString() + _ = p.lexer.consumeToken() + rightExpr, err := p.parseSubExpr(p.Pos(), precedence) + if err != nil { + return nil, err + } + return &BinaryOperation{ + LeftExpr: expr, + Operation: TokenKind(op), + RightExpr: rightExpr, + }, nil + case p.matchKeyword(KeywordGlobal): + _ = p.lexer.consumeToken() + if p.consumeKeyword(KeywordIn) != nil { + return nil, fmt.Errorf("expected IN after GLOBAL, got %s", p.lastTokenKind()) + } + rightExpr, err := p.parseSubExpr(p.Pos(), precedence) + if err != nil { + return nil, err + } + return &BinaryOperation{ + LeftExpr: expr, + Operation: "GLOBAL IN", + RightExpr: rightExpr, + }, nil + + case p.matchKeyword(KeywordNot): + _ = p.lexer.consumeToken() + switch { + case p.matchKeyword(KeywordIn): + case p.matchKeyword(KeywordLike): + case p.matchKeyword(KeywordIlike): + case p.matchKeyword(KeywordBetween): + default: + return nil, fmt.Errorf("expected IN, LIKE, ILIKE or BETWEEN after NOT, got %s", p.lastTokenKind()) + } + op := p.last().ToString() + _ = p.lexer.consumeToken() + rightExpr, err := p.parseSubExpr(p.Pos(), precedence) + if err != nil { + return nil, err + } + return &BinaryOperation{ + LeftExpr: expr, + Operation: TokenKind("NOT " + op), + RightExpr: rightExpr, + }, nil + case p.matchTokenKind("["): + params, err := p.parseArrayParams(p.Pos()) + if err != nil { + return nil, err + } + return &ObjectParams{ + Object: expr, + Params: params, + }, nil + case p.matchTokenKind(opTypeQuery): + return p.parseTernaryExpr(expr) + case p.matchKeyword(KeywordIs): + _ = p.lexer.consumeToken() + isNotNull := p.tryConsumeKeyword(KeywordNot) != nil + if err := p.consumeKeyword(KeywordNull); err != nil { + return nil, err + } + if isNotNull { + return &IsNotNullExpr{ + IsPos: p.Pos(), + Expr: expr, + }, nil + } + return &IsNullExpr{ + IsPos: p.Pos(), + Expr: expr, + }, nil + default: + return nil, fmt.Errorf("unexpected token kind: %s", p.lastTokenKind()) + } +} + func (p *Parser) parseExpr(pos Pos) (Expr, error) { - orExpr, err := p.parseOrExpr(pos) + expr, err := p.parseSubExpr(pos, PrecedenceUnknown) if err != nil { - return orExpr, err + return nil, err } - switch { - case p.matchKeyword(KeywordAs): // syntax: columnExpr (alias | AS identifier) + if p.matchKeyword(KeywordAs) { + pos := p.Pos() _ = p.lexer.consumeToken() alias, err := p.parseIdent() if err != nil { return nil, err } return &AliasExpr{ - AliasPos: alias.Pos(), - Expr: orExpr, + AliasPos: pos, + Expr: expr, Alias: alias, }, nil } - return orExpr, nil + return expr, nil +} + +func (p *Parser) parseSubExpr(pos Pos, precedence int) (Expr, error) { + expr, err := p.parseUnaryExpr(pos) + if err != nil { + return nil, err + } + for !p.lexer.isEOF() { + nextPrecedence := p.getNextPrecedence(p.Pos()) + if nextPrecedence <= precedence { + return expr, nil + } + // parse binary operation + expr, err = p.parseInfix(expr, nextPrecedence) + if err != nil { + return nil, err + } + } + return expr, nil } func (p *Parser) parseOrExpr(pos Pos) (Expr, error) { @@ -365,7 +530,7 @@ func (p *Parser) parseColumnExpr(pos Pos) (Expr, error) { //nolint:funlen case p.matchTokenKind("("): if peek, _ := p.lexer.peekToken(); peek != nil { if peek.Kind == TokenKeyword && strings.EqualFold(peek.String, KeywordSelect) { - return p.parseSelectQuery(pos) + return p.parseSubQuery(pos) } } return p.parseFunctionParams(p.Pos()) diff --git a/parser/parser_query.go b/parser/parser_query.go index 376ec3d..47e8d4a 100644 --- a/parser/parser_query.go +++ b/parser/parser_query.go @@ -304,7 +304,7 @@ func (p *Parser) parseTableExpr(pos Pos) (*TableExpr, error) { } } case p.matchTokenKind("("): - expr, err = p.parseSelectQuery(p.Pos()) + expr, err = p.parseSubQuery(p.Pos()) default: return nil, errors.New("expect table name or subquery") } @@ -729,19 +729,23 @@ func (p *Parser) parseHavingClause(pos Pos) (*HavingClause, error) { }, nil } -func (p *Parser) parseSubQueryClause(pos Pos) (*SubQueryClause, error) { - if err := p.consumeKeyword(KeywordAs); err != nil { - return nil, err - } +func (p *Parser) parseSubQuery(pos Pos) (*SubQuery, error) { + + hasParen := p.tryConsumeTokenKind("(") != nil selectQuery, err := p.parseSelectQuery(p.Pos()) if err != nil { return nil, err } + if hasParen { + if _, err := p.consumeTokenKind(")"); err != nil { + return nil, err + } + } - return &SubQueryClause{ - AsPos: pos, - Select: selectQuery, + return &SubQuery{ + HasParen: hasParen, + Select: selectQuery, }, nil } diff --git a/parser/parser_table.go b/parser/parser_table.go index eb0fdab..86bdef1 100644 --- a/parser/parser_table.go +++ b/parser/parser_table.go @@ -158,8 +158,8 @@ func (p *Parser) parseCreateTable(pos Pos) (*CreateTable, error) { createTable.StatementEnd = engineExpr.End() } - if p.matchKeyword(KeywordAs) { - subQuery, err := p.parseSubQueryClause(p.Pos()) + if p.tryConsumeKeyword(KeywordAs) != nil { + subQuery, err := p.parseSubQuery(p.Pos()) if err != nil { return nil, err } diff --git a/parser/parser_view.go b/parser/parser_view.go index c4bd367..7b3f295 100644 --- a/parser/parser_view.go +++ b/parser/parser_view.go @@ -61,8 +61,8 @@ func (p *Parser) parseCreateMaterializedView(pos Pos) (*CreateMaterializedView, default: return nil, fmt.Errorf("unexpected token: %q, expected TO or ENGINE", p.lastTokenKind()) } - if p.matchKeyword(KeywordAs) { - subQuery, err := p.parseSubQueryClause(p.Pos()) + if p.tryConsumeKeyword(KeywordAs) != nil { + subQuery, err := p.parseSubQuery(p.Pos()) if err != nil { return nil, err } @@ -111,12 +111,14 @@ func (p *Parser) parseCreateView(pos Pos) (*CreateView, error) { createView.TableSchema = tableSchema } - subQuery, err := p.parseSubQueryClause(p.Pos()) - if err != nil { - return nil, err + if p.tryConsumeKeyword(KeywordAs) != nil { + subQuery, err := p.parseSubQuery(p.Pos()) + if err != nil { + return nil, err + } + createView.SubQuery = subQuery + createView.StatementEnd = subQuery.End() } - createView.SubQuery = subQuery - createView.StatementEnd = subQuery.End() return createView, nil } @@ -182,12 +184,14 @@ func (p *Parser) parseCreateLiveView(pos Pos) (*CreateLiveView, error) { createLiveView.TableSchema = tableSchema } - subQuery, err := p.parseSubQueryClause(p.Pos()) - if err != nil { - return nil, err + if p.tryConsumeKeyword(KeywordAs) != nil { + subQuery, err := p.parseSubQuery(p.Pos()) + if err != nil { + return nil, err + } + createLiveView.SubQuery = subQuery + createLiveView.StatementEnd = subQuery.End() } - createLiveView.SubQuery = subQuery - createLiveView.StatementEnd = subQuery.End() return createLiveView, nil } diff --git a/parser/testdata/ddl/format/bug_001.sql b/parser/testdata/ddl/format/bug_001.sql index 6d764cf..4339c0f 100644 --- a/parser/testdata/ddl/format/bug_001.sql +++ b/parser/testdata/ddl/format/bug_001.sql @@ -18,4 +18,4 @@ FROM db.table WHERE db.table.event = 'hello'; -- Format SQL: -CREATE MATERIALIZED VIEW IF NOT EXISTS db.table ON CLUSTER 'default_cluster' TO db.table_mv AS (SELECT event_ts, org_id, visitParamExtractString(properties, 'x') AS x, visitParamExtractString(properties, 'y') AS y, visitParamExtractString(properties, 'z') AS z, visitParamExtractString(properties, 'a') AS a, visitParamExtractString(properties, 'b') AS b, visitParamExtractString(properties, 'c') AS c, visitParamExtractString(properties, 'd') AS d, visitParamExtractInt(properties, 'e') AS e, visitParamExtractInt(properties, 'f') AS f FROM db.table WHERE db.table.event = 'hello'); +CREATE MATERIALIZED VIEW IF NOT EXISTS db.table ON CLUSTER 'default_cluster' TO db.table_mv AS SELECT event_ts, org_id, visitParamExtractString(properties, 'x') AS x, visitParamExtractString(properties, 'y') AS y, visitParamExtractString(properties, 'z') AS z, visitParamExtractString(properties, 'a') AS a, visitParamExtractString(properties, 'b') AS b, visitParamExtractString(properties, 'c') AS c, visitParamExtractString(properties, 'd') AS d, visitParamExtractInt(properties, 'e') AS e, visitParamExtractInt(properties, 'f') AS f FROM db.table WHERE db.table.event = 'hello'; diff --git a/parser/testdata/ddl/format/create_live_view_basic.sql b/parser/testdata/ddl/format/create_live_view_basic.sql index f5d2299..17e5101 100644 --- a/parser/testdata/ddl/format/create_live_view_basic.sql +++ b/parser/testdata/ddl/format/create_live_view_basic.sql @@ -5,4 +5,4 @@ AS SELECT id FROM my_table; -- Format SQL: -CREATE LIVE VIEW my_live_view WITH TIMEOUT 10 TO my_destination (id String) AS (SELECT id FROM my_table); +CREATE LIVE VIEW my_live_view WITH TIMEOUT 10 TO my_destination (id String) AS SELECT id FROM my_table; diff --git a/parser/testdata/ddl/format/create_materialized_view_basic.sql b/parser/testdata/ddl/format/create_materialized_view_basic.sql index cd5b040..50721ab 100644 --- a/parser/testdata/ddl/format/create_materialized_view_basic.sql +++ b/parser/testdata/ddl/format/create_materialized_view_basic.sql @@ -22,4 +22,4 @@ WHERE infra_bm.table_name1.event = 'test-event'; -- Format SQL: -CREATE MATERIALIZED VIEW infra_bm.view_name ON CLUSTER 'default_cluster' TO infra_bm.table_name (`f1` DateTime64(3), `f2` String, `f3` String, `f4` String, `f5` String, `f6` Int64) AS (SELECT f1, f2, visitParamExtractString(properties, 'f3') AS f3, visitParamExtractString(properties, 'f4') AS f4, visitParamExtractString(properties, 'f5') AS f5, visitParamExtractInt(properties, 'f6') AS f6 FROM infra_bm.table_name1 WHERE infra_bm.table_name1.event = 'test-event'); +CREATE MATERIALIZED VIEW infra_bm.view_name ON CLUSTER 'default_cluster' TO infra_bm.table_name (`f1` DateTime64(3), `f2` String, `f3` String, `f4` String, `f5` String, `f6` Int64) AS SELECT f1, f2, visitParamExtractString(properties, 'f3') AS f3, visitParamExtractString(properties, 'f4') AS f4, visitParamExtractString(properties, 'f5') AS f5, visitParamExtractInt(properties, 'f6') AS f6 FROM infra_bm.table_name1 WHERE infra_bm.table_name1.event = 'test-event'; diff --git a/parser/testdata/ddl/format/create_materialized_view_with_empty_table_schema.sql b/parser/testdata/ddl/format/create_materialized_view_with_empty_table_schema.sql index 99183ab..0cbf223 100644 --- a/parser/testdata/ddl/format/create_materialized_view_with_empty_table_schema.sql +++ b/parser/testdata/ddl/format/create_materialized_view_with_empty_table_schema.sql @@ -16,4 +16,4 @@ from where rn = 1; -- Format SQL: -CREATE MATERIALIZED VIEW test.t0 ON CLUSTER default_cluster ENGINE = ReplicatedAggregatingMergeTree('/clickhouse/{layer}-{shard}/test/t0', '{replica}') PARTITION BY toYYYYMM(f0) ORDER BY (f0) POPULATE AS (SELECT f0, f1, f2, coalesce(f0, f1) AS f333 FROM (SELECT f0, f1, f2, ROW_NUMBER() OVER ( PARTITION BY f0 ORDER BY coalesce(f1, f2)) AS rn FROM test.t WHERE f3 IN ('foo', 'bar', 'test') AND env = 'test') AS tmp WHERE rn = 1); +CREATE MATERIALIZED VIEW test.t0 ON CLUSTER default_cluster ENGINE = ReplicatedAggregatingMergeTree('/clickhouse/{layer}-{shard}/test/t0', '{replica}') PARTITION BY toYYYYMM(f0) ORDER BY (f0) POPULATE AS SELECT f0, f1, f2, coalesce(f0, f1) AS f333 FROM (SELECT f0, f1, f2, ROW_NUMBER() OVER ( PARTITION BY f0 ORDER BY coalesce(f1, f2)) AS rn FROM test.t WHERE f3 IN ('foo', 'bar', 'test') AND env = 'test') AS tmp WHERE rn = 1; diff --git a/parser/testdata/ddl/format/create_view_basic.sql b/parser/testdata/ddl/format/create_view_basic.sql index 408ab4f..b1b3fd6 100644 --- a/parser/testdata/ddl/format/create_view_basic.sql +++ b/parser/testdata/ddl/format/create_view_basic.sql @@ -8,4 +8,4 @@ FROM my_table; -- Format SQL: -CREATE VIEW IF NOT EXISTS my_view (col1 String, col2 String) AS (SELECT id, name FROM my_table); +CREATE VIEW IF NOT EXISTS my_view (col1 String, col2 String) AS SELECT id, name FROM my_table; diff --git a/parser/testdata/ddl/output/attach_table_basic.sql.golden.json b/parser/testdata/ddl/output/attach_table_basic.sql.golden.json index 3936530..9a5c523 100644 --- a/parser/testdata/ddl/output/attach_table_basic.sql.golden.json +++ b/parser/testdata/ddl/output/attach_table_basic.sql.golden.json @@ -330,7 +330,7 @@ "Literal": "/clickhouse/tables/{layer}-{shard}/test/events_local" }, { - "LiteralPos": 315, + "LiteralPos": 259, "LiteralEnd": 324, "Literal": "{replica}" } @@ -453,6 +453,7 @@ ] } }, + "Alias": null, "SubQuery": null, "HasTemporary": false } diff --git a/parser/testdata/ddl/output/bug_001.sql.golden.json b/parser/testdata/ddl/output/bug_001.sql.golden.json index 6546f99..9f47e00 100644 --- a/parser/testdata/ddl/output/bug_001.sql.golden.json +++ b/parser/testdata/ddl/output/bug_001.sql.golden.json @@ -45,7 +45,7 @@ "TableSchema": null }, "SubQuery": { - "AsPos": 104, + "HasParen": false, "Select": { "SelectPos": 107, "StatementEnd": 635, @@ -94,7 +94,7 @@ "NameEnd": 178 }, { - "LiteralPos": 181, + "LiteralPos": 168, "LiteralEnd": 182, "Literal": "x" } @@ -103,7 +103,7 @@ "ColumnArgList": null } }, - "AliasPos": 188, + "AliasPos": 185, "Alias": { "Name": "x", "QuoteType": 1, @@ -137,7 +137,7 @@ "NameEnd": 229 }, { - "LiteralPos": 232, + "LiteralPos": 219, "LiteralEnd": 233, "Literal": "y" } @@ -146,7 +146,7 @@ "ColumnArgList": null } }, - "AliasPos": 239, + "AliasPos": 236, "Alias": { "Name": "y", "QuoteType": 1, @@ -180,7 +180,7 @@ "NameEnd": 280 }, { - "LiteralPos": 283, + "LiteralPos": 270, "LiteralEnd": 284, "Literal": "z" } @@ -189,7 +189,7 @@ "ColumnArgList": null } }, - "AliasPos": 290, + "AliasPos": 287, "Alias": { "Name": "z", "QuoteType": 1, @@ -223,7 +223,7 @@ "NameEnd": 331 }, { - "LiteralPos": 334, + "LiteralPos": 321, "LiteralEnd": 335, "Literal": "a" } @@ -232,7 +232,7 @@ "ColumnArgList": null } }, - "AliasPos": 341, + "AliasPos": 338, "Alias": { "Name": "a", "QuoteType": 1, @@ -266,7 +266,7 @@ "NameEnd": 382 }, { - "LiteralPos": 385, + "LiteralPos": 372, "LiteralEnd": 386, "Literal": "b" } @@ -275,7 +275,7 @@ "ColumnArgList": null } }, - "AliasPos": 392, + "AliasPos": 389, "Alias": { "Name": "b", "QuoteType": 1, @@ -309,7 +309,7 @@ "NameEnd": 433 }, { - "LiteralPos": 436, + "LiteralPos": 423, "LiteralEnd": 437, "Literal": "c" } @@ -318,7 +318,7 @@ "ColumnArgList": null } }, - "AliasPos": 443, + "AliasPos": 440, "Alias": { "Name": "c", "QuoteType": 1, @@ -352,7 +352,7 @@ "NameEnd": 484 }, { - "LiteralPos": 487, + "LiteralPos": 474, "LiteralEnd": 488, "Literal": "d" } @@ -361,7 +361,7 @@ "ColumnArgList": null } }, - "AliasPos": 494, + "AliasPos": 491, "Alias": { "Name": "d", "QuoteType": 1, @@ -395,7 +395,7 @@ "NameEnd": 532 }, { - "LiteralPos": 535, + "LiteralPos": 522, "LiteralEnd": 536, "Literal": "e" } @@ -404,7 +404,7 @@ "ColumnArgList": null } }, - "AliasPos": 542, + "AliasPos": 539, "Alias": { "Name": "e", "QuoteType": 1, @@ -438,7 +438,7 @@ "NameEnd": 580 }, { - "LiteralPos": 583, + "LiteralPos": 570, "LiteralEnd": 584, "Literal": "f" } @@ -447,7 +447,7 @@ "ColumnArgList": null } }, - "AliasPos": 590, + "AliasPos": 587, "Alias": { "Name": "f", "QuoteType": 1, diff --git a/parser/testdata/ddl/output/create_distributed_table.sql.golden.json b/parser/testdata/ddl/output/create_distributed_table.sql.golden.json index c856202..2e4e598 100644 --- a/parser/testdata/ddl/output/create_distributed_table.sql.golden.json +++ b/parser/testdata/ddl/output/create_distributed_table.sql.golden.json @@ -126,6 +126,7 @@ }, "OrderBy": null }, + "Alias": null, "SubQuery": null, "HasTemporary": false } diff --git a/parser/testdata/ddl/output/create_live_view_basic.sql.golden.json b/parser/testdata/ddl/output/create_live_view_basic.sql.golden.json index 19b6e6c..82c4c5c 100644 --- a/parser/testdata/ddl/output/create_live_view_basic.sql.golden.json +++ b/parser/testdata/ddl/output/create_live_view_basic.sql.golden.json @@ -76,7 +76,7 @@ } }, "SubQuery": { - "AsPos": 75, + "HasParen": false, "Select": { "SelectPos": 78, "StatementEnd": 101, diff --git a/parser/testdata/ddl/output/create_materialized_view_basic.sql.golden.json b/parser/testdata/ddl/output/create_materialized_view_basic.sql.golden.json index a7da2e6..2bdda6b 100644 --- a/parser/testdata/ddl/output/create_materialized_view_basic.sql.golden.json +++ b/parser/testdata/ddl/output/create_materialized_view_basic.sql.golden.json @@ -242,7 +242,7 @@ } }, "SubQuery": { - "AsPos": 205, + "HasParen": false, "Select": { "SelectPos": 208, "StatementEnd": 537, @@ -291,7 +291,7 @@ "NameEnd": 271 }, { - "LiteralPos": 274, + "LiteralPos": 261, "LiteralEnd": 276, "Literal": "f3" } @@ -300,7 +300,7 @@ "ColumnArgList": null } }, - "AliasPos": 284, + "AliasPos": 281, "Alias": { "Name": "f3", "QuoteType": 1, @@ -334,7 +334,7 @@ "NameEnd": 329 }, { - "LiteralPos": 332, + "LiteralPos": 319, "LiteralEnd": 334, "Literal": "f4" } @@ -343,7 +343,7 @@ "ColumnArgList": null } }, - "AliasPos": 345, + "AliasPos": 342, "Alias": { "Name": "f4", "QuoteType": 1, @@ -377,7 +377,7 @@ "NameEnd": 390 }, { - "LiteralPos": 393, + "LiteralPos": 380, "LiteralEnd": 395, "Literal": "f5" } @@ -386,7 +386,7 @@ "ColumnArgList": null } }, - "AliasPos": 404, + "AliasPos": 401, "Alias": { "Name": "f5", "QuoteType": 1, @@ -420,7 +420,7 @@ "NameEnd": 443 }, { - "LiteralPos": 446, + "LiteralPos": 433, "LiteralEnd": 448, "Literal": "f6" } @@ -429,7 +429,7 @@ "ColumnArgList": null } }, - "AliasPos": 454, + "AliasPos": 451, "Alias": { "Name": "f6", "QuoteType": 1, diff --git a/parser/testdata/ddl/output/create_materialized_view_with_empty_table_schema.sql.golden.json b/parser/testdata/ddl/output/create_materialized_view_with_empty_table_schema.sql.golden.json index 3dab6e6..d06912b 100644 --- a/parser/testdata/ddl/output/create_materialized_view_with_empty_table_schema.sql.golden.json +++ b/parser/testdata/ddl/output/create_materialized_view_with_empty_table_schema.sql.golden.json @@ -44,7 +44,7 @@ "Literal": "/clickhouse/{layer}-{shard}/test/t0" }, { - "LiteralPos": 140, + "LiteralPos": 101, "LiteralEnd": 149, "Literal": "{replica}" } @@ -123,7 +123,7 @@ }, "Destination": null, "SubQuery": { - "AsPos": 201, + "HasParen": false, "Select": { "SelectPos": 204, "StatementEnd": 460, @@ -191,7 +191,7 @@ "ColumnArgList": null } }, - "AliasPos": 239, + "AliasPos": 236, "Alias": { "Name": "f333", "QuoteType": 1, @@ -211,240 +211,243 @@ "Alias": null, "Expr": { "Expr": { - "SelectPos": 254, - "StatementEnd": 433, - "With": null, - "Top": null, - "SelectItems": [ - { - "Expr": { - "Name": "f0", - "QuoteType": 1, - "NamePos": 270, - "NameEnd": 272 + "HasParen": true, + "Select": { + "SelectPos": 254, + "StatementEnd": 433, + "With": null, + "Top": null, + "SelectItems": [ + { + "Expr": { + "Name": "f0", + "QuoteType": 1, + "NamePos": 270, + "NameEnd": 272 + }, + "Modifiers": [] }, - "Modifiers": [] - }, - { - "Expr": { - "Name": "f1", - "QuoteType": 1, - "NamePos": 273, - "NameEnd": 275 + { + "Expr": { + "Name": "f1", + "QuoteType": 1, + "NamePos": 273, + "NameEnd": 275 + }, + "Modifiers": [] }, - "Modifiers": [] - }, - { - "Expr": { - "Name": "f2", - "QuoteType": 1, - "NamePos": 276, - "NameEnd": 278 + { + "Expr": { + "Name": "f2", + "QuoteType": 1, + "NamePos": 276, + "NameEnd": 278 + }, + "Modifiers": [] }, - "Modifiers": [] - }, - { - "Expr": { + { "Expr": { - "Function": { - "Name": { - "Name": "ROW_NUMBER", - "QuoteType": 1, - "NamePos": 289, - "NameEnd": 299 + "Expr": { + "Function": { + "Name": { + "Name": "ROW_NUMBER", + "QuoteType": 1, + "NamePos": 289, + "NameEnd": 299 + }, + "Params": { + "LeftParenPos": 299, + "RightParenPos": 300, + "Items": { + "ListPos": 300, + "ListEnd": 300, + "HasDistinct": false, + "Items": [] + }, + "ColumnArgList": null + } }, - "Params": { - "LeftParenPos": 299, - "RightParenPos": 300, - "Items": { - "ListPos": 300, - "ListEnd": 300, - "HasDistinct": false, - "Items": [] + "OverPos": 302, + "OverExpr": { + "LeftParenPos": 306, + "RightParenPos": 347, + "PartitionBy": { + "PartitionPos": 306, + "Expr": { + "ListPos": 320, + "ListEnd": 322, + "HasDistinct": false, + "Items": [ + { + "Name": "f0", + "QuoteType": 1, + "NamePos": 320, + "NameEnd": 322 + } + ] + } }, - "ColumnArgList": null - } - }, - "OverPos": 302, - "OverExpr": { - "LeftParenPos": 306, - "RightParenPos": 347, - "PartitionBy": { - "PartitionPos": 306, - "Expr": { - "ListPos": 320, - "ListEnd": 322, - "HasDistinct": false, + "OrderBy": { + "OrderPos": 323, + "ListEnd": 346, "Items": [ { - "Name": "f0", - "QuoteType": 1, - "NamePos": 320, - "NameEnd": 322 + "OrderPos": 323, + "Expr": { + "Name": { + "Name": "coalesce", + "QuoteType": 1, + "NamePos": 332, + "NameEnd": 340 + }, + "Params": { + "LeftParenPos": 340, + "RightParenPos": 346, + "Items": { + "ListPos": 341, + "ListEnd": 346, + "HasDistinct": false, + "Items": [ + { + "Name": "f1", + "QuoteType": 1, + "NamePos": 341, + "NameEnd": 343 + }, + { + "Name": "f2", + "QuoteType": 1, + "NamePos": 344, + "NameEnd": 346 + } + ] + }, + "ColumnArgList": null + } + }, + "Direction": "None" } ] - } + }, + "Frame": null + } + }, + "AliasPos": 349, + "Alias": { + "Name": "rn", + "QuoteType": 1, + "NamePos": 352, + "NameEnd": 354 + } + }, + "Modifiers": [] + } + ], + "From": { + "FromPos": 360, + "Expr": { + "Table": { + "TablePos": 365, + "TableEnd": 371, + "Alias": null, + "Expr": { + "Database": { + "Name": "test", + "QuoteType": 1, + "NamePos": 365, + "NameEnd": 369 }, - "OrderBy": { - "OrderPos": 323, - "ListEnd": 346, + "Table": { + "Name": "t", + "QuoteType": 1, + "NamePos": 370, + "NameEnd": 371 + } + }, + "HasFinal": false + }, + "StatementEnd": 371, + "SampleRatio": null, + "HasFinal": false + } + }, + "ArrayJoin": null, + "Window": null, + "Prewhere": null, + "Where": { + "WherePos": 377, + "Expr": { + "LeftExpr": { + "LeftExpr": { + "Name": "f3", + "QuoteType": 1, + "NamePos": 383, + "NameEnd": 385 + }, + "Operation": "IN", + "RightExpr": { + "LeftParenPos": 389, + "RightParenPos": 410, + "Items": { + "ListPos": 391, + "ListEnd": 409, + "HasDistinct": false, "Items": [ { - "OrderPos": 323, - "Expr": { - "Name": { - "Name": "coalesce", - "QuoteType": 1, - "NamePos": 332, - "NameEnd": 340 - }, - "Params": { - "LeftParenPos": 340, - "RightParenPos": 346, - "Items": { - "ListPos": 341, - "ListEnd": 346, - "HasDistinct": false, - "Items": [ - { - "Name": "f1", - "QuoteType": 1, - "NamePos": 341, - "NameEnd": 343 - }, - { - "Name": "f2", - "QuoteType": 1, - "NamePos": 344, - "NameEnd": 346 - } - ] - }, - "ColumnArgList": null - } - }, - "Direction": "None" + "LiteralPos": 391, + "LiteralEnd": 394, + "Literal": "foo" + }, + { + "LiteralPos": 391, + "LiteralEnd": 401, + "Literal": "bar" + }, + { + "LiteralPos": 391, + "LiteralEnd": 409, + "Literal": "test" } ] }, - "Frame": null - } - }, - "AliasPos": 352, - "Alias": { - "Name": "rn", - "QuoteType": 1, - "NamePos": 352, - "NameEnd": 354 - } - }, - "Modifiers": [] - } - ], - "From": { - "FromPos": 360, - "Expr": { - "Table": { - "TablePos": 365, - "TableEnd": 371, - "Alias": null, - "Expr": { - "Database": { - "Name": "test", - "QuoteType": 1, - "NamePos": 365, - "NameEnd": 369 + "ColumnArgList": null }, - "Table": { - "Name": "t", - "QuoteType": 1, - "NamePos": 370, - "NameEnd": 371 - } + "HasGlobal": false, + "HasNot": false }, - "HasFinal": false - }, - "StatementEnd": 371, - "SampleRatio": null, - "HasFinal": false - } - }, - "ArrayJoin": null, - "Window": null, - "Prewhere": null, - "Where": { - "WherePos": 377, - "Expr": { - "LeftExpr": { - "LeftExpr": { - "Name": "f3", - "QuoteType": 1, - "NamePos": 383, - "NameEnd": 385 - }, - "Operation": "IN", + "Operation": "AND", "RightExpr": { - "LeftParenPos": 389, - "RightParenPos": 410, - "Items": { - "ListPos": 391, - "ListEnd": 409, - "HasDistinct": false, - "Items": [ - { - "LiteralPos": 391, - "LiteralEnd": 394, - "Literal": "foo" - }, - { - "LiteralPos": 398, - "LiteralEnd": 401, - "Literal": "bar" - }, - { - "LiteralPos": 405, - "LiteralEnd": 409, - "Literal": "test" - } - ] + "LeftExpr": { + "Name": "env", + "QuoteType": 1, + "NamePos": 423, + "NameEnd": 426 }, - "ColumnArgList": null - }, - "HasGlobal": false, - "HasNot": false - }, - "Operation": "AND", - "RightExpr": { - "LeftExpr": { - "Name": "env", - "QuoteType": 1, - "NamePos": 423, - "NameEnd": 426 - }, - "Operation": "=", - "RightExpr": { - "LiteralPos": 429, - "LiteralEnd": 433, - "Literal": "test" + "Operation": "=", + "RightExpr": { + "LiteralPos": 429, + "LiteralEnd": 433, + "Literal": "test" + }, + "HasGlobal": false, + "HasNot": false }, "HasGlobal": false, "HasNot": false - }, - "HasGlobal": false, - "HasNot": false - } - }, - "GroupBy": null, - "WithTotal": false, - "Having": null, - "OrderBy": null, - "LimitBy": null, - "Limit": null, - "Settings": null, - "Format": null, - "UnionAll": null, - "UnionDistinct": null, - "Except": null + } + }, + "GroupBy": null, + "WithTotal": false, + "Having": null, + "OrderBy": null, + "LimitBy": null, + "Limit": null, + "Settings": null, + "Format": null, + "UnionAll": null, + "UnionDistinct": null, + "Except": null + } }, "AliasPos": 444, "Alias": { diff --git a/parser/testdata/ddl/output/create_table_basic.sql.golden.json b/parser/testdata/ddl/output/create_table_basic.sql.golden.json index c1e268d..aaad673 100644 --- a/parser/testdata/ddl/output/create_table_basic.sql.golden.json +++ b/parser/testdata/ddl/output/create_table_basic.sql.golden.json @@ -806,6 +806,7 @@ ] } }, + "Alias": null, "SubQuery": null, "HasTemporary": false } diff --git a/parser/testdata/ddl/output/create_table_with_codec_delta.sql.golden.json b/parser/testdata/ddl/output/create_table_with_codec_delta.sql.golden.json index b3fa45a..8ba95d7 100644 --- a/parser/testdata/ddl/output/create_table_with_codec_delta.sql.golden.json +++ b/parser/testdata/ddl/output/create_table_with_codec_delta.sql.golden.json @@ -443,7 +443,7 @@ "Literal": "/root/test_local" }, { - "LiteralPos": 427, + "LiteralPos": 407, "LiteralEnd": 436, "Literal": "{replica}" } @@ -728,6 +728,7 @@ ] } }, + "Alias": null, "SubQuery": null, "HasTemporary": false } diff --git a/parser/testdata/ddl/output/create_table_with_index.sql.golden.json b/parser/testdata/ddl/output/create_table_with_index.sql.golden.json index e9ec0d2..a68a187 100644 --- a/parser/testdata/ddl/output/create_table_with_index.sql.golden.json +++ b/parser/testdata/ddl/output/create_table_with_index.sql.golden.json @@ -488,7 +488,7 @@ "Literal": "/root/test_local" }, { - "LiteralPos": 533, + "LiteralPos": 513, "LiteralEnd": 542, "Literal": "{replica}" } @@ -773,6 +773,7 @@ ] } }, + "Alias": null, "SubQuery": null, "HasTemporary": false } diff --git a/parser/testdata/ddl/output/create_table_with_keyword_partition_by.sql.golden.json b/parser/testdata/ddl/output/create_table_with_keyword_partition_by.sql.golden.json index 1bd8bf8..ec950fa 100644 --- a/parser/testdata/ddl/output/create_table_with_keyword_partition_by.sql.golden.json +++ b/parser/testdata/ddl/output/create_table_with_keyword_partition_by.sql.golden.json @@ -233,6 +233,7 @@ ] } }, + "Alias": null, "SubQuery": null, "HasTemporary": false } diff --git a/parser/testdata/ddl/output/create_table_with_nullable.sql.golden.json b/parser/testdata/ddl/output/create_table_with_nullable.sql.golden.json index 10c5071..b8737f3 100644 --- a/parser/testdata/ddl/output/create_table_with_nullable.sql.golden.json +++ b/parser/testdata/ddl/output/create_table_with_nullable.sql.golden.json @@ -414,6 +414,7 @@ ] } }, + "Alias": null, "SubQuery": null, "HasTemporary": false } diff --git a/parser/testdata/ddl/output/create_table_with_on_clsuter.sql.golden.json b/parser/testdata/ddl/output/create_table_with_on_clsuter.sql.golden.json index 3936530..9a5c523 100644 --- a/parser/testdata/ddl/output/create_table_with_on_clsuter.sql.golden.json +++ b/parser/testdata/ddl/output/create_table_with_on_clsuter.sql.golden.json @@ -330,7 +330,7 @@ "Literal": "/clickhouse/tables/{layer}-{shard}/test/events_local" }, { - "LiteralPos": 315, + "LiteralPos": 259, "LiteralEnd": 324, "Literal": "{replica}" } @@ -453,6 +453,7 @@ ] } }, + "Alias": null, "SubQuery": null, "HasTemporary": false } diff --git a/parser/testdata/ddl/output/create_table_with_sample_by.sql.golden.json b/parser/testdata/ddl/output/create_table_with_sample_by.sql.golden.json index 69bc028..72b6859 100644 --- a/parser/testdata/ddl/output/create_table_with_sample_by.sql.golden.json +++ b/parser/testdata/ddl/output/create_table_with_sample_by.sql.golden.json @@ -141,7 +141,7 @@ "Literal": "/clickhouse/tables/{layer}/{shard}/default/test" }, { - "LiteralPos": 207, + "LiteralPos": 156, "LiteralEnd": 216, "Literal": "{replica}" } @@ -278,6 +278,7 @@ ] } }, + "Alias": null, "SubQuery": null, "HasTemporary": false } diff --git a/parser/testdata/ddl/output/create_table_with_uuid.sql.golden.json b/parser/testdata/ddl/output/create_table_with_uuid.sql.golden.json index 1e26479..e711af4 100644 --- a/parser/testdata/ddl/output/create_table_with_uuid.sql.golden.json +++ b/parser/testdata/ddl/output/create_table_with_uuid.sql.golden.json @@ -336,7 +336,7 @@ "Literal": "/clickhouse/tables/{layer}-{shard}/test/events_local" }, { - "LiteralPos": 327, + "LiteralPos": 271, "LiteralEnd": 336, "Literal": "{replica}" } @@ -459,6 +459,7 @@ ] } }, + "Alias": null, "SubQuery": null, "HasTemporary": false } diff --git a/parser/testdata/ddl/output/create_view_basic.sql.golden.json b/parser/testdata/ddl/output/create_view_basic.sql.golden.json index 333d47d..8b6023c 100644 --- a/parser/testdata/ddl/output/create_view_basic.sql.golden.json +++ b/parser/testdata/ddl/output/create_view_basic.sql.golden.json @@ -83,7 +83,7 @@ "TableFunction": null }, "SubQuery": { - "AsPos": 60, + "HasParen": false, "Select": { "SelectPos": 63, "StatementEnd": 104, diff --git a/parser/testdata/ddl/output/create_view_on_cluster_with_uuid.sql.golden.json b/parser/testdata/ddl/output/create_view_on_cluster_with_uuid.sql.golden.json index 3757f88..50a8e9d 100644 --- a/parser/testdata/ddl/output/create_view_on_cluster_with_uuid.sql.golden.json +++ b/parser/testdata/ddl/output/create_view_on_cluster_with_uuid.sql.golden.json @@ -34,7 +34,7 @@ }, "TableSchema": null, "SubQuery": { - "AsPos": 131, + "HasParen": true, "Select": { "SelectPos": 140, "StatementEnd": 199, diff --git a/parser/testdata/query/format/query_with_expr_compare.sql b/parser/testdata/query/format/query_with_expr_compare.sql new file mode 100644 index 0000000..11a755e --- /dev/null +++ b/parser/testdata/query/format/query_with_expr_compare.sql @@ -0,0 +1,10 @@ +-- Origin SQL: +SELECT date, path, splitByChar('/', path)[2] AS path_b +FROM( + SELECT 'pathA/pathB/pathC' AS path, '2024-09-10' AS date + ) +WHERE toDate(date) = '2024-09-01' AND '2024-09-30' + AND splitByChar('/', path)[1] = 'pathA' + +-- Format SQL: +SELECT date, path, splitByChar('/', path)[2] AS path_b FROM (SELECT 'pathA/pathB/pathC' AS path, '2024-09-10' AS date) WHERE toDate(date) = '2024-09-01' AND '2024-09-30' AND splitByChar('/', path)[1] = 'pathA'; diff --git a/parser/testdata/query/output/query_with_expr_compare.sql.golden.json b/parser/testdata/query/output/query_with_expr_compare.sql.golden.json new file mode 100644 index 0000000..c78533f --- /dev/null +++ b/parser/testdata/query/output/query_with_expr_compare.sql.golden.json @@ -0,0 +1,293 @@ +[ + { + "SelectPos": 0, + "StatementEnd": 219, + "With": null, + "Top": null, + "SelectItems": [ + { + "Expr": { + "Name": "date", + "QuoteType": 1, + "NamePos": 7, + "NameEnd": 11 + }, + "Modifiers": [] + }, + { + "Expr": { + "Name": "path", + "QuoteType": 1, + "NamePos": 13, + "NameEnd": 17 + }, + "Modifiers": [] + }, + { + "Expr": { + "Expr": { + "Object": { + "Name": { + "Name": "splitByChar", + "QuoteType": 1, + "NamePos": 19, + "NameEnd": 30 + }, + "Params": { + "LeftParenPos": 30, + "RightParenPos": 40, + "Items": { + "ListPos": 32, + "ListEnd": 40, + "HasDistinct": false, + "Items": [ + { + "LiteralPos": 32, + "LiteralEnd": 33, + "Literal": "/" + }, + { + "Name": "path", + "QuoteType": 1, + "NamePos": 36, + "NameEnd": 40 + } + ] + }, + "ColumnArgList": null + } + }, + "Params": { + "LeftBracketPos": 41, + "RightBracketPos": 43, + "Items": { + "ListPos": 42, + "ListEnd": 43, + "HasDistinct": false, + "Items": [ + { + "NumPos": 42, + "NumEnd": 43, + "Literal": "2", + "Base": 10 + } + ] + } + } + }, + "AliasPos": 45, + "Alias": { + "Name": "path_b", + "QuoteType": 1, + "NamePos": 48, + "NameEnd": 54 + } + }, + "Modifiers": [] + } + ], + "From": { + "FromPos": 55, + "Expr": { + "Table": { + "TablePos": 59, + "TableEnd": 121, + "Alias": null, + "Expr": { + "HasParen": true, + "Select": { + "SelectPos": 65, + "StatementEnd": 121, + "With": null, + "Top": null, + "SelectItems": [ + { + "Expr": { + "Expr": { + "LiteralPos": 73, + "LiteralEnd": 90, + "Literal": "pathA/pathB/pathC" + }, + "AliasPos": 92, + "Alias": { + "Name": "path", + "QuoteType": 1, + "NamePos": 95, + "NameEnd": 99 + } + }, + "Modifiers": [] + }, + { + "Expr": { + "Expr": { + "LiteralPos": 102, + "LiteralEnd": 112, + "Literal": "2024-09-10" + }, + "AliasPos": 114, + "Alias": { + "Name": "date", + "QuoteType": 1, + "NamePos": 117, + "NameEnd": 121 + } + }, + "Modifiers": [] + } + ], + "From": null, + "ArrayJoin": null, + "Window": null, + "Prewhere": null, + "Where": null, + "GroupBy": null, + "WithTotal": false, + "Having": null, + "OrderBy": null, + "LimitBy": null, + "Limit": null, + "Settings": null, + "Format": null, + "UnionAll": null, + "UnionDistinct": null, + "Except": null + } + }, + "HasFinal": false + }, + "StatementEnd": 121, + "SampleRatio": null, + "HasFinal": false + } + }, + "ArrayJoin": null, + "Window": null, + "Prewhere": null, + "Where": { + "WherePos": 128, + "Expr": { + "LeftExpr": { + "LeftExpr": { + "LeftExpr": { + "Name": { + "Name": "toDate", + "QuoteType": 1, + "NamePos": 134, + "NameEnd": 140 + }, + "Params": { + "LeftParenPos": 140, + "RightParenPos": 145, + "Items": { + "ListPos": 141, + "ListEnd": 145, + "HasDistinct": false, + "Items": [ + { + "Name": "date", + "QuoteType": 1, + "NamePos": 141, + "NameEnd": 145 + } + ] + }, + "ColumnArgList": null + } + }, + "Operation": "=", + "RightExpr": { + "LiteralPos": 150, + "LiteralEnd": 160, + "Literal": "2024-09-01" + }, + "HasGlobal": false, + "HasNot": false + }, + "Operation": "AND", + "RightExpr": { + "LiteralPos": 167, + "LiteralEnd": 177, + "Literal": "2024-09-30" + }, + "HasGlobal": false, + "HasNot": false + }, + "Operation": "AND", + "RightExpr": { + "LeftExpr": { + "Object": { + "Name": { + "Name": "splitByChar", + "QuoteType": 1, + "NamePos": 185, + "NameEnd": 196 + }, + "Params": { + "LeftParenPos": 196, + "RightParenPos": 206, + "Items": { + "ListPos": 198, + "ListEnd": 206, + "HasDistinct": false, + "Items": [ + { + "LiteralPos": 198, + "LiteralEnd": 199, + "Literal": "/" + }, + { + "Name": "path", + "QuoteType": 1, + "NamePos": 202, + "NameEnd": 206 + } + ] + }, + "ColumnArgList": null + } + }, + "Params": { + "LeftBracketPos": 207, + "RightBracketPos": 209, + "Items": { + "ListPos": 208, + "ListEnd": 209, + "HasDistinct": false, + "Items": [ + { + "NumPos": 208, + "NumEnd": 209, + "Literal": "1", + "Base": 10 + } + ] + } + } + }, + "Operation": "=", + "RightExpr": { + "LiteralPos": 214, + "LiteralEnd": 219, + "Literal": "pathA" + }, + "HasGlobal": false, + "HasNot": false + }, + "HasGlobal": false, + "HasNot": false + } + }, + "GroupBy": null, + "WithTotal": false, + "Having": null, + "OrderBy": null, + "LimitBy": null, + "Limit": null, + "Settings": null, + "Format": null, + "UnionAll": null, + "UnionDistinct": null, + "Except": null + } +] \ No newline at end of file diff --git a/parser/testdata/query/output/select_cast.sql.golden.json b/parser/testdata/query/output/select_cast.sql.golden.json index 9bb5cbe..1b4e4a5 100644 --- a/parser/testdata/query/output/select_cast.sql.golden.json +++ b/parser/testdata/query/output/select_cast.sql.golden.json @@ -26,7 +26,7 @@ } } }, - "AliasPos": 29, + "AliasPos": 26, "Alias": { "Name": "value", "QuoteType": 1, @@ -78,7 +78,7 @@ "Literal": "Float64" } }, - "AliasPos": 65, + "AliasPos": 62, "Alias": { "Name": "value", "QuoteType": 1, @@ -129,7 +129,7 @@ "Literal": "1", "Base": 10 }, - "AliasPos": 85, + "AliasPos": 82, "Alias": { "Name": "Float64", "QuoteType": 1, @@ -141,7 +141,7 @@ }, "ColumnArgList": null }, - "AliasPos": 97, + "AliasPos": 94, "Alias": { "Name": "value", "QuoteType": 1, @@ -194,7 +194,7 @@ "HasGlobal": false, "HasNot": false }, - "AliasPos": 125, + "AliasPos": 122, "Alias": { "Name": "value", "QuoteType": 1, diff --git a/parser/testdata/query/output/select_column_alias_string.sql.golden.json b/parser/testdata/query/output/select_column_alias_string.sql.golden.json index 38b505c..6e55a38 100644 --- a/parser/testdata/query/output/select_column_alias_string.sql.golden.json +++ b/parser/testdata/query/output/select_column_alias_string.sql.golden.json @@ -12,7 +12,7 @@ "LiteralEnd": 11, "Literal": "abc" }, - "AliasPos": 17, + "AliasPos": 13, "Alias": { "Name": "value2", "QuoteType": 2, diff --git a/parser/testdata/query/output/select_item_with_modifiers.sql.golden.json b/parser/testdata/query/output/select_item_with_modifiers.sql.golden.json index e2a1213..cb3f225 100644 --- a/parser/testdata/query/output/select_item_with_modifiers.sql.golden.json +++ b/parser/testdata/query/output/select_item_with_modifiers.sql.golden.json @@ -35,7 +35,7 @@ "NamePos": 18, "NameEnd": 20 }, - "AliasPos": 24, + "AliasPos": 21, "Alias": { "Name": "c1", "QuoteType": 1, @@ -137,7 +137,7 @@ "HasGlobal": false, "HasNot": false }, - "AliasPos": 63, + "AliasPos": 60, "Alias": { "Name": "i", "QuoteType": 1, @@ -239,7 +239,7 @@ "HasGlobal": false, "HasNot": false }, - "AliasPos": 101, + "AliasPos": 98, "Alias": { "Name": "i", "QuoteType": 1, diff --git a/parser/testdata/query/output/select_simple.sql.golden.json b/parser/testdata/query/output/select_simple.sql.golden.json index 780ce58..28b518e 100644 --- a/parser/testdata/query/output/select_simple.sql.golden.json +++ b/parser/testdata/query/output/select_simple.sql.golden.json @@ -48,7 +48,7 @@ "ColumnArgList": null } }, - "AliasPos": 35, + "AliasPos": 32, "Alias": { "Name": "f3", "QuoteType": 1, @@ -119,7 +119,7 @@ "Frame": null } }, - "AliasPos": 94, + "AliasPos": 91, "Alias": { "Name": "rn", "QuoteType": 1, @@ -196,12 +196,12 @@ "Literal": "foo" }, { - "LiteralPos": 142, + "LiteralPos": 135, "LiteralEnd": 145, "Literal": "bar" }, { - "LiteralPos": 149, + "LiteralPos": 135, "LiteralEnd": 153, "Literal": "test" } @@ -264,14 +264,14 @@ "NamePos": 183, "NameEnd": 185 }, - "Operation": "LIKE", + "Operation": "NOT LIKE", "RightExpr": { "LiteralPos": 196, "LiteralEnd": 204, "Literal": "testing2" }, "HasGlobal": false, - "HasNot": true + "HasNot": false } ] }, @@ -288,7 +288,7 @@ "NamePos": 211, "NameEnd": 213 }, - "Operation": "IN", + "Operation": "NOT IN", "RightExpr": { "LeftParenPos": 221, "RightParenPos": 235, @@ -303,12 +303,12 @@ "Literal": "a" }, { - "LiteralPos": 228, + "LiteralPos": 223, "LiteralEnd": 229, "Literal": "b" }, { - "LiteralPos": 233, + "LiteralPos": 223, "LiteralEnd": 234, "Literal": "c" } @@ -317,7 +317,7 @@ "ColumnArgList": null }, "HasGlobal": false, - "HasNot": true + "HasNot": false }, "HasGlobal": false, "HasNot": false diff --git a/parser/testdata/query/output/select_simple_with_bracket.sql.golden.json b/parser/testdata/query/output/select_simple_with_bracket.sql.golden.json index 947e5ba..be6c350 100644 --- a/parser/testdata/query/output/select_simple_with_bracket.sql.golden.json +++ b/parser/testdata/query/output/select_simple_with_bracket.sql.golden.json @@ -37,7 +37,7 @@ "Base": 10 }, { - "NumPos": 23, + "NumPos": 20, "NumEnd": 24, "Literal": "2", "Base": 10 @@ -60,7 +60,7 @@ "Base": 10 }, { - "NumPos": 31, + "NumPos": 28, "NumEnd": 32, "Literal": "4", "Base": 10 @@ -83,7 +83,7 @@ "Base": 10 }, { - "NumPos": 39, + "NumPos": 36, "NumEnd": 40, "Literal": "6", "Base": 10 @@ -96,7 +96,7 @@ "ColumnArgList": null } }, - "AliasPos": 46, + "AliasPos": 43, "Alias": { "Name": "res", "QuoteType": 1, @@ -133,7 +133,7 @@ } } }, - "AliasPos": 64, + "AliasPos": 61, "Alias": { "Name": "f2", "QuoteType": 1, diff --git a/parser/testdata/query/output/select_simple_with_cte_with_column_aliases.sql.golden.json b/parser/testdata/query/output/select_simple_with_cte_with_column_aliases.sql.golden.json index 6ef5312..f1acad6 100644 --- a/parser/testdata/query/output/select_simple_with_cte_with_column_aliases.sql.golden.json +++ b/parser/testdata/query/output/select_simple_with_cte_with_column_aliases.sql.golden.json @@ -132,7 +132,7 @@ "NamePos": 71, "NameEnd": 73 }, - "AliasPos": 77, + "AliasPos": 74, "Alias": { "Name": "new_f1", "QuoteType": 1, @@ -150,7 +150,7 @@ "NamePos": 89, "NameEnd": 91 }, - "AliasPos": 95, + "AliasPos": 92, "Alias": { "Name": "new_f2", "QuoteType": 1, @@ -168,7 +168,7 @@ "NamePos": 107, "NameEnd": 109 }, - "AliasPos": 113, + "AliasPos": 110, "Alias": { "Name": "new_f3", "QuoteType": 1, diff --git a/parser/testdata/query/output/select_simple_with_is_not_null.sql.golden.json b/parser/testdata/query/output/select_simple_with_is_not_null.sql.golden.json index 26d471d..08cbf00 100644 --- a/parser/testdata/query/output/select_simple_with_is_not_null.sql.golden.json +++ b/parser/testdata/query/output/select_simple_with_is_not_null.sql.golden.json @@ -40,7 +40,7 @@ "NamePos": 16, "NameEnd": 18 }, - "AliasPos": 22, + "AliasPos": 19, "Alias": { "Name": "a0", "QuoteType": 1, @@ -117,12 +117,12 @@ "Literal": "foo" }, { - "LiteralPos": 70, + "LiteralPos": 63, "LiteralEnd": 73, "Literal": "bar" }, { - "LiteralPos": 77, + "LiteralPos": 63, "LiteralEnd": 81, "Literal": "test" } @@ -171,7 +171,7 @@ }, "Operation": "AND", "RightExpr": { - "IsPos": 114, + "IsPos": 127, "Expr": { "Name": "f2", "QuoteType": 1, @@ -184,7 +184,7 @@ }, "Operation": "AND", "RightExpr": { - "IsPos": 131, + "IsPos": 145, "Expr": { "Name": "f3", "QuoteType": 1, diff --git a/parser/testdata/query/output/select_simple_with_is_null.sql.golden.json b/parser/testdata/query/output/select_simple_with_is_null.sql.golden.json index ec1a135..83b79a1 100644 --- a/parser/testdata/query/output/select_simple_with_is_null.sql.golden.json +++ b/parser/testdata/query/output/select_simple_with_is_null.sql.golden.json @@ -40,7 +40,7 @@ "NamePos": 16, "NameEnd": 18 }, - "AliasPos": 22, + "AliasPos": 19, "Alias": { "Name": "a0", "QuoteType": 1, @@ -116,12 +116,12 @@ "Literal": "foo" }, { - "LiteralPos": 70, + "LiteralPos": 63, "LiteralEnd": 73, "Literal": "bar" }, { - "LiteralPos": 77, + "LiteralPos": 63, "LiteralEnd": 81, "Literal": "test" } @@ -170,7 +170,7 @@ }, "Operation": "AND", "RightExpr": { - "IsPos": 110, + "IsPos": 120, "Expr": { "Name": "f2", "QuoteType": 1, diff --git a/parser/testdata/query/output/select_with_left_join.sql.golden.json b/parser/testdata/query/output/select_with_left_join.sql.golden.json index 5704615..871b120 100644 --- a/parser/testdata/query/output/select_with_left_join.sql.golden.json +++ b/parser/testdata/query/output/select_with_left_join.sql.golden.json @@ -28,7 +28,7 @@ "Literal": "1", "Base": 10 }, - "AliasPos": 49, + "AliasPos": 46, "Alias": { "Name": "value", "QuoteType": 1, @@ -79,7 +79,7 @@ "Literal": "2", "Base": 10 }, - "AliasPos": 93, + "AliasPos": 90, "Alias": { "Name": "value", "QuoteType": 1, diff --git a/parser/testdata/query/output/select_with_multi_join.sql.golden.json b/parser/testdata/query/output/select_with_multi_join.sql.golden.json index b6d3427..49c2871 100644 --- a/parser/testdata/query/output/select_with_multi_join.sql.golden.json +++ b/parser/testdata/query/output/select_with_multi_join.sql.golden.json @@ -27,7 +27,7 @@ "LiteralEnd": 31, "Literal": "value1" }, - "AliasPos": 36, + "AliasPos": 33, "Alias": { "Name": "value", "QuoteType": 1, @@ -77,7 +77,7 @@ "LiteralEnd": 71, "Literal": "value2" }, - "AliasPos": 76, + "AliasPos": 73, "Alias": { "Name": "value", "QuoteType": 1, @@ -127,7 +127,7 @@ "LiteralEnd": 111, "Literal": "value3" }, - "AliasPos": 116, + "AliasPos": 113, "Alias": { "Name": "value", "QuoteType": 1, @@ -177,7 +177,7 @@ "NameEnd": 147 } }, - "AliasPos": 151, + "AliasPos": 148, "Alias": { "Name": "value1", "QuoteType": 1, @@ -204,7 +204,7 @@ "NameEnd": 171 } }, - "AliasPos": 175, + "AliasPos": 172, "Alias": { "Name": "value2", "QuoteType": 1, @@ -231,7 +231,7 @@ "NameEnd": 195 } }, - "AliasPos": 199, + "AliasPos": 196, "Alias": { "Name": "value3", "QuoteType": 1, diff --git a/parser/testdata/query/output/select_with_multi_union.sql.golden.json b/parser/testdata/query/output/select_with_multi_union.sql.golden.json index 76349ed..342473e 100644 --- a/parser/testdata/query/output/select_with_multi_union.sql.golden.json +++ b/parser/testdata/query/output/select_with_multi_union.sql.golden.json @@ -13,7 +13,7 @@ "Literal": "1", "Base": 10 }, - "AliasPos": 12, + "AliasPos": 9, "Alias": { "Name": "v1", "QuoteType": 1, @@ -51,7 +51,7 @@ "Literal": "2", "Base": 10 }, - "AliasPos": 37, + "AliasPos": 34, "Alias": { "Name": "v2", "QuoteType": 1, @@ -89,7 +89,7 @@ "Literal": "3", "Base": 10 }, - "AliasPos": 62, + "AliasPos": 59, "Alias": { "Name": "v3", "QuoteType": 1, diff --git a/parser/testdata/query/output/select_with_query_parameter.sql.golden.json b/parser/testdata/query/output/select_with_query_parameter.sql.golden.json index a61d054..f653417 100644 --- a/parser/testdata/query/output/select_with_query_parameter.sql.golden.json +++ b/parser/testdata/query/output/select_with_query_parameter.sql.golden.json @@ -108,7 +108,7 @@ "Base": 10 }, { - "NumPos": 102, + "NumPos": 98, "NumEnd": 104, "Literal": "12", "Base": 10 @@ -138,7 +138,7 @@ "Base": 10 }, { - "NumPos": 118, + "NumPos": 114, "NumEnd": 120, "Literal": "15", "Base": 10 diff --git a/parser/testdata/query/output/select_with_string_expr.sql.golden.json b/parser/testdata/query/output/select_with_string_expr.sql.golden.json index 9f65a73..f10d6a2 100644 --- a/parser/testdata/query/output/select_with_string_expr.sql.golden.json +++ b/parser/testdata/query/output/select_with_string_expr.sql.golden.json @@ -28,7 +28,7 @@ "Literal": "1", "Base": 10 }, - "AliasPos": 27, + "AliasPos": 24, "Alias": { "Name": "a", "QuoteType": 1, diff --git a/parser/testdata/query/output/select_with_variable.sql.golden.json b/parser/testdata/query/output/select_with_variable.sql.golden.json index e87c2f1..ebdebbf 100644 --- a/parser/testdata/query/output/select_with_variable.sql.golden.json +++ b/parser/testdata/query/output/select_with_variable.sql.golden.json @@ -28,7 +28,7 @@ "Literal": "1", "Base": 10 }, - "AliasPos": 26, + "AliasPos": 23, "Alias": { "Name": "a", "QuoteType": 1, diff --git a/parser/testdata/query/query_with_expr_compare.sql b/parser/testdata/query/query_with_expr_compare.sql new file mode 100644 index 0000000..edcf504 --- /dev/null +++ b/parser/testdata/query/query_with_expr_compare.sql @@ -0,0 +1,6 @@ +SELECT date, path, splitByChar('/', path)[2] AS path_b +FROM( + SELECT 'pathA/pathB/pathC' AS path, '2024-09-10' AS date + ) +WHERE toDate(date) = '2024-09-01' AND '2024-09-30' + AND splitByChar('/', path)[1] = 'pathA' \ No newline at end of file