Skip to content
This repository was archived by the owner on Jan 28, 2021. It is now read-only.

Commit 201bcd6

Browse files
authored
Merge pull request #640 from kuba--/fix-639/index-alias
Check projection aliases when assigned to index.
2 parents 8141017 + 5b17ae1 commit 201bcd6

File tree

5 files changed

+133
-30
lines changed

5 files changed

+133
-30
lines changed

engine_test.go

Lines changed: 52 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1638,22 +1638,32 @@ func TestIndexes(t *testing.T) {
16381638

16391639
_, _, err = e.Query(
16401640
newCtx(),
1641-
"CREATE INDEX myidx ON mytable USING pilosa (i) WITH (async = false)",
1641+
"CREATE INDEX idx_i ON mytable USING pilosa (i) WITH (async = false)",
16421642
)
16431643
require.NoError(t, err)
16441644

16451645
_, _, err = e.Query(
16461646
newCtx(),
1647-
"CREATE INDEX myidx_multi ON mytable USING pilosa (i, s) WITH (async = false)",
1647+
"CREATE INDEX idx_s ON mytable USING pilosa (s) WITH (async = false)",
1648+
)
1649+
require.NoError(t, err)
1650+
1651+
_, _, err = e.Query(
1652+
newCtx(),
1653+
"CREATE INDEX idx_is ON mytable USING pilosa (i, s) WITH (async = false)",
16481654
)
16491655
require.NoError(t, err)
16501656

16511657
defer func() {
1652-
done, err := e.Catalog.DeleteIndex("mydb", "myidx", true)
1658+
done, err := e.Catalog.DeleteIndex("mydb", "idx_i", true)
16531659
require.NoError(t, err)
16541660
<-done
16551661

1656-
done, err = e.Catalog.DeleteIndex("foo", "myidx_multi", true)
1662+
done, err = e.Catalog.DeleteIndex("mydb", "idx_s", true)
1663+
require.NoError(t, err)
1664+
<-done
1665+
1666+
done, err = e.Catalog.DeleteIndex("foo", "idx_is", true)
16571667
require.NoError(t, err)
16581668
<-done
16591669
}()
@@ -1724,6 +1734,44 @@ func TestIndexes(t *testing.T) {
17241734
"SELECT * FROM mytable WHERE i = 1 AND i = 2",
17251735
([]sql.Row)(nil),
17261736
},
1737+
{
1738+
"SELECT i as mytable_i FROM mytable WHERE mytable_i = 2",
1739+
[]sql.Row{
1740+
{int64(2)},
1741+
},
1742+
},
1743+
{
1744+
"SELECT i as mytable_i FROM mytable WHERE mytable_i > 1",
1745+
[]sql.Row{
1746+
{int64(3)},
1747+
{int64(2)},
1748+
},
1749+
},
1750+
{
1751+
"SELECT i as mytable_i, s as mytable_s FROM mytable WHERE mytable_i = 2 AND mytable_s = 'second row'",
1752+
[]sql.Row{
1753+
{int64(2), "second row"},
1754+
},
1755+
},
1756+
{
1757+
"SELECT s, SUBSTRING(s, 1, 1) AS sub_s FROM mytable WHERE sub_s = 's'",
1758+
[]sql.Row{
1759+
{"second row", "s"},
1760+
},
1761+
},
1762+
{
1763+
"SELECT count(i) AS mytable_i, SUBSTR(s, -3) AS mytable_s FROM mytable WHERE i > 0 AND mytable_s='row' GROUP BY mytable_s",
1764+
[]sql.Row{
1765+
{int32(3), "row"},
1766+
},
1767+
},
1768+
{
1769+
"SELECT mytable_i FROM (SELECT i AS mytable_i FROM mytable) as t WHERE mytable_i > 1",
1770+
[]sql.Row{
1771+
{int64(2)},
1772+
{int64(3)},
1773+
},
1774+
},
17271775
}
17281776

17291777
for _, tt := range testCases {

go.mod

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ require (
1818
github.com/mitchellh/hashstructure v1.0.0
1919
github.com/oliveagle/jsonpath v0.0.0-20180606110733-2e52cf6e6852
2020
github.com/opentracing/opentracing-go v1.0.2
21+
github.com/pbnjay/memory v0.0.0-20190104145345-974d429e7ae4
2122
github.com/pelletier/go-toml v1.2.0 // indirect
2223
github.com/pilosa/pilosa v1.2.0
2324
github.com/pkg/errors v0.8.1 // indirect

go.sum

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,8 @@ github.com/opentracing/opentracing-go v1.0.2 h1:3jA2P6O1F9UOrWVpwrIo17pu01KWvNWg
6969
github.com/opentracing/opentracing-go v1.0.2/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o=
7070
github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c h1:Lgl0gzECD8GnQ5QCWA8o6BtfL6mDH5rQgM4/fX3avOs=
7171
github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc=
72+
github.com/pbnjay/memory v0.0.0-20190104145345-974d429e7ae4 h1:MfIUBZ1bz7TgvQLVa/yPJZOGeKEgs6eTKUjz3zB4B+U=
73+
github.com/pbnjay/memory v0.0.0-20190104145345-974d429e7ae4/go.mod h1:RMU2gJXhratVxBDTFeOdNhd540tG57lt9FIUV0YLvIQ=
7274
github.com/pelletier/go-toml v1.2.0 h1:T5zMGML61Wp+FlcbWjRDT7yAxhJNAiPPLOFECq181zc=
7375
github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic=
7476
github.com/pilosa/pilosa v1.2.0 h1:bi58fPsjyGIFnY5DtzECY+8RC9nRLvPrGC6fOqgtkTw=

sql/analyzer/assign_indexes.go

Lines changed: 76 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -35,15 +35,42 @@ func assignIndexes(a *Analyzer, node sql.Node) (map[string]*indexLookup, error)
3535
}
3636
}()
3737

38-
var err error
38+
aliases := make(map[string]sql.Expression)
39+
var (
40+
err error
41+
fn func(node sql.Node) bool
42+
)
43+
fn = func(n sql.Node) bool {
44+
if n == nil {
45+
return true
46+
}
47+
48+
if prj, ok := n.(*plan.Project); ok {
49+
for _, ex := range prj.Expressions() {
50+
if alias, ok := ex.(*expression.Alias); ok {
51+
if _, ok := aliases[alias.Name()]; !ok {
52+
aliases[alias.Name()] = alias.Child
53+
}
54+
}
55+
}
56+
} else {
57+
for _, ch := range n.Children() {
58+
plan.Inspect(ch, fn)
59+
}
60+
}
61+
62+
return true
63+
}
64+
3965
plan.Inspect(node, func(node sql.Node) bool {
4066
filter, ok := node.(*plan.Filter)
4167
if !ok {
4268
return true
4369
}
70+
fn(filter.Child)
4471

4572
var result map[string]*indexLookup
46-
result, err = getIndexes(filter.Expression, a)
73+
result, err = getIndexes(filter.Expression, aliases, a)
4774
if err != nil {
4875
return false
4976
}
@@ -60,16 +87,16 @@ func assignIndexes(a *Analyzer, node sql.Node) (map[string]*indexLookup, error)
6087
return indexes, err
6188
}
6289

63-
func getIndexes(e sql.Expression, a *Analyzer) (map[string]*indexLookup, error) {
90+
func getIndexes(e sql.Expression, aliases map[string]sql.Expression, a *Analyzer) (map[string]*indexLookup, error) {
6491
var result = make(map[string]*indexLookup)
6592
switch e := e.(type) {
6693
case *expression.Or:
67-
leftIndexes, err := getIndexes(e.Left, a)
94+
leftIndexes, err := getIndexes(e.Left, aliases, a)
6895
if err != nil {
6996
return nil, err
7097
}
7198

72-
rightIndexes, err := getIndexes(e.Right, a)
99+
rightIndexes, err := getIndexes(e.Right, aliases, a)
73100
if err != nil {
74101
return nil, err
75102
}
@@ -101,7 +128,7 @@ func getIndexes(e sql.Expression, a *Analyzer) (map[string]*indexLookup, error)
101128
// the right branch is evaluable and the indexlookup supports set
102129
// operations.
103130
if !isEvaluable(c.Left()) && isEvaluable(c.Right()) {
104-
idx := a.Catalog.IndexByExpression(a.Catalog.CurrentDatabase(), c.Left())
131+
idx := a.Catalog.IndexByExpression(a.Catalog.CurrentDatabase(), unifyExpressions(aliases, c.Left())...)
105132
if idx != nil {
106133
var nidx sql.NegateIndex
107134
if negate {
@@ -178,7 +205,7 @@ func getIndexes(e sql.Expression, a *Analyzer) (map[string]*indexLookup, error)
178205
*expression.GreaterThan,
179206
*expression.LessThanOrEqual,
180207
*expression.GreaterThanOrEqual:
181-
idx, lookup, err := getComparisonIndex(a, e.(expression.Comparer))
208+
idx, lookup, err := getComparisonIndex(a, e.(expression.Comparer), aliases)
182209
if err != nil || lookup == nil {
183210
return result, err
184211
}
@@ -188,7 +215,7 @@ func getIndexes(e sql.Expression, a *Analyzer) (map[string]*indexLookup, error)
188215
lookup: lookup,
189216
}
190217
case *expression.Not:
191-
r, err := getNegatedIndexes(a, e)
218+
r, err := getNegatedIndexes(a, e, aliases)
192219
if err != nil {
193220
return nil, err
194221
}
@@ -198,7 +225,7 @@ func getIndexes(e sql.Expression, a *Analyzer) (map[string]*indexLookup, error)
198225
}
199226
case *expression.Between:
200227
if !isEvaluable(e.Val) && isEvaluable(e.Upper) && isEvaluable(e.Lower) {
201-
idx := a.Catalog.IndexByExpression(a.Catalog.CurrentDatabase(), e.Val)
228+
idx := a.Catalog.IndexByExpression(a.Catalog.CurrentDatabase(), unifyExpressions(aliases, e.Val)...)
202229
if idx != nil {
203230
// release the index if it was not used
204231
defer func() {
@@ -238,7 +265,7 @@ func getIndexes(e sql.Expression, a *Analyzer) (map[string]*indexLookup, error)
238265
exprs := splitExpression(e)
239266
used := make(map[sql.Expression]struct{})
240267

241-
result, err := getMultiColumnIndexes(exprs, a, used)
268+
result, err := getMultiColumnIndexes(exprs, a, used, aliases)
242269
if err != nil {
243270
return nil, err
244271
}
@@ -248,7 +275,7 @@ func getIndexes(e sql.Expression, a *Analyzer) (map[string]*indexLookup, error)
248275
continue
249276
}
250277

251-
indexes, err := getIndexes(e, a)
278+
indexes, err := getIndexes(e, aliases, a)
252279
if err != nil {
253280
return nil, err
254281
}
@@ -262,6 +289,28 @@ func getIndexes(e sql.Expression, a *Analyzer) (map[string]*indexLookup, error)
262289
return result, nil
263290
}
264291

292+
func unifyExpressions(aliases map[string]sql.Expression, expr ...sql.Expression) []sql.Expression {
293+
expressions := make([]sql.Expression, len(expr))
294+
295+
for i, e := range expr {
296+
uex := e
297+
name := e.String()
298+
if n, ok := e.(sql.Nameable); ok {
299+
name = n.Name()
300+
}
301+
302+
if aliases != nil && len(aliases) > 0 {
303+
if alias, ok := aliases[name]; ok {
304+
uex = alias
305+
}
306+
}
307+
308+
expressions[i] = uex
309+
}
310+
311+
return expressions
312+
}
313+
265314
func betweenIndexLookup(index sql.Index, upper, lower []interface{}) (sql.IndexLookup, error) {
266315
ai, isAscend := index.(sql.AscendIndex)
267316
di, isDescend := index.(sql.DescendIndex)
@@ -293,6 +342,7 @@ func betweenIndexLookup(index sql.Index, upper, lower []interface{}) (sql.IndexL
293342
func getComparisonIndex(
294343
a *Analyzer,
295344
e expression.Comparer,
345+
aliases map[string]sql.Expression,
296346
) (sql.Index, sql.IndexLookup, error) {
297347
left, right := e.Left(), e.Right()
298348
// if the form is SOMETHING OP {INDEXABLE EXPR}, swap it, so it's {INDEXABLE EXPR} OP SOMETHING
@@ -301,7 +351,7 @@ func getComparisonIndex(
301351
}
302352

303353
if !isEvaluable(left) && isEvaluable(right) {
304-
idx := a.Catalog.IndexByExpression(a.Catalog.CurrentDatabase(), left)
354+
idx := a.Catalog.IndexByExpression(a.Catalog.CurrentDatabase(), unifyExpressions(aliases, left)...)
305355
if idx != nil {
306356
value, err := right.Eval(sql.NewEmptyContext(), nil)
307357
if err != nil {
@@ -363,10 +413,10 @@ func comparisonIndexLookup(
363413
return nil, nil
364414
}
365415

366-
func getNegatedIndexes(a *Analyzer, not *expression.Not) (map[string]*indexLookup, error) {
416+
func getNegatedIndexes(a *Analyzer, not *expression.Not, aliases map[string]sql.Expression) (map[string]*indexLookup, error) {
367417
switch e := not.Child.(type) {
368418
case *expression.Not:
369-
return getIndexes(e.Child, a)
419+
return getIndexes(e.Child, aliases, a)
370420
case *expression.Equals:
371421
left, right := e.Left(), e.Right()
372422
// if the form is SOMETHING OP {INDEXABLE EXPR}, swap it, so it's {INDEXABLE EXPR} OP SOMETHING
@@ -378,7 +428,7 @@ func getNegatedIndexes(a *Analyzer, not *expression.Not) (map[string]*indexLooku
378428
return nil, nil
379429
}
380430

381-
idx := a.Catalog.IndexByExpression(a.Catalog.CurrentDatabase(), left)
431+
idx := a.Catalog.IndexByExpression(a.Catalog.CurrentDatabase(), unifyExpressions(aliases, left)...)
382432
if idx == nil {
383433
return nil, nil
384434
}
@@ -410,37 +460,37 @@ func getNegatedIndexes(a *Analyzer, not *expression.Not) (map[string]*indexLooku
410460
return result, nil
411461
case *expression.GreaterThan:
412462
lte := expression.NewLessThanOrEqual(e.Left(), e.Right())
413-
return getIndexes(lte, a)
463+
return getIndexes(lte, aliases, a)
414464
case *expression.GreaterThanOrEqual:
415465
lt := expression.NewLessThan(e.Left(), e.Right())
416-
return getIndexes(lt, a)
466+
return getIndexes(lt, aliases, a)
417467
case *expression.LessThan:
418468
gte := expression.NewGreaterThanOrEqual(e.Left(), e.Right())
419-
return getIndexes(gte, a)
469+
return getIndexes(gte, aliases, a)
420470
case *expression.LessThanOrEqual:
421471
gt := expression.NewGreaterThan(e.Left(), e.Right())
422-
return getIndexes(gt, a)
472+
return getIndexes(gt, aliases, a)
423473
case *expression.Between:
424474
or := expression.NewOr(
425475
expression.NewLessThan(e.Val, e.Lower),
426476
expression.NewGreaterThan(e.Val, e.Upper),
427477
)
428478

429-
return getIndexes(or, a)
479+
return getIndexes(or, aliases, a)
430480
case *expression.Or:
431481
and := expression.NewAnd(
432482
expression.NewNot(e.Left),
433483
expression.NewNot(e.Right),
434484
)
435485

436-
return getIndexes(and, a)
486+
return getIndexes(and, aliases, a)
437487
case *expression.And:
438488
or := expression.NewOr(
439489
expression.NewNot(e.Left),
440490
expression.NewNot(e.Right),
441491
)
442492

443-
return getIndexes(or, a)
493+
return getIndexes(or, aliases, a)
444494
default:
445495
return nil, nil
446496

@@ -481,6 +531,7 @@ func getMultiColumnIndexes(
481531
exprs []sql.Expression,
482532
a *Analyzer,
483533
used map[sql.Expression]struct{},
534+
aliases map[string]sql.Expression,
484535
) (map[string]*indexLookup, error) {
485536
result := make(map[string]*indexLookup)
486537
columnExprs := columnExprsByTable(exprs)
@@ -502,7 +553,7 @@ func getMultiColumnIndexes(
502553
}
503554

504555
if len(selected) > 0 {
505-
index, lookup, err := getMultiColumnIndexForExpressions(a, selected, exps, used)
556+
index, lookup, err := getMultiColumnIndexForExpressions(a, selected, exps, used, aliases)
506557
if err != nil || lookup == nil {
507558
if index != nil {
508559
a.Catalog.ReleaseIndex(index)
@@ -534,8 +585,9 @@ func getMultiColumnIndexForExpressions(
534585
selected []sql.Expression,
535586
exprs []columnExpr,
536587
used map[sql.Expression]struct{},
588+
aliases map[string]sql.Expression,
537589
) (index sql.Index, lookup sql.IndexLookup, err error) {
538-
index = a.Catalog.IndexByExpression(a.Catalog.CurrentDatabase(), selected...)
590+
index = a.Catalog.IndexByExpression(a.Catalog.CurrentDatabase(), unifyExpressions(aliases, selected...)...)
539591
if index != nil {
540592
var first sql.Expression
541593
for _, e := range exprs {

sql/analyzer/assign_indexes_test.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -682,7 +682,7 @@ func TestGetIndexes(t *testing.T) {
682682
t.Run(tt.expr.String(), func(t *testing.T) {
683683
require := require.New(t)
684684

685-
result, err := getIndexes(tt.expr, a)
685+
result, err := getIndexes(tt.expr, nil, a)
686686
if tt.ok {
687687
require.NoError(err)
688688
require.Equal(tt.expected, result)
@@ -779,7 +779,7 @@ func TestGetMultiColumnIndexes(t *testing.T) {
779779
lit(6),
780780
),
781781
}
782-
result, err := getMultiColumnIndexes(exprs, a, used)
782+
result, err := getMultiColumnIndexes(exprs, a, used, nil)
783783
require.NoError(err)
784784

785785
expected := map[string]*indexLookup{

0 commit comments

Comments
 (0)