github.com/cockroachdb/cockroach@v20.2.0-alpha.1+incompatible/pkg/sql/plan_node_to_row_source.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 sql
    12  
    13  import (
    14  	"context"
    15  
    16  	"github.com/cockroachdb/cockroach/pkg/sql/execinfra"
    17  	"github.com/cockroachdb/cockroach/pkg/sql/execinfrapb"
    18  	"github.com/cockroachdb/cockroach/pkg/sql/sem/tree"
    19  	"github.com/cockroachdb/cockroach/pkg/sql/sqlbase"
    20  	"github.com/cockroachdb/cockroach/pkg/sql/types"
    21  	"github.com/cockroachdb/cockroach/pkg/util/log"
    22  )
    23  
    24  type metadataForwarder interface {
    25  	forwardMetadata(metadata *execinfrapb.ProducerMetadata)
    26  }
    27  
    28  type planNodeToRowSource struct {
    29  	execinfra.ProcessorBase
    30  
    31  	started bool
    32  
    33  	fastPath bool
    34  
    35  	node        planNode
    36  	params      runParams
    37  	outputTypes []*types.T
    38  
    39  	firstNotWrapped planNode
    40  
    41  	// run time state machine values
    42  	row sqlbase.EncDatumRow
    43  }
    44  
    45  func makePlanNodeToRowSource(
    46  	source planNode, params runParams, fastPath bool,
    47  ) (*planNodeToRowSource, error) {
    48  	nodeColumns := planColumns(source)
    49  
    50  	types := make([]*types.T, len(nodeColumns))
    51  	for i := range nodeColumns {
    52  		types[i] = nodeColumns[i].Typ
    53  	}
    54  	row := make(sqlbase.EncDatumRow, len(nodeColumns))
    55  
    56  	return &planNodeToRowSource{
    57  		node:        source,
    58  		params:      params,
    59  		outputTypes: types,
    60  		row:         row,
    61  		fastPath:    fastPath,
    62  	}, nil
    63  }
    64  
    65  var _ execinfra.LocalProcessor = &planNodeToRowSource{}
    66  
    67  // InitWithOutput implements the LocalProcessor interface.
    68  func (p *planNodeToRowSource) InitWithOutput(
    69  	post *execinfrapb.PostProcessSpec, output execinfra.RowReceiver,
    70  ) error {
    71  	return p.InitWithEvalCtx(
    72  		p,
    73  		post,
    74  		p.outputTypes,
    75  		nil, /* flowCtx */
    76  		p.params.EvalContext(),
    77  		0, /* processorID */
    78  		output,
    79  		nil, /* memMonitor */
    80  		execinfra.ProcStateOpts{},
    81  	)
    82  }
    83  
    84  // SetInput implements the LocalProcessor interface.
    85  // input is the first upstream RowSource. When we're done executing, we need to
    86  // drain this row source of its metadata in case the planNode tree we're
    87  // wrapping returned an error, since planNodes don't know how to drain trailing
    88  // metadata.
    89  func (p *planNodeToRowSource) SetInput(ctx context.Context, input execinfra.RowSource) error {
    90  	if p.firstNotWrapped == nil {
    91  		// Short-circuit if we never set firstNotWrapped - indicating this planNode
    92  		// tree had no DistSQL-plannable subtrees.
    93  		return nil
    94  	}
    95  	p.AddInputToDrain(input)
    96  	// Search the plan we're wrapping for firstNotWrapped, which is the planNode
    97  	// that DistSQL planning resumed in. Replace that planNode with input,
    98  	// wrapped as a planNode.
    99  	return walkPlan(ctx, p.node, planObserver{
   100  		replaceNode: func(ctx context.Context, nodeName string, plan planNode) (planNode, error) {
   101  			if plan == p.firstNotWrapped {
   102  				return makeRowSourceToPlanNode(input, p, planColumns(p.firstNotWrapped), p.firstNotWrapped), nil
   103  			}
   104  			return nil, nil
   105  		},
   106  	})
   107  }
   108  
   109  func (p *planNodeToRowSource) Start(ctx context.Context) context.Context {
   110  	// We do not call p.StartInternal to avoid creating a span. Only the context
   111  	// needs to be set.
   112  	p.Ctx = ctx
   113  	p.params.ctx = ctx
   114  	if !p.started {
   115  		p.started = true
   116  		// This starts all of the nodes below this node.
   117  		if err := startExec(p.params, p.node); err != nil {
   118  			p.MoveToDraining(err)
   119  			return ctx
   120  		}
   121  	}
   122  	return ctx
   123  }
   124  
   125  func (p *planNodeToRowSource) InternalClose() {
   126  	if p.ProcessorBase.InternalClose() {
   127  		p.started = true
   128  	}
   129  }
   130  
   131  func (p *planNodeToRowSource) Next() (sqlbase.EncDatumRow, *execinfrapb.ProducerMetadata) {
   132  	if p.State == execinfra.StateRunning && p.fastPath {
   133  		var count int
   134  		// If our node is a "fast path node", it means that we're set up to just
   135  		// return a row count. So trigger the fast path and return the row count as
   136  		// a row with a single column.
   137  		fastPath, ok := p.node.(planNodeFastPath)
   138  
   139  		if ok {
   140  			var res bool
   141  			if count, res = fastPath.FastPathResults(); res {
   142  				if p.params.extendedEvalCtx.Tracing.Enabled() {
   143  					log.VEvent(p.params.ctx, 2, "fast path completed")
   144  				}
   145  			} else {
   146  				// Fall back to counting the rows.
   147  				count = 0
   148  				ok = false
   149  			}
   150  		}
   151  
   152  		if !ok {
   153  			// If we have no fast path to trigger, fall back to counting the rows
   154  			// by Nexting our source until exhaustion.
   155  			next, err := p.node.Next(p.params)
   156  			for ; next; next, err = p.node.Next(p.params) {
   157  				count++
   158  			}
   159  			if err != nil {
   160  				p.MoveToDraining(err)
   161  				return nil, p.DrainHelper()
   162  			}
   163  		}
   164  		p.MoveToDraining(nil /* err */)
   165  		// Return the row count the only way we can: as a single-column row with
   166  		// the count inside.
   167  		return sqlbase.EncDatumRow{sqlbase.EncDatum{Datum: tree.NewDInt(tree.DInt(count))}}, nil
   168  	}
   169  
   170  	for p.State == execinfra.StateRunning {
   171  		valid, err := p.node.Next(p.params)
   172  		if err != nil || !valid {
   173  			p.MoveToDraining(err)
   174  			return nil, p.DrainHelper()
   175  		}
   176  
   177  		for i, datum := range p.node.Values() {
   178  			if datum != nil {
   179  				p.row[i] = sqlbase.DatumToEncDatum(p.outputTypes[i], datum)
   180  			}
   181  		}
   182  		// ProcessRow here is required to deal with projections, which won't be
   183  		// pushed into the wrapped plan.
   184  		if outRow := p.ProcessRowHelper(p.row); outRow != nil {
   185  			return outRow, nil
   186  		}
   187  	}
   188  	return nil, p.DrainHelper()
   189  }
   190  
   191  func (p *planNodeToRowSource) ConsumerDone() {
   192  	p.MoveToDraining(nil /* err */)
   193  }
   194  
   195  func (p *planNodeToRowSource) ConsumerClosed() {
   196  	// The consumer is done, Next() will not be called again.
   197  	p.InternalClose()
   198  }
   199  
   200  // IsException implements the VectorizeAlwaysException interface.
   201  func (p *planNodeToRowSource) IsException() bool {
   202  	_, ok := p.node.(*setVarNode)
   203  	return ok
   204  }
   205  
   206  // forwardMetadata will be called by any upstream rowSourceToPlanNode processors
   207  // that need to forward metadata to the end of the flow. They can't pass
   208  // metadata through local processors, so they instead add the metadata to our
   209  // trailing metadata and expect us to forward it further.
   210  func (p *planNodeToRowSource) forwardMetadata(metadata *execinfrapb.ProducerMetadata) {
   211  	p.ProcessorBase.AppendTrailingMeta(*metadata)
   212  }