github.com/cockroachdb/cockroach@v20.2.0-alpha.1+incompatible/pkg/sql/opt/exec/execbuilder/builder.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 execbuilder
    12  
    13  import (
    14  	"github.com/cockroachdb/cockroach/pkg/sql/opt"
    15  	"github.com/cockroachdb/cockroach/pkg/sql/opt/cat"
    16  	"github.com/cockroachdb/cockroach/pkg/sql/opt/exec"
    17  	"github.com/cockroachdb/cockroach/pkg/sql/opt/memo"
    18  	"github.com/cockroachdb/cockroach/pkg/sql/sem/tree"
    19  	"github.com/cockroachdb/cockroach/pkg/util/errorutil"
    20  	"github.com/cockroachdb/cockroach/pkg/util/log"
    21  	"github.com/cockroachdb/errors"
    22  )
    23  
    24  // Builder constructs a tree of execution nodes (exec.Node) from an optimized
    25  // expression tree (opt.Expr).
    26  type Builder struct {
    27  	factory            exec.Factory
    28  	mem                *memo.Memo
    29  	catalog            cat.Catalog
    30  	e                  opt.Expr
    31  	disableTelemetry   bool
    32  	evalCtx            *tree.EvalContext
    33  	fastIsConstVisitor fastIsConstVisitor
    34  
    35  	// subqueries accumulates information about subqueries that are part of scalar
    36  	// expressions we built. Each entry is associated with a tree.Subquery
    37  	// expression node.
    38  	subqueries []exec.Subquery
    39  
    40  	// cascades accumulates cascades that run after the main query but before
    41  	// checks.
    42  	cascades []exec.Cascade
    43  
    44  	// checks accumulates check queries that are run after the main query and
    45  	// any cascades.
    46  	checks []exec.Node
    47  
    48  	// nameGen is used to generate names for the tables that will be created for
    49  	// each relational subexpression when evalCtx.SessionData.SaveTablesPrefix is
    50  	// non-empty.
    51  	nameGen *memo.ExprNameGenerator
    52  
    53  	// withExprs is the set of With expressions which may be referenced elsewhere
    54  	// in the query.
    55  	// TODO(justin): set this up so that we can look them up by index lookups
    56  	// rather than scans.
    57  	withExprs []builtWithExpr
    58  
    59  	// allowAutoCommit is passed through to factory methods for mutation
    60  	// operators. It allows execution to commit the transaction as part of the
    61  	// mutation itself. See canAutoCommit().
    62  	allowAutoCommit bool
    63  
    64  	allowInsertFastPath bool
    65  
    66  	// forceForUpdateLocking is conditionally passed through to factory methods
    67  	// for scan operators that serve as the input for mutation operators. When
    68  	// set to true, it ensures that a FOR UPDATE row-level locking mode is used
    69  	// by scans. See forUpdateLocking.
    70  	forceForUpdateLocking bool
    71  
    72  	// -- output --
    73  
    74  	// IsDDL is set to true if the statement contains DDL.
    75  	IsDDL bool
    76  }
    77  
    78  // New constructs an instance of the execution node builder using the
    79  // given factory to construct nodes. The Build method will build the execution
    80  // node tree from the given optimized expression tree.
    81  //
    82  // catalog is only needed if the statement contains an EXPLAIN (OPT, CATALOG).
    83  func New(
    84  	factory exec.Factory, mem *memo.Memo, catalog cat.Catalog, e opt.Expr, evalCtx *tree.EvalContext,
    85  ) *Builder {
    86  	b := &Builder{
    87  		factory:         factory,
    88  		mem:             mem,
    89  		catalog:         catalog,
    90  		e:               e,
    91  		evalCtx:         evalCtx,
    92  		allowAutoCommit: true,
    93  	}
    94  	if evalCtx != nil {
    95  		if evalCtx.SessionData.SaveTablesPrefix != "" {
    96  			b.nameGen = memo.NewExprNameGenerator(evalCtx.SessionData.SaveTablesPrefix)
    97  		}
    98  		b.allowInsertFastPath = evalCtx.SessionData.InsertFastPath
    99  	}
   100  	return b
   101  }
   102  
   103  // Build constructs the execution node tree and returns its root node if no
   104  // error occurred.
   105  func (b *Builder) Build() (_ exec.Plan, err error) {
   106  	plan, err := b.build(b.e)
   107  	if err != nil {
   108  		return nil, err
   109  	}
   110  	return b.factory.ConstructPlan(plan.root, b.subqueries, b.cascades, b.checks)
   111  }
   112  
   113  func (b *Builder) build(e opt.Expr) (_ execPlan, err error) {
   114  	defer func() {
   115  		if r := recover(); r != nil {
   116  			// This code allows us to propagate errors without adding lots of checks
   117  			// for `if err != nil` throughout the construction code. This is only
   118  			// possible because the code does not update shared state and does not
   119  			// manipulate locks.
   120  			if ok, e := errorutil.ShouldCatch(r); ok {
   121  				err = e
   122  			} else {
   123  				panic(r)
   124  			}
   125  		}
   126  	}()
   127  
   128  	rel, ok := e.(memo.RelExpr)
   129  	if !ok {
   130  		return execPlan{}, errors.AssertionFailedf(
   131  			"building execution for non-relational operator %s", log.Safe(e.Op()),
   132  		)
   133  	}
   134  
   135  	b.allowAutoCommit = b.allowAutoCommit && b.canAutoCommit(rel)
   136  
   137  	return b.buildRelational(rel)
   138  }
   139  
   140  // BuildScalar converts a scalar expression to a TypedExpr. Variables are mapped
   141  // according to the IndexedVarHelper.
   142  func (b *Builder) BuildScalar(ivh *tree.IndexedVarHelper) (tree.TypedExpr, error) {
   143  	scalar, ok := b.e.(opt.ScalarExpr)
   144  	if !ok {
   145  		return nil, errors.AssertionFailedf("BuildScalar cannot be called for non-scalar operator %s", log.Safe(b.e.Op()))
   146  	}
   147  	ctx := buildScalarCtx{ivh: *ivh}
   148  	for i := 0; i < ivh.NumVars(); i++ {
   149  		ctx.ivarMap.Set(i+1, i)
   150  	}
   151  	return b.buildScalar(&ctx, scalar)
   152  }
   153  
   154  func (b *Builder) decorrelationError() error {
   155  	return errors.Errorf("could not decorrelate subquery")
   156  }
   157  
   158  // builtWithExpr is metadata regarding a With expression which has already been
   159  // added to the set of subqueries for the query.
   160  type builtWithExpr struct {
   161  	id opt.WithID
   162  	// outputCols maps the output ColumnIDs of the With expression to the ordinal
   163  	// positions they are output to. See execPlan.outputCols for more details.
   164  	outputCols opt.ColMap
   165  	bufferNode exec.BufferNode
   166  }
   167  
   168  func (b *Builder) addBuiltWithExpr(
   169  	id opt.WithID, outputCols opt.ColMap, bufferNode exec.BufferNode,
   170  ) {
   171  	b.withExprs = append(b.withExprs, builtWithExpr{
   172  		id:         id,
   173  		outputCols: outputCols,
   174  		bufferNode: bufferNode,
   175  	})
   176  }
   177  
   178  func (b *Builder) findBuiltWithExpr(id opt.WithID) *builtWithExpr {
   179  	for i := range b.withExprs {
   180  		if b.withExprs[i].id == id {
   181  			return &b.withExprs[i]
   182  		}
   183  	}
   184  	return nil
   185  }