github.com/cockroachdb/cockroach@v20.2.0-alpha.1+incompatible/pkg/sql/opt/ordering/lookup_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"
    17  	"github.com/cockroachdb/cockroach/pkg/sql/opt/props/physical"
    18  )
    19  
    20  func lookupOrIndexJoinCanProvideOrdering(
    21  	expr memo.RelExpr, required *physical.OrderingChoice,
    22  ) bool {
    23  	// LookupJoin and IndexJoin can pass through their ordering if the ordering
    24  	// depends only on columns present in the input.
    25  	inputCols := expr.Child(0).(memo.RelExpr).Relational().OutputCols
    26  	return required.CanProjectCols(inputCols)
    27  }
    28  
    29  func lookupOrIndexJoinBuildChildReqOrdering(
    30  	parent memo.RelExpr, required *physical.OrderingChoice, childIdx int,
    31  ) physical.OrderingChoice {
    32  	if childIdx != 0 {
    33  		return physical.OrderingChoice{}
    34  	}
    35  
    36  	// We may need to remove ordering columns that are not output by the input
    37  	// expression.
    38  	child := parent.Child(0).(memo.RelExpr)
    39  	res := projectOrderingToInput(child, required)
    40  	// It is in principle possible that the lookup join has an ON condition that
    41  	// forces an equality on two columns in the input. In this case we need to
    42  	// trim the column groups to keep the ordering valid w.r.t the child FDs
    43  	// (similar to Select).
    44  	//
    45  	// This case indicates that we didn't do a good job pushing down equalities
    46  	// (see #36219), but it should be handled correctly here nevertheless.
    47  	return trimColumnGroups(&res, &child.Relational().FuncDeps)
    48  }
    49  
    50  func indexJoinBuildProvided(expr memo.RelExpr, required *physical.OrderingChoice) opt.Ordering {
    51  	// If an index join has a requirement on some input columns, those columns
    52  	// must be output columns (or equivalent to them). We may still need to remap
    53  	// using column equivalencies.
    54  	indexJoin := expr.(*memo.IndexJoinExpr)
    55  	rel := indexJoin.Relational()
    56  	return remapProvided(indexJoin.Input.ProvidedPhysical().Ordering, &rel.FuncDeps, rel.OutputCols)
    57  }
    58  
    59  func lookupJoinBuildProvided(expr memo.RelExpr, required *physical.OrderingChoice) opt.Ordering {
    60  	lookupJoin := expr.(*memo.LookupJoinExpr)
    61  	childProvided := lookupJoin.Input.ProvidedPhysical().Ordering
    62  
    63  	// The lookup join includes an implicit projection (lookupJoin.Cols); some of
    64  	// the input columns might not be output columns so we may need to remap them.
    65  	// First check if we need to.
    66  	needsRemap := false
    67  	for i := range childProvided {
    68  		if !lookupJoin.Cols.Contains(childProvided[i].ID()) {
    69  			needsRemap = true
    70  			break
    71  		}
    72  	}
    73  	if !needsRemap {
    74  		// Fast path: we don't need to remap any columns.
    75  		return childProvided
    76  	}
    77  
    78  	// Because of the implicit projection, the FDs of the LookupJoin don't include
    79  	// all the columns we care about; we have to recreate the FDs of the join
    80  	// before the projection. These are the FDs of the input plus the equality
    81  	// constraints implied by the lookup join.
    82  	var fds props.FuncDepSet
    83  	fds.CopyFrom(&lookupJoin.Input.Relational().FuncDeps)
    84  
    85  	md := lookupJoin.Memo().Metadata()
    86  	index := md.Table(lookupJoin.Table).Index(lookupJoin.Index)
    87  	for i, colID := range lookupJoin.KeyCols {
    88  		indexColID := lookupJoin.Table.ColumnID(index.Column(i).Ordinal)
    89  		fds.AddEquivalency(colID, indexColID)
    90  	}
    91  
    92  	return remapProvided(childProvided, &fds, lookupJoin.Cols)
    93  }