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  }