github.com/cockroachdb/cockroach@v20.2.0-alpha.1+incompatible/pkg/sql/opt/optbuilder/util.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  	"github.com/cockroachdb/cockroach/pkg/sql/opt"
    15  	"github.com/cockroachdb/cockroach/pkg/sql/opt/cat"
    16  	"github.com/cockroachdb/cockroach/pkg/sql/opt/memo"
    17  	"github.com/cockroachdb/cockroach/pkg/sql/pgwire/pgcode"
    18  	"github.com/cockroachdb/cockroach/pkg/sql/pgwire/pgerror"
    19  	"github.com/cockroachdb/cockroach/pkg/sql/privilege"
    20  	"github.com/cockroachdb/cockroach/pkg/sql/sem/tree"
    21  	"github.com/cockroachdb/cockroach/pkg/sql/sessiondata"
    22  	"github.com/cockroachdb/cockroach/pkg/sql/sqlbase"
    23  	"github.com/cockroachdb/cockroach/pkg/sql/types"
    24  	"github.com/cockroachdb/cockroach/pkg/util/errorutil/unimplemented"
    25  	"github.com/cockroachdb/errors"
    26  )
    27  
    28  // windowAggregateFrame() returns a frame that any aggregate built as a window
    29  // can use.
    30  func windowAggregateFrame() memo.WindowFrame {
    31  	return memo.WindowFrame{
    32  		StartBoundType: unboundedStartBound.BoundType,
    33  		EndBoundType:   unboundedEndBound.BoundType,
    34  	}
    35  }
    36  
    37  // getTypedExprs casts the exprs into TypedExps and returns them.
    38  func getTypedExprs(exprs []tree.Expr) []tree.TypedExpr {
    39  	argExprs := make([]tree.TypedExpr, len(exprs))
    40  	for i, expr := range exprs {
    41  		argExprs[i] = expr.(tree.TypedExpr)
    42  	}
    43  	return argExprs
    44  }
    45  
    46  // expandStar expands expr into a list of columns if expr
    47  // corresponds to a "*", "<table>.*" or "(Expr).*".
    48  func (b *Builder) expandStar(
    49  	expr tree.Expr, inScope *scope,
    50  ) (aliases []string, exprs []tree.TypedExpr) {
    51  	if b.insideViewDef {
    52  		panic(unimplemented.NewWithIssue(10028, "views do not currently support * expressions"))
    53  	}
    54  	switch t := expr.(type) {
    55  	case *tree.TupleStar:
    56  		texpr := inScope.resolveType(t.Expr, types.Any)
    57  		typ := texpr.ResolvedType()
    58  		if typ.Family() != types.TupleFamily {
    59  			panic(tree.NewTypeIsNotCompositeError(typ))
    60  		}
    61  
    62  		// If the sub-expression is a tuple constructor, we'll de-tuplify below.
    63  		// Otherwise we'll re-evaluate the expression multiple times.
    64  		//
    65  		// The following query generates a tuple constructor:
    66  		//     SELECT (kv.*).* FROM kv
    67  		//     -- the inner star expansion (scope.VisitPre) first expands to
    68  		//     SELECT (((kv.k, kv.v) as k,v)).* FROM kv
    69  		//     -- then the inner tuple constructor detuplifies here to:
    70  		//     SELECT kv.k, kv.v FROM kv
    71  		//
    72  		// The following query generates a scalar var with tuple type that
    73  		// is not a tuple constructor:
    74  		//
    75  		//     SELECT (SELECT pg_get_keywords() AS x LIMIT 1).*
    76  		//     -- does not detuplify, one gets instead:
    77  		//     SELECT (SELECT pg_get_keywords() AS x LIMIT 1).word,
    78  		//            (SELECT pg_get_keywords() AS x LIMIT 1).catcode,
    79  		//            (SELECT pg_get_keywords() AS x LIMIT 1).catdesc
    80  		//     -- (and we hope a later opt will merge the subqueries)
    81  		tTuple, isTuple := texpr.(*tree.Tuple)
    82  
    83  		aliases = typ.TupleLabels()
    84  		exprs = make([]tree.TypedExpr, len(typ.TupleContents()))
    85  		for i := range typ.TupleContents() {
    86  			if isTuple {
    87  				// De-tuplify: ((a,b,c)).* -> a, b, c
    88  				exprs[i] = tTuple.Exprs[i].(tree.TypedExpr)
    89  			} else {
    90  				// Can't de-tuplify:
    91  				// either (Expr).* -> (Expr).a, (Expr).b, (Expr).c if there are enough
    92  				// labels, or (Expr).* -> (Expr).@1, (Expr).@2, (Expr).@3 if labels are
    93  				// missing.
    94  				//
    95  				// We keep the labels if available so that the column name
    96  				// generation still produces column label "x" for, e.g. (E).x.
    97  				colName := ""
    98  				if i < len(aliases) {
    99  					colName = aliases[i]
   100  				}
   101  				// NewTypedColumnAccessExpr expects colName to be empty if the tuple
   102  				// should be accessed by index.
   103  				exprs[i] = tree.NewTypedColumnAccessExpr(texpr, colName, i)
   104  			}
   105  		}
   106  		for i := len(aliases); i < len(typ.TupleContents()); i++ {
   107  			// Add aliases for all the non-named columns in the tuple.
   108  			aliases = append(aliases, "?column?")
   109  		}
   110  
   111  	case *tree.AllColumnsSelector:
   112  		src, srcMeta, err := t.Resolve(b.ctx, inScope)
   113  		if err != nil {
   114  			panic(err)
   115  		}
   116  		refScope := srcMeta.(*scope)
   117  		exprs = make([]tree.TypedExpr, 0, len(refScope.cols))
   118  		aliases = make([]string, 0, len(refScope.cols))
   119  		for i := range refScope.cols {
   120  			col := &refScope.cols[i]
   121  			if col.table == *src && !col.hidden {
   122  				exprs = append(exprs, col)
   123  				aliases = append(aliases, string(col.name))
   124  			}
   125  		}
   126  
   127  	case tree.UnqualifiedStar:
   128  		if len(inScope.cols) == 0 {
   129  			panic(pgerror.Newf(pgcode.InvalidName,
   130  				"cannot use %q without a FROM clause", tree.ErrString(expr)))
   131  		}
   132  		exprs = make([]tree.TypedExpr, 0, len(inScope.cols))
   133  		aliases = make([]string, 0, len(inScope.cols))
   134  		for i := range inScope.cols {
   135  			col := &inScope.cols[i]
   136  			if !col.hidden {
   137  				exprs = append(exprs, col)
   138  				aliases = append(aliases, string(col.name))
   139  			}
   140  		}
   141  
   142  	default:
   143  		panic(errors.AssertionFailedf("unhandled type: %T", expr))
   144  	}
   145  
   146  	return aliases, exprs
   147  }
   148  
   149  // expandStarAndResolveType expands expr into a list of columns if
   150  // expr corresponds to a "*", "<table>.*" or "(Expr).*". Otherwise,
   151  // expandStarAndResolveType resolves the type of expr and returns it
   152  // as a []TypedExpr.
   153  func (b *Builder) expandStarAndResolveType(
   154  	expr tree.Expr, inScope *scope,
   155  ) (exprs []tree.TypedExpr) {
   156  	switch t := expr.(type) {
   157  	case *tree.AllColumnsSelector, tree.UnqualifiedStar, *tree.TupleStar:
   158  		_, exprs = b.expandStar(expr, inScope)
   159  
   160  	case *tree.UnresolvedName:
   161  		vn, err := t.NormalizeVarName()
   162  		if err != nil {
   163  			panic(err)
   164  		}
   165  		return b.expandStarAndResolveType(vn, inScope)
   166  
   167  	default:
   168  		texpr := inScope.resolveType(t, types.Any)
   169  		exprs = []tree.TypedExpr{texpr}
   170  	}
   171  
   172  	return exprs
   173  }
   174  
   175  // synthesizeColumn is used to synthesize new columns. This is needed for
   176  // operations such as projection of scalar expressions and aggregations. For
   177  // example, the query `SELECT (x + 1) AS "x_incr" FROM t` has a projection with
   178  // a synthesized column "x_incr".
   179  //
   180  // scope  The scope is passed in so it can can be updated with the newly bound
   181  //        variable.
   182  // alias  This is an optional alias for the new column (e.g., if specified with
   183  //        the AS keyword).
   184  // typ    The type of the column.
   185  // expr   The expression this column refers to (if any).
   186  // scalar The scalar expression associated with this column (if any).
   187  //
   188  // The new column is returned as a scopeColumn object.
   189  func (b *Builder) synthesizeColumn(
   190  	scope *scope, alias string, typ *types.T, expr tree.TypedExpr, scalar opt.ScalarExpr,
   191  ) *scopeColumn {
   192  	name := tree.Name(alias)
   193  	colID := b.factory.Metadata().AddColumn(alias, typ)
   194  	scope.cols = append(scope.cols, scopeColumn{
   195  		name:   name,
   196  		typ:    typ,
   197  		id:     colID,
   198  		expr:   expr,
   199  		scalar: scalar,
   200  	})
   201  	return &scope.cols[len(scope.cols)-1]
   202  }
   203  
   204  // populateSynthesizedColumn is similar to synthesizeColumn, but it fills in
   205  // the given existing column rather than allocating a new one.
   206  func (b *Builder) populateSynthesizedColumn(col *scopeColumn, scalar opt.ScalarExpr) {
   207  	colID := b.factory.Metadata().AddColumn(string(col.name), col.typ)
   208  	col.id = colID
   209  	col.scalar = scalar
   210  }
   211  
   212  // projectColumn projects src by copying its column ID to dst. projectColumn
   213  // also copies src.name to dst if an alias is not already set in dst. No other
   214  // fields are copied, for the following reasons:
   215  // - We don't copy group, as dst becomes a pass-through column in the new
   216  //   scope. dst already has group=0, so keep it as-is.
   217  // - We don't copy hidden, because projecting a column makes it visible.
   218  //   dst already has hidden=false, so keep it as-is.
   219  // - We don't copy table, since the table becomes anonymous in the new scope.
   220  // - We don't copy descending, since we don't want to overwrite dst.descending
   221  //   if dst is an ORDER BY column.
   222  // - expr, exprStr and typ in dst already correspond to the expression and type
   223  //   of the src column.
   224  func (b *Builder) projectColumn(dst *scopeColumn, src *scopeColumn) {
   225  	if dst.name == "" {
   226  		dst.name = src.name
   227  	}
   228  	dst.id = src.id
   229  }
   230  
   231  // shouldCreateDefaultColumn decides if we need to create a default
   232  // column and default label for a function expression.
   233  // Returns true if the function's return type is not an empty tuple and
   234  // doesn't declare any tuple labels.
   235  func (b *Builder) shouldCreateDefaultColumn(texpr tree.TypedExpr) bool {
   236  	if texpr.ResolvedType() == types.EmptyTuple {
   237  		// This is only to support crdb_internal.unary_table().
   238  		return false
   239  	}
   240  
   241  	// We need to create a default column with a default name when
   242  	// the function return type doesn't declare any return labels.
   243  	return len(texpr.ResolvedType().TupleLabels()) == 0
   244  }
   245  
   246  // addColumn adds a column to scope with the given alias, type, and
   247  // expression. It returns a pointer to the new column. The column ID and group
   248  // are left empty so they can be filled in later.
   249  func (b *Builder) addColumn(scope *scope, alias string, expr tree.TypedExpr) *scopeColumn {
   250  	name := tree.Name(alias)
   251  	scope.cols = append(scope.cols, scopeColumn{
   252  		name: name,
   253  		typ:  expr.ResolvedType(),
   254  		expr: expr,
   255  	})
   256  	return &scope.cols[len(scope.cols)-1]
   257  }
   258  
   259  func (b *Builder) synthesizeResultColumns(scope *scope, cols sqlbase.ResultColumns) {
   260  	for i := range cols {
   261  		c := b.synthesizeColumn(scope, cols[i].Name, cols[i].Typ, nil /* expr */, nil /* scalar */)
   262  		if cols[i].Hidden {
   263  			c.hidden = true
   264  		}
   265  	}
   266  }
   267  
   268  // colIndex takes an expression that refers to a column using an integer,
   269  // verifies it refers to a valid target in the SELECT list, and returns the
   270  // corresponding column index. For example:
   271  //    SELECT a from T ORDER by 1
   272  // Here "1" refers to the first item in the SELECT list, "a". The returned
   273  // index is 0.
   274  func colIndex(numOriginalCols int, expr tree.Expr, context string) int {
   275  	ord := int64(-1)
   276  	switch i := expr.(type) {
   277  	case *tree.NumVal:
   278  		if i.ShouldBeInt64() {
   279  			val, err := i.AsInt64()
   280  			if err != nil {
   281  				panic(err)
   282  			}
   283  			ord = val
   284  		} else {
   285  			panic(pgerror.Newf(
   286  				pgcode.Syntax,
   287  				"non-integer constant in %s: %s", context, expr,
   288  			))
   289  		}
   290  	case *tree.DInt:
   291  		if *i >= 0 {
   292  			ord = int64(*i)
   293  		}
   294  	case *tree.StrVal:
   295  		panic(pgerror.Newf(
   296  			pgcode.Syntax, "non-integer constant in %s: %s", context, expr,
   297  		))
   298  	case tree.Datum:
   299  		panic(pgerror.Newf(
   300  			pgcode.Syntax, "non-integer constant in %s: %s", context, expr,
   301  		))
   302  	}
   303  	if ord != -1 {
   304  		if ord < 1 || ord > int64(numOriginalCols) {
   305  			panic(pgerror.Newf(
   306  				pgcode.InvalidColumnReference,
   307  				"%s position %s is not in select list", context, expr,
   308  			))
   309  		}
   310  		ord--
   311  	}
   312  	return int(ord)
   313  }
   314  
   315  // colIdxByProjectionAlias returns the corresponding index in columns of an expression
   316  // that may refer to a column alias.
   317  // If there are no aliases in columns that expr refers to, then -1 is returned.
   318  // This method is pertinent to ORDER BY and DISTINCT ON clauses that may refer
   319  // to a column alias.
   320  func colIdxByProjectionAlias(expr tree.Expr, op string, scope *scope) int {
   321  	index := -1
   322  
   323  	if vBase, ok := expr.(tree.VarName); ok {
   324  		v, err := vBase.NormalizeVarName()
   325  		if err != nil {
   326  			panic(err)
   327  		}
   328  
   329  		if c, ok := v.(*tree.ColumnItem); ok && c.TableName == nil {
   330  			// Look for an output column that matches the name. This
   331  			// handles cases like:
   332  			//
   333  			//   SELECT a AS b FROM t ORDER BY b
   334  			//   SELECT DISTINCT ON (b) a AS b FROM t
   335  			target := c.ColumnName
   336  			for j := range scope.cols {
   337  				col := &scope.cols[j]
   338  				if col.name != target {
   339  					continue
   340  				}
   341  
   342  				if col.mutation {
   343  					panic(makeBackfillError(col.name))
   344  				}
   345  
   346  				if index != -1 {
   347  					// There is more than one projection alias that matches the clause.
   348  					// Here, SQL92 is specific as to what should be done: if the
   349  					// underlying expression is known and it is equivalent, then just
   350  					// accept that and ignore the ambiguity. This plays nice with
   351  					// `SELECT b, * FROM t ORDER BY b`. Otherwise, reject with an
   352  					// ambiguity error.
   353  					if scope.cols[j].getExprStr() != scope.cols[index].getExprStr() {
   354  						panic(pgerror.Newf(pgcode.AmbiguousAlias,
   355  							"%s \"%s\" is ambiguous", op, target))
   356  					}
   357  					// Use the index of the first matching column.
   358  					continue
   359  				}
   360  				index = j
   361  			}
   362  		}
   363  	}
   364  
   365  	return index
   366  }
   367  
   368  // makeBackfillError returns an error indicating that the column of the given
   369  // name is currently being backfilled and cannot be referenced.
   370  func makeBackfillError(name tree.Name) error {
   371  	return pgerror.Newf(pgcode.InvalidColumnReference,
   372  		"column %q is being backfilled", tree.ErrString(&name))
   373  }
   374  
   375  // flattenTuples extracts the members of tuples into a list of columns.
   376  func flattenTuples(exprs []tree.TypedExpr) []tree.TypedExpr {
   377  	// We want to avoid allocating new slices unless strictly necessary.
   378  	var newExprs []tree.TypedExpr
   379  	for i, e := range exprs {
   380  		if t, ok := e.(*tree.Tuple); ok {
   381  			if newExprs == nil {
   382  				// All right, it was necessary to allocate the slices after all.
   383  				newExprs = make([]tree.TypedExpr, i, len(exprs))
   384  				copy(newExprs, exprs[:i])
   385  			}
   386  
   387  			newExprs = flattenTuple(t, newExprs)
   388  		} else if newExprs != nil {
   389  			newExprs = append(newExprs, e)
   390  		}
   391  	}
   392  	if newExprs != nil {
   393  		return newExprs
   394  	}
   395  	return exprs
   396  }
   397  
   398  // flattenTuple recursively extracts the members of a tuple into a list of
   399  // expressions.
   400  func flattenTuple(t *tree.Tuple, exprs []tree.TypedExpr) []tree.TypedExpr {
   401  	for _, e := range t.Exprs {
   402  		if eT, ok := e.(*tree.Tuple); ok {
   403  			exprs = flattenTuple(eT, exprs)
   404  		} else {
   405  			expr := e.(tree.TypedExpr)
   406  			exprs = append(exprs, expr)
   407  		}
   408  	}
   409  	return exprs
   410  }
   411  
   412  // symbolicExprStr returns a string representation of the expression using
   413  // symbolic notation. Because the symbolic notation disambiguates columns, this
   414  // string can be used to determine if two expressions are equivalent.
   415  func symbolicExprStr(expr tree.Expr) string {
   416  	return tree.AsStringWithFlags(expr, tree.FmtCheckEquivalence)
   417  }
   418  
   419  func colsToColList(cols []scopeColumn) opt.ColList {
   420  	colList := make(opt.ColList, len(cols))
   421  	for i := range cols {
   422  		colList[i] = cols[i].id
   423  	}
   424  	return colList
   425  }
   426  
   427  // resolveAndBuildScalar is used to build a scalar with a required type.
   428  func (b *Builder) resolveAndBuildScalar(
   429  	expr tree.Expr,
   430  	requiredType *types.T,
   431  	context exprKind,
   432  	flags tree.SemaRejectFlags,
   433  	inScope *scope,
   434  ) opt.ScalarExpr {
   435  	// We need to save and restore the previous value of the field in
   436  	// semaCtx in case we are recursively called within a subquery
   437  	// context.
   438  	defer b.semaCtx.Properties.Restore(b.semaCtx.Properties)
   439  	b.semaCtx.Properties.Require(context.String(), flags)
   440  
   441  	inScope.context = context
   442  	texpr := inScope.resolveAndRequireType(expr, requiredType)
   443  	return b.buildScalar(texpr, inScope, nil, nil, nil)
   444  }
   445  
   446  // In Postgres, qualifying an object name with pg_temp is equivalent to explicitly
   447  // specifying TEMP/TEMPORARY in the CREATE syntax. resolveTemporaryStatus returns
   448  // true if either(or both) of these conditions are true.
   449  func resolveTemporaryStatus(name *tree.TableName, explicitTemp bool) bool {
   450  	// An explicit schema can only be provided in the CREATE TEMP TABLE statement
   451  	// iff it is pg_temp.
   452  	if explicitTemp && name.ExplicitSchema && name.SchemaName != sessiondata.PgTempSchemaName {
   453  		panic(pgerror.New(pgcode.InvalidTableDefinition, "cannot create temporary relation in non-temporary schema"))
   454  	}
   455  	return name.SchemaName == sessiondata.PgTempSchemaName || explicitTemp
   456  }
   457  
   458  // resolveSchemaForCreate returns the schema that will contain a newly created
   459  // catalog object with the given name. If the current user does not have the
   460  // CREATE privilege, then resolveSchemaForCreate raises an error.
   461  func (b *Builder) resolveSchemaForCreate(name *tree.TableName) (cat.Schema, cat.SchemaName) {
   462  	flags := cat.Flags{AvoidDescriptorCaches: true}
   463  	sch, resName, err := b.catalog.ResolveSchema(b.ctx, flags, &name.ObjectNamePrefix)
   464  	if err != nil {
   465  		// Remap invalid schema name error text so that it references the catalog
   466  		// object that could not be created.
   467  		if code := pgerror.GetPGCode(err); code == pgcode.InvalidSchemaName {
   468  			var newErr error
   469  			newErr = pgerror.Newf(pgcode.InvalidSchemaName,
   470  				"cannot create %q because the target database or schema does not exist",
   471  				tree.ErrString(name))
   472  			newErr = errors.WithSecondaryError(newErr, err)
   473  			newErr = errors.WithHint(newErr, "verify that the current database and search_path are valid and/or the target database exists")
   474  			panic(newErr)
   475  		}
   476  		panic(err)
   477  	}
   478  
   479  	// Only allow creation of objects in the public schema.
   480  	if resName.Schema() != tree.PublicSchema {
   481  		panic(pgerror.Newf(pgcode.InvalidName,
   482  			"schema cannot be modified: %q", tree.ErrString(&resName)))
   483  	}
   484  
   485  	if err := b.catalog.CheckPrivilege(b.ctx, sch, privilege.CREATE); err != nil {
   486  		panic(err)
   487  	}
   488  
   489  	return sch, resName
   490  }
   491  
   492  // resolveTableForMutation is a helper method for building mutations. It returns
   493  // the table in the catalog that matches the given TableExpr, along with the
   494  // table's MDDepName and alias, and the IDs of any columns explicitly specified
   495  // by the TableExpr (see tree.TableRef).
   496  //
   497  // If the name does not resolve to a table, then resolveTableForMutation raises
   498  // an error. Privileges are checked when resolving the table, and an error is
   499  // raised if the current user does not have the given privilege.
   500  func (b *Builder) resolveTableForMutation(
   501  	n tree.TableExpr, priv privilege.Kind,
   502  ) (tab cat.Table, depName opt.MDDepName, alias tree.TableName, columns []tree.ColumnID) {
   503  	// Strip off an outer AliasedTableExpr if there is one.
   504  	var outerAlias *tree.TableName
   505  	if ate, ok := n.(*tree.AliasedTableExpr); ok {
   506  		n = ate.Expr
   507  		// It's okay to ignore the As columns here, as they're not permitted in
   508  		// DML aliases where this function is used. The grammar does not allow
   509  		// them, so the parser would have reported an error if they were present.
   510  		if ate.As.Alias != "" {
   511  			outerAlias = tree.NewUnqualifiedTableName(ate.As.Alias)
   512  		}
   513  	}
   514  
   515  	switch t := n.(type) {
   516  	case *tree.TableName:
   517  		tab, alias = b.resolveTable(t, priv)
   518  		depName = opt.DepByName(t)
   519  
   520  	case *tree.TableRef:
   521  		tab = b.resolveTableRef(t, priv)
   522  		alias = tree.MakeUnqualifiedTableName(t.As.Alias)
   523  		depName = opt.DepByID(cat.StableID(t.TableID))
   524  
   525  		// See tree.TableRef: "Note that a nil [Columns] array means 'unspecified'
   526  		// (all columns). whereas an array of length 0 means 'zero columns'.
   527  		// Lists of zero columns are not supported and will throw an error."
   528  		if t.Columns != nil && len(t.Columns) == 0 {
   529  			panic(pgerror.Newf(pgcode.Syntax,
   530  				"an explicit list of column IDs must include at least one column"))
   531  		}
   532  		columns = t.Columns
   533  
   534  	default:
   535  		panic(pgerror.Newf(pgcode.WrongObjectType,
   536  			"%q does not resolve to a table", tree.ErrString(n)))
   537  	}
   538  
   539  	if outerAlias != nil {
   540  		alias = *outerAlias
   541  	}
   542  
   543  	return tab, depName, alias, columns
   544  }
   545  
   546  // resolveTable returns the table in the catalog with the given name. If the
   547  // name does not resolve to a table, or if the current user does not have the
   548  // given privilege, then resolveTable raises an error.
   549  func (b *Builder) resolveTable(
   550  	tn *tree.TableName, priv privilege.Kind,
   551  ) (cat.Table, tree.TableName) {
   552  	ds, resName := b.resolveDataSource(tn, priv)
   553  	tab, ok := ds.(cat.Table)
   554  	if !ok {
   555  		panic(sqlbase.NewWrongObjectTypeError(tn, "table"))
   556  	}
   557  	return tab, resName
   558  }
   559  
   560  // resolveTableRef returns the table in the catalog that matches the given
   561  // TableRef spec. If the name does not resolve to a table, or if the current
   562  // user does not have the given privilege, then resolveTableRef raises an error.
   563  func (b *Builder) resolveTableRef(ref *tree.TableRef, priv privilege.Kind) cat.Table {
   564  	ds := b.resolveDataSourceRef(ref, priv)
   565  	tab, ok := ds.(cat.Table)
   566  	if !ok {
   567  		panic(sqlbase.NewWrongObjectTypeError(ref, "table"))
   568  	}
   569  	return tab
   570  }
   571  
   572  // resolveDataSource returns the data source in the catalog with the given name.
   573  // If the name does not resolve to a table, or if the current user does not have
   574  // the given privilege, then resolveDataSource raises an error.
   575  //
   576  // If the b.qualifyDataSourceNamesInAST flag is set, tn is updated to contain
   577  // the fully qualified name.
   578  func (b *Builder) resolveDataSource(
   579  	tn *tree.TableName, priv privilege.Kind,
   580  ) (cat.DataSource, cat.DataSourceName) {
   581  	var flags cat.Flags
   582  	if b.insideViewDef {
   583  		// Avoid taking table leases when we're creating a view.
   584  		flags.AvoidDescriptorCaches = true
   585  	}
   586  	ds, resName, err := b.catalog.ResolveDataSource(b.ctx, flags, tn)
   587  	if err != nil {
   588  		panic(err)
   589  	}
   590  	b.checkPrivilege(opt.DepByName(tn), ds, priv)
   591  
   592  	if b.qualifyDataSourceNamesInAST {
   593  		*tn = resName
   594  		tn.ExplicitCatalog = true
   595  		tn.ExplicitSchema = true
   596  	}
   597  	return ds, resName
   598  }
   599  
   600  // resolveDataSourceFromRef returns the data source in the catalog that matches
   601  // the given TableRef spec. If no data source matches, or if the current user
   602  // does not have the given privilege, then resolveDataSourceFromRef raises an
   603  // error.
   604  func (b *Builder) resolveDataSourceRef(ref *tree.TableRef, priv privilege.Kind) cat.DataSource {
   605  	var flags cat.Flags
   606  	if b.insideViewDef {
   607  		// Avoid taking table leases when we're creating a view.
   608  		flags.AvoidDescriptorCaches = true
   609  	}
   610  	ds, _, err := b.catalog.ResolveDataSourceByID(b.ctx, flags, cat.StableID(ref.TableID))
   611  	if err != nil {
   612  		panic(pgerror.Wrapf(err, pgcode.UndefinedObject, "%s", tree.ErrString(ref)))
   613  	}
   614  	b.checkPrivilege(opt.DepByID(cat.StableID(ref.TableID)), ds, priv)
   615  	return ds
   616  }
   617  
   618  // checkPrivilege ensures that the current user has the privilege needed to
   619  // access the given object in the catalog. If not, then checkPrivilege raises an
   620  // error. It also adds the object and it's original unresolved name as a
   621  // dependency to the metadata, so that the privileges can be re-checked on reuse
   622  // of the memo.
   623  func (b *Builder) checkPrivilege(name opt.MDDepName, ds cat.DataSource, priv privilege.Kind) {
   624  	if !(priv == privilege.SELECT && b.skipSelectPrivilegeChecks) {
   625  		err := b.catalog.CheckPrivilege(b.ctx, ds, priv)
   626  		if err != nil {
   627  			panic(err)
   628  		}
   629  	} else {
   630  		// The check is skipped, so don't recheck when dependencies are checked.
   631  		priv = 0
   632  	}
   633  
   634  	// Add dependency on this object to the metadata, so that the metadata can be
   635  	// cached and later checked for freshness.
   636  	b.factory.Metadata().AddDependency(name, ds, priv)
   637  }