github.com/cockroachdb/cockroach@v20.2.0-alpha.1+incompatible/pkg/sql/execinfra/metadata_test_sender.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 package execinfra 12 13 import ( 14 "context" 15 16 "github.com/cockroachdb/cockroach/pkg/sql/execinfrapb" 17 "github.com/cockroachdb/cockroach/pkg/sql/sqlbase" 18 ) 19 20 // MetadataTestSender intersperses a metadata record after every row. 21 type MetadataTestSender struct { 22 ProcessorBase 23 input RowSource 24 id string 25 26 // sendRowNumMeta is set to true when the next call to Next() must return 27 // RowNum metadata, and false otherwise. 28 sendRowNumMeta bool 29 rowNumCnt int32 30 } 31 32 var _ Processor = &MetadataTestSender{} 33 var _ RowSource = &MetadataTestSender{} 34 35 const metadataTestSenderProcName = "meta sender" 36 37 // NewMetadataTestSender creates a new MetadataTestSender. 38 func NewMetadataTestSender( 39 flowCtx *FlowCtx, 40 processorID int32, 41 input RowSource, 42 post *execinfrapb.PostProcessSpec, 43 output RowReceiver, 44 id string, 45 ) (*MetadataTestSender, error) { 46 mts := &MetadataTestSender{input: input, id: id} 47 if err := mts.Init( 48 mts, 49 post, 50 input.OutputTypes(), 51 flowCtx, 52 processorID, 53 output, 54 nil, /* memMonitor */ 55 ProcStateOpts{ 56 InputsToDrain: []RowSource{mts.input}, 57 TrailingMetaCallback: func(context.Context) []execinfrapb.ProducerMetadata { 58 mts.InternalClose() 59 // Send a final record with LastMsg set. 60 meta := execinfrapb.ProducerMetadata{ 61 RowNum: &execinfrapb.RemoteProducerMetadata_RowNum{ 62 RowNum: mts.rowNumCnt, 63 SenderID: mts.id, 64 LastMsg: true, 65 }, 66 } 67 return []execinfrapb.ProducerMetadata{meta} 68 }, 69 }, 70 ); err != nil { 71 return nil, err 72 } 73 return mts, nil 74 } 75 76 // Start is part of the RowSource interface. 77 func (mts *MetadataTestSender) Start(ctx context.Context) context.Context { 78 mts.input.Start(ctx) 79 return mts.StartInternal(ctx, metadataTestSenderProcName) 80 } 81 82 // Next is part of the RowSource interface. 83 func (mts *MetadataTestSender) Next() (sqlbase.EncDatumRow, *execinfrapb.ProducerMetadata) { 84 // Every call after a row has been returned returns a metadata record. 85 if mts.sendRowNumMeta { 86 mts.sendRowNumMeta = false 87 mts.rowNumCnt++ 88 return nil, &execinfrapb.ProducerMetadata{ 89 RowNum: &execinfrapb.RemoteProducerMetadata_RowNum{ 90 RowNum: mts.rowNumCnt, 91 SenderID: mts.id, 92 LastMsg: false, 93 }, 94 } 95 } 96 97 for mts.State == StateRunning { 98 row, meta := mts.input.Next() 99 if meta != nil { 100 // Other processors will start draining when they get an error meta from 101 // their input. We don't do that here, as the mts should be an unintrusive 102 // as possible. 103 return nil, meta 104 } 105 if row == nil { 106 mts.MoveToDraining(nil /* err */) 107 break 108 } 109 110 if outRow := mts.ProcessRowHelper(row); outRow != nil { 111 mts.sendRowNumMeta = true 112 return outRow, nil 113 } 114 } 115 return nil, mts.DrainHelper() 116 } 117 118 // ConsumerClosed is part of the RowSource interface. 119 func (mts *MetadataTestSender) ConsumerClosed() { 120 // The consumer is done, Next() will not be called again. 121 mts.InternalClose() 122 }