github.com/cockroachdb/cockroach@v20.2.0-alpha.1+incompatible/pkg/sql/opt/ordering/row_number.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 ordinalityCanProvideOrdering(expr memo.RelExpr, required *physical.OrderingChoice) bool {
    20  	r := expr.(*memo.OrdinalityExpr)
    21  	prefix := ordinalityOrdPrefix(r, required)
    22  	if prefix < len(required.Columns) {
    23  		truncated := required.Copy()
    24  		truncated.Truncate(prefix)
    25  		return r.Ordering.Implies(&truncated)
    26  	}
    27  	return r.Ordering.Implies(required)
    28  }
    29  
    30  // ordinalityOrdPrefix is the length of the longest prefix of required.Columns
    31  // before the ordinality column (or the entire length if the ordinality column
    32  // is not in the required ordering).
    33  //
    34  // By construction, any prefix of the ordering internally required of the input
    35  // (i.e. OrdinalityPrivate.Ordering) is also ordered by the ordinality column.
    36  // For example, if the internal ordering is +a,+b, then the ord column numbers
    37  // rows in the +a,+b order and any of these required orderings can be provided:
    38  //   +ord
    39  //   +a,+ord
    40  //   +a,+b,+ord
    41  //
    42  // As long as normalization rules are enabled, they will have already reduced
    43  // the ordering required of this operator to take into account that the
    44  // ordinality column is a key, so there will not be ordering columns after the
    45  // ordinality column in that case.
    46  func ordinalityOrdPrefix(r *memo.OrdinalityExpr, required *physical.OrderingChoice) int {
    47  	ordCol := opt.MakeOrderingColumn(r.ColID, false /* descending */)
    48  	for i := range required.Columns {
    49  		if required.MatchesAt(i, ordCol) {
    50  			return i
    51  		}
    52  	}
    53  	return len(required.Columns)
    54  }
    55  
    56  func ordinalityBuildChildReqOrdering(
    57  	parent memo.RelExpr, required *physical.OrderingChoice, childIdx int,
    58  ) physical.OrderingChoice {
    59  	if childIdx != 0 {
    60  		return physical.OrderingChoice{}
    61  	}
    62  	// RowNumber always requires its internal ordering.
    63  	return parent.(*memo.OrdinalityExpr).Ordering
    64  }
    65  
    66  func ordinalityBuildProvided(expr memo.RelExpr, required *physical.OrderingChoice) opt.Ordering {
    67  	r := expr.(*memo.OrdinalityExpr)
    68  	childProvided := r.Input.ProvidedPhysical().Ordering
    69  	prefix := ordinalityOrdPrefix(r, required)
    70  	if prefix == len(required.Columns) {
    71  		// The required ordering doesn't contain the ordinality column, so it only
    72  		// refers to columns that are in the input.
    73  		return trimProvided(childProvided, required, &r.Relational().FuncDeps)
    74  	}
    75  
    76  	truncated := required.Copy()
    77  	truncated.Truncate(prefix)
    78  	// The input's provided ordering satisfies both <truncated> and the RowNumber
    79  	// internal ordering; it may need to be trimmed.
    80  	provided := trimProvided(childProvided, &truncated, &r.Relational().FuncDeps)
    81  	// Add the ordinality column to the provided ordering so that it satisfies
    82  	// <required>.
    83  	provided = append(
    84  		provided[:len(provided):len(provided)], // force reallocation
    85  		opt.MakeOrderingColumn(r.ColID, false /* descending */),
    86  	)
    87  	return provided
    88  }