vitess.io/vitess@v0.16.2/go/vt/vtgate/planbuilder/operators/join.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/operators/rewrite" 23 "vitess.io/vitess/go/vt/vtgate/planbuilder/plancontext" 24 ) 25 26 // Join represents a join. If we have a predicate, this is an inner join. If no predicate exists, it is a cross join 27 type Join struct { 28 LHS, RHS ops.Operator 29 Predicate sqlparser.Expr 30 LeftJoin bool 31 32 noColumns 33 } 34 35 var _ ops.Operator = (*Join)(nil) 36 37 // Clone implements the Operator interface 38 func (j *Join) Clone(inputs []ops.Operator) ops.Operator { 39 clone := *j 40 clone.LHS = inputs[0] 41 clone.RHS = inputs[1] 42 return &Join{ 43 LHS: inputs[0], 44 RHS: inputs[1], 45 Predicate: j.Predicate, 46 LeftJoin: j.LeftJoin, 47 } 48 } 49 50 // Inputs implements the Operator interface 51 func (j *Join) Inputs() []ops.Operator { 52 return []ops.Operator{j.LHS, j.RHS} 53 } 54 55 func (j *Join) Compact(ctx *plancontext.PlanningContext) (ops.Operator, rewrite.TreeIdentity, error) { 56 if j.LeftJoin { 57 // we can't merge outer joins into a single QG 58 return j, rewrite.SameTree, nil 59 } 60 61 lqg, lok := j.LHS.(*QueryGraph) 62 rqg, rok := j.RHS.(*QueryGraph) 63 if !lok || !rok { 64 return j, rewrite.SameTree, nil 65 } 66 67 newOp := &QueryGraph{ 68 Tables: append(lqg.Tables, rqg.Tables...), 69 innerJoins: append(lqg.innerJoins, rqg.innerJoins...), 70 NoDeps: ctx.SemTable.AndExpressions(lqg.NoDeps, rqg.NoDeps), 71 } 72 if j.Predicate != nil { 73 err := newOp.collectPredicate(ctx, j.Predicate) 74 if err != nil { 75 return nil, rewrite.SameTree, err 76 } 77 } 78 return newOp, rewrite.NewTree, nil 79 } 80 81 func createOuterJoin(tableExpr *sqlparser.JoinTableExpr, lhs, rhs ops.Operator) (ops.Operator, error) { 82 if tableExpr.Join == sqlparser.RightJoinType { 83 lhs, rhs = rhs, lhs 84 } 85 predicate := tableExpr.Condition.On 86 sqlparser.RemoveKeyspaceFromColName(predicate) 87 return &Join{LHS: lhs, RHS: rhs, LeftJoin: true, Predicate: predicate}, nil 88 } 89 90 func createJoin(ctx *plancontext.PlanningContext, LHS, RHS ops.Operator) ops.Operator { 91 lqg, lok := LHS.(*QueryGraph) 92 rqg, rok := RHS.(*QueryGraph) 93 if lok && rok { 94 op := &QueryGraph{ 95 Tables: append(lqg.Tables, rqg.Tables...), 96 innerJoins: append(lqg.innerJoins, rqg.innerJoins...), 97 NoDeps: ctx.SemTable.AndExpressions(lqg.NoDeps, rqg.NoDeps), 98 } 99 return op 100 } 101 return &Join{LHS: LHS, RHS: RHS} 102 } 103 104 func createInnerJoin(ctx *plancontext.PlanningContext, tableExpr *sqlparser.JoinTableExpr, lhs, rhs ops.Operator) (ops.Operator, error) { 105 op := createJoin(ctx, lhs, rhs) 106 pred := tableExpr.Condition.On 107 if pred != nil { 108 var err error 109 sqlparser.RemoveKeyspaceFromColName(pred) 110 op, err = op.AddPredicate(ctx, pred) 111 if err != nil { 112 return nil, err 113 } 114 } 115 return op, nil 116 } 117 118 func (j *Join) AddPredicate(ctx *plancontext.PlanningContext, expr sqlparser.Expr) (ops.Operator, error) { 119 return AddPredicate(j, ctx, expr, false, newFilter) 120 } 121 122 var _ JoinOp = (*Join)(nil) 123 124 func (j *Join) GetLHS() ops.Operator { 125 return j.LHS 126 } 127 128 func (j *Join) GetRHS() ops.Operator { 129 return j.RHS 130 } 131 132 func (j *Join) SetLHS(operator ops.Operator) { 133 j.LHS = operator 134 } 135 136 func (j *Join) SetRHS(operator ops.Operator) { 137 j.RHS = operator 138 } 139 140 func (j *Join) MakeInner() { 141 j.LeftJoin = false 142 } 143 144 func (j *Join) IsInner() bool { 145 return !j.LeftJoin 146 } 147 148 func (j *Join) AddJoinPredicate(ctx *plancontext.PlanningContext, expr sqlparser.Expr) error { 149 j.Predicate = ctx.SemTable.AndExpressions(j.Predicate, expr) 150 return nil 151 }