vitess.io/vitess@v0.16.2/go/vt/vtgate/planbuilder/route_test.go (about) 1 /* 2 Copyright 2020 The Vitess Authors. 3 4 Licensed under the Apache License, Version 2.0 (the "License"); 5 you may not use this file except in compliance with the License. 6 You may obtain a copy of the License at 7 8 http://www.apache.org/licenses/LICENSE-2.0 9 10 Unless required by applicable law or agreed to in writing, software 11 distributed under the License is distributed on an "AS IS" BASIS, 12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 See the License for the specific language governing permissions and 14 limitations under the License. 15 */ 16 17 package planbuilder 18 19 import ( 20 "fmt" 21 "testing" 22 23 "github.com/stretchr/testify/assert" 24 25 "vitess.io/vitess/go/vt/sqlparser" 26 "vitess.io/vitess/go/vt/vtgate/engine" 27 "vitess.io/vitess/go/vt/vtgate/vindexes" 28 ) 29 30 /* 31 32 This test file only tests the V3 planner. It does not test the Subshard opcode 33 34 For easy reference, opcodes are: 35 Unsharded 0 36 EqualUnique 1 37 Equal 2 38 IN 3 39 MultiEqual 4 40 Scatter 5 41 Next 6 42 DBA 7 43 Reference 8 44 None 9 45 */ 46 47 func TestJoinCanMerge(t *testing.T) { 48 testcases := [][]bool{ 49 {true, false, false, false, false /*not tested*/, false, false, false, false, true, false, false}, 50 {false, true, false, false, false /*not tested*/, false, false, false, false, true, false, false}, 51 {false, false, false, false, false /*not tested*/, false, false, false, false, true, false, false}, 52 {false, false, false, false, false /*not tested*/, false, false, false, false, true, false, false}, 53 {false, false, false, false, false /*not tested*/, false, false, false, false, true, false, false}, 54 55 {false, false, false, false, false, false, false, false, false, false, false, false}, // this whole line is not tested 56 57 {false, false, false, false, false /*not tested*/, false, false, false, false, true, false, false}, 58 {false, false, false, false, false /*not tested*/, false, false, false, false, true, false, false}, 59 {false, false, false, false, false /*not tested*/, false, false, false, true, true, false, false}, 60 {true, true, true, true, true /*not tested*/, false, true, true, true, true, true, true}, 61 {false, false, false, false, false /*not tested*/, false, false, false, false, true, false, false}, 62 {false, false, false, false, false /*not tested*/, false, false, false, false, true, false, false}, 63 } 64 65 ks := &vindexes.Keyspace{} 66 for left, vals := range testcases { 67 for right, val := range vals { 68 name := fmt.Sprintf("%s:%s", engine.Opcode(left).String(), engine.Opcode(right).String()) 69 if left == int(engine.SubShard) || right == int(engine.SubShard) { 70 continue // not used by v3 71 } 72 73 t.Run(name, func(t *testing.T) { 74 lRoute := &route{ 75 // Setting condition will make SelectEqualUnique match itself. 76 condition: &sqlparser.ColName{}, 77 } 78 pb := &primitiveBuilder{ 79 plan: lRoute, 80 } 81 rRoute := &route{ 82 condition: &sqlparser.ColName{}, 83 } 84 lRoute.eroute = engine.NewSimpleRoute(engine.Opcode(left), ks) 85 rRoute.eroute = engine.NewSimpleRoute(engine.Opcode(right), ks) 86 assert.Equal(t, val, lRoute.JoinCanMerge(pb, rRoute, nil, nil), fmt.Sprintf("%v:%v", lRoute.eroute.RouteType(), rRoute.eroute.RouteType())) 87 }) 88 } 89 } 90 } 91 92 func TestSubqueryCanMerge(t *testing.T) { 93 testcases := [][]bool{ 94 // US EU E IN ME subShard scatter nxt dba ref none byD 95 {true, false, false, false, false /*not tested*/, false, false, false, false, true, false, false}, // unsharded 96 {false, false, false, false, false /*not tested*/, false, false, false, false, true, false, false}, // equalUnique 97 {false, false, false, false, false /*not tested*/, false, false, false, false, false, false, false}, // equal 98 {false, false, false, false, false /*not tested*/, false, false, false, false, false, false, false}, // in 99 {false, false, false, false, false /*not tested*/, false, false, false, false, false, false, false}, // multiEqual 100 101 {false, false, false, false, false, false, false, false, false, false, false, false, false}, // subshard - this whole line is not tested 102 103 {false, false, false, false, false /*not tested*/, false, false, false, false, false, false, false}, // scatter 104 {false, false, false, false, false /*not tested*/, false, false, false, false, true, false, false}, // next 105 {false, false, false, false, false /*not tested*/, false, false, false, true, true, false, false}, // dba 106 {true, true, false, false, false /*not tested*/, false, false, true, true, true, false, false}, // reference 107 {false, false, false, false, false /*not tested*/, false, false, false, false, false, false, false}, // none 108 {false, false, false, false, false /*not tested*/, false, false, false, false, false, false, false}, // byDestination 109 } 110 111 ks := &vindexes.Keyspace{} 112 lRoute := &route{} 113 pb := &primitiveBuilder{ 114 plan: lRoute, 115 } 116 rRoute := &route{} 117 for left, vals := range testcases { 118 lRoute.eroute = engine.NewSimpleRoute(engine.Opcode(left), ks) 119 for right, val := range vals { 120 name := fmt.Sprintf("%s:%s", engine.Opcode(left).String(), engine.Opcode(right).String()) 121 t.Run(name, func(t *testing.T) { 122 if left == int(engine.SubShard) || right == int(engine.SubShard) { 123 t.Skip("not used by v3") 124 } 125 126 rRoute.eroute = engine.NewSimpleRoute(engine.Opcode(right), ks) 127 assert.Equal(t, val, lRoute.SubqueryCanMerge(pb, rRoute), fmt.Sprintf("%v:%v", lRoute.eroute.RouteType(), rRoute.eroute.RouteType())) 128 }) 129 } 130 } 131 } 132 133 func TestUnionCanMerge(t *testing.T) { 134 testcases := [][]bool{ 135 {true, false, false, false, false /*not tested*/, false, false, false, false, false, false, false}, 136 {false, false, false, false, false /*not tested*/, false, false, false, false, false, false, false}, 137 {false, false, false, false, false /*not tested*/, false, false, false, false, false, false, false}, 138 {false, false, false, false, false /*not tested*/, false, false, false, false, false, false, false}, 139 {false, false, false, false, false /*not tested*/, false, false, false, false, false, false, false}, 140 141 {false, false, false, false, false, false, false, false, false, false, false, false, false}, // this whole line is not tested 142 143 {false, false, false, false, false /*not tested*/, false, true, false, false, false, false, false}, 144 {false, false, false, false, false /*not tested*/, false, false, false, false, false, false, false}, 145 {false, false, false, false, false /*not tested*/, false, false, false, true, false, false, false}, 146 {false, false, false, false, false /*not tested*/, false, false, false, false, true, false, false}, 147 {false, false, false, false, false /*not tested*/, false, false, false, false, false, false, false}, 148 {false, false, false, false, false /*not tested*/, false, false, false, false, false, false, false}, 149 } 150 151 ks := &vindexes.Keyspace{} 152 lRoute := &route{} 153 rRoute := &route{} 154 for left, vals := range testcases { 155 lRoute.eroute = engine.NewSimpleRoute(engine.Opcode(left), ks) 156 for right, val := range vals { 157 name := fmt.Sprintf("%s:%s", engine.Opcode(left).String(), engine.Opcode(right).String()) 158 t.Run(name, func(t *testing.T) { 159 if left == int(engine.SubShard) || right == int(engine.SubShard) { 160 t.Skip("not used by v3") 161 } 162 163 rRoute.eroute = engine.NewSimpleRoute(engine.Opcode(right), ks) 164 assert.Equal(t, val, lRoute.unionCanMerge(rRoute, false), fmt.Sprintf("can't create a single route from these two inputs %v:%v", lRoute.eroute.RouteType(), rRoute.eroute.RouteType())) 165 }) 166 } 167 } 168 }