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 }