github.com/cockroachdb/cockroach@v20.2.0-alpha.1+incompatible/pkg/sql/plan_columns.go (about) 1 // Copyright 2017 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 "github.com/cockroachdb/cockroach/pkg/sql/sqlbase" 14 15 var noColumns = make(sqlbase.ResultColumns, 0) 16 17 // planColumns returns the signature of rows logically computed 18 // by the given planNode. 19 // The signature consists of the list of columns with 20 // their name and type. 21 // 22 // The length of the returned slice is guaranteed to be equal to the 23 // length of the tuple returned by the planNode's Values() method 24 // during local execution. 25 // 26 // The returned slice is *not* mutable. To modify the result column 27 // set, implement a separate recursion (e.g. needed_columns.go) or use 28 // planMutableColumns defined below. 29 func planColumns(plan planNode) sqlbase.ResultColumns { 30 return getPlanColumns(plan, false) 31 } 32 33 // planMutableColumns is similar to planColumns() but returns a 34 // ResultColumns slice that can be modified by the caller. 35 func planMutableColumns(plan planNode) sqlbase.ResultColumns { 36 return getPlanColumns(plan, true) 37 } 38 39 // getPlanColumns implements the logic for the 40 // planColumns/planMutableColumns functions. The mut argument 41 // indicates whether the slice should be mutable (mut=true) or not. 42 func getPlanColumns(plan planNode, mut bool) sqlbase.ResultColumns { 43 switch n := plan.(type) { 44 45 // Nodes that define their own schema. 46 case *delayedNode: 47 return n.columns 48 case *groupNode: 49 return n.columns 50 case *joinNode: 51 return n.columns 52 case *ordinalityNode: 53 return n.columns 54 case *renderNode: 55 return n.columns 56 case *scanNode: 57 return n.resultColumns 58 case *unionNode: 59 return n.columns 60 case *valuesNode: 61 return n.columns 62 case *virtualTableNode: 63 return n.columns 64 case *explainPlanNode: 65 return n.run.results.columns 66 case *windowNode: 67 return n.columns 68 case *showTraceNode: 69 return n.columns 70 case *zeroNode: 71 return n.columns 72 case *deleteNode: 73 return n.columns 74 case *updateNode: 75 return n.columns 76 case *insertNode: 77 return n.columns 78 case *insertFastPathNode: 79 return n.columns 80 case *upsertNode: 81 return n.columns 82 case *indexJoinNode: 83 return n.resultColumns 84 case *projectSetNode: 85 return n.columns 86 case *applyJoinNode: 87 return n.columns 88 case *lookupJoinNode: 89 return n.columns 90 case *zigzagJoinNode: 91 return n.columns 92 case *vTableLookupJoinNode: 93 return n.columns 94 95 // Nodes with a fixed schema. 96 case *scrubNode: 97 return n.getColumns(mut, sqlbase.ScrubColumns) 98 case *explainDistSQLNode: 99 return n.getColumns(mut, sqlbase.ExplainDistSQLColumns) 100 case *explainVecNode: 101 return n.getColumns(mut, sqlbase.ExplainVecColumns) 102 case *relocateNode: 103 return n.getColumns(mut, sqlbase.AlterTableRelocateColumns) 104 case *scatterNode: 105 return n.getColumns(mut, sqlbase.AlterTableScatterColumns) 106 case *showFingerprintsNode: 107 return n.getColumns(mut, sqlbase.ShowFingerprintsColumns) 108 case *splitNode: 109 return n.getColumns(mut, sqlbase.AlterTableSplitColumns) 110 case *unsplitNode: 111 return n.getColumns(mut, sqlbase.AlterTableUnsplitColumns) 112 case *unsplitAllNode: 113 return n.getColumns(mut, sqlbase.AlterTableUnsplitColumns) 114 case *showTraceReplicaNode: 115 return n.getColumns(mut, sqlbase.ShowReplicaTraceColumns) 116 case *sequenceSelectNode: 117 return n.getColumns(mut, sqlbase.SequenceSelectColumns) 118 case *exportNode: 119 return n.getColumns(mut, sqlbase.ExportColumns) 120 121 // The columns in the hookFnNode are returned by the hook function; we don't 122 // know if they can be modified in place or not. 123 case *hookFnNode: 124 return n.getColumns(mut, n.header) 125 126 // Nodes that have the same schema as their source or their 127 // valueNode helper. 128 case *bufferNode: 129 return getPlanColumns(n.plan, mut) 130 case *distinctNode: 131 return getPlanColumns(n.plan, mut) 132 case *filterNode: 133 return getPlanColumns(n.source.plan, mut) 134 case *max1RowNode: 135 return getPlanColumns(n.plan, mut) 136 case *limitNode: 137 return getPlanColumns(n.plan, mut) 138 case *spoolNode: 139 return getPlanColumns(n.source, mut) 140 case *serializeNode: 141 return getPlanColumns(n.source, mut) 142 case *saveTableNode: 143 return getPlanColumns(n.source, mut) 144 case *scanBufferNode: 145 return getPlanColumns(n.buffer, mut) 146 case *sortNode: 147 return getPlanColumns(n.plan, mut) 148 case *recursiveCTENode: 149 return getPlanColumns(n.initial, mut) 150 151 case *rowSourceToPlanNode: 152 return n.planCols 153 } 154 155 // Every other node has no columns in their results. 156 return noColumns 157 } 158 159 // optColumnsSlot is a helper struct for nodes with a static signature 160 // (e.g. explainDistSQLNode). It allows instances to reuse a common 161 // (shared) ResultColumns slice as long as no read/write access is 162 // requested to the slice via planMutableColumns. 163 type optColumnsSlot struct { 164 columns sqlbase.ResultColumns 165 } 166 167 func (c *optColumnsSlot) getColumns(mut bool, cols sqlbase.ResultColumns) sqlbase.ResultColumns { 168 if c.columns != nil { 169 return c.columns 170 } 171 if !mut { 172 return cols 173 } 174 c.columns = make(sqlbase.ResultColumns, len(cols)) 175 copy(c.columns, cols) 176 return c.columns 177 }