github.com/cockroachdb/cockroach@v20.2.0-alpha.1+incompatible/pkg/sql/colexec/window_peer_grouper_tmpl.go (about) 1 // Copyright 2019 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 window_peer_grouper.eg.go. It's 15 // formatted in a special way, so it's both valid Go and a valid text/template 16 // input. This permits editing this file with editor support. 17 // 18 // */}} 19 20 package colexec 21 22 import ( 23 "context" 24 25 "github.com/cockroachdb/cockroach/pkg/col/coldata" 26 "github.com/cockroachdb/cockroach/pkg/sql/colexecbase" 27 "github.com/cockroachdb/cockroach/pkg/sql/colmem" 28 "github.com/cockroachdb/cockroach/pkg/sql/execinfrapb" 29 "github.com/cockroachdb/cockroach/pkg/sql/types" 30 ) 31 32 // NewWindowPeerGrouper creates a new Operator that puts 'true' in 33 // outputColIdx'th column (which is appended if needed) for every tuple that is 34 // the first within its peer group. Peers are tuples that belong to the same 35 // partition and are equal on the ordering columns. If orderingCols is empty, 36 // then all tuples within the partition are peers. 37 // - partitionColIdx, if not columnOmitted, *must* specify the column in which 38 // 'true' indicates the start of a new partition. 39 // NOTE: the input *must* already be ordered on ordCols. 40 func NewWindowPeerGrouper( 41 allocator *colmem.Allocator, 42 input colexecbase.Operator, 43 typs []*types.T, 44 orderingCols []execinfrapb.Ordering_Column, 45 partitionColIdx int, 46 outputColIdx int, 47 ) (op colexecbase.Operator, err error) { 48 allPeers := len(orderingCols) == 0 49 var distinctCol []bool 50 if !allPeers { 51 orderIdxs := make([]uint32, len(orderingCols)) 52 for i, ordCol := range orderingCols { 53 orderIdxs[i] = ordCol.ColIdx 54 } 55 input, distinctCol, err = OrderedDistinctColsToOperators( 56 input, orderIdxs, typs, 57 ) 58 if err != nil { 59 return nil, err 60 } 61 } 62 input = newVectorTypeEnforcer(allocator, input, types.Bool, outputColIdx) 63 initFields := windowPeerGrouperInitFields{ 64 OneInputNode: NewOneInputNode(input), 65 allocator: allocator, 66 partitionColIdx: partitionColIdx, 67 distinctCol: distinctCol, 68 outputColIdx: outputColIdx, 69 } 70 if allPeers { 71 if partitionColIdx != columnOmitted { 72 return &windowPeerGrouperAllPeersWithPartitionOp{ 73 windowPeerGrouperInitFields: initFields, 74 }, nil 75 } 76 return &windowPeerGrouperAllPeersNoPartitionOp{ 77 windowPeerGrouperInitFields: initFields, 78 }, nil 79 } 80 if partitionColIdx != columnOmitted { 81 return &windowPeerGrouperWithPartitionOp{ 82 windowPeerGrouperInitFields: initFields, 83 }, nil 84 } 85 return &windowPeerGrouperNoPartitionOp{ 86 windowPeerGrouperInitFields: initFields, 87 }, nil 88 } 89 90 type windowPeerGrouperInitFields struct { 91 OneInputNode 92 93 allocator *colmem.Allocator 94 partitionColIdx int 95 // distinctCol is the output column of the chain of ordered distinct 96 // operators in which 'true' will indicate that a new peer group begins with 97 // the corresponding tuple. 98 distinctCol []bool 99 outputColIdx int 100 } 101 102 // {{range .}} 103 104 type _PEER_GROUPER_STRINGOp struct { 105 windowPeerGrouperInitFields 106 // {{if and .AllPeers (not .HasPartition)}} 107 seenFirstTuple bool 108 // {{end}} 109 } 110 111 var _ colexecbase.Operator = &_PEER_GROUPER_STRINGOp{} 112 113 func (p *_PEER_GROUPER_STRINGOp) Init() { 114 p.input.Init() 115 } 116 117 func (p *_PEER_GROUPER_STRINGOp) Next(ctx context.Context) coldata.Batch { 118 b := p.input.Next(ctx) 119 n := b.Length() 120 if n == 0 { 121 return b 122 } 123 // {{if .HasPartition}} 124 partitionCol := b.ColVec(p.partitionColIdx).Bool() 125 // {{end}} 126 sel := b.Selection() 127 peersVec := b.ColVec(p.outputColIdx) 128 if peersVec.MaybeHasNulls() { 129 // We need to make sure that there are no left over null values in the 130 // output vector. 131 peersVec.Nulls().UnsetNulls() 132 } 133 peersCol := peersVec.Bool() 134 if sel != nil { 135 for _, i := range sel[:n] { 136 // {{if .AllPeers}} 137 // {{if .HasPartition}} 138 // All tuples within the partition are peers, so we simply need to copy 139 // over partitionCol according to sel. 140 peersCol[i] = partitionCol[i] 141 // {{else}} 142 // There is only one partition and all tuples within it are peers, so we 143 // need to set 'true' to only the first tuple ever seen. 144 peersCol[i] = !p.seenFirstTuple 145 p.seenFirstTuple = true 146 // {{end}} 147 // {{else}} 148 // {{if .HasPartition}} 149 // The new peer group begins either when a new partition begins (in which 150 // case partitionCol[i] is 'true') or when i'th tuple is different from 151 // i-1'th (in which case p.distinctCol[i] is 'true'). 152 peersCol[i] = partitionCol[i] || p.distinctCol[i] 153 // {{else}} 154 // The new peer group begins when i'th tuple is different from i-1'th (in 155 // which case p.distinctCol[i] is 'true'). 156 peersCol[i] = p.distinctCol[i] 157 // {{end}} 158 // {{end}} 159 } 160 } else { 161 // {{if .AllPeers}} 162 // {{if .HasPartition}} 163 // All tuples within the partition are peers, so we simply need to copy 164 // over partitionCol. 165 copy(peersCol[:n], partitionCol[:n]) 166 // {{else}} 167 // There is only one partition and all tuples within it are peers, so we 168 // need to set 'true' to only the first tuple ever seen. 169 copy(peersCol[:n], zeroBoolColumn[:n]) 170 peersCol[0] = !p.seenFirstTuple 171 p.seenFirstTuple = true 172 // {{end}} 173 // {{else}} 174 // {{if .HasPartition}} 175 // The new peer group begins either when a new partition begins (in which 176 // case partitionCol[i] is 'true') or when i'th tuple is different from 177 // i-1'th (in which case p.distinctCol[i] is 'true'). 178 for i := range peersCol[:n] { 179 peersCol[i] = partitionCol[i] || p.distinctCol[i] 180 } 181 // {{else}} 182 // The new peer group begins when i'th tuple is different from i-1'th (in 183 // which case p.distinctCol[i] is 'true'), so we simply need to copy over 184 // p.distinctCol. 185 copy(peersCol[:n], p.distinctCol[:n]) 186 // {{end}} 187 // {{end}} 188 } 189 return b 190 } 191 192 // {{end}}