github.com/cockroachdb/cockroach@v20.2.0-alpha.1+incompatible/pkg/sql/opt/ordering/group_by.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 scalarGroupByBuildChildReqOrdering(
    20  	parent memo.RelExpr, required *physical.OrderingChoice, childIdx int,
    21  ) physical.OrderingChoice {
    22  	if childIdx != 0 {
    23  		return physical.OrderingChoice{}
    24  	}
    25  	// Scalar group by requires the ordering in its private.
    26  	return parent.(*memo.ScalarGroupByExpr).Ordering
    27  }
    28  
    29  func groupByCanProvideOrdering(expr memo.RelExpr, required *physical.OrderingChoice) bool {
    30  	// GroupBy may require a certain ordering of its input, but can also pass
    31  	// through a stronger ordering on the grouping columns.
    32  	groupBy := expr.(*memo.GroupByExpr)
    33  	return required.CanProjectCols(groupBy.GroupingCols) && required.Intersects(&groupBy.Ordering)
    34  }
    35  
    36  func groupByBuildChildReqOrdering(
    37  	parent memo.RelExpr, required *physical.OrderingChoice, childIdx int,
    38  ) physical.OrderingChoice {
    39  	if childIdx != 0 {
    40  		return physical.OrderingChoice{}
    41  	}
    42  	groupBy := parent.(*memo.GroupByExpr)
    43  	result := *required
    44  	if !result.SubsetOfCols(groupBy.GroupingCols) {
    45  		result = result.Copy()
    46  		result.ProjectCols(groupBy.GroupingCols)
    47  	}
    48  
    49  	result = result.Intersection(&groupBy.Ordering)
    50  
    51  	// The FD set of the input doesn't "pass through" to the GroupBy FD set;
    52  	// check the ordering to see if it can be simplified with respect to the
    53  	// input FD set.
    54  	result.Simplify(&groupBy.Input.Relational().FuncDeps)
    55  
    56  	return result
    57  }
    58  
    59  func groupByBuildProvided(expr memo.RelExpr, required *physical.OrderingChoice) opt.Ordering {
    60  	groupBy := expr.(*memo.GroupByExpr)
    61  	provided := groupBy.Input.ProvidedPhysical().Ordering
    62  	inputFDs := &groupBy.Input.Relational().FuncDeps
    63  
    64  	// Since the input's provided ordering has to satisfy both <required> and the
    65  	// GroupBy internal ordering, it may need to be trimmed.
    66  	provided = trimProvided(provided, required, inputFDs)
    67  	return remapProvided(provided, inputFDs, groupBy.GroupingCols)
    68  }
    69  
    70  func distinctOnCanProvideOrdering(expr memo.RelExpr, required *physical.OrderingChoice) bool {
    71  	// DistinctOn may require a certain ordering of its input, but can also pass
    72  	// through a stronger ordering on the grouping columns.
    73  	return required.Intersects(&expr.Private().(*memo.GroupingPrivate).Ordering)
    74  }
    75  
    76  func distinctOnBuildChildReqOrdering(
    77  	parent memo.RelExpr, required *physical.OrderingChoice, childIdx int,
    78  ) physical.OrderingChoice {
    79  	if childIdx != 0 {
    80  		return physical.OrderingChoice{}
    81  	}
    82  	// The FD set of the input doesn't "pass through" to the DistinctOn FD set;
    83  	// check the ordering to see if it can be simplified with respect to the input
    84  	// FD set.
    85  	result := required.Intersection(&parent.Private().(*memo.GroupingPrivate).Ordering)
    86  	result.Simplify(&parent.Child(0).(memo.RelExpr).Relational().FuncDeps)
    87  	return result
    88  }
    89  
    90  func distinctOnBuildProvided(expr memo.RelExpr, required *physical.OrderingChoice) opt.Ordering {
    91  	input := expr.Child(0).(memo.RelExpr)
    92  	provided := input.ProvidedPhysical().Ordering
    93  	inputFDs := &input.Relational().FuncDeps
    94  	// Since the input's provided ordering has to satisfy both <required> and the
    95  	// DistinctOn internal ordering, it may need to be trimmed.
    96  	provided = trimProvided(provided, required, inputFDs)
    97  	return remapProvided(provided, inputFDs, expr.Relational().OutputCols)
    98  }
    99  
   100  // StreamingGroupingColOrdering returns an ordering on grouping columns that is
   101  // guaranteed on the input of an aggregation operator. This ordering can be used
   102  // perform a streaming aggregation.
   103  func StreamingGroupingColOrdering(
   104  	g *memo.GroupingPrivate, required *physical.OrderingChoice,
   105  ) opt.Ordering {
   106  	inputOrdering := required.Intersection(&g.Ordering)
   107  	ordering := make(opt.Ordering, len(inputOrdering.Columns))
   108  	for i := range inputOrdering.Columns {
   109  		// Get any grouping column from the set. Normally there would be at most one
   110  		// because we have rules that remove redundant grouping columns.
   111  		cols := inputOrdering.Columns[i].Group.Intersection(g.GroupingCols)
   112  		colID, ok := cols.Next(0)
   113  		if !ok {
   114  			// This group refers to a column that is not a grouping column.
   115  			// The rest of the ordering is not useful.
   116  			return ordering[:i]
   117  		}
   118  		ordering[i] = opt.MakeOrderingColumn(colID, inputOrdering.Columns[i].Descending)
   119  	}
   120  	return ordering
   121  }