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  }