github.com/cockroachdb/cockroach@v20.2.0-alpha.1+incompatible/pkg/sql/rowexec/ordinality.go (about) 1 // Copyright 2019 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 rowexec 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/tracing" 22 "github.com/opentracing/opentracing-go" 23 ) 24 25 // ordinalityProcessor is the processor of the WITH ORDINALITY operator, which 26 // adds an additional ordinal column to the result. 27 type ordinalityProcessor struct { 28 execinfra.ProcessorBase 29 30 input execinfra.RowSource 31 curCnt int64 32 } 33 34 var _ execinfra.Processor = &ordinalityProcessor{} 35 var _ execinfra.RowSource = &ordinalityProcessor{} 36 37 const ordinalityProcName = "ordinality" 38 39 func newOrdinalityProcessor( 40 flowCtx *execinfra.FlowCtx, 41 processorID int32, 42 spec *execinfrapb.OrdinalitySpec, 43 input execinfra.RowSource, 44 post *execinfrapb.PostProcessSpec, 45 output execinfra.RowReceiver, 46 ) (execinfra.RowSourcedProcessor, error) { 47 ctx := flowCtx.EvalCtx.Ctx() 48 o := &ordinalityProcessor{input: input, curCnt: 1} 49 50 colTypes := make([]*types.T, len(input.OutputTypes())+1) 51 copy(colTypes, input.OutputTypes()) 52 colTypes[len(colTypes)-1] = types.Int 53 if err := o.Init( 54 o, 55 post, 56 colTypes, 57 flowCtx, 58 processorID, 59 output, 60 nil, /* memMonitor */ 61 execinfra.ProcStateOpts{ 62 InputsToDrain: []execinfra.RowSource{o.input}, 63 TrailingMetaCallback: func(context.Context) []execinfrapb.ProducerMetadata { 64 o.ConsumerClosed() 65 return nil 66 }}, 67 ); err != nil { 68 return nil, err 69 } 70 71 if sp := opentracing.SpanFromContext(ctx); sp != nil && tracing.IsRecording(sp) { 72 o.input = newInputStatCollector(o.input) 73 o.FinishTrace = o.outputStatsToTrace 74 } 75 76 return o, nil 77 } 78 79 // Start is part of the RowSource interface. 80 func (o *ordinalityProcessor) Start(ctx context.Context) context.Context { 81 o.input.Start(ctx) 82 return o.StartInternal(ctx, ordinalityProcName) 83 } 84 85 // Next is part of the RowSource interface. 86 func (o *ordinalityProcessor) Next() (sqlbase.EncDatumRow, *execinfrapb.ProducerMetadata) { 87 for o.State == execinfra.StateRunning { 88 row, meta := o.input.Next() 89 90 if meta != nil { 91 if meta.Err != nil { 92 o.MoveToDraining(nil /* err */) 93 } 94 return nil, meta 95 } 96 if row == nil { 97 o.MoveToDraining(nil /* err */) 98 break 99 } 100 101 // The ordinality should increment even if the row gets filtered out. 102 row = append(row, sqlbase.DatumToEncDatum(types.Int, tree.NewDInt(tree.DInt(o.curCnt)))) 103 o.curCnt++ 104 if outRow := o.ProcessRowHelper(row); outRow != nil { 105 return outRow, nil 106 } 107 } 108 return nil, o.DrainHelper() 109 110 } 111 112 // ConsumerClosed is part of the RowSource interface. 113 func (o *ordinalityProcessor) ConsumerClosed() { 114 // The consumer is done, Next() will not be called again. 115 o.InternalClose() 116 } 117 118 const ordinalityTagPrefix = "ordinality." 119 120 // Stats implements the SpanStats interface. 121 func (os *OrdinalityStats) Stats() map[string]string { 122 return os.InputStats.Stats(ordinalityTagPrefix) 123 } 124 125 // StatsForQueryPlan implements the DistSQLSpanStats interface. 126 func (os *OrdinalityStats) StatsForQueryPlan() []string { 127 return os.InputStats.StatsForQueryPlan("") 128 } 129 130 // outputStatsToTrace outputs the collected distinct stats to the trace. Will 131 // fail silently if the Distinct processor is not collecting stats. 132 func (o *ordinalityProcessor) outputStatsToTrace() { 133 is, ok := getInputStats(o.FlowCtx, o.input) 134 if !ok { 135 return 136 } 137 if sp := opentracing.SpanFromContext(o.Ctx); sp != nil { 138 tracing.SetSpanStats( 139 sp, &OrdinalityStats{InputStats: is}, 140 ) 141 } 142 }