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 }