github.com/cockroachdb/cockroach@v20.2.0-alpha.1+incompatible/pkg/sql/rowexec/values.go (about)

     1  // Copyright 2017 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  	"fmt"
    16  
    17  	"github.com/cockroachdb/cockroach/pkg/sql/execinfra"
    18  	"github.com/cockroachdb/cockroach/pkg/sql/execinfrapb"
    19  	"github.com/cockroachdb/cockroach/pkg/sql/flowinfra"
    20  	"github.com/cockroachdb/cockroach/pkg/sql/sqlbase"
    21  	"github.com/cockroachdb/cockroach/pkg/sql/types"
    22  )
    23  
    24  // valuesProcessor is a processor that has no inputs and generates "pre-canned"
    25  // rows.
    26  type valuesProcessor struct {
    27  	execinfra.ProcessorBase
    28  
    29  	columns []execinfrapb.DatumInfo
    30  	data    [][]byte
    31  	// numRows is only guaranteed to be set if there are zero columns (because of
    32  	// backward compatibility). If it set and there are columns, it matches the
    33  	// number of rows that are encoded in data.
    34  	numRows uint64
    35  
    36  	sd     flowinfra.StreamDecoder
    37  	rowBuf sqlbase.EncDatumRow
    38  }
    39  
    40  var _ execinfra.Processor = &valuesProcessor{}
    41  var _ execinfra.RowSource = &valuesProcessor{}
    42  var _ execinfra.OpNode = &valuesProcessor{}
    43  
    44  const valuesProcName = "values"
    45  
    46  func newValuesProcessor(
    47  	flowCtx *execinfra.FlowCtx,
    48  	processorID int32,
    49  	spec *execinfrapb.ValuesCoreSpec,
    50  	post *execinfrapb.PostProcessSpec,
    51  	output execinfra.RowReceiver,
    52  ) (*valuesProcessor, error) {
    53  	v := &valuesProcessor{
    54  		columns: spec.Columns,
    55  		numRows: spec.NumRows,
    56  		data:    spec.RawBytes,
    57  	}
    58  	types := make([]*types.T, len(v.columns))
    59  	for i := range v.columns {
    60  		types[i] = v.columns[i].Type
    61  	}
    62  	if err := v.Init(
    63  		v, post, types, flowCtx, processorID, output, nil /* memMonitor */, execinfra.ProcStateOpts{},
    64  	); err != nil {
    65  		return nil, err
    66  	}
    67  	return v, nil
    68  }
    69  
    70  // Start is part of the RowSource interface.
    71  func (v *valuesProcessor) Start(ctx context.Context) context.Context {
    72  	ctx = v.StartInternal(ctx, valuesProcName)
    73  
    74  	// Add a bogus header to appease the StreamDecoder, which wants to receive a
    75  	// header before any data.
    76  	m := &execinfrapb.ProducerMessage{
    77  		Typing: v.columns,
    78  		Header: &execinfrapb.ProducerHeader{},
    79  	}
    80  	if err := v.sd.AddMessage(ctx, m); err != nil {
    81  		v.MoveToDraining(err)
    82  		return ctx
    83  	}
    84  
    85  	v.rowBuf = make(sqlbase.EncDatumRow, len(v.columns))
    86  	return ctx
    87  }
    88  
    89  // Next is part of the RowSource interface.
    90  func (v *valuesProcessor) Next() (sqlbase.EncDatumRow, *execinfrapb.ProducerMetadata) {
    91  	for v.State == execinfra.StateRunning {
    92  		row, meta, err := v.sd.GetRow(v.rowBuf)
    93  		if err != nil {
    94  			v.MoveToDraining(err)
    95  			break
    96  		}
    97  
    98  		if meta != nil {
    99  			return nil, meta
   100  		}
   101  
   102  		if row == nil {
   103  			// Push a chunk of data to the stream decoder.
   104  			m := &execinfrapb.ProducerMessage{}
   105  			if len(v.columns) == 0 {
   106  				if v.numRows == 0 {
   107  					v.MoveToDraining(nil /* err */)
   108  					break
   109  				}
   110  				m.Data.NumEmptyRows = int32(v.numRows)
   111  				v.numRows = 0
   112  			} else {
   113  				if len(v.data) == 0 {
   114  					v.MoveToDraining(nil /* err */)
   115  					break
   116  				}
   117  				m.Data.RawBytes = v.data[0]
   118  				v.data = v.data[1:]
   119  			}
   120  			if err := v.sd.AddMessage(context.TODO(), m); err != nil {
   121  				v.MoveToDraining(err)
   122  				break
   123  			}
   124  			continue
   125  		}
   126  
   127  		if outRow := v.ProcessRowHelper(row); outRow != nil {
   128  			return outRow, nil
   129  		}
   130  	}
   131  	return nil, v.DrainHelper()
   132  
   133  }
   134  
   135  // ConsumerClosed is part of the RowSource interface.
   136  func (v *valuesProcessor) ConsumerClosed() {
   137  	// The consumer is done, Next() will not be called again.
   138  	v.InternalClose()
   139  }
   140  
   141  // ChildCount is part of the execinfra.OpNode interface.
   142  func (v *valuesProcessor) ChildCount(verbose bool) int {
   143  	return 0
   144  }
   145  
   146  // Child is part of the execinfra.OpNode interface.
   147  func (v *valuesProcessor) Child(nth int, verbose bool) execinfra.OpNode {
   148  	panic(fmt.Sprintf("invalid index %d", nth))
   149  }