github.com/cockroachdb/cockroach@v20.2.0-alpha.1+incompatible/pkg/sql/opt/ordering/merge_join.go (about) 1 // Copyright 2018 The Cockroach Authors. 2 // 3 // Use of this software is governed by the Business Source License 4 // included in the file licenses/BSL.txt. 5 // 6 // As of the Change Date specified in that file, in accordance with 7 // the Business Source License, use of this software will be governed 8 // by the Apache License, Version 2.0, included in the file 9 // licenses/APL.txt. 10 11 package ordering 12 13 import ( 14 "github.com/cockroachdb/cockroach/pkg/sql/opt" 15 "github.com/cockroachdb/cockroach/pkg/sql/opt/memo" 16 "github.com/cockroachdb/cockroach/pkg/sql/opt/props/physical" 17 ) 18 19 func mergeJoinCanProvideOrdering(expr memo.RelExpr, required *physical.OrderingChoice) bool { 20 m := expr.(*memo.MergeJoinExpr) 21 // TODO(radu): in principle, we could pass through an ordering that covers 22 // more than the equality columns. For example, if we have a merge join 23 // with left ordering a+,b+ and right ordering x+,y+ we could guarantee 24 // a+,b+,c+ if we pass that requirement through to the left side. However, 25 // this requires a specific contract on the execution side on which side's 26 // ordering is preserved when multiple rows match on the equality columns. 27 switch m.JoinType { 28 case opt.InnerJoinOp: 29 return m.LeftOrdering.Implies(required) || m.RightOrdering.Implies(required) 30 31 case opt.LeftJoinOp, opt.SemiJoinOp, opt.AntiJoinOp: 32 return m.LeftOrdering.Implies(required) 33 34 case opt.RightJoinOp: 35 return m.RightOrdering.Implies(required) 36 37 default: 38 return false 39 } 40 } 41 42 func mergeJoinBuildChildReqOrdering( 43 parent memo.RelExpr, required *physical.OrderingChoice, childIdx int, 44 ) physical.OrderingChoice { 45 switch childIdx { 46 case 0: 47 return parent.(*memo.MergeJoinExpr).LeftOrdering 48 case 1: 49 return parent.(*memo.MergeJoinExpr).RightOrdering 50 default: 51 return physical.OrderingChoice{} 52 } 53 } 54 55 func mergeJoinBuildProvided(expr memo.RelExpr, required *physical.OrderingChoice) opt.Ordering { 56 m := expr.(*memo.MergeJoinExpr) 57 // This code parallels the one in mergeJoinCanProvideOrdering: the required 58 // ordering has to be provided by one of the inputs (as allowed by the join 59 // type). 60 var provided opt.Ordering 61 switch m.JoinType { 62 case opt.InnerJoinOp: 63 if m.LeftOrdering.Implies(required) { 64 provided = m.Left.ProvidedPhysical().Ordering 65 } else { 66 provided = m.Right.ProvidedPhysical().Ordering 67 } 68 69 case opt.LeftJoinOp, opt.SemiJoinOp, opt.AntiJoinOp: 70 provided = m.Left.ProvidedPhysical().Ordering 71 72 case opt.RightJoinOp: 73 provided = m.Right.ProvidedPhysical().Ordering 74 } 75 // The input's ordering satisfies both <required> and the ordering required by 76 // the merge join itself; it may need to be trimmed. 77 return trimProvided(provided, required, &expr.Relational().FuncDeps) 78 }