github.com/cockroachdb/cockroach@v20.2.0-alpha.1+incompatible/pkg/sql/colexec/buffer.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 colexec 12 13 import ( 14 "context" 15 16 "github.com/cockroachdb/cockroach/pkg/col/coldata" 17 "github.com/cockroachdb/cockroach/pkg/sql/colexecbase" 18 ) 19 20 // bufferOp is an operator that buffers a single batch at a time from an input, 21 // and makes it available to be read multiple times by downstream consumers. 22 type bufferOp struct { 23 OneInputNode 24 initStatus OperatorInitStatus 25 26 // read is true if someone has read the current batch already. 27 read bool 28 batch coldata.Batch 29 } 30 31 var _ colexecbase.Operator = &bufferOp{} 32 33 // NewBufferOp returns a new bufferOp, initialized to buffer batches from the 34 // supplied input. 35 func NewBufferOp(input colexecbase.Operator) colexecbase.Operator { 36 return &bufferOp{ 37 OneInputNode: NewOneInputNode(input), 38 } 39 } 40 41 func (b *bufferOp) Init() { 42 // bufferOp can be an input to multiple operator chains, so Init on it can be 43 // called multiple times. However, we do not want to call Init many times on 44 // the input to bufferOp, so we do this check whether Init has already been 45 // performed. 46 if b.initStatus == OperatorNotInitialized { 47 b.input.Init() 48 b.initStatus = OperatorInitialized 49 } 50 } 51 52 // rewind resets this buffer to be readable again. 53 // NOTE: it is the caller responsibility to restore the batch into the desired 54 // state. 55 func (b *bufferOp) rewind() { 56 b.read = false 57 } 58 59 // advance reads the next batch from the input into the buffer, preparing itself 60 // for reads. 61 func (b *bufferOp) advance(ctx context.Context) { 62 b.batch = b.input.Next(ctx) 63 b.rewind() 64 } 65 66 func (b *bufferOp) Next(ctx context.Context) coldata.Batch { 67 if b.read { 68 return coldata.ZeroBatch 69 } 70 b.read = true 71 return b.batch 72 }