github.com/cockroachdb/cockroach@v20.2.0-alpha.1+incompatible/pkg/sql/join_predicate.go (about) 1 // Copyright 2016 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 sql 12 13 import ( 14 "github.com/cockroachdb/cockroach/pkg/sql/sem/tree" 15 "github.com/cockroachdb/cockroach/pkg/sql/sqlbase" 16 "github.com/cockroachdb/cockroach/pkg/sql/types" 17 "github.com/cockroachdb/cockroach/pkg/util" 18 ) 19 20 // joinPredicate implements the predicate logic for joins. 21 type joinPredicate struct { 22 // This struct must be allocated on the heap and its location stay 23 // stable after construction because it implements 24 // IndexedVarContainer and the IndexedVar objects in sub-expressions 25 // will link to it by reference after checkRenderStar / analyzeExpr. 26 // Enforce this using NoCopy. 27 _ util.NoCopy 28 29 joinType sqlbase.JoinType 30 31 // numLeft/RightCols are the number of columns in the left and right 32 // operands. 33 numLeftCols, numRightCols int 34 35 // left/rightEqualityIndices give the position of equality columns 36 // on the left and right input row arrays, respectively. 37 // Only columns with the same left and right value types can be equality 38 // columns. 39 leftEqualityIndices []int 40 rightEqualityIndices []int 41 42 // The list of names for the columns listed in leftEqualityIndices. 43 // Used mainly for pretty-printing. 44 leftColNames tree.NameList 45 // The list of names for the columns listed in rightEqualityIndices. 46 // Used mainly for pretty-printing. 47 rightColNames tree.NameList 48 49 // For ON predicates or joins with an added filter expression, 50 // we need an IndexedVarHelper, the DataSourceInfo, a row buffer 51 // and the expression itself. 52 iVarHelper tree.IndexedVarHelper 53 curRow tree.Datums 54 // The ON condition that needs to be evaluated (in addition to the 55 // equality columns). 56 onCond tree.TypedExpr 57 58 leftCols sqlbase.ResultColumns 59 rightCols sqlbase.ResultColumns 60 cols sqlbase.ResultColumns 61 62 // If set, the left equality columns form a key in the left input. Used as a 63 // hint for optimizing execution. 64 leftEqKey bool 65 // If set, the right equality columns form a key in the right input. Used as a 66 // hint for optimizing execution. 67 rightEqKey bool 68 } 69 70 // makePredicate constructs a joinPredicate object for joins. The equality 71 // columns / on condition must be initialized separately. 72 func makePredicate( 73 joinType sqlbase.JoinType, left, right sqlbase.ResultColumns, 74 ) (*joinPredicate, error) { 75 // For anti and semi joins, the right columns are omitted from the output (but 76 // they must be available internally for the ON condition evaluation). 77 omitRightColumns := joinType == sqlbase.LeftSemiJoin || joinType == sqlbase.LeftAntiJoin 78 79 // Prepare the metadata for the result columns. 80 // The structure of the join data source results is like this: 81 // - all the left columns, 82 // - then all the right columns (except for anti/semi join). 83 columns := make(sqlbase.ResultColumns, 0, len(left)+len(right)) 84 columns = append(columns, left...) 85 if !omitRightColumns { 86 columns = append(columns, right...) 87 } 88 89 pred := &joinPredicate{ 90 joinType: joinType, 91 numLeftCols: len(left), 92 numRightCols: len(right), 93 leftCols: left, 94 rightCols: right, 95 cols: columns, 96 } 97 // We must initialize the indexed var helper in all cases, even when 98 // there is no on condition, so that getNeededColumns() does not get 99 // confused. 100 pred.curRow = make(tree.Datums, len(left)+len(right)) 101 pred.iVarHelper = tree.MakeIndexedVarHelper(pred, len(pred.curRow)) 102 103 return pred, nil 104 } 105 106 // IndexedVarEval implements the tree.IndexedVarContainer interface. 107 func (p *joinPredicate) IndexedVarEval(idx int, ctx *tree.EvalContext) (tree.Datum, error) { 108 return p.curRow[idx].Eval(ctx) 109 } 110 111 // IndexedVarResolvedType implements the tree.IndexedVarContainer interface. 112 func (p *joinPredicate) IndexedVarResolvedType(idx int) *types.T { 113 if idx < p.numLeftCols { 114 return p.leftCols[idx].Typ 115 } 116 return p.rightCols[idx-p.numLeftCols].Typ 117 } 118 119 // IndexedVarNodeFormatter implements the tree.IndexedVarContainer interface. 120 func (p *joinPredicate) IndexedVarNodeFormatter(idx int) tree.NodeFormatter { 121 if idx < p.numLeftCols { 122 return p.leftCols.NodeFormatter(idx) 123 } 124 return p.rightCols.NodeFormatter(idx - p.numLeftCols) 125 } 126 127 // eval for joinPredicate runs the on condition across the columns that do 128 // not participate in the equality (the equality columns are checked 129 // in the join algorithm already). 130 // Returns true if there is no on condition or the on condition accepts the 131 // row. 132 func (p *joinPredicate) eval(ctx *tree.EvalContext, leftRow, rightRow tree.Datums) (bool, error) { 133 if p.onCond != nil { 134 copy(p.curRow[:len(leftRow)], leftRow) 135 copy(p.curRow[len(leftRow):], rightRow) 136 ctx.PushIVarContainer(p.iVarHelper.Container()) 137 pred, err := sqlbase.RunFilter(p.onCond, ctx) 138 ctx.PopIVarContainer() 139 return pred, err 140 } 141 return true, nil 142 } 143 144 // prepareRow prepares the output row by combining values from the 145 // input data sources. 146 func (p *joinPredicate) prepareRow(result, leftRow, rightRow tree.Datums) { 147 copy(result[:len(leftRow)], leftRow) 148 copy(result[len(leftRow):], rightRow) 149 }