github.com/cockroachdb/cockroach@v20.2.0-alpha.1+incompatible/pkg/sql/opt/optbuilder/mutation_builder.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 optbuilder
    12  
    13  import (
    14  	"fmt"
    15  	"strings"
    16  
    17  	"github.com/cockroachdb/cockroach/pkg/server/telemetry"
    18  	"github.com/cockroachdb/cockroach/pkg/sql/opt"
    19  	"github.com/cockroachdb/cockroach/pkg/sql/opt/cat"
    20  	"github.com/cockroachdb/cockroach/pkg/sql/opt/memo"
    21  	"github.com/cockroachdb/cockroach/pkg/sql/parser"
    22  	"github.com/cockroachdb/cockroach/pkg/sql/pgwire/pgcode"
    23  	"github.com/cockroachdb/cockroach/pkg/sql/pgwire/pgerror"
    24  	"github.com/cockroachdb/cockroach/pkg/sql/sem/builtins"
    25  	"github.com/cockroachdb/cockroach/pkg/sql/sem/tree"
    26  	"github.com/cockroachdb/cockroach/pkg/sql/sqlbase"
    27  	"github.com/cockroachdb/cockroach/pkg/sql/sqltelemetry"
    28  	"github.com/cockroachdb/cockroach/pkg/sql/types"
    29  	"github.com/cockroachdb/cockroach/pkg/util"
    30  	"github.com/cockroachdb/errors"
    31  )
    32  
    33  // mutationBuilder is a helper struct that supports building Insert, Update,
    34  // Upsert, and Delete operators in stages.
    35  // TODO(andyk): Add support for Delete.
    36  type mutationBuilder struct {
    37  	b  *Builder
    38  	md *opt.Metadata
    39  
    40  	// opName is the statement's name, used in error messages.
    41  	opName string
    42  
    43  	// tab is the target table.
    44  	tab cat.Table
    45  
    46  	// tabID is the metadata ID of the table.
    47  	tabID opt.TableID
    48  
    49  	// alias is the table alias specified in the mutation statement, or just the
    50  	// resolved table name if no alias was specified.
    51  	alias tree.TableName
    52  
    53  	// outScope contains the current set of columns that are in scope, as well as
    54  	// the output expression as it is incrementally built. Once the final mutation
    55  	// expression is completed, it will be contained in outScope.expr. Columns,
    56  	// when present, are arranged in this order:
    57  	//
    58  	//   +--------+-------+--------+--------+-------+------------------+
    59  	//   | Insert | Fetch | Update | Upsert | Check | Index Predicates |
    60  	//   +--------+-------+--------+--------+-------+------------------+
    61  	//
    62  	// Each column is identified by its ordinal position in outScope, and those
    63  	// ordinals are stored in the corresponding ScopeOrds fields (see below).
    64  	outScope *scope
    65  
    66  	// targetColList is an ordered list of IDs of the table columns into which
    67  	// values will be inserted, or which will be updated with new values. It is
    68  	// incrementally built as the mutation operator is built.
    69  	targetColList opt.ColList
    70  
    71  	// targetColSet contains the same column IDs as targetColList, but as a set.
    72  	targetColSet opt.ColSet
    73  
    74  	// insertOrds lists the outScope columns providing values to insert. Its
    75  	// length is always equal to the number of columns in the target table,
    76  	// including mutation columns. Table columns which will not have values
    77  	// inserted are set to -1 (e.g. delete-only mutation columns). insertOrds
    78  	// is empty if this is not an Insert/Upsert operator.
    79  	insertOrds []scopeOrdinal
    80  
    81  	// fetchOrds lists the outScope columns storing values which are fetched
    82  	// from the target table in order to provide existing values that will form
    83  	// lookup and update values. Its length is always equal to the number of
    84  	// columns in the target table, including mutation columns. Table columns
    85  	// which do not need to be fetched are set to -1. fetchOrds is empty if
    86  	// this is an Insert operator.
    87  	fetchOrds []scopeOrdinal
    88  
    89  	// updateOrds lists the outScope columns providing update values. Its length
    90  	// is always equal to the number of columns in the target table, including
    91  	// mutation columns. Table columns which do not need to be updated are set
    92  	// to -1.
    93  	updateOrds []scopeOrdinal
    94  
    95  	// upsertOrds lists the outScope columns that choose between an insert or
    96  	// update column using a CASE expression:
    97  	//
    98  	//   CASE WHEN canary_col IS NULL THEN ins_col ELSE upd_col END
    99  	//
   100  	// These columns are used to compute constraints and to return result rows.
   101  	// The length of upsertOrds is always equal to the number of columns in
   102  	// the target table, including mutation columns. Table columns which do not
   103  	// need to be updated are set to -1. upsertOrds is empty if this is not
   104  	// an Upsert operator.
   105  	upsertOrds []scopeOrdinal
   106  
   107  	// checkOrds lists the outScope columns storing the boolean results of
   108  	// evaluating check constraint expressions defined on the target table. Its
   109  	// length is always equal to the number of check constraints on the table
   110  	// (see opt.Table.CheckCount).
   111  	checkOrds []scopeOrdinal
   112  
   113  	// indexPredicateOrds lists the outScope columns storing the boolean results
   114  	// of evaluating partial index predicate expressions defined on the indexes
   115  	// of the target table. Its length is always equal to the number of partial
   116  	// indexes on the table.
   117  	// TODO(mgartner): We will likely need two sets of columns to support
   118  	// updates for partial indexes; one set to indicate current rows that need
   119  	// to be removed from the index, and the other to indicate updated rows that
   120  	// need to be added to the index.
   121  	indexPredicateOrds []scopeOrdinal
   122  
   123  	// canaryColID is the ID of the column that is used to decide whether to
   124  	// insert or update each row. If the canary column's value is null, then it's
   125  	// an insert; otherwise it's an update.
   126  	canaryColID opt.ColumnID
   127  
   128  	// subqueries temporarily stores subqueries that were built during initial
   129  	// analysis of SET expressions. They will be used later when the subqueries
   130  	// are joined into larger LEFT OUTER JOIN expressions.
   131  	subqueries []*scope
   132  
   133  	// parsedExprs is a cached set of parsed default and computed expressions
   134  	// from the table schema. These are parsed once and cached for reuse.
   135  	parsedExprs []tree.Expr
   136  
   137  	// checks contains foreign key check queries; see buildFK* methods.
   138  	checks memo.FKChecksExpr
   139  
   140  	// cascades contains foreign key check cascades; see buildFK* methods.
   141  	cascades memo.FKCascades
   142  
   143  	// fkFallback is true if we need to fall back on the legacy path for
   144  	// FK checks / cascades. See buildFK* methods.
   145  	fkFallback bool
   146  
   147  	// withID is nonzero if we need to buffer the input for FK checks.
   148  	withID opt.WithID
   149  
   150  	// extraAccessibleCols stores all the columns that are available to the
   151  	// mutation that are not part of the target table. This is useful for
   152  	// UPDATE ... FROM queries, as the columns from the FROM tables must be
   153  	// made accessible to the RETURNING clause.
   154  	extraAccessibleCols []scopeColumn
   155  
   156  	// fkCheckHelper is used to prevent allocating the helper separately.
   157  	fkCheckHelper fkCheckHelper
   158  }
   159  
   160  func (mb *mutationBuilder) init(b *Builder, opName string, tab cat.Table, alias tree.TableName) {
   161  	mb.b = b
   162  	mb.md = b.factory.Metadata()
   163  	mb.opName = opName
   164  	mb.tab = tab
   165  	mb.alias = alias
   166  	mb.targetColList = make(opt.ColList, 0, tab.DeletableColumnCount())
   167  
   168  	// Allocate segmented array of scope column ordinals.
   169  	n := tab.DeletableColumnCount()
   170  	scopeOrds := make([]scopeOrdinal, n*4+tab.CheckCount()+partialIndexCount(tab))
   171  	for i := range scopeOrds {
   172  		scopeOrds[i] = -1
   173  	}
   174  	mb.insertOrds = scopeOrds[:n]
   175  	mb.fetchOrds = scopeOrds[n : n*2]
   176  	mb.updateOrds = scopeOrds[n*2 : n*3]
   177  	mb.upsertOrds = scopeOrds[n*3 : n*4]
   178  	mb.checkOrds = scopeOrds[n*4 : n*4+tab.CheckCount()]
   179  	mb.indexPredicateOrds = scopeOrds[n*4+tab.CheckCount():]
   180  
   181  	// Add the table and its columns (including mutation columns) to metadata.
   182  	mb.tabID = mb.md.AddTable(tab, &mb.alias)
   183  }
   184  
   185  // scopeOrdToColID returns the ID of the given scope column. If no scope column
   186  // is defined, scopeOrdToColID returns 0.
   187  func (mb *mutationBuilder) scopeOrdToColID(ord scopeOrdinal) opt.ColumnID {
   188  	if ord == -1 {
   189  		return 0
   190  	}
   191  	return mb.outScope.cols[ord].id
   192  }
   193  
   194  // insertColID is a convenience method that returns the ID of the input column
   195  // that provides the insertion value for the given table column (specified by
   196  // ordinal position in the table).
   197  func (mb *mutationBuilder) insertColID(tabOrd int) opt.ColumnID {
   198  	return mb.scopeOrdToColID(mb.insertOrds[tabOrd])
   199  }
   200  
   201  // buildInputForUpdate constructs a Select expression from the fields in
   202  // the Update operator, similar to this:
   203  //
   204  //   SELECT <cols>
   205  //   FROM <table>
   206  //   WHERE <where>
   207  //   ORDER BY <order-by>
   208  //   LIMIT <limit>
   209  //
   210  // All columns from the table to update are added to fetchColList.
   211  // If a FROM clause is defined, we build out each of the table
   212  // expressions required and JOIN them together (LATERAL joins between
   213  // the tables are allowed). We then JOIN the result with the target
   214  // table (the FROM tables can't reference this table) and apply the
   215  // appropriate WHERE conditions.
   216  //
   217  // It is the responsibility of the user to guarantee that the JOIN
   218  // produces a maximum of one row per row of the target table. If multiple
   219  // are found, an arbitrary one is chosen (this row is not readily
   220  // predictable, consistent with the POSTGRES implementation).
   221  // buildInputForUpdate stores the columns of the FROM tables in the
   222  // mutation builder so they can be made accessible to other parts of
   223  // the query (RETURNING clause).
   224  // TODO(andyk): Do needed column analysis to project fewer columns if possible.
   225  func (mb *mutationBuilder) buildInputForUpdate(
   226  	inScope *scope,
   227  	texpr tree.TableExpr,
   228  	from tree.TableExprs,
   229  	where *tree.Where,
   230  	limit *tree.Limit,
   231  	orderBy tree.OrderBy,
   232  ) {
   233  	var indexFlags *tree.IndexFlags
   234  	if source, ok := texpr.(*tree.AliasedTableExpr); ok && source.IndexFlags != nil {
   235  		indexFlags = source.IndexFlags
   236  		telemetry.Inc(sqltelemetry.IndexHintUseCounter)
   237  		telemetry.Inc(sqltelemetry.IndexHintUpdateUseCounter)
   238  	}
   239  
   240  	// Fetch columns from different instance of the table metadata, so that it's
   241  	// possible to remap columns, as in this example:
   242  	//
   243  	//   UPDATE abc SET a=b
   244  	//
   245  	// NOTE: Include mutation columns, but be careful to never use them for any
   246  	//       reason other than as "fetch columns". See buildScan comment.
   247  	mb.outScope = mb.b.buildScan(
   248  		mb.b.addTable(mb.tab, &mb.alias),
   249  		nil, /* ordinals */
   250  		indexFlags,
   251  		noRowLocking,
   252  		includeMutations,
   253  		inScope,
   254  	)
   255  
   256  	fromClausePresent := len(from) > 0
   257  	numCols := len(mb.outScope.cols)
   258  
   259  	// If there is a FROM clause present, we must join all the tables
   260  	// together with the table being updated.
   261  	if fromClausePresent {
   262  		fromScope := mb.b.buildFromTables(from, noRowLocking, inScope)
   263  
   264  		// Check that the same table name is not used multiple times.
   265  		mb.b.validateJoinTableNames(mb.outScope, fromScope)
   266  
   267  		// The FROM table columns can be accessed by the RETURNING clause of the
   268  		// query and so we have to make them accessible.
   269  		mb.extraAccessibleCols = fromScope.cols
   270  
   271  		// Add the columns in the FROM scope.
   272  		mb.outScope.appendColumnsFromScope(fromScope)
   273  
   274  		left := mb.outScope.expr.(memo.RelExpr)
   275  		right := fromScope.expr.(memo.RelExpr)
   276  		mb.outScope.expr = mb.b.factory.ConstructInnerJoin(left, right, memo.TrueFilter, memo.EmptyJoinPrivate)
   277  	}
   278  
   279  	// WHERE
   280  	mb.b.buildWhere(where, mb.outScope)
   281  
   282  	// SELECT + ORDER BY (which may add projected expressions)
   283  	projectionsScope := mb.outScope.replace()
   284  	projectionsScope.appendColumnsFromScope(mb.outScope)
   285  	orderByScope := mb.b.analyzeOrderBy(orderBy, mb.outScope, projectionsScope)
   286  	mb.b.buildOrderBy(mb.outScope, projectionsScope, orderByScope)
   287  	mb.b.constructProjectForScope(mb.outScope, projectionsScope)
   288  
   289  	// LIMIT
   290  	if limit != nil {
   291  		mb.b.buildLimit(limit, inScope, projectionsScope)
   292  	}
   293  
   294  	mb.outScope = projectionsScope
   295  
   296  	// Build a distinct on to ensure there is at most one row in the joined output
   297  	// for every row in the table.
   298  	if fromClausePresent {
   299  		var pkCols opt.ColSet
   300  
   301  		// We need to ensure that the join has a maximum of one row for every row
   302  		// in the table and we ensure this by constructing a distinct on the primary
   303  		// key columns.
   304  		primaryIndex := mb.tab.Index(cat.PrimaryIndex)
   305  		for i := 0; i < primaryIndex.KeyColumnCount(); i++ {
   306  			pkCol := mb.outScope.cols[primaryIndex.Column(i).Ordinal]
   307  
   308  			// If the primary key column is hidden, then we don't need to use it
   309  			// for the distinct on.
   310  			if !pkCol.hidden {
   311  				pkCols.Add(pkCol.id)
   312  			}
   313  		}
   314  
   315  		if !pkCols.Empty() {
   316  			mb.outScope = mb.b.buildDistinctOn(
   317  				pkCols, mb.outScope, false /* nullsAreDistinct */, "" /* errorOnDup */)
   318  		}
   319  	}
   320  
   321  	// Set list of columns that will be fetched by the input expression.
   322  	for i := 0; i < numCols; i++ {
   323  		mb.fetchOrds[i] = scopeOrdinal(i)
   324  	}
   325  }
   326  
   327  // buildInputForDelete constructs a Select expression from the fields in
   328  // the Delete operator, similar to this:
   329  //
   330  //   SELECT <cols>
   331  //   FROM <table>
   332  //   WHERE <where>
   333  //   ORDER BY <order-by>
   334  //   LIMIT <limit>
   335  //
   336  // All columns from the table to update are added to fetchColList.
   337  // TODO(andyk): Do needed column analysis to project fewer columns if possible.
   338  func (mb *mutationBuilder) buildInputForDelete(
   339  	inScope *scope, texpr tree.TableExpr, where *tree.Where, limit *tree.Limit, orderBy tree.OrderBy,
   340  ) {
   341  	var indexFlags *tree.IndexFlags
   342  	if source, ok := texpr.(*tree.AliasedTableExpr); ok && source.IndexFlags != nil {
   343  		indexFlags = source.IndexFlags
   344  		telemetry.Inc(sqltelemetry.IndexHintUseCounter)
   345  		telemetry.Inc(sqltelemetry.IndexHintDeleteUseCounter)
   346  	}
   347  
   348  	// Fetch columns from different instance of the table metadata, so that it's
   349  	// possible to remap columns, as in this example:
   350  	//
   351  	//   DELETE FROM abc WHERE a=b
   352  	//
   353  	// NOTE: Include mutation columns, but be careful to never use them for any
   354  	//       reason other than as "fetch columns". See buildScan comment.
   355  	// TODO(andyk): Why does execution engine need mutation columns for Delete?
   356  	mb.outScope = mb.b.buildScan(
   357  		mb.b.addTable(mb.tab, &mb.alias),
   358  		nil, /* ordinals */
   359  		indexFlags,
   360  		noRowLocking,
   361  		includeMutations,
   362  		inScope,
   363  	)
   364  
   365  	// WHERE
   366  	mb.b.buildWhere(where, mb.outScope)
   367  
   368  	// SELECT + ORDER BY (which may add projected expressions)
   369  	projectionsScope := mb.outScope.replace()
   370  	projectionsScope.appendColumnsFromScope(mb.outScope)
   371  	orderByScope := mb.b.analyzeOrderBy(orderBy, mb.outScope, projectionsScope)
   372  	mb.b.buildOrderBy(mb.outScope, projectionsScope, orderByScope)
   373  	mb.b.constructProjectForScope(mb.outScope, projectionsScope)
   374  
   375  	// LIMIT
   376  	if limit != nil {
   377  		mb.b.buildLimit(limit, inScope, projectionsScope)
   378  	}
   379  
   380  	mb.outScope = projectionsScope
   381  
   382  	// Set list of columns that will be fetched by the input expression.
   383  	for i := range mb.outScope.cols {
   384  		mb.fetchOrds[i] = scopeOrdinal(i)
   385  	}
   386  }
   387  
   388  // addTargetColsByName adds one target column for each of the names in the given
   389  // list.
   390  func (mb *mutationBuilder) addTargetColsByName(names tree.NameList) {
   391  	for _, name := range names {
   392  		// Determine the ordinal position of the named column in the table and
   393  		// add it as a target column.
   394  		if ord := cat.FindTableColumnByName(mb.tab, name); ord != -1 {
   395  			mb.addTargetCol(ord)
   396  			continue
   397  		}
   398  		panic(sqlbase.NewUndefinedColumnError(string(name)))
   399  	}
   400  }
   401  
   402  // addTargetCol adds a target column by its ordinal position in the target
   403  // table. It raises an error if a mutation or computed column is targeted, or if
   404  // the same column is targeted multiple times.
   405  func (mb *mutationBuilder) addTargetCol(ord int) {
   406  	tabCol := mb.tab.Column(ord)
   407  
   408  	// Don't allow targeting of mutation columns.
   409  	if cat.IsMutationColumn(mb.tab, ord) {
   410  		panic(makeBackfillError(tabCol.ColName()))
   411  	}
   412  
   413  	// Computed columns cannot be targeted with input values.
   414  	if tabCol.IsComputed() {
   415  		panic(sqlbase.CannotWriteToComputedColError(string(tabCol.ColName())))
   416  	}
   417  
   418  	// Ensure that the name list does not contain duplicates.
   419  	colID := mb.tabID.ColumnID(ord)
   420  	if mb.targetColSet.Contains(colID) {
   421  		panic(pgerror.Newf(pgcode.Syntax,
   422  			"multiple assignments to the same column %q", tabCol.ColName()))
   423  	}
   424  	mb.targetColSet.Add(colID)
   425  
   426  	mb.targetColList = append(mb.targetColList, colID)
   427  }
   428  
   429  // extractValuesInput tests whether the given input is a VALUES clause with no
   430  // WITH, ORDER BY, or LIMIT modifier. If so, it's returned, otherwise nil is
   431  // returned.
   432  func (mb *mutationBuilder) extractValuesInput(inputRows *tree.Select) *tree.ValuesClause {
   433  	if inputRows == nil {
   434  		return nil
   435  	}
   436  
   437  	// Only extract a simple VALUES clause with no modifiers.
   438  	if inputRows.With != nil || inputRows.OrderBy != nil || inputRows.Limit != nil {
   439  		return nil
   440  	}
   441  
   442  	// Discard parentheses.
   443  	if parens, ok := inputRows.Select.(*tree.ParenSelect); ok {
   444  		return mb.extractValuesInput(parens.Select)
   445  	}
   446  
   447  	if values, ok := inputRows.Select.(*tree.ValuesClause); ok {
   448  		return values
   449  	}
   450  
   451  	return nil
   452  }
   453  
   454  // replaceDefaultExprs looks for DEFAULT specifiers in input value expressions
   455  // and replaces them with the corresponding default value expression for the
   456  // corresponding column. This is only possible when the input is a VALUES
   457  // clause. For example:
   458  //
   459  //   INSERT INTO t (a, b) (VALUES (1, DEFAULT), (DEFAULT, 2))
   460  //
   461  // Here, the two DEFAULT specifiers are replaced by the default value expression
   462  // for the a and b columns, respectively.
   463  //
   464  // replaceDefaultExprs returns a VALUES expression with replaced DEFAULT values,
   465  // or just the unchanged input expression if there are no DEFAULT values.
   466  func (mb *mutationBuilder) replaceDefaultExprs(inRows *tree.Select) (outRows *tree.Select) {
   467  	values := mb.extractValuesInput(inRows)
   468  	if values == nil {
   469  		return inRows
   470  	}
   471  
   472  	// Ensure that the number of input columns exactly matches the number of
   473  	// target columns.
   474  	numCols := len(values.Rows[0])
   475  	mb.checkNumCols(len(mb.targetColList), numCols)
   476  
   477  	var newRows []tree.Exprs
   478  	for irow, tuple := range values.Rows {
   479  		if len(tuple) != numCols {
   480  			reportValuesLenError(numCols, len(tuple))
   481  		}
   482  
   483  		// Scan list of tuples in the VALUES row, looking for DEFAULT specifiers.
   484  		var newTuple tree.Exprs
   485  		for itup, val := range tuple {
   486  			if _, ok := val.(tree.DefaultVal); ok {
   487  				// Found DEFAULT, so lazily create new rows and tuple lists.
   488  				if newRows == nil {
   489  					newRows = make([]tree.Exprs, irow, len(values.Rows))
   490  					copy(newRows, values.Rows[:irow])
   491  				}
   492  
   493  				if newTuple == nil {
   494  					newTuple = make(tree.Exprs, itup, numCols)
   495  					copy(newTuple, tuple[:itup])
   496  				}
   497  
   498  				val = mb.parseDefaultOrComputedExpr(mb.targetColList[itup])
   499  			}
   500  			if newTuple != nil {
   501  				newTuple = append(newTuple, val)
   502  			}
   503  		}
   504  
   505  		if newRows != nil {
   506  			if newTuple != nil {
   507  				newRows = append(newRows, newTuple)
   508  			} else {
   509  				newRows = append(newRows, tuple)
   510  			}
   511  		}
   512  	}
   513  
   514  	if newRows != nil {
   515  		return &tree.Select{Select: &tree.ValuesClause{Rows: newRows}}
   516  	}
   517  	return inRows
   518  }
   519  
   520  // addSynthesizedCols is a helper method for addSynthesizedColsForInsert
   521  // and addSynthesizedColsForUpdate that scans the list of table columns, looking
   522  // for any that do not yet have values provided by the input expression. New
   523  // columns are synthesized for any missing columns, as long as the addCol
   524  // callback function returns true for that column.
   525  //
   526  // Values are synthesized for columns based on checking these rules, in order:
   527  //   1. If column is computed, evaluate that expression as its value.
   528  //   2. If column has a default value specified for it, use that as its value.
   529  //   3. If column is nullable, use NULL as its value.
   530  //   4. If column is currently being added or dropped (i.e. a mutation column),
   531  //      use a default value (0 for INT column, "" for STRING column, etc). Note
   532  //      that the existing "fetched" value returned by the scan cannot be used,
   533  //      since it may not have been initialized yet by the backfiller.
   534  //
   535  func (mb *mutationBuilder) addSynthesizedCols(
   536  	scopeOrds []scopeOrdinal, addCol func(colOrd int) bool,
   537  ) {
   538  	var projectionsScope *scope
   539  
   540  	// Skip delete-only mutation columns, since they are ignored by all mutation
   541  	// operators that synthesize columns.
   542  	for i, n := 0, mb.tab.WritableColumnCount(); i < n; i++ {
   543  		// Skip columns that are already specified.
   544  		if scopeOrds[i] != -1 {
   545  			continue
   546  		}
   547  
   548  		// Invoke addCol to determine whether column should be added.
   549  		if !addCol(i) {
   550  			continue
   551  		}
   552  
   553  		// Construct a new Project operator that will contain the newly synthesized
   554  		// column(s).
   555  		if projectionsScope == nil {
   556  			projectionsScope = mb.outScope.replace()
   557  			projectionsScope.appendColumnsFromScope(mb.outScope)
   558  		}
   559  		tabColID := mb.tabID.ColumnID(i)
   560  		tabCol := mb.tab.Column(i)
   561  		expr := mb.parseDefaultOrComputedExpr(tabColID)
   562  		texpr := mb.outScope.resolveAndRequireType(expr, tabCol.DatumType())
   563  		scopeCol := mb.b.addColumn(projectionsScope, "" /* alias */, texpr)
   564  		mb.b.buildScalar(texpr, mb.outScope, projectionsScope, scopeCol, nil)
   565  
   566  		// Assign name to synthesized column. Computed columns may refer to default
   567  		// columns in the table by name.
   568  		scopeCol.name = tabCol.ColName()
   569  
   570  		// Remember ordinal position of the new scope column.
   571  		scopeOrds[i] = scopeOrdinal(len(projectionsScope.cols) - 1)
   572  
   573  		// Add corresponding target column.
   574  		mb.targetColList = append(mb.targetColList, tabColID)
   575  		mb.targetColSet.Add(tabColID)
   576  	}
   577  
   578  	if projectionsScope != nil {
   579  		mb.b.constructProjectForScope(mb.outScope, projectionsScope)
   580  		mb.outScope = projectionsScope
   581  	}
   582  }
   583  
   584  // roundDecimalValues wraps each DECIMAL-related column (including arrays of
   585  // decimals) with a call to the crdb_internal.round_decimal_values function, if
   586  // column values may need to be rounded. This is necessary when mutating table
   587  // columns that have a limited scale (e.g. DECIMAL(10, 1)). Here is the PG docs
   588  // description:
   589  //
   590  //   http://www.postgresql.org/docs/9.5/static/datatype-numeric.html
   591  //   "If the scale of a value to be stored is greater than
   592  //   the declared scale of the column, the system will round the
   593  //   value to the specified number of fractional digits. Then,
   594  //   if the number of digits to the left of the decimal point
   595  //   exceeds the declared precision minus the declared scale, an
   596  //   error is raised."
   597  //
   598  // Note that this function only handles the rounding portion of that. The
   599  // precision check is done by the execution engine. The rounding cannot be done
   600  // there, since it needs to happen before check constraints are computed, and
   601  // before UPSERT joins.
   602  //
   603  // if roundComputedCols is false, then don't wrap computed columns. If true,
   604  // then only wrap computed columns. This is necessary because computed columns
   605  // can depend on other columns mutated by the operation; it is necessary to
   606  // first round those values, then evaluated the computed expression, and then
   607  // round the result of the computation.
   608  func (mb *mutationBuilder) roundDecimalValues(scopeOrds []scopeOrdinal, roundComputedCols bool) {
   609  	var projectionsScope *scope
   610  
   611  	for i, ord := range scopeOrds {
   612  		if ord == -1 {
   613  			// Column not mutated, so nothing to do.
   614  			continue
   615  		}
   616  
   617  		// Include or exclude computed columns, depending on the value of
   618  		// roundComputedCols.
   619  		col := mb.tab.Column(i)
   620  		if col.IsComputed() != roundComputedCols {
   621  			continue
   622  		}
   623  
   624  		// Check whether the target column's type may require rounding of the
   625  		// input value.
   626  		props, overload := findRoundingFunction(col.DatumType(), col.ColTypePrecision())
   627  		if props == nil {
   628  			continue
   629  		}
   630  		private := &memo.FunctionPrivate{
   631  			Name:       "crdb_internal.round_decimal_values",
   632  			Typ:        mb.outScope.cols[ord].typ,
   633  			Properties: props,
   634  			Overload:   overload,
   635  		}
   636  		variable := mb.b.factory.ConstructVariable(mb.scopeOrdToColID(ord))
   637  		scale := mb.b.factory.ConstructConstVal(tree.NewDInt(tree.DInt(col.ColTypeWidth())), types.Int)
   638  		fn := mb.b.factory.ConstructFunction(memo.ScalarListExpr{variable, scale}, private)
   639  
   640  		// Lazily create new scope and update the scope column to be rounded.
   641  		if projectionsScope == nil {
   642  			projectionsScope = mb.outScope.replace()
   643  			projectionsScope.appendColumnsFromScope(mb.outScope)
   644  		}
   645  		mb.b.populateSynthesizedColumn(&projectionsScope.cols[ord], fn)
   646  	}
   647  
   648  	if projectionsScope != nil {
   649  		mb.b.constructProjectForScope(mb.outScope, projectionsScope)
   650  		mb.outScope = projectionsScope
   651  	}
   652  }
   653  
   654  // findRoundingFunction returns the builtin function overload needed to round
   655  // input values. This is only necessary for DECIMAL or DECIMAL[] types that have
   656  // limited precision, such as:
   657  //
   658  //   DECIMAL(15, 1)
   659  //   DECIMAL(10, 3)[]
   660  //
   661  // If an input decimal value has more than the required number of fractional
   662  // digits, it must be rounded before being inserted into these types.
   663  //
   664  // NOTE: CRDB does not allow nested array storage types, so only one level of
   665  // array nesting needs to be checked.
   666  func findRoundingFunction(typ *types.T, precision int) (*tree.FunctionProperties, *tree.Overload) {
   667  	if precision == 0 {
   668  		// Unlimited precision decimal target type never needs rounding.
   669  		return nil, nil
   670  	}
   671  
   672  	props, overloads := builtins.GetBuiltinProperties("crdb_internal.round_decimal_values")
   673  
   674  	if typ.Equivalent(types.Decimal) {
   675  		return props, &overloads[0]
   676  	}
   677  	if typ.Equivalent(types.DecimalArray) {
   678  		return props, &overloads[1]
   679  	}
   680  
   681  	// Not DECIMAL or DECIMAL[].
   682  	return nil, nil
   683  }
   684  
   685  // addCheckConstraintCols synthesizes a boolean output column for each check
   686  // constraint defined on the target table. The mutation operator will report
   687  // a constraint violation error if the value of the column is false.
   688  func (mb *mutationBuilder) addCheckConstraintCols() {
   689  	if mb.tab.CheckCount() != 0 {
   690  		projectionsScope := mb.outScope.replace()
   691  		projectionsScope.appendColumnsFromScope(mb.outScope)
   692  
   693  		for i, n := 0, mb.tab.CheckCount(); i < n; i++ {
   694  			expr, err := parser.ParseExpr(mb.tab.Check(i).Constraint)
   695  			if err != nil {
   696  				panic(err)
   697  			}
   698  
   699  			alias := fmt.Sprintf("check%d", i+1)
   700  			texpr := mb.outScope.resolveAndRequireType(expr, types.Bool)
   701  			scopeCol := mb.b.addColumn(projectionsScope, alias, texpr)
   702  
   703  			// TODO(ridwanmsharif): Maybe we can avoid building constraints here
   704  			// and instead use the constraints stored in the table metadata.
   705  			mb.b.buildScalar(texpr, mb.outScope, projectionsScope, scopeCol, nil)
   706  			mb.checkOrds[i] = scopeOrdinal(len(projectionsScope.cols) - 1)
   707  		}
   708  
   709  		mb.b.constructProjectForScope(mb.outScope, projectionsScope)
   710  		mb.outScope = projectionsScope
   711  	}
   712  }
   713  
   714  // addPartialIndexPredicateCols synthesizes a boolean output column for each
   715  // partial index defined on the target table. The execution code uses these
   716  // booleans to determine whether or not to insert or delete a row in the partial
   717  // index.
   718  func (mb *mutationBuilder) addPartialIndexPredicateCols() {
   719  	projectionsScope := mb.outScope.replace()
   720  	projectionsScope.appendColumnsFromScope(mb.outScope)
   721  
   722  	ord := 0
   723  	for i, n := 0, mb.tab.IndexCount(); i < n; i++ {
   724  		index := mb.tab.Index(i)
   725  		predicate, ok := index.Predicate()
   726  		if !ok {
   727  			continue
   728  		}
   729  
   730  		expr, err := parser.ParseExpr(predicate)
   731  		if err != nil {
   732  			panic(err)
   733  		}
   734  
   735  		alias := fmt.Sprintf("indexpred%d", ord+1)
   736  		texpr := mb.outScope.resolveAndRequireType(expr, types.Bool)
   737  		scopeCol := mb.b.addColumn(projectionsScope, alias, texpr)
   738  
   739  		mb.b.buildScalar(texpr, mb.outScope, projectionsScope, scopeCol, nil)
   740  		mb.indexPredicateOrds[ord] = scopeOrdinal(len(projectionsScope.cols) - 1)
   741  
   742  		ord++
   743  	}
   744  
   745  	mb.b.constructProjectForScope(mb.outScope, projectionsScope)
   746  	mb.outScope = projectionsScope
   747  }
   748  
   749  // disambiguateColumns ranges over the scope and ensures that at most one column
   750  // has each table column name, and that name refers to the column with the final
   751  // value that the mutation applies.
   752  func (mb *mutationBuilder) disambiguateColumns() {
   753  	// Determine the set of scope columns that will have their names preserved.
   754  	var preserve util.FastIntSet
   755  	for i, n := 0, mb.tab.DeletableColumnCount(); i < n; i++ {
   756  		scopeOrd := mb.mapToReturnScopeOrd(i)
   757  		if scopeOrd != -1 {
   758  			preserve.Add(int(scopeOrd))
   759  		}
   760  	}
   761  
   762  	// Clear names of all non-preserved columns.
   763  	for i := range mb.outScope.cols {
   764  		if !preserve.Contains(i) {
   765  			mb.outScope.cols[i].clearName()
   766  		}
   767  	}
   768  }
   769  
   770  // makeMutationPrivate builds a MutationPrivate struct containing the table and
   771  // column metadata needed for the mutation operator.
   772  func (mb *mutationBuilder) makeMutationPrivate(needResults bool) *memo.MutationPrivate {
   773  	// Helper function to create a column list in the MutationPrivate.
   774  	makeColList := func(scopeOrds []scopeOrdinal) opt.ColList {
   775  		var colList opt.ColList
   776  		for i := range scopeOrds {
   777  			if scopeOrds[i] != -1 {
   778  				if colList == nil {
   779  					colList = make(opt.ColList, len(scopeOrds))
   780  				}
   781  				colList[i] = mb.scopeOrdToColID(scopeOrds[i])
   782  			}
   783  		}
   784  		return colList
   785  	}
   786  
   787  	private := &memo.MutationPrivate{
   788  		Table:              mb.tabID,
   789  		InsertCols:         makeColList(mb.insertOrds),
   790  		FetchCols:          makeColList(mb.fetchOrds),
   791  		UpdateCols:         makeColList(mb.updateOrds),
   792  		CanaryCol:          mb.canaryColID,
   793  		CheckCols:          makeColList(mb.checkOrds),
   794  		IndexPredicateCols: makeColList(mb.indexPredicateOrds),
   795  		FKCascades:         mb.cascades,
   796  		FKFallback:         mb.fkFallback,
   797  	}
   798  
   799  	// If we didn't actually plan any checks or cascades, don't buffer the input.
   800  	if len(mb.checks) > 0 || len(mb.cascades) > 0 {
   801  		private.WithID = mb.withID
   802  	}
   803  
   804  	if needResults {
   805  		// Only non-mutation columns are output columns. ReturnCols needs to have
   806  		// DeletableColumnCount entries, but only the first ColumnCount entries
   807  		// can be defined (i.e. >= 0).
   808  		private.ReturnCols = make(opt.ColList, mb.tab.DeletableColumnCount())
   809  		for i, n := 0, mb.tab.ColumnCount(); i < n; i++ {
   810  			scopeOrd := mb.mapToReturnScopeOrd(i)
   811  			if scopeOrd == -1 {
   812  				panic(errors.AssertionFailedf("column %d is not available in the mutation input", i))
   813  			}
   814  			private.ReturnCols[i] = mb.outScope.cols[scopeOrd].id
   815  		}
   816  	}
   817  
   818  	return private
   819  }
   820  
   821  // mapToReturnScopeOrd returns the ordinal of the scope column that provides the
   822  // final value for the column at the given ordinal position in the table. This
   823  // value might mutate the column, or it might be returned by the mutation
   824  // statement, or it might not be used at all. Columns take priority in this
   825  // order:
   826  //
   827  //   upsert, update, fetch, insert
   828  //
   829  // If an upsert column is available, then it already combines an update/fetch
   830  // value with an insert value, so it takes priority. If an update column is
   831  // available, then it overrides any fetch value. Finally, the relative priority
   832  // of fetch and insert columns doesn't matter, since they're only used together
   833  // in the upsert case where an upsert column would be available.
   834  //
   835  // If the column is never referenced by the statement, then mapToReturnScopeOrd
   836  // returns 0. This would be the case for delete-only columns in an Insert
   837  // statement, because they're neither fetched nor mutated.
   838  func (mb *mutationBuilder) mapToReturnScopeOrd(tabOrd int) scopeOrdinal {
   839  	switch {
   840  	case mb.upsertOrds[tabOrd] != -1:
   841  		return mb.upsertOrds[tabOrd]
   842  
   843  	case mb.updateOrds[tabOrd] != -1:
   844  		return mb.updateOrds[tabOrd]
   845  
   846  	case mb.fetchOrds[tabOrd] != -1:
   847  		return mb.fetchOrds[tabOrd]
   848  
   849  	case mb.insertOrds[tabOrd] != -1:
   850  		return mb.insertOrds[tabOrd]
   851  
   852  	default:
   853  		// Column is never referenced by the statement.
   854  		return -1
   855  	}
   856  }
   857  
   858  // buildReturning wraps the input expression with a Project operator that
   859  // projects the given RETURNING expressions.
   860  func (mb *mutationBuilder) buildReturning(returning tree.ReturningExprs) {
   861  	// Handle case of no RETURNING clause.
   862  	if returning == nil {
   863  		expr := mb.outScope.expr
   864  		mb.outScope = mb.b.allocScope()
   865  		mb.outScope.expr = expr
   866  		return
   867  	}
   868  
   869  	// Start out by constructing a scope containing one column for each non-
   870  	// mutation column in the target table, in the same order, and with the
   871  	// same names. These columns can be referenced by the RETURNING clause.
   872  	//
   873  	//   1. Project only non-mutation columns.
   874  	//   2. Alias columns to use table column names.
   875  	//   3. Mark hidden columns.
   876  	//   4. Project columns in same order as defined in table schema.
   877  	//
   878  	inScope := mb.outScope.replace()
   879  	inScope.expr = mb.outScope.expr
   880  	inScope.appendColumnsFromTable(mb.md.TableMeta(mb.tabID), &mb.alias)
   881  
   882  	// extraAccessibleCols contains all the columns that the RETURNING
   883  	// clause can refer to in addition to the table columns. This is useful for
   884  	// UPDATE ... FROM statements, where all columns from tables in the FROM clause
   885  	// are in scope for the RETURNING clause.
   886  	inScope.appendColumns(mb.extraAccessibleCols)
   887  
   888  	// Construct the Project operator that projects the RETURNING expressions.
   889  	outScope := inScope.replace()
   890  	mb.b.analyzeReturningList(returning, nil /* desiredTypes */, inScope, outScope)
   891  	mb.b.buildProjectionList(inScope, outScope)
   892  	mb.b.constructProjectForScope(inScope, outScope)
   893  	mb.outScope = outScope
   894  }
   895  
   896  // checkNumCols raises an error if the expected number of columns does not match
   897  // the actual number of columns.
   898  func (mb *mutationBuilder) checkNumCols(expected, actual int) {
   899  	if actual != expected {
   900  		more, less := "expressions", "target columns"
   901  		if actual < expected {
   902  			more, less = less, more
   903  		}
   904  
   905  		panic(pgerror.Newf(pgcode.Syntax,
   906  			"%s has more %s than %s, %d expressions for %d targets",
   907  			strings.ToUpper(mb.opName), more, less, actual, expected))
   908  	}
   909  }
   910  
   911  // parseDefaultOrComputedExpr parses the default (including nullable) or
   912  // computed value expression for the given table column, and caches it for
   913  // reuse.
   914  func (mb *mutationBuilder) parseDefaultOrComputedExpr(colID opt.ColumnID) tree.Expr {
   915  	if mb.parsedExprs == nil {
   916  		mb.parsedExprs = make([]tree.Expr, mb.tab.DeletableColumnCount())
   917  	}
   918  
   919  	// Return expression from cache, if it was already parsed previously.
   920  	ord := mb.tabID.ColumnOrdinal(colID)
   921  	if mb.parsedExprs[ord] != nil {
   922  		return mb.parsedExprs[ord]
   923  	}
   924  
   925  	var exprStr string
   926  	tabCol := mb.tab.Column(ord)
   927  	switch {
   928  	case tabCol.IsComputed():
   929  		exprStr = tabCol.ComputedExprStr()
   930  	case tabCol.HasDefault():
   931  		exprStr = tabCol.DefaultExprStr()
   932  	case tabCol.IsNullable():
   933  		return tree.DNull
   934  	default:
   935  		// Synthesize default value for NOT NULL mutation column so that it can be
   936  		// set when in the write-only state. This is only used when no other value
   937  		// is possible (no default value available, NULL not allowed).
   938  		if cat.IsMutationColumn(mb.tab, ord) {
   939  			datum, err := tree.NewDefaultDatum(mb.b.evalCtx, tabCol.DatumType())
   940  			if err != nil {
   941  				panic(err)
   942  			}
   943  			return datum
   944  		}
   945  		return tree.DNull
   946  	}
   947  
   948  	expr, err := parser.ParseExpr(exprStr)
   949  	if err != nil {
   950  		panic(err)
   951  	}
   952  
   953  	mb.parsedExprs[ord] = expr
   954  	return expr
   955  }
   956  
   957  // getIndexLaxKeyOrdinals returns the ordinals of all lax key columns in the
   958  // given index. A column's ordinal is the ordered position of that column in the
   959  // owning table.
   960  func getIndexLaxKeyOrdinals(index cat.Index) util.FastIntSet {
   961  	var keyOrds util.FastIntSet
   962  	for i, n := 0, index.LaxKeyColumnCount(); i < n; i++ {
   963  		keyOrds.Add(index.Column(i).Ordinal)
   964  	}
   965  	return keyOrds
   966  }
   967  
   968  // findNotNullIndexCol finds the first not-null column in the given index and
   969  // returns its ordinal position in the owner table. There must always be such a
   970  // column, even if it turns out to be an implicit primary key column.
   971  func findNotNullIndexCol(index cat.Index) int {
   972  	for i, n := 0, index.KeyColumnCount(); i < n; i++ {
   973  		indexCol := index.Column(i)
   974  		if !indexCol.IsNullable() {
   975  			return indexCol.Ordinal
   976  		}
   977  	}
   978  	panic(errors.AssertionFailedf("should have found not null column in index"))
   979  }
   980  
   981  // resultsNeeded determines whether a statement that might have a RETURNING
   982  // clause needs to provide values for result rows for a downstream plan.
   983  func resultsNeeded(r tree.ReturningClause) bool {
   984  	switch t := r.(type) {
   985  	case *tree.ReturningExprs:
   986  		return true
   987  	case *tree.ReturningNothing, *tree.NoReturningClause:
   988  		return false
   989  	default:
   990  		panic(errors.AssertionFailedf("unexpected ReturningClause type: %T", t))
   991  	}
   992  }
   993  
   994  // checkDatumTypeFitsColumnType verifies that a given scalar value type is valid
   995  // to be stored in a column of the given column type.
   996  //
   997  // For the purpose of this analysis, column type aliases are not considered to
   998  // be different (eg. TEXT and VARCHAR will fit the same scalar type String).
   999  //
  1000  // This is used by the UPDATE, INSERT and UPSERT code.
  1001  func checkDatumTypeFitsColumnType(col cat.Column, typ *types.T) {
  1002  	if typ.Equivalent(col.DatumType()) {
  1003  		return
  1004  	}
  1005  
  1006  	colName := string(col.ColName())
  1007  	panic(pgerror.Newf(pgcode.DatatypeMismatch,
  1008  		"value type %s doesn't match type %s of column %q",
  1009  		typ, col.DatumType(), tree.ErrNameString(colName)))
  1010  }
  1011  
  1012  // partialIndexCount returns the number of public, write-only, and delete-only
  1013  // partial indexes defined on the table.
  1014  func partialIndexCount(tab cat.Table) int {
  1015  	count := 0
  1016  	for i, n := 0, tab.DeletableIndexCount(); i < n; i++ {
  1017  		if _, ok := tab.Index(i).Predicate(); ok {
  1018  			count++
  1019  		}
  1020  	}
  1021  	return count
  1022  }