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

     1  // Copyright 2016 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/opt/constraint"
    17  	"github.com/cockroachdb/cockroach/pkg/sql/sem/tree"
    18  	"github.com/cockroachdb/cockroach/pkg/sql/sqlbase"
    19  )
    20  
    21  // delayedNode wraps a planNode in cases where the planNode
    22  // constructor must be delayed during query execution (as opposed to
    23  // SQL prepare) for resource tracking purposes.
    24  type delayedNode struct {
    25  	name            string
    26  	columns         sqlbase.ResultColumns
    27  	indexConstraint *constraint.Constraint
    28  	constructor     nodeConstructor
    29  	plan            planNode
    30  }
    31  
    32  type nodeConstructor func(context.Context, *planner) (planNode, error)
    33  
    34  func (d *delayedNode) Next(params runParams) (bool, error) { return d.plan.Next(params) }
    35  func (d *delayedNode) Values() tree.Datums                 { return d.plan.Values() }
    36  
    37  func (d *delayedNode) Close(ctx context.Context) {
    38  	if d.plan != nil {
    39  		d.plan.Close(ctx)
    40  		d.plan = nil
    41  	}
    42  }
    43  
    44  // startExec constructs the wrapped planNode now that execution is underway.
    45  func (d *delayedNode) startExec(params runParams) error {
    46  	if d.plan != nil {
    47  		panic("wrapped plan should not yet exist")
    48  	}
    49  
    50  	plan, err := d.constructor(params.ctx, params.p)
    51  	if err != nil {
    52  		return err
    53  	}
    54  	d.plan = plan
    55  
    56  	// Recursively invoke startExec on new plan. Normally, startExec doesn't
    57  	// recurse - calling children is handled by the planNode walker. The reason
    58  	// this won't suffice here is that the the child of this node doesn't exist
    59  	// until after startExec is invoked.
    60  	return startExec(params, plan)
    61  }