github.com/cockroachdb/cockroach@v20.2.0-alpha.1+incompatible/pkg/sql/opt/ordering/project.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 projectCanProvideOrdering(expr memo.RelExpr, required *physical.OrderingChoice) bool {
    20  	// Project can pass through its ordering if the ordering depends only on
    21  	// columns present in the input.
    22  	proj := expr.(*memo.ProjectExpr)
    23  	inputCols := proj.Input.Relational().OutputCols
    24  
    25  	if required.CanProjectCols(inputCols) {
    26  		return true
    27  	}
    28  
    29  	// We may be able to "remap" columns using the internal FD set.
    30  	if fdSet := proj.InternalFDs(); required.CanSimplify(fdSet) {
    31  		simplified := required.Copy()
    32  		simplified.Simplify(fdSet)
    33  		return simplified.CanProjectCols(inputCols)
    34  	}
    35  
    36  	return false
    37  }
    38  
    39  func projectBuildChildReqOrdering(
    40  	parent memo.RelExpr, required *physical.OrderingChoice, childIdx int,
    41  ) physical.OrderingChoice {
    42  	if childIdx != 0 {
    43  		return physical.OrderingChoice{}
    44  	}
    45  
    46  	// Project can prune input columns, which can cause its FD set to be
    47  	// pruned as well. Check the ordering to see if it can be simplified
    48  	// with respect to the internal FD set.
    49  	proj := parent.(*memo.ProjectExpr)
    50  	simplified := *required
    51  	if fdSet := proj.InternalFDs(); simplified.CanSimplify(fdSet) {
    52  		simplified = simplified.Copy()
    53  		simplified.Simplify(fdSet)
    54  	}
    55  
    56  	// We may need to remove ordering columns that are not output by the input
    57  	// expression.
    58  	result := projectOrderingToInput(proj.Input, &simplified)
    59  
    60  	return result
    61  }
    62  
    63  // projectOrderingToInput projects out columns from an ordering (if necessary);
    64  // can only be used if the ordering can be expressed in terms of the input
    65  // columns. If projection is not necessary, returns a shallow copy of the
    66  // ordering.
    67  func projectOrderingToInput(
    68  	input memo.RelExpr, ordering *physical.OrderingChoice,
    69  ) physical.OrderingChoice {
    70  	childOutCols := input.Relational().OutputCols
    71  	if ordering.SubsetOfCols(childOutCols) {
    72  		return *ordering
    73  	}
    74  	result := ordering.Copy()
    75  	result.ProjectCols(childOutCols)
    76  	return result
    77  }
    78  
    79  func projectBuildProvided(expr memo.RelExpr, required *physical.OrderingChoice) opt.Ordering {
    80  	p := expr.(*memo.ProjectExpr)
    81  	// Project can only satisfy required orderings that refer to projected
    82  	// columns; it should always be possible to remap the columns in the input's
    83  	// provided ordering.
    84  	return remapProvided(
    85  		p.Input.ProvidedPhysical().Ordering,
    86  		p.InternalFDs(),
    87  		p.Relational().OutputCols,
    88  	)
    89  }