github.com/cockroachdb/cockroach@v20.2.0-alpha.1+incompatible/pkg/sql/colexec/sort_tmpl.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 // {{/* 12 // +build execgen_template 13 // 14 // This file is the execgen template for sort.eg.go. It's formatted in a 15 // special way, so it's both valid Go and a valid text/template input. This 16 // permits editing this file with editor support. 17 // 18 // */}} 19 20 package colexec 21 22 import ( 23 "context" 24 "fmt" 25 26 "github.com/cockroachdb/cockroach/pkg/col/coldata" 27 "github.com/cockroachdb/cockroach/pkg/col/typeconv" 28 "github.com/cockroachdb/cockroach/pkg/sql/colexec/execgen" 29 "github.com/cockroachdb/cockroach/pkg/sql/colexecbase/colexecerror" 30 "github.com/cockroachdb/cockroach/pkg/sql/execinfrapb" 31 "github.com/cockroachdb/cockroach/pkg/sql/types" 32 ) 33 34 // Remove unused warning. 35 var _ = execgen.UNSAFEGET 36 37 // {{/* 38 39 // Declarations to make the template compile properly. 40 41 // _GOTYPESLICE is the template variable. 42 type _GOTYPESLICE interface{} 43 44 // _CANONICAL_TYPE_FAMILY is the template variable. 45 const _CANONICAL_TYPE_FAMILY = types.UnknownFamily 46 47 // _TYPE_WIDTH is the template variable. 48 const _TYPE_WIDTH = 0 49 50 // _DIR_ENUM is the template variable. 51 const _DIR_ENUM = 0 52 53 // _ISNULL is the template type variable for whether the sorter handles nulls 54 // or not. It will be replaced by the appropriate boolean. 55 const _ISNULL = false 56 57 // _ASSIGN_LT is the template equality function for assigning the first input 58 // to the result of the second input < the third input. 59 func _ASSIGN_LT(_, _, _, _, _, _ string) bool { 60 colexecerror.InternalError("") 61 } 62 63 // */}} 64 65 func isSorterSupported(t *types.T, dir execinfrapb.Ordering_Column_Direction) bool { 66 // {{range .}} 67 // {{if .Nulls}} 68 switch dir { 69 // {{range .DirOverloads}} 70 case _DIR_ENUM: 71 switch typeconv.TypeFamilyToCanonicalTypeFamily(t.Family()) { 72 // {{range .FamilyOverloads}} 73 case _CANONICAL_TYPE_FAMILY: 74 switch t.Width() { 75 // {{range .WidthOverloads}} 76 case _TYPE_WIDTH: 77 return true 78 // {{end}} 79 } 80 // {{end}} 81 } 82 // {{end}} 83 } 84 // {{end}} 85 // {{end}} 86 return false 87 } 88 89 func newSingleSorter( 90 t *types.T, dir execinfrapb.Ordering_Column_Direction, hasNulls bool, 91 ) colSorter { 92 switch hasNulls { 93 // {{range .}} 94 // {{$nulls := .Nulls}} 95 case _ISNULL: 96 switch dir { 97 // {{range .DirOverloads}} 98 // {{$dir := .DirString}} 99 case _DIR_ENUM: 100 switch typeconv.TypeFamilyToCanonicalTypeFamily(t.Family()) { 101 // {{range .FamilyOverloads}} 102 case _CANONICAL_TYPE_FAMILY: 103 switch t.Width() { 104 // {{range .WidthOverloads}} 105 case _TYPE_WIDTH: 106 return &sort_TYPE_DIR_HANDLES_NULLSOp{} 107 // {{end}} 108 } 109 // {{end}} 110 } 111 // {{end}} 112 } 113 // {{end}} 114 } 115 colexecerror.InternalError("isSorterSupported should have caught this") 116 // This code is unreachable, but the compiler cannot infer that. 117 return nil 118 } 119 120 // {{range .}} 121 // {{$nulls := .Nulls}} 122 // {{range .DirOverloads}} 123 // {{$dir := .DirString}} 124 // {{range .FamilyOverloads}} 125 // {{range .WidthOverloads}} 126 127 type sort_TYPE_DIR_HANDLES_NULLSOp struct { 128 sortCol _GOTYPESLICE 129 nulls *coldata.Nulls 130 order []int 131 cancelChecker CancelChecker 132 } 133 134 func (s *sort_TYPE_DIR_HANDLES_NULLSOp) init(col coldata.Vec, order []int) { 135 s.sortCol = col.TemplateType() 136 s.nulls = col.Nulls() 137 s.order = order 138 } 139 140 func (s *sort_TYPE_DIR_HANDLES_NULLSOp) sort(ctx context.Context) { 141 n := execgen.LEN(s.sortCol) 142 s.quickSort(ctx, 0, n, maxDepth(n)) 143 } 144 145 func (s *sort_TYPE_DIR_HANDLES_NULLSOp) sortPartitions(ctx context.Context, partitions []int) { 146 if len(partitions) < 1 { 147 colexecerror.InternalError(fmt.Sprintf("invalid partitions list %v", partitions)) 148 } 149 order := s.order 150 for i, partitionStart := range partitions { 151 var partitionEnd int 152 if i == len(partitions)-1 { 153 partitionEnd = len(order) 154 } else { 155 partitionEnd = partitions[i+1] 156 } 157 s.order = order[partitionStart:partitionEnd] 158 n := partitionEnd - partitionStart 159 s.quickSort(ctx, 0, n, maxDepth(n)) 160 } 161 } 162 163 func (s *sort_TYPE_DIR_HANDLES_NULLSOp) Less(i, j int) bool { 164 // {{if $nulls}} 165 n1 := s.nulls.MaybeHasNulls() && s.nulls.NullAt(s.order[i]) 166 n2 := s.nulls.MaybeHasNulls() && s.nulls.NullAt(s.order[j]) 167 // {{if eq $dir "Asc"}} 168 // If ascending, nulls always sort first, so we encode that logic here. 169 if n1 && n2 { 170 return false 171 } else if n1 { 172 return true 173 } else if n2 { 174 return false 175 } 176 // {{else if eq $dir "Desc"}} 177 // If descending, nulls always sort last, so we encode that logic here. 178 if n1 && n2 { 179 return false 180 } else if n1 { 181 return false 182 } else if n2 { 183 return true 184 } 185 // {{end}} 186 // {{end}} 187 var lt bool 188 // We always indirect via the order vector. 189 arg1 := execgen.UNSAFEGET(s.sortCol, s.order[i]) 190 arg2 := execgen.UNSAFEGET(s.sortCol, s.order[j]) 191 _ASSIGN_LT(lt, arg1, arg2, _, s.sortCol, s.sortCol) 192 return lt 193 } 194 195 func (s *sort_TYPE_DIR_HANDLES_NULLSOp) Swap(i, j int) { 196 // We don't physically swap the column - we merely edit the order vector. 197 s.order[i], s.order[j] = s.order[j], s.order[i] 198 } 199 200 func (s *sort_TYPE_DIR_HANDLES_NULLSOp) Len() int { 201 return len(s.order) 202 } 203 204 // {{end}} 205 // {{end}} 206 // {{end}} 207 // {{end}}