vitess.io/vitess@v0.16.2/go/vt/vtgate/planbuilder/operators/querygraph.go (about) 1 /* 2 Copyright 2021 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 operators 18 19 import ( 20 "vitess.io/vitess/go/vt/sqlparser" 21 "vitess.io/vitess/go/vt/vtgate/planbuilder/operators/ops" 22 "vitess.io/vitess/go/vt/vtgate/planbuilder/plancontext" 23 "vitess.io/vitess/go/vt/vtgate/semantics" 24 ) 25 26 type ( 27 /*QueryGraph represents the FROM and WHERE parts of a query. 28 It is an intermediate representation of the query that makes it easier for the planner 29 to find all possible join combinations. Instead of storing the query information in a form that is close 30 to the syntax (AST), we extract the interesting parts into a graph form with the nodes being tables in the FROM 31 clause and the edges between them being predicates. We keep predicates in a hash map keyed by the dependencies of 32 the predicate. This makes it very fast to look up connections between tables in the query. 33 */ 34 QueryGraph struct { 35 // the Tables, including predicates that only depend on this particular table 36 Tables []*QueryTable 37 38 // innerJoins contains the predicates that need multiple Tables 39 innerJoins []*innerJoin 40 41 // NoDeps contains the predicates that can be evaluated anywhere. 42 NoDeps sqlparser.Expr 43 44 noInputs 45 noColumns 46 } 47 48 innerJoin struct { 49 deps semantics.TableSet 50 exprs []sqlparser.Expr 51 } 52 53 // QueryTable is a single FROM table, including all predicates particular to this table 54 // This is to be used as an immutable data structure which is created in the logical Operator Tree 55 QueryTable struct { 56 ID semantics.TableSet 57 Alias *sqlparser.AliasedTableExpr 58 Table sqlparser.TableName 59 Predicates []sqlparser.Expr 60 IsInfSchema bool 61 } 62 ) 63 64 var _ ops.Operator = (*QueryGraph)(nil) 65 66 // Introduces implements the TableIDIntroducer interface 67 func (qg *QueryGraph) Introduces() semantics.TableSet { 68 var ts semantics.TableSet 69 for _, table := range qg.Tables { 70 ts = ts.Merge(table.ID) 71 } 72 return ts 73 } 74 75 // GetPredicates returns the predicates that are applicable for the two given TableSets 76 func (qg *QueryGraph) GetPredicates(lhs, rhs semantics.TableSet) []sqlparser.Expr { 77 var allExprs []sqlparser.Expr 78 for _, join := range qg.innerJoins { 79 tableSet, exprs := join.deps, join.exprs 80 if tableSet.IsSolvedBy(lhs.Merge(rhs)) && 81 tableSet.IsOverlapping(rhs) && 82 tableSet.IsOverlapping(lhs) { 83 allExprs = append(allExprs, exprs...) 84 } 85 } 86 return allExprs 87 } 88 89 func newQueryGraph() *QueryGraph { 90 return &QueryGraph{} 91 } 92 93 func (qg *QueryGraph) collectPredicates(ctx *plancontext.PlanningContext, sel *sqlparser.Select) error { 94 predicates := sqlparser.SplitAndExpression(nil, sel.Where.Expr) 95 96 for _, predicate := range predicates { 97 err := qg.collectPredicate(ctx, predicate) 98 if err != nil { 99 return err 100 } 101 } 102 return nil 103 } 104 105 func (qg *QueryGraph) getPredicateByDeps(ts semantics.TableSet) ([]sqlparser.Expr, bool) { 106 for _, join := range qg.innerJoins { 107 if join.deps == ts { 108 return join.exprs, true 109 } 110 } 111 return nil, false 112 } 113 func (qg *QueryGraph) addJoinPredicates(ctx *plancontext.PlanningContext, ts semantics.TableSet, predicate sqlparser.Expr) { 114 for _, join := range qg.innerJoins { 115 if join.deps == ts { 116 if ctx.SemTable.ContainsExpr(predicate, join.exprs) { 117 return 118 } 119 120 join.exprs = append(join.exprs, predicate) 121 return 122 } 123 } 124 125 qg.innerJoins = append(qg.innerJoins, &innerJoin{ 126 deps: ts, 127 exprs: []sqlparser.Expr{predicate}, 128 }) 129 } 130 131 func (qg *QueryGraph) collectPredicate(ctx *plancontext.PlanningContext, predicate sqlparser.Expr) error { 132 deps := ctx.SemTable.RecursiveDeps(predicate) 133 switch deps.NumberOfTables() { 134 case 0: 135 qg.addNoDepsPredicate(predicate) 136 case 1: 137 found := qg.addToSingleTable(ctx, deps, predicate) 138 if !found { 139 // this could be a predicate that only has dependencies from outside this QG 140 qg.addJoinPredicates(ctx, deps, predicate) 141 } 142 default: 143 qg.addJoinPredicates(ctx, deps, predicate) 144 } 145 return nil 146 } 147 148 func (qg *QueryGraph) addToSingleTable(ctx *plancontext.PlanningContext, table semantics.TableSet, predicate sqlparser.Expr) bool { 149 for _, t := range qg.Tables { 150 if table == t.ID { 151 if !ctx.SemTable.ContainsExpr(predicate, t.Predicates) { 152 t.Predicates = append(t.Predicates, predicate) 153 } 154 return true 155 } 156 } 157 return false 158 } 159 160 func (qg *QueryGraph) addNoDepsPredicate(predicate sqlparser.Expr) { 161 if qg.NoDeps == nil { 162 qg.NoDeps = predicate 163 } else { 164 qg.NoDeps = &sqlparser.AndExpr{ 165 Left: qg.NoDeps, 166 Right: predicate, 167 } 168 } 169 } 170 171 // UnsolvedPredicates implements the unresolved interface 172 func (qg *QueryGraph) UnsolvedPredicates(_ *semantics.SemTable) []sqlparser.Expr { 173 var result []sqlparser.Expr 174 tables := TableID(qg) 175 for _, join := range qg.innerJoins { 176 set, exprs := join.deps, join.exprs 177 if !set.IsSolvedBy(tables) { 178 result = append(result, exprs...) 179 } 180 } 181 return result 182 } 183 184 // Clone implements the Operator interface 185 func (qg *QueryGraph) Clone(inputs []ops.Operator) ops.Operator { 186 result := &QueryGraph{ 187 Tables: nil, 188 innerJoins: nil, 189 NoDeps: nil, 190 } 191 192 result.Tables = append([]*QueryTable{}, qg.Tables...) 193 result.innerJoins = append([]*innerJoin{}, qg.innerJoins...) 194 result.NoDeps = qg.NoDeps 195 return result 196 } 197 198 func (qg *QueryGraph) AddPredicate(ctx *plancontext.PlanningContext, expr sqlparser.Expr) (ops.Operator, error) { 199 for _, e := range sqlparser.SplitAndExpression(nil, expr) { 200 err := qg.collectPredicate(ctx, e) 201 if err != nil { 202 return nil, err 203 } 204 } 205 return qg, nil 206 } 207 208 // Clone implements the Operator interface 209 func (qt *QueryTable) Clone() *QueryTable { 210 return &QueryTable{ 211 ID: qt.ID, 212 Alias: sqlparser.CloneRefOfAliasedTableExpr(qt.Alias), 213 Table: sqlparser.CloneTableName(qt.Table), 214 Predicates: qt.Predicates, 215 IsInfSchema: qt.IsInfSchema, 216 } 217 }