github.com/cockroachdb/cockroach@v20.2.0-alpha.1+incompatible/pkg/sql/opt/exec/execbuilder/statement.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 execbuilder 12 13 import ( 14 "bytes" 15 16 "github.com/cockroachdb/cockroach/pkg/server/telemetry" 17 "github.com/cockroachdb/cockroach/pkg/sql/opt" 18 "github.com/cockroachdb/cockroach/pkg/sql/opt/cat" 19 "github.com/cockroachdb/cockroach/pkg/sql/opt/exec" 20 "github.com/cockroachdb/cockroach/pkg/sql/opt/memo" 21 "github.com/cockroachdb/cockroach/pkg/sql/sem/tree" 22 "github.com/cockroachdb/cockroach/pkg/sql/sqlbase" 23 "github.com/cockroachdb/cockroach/pkg/sql/sqltelemetry" 24 "github.com/cockroachdb/cockroach/pkg/util/treeprinter" 25 ) 26 27 func (b *Builder) buildCreateTable(ct *memo.CreateTableExpr) (execPlan, error) { 28 var root exec.Node 29 if ct.Syntax.As() { 30 // Construct AS input to CREATE TABLE. 31 input, err := b.buildRelational(ct.Input) 32 if err != nil { 33 return execPlan{}, err 34 } 35 // Impose ordering and naming on input columns, so that they match the 36 // order and names of the table columns into which values will be 37 // inserted. 38 colList := make(opt.ColList, len(ct.InputCols)) 39 colNames := make([]string, len(ct.InputCols)) 40 for i := range ct.InputCols { 41 colList[i] = ct.InputCols[i].ID 42 colNames[i] = ct.InputCols[i].Alias 43 } 44 input, err = b.ensureColumns(input, colList, colNames, nil /* provided */) 45 if err != nil { 46 return execPlan{}, err 47 } 48 root = input.root 49 } 50 51 schema := b.mem.Metadata().Schema(ct.Schema) 52 root, err := b.factory.ConstructCreateTable(root, schema, ct.Syntax) 53 return execPlan{root: root}, err 54 } 55 56 func (b *Builder) buildCreateView(cv *memo.CreateViewExpr) (execPlan, error) { 57 md := b.mem.Metadata() 58 schema := md.Schema(cv.Schema) 59 cols := make(sqlbase.ResultColumns, len(cv.Columns)) 60 for i := range cols { 61 cols[i].Name = cv.Columns[i].Alias 62 cols[i].Typ = md.ColumnMeta(cv.Columns[i].ID).Type 63 } 64 root, err := b.factory.ConstructCreateView( 65 schema, 66 cv.ViewName, 67 cv.IfNotExists, 68 cv.Replace, 69 cv.Temporary, 70 cv.ViewQuery, 71 cols, 72 cv.Deps, 73 ) 74 return execPlan{root: root}, err 75 } 76 77 func (b *Builder) buildExplain(explain *memo.ExplainExpr) (execPlan, error) { 78 var node exec.Node 79 80 if explain.Options.Mode == tree.ExplainOpt { 81 fmtFlags := memo.ExprFmtHideAll 82 switch { 83 case explain.Options.Flags[tree.ExplainFlagVerbose]: 84 fmtFlags = memo.ExprFmtHideQualifications | memo.ExprFmtHideScalars | 85 memo.ExprFmtHideTypes | memo.ExprFmtHideNotNull 86 87 case explain.Options.Flags[tree.ExplainFlagTypes]: 88 fmtFlags = memo.ExprFmtHideQualifications 89 } 90 91 // Format the plan here and pass it through to the exec factory. 92 93 // If catalog option was passed, show catalog object details for all tables. 94 var planText bytes.Buffer 95 if explain.Options.Flags[tree.ExplainFlagCatalog] { 96 for _, t := range b.mem.Metadata().AllTables() { 97 tp := treeprinter.New() 98 cat.FormatTable(b.catalog, t.Table, tp) 99 planText.WriteString(tp.String()) 100 } 101 // TODO(radu): add views, sequences 102 } 103 104 f := memo.MakeExprFmtCtx(fmtFlags, b.mem, b.catalog) 105 f.FormatExpr(explain.Input) 106 planText.WriteString(f.Buffer.String()) 107 108 // If we're going to display the environment, there's a bunch of queries we 109 // need to run to get that information, and we can't run them from here, so 110 // tell the exec factory what information it needs to fetch. 111 var envOpts exec.ExplainEnvData 112 if explain.Options.Flags[tree.ExplainFlagEnv] { 113 envOpts = b.getEnvData() 114 } 115 116 var err error 117 node, err = b.factory.ConstructExplainOpt(planText.String(), envOpts) 118 if err != nil { 119 return execPlan{}, err 120 } 121 } else { 122 123 // The auto commit flag should reflect what would happen if this statement 124 // was run without the explain, so recalculate it. 125 defer func(oldVal bool) { 126 b.allowAutoCommit = oldVal 127 }(b.allowAutoCommit) 128 b.allowAutoCommit = b.canAutoCommit(explain.Input) 129 130 input, err := b.buildRelational(explain.Input) 131 if err != nil { 132 return execPlan{}, err 133 } 134 135 plan, err := b.factory.ConstructPlan(input.root, b.subqueries, b.cascades, b.checks) 136 if err != nil { 137 return execPlan{}, err 138 } 139 140 node, err = b.factory.ConstructExplain(&explain.Options, explain.StmtType, plan) 141 if err != nil { 142 return execPlan{}, err 143 } 144 } 145 146 ep := execPlan{root: node} 147 for i, c := range explain.ColList { 148 ep.outputCols.Set(int(c), i) 149 } 150 // The subqueries/cascades/checks are now owned by the explain node; 151 // remove them so they don't also show up in the final plan. 152 b.subqueries = nil 153 b.cascades = nil 154 b.checks = nil 155 return ep, nil 156 } 157 158 func (b *Builder) buildShowTrace(show *memo.ShowTraceForSessionExpr) (execPlan, error) { 159 node, err := b.factory.ConstructShowTrace(show.TraceType, show.Compact) 160 if err != nil { 161 return execPlan{}, err 162 } 163 ep := execPlan{root: node} 164 for i, c := range show.ColList { 165 ep.outputCols.Set(int(c), i) 166 } 167 return ep, nil 168 } 169 170 func (b *Builder) buildAlterTableSplit(split *memo.AlterTableSplitExpr) (execPlan, error) { 171 input, err := b.buildRelational(split.Input) 172 if err != nil { 173 return execPlan{}, err 174 } 175 scalarCtx := buildScalarCtx{} 176 expiration, err := b.buildScalar(&scalarCtx, split.Expiration) 177 if err != nil { 178 return execPlan{}, err 179 } 180 table := b.mem.Metadata().Table(split.Table) 181 node, err := b.factory.ConstructAlterTableSplit( 182 table.Index(split.Index), 183 input.root, 184 expiration, 185 ) 186 if err != nil { 187 return execPlan{}, err 188 } 189 ep := execPlan{root: node} 190 for i, c := range split.Columns { 191 ep.outputCols.Set(int(c), i) 192 } 193 return ep, nil 194 } 195 196 func (b *Builder) buildAlterTableUnsplit(unsplit *memo.AlterTableUnsplitExpr) (execPlan, error) { 197 input, err := b.buildRelational(unsplit.Input) 198 if err != nil { 199 return execPlan{}, err 200 } 201 table := b.mem.Metadata().Table(unsplit.Table) 202 node, err := b.factory.ConstructAlterTableUnsplit( 203 table.Index(unsplit.Index), 204 input.root, 205 ) 206 if err != nil { 207 return execPlan{}, err 208 } 209 ep := execPlan{root: node} 210 for i, c := range unsplit.Columns { 211 ep.outputCols.Set(int(c), i) 212 } 213 return ep, nil 214 } 215 216 func (b *Builder) buildAlterTableUnsplitAll( 217 unsplitAll *memo.AlterTableUnsplitAllExpr, 218 ) (execPlan, error) { 219 table := b.mem.Metadata().Table(unsplitAll.Table) 220 node, err := b.factory.ConstructAlterTableUnsplitAll(table.Index(unsplitAll.Index)) 221 if err != nil { 222 return execPlan{}, err 223 } 224 ep := execPlan{root: node} 225 for i, c := range unsplitAll.Columns { 226 ep.outputCols.Set(int(c), i) 227 } 228 return ep, nil 229 } 230 231 func (b *Builder) buildAlterTableRelocate(relocate *memo.AlterTableRelocateExpr) (execPlan, error) { 232 input, err := b.buildRelational(relocate.Input) 233 if err != nil { 234 return execPlan{}, err 235 } 236 table := b.mem.Metadata().Table(relocate.Table) 237 node, err := b.factory.ConstructAlterTableRelocate( 238 table.Index(relocate.Index), 239 input.root, 240 relocate.RelocateLease, 241 ) 242 if err != nil { 243 return execPlan{}, err 244 } 245 ep := execPlan{root: node} 246 for i, c := range relocate.Columns { 247 ep.outputCols.Set(int(c), i) 248 } 249 return ep, nil 250 } 251 252 func (b *Builder) buildControlJobs(ctl *memo.ControlJobsExpr) (execPlan, error) { 253 input, err := b.buildRelational(ctl.Input) 254 if err != nil { 255 return execPlan{}, err 256 } 257 node, err := b.factory.ConstructControlJobs( 258 ctl.Command, 259 input.root, 260 ) 261 if err != nil { 262 return execPlan{}, err 263 } 264 // ControlJobs returns no columns. 265 return execPlan{root: node}, nil 266 } 267 268 func (b *Builder) buildCancelQueries(cancel *memo.CancelQueriesExpr) (execPlan, error) { 269 input, err := b.buildRelational(cancel.Input) 270 if err != nil { 271 return execPlan{}, err 272 } 273 node, err := b.factory.ConstructCancelQueries(input.root, cancel.IfExists) 274 if err != nil { 275 return execPlan{}, err 276 } 277 if !b.disableTelemetry { 278 telemetry.Inc(sqltelemetry.CancelQueriesUseCounter) 279 } 280 // CancelQueries returns no columns. 281 return execPlan{root: node}, nil 282 } 283 284 func (b *Builder) buildCancelSessions(cancel *memo.CancelSessionsExpr) (execPlan, error) { 285 input, err := b.buildRelational(cancel.Input) 286 if err != nil { 287 return execPlan{}, err 288 } 289 node, err := b.factory.ConstructCancelSessions(input.root, cancel.IfExists) 290 if err != nil { 291 return execPlan{}, err 292 } 293 if !b.disableTelemetry { 294 telemetry.Inc(sqltelemetry.CancelSessionsUseCounter) 295 } 296 // CancelSessions returns no columns. 297 return execPlan{root: node}, nil 298 } 299 300 func (b *Builder) buildExport(export *memo.ExportExpr) (execPlan, error) { 301 input, err := b.buildRelational(export.Input) 302 if err != nil { 303 return execPlan{}, err 304 } 305 306 scalarCtx := buildScalarCtx{} 307 fileName, err := b.buildScalar(&scalarCtx, export.FileName) 308 if err != nil { 309 return execPlan{}, err 310 } 311 312 opts := make([]exec.KVOption, len(export.Options)) 313 for i, o := range export.Options { 314 opts[i].Key = o.Key 315 var err error 316 opts[i].Value, err = b.buildScalar(&scalarCtx, o.Value) 317 if err != nil { 318 return execPlan{}, err 319 } 320 } 321 322 node, err := b.factory.ConstructExport( 323 input.root, 324 fileName, 325 export.FileFormat, 326 opts, 327 ) 328 if err != nil { 329 return execPlan{}, err 330 } 331 ep := execPlan{root: node} 332 for i, c := range export.Columns { 333 ep.outputCols.Set(int(c), i) 334 } 335 return ep, nil 336 }