Skip to content

Commit 258ea28

Browse files
authored
Fix cannot parse LEFT JOIN correctly (#41)
1 parent a974e05 commit 258ea28

9 files changed

+282
-16
lines changed

parser/ast.go

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2548,7 +2548,7 @@ type JoinExpr struct {
25482548
JoinPos Pos
25492549
Left Expr
25502550
Right Expr
2551-
JoinType string
2551+
Modifiers []string
25522552
SampleRatio *SampleRatioExpr
25532553
Constraints Expr
25542554
}
@@ -2564,11 +2564,13 @@ func (j *JoinExpr) End() Pos {
25642564
func (j *JoinExpr) String(level int) string {
25652565
var builder strings.Builder
25662566
builder.WriteString(j.Left.String(level))
2567-
if j.JoinType != "" {
2568-
builder.WriteString(j.JoinType)
2567+
if len(j.Modifiers) != 0 {
2568+
builder.WriteByte(' ')
2569+
builder.WriteString(strings.Join(j.Modifiers, " "))
25692570
} else {
25702571
builder.WriteString(",")
25712572
}
2573+
builder.WriteByte(' ')
25722574
builder.WriteString(j.Right.String(level))
25732575
if j.Constraints != nil {
25742576
builder.WriteByte(' ')

parser/keyword.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,7 @@ const (
6969
KeywordExplain = "EXPLAIN"
7070
KeywordExpression = "EXPRESSION"
7171
KeywordExtract = "EXTRACT"
72+
KeywordFalse = "FALSE"
7273
KeywordFetches = "FETCHES"
7374
KeywordFileSystem = "FILESYSTEM"
7475
KeywordFinal = "FINAL"
@@ -198,6 +199,7 @@ const (
198199
KeywordTotals = "TOTALS"
199200
KeywordTrailing = "TRAILING"
200201
KeywordTrim = "TRIM"
202+
KeywordTrue = "TRUE"
201203
KeywordTruncate = "TRUNCATE"
202204
KeywordTtl = "TTL"
203205
KeywordType = "TYPE"
@@ -290,6 +292,7 @@ var keywords = NewSet(
290292
KeywordExplain,
291293
KeywordExpression,
292294
KeywordExtract,
295+
KeywordFalse,
293296
KeywordFetches,
294297
KeywordFileSystem,
295298
KeywordFinal,
@@ -418,6 +421,7 @@ var keywords = NewSet(
418421
KeywordTotals,
419422
KeywordTrailing,
420423
KeywordTrim,
424+
KeywordTrue,
421425
KeywordTruncate,
422426
KeywordTtl,
423427
KeywordType,

parser/parser_column.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -433,7 +433,7 @@ func (p *Parser) parseColumnExprListWithTerm(term TokenKind, pos Pos) (*ColumnEx
433433
}
434434
columnExprList.HasDistinct = p.tryConsumeKeyword(KeywordDistinct) != nil
435435
columnList := make([]Expr, 0)
436-
for !p.lexer.isEOF() {
436+
for !p.lexer.isEOF() || p.last() != nil {
437437
if term != "" && p.matchTokenKind(term) {
438438
break
439439
}

parser/parser_query.go

Lines changed: 30 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,7 @@ func (p *Parser) parseFromExpr(pos Pos) (*FromExpr, error) {
9696
func (p *Parser) tryParseJoinConstraints(pos Pos) (Expr, error) {
9797
switch {
9898
case p.tryConsumeKeyword(KeywordOn) != nil:
99-
columnExprList, err := p.parseColumnExprListWithRoundBracket(p.Pos())
99+
columnExprList, err := p.parseColumnExprList(p.Pos())
100100
if err != nil {
101101
return nil, err
102102
}
@@ -123,56 +123,76 @@ func (p *Parser) tryParseJoinConstraints(pos Pos) (Expr, error) {
123123
return nil, nil
124124
}
125125

126-
func (p *Parser) parseJoinOp(_ Pos) (Expr, error) {
126+
func (p *Parser) parseJoinOp(_ Pos) (Expr, []string, error) {
127+
var modifiers []string
127128
switch {
128129
case p.tryConsumeKeyword(KeywordCross) != nil: // cross join
129-
if err := p.consumeKeyword(KeywordJoin); err != nil {
130-
return nil, err
131-
}
130+
modifiers = append(modifiers, KeywordCross)
132131
case p.tryConsumeTokenKind(",") != nil:
133132
case p.matchKeyword(KeywordAny), p.matchKeyword(KeywordAll):
133+
modifiers = append(modifiers, p.last().String)
134134
_ = p.lexer.consumeToken()
135135
if p.matchKeyword(KeywordFull) {
136+
modifiers = append(modifiers, p.last().String)
136137
_ = p.lexer.consumeToken()
137138
}
138139
if p.matchKeyword(KeywordLeft) || p.matchKeyword(KeywordRight) || p.matchKeyword(KeywordInner) || p.matchKeyword(KeywordOuter) {
140+
modifiers = append(modifiers, p.last().String)
139141
_ = p.lexer.consumeToken()
140142
}
141143
case p.matchKeyword(KeywordSemi), p.matchKeyword(KeywordAsof):
144+
modifiers = append(modifiers, p.last().String)
142145
_ = p.lexer.consumeToken()
143146
if p.matchKeyword(KeywordLeft) || p.matchKeyword(KeywordRight) {
147+
modifiers = append(modifiers, p.last().String)
144148
_ = p.lexer.consumeToken()
145149
}
146150
if p.matchKeyword(KeywordOuter) {
151+
modifiers = append(modifiers, p.last().String)
147152
_ = p.lexer.consumeToken()
148153
}
149154
case p.matchKeyword(KeywordInner):
155+
modifiers = append(modifiers, p.last().String)
150156
_ = p.lexer.consumeToken()
151157
if p.matchKeyword(KeywordAll) || p.matchKeyword(KeywordAny) || p.matchKeyword(KeywordAsof) {
158+
modifiers = append(modifiers, p.last().String)
152159
_ = p.lexer.consumeToken()
153160
}
154161
case p.matchKeyword(KeywordLeft), p.matchKeyword(KeywordRight):
162+
modifiers = append(modifiers, p.last().String)
163+
_ = p.lexer.consumeToken()
155164
if p.matchKeyword(KeywordOuter) {
165+
modifiers = append(modifiers, p.last().String)
156166
_ = p.lexer.consumeToken()
157167
}
158168
if p.matchKeyword(KeywordSemi) || p.matchKeyword(KeywordAnti) ||
159169
p.matchKeyword(KeywordAny) || p.matchKeyword(KeywordAll) ||
160170
p.matchKeyword(KeywordAsof) || p.matchKeyword(KeywordArray) {
171+
modifiers = append(modifiers, p.last().String)
161172
_ = p.lexer.consumeToken()
162173
}
163174
case p.matchKeyword(KeywordFull):
175+
modifiers = append(modifiers, p.last().String)
164176
_ = p.lexer.consumeToken()
165177
if p.matchKeyword(KeywordOuter) {
178+
modifiers = append(modifiers, p.last().String)
166179
_ = p.lexer.consumeToken()
167180
}
168181
if p.matchKeyword(KeywordAll) || p.matchKeyword(KeywordAny) {
182+
modifiers = append(modifiers, p.last().String)
169183
_ = p.lexer.consumeToken()
170184
}
171185
default:
172-
return nil, nil
186+
return nil, nil, nil
187+
}
188+
if p.tryConsumeKeyword(KeywordJoin) != nil {
189+
modifiers = append(modifiers, KeywordJoin)
190+
}
191+
expr, err := p.parseJoinExpr(p.Pos())
192+
if err != nil {
193+
return nil, nil, err
173194
}
174-
_ = p.tryConsumeKeyword(KeywordJoin)
175-
return p.parseJoinExpr(p.Pos())
195+
return expr, modifiers, nil
176196
}
177197

178198
func (p *Parser) parseJoinExpr(pos Pos) (expr Expr, err error) {
@@ -197,7 +217,7 @@ func (p *Parser) parseJoinExpr(pos Pos) (expr Expr, err error) {
197217
if p.matchKeyword(KeywordGlobal) || p.matchKeyword(KeywordLocal) {
198218
_ = p.lexer.consumeToken()
199219
}
200-
rightExpr, err := p.parseJoinOp(p.Pos())
220+
rightExpr, modifiers, err := p.parseJoinOp(p.Pos())
201221
if err != nil {
202222
return nil, err
203223
}
@@ -213,6 +233,7 @@ func (p *Parser) parseJoinExpr(pos Pos) (expr Expr, err error) {
213233
JoinPos: pos,
214234
Left: expr,
215235
Right: rightExpr,
236+
Modifiers: modifiers,
216237
SampleRatio: sampleRatio,
217238
Constraints: constrains,
218239
}, nil

parser/testdata/query/format/select_simple_with_with_clause.sql

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,4 +28,4 @@ SELECT
2828
cte2.f2,
2929
t3.f3
3030
FROM
31-
t3,cte1,cte2;
31+
t3, cte1, cte2;
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
-- Origin SQL:
2+
WITH
3+
t1 AS
4+
(
5+
SELECT 1 AS value
6+
),
7+
t2 AS
8+
(
9+
SELECT 2 AS value
10+
)
11+
SELECT *
12+
FROM t1
13+
LEFT JOIN t2 ON true
14+
15+
-- Format SQL:
16+
WITH
17+
t1 AS (
18+
SELECT
19+
1 AS value),
20+
t2 AS (
21+
SELECT
22+
2 AS value)
23+
SELECT
24+
*
25+
FROM
26+
t1 LEFT JOIN t2 ON true;

parser/testdata/query/output/select_simple_with_with_clause.sql.golden.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -232,11 +232,11 @@
232232
},
233233
"HasFinal": false
234234
},
235-
"JoinType": "",
235+
"Modifiers": null,
236236
"SampleRatio": null,
237237
"Constraints": null
238238
},
239-
"JoinType": "",
239+
"Modifiers": null,
240240
"SampleRatio": null,
241241
"Constraints": null
242242
}

0 commit comments

Comments
 (0)