github.com/dolthub/go-mysql-server@v0.18.0/sql/analyzer/index_analyzer_test.go (about) 1 // Copyright 2021 Dolthub, Inc. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package analyzer 16 17 import ( 18 "testing" 19 20 "github.com/stretchr/testify/require" 21 22 "github.com/dolthub/go-mysql-server/sql" 23 "github.com/dolthub/go-mysql-server/sql/expression" 24 "github.com/dolthub/go-mysql-server/sql/types" 25 ) 26 27 func TestMatchingIndexes(t *testing.T) { 28 ctx := sql.NewEmptyContext() 29 const testDb = "mydb" 30 const testTable = "test" 31 32 v1 := expression.NewLiteral(1, types.Int64) 33 v2 := expression.NewLiteral(2, types.Int64) 34 v3 := expression.NewLiteral(3, types.Int64) 35 36 dummy1 := &dummyIdx{ 37 id: "dummy1", 38 expr: []sql.Expression{v1}, 39 database: testDb, 40 table: testTable, 41 } 42 dummy2 := &dummyIdx{ 43 id: "dummy2", 44 expr: []sql.Expression{v1, v2, v3}, 45 database: testDb, 46 table: testTable, 47 } 48 dummy3 := &dummyIdx{ 49 id: "dummy3", 50 expr: []sql.Expression{v1, v2}, 51 database: testDb, 52 table: testTable, 53 } 54 dummy4 := &dummyIdx{ 55 id: "dummy4", 56 expr: []sql.Expression{v3, v2, v1}, 57 database: testDb, 58 table: testTable, 59 } 60 61 ia := &indexAnalyzer{ 62 indexesByTable: map[string][]sql.Index{testTable: {dummy1, dummy2, dummy3, dummy4}}, 63 indexRegistry: nil, 64 registryIdxes: nil, 65 } 66 67 require.Equal(t, []sql.Index{dummy1, dummy2, dummy3}, ia.MatchingIndexes(ctx, testTable, testDb, v1)) 68 require.Equal(t, []sql.Index{dummy3, dummy2}, ia.MatchingIndexes(ctx, testTable, testDb, v2, v1)) 69 require.Equal(t, []sql.Index{dummy2, dummy4}, ia.MatchingIndexes(ctx, testTable, testDb, v3, v1)) 70 require.Equal(t, []sql.Index{dummy2, dummy4}, ia.MatchingIndexes(ctx, testTable, testDb, v2, v3, v1)) 71 require.Equal(t, []sql.Index{dummy4}, ia.MatchingIndexes(ctx, testTable, testDb, v3)) 72 require.Equal(t, []sql.Index{dummy4}, ia.MatchingIndexes(ctx, testTable, testDb, v2, v3)) 73 require.Equal(t, dummy1, ia.MatchingIndex(ctx, testTable, testDb, v1)) 74 require.Equal(t, dummy3, ia.MatchingIndex(ctx, testTable, testDb, v2, v1)) 75 require.Equal(t, dummy2, ia.MatchingIndex(ctx, testTable, testDb, v3, v1)) 76 require.Equal(t, dummy2, ia.MatchingIndex(ctx, testTable, testDb, v2, v3, v1)) 77 require.Equal(t, dummy4, ia.MatchingIndex(ctx, testTable, testDb, v3)) 78 require.Equal(t, dummy4, ia.MatchingIndex(ctx, testTable, testDb, v2, v3)) 79 } 80 81 func TestExpressionsWithIndexesPartialMatching(t *testing.T) { 82 const testDb = "mydb" 83 const testTable = "test" 84 85 v1 := expression.NewLiteral(1, types.Int64) 86 v2 := expression.NewLiteral(2, types.Int64) 87 v3 := expression.NewLiteral(3, types.Int64) 88 v4 := expression.NewLiteral(4, types.Int64) 89 90 gf1 := expression.NewGetField(0, types.Int64, "1", false) 91 gf2 := expression.NewGetField(1, types.Int64, "2", false) 92 //gf3 := expression.NewGetField(2, sql.Int64, "3", false) 93 gf4 := expression.NewGetField(3, types.Int64, "4", false) 94 95 dummy1 := &dummyIdx{ 96 id: "dummy", 97 expr: []sql.Expression{v1, v2, v3}, 98 database: testDb, 99 table: testTable, 100 } 101 dummy2 := &dummyIdx{ 102 id: "dummy", 103 expr: []sql.Expression{v2, v4, v1, v3}, 104 database: testDb, 105 table: testTable, 106 } 107 108 ia := &indexAnalyzer{ 109 indexesByTable: map[string][]sql.Index{testTable: {dummy1}}, 110 indexRegistry: nil, 111 registryIdxes: nil, 112 } 113 exprList := ia.ExpressionsWithIndexes(testDb, gf1, gf2) 114 require.Equal(t, [][]sql.Expression{{gf1, gf2}}, exprList) 115 116 ia = &indexAnalyzer{ 117 indexesByTable: map[string][]sql.Index{testTable: {dummy1, dummy2}}, 118 indexRegistry: nil, 119 registryIdxes: nil, 120 } 121 exprList = ia.ExpressionsWithIndexes(testDb, gf2, gf4, gf1) 122 require.Equal(t, [][]sql.Expression{{gf2, gf4, gf1}, {gf1, gf2}}, exprList) 123 } 124 125 type dummyIdx struct { 126 id string 127 expr []sql.Expression 128 database string 129 table string 130 } 131 132 var _ sql.Index = (*dummyIdx)(nil) 133 134 func (i dummyIdx) CanSupport(r ...sql.Range) bool { 135 return true 136 } 137 138 func (i dummyIdx) Expressions() []string { 139 var exprs []string 140 for _, e := range i.expr { 141 exprs = append(exprs, e.String()) 142 } 143 return exprs 144 } 145 func (i *dummyIdx) ID() string { return i.id } 146 func (i *dummyIdx) Database() string { return i.database } 147 func (i *dummyIdx) Table() string { return i.table } 148 func (i *dummyIdx) IsUnique() bool { return false } 149 func (i *dummyIdx) IsSpatial() bool { return false } 150 func (i *dummyIdx) IsFullText() bool { return false } 151 func (i *dummyIdx) Comment() string { return "" } 152 func (i *dummyIdx) IsGenerated() bool { return false } 153 func (i *dummyIdx) IndexType() string { return "BTREE" } 154 func (i *dummyIdx) PrefixLengths() []uint16 { return nil } 155 156 func (i *dummyIdx) NewLookup(*sql.Context, ...sql.Range) (sql.IndexLookup, error) { 157 panic("not implemented") 158 } 159 func (i *dummyIdx) ColumnExpressionTypes() []sql.ColumnExpressionType { 160 panic("not implemented") 161 }