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 }