Skip to content

Commit bc14c9d

Browse files
With clause support extended, fixed test cases.
1 parent a3930da commit bc14c9d

5 files changed

Lines changed: 44 additions & 26 deletions

File tree

expr/selector.go

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
package expr
22

33
import (
4-
"github.com/viant/sqlparser/node"
54
"strings"
5+
6+
"github.com/viant/sqlparser/node"
67
)
78

89
// Selector represent identifier selector
@@ -24,9 +25,11 @@ func NewSelector(name string) node.Node {
2425
name = strings.Replace(name, expr, "", 1)
2526
expr = expr[1 : len(expr)-1]
2627
}
27-
2828
part := strings.Index(name, ".")
2929
if part == -1 {
30+
if expr != "" {
31+
return &Selector{Name: name, Expression: expr}
32+
}
3033
return &Ident{Name: name}
3134
}
3235
return &Selector{Name: name[:part], X: NewSelector(name[part+1:]), Expression: expr}

join.go

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8,27 +8,27 @@ import (
88

99
func parseJoin(cursor *parsly.Cursor, join *query.Join, dest *query.Select, expectOn bool) error {
1010
match := cursor.MatchAfterOptional(whitespaceMatcher, parenthesesMatcher, exprMatcher, selectorMatcher)
11+
var skipAlias bool
1112
switch match.Code {
1213
case parenthesesCode:
1314
join.With = expr.NewRaw(match.Text(cursor))
1415
case selectorTokenCode:
1516
identityOrAlias := match.Text(cursor)
16-
1717
match = cursor.MatchAfterOptional(whitespaceMatcher, parenthesesMatcher)
1818
if match.Code == parenthesesCode {
1919
identityOrAlias += match.Text(cursor)
2020
}
21-
2221
withSelect := dest.WithSelects.Select(identityOrAlias)
2322
if withSelect != nil {
24-
join.With = expr.NewParenthesis(withSelect.Raw)
25-
join.Alias = identityOrAlias
23+
join.With = expr.NewSelector(identityOrAlias)
24+
join.Alias = ""
25+
skipAlias = true
2626
} else {
2727
join.With = expr.NewSelector(identityOrAlias)
28+
skipAlias = false
2829
}
2930
}
30-
31-
if join.Alias == "" {
31+
if join.Alias == "" && !skipAlias {
3232
join.Alias = discoverAlias(cursor)
3333
}
3434
match = cursor.MatchAfterOptional(whitespaceMatcher, commentBlockMatcher, onKeywordMatcher)

query.go

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,11 @@ package sqlparser
33
import (
44
"bytes"
55
"fmt"
6+
"strings"
7+
68
"github.com/viant/parsly"
79
"github.com/viant/sqlparser/expr"
810
"github.com/viant/sqlparser/query"
9-
"strings"
1011
)
1112

1213
// ParseQuery parses query
@@ -93,15 +94,18 @@ beginMatch:
9394
case fromKeyword:
9495
dest.From = query.From{}
9596
match = cursor.MatchAfterOptional(whitespaceMatcher, tableMatcher, parenthesesMatcher)
97+
var skipAlias bool
9698
switch match.Code {
9799
case tableTokenCode:
98100
identityOrAlias := match.Text(cursor)
99101
withSelect := dest.WithSelects.Select(identityOrAlias)
100102
if withSelect != nil {
101-
dest.From.X = expr.NewParenthesis(withSelect.Raw)
102-
dest.From.Alias = identityOrAlias
103+
dest.From.X = expr.NewSelector(identityOrAlias)
104+
dest.From.Alias = ""
105+
skipAlias = true
103106
} else {
104107
dest.From.X = expr.NewSelector(identityOrAlias)
108+
skipAlias = false
105109
}
106110
case parenthesesCode:
107111
dest.From.X = expr.NewRaw(match.Text(cursor))
@@ -116,7 +120,7 @@ beginMatch:
116120
}
117121
rawNode.X = subSelect
118122
}
119-
if dest.From.Alias == "" {
123+
if dest.From.Alias == "" && !skipAlias {
120124
dest.From.Alias = discoverAlias(cursor)
121125
}
122126
match = cursor.MatchAfterOptional(whitespaceMatcher, commentBlockMatcher)

query_test.go

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,14 @@ package sqlparser
33
import (
44
"encoding/json"
55
"fmt"
6+
"strings"
7+
"testing"
8+
69
"github.com/stretchr/testify/assert"
710
"github.com/viant/parsly"
811
"github.com/viant/sqlparser/expr"
912
"github.com/viant/sqlparser/node"
1013
"github.com/viant/sqlparser/query"
11-
"strings"
12-
"testing"
1314
)
1415

1516
func TestBinaryWalk(t *testing.T) {
@@ -69,7 +70,7 @@ func TestParseSelect(t *testing.T) {
6970
description: "with syntax",
7071
SQL: `WITH p AS (SELECT * FROM product), v AS (SELECT * FROM vendor)
7172
SELECT p.*, v.* FROM p JOIN v ON p.VENDOR_ID = v.ID`,
72-
expect: `SELECT p.*, v.* FROM (SELECT * FROM product) p JOIN (SELECT * FROM vendor) v ON p.VENDOR_ID = v.ID`,
73+
expect: `WITH p AS (SELECT * FROM product), v AS (SELECT * FROM vendor) SELECT p.*, v.* FROM p JOIN v ON p.VENDOR_ID = v.ID`,
7374
},
7475

7576
{
@@ -359,6 +360,7 @@ func TestParseSelect(t *testing.T) {
359360
actual := strings.TrimSpace(Stringify(query))
360361
if !assert.EqualValues(t, testCase.expect, actual) {
361362
data, _ := json.Marshal(query)
363+
fmt.Printf("failed test case: %s\n", testCase.description)
362364
fmt.Printf("%s\n", data)
363365
}
364366
}

stringify.go

Lines changed: 20 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -39,17 +39,18 @@ func stringify(n node.Node, builder *bytes.Buffer) {
3939
}
4040
builder.WriteString(withSel.Alias)
4141
builder.WriteString(" AS ")
42-
if withSel.Raw != "" {
42+
switch {
43+
case withSel.Raw != "":
4344
builder.WriteString(withSel.Raw)
44-
} else if withSel.X != nil {
45-
builder.WriteString("(")
45+
case withSel.X != nil:
46+
builder.WriteByte('(')
4647
stringify(withSel.X, builder)
47-
builder.WriteString(")")
48-
} else {
48+
builder.WriteByte(')')
49+
default:
4950
builder.WriteString("()")
5051
}
5152
}
52-
builder.WriteString(" ")
53+
builder.WriteByte(' ')
5354
}
5455
builder.WriteString("SELECT ")
5556
stringify(actual.List, builder)
@@ -210,16 +211,24 @@ func stringify(n node.Node, builder *bytes.Buffer) {
210211
builder.WriteString(" AND ")
211212
stringify(actual.Max, builder)
212213
case *expr.Selector:
213-
builder.WriteString(actual.Name)
214-
if actual.Expression != "" {
215-
builder.WriteString("[")
214+
name := actual.Name
215+
if actual.Expression == "" {
216+
builder.WriteString(name)
217+
} else if strings.HasPrefix(name, "`") && strings.HasSuffix(name, "`") && len(name) > 1 {
218+
builder.WriteString(name[:len(name)-1])
219+
builder.WriteByte('[')
216220
builder.WriteString(actual.Expression)
217-
builder.WriteString("]")
221+
builder.WriteString("]`")
222+
} else {
223+
builder.WriteString(name)
224+
builder.WriteByte('[')
225+
builder.WriteString(actual.Expression)
226+
builder.WriteByte(']')
218227
}
219228
if actual.X != nil {
220229
builder.WriteByte('.')
230+
stringify(actual.X, builder)
221231
}
222-
stringify(actual.X, builder)
223232
case *update.Item:
224233
stringify(actual.Column, builder)
225234
builder.WriteString(" = ")

0 commit comments

Comments
 (0)