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  }