From 036e3cffe9d45c638d89fe62ea8f5c394eff3ae5 Mon Sep 17 00:00:00 2001 From: hulk Date: Tue, 18 Feb 2025 23:45:06 +0800 Subject: [PATCH] Fix column index style wasn't supported in query (#119) --- parser/ast.go | 8 +- parser/parser_column.go | 4 +- parser/parser_table.go | 13 +- .../query/format/select_with_number_field.sql | 5 + .../access_tuple_with_dot.sql.golden.json | 6 +- .../select_with_number_field.sql.golden.json | 120 ++++++++++++++++++ .../query/select_with_number_field.sql | 1 + 7 files changed, 148 insertions(+), 9 deletions(-) create mode 100644 parser/testdata/query/format/select_with_number_field.sql create mode 100644 parser/testdata/query/output/select_with_number_field.sql.golden.json create mode 100644 parser/testdata/query/select_with_number_field.sql diff --git a/parser/ast.go b/parser/ast.go index 548f1b3..a4719ee 100644 --- a/parser/ast.go +++ b/parser/ast.go @@ -188,7 +188,7 @@ func (p *BinaryOperation) Accept(visitor ASTVisitor) error { } type IndexOperation struct { - LeftExpr Expr + Object Expr Operation TokenKind Index Expr } @@ -196,7 +196,7 @@ type IndexOperation struct { func (i *IndexOperation) Accept(visitor ASTVisitor) error { visitor.enter(i) defer visitor.leave(i) - if err := i.LeftExpr.Accept(visitor); err != nil { + if err := i.Object.Accept(visitor); err != nil { return err } if err := i.Index.Accept(visitor); err != nil { @@ -206,7 +206,7 @@ func (i *IndexOperation) Accept(visitor ASTVisitor) error { } func (i *IndexOperation) Pos() Pos { - return i.LeftExpr.Pos() + return i.Object.Pos() } func (i *IndexOperation) End() Pos { @@ -215,7 +215,7 @@ func (i *IndexOperation) End() Pos { func (i *IndexOperation) String() string { var builder strings.Builder - builder.WriteString(i.LeftExpr.String()) + builder.WriteString(i.Object.String()) builder.WriteString(string(i.Operation)) builder.WriteString(i.Index.String()) return builder.String() diff --git a/parser/parser_column.go b/parser/parser_column.go index 6aafb8d..1db650c 100644 --- a/parser/parser_column.go +++ b/parser/parser_column.go @@ -41,6 +41,8 @@ func (p *Parser) getNextPrecedence() int { return PrecedenceIs case p.matchKeyword(KeywordNot): return PrecedenceNot + case p.matchTokenKind(TokenKindDot): + return PrecedenceDot case p.matchTokenKind(TokenKindDash): return PrecedenceDoubleColon case p.matchTokenKind(TokenKindSingleEQ), p.matchTokenKind(TokenKindLT), p.matchTokenKind(TokenKindLE), @@ -155,7 +157,7 @@ func (p *Parser) parseInfix(expr Expr, precedence int) (Expr, error) { return nil, err } return &IndexOperation{ - LeftExpr: expr, + Object: expr, Operation: TokenKindDot, Index: rightExpr, }, nil diff --git a/parser/parser_table.go b/parser/parser_table.go index faf6649..f6bcba4 100644 --- a/parser/parser_table.go +++ b/parser/parser_table.go @@ -254,8 +254,19 @@ func (p *Parser) parseIdentOrFunction(_ Pos) (Expr, error) { Ident: ident, DotIdent: nextIdent, }, nil + case p.matchTokenKind(TokenKindInt): + i, err := p.parseNumber(p.Pos()) + if err != nil { + return nil, err + } + return &IndexOperation{ + Object: ident, + Operation: TokenKindDot, + Index: i, + }, nil + default: + return nil, fmt.Errorf("expected IDENT, NUMBER or *, but got %q", p.lastTokenKind()) } - } return ident, nil } diff --git a/parser/testdata/query/format/select_with_number_field.sql b/parser/testdata/query/format/select_with_number_field.sql new file mode 100644 index 0000000..bc9df57 --- /dev/null +++ b/parser/testdata/query/format/select_with_number_field.sql @@ -0,0 +1,5 @@ +-- Origin SQL: +SELECT foo, bar.1, foo.2 FROM foo ARRAY JOIN m as bar + +-- Format SQL: +SELECT foo, bar.1, foo.2 FROM foo ARRAY JOIN m AS bar; diff --git a/parser/testdata/query/output/access_tuple_with_dot.sql.golden.json b/parser/testdata/query/output/access_tuple_with_dot.sql.golden.json index 563e409..f290a1d 100644 --- a/parser/testdata/query/output/access_tuple_with_dot.sql.golden.json +++ b/parser/testdata/query/output/access_tuple_with_dot.sql.golden.json @@ -7,7 +7,7 @@ "SelectItems": [ { "Expr": { - "LeftExpr": { + "Object": { "Name": { "Name": "tuple", "QuoteType": 1, @@ -291,7 +291,7 @@ }, { "Expr": { - "LeftExpr": { + "Object": { "LeftParenPos": 161, "RightParenPos": 257, "Items": { @@ -485,7 +485,7 @@ }, { "Expr": { - "LeftExpr": { + "Object": { "Name": { "Name": "tuple", "QuoteType": 1, diff --git a/parser/testdata/query/output/select_with_number_field.sql.golden.json b/parser/testdata/query/output/select_with_number_field.sql.golden.json new file mode 100644 index 0000000..27387eb --- /dev/null +++ b/parser/testdata/query/output/select_with_number_field.sql.golden.json @@ -0,0 +1,120 @@ +[ + { + "SelectPos": 0, + "StatementEnd": 53, + "With": null, + "Top": null, + "SelectItems": [ + { + "Expr": { + "Name": "foo", + "QuoteType": 1, + "NamePos": 7, + "NameEnd": 10 + }, + "Modifiers": [], + "Alias": null + }, + { + "Expr": { + "Object": { + "Name": "bar", + "QuoteType": 1, + "NamePos": 12, + "NameEnd": 15 + }, + "Operation": ".", + "Index": { + "NumPos": 16, + "NumEnd": 17, + "Literal": "1", + "Base": 10 + } + }, + "Modifiers": [], + "Alias": null + }, + { + "Expr": { + "Object": { + "Name": "foo", + "QuoteType": 1, + "NamePos": 19, + "NameEnd": 22 + }, + "Operation": ".", + "Index": { + "NumPos": 23, + "NumEnd": 24, + "Literal": "2", + "Base": 10 + } + }, + "Modifiers": [], + "Alias": null + } + ], + "From": { + "FromPos": 25, + "Expr": { + "Table": { + "TablePos": 30, + "TableEnd": 33, + "Alias": null, + "Expr": { + "Database": null, + "Table": { + "Name": "foo", + "QuoteType": 1, + "NamePos": 30, + "NameEnd": 33 + } + }, + "HasFinal": false + }, + "StatementEnd": 33, + "SampleRatio": null, + "HasFinal": false + } + }, + "ArrayJoin": { + "ArrayPos": 34, + "Type": "", + "Expr": { + "ListPos": 45, + "ListEnd": 53, + "HasDistinct": false, + "Items": [ + { + "Expr": { + "Name": "m", + "QuoteType": 1, + "NamePos": 45, + "NameEnd": 46 + }, + "Alias": { + "Name": "bar", + "QuoteType": 1, + "NamePos": 50, + "NameEnd": 53 + } + } + ] + } + }, + "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 + } +] \ No newline at end of file diff --git a/parser/testdata/query/select_with_number_field.sql b/parser/testdata/query/select_with_number_field.sql new file mode 100644 index 0000000..4d21dbe --- /dev/null +++ b/parser/testdata/query/select_with_number_field.sql @@ -0,0 +1 @@ +SELECT foo, bar.1, foo.2 FROM foo ARRAY JOIN m as bar \ No newline at end of file