github.com/cockroachdb/cockroach@v20.2.0-alpha.1+incompatible/pkg/sql/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 sql 12 13 import ( 14 "context" 15 16 "github.com/cockroachdb/cockroach/pkg/sql/rowcontainer" 17 "github.com/cockroachdb/cockroach/pkg/sql/sem/tree" 18 "github.com/cockroachdb/cockroach/pkg/sql/sqlbase" 19 ) 20 21 // bufferNode consumes its input one row at a time, stores it in the buffer, 22 // and passes the row through. The buffered rows can be iterated over multiple 23 // times. 24 type bufferNode struct { 25 plan planNode 26 27 // TODO(yuzefovich): the buffer should probably be backed by disk. If so, the 28 // comments about TempStorage suggest that it should be used by DistSQL 29 // processors, but this node is local. 30 bufferedRows *rowcontainer.RowContainer 31 passThruNextRowIdx int 32 33 // label is a string used to describe the node in an EXPLAIN plan. 34 label string 35 } 36 37 // BufferNodeMarker is part of the exec.BufferNode interface. 38 func (n *bufferNode) BufferNodeMarker() {} 39 40 func (n *bufferNode) startExec(params runParams) error { 41 n.bufferedRows = rowcontainer.NewRowContainer( 42 params.EvalContext().Mon.MakeBoundAccount(), 43 sqlbase.ColTypeInfoFromResCols(getPlanColumns(n.plan, false /* mut */)), 44 0, /* rowCapacity */ 45 ) 46 return nil 47 } 48 49 func (n *bufferNode) Next(params runParams) (bool, error) { 50 if err := params.p.cancelChecker.Check(); err != nil { 51 return false, err 52 } 53 ok, err := n.plan.Next(params) 54 if err != nil { 55 return false, err 56 } 57 if !ok { 58 return false, nil 59 } 60 if _, err = n.bufferedRows.AddRow(params.ctx, n.plan.Values()); err != nil { 61 return false, err 62 } 63 n.passThruNextRowIdx++ 64 return true, nil 65 } 66 67 func (n *bufferNode) Values() tree.Datums { 68 return n.bufferedRows.At(n.passThruNextRowIdx - 1) 69 } 70 71 func (n *bufferNode) Close(ctx context.Context) { 72 n.plan.Close(ctx) 73 n.bufferedRows.Close(ctx) 74 } 75 76 // scanBufferNode behaves like an iterator into the bufferNode it is 77 // referencing. The bufferNode can be iterated over multiple times 78 // simultaneously, however, a new scanBufferNode is needed. 79 type scanBufferNode struct { 80 buffer *bufferNode 81 82 nextRowIdx int 83 84 // label is a string used to describe the node in an EXPLAIN plan. 85 label string 86 } 87 88 func (n *scanBufferNode) startExec(runParams) error { 89 return nil 90 } 91 92 func (n *scanBufferNode) Next(runParams) (bool, error) { 93 n.nextRowIdx++ 94 return n.nextRowIdx <= n.buffer.bufferedRows.Len(), nil 95 } 96 97 func (n *scanBufferNode) Values() tree.Datums { 98 return n.buffer.bufferedRows.At(n.nextRowIdx - 1) 99 } 100 101 func (n *scanBufferNode) Close(context.Context) { 102 }