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 }