github.com/cockroachdb/cockroach@v20.2.0-alpha.1+incompatible/pkg/sql/rowexec/processors.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 package rowexec 12 13 import ( 14 "context" 15 16 "github.com/cockroachdb/cockroach/pkg/sql/execinfra" 17 "github.com/cockroachdb/cockroach/pkg/sql/execinfrapb" 18 "github.com/cockroachdb/cockroach/pkg/sql/sqlbase" 19 "github.com/cockroachdb/cockroach/pkg/util/log" 20 "github.com/cockroachdb/errors" 21 ) 22 23 // emitHelper is a utility wrapper on top of ProcOutputHelper.EmitRow(). 24 // It takes a row to emit and, if anything happens other than the normal 25 // situation where the emitting succeeds and the consumer still needs rows, both 26 // the (potentially many) inputs and the output are properly closed after 27 // potentially draining the inputs. It's allowed to not pass any inputs, in 28 // which case nothing will be drained (this can happen when the caller has 29 // already fully consumed the inputs). 30 // 31 // As opposed to EmitRow(), this also supports metadata rows which bypass the 32 // ProcOutputHelper and are routed directly to its output. 33 // 34 // If the consumer signals the producer to drain, the message is relayed and all 35 // the draining metadata is consumed and forwarded. 36 // 37 // inputs are optional. 38 // 39 // pushTrailingMeta is called after draining the sources and before calling 40 // dst.ProducerDone(). It gives the caller the opportunity to push some trailing 41 // metadata (e.g. tracing information and txn updates, if applicable). 42 // 43 // Returns true if more rows are needed, false otherwise. If false is returned 44 // both the inputs and the output have been properly closed. 45 func emitHelper( 46 ctx context.Context, 47 output *execinfra.ProcOutputHelper, 48 row sqlbase.EncDatumRow, 49 meta *execinfrapb.ProducerMetadata, 50 pushTrailingMeta func(context.Context), 51 inputs ...execinfra.RowSource, 52 ) bool { 53 if output.Output() == nil { 54 panic("output RowReceiver not initialized for emitting") 55 } 56 var consumerStatus execinfra.ConsumerStatus 57 if meta != nil { 58 if row != nil { 59 panic("both row data and metadata in the same emitHelper call") 60 } 61 // Bypass EmitRow() and send directly to output.output. 62 foundErr := meta.Err != nil 63 consumerStatus = output.Output().Push(nil /* row */, meta) 64 if foundErr { 65 consumerStatus = execinfra.ConsumerClosed 66 } 67 } else { 68 var err error 69 consumerStatus, err = output.EmitRow(ctx, row) 70 if err != nil { 71 output.Output().Push(nil /* row */, &execinfrapb.ProducerMetadata{Err: err}) 72 consumerStatus = execinfra.ConsumerClosed 73 } 74 } 75 switch consumerStatus { 76 case execinfra.NeedMoreRows: 77 return true 78 case execinfra.DrainRequested: 79 log.VEventf(ctx, 1, "no more rows required. drain requested.") 80 execinfra.DrainAndClose(ctx, output.Output(), nil /* cause */, pushTrailingMeta, inputs...) 81 return false 82 case execinfra.ConsumerClosed: 83 log.VEventf(ctx, 1, "no more rows required. Consumer shut down.") 84 for _, input := range inputs { 85 input.ConsumerClosed() 86 } 87 output.Close() 88 return false 89 default: 90 log.Fatalf(ctx, "unexpected consumerStatus: %d", consumerStatus) 91 return false 92 } 93 } 94 95 func checkNumInOut( 96 inputs []execinfra.RowSource, outputs []execinfra.RowReceiver, numIn, numOut int, 97 ) error { 98 if len(inputs) != numIn { 99 return errors.Errorf("expected %d input(s), got %d", numIn, len(inputs)) 100 } 101 if len(outputs) != numOut { 102 return errors.Errorf("expected %d output(s), got %d", numOut, len(outputs)) 103 } 104 return nil 105 } 106 107 // NewProcessor creates a new execinfra.Processor according to the provided 108 // core. 109 func NewProcessor( 110 ctx context.Context, 111 flowCtx *execinfra.FlowCtx, 112 processorID int32, 113 core *execinfrapb.ProcessorCoreUnion, 114 post *execinfrapb.PostProcessSpec, 115 inputs []execinfra.RowSource, 116 outputs []execinfra.RowReceiver, 117 localProcessors []execinfra.LocalProcessor, 118 ) (execinfra.Processor, error) { 119 if core.Noop != nil { 120 if err := checkNumInOut(inputs, outputs, 1, 1); err != nil { 121 return nil, err 122 } 123 return newNoopProcessor(flowCtx, processorID, inputs[0], post, outputs[0]) 124 } 125 if core.Values != nil { 126 if err := checkNumInOut(inputs, outputs, 0, 1); err != nil { 127 return nil, err 128 } 129 return newValuesProcessor(flowCtx, processorID, core.Values, post, outputs[0]) 130 } 131 if core.TableReader != nil { 132 if err := checkNumInOut(inputs, outputs, 0, 1); err != nil { 133 return nil, err 134 } 135 if core.TableReader.IsCheck { 136 return newScrubTableReader(flowCtx, processorID, core.TableReader, post, outputs[0]) 137 } 138 return newTableReader(flowCtx, processorID, core.TableReader, post, outputs[0]) 139 } 140 if core.JoinReader != nil { 141 if err := checkNumInOut(inputs, outputs, 1, 1); err != nil { 142 return nil, err 143 } 144 if len(core.JoinReader.LookupColumns) == 0 { 145 return newIndexJoiner( 146 flowCtx, processorID, core.JoinReader, inputs[0], post, outputs[0]) 147 } 148 return newJoinReader(flowCtx, processorID, core.JoinReader, inputs[0], post, outputs[0]) 149 } 150 if core.Sorter != nil { 151 if err := checkNumInOut(inputs, outputs, 1, 1); err != nil { 152 return nil, err 153 } 154 return newSorter(ctx, flowCtx, processorID, core.Sorter, inputs[0], post, outputs[0]) 155 } 156 if core.Distinct != nil { 157 if err := checkNumInOut(inputs, outputs, 1, 1); err != nil { 158 return nil, err 159 } 160 return newDistinct(flowCtx, processorID, core.Distinct, inputs[0], post, outputs[0]) 161 } 162 if core.Ordinality != nil { 163 if err := checkNumInOut(inputs, outputs, 1, 1); err != nil { 164 return nil, err 165 } 166 return newOrdinalityProcessor(flowCtx, processorID, core.Ordinality, inputs[0], post, outputs[0]) 167 } 168 if core.Aggregator != nil { 169 if err := checkNumInOut(inputs, outputs, 1, 1); err != nil { 170 return nil, err 171 } 172 return newAggregator(flowCtx, processorID, core.Aggregator, inputs[0], post, outputs[0]) 173 } 174 if core.MergeJoiner != nil { 175 if err := checkNumInOut(inputs, outputs, 2, 1); err != nil { 176 return nil, err 177 } 178 return newMergeJoiner( 179 flowCtx, processorID, core.MergeJoiner, inputs[0], inputs[1], post, outputs[0], 180 ) 181 } 182 if core.InterleavedReaderJoiner != nil { 183 if err := checkNumInOut(inputs, outputs, 0, 1); err != nil { 184 return nil, err 185 } 186 return newInterleavedReaderJoiner( 187 flowCtx, processorID, core.InterleavedReaderJoiner, post, outputs[0], 188 ) 189 } 190 if core.ZigzagJoiner != nil { 191 if err := checkNumInOut(inputs, outputs, 0, 1); err != nil { 192 return nil, err 193 } 194 return newZigzagJoiner( 195 flowCtx, processorID, core.ZigzagJoiner, nil, post, outputs[0], 196 ) 197 } 198 if core.HashJoiner != nil { 199 if err := checkNumInOut(inputs, outputs, 2, 1); err != nil { 200 return nil, err 201 } 202 return newHashJoiner( 203 flowCtx, processorID, core.HashJoiner, inputs[0], inputs[1], post, 204 outputs[0], false, /* disableTempStorage */ 205 ) 206 } 207 if core.Backfiller != nil { 208 if err := checkNumInOut(inputs, outputs, 0, 1); err != nil { 209 return nil, err 210 } 211 switch core.Backfiller.Type { 212 case execinfrapb.BackfillerSpec_Index: 213 return newIndexBackfiller(flowCtx, processorID, *core.Backfiller, post, outputs[0]) 214 case execinfrapb.BackfillerSpec_Column: 215 return newColumnBackfiller(ctx, flowCtx, processorID, *core.Backfiller, post, outputs[0]) 216 } 217 } 218 if core.Sampler != nil { 219 if err := checkNumInOut(inputs, outputs, 1, 1); err != nil { 220 return nil, err 221 } 222 return newSamplerProcessor(flowCtx, processorID, core.Sampler, inputs[0], post, outputs[0]) 223 } 224 if core.SampleAggregator != nil { 225 if err := checkNumInOut(inputs, outputs, 1, 1); err != nil { 226 return nil, err 227 } 228 return newSampleAggregator(flowCtx, processorID, core.SampleAggregator, inputs[0], post, outputs[0]) 229 } 230 if core.ReadImport != nil { 231 if err := checkNumInOut(inputs, outputs, 0, 1); err != nil { 232 return nil, err 233 } 234 if NewReadImportDataProcessor == nil { 235 return nil, errors.New("ReadImportData processor unimplemented") 236 } 237 return NewReadImportDataProcessor(flowCtx, processorID, *core.ReadImport, outputs[0]) 238 } 239 if core.CSVWriter != nil { 240 if err := checkNumInOut(inputs, outputs, 1, 1); err != nil { 241 return nil, err 242 } 243 if NewCSVWriterProcessor == nil { 244 return nil, errors.New("CSVWriter processor unimplemented") 245 } 246 return NewCSVWriterProcessor(flowCtx, processorID, *core.CSVWriter, inputs[0], outputs[0]) 247 } 248 if core.BulkRowWriter != nil { 249 if err := checkNumInOut(inputs, outputs, 1, 1); err != nil { 250 return nil, err 251 } 252 return newBulkRowWriterProcessor(flowCtx, processorID, *core.BulkRowWriter, inputs[0], outputs[0]) 253 } 254 if core.MetadataTestSender != nil { 255 if err := checkNumInOut(inputs, outputs, 1, 1); err != nil { 256 return nil, err 257 } 258 return execinfra.NewMetadataTestSender(flowCtx, processorID, inputs[0], post, outputs[0], core.MetadataTestSender.ID) 259 } 260 if core.MetadataTestReceiver != nil { 261 if err := checkNumInOut(inputs, outputs, 1, 1); err != nil { 262 return nil, err 263 } 264 return execinfra.NewMetadataTestReceiver( 265 flowCtx, processorID, inputs[0], post, outputs[0], core.MetadataTestReceiver.SenderIDs, 266 ) 267 } 268 if core.ProjectSet != nil { 269 if err := checkNumInOut(inputs, outputs, 1, 1); err != nil { 270 return nil, err 271 } 272 return newProjectSetProcessor(flowCtx, processorID, core.ProjectSet, inputs[0], post, outputs[0]) 273 } 274 if core.Windower != nil { 275 if err := checkNumInOut(inputs, outputs, 1, 1); err != nil { 276 return nil, err 277 } 278 return newWindower(flowCtx, processorID, core.Windower, inputs[0], post, outputs[0]) 279 } 280 if core.LocalPlanNode != nil { 281 numInputs := 0 282 if core.LocalPlanNode.NumInputs != nil { 283 numInputs = int(*core.LocalPlanNode.NumInputs) 284 } 285 if err := checkNumInOut(inputs, outputs, numInputs, 1); err != nil { 286 return nil, err 287 } 288 processor := localProcessors[*core.LocalPlanNode.RowSourceIdx] 289 if err := processor.InitWithOutput(post, outputs[0]); err != nil { 290 return nil, err 291 } 292 if numInputs == 1 { 293 if err := processor.SetInput(ctx, inputs[0]); err != nil { 294 return nil, err 295 } 296 } else if numInputs > 1 { 297 return nil, errors.Errorf("invalid localPlanNode core with multiple inputs %+v", core.LocalPlanNode) 298 } 299 return processor, nil 300 } 301 if core.ChangeAggregator != nil { 302 if err := checkNumInOut(inputs, outputs, 0, 1); err != nil { 303 return nil, err 304 } 305 if NewChangeAggregatorProcessor == nil { 306 return nil, errors.New("ChangeAggregator processor unimplemented") 307 } 308 return NewChangeAggregatorProcessor(flowCtx, processorID, *core.ChangeAggregator, outputs[0]) 309 } 310 if core.ChangeFrontier != nil { 311 if err := checkNumInOut(inputs, outputs, 1, 1); err != nil { 312 return nil, err 313 } 314 if NewChangeFrontierProcessor == nil { 315 return nil, errors.New("ChangeFrontier processor unimplemented") 316 } 317 return NewChangeFrontierProcessor(flowCtx, processorID, *core.ChangeFrontier, inputs[0], outputs[0]) 318 } 319 if core.InvertedFilterer != nil { 320 if err := checkNumInOut(inputs, outputs, 1, 1); err != nil { 321 return nil, err 322 } 323 return newInvertedFilterer(flowCtx, processorID, core.InvertedFilterer, inputs[0], post, outputs[0]) 324 } 325 return nil, errors.Errorf("unsupported processor core %q", core) 326 } 327 328 // NewReadImportDataProcessor is externally implemented and registered by 329 // ccl/sqlccl/csv.go. 330 var NewReadImportDataProcessor func(*execinfra.FlowCtx, int32, execinfrapb.ReadImportDataSpec, execinfra.RowReceiver) (execinfra.Processor, error) 331 332 // NewCSVWriterProcessor is externally implemented. 333 var NewCSVWriterProcessor func(*execinfra.FlowCtx, int32, execinfrapb.CSVWriterSpec, execinfra.RowSource, execinfra.RowReceiver) (execinfra.Processor, error) 334 335 // NewChangeAggregatorProcessor is externally implemented. 336 var NewChangeAggregatorProcessor func(*execinfra.FlowCtx, int32, execinfrapb.ChangeAggregatorSpec, execinfra.RowReceiver) (execinfra.Processor, error) 337 338 // NewChangeFrontierProcessor is externally implemented. 339 var NewChangeFrontierProcessor func(*execinfra.FlowCtx, int32, execinfrapb.ChangeFrontierSpec, execinfra.RowSource, execinfra.RowReceiver) (execinfra.Processor, error)