github.com/cockroachdb/cockroach@v20.2.0-alpha.1+incompatible/pkg/sql/opt/props/physical/required.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 physical 12 13 import ( 14 "bytes" 15 "fmt" 16 17 "github.com/cockroachdb/cockroach/pkg/sql/opt" 18 ) 19 20 // Required properties are interesting characteristics of an expression that 21 // impact its layout, presentation, or location, but not its logical content. 22 // Examples include row order, column naming, and data distribution (physical 23 // location of data ranges). Physical properties exist outside of the relational 24 // algebra, and arise from both the SQL query itself (e.g. the non-relational 25 // ORDER BY operator) and by the selection of specific implementations during 26 // optimization (e.g. a merge join requires the inputs to be sorted in a 27 // particular order). 28 // 29 // Required properties are derived top-to-bottom - there is a required physical 30 // property on the root, and each expression can require physical properties on 31 // one or more of its operands. When an expression is optimized, it is always 32 // with respect to a particular set of required physical properties. The goal 33 // is to find the lowest cost expression that provides those properties while 34 // still remaining logically equivalent. 35 type Required struct { 36 // Presentation specifies the naming, membership (including duplicates), 37 // and order of result columns. If Presentation is not defined, then no 38 // particular column presentation is required or provided. 39 Presentation Presentation 40 41 // Ordering specifies the sort order of result rows. Rows can be sorted by 42 // one or more columns, each of which can be sorted in either ascending or 43 // descending order. If Ordering is not defined, then no particular ordering 44 // is required or provided. 45 Ordering OrderingChoice 46 47 // LimitHint specifies a "soft limit" to the number of result rows that may 48 // be required of the expression. If requested, an expression will still need 49 // to return all result rows, but it can be optimized based on the assumption 50 // that only the hinted number of rows will be needed. 51 // A LimitHint of 0 indicates "no limit". The LimitHint is an intermediate 52 // float64 representation, and can be converted to an integer number of rows 53 // using math.Ceil. 54 LimitHint float64 55 } 56 57 // MinRequired are the default physical properties that require nothing and 58 // provide nothing. 59 var MinRequired = &Required{} 60 61 // Defined is true if any physical property is defined. If none is defined, then 62 // this is an instance of MinRequired. 63 func (p *Required) Defined() bool { 64 return !p.Presentation.Any() || !p.Ordering.Any() || p.LimitHint != 0 65 } 66 67 // ColSet returns the set of columns used by any of the physical properties. 68 func (p *Required) ColSet() opt.ColSet { 69 colSet := p.Ordering.ColSet() 70 for _, col := range p.Presentation { 71 colSet.Add(col.ID) 72 } 73 return colSet 74 } 75 76 func (p *Required) String() string { 77 var buf bytes.Buffer 78 output := func(name string, fn func(*bytes.Buffer)) { 79 if buf.Len() != 0 { 80 buf.WriteByte(' ') 81 } 82 buf.WriteByte('[') 83 buf.WriteString(name) 84 buf.WriteString(": ") 85 fn(&buf) 86 buf.WriteByte(']') 87 } 88 89 if !p.Presentation.Any() { 90 output("presentation", p.Presentation.format) 91 } 92 if !p.Ordering.Any() { 93 output("ordering", p.Ordering.Format) 94 } 95 if p.LimitHint != 0 { 96 output("limit hint", func(buf *bytes.Buffer) { fmt.Fprintf(buf, "%.2f", p.LimitHint) }) 97 } 98 99 // Handle empty properties case. 100 if buf.Len() == 0 { 101 return "[]" 102 } 103 return buf.String() 104 } 105 106 // Equals returns true if the two physical properties are identical. 107 func (p *Required) Equals(rhs *Required) bool { 108 return p.Presentation.Equals(rhs.Presentation) && p.Ordering.Equals(&rhs.Ordering) && p.LimitHint == rhs.LimitHint 109 } 110 111 // Presentation specifies the naming, membership (including duplicates), and 112 // order of result columns that are required of or provided by an operator. 113 // While it cannot add unique columns, Presentation can rename, reorder, 114 // duplicate and discard columns. If Presentation is not defined, then no 115 // particular column presentation is required or provided. For example: 116 // a.y:2 a.x:1 a.y:2 column1:3 117 type Presentation []opt.AliasedColumn 118 119 // Any is true if any column presentation is allowed or can be provided. 120 func (p Presentation) Any() bool { 121 return p == nil 122 } 123 124 // Equals returns true iff this presentation exactly matches the given 125 // presentation. 126 func (p Presentation) Equals(rhs Presentation) bool { 127 // The 0 column presentation is not the same as the nil presentation. 128 if p.Any() != rhs.Any() { 129 return false 130 } 131 if len(p) != len(rhs) { 132 return false 133 } 134 135 for i := 0; i < len(p); i++ { 136 if p[i] != rhs[i] { 137 return false 138 } 139 } 140 return true 141 } 142 143 func (p Presentation) String() string { 144 var buf bytes.Buffer 145 p.format(&buf) 146 return buf.String() 147 } 148 149 func (p Presentation) format(buf *bytes.Buffer) { 150 for i, col := range p { 151 if i > 0 { 152 buf.WriteString(",") 153 } 154 fmt.Fprintf(buf, "%s:%d", col.Alias, col.ID) 155 } 156 }