github.com/cockroachdb/cockroach@v20.2.0-alpha.1+incompatible/pkg/sql/opt/optbuilder/scope_column.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  	"context"
    15  
    16  	"github.com/cockroachdb/cockroach/pkg/sql/opt"
    17  	"github.com/cockroachdb/cockroach/pkg/sql/sem/tree"
    18  	"github.com/cockroachdb/cockroach/pkg/sql/types"
    19  	"github.com/cockroachdb/errors"
    20  )
    21  
    22  // scopeColumn holds per-column information that is scoped to a particular
    23  // relational expression. Note that scopeColumn implements the tree.TypedExpr
    24  // interface. During name resolution, unresolved column names in the AST are
    25  // replaced with a scopeColumn.
    26  type scopeColumn struct {
    27  	// name is the current name of this column. It is usually the same as
    28  	// the original name, unless this column was renamed with an AS expression.
    29  	name  tree.Name
    30  	table tree.TableName
    31  	typ   *types.T
    32  
    33  	// id is an identifier for this column, which is unique across all the
    34  	// columns in the query.
    35  	id opt.ColumnID
    36  
    37  	// hidden is true if the column is not selected by a '*' wildcard operator.
    38  	// The column must be explicitly referenced by name, or otherwise is not
    39  	// included.
    40  	hidden bool
    41  
    42  	// mutation is true if the column is in the process of being dropped or added
    43  	// to the table. It should not be visible to variable references.
    44  	mutation bool
    45  
    46  	// descending indicates whether this column is sorted in descending order.
    47  	// This field is only used for ordering columns.
    48  	descending bool
    49  
    50  	// scalar is the scalar expression associated with this column. If it is nil,
    51  	// then the column is a passthrough from an inner scope or a table column.
    52  	scalar opt.ScalarExpr
    53  
    54  	// expr is the AST expression that this column refers to, if any.
    55  	// expr is nil if the column does not refer to an expression.
    56  	expr tree.TypedExpr
    57  
    58  	// exprStr contains a stringified representation of expr, or the original
    59  	// column name if expr is nil. It is populated lazily inside getExprStr().
    60  	exprStr string
    61  }
    62  
    63  // clearName sets the empty table and column name. This is used to make the
    64  // column anonymous so that it cannot be referenced, but will still be
    65  // projected.
    66  func (c *scopeColumn) clearName() {
    67  	c.name = ""
    68  	c.table = tree.TableName{}
    69  }
    70  
    71  // getExpr returns the the expression that this column refers to, or the column
    72  // itself if the column does not refer to an expression.
    73  func (c *scopeColumn) getExpr() tree.TypedExpr {
    74  	if c.expr == nil {
    75  		return c
    76  	}
    77  	return c.expr
    78  }
    79  
    80  // getExprStr gets a stringified representation of the expression that this
    81  // column refers to.
    82  func (c *scopeColumn) getExprStr() string {
    83  	if c.exprStr == "" {
    84  		c.exprStr = symbolicExprStr(c.getExpr())
    85  	}
    86  	return c.exprStr
    87  }
    88  
    89  var _ tree.Expr = &scopeColumn{}
    90  var _ tree.TypedExpr = &scopeColumn{}
    91  var _ tree.VariableExpr = &scopeColumn{}
    92  
    93  func (c *scopeColumn) String() string {
    94  	return tree.AsString(c)
    95  }
    96  
    97  // Format implements the NodeFormatter interface.
    98  func (c *scopeColumn) Format(ctx *tree.FmtCtx) {
    99  	// FmtCheckEquivalence is used by getExprStr when comparing expressions for
   100  	// equivalence. If that flag is present, then use the unique column id to
   101  	// differentiate this column from other columns.
   102  	if ctx.HasFlags(tree.FmtCheckEquivalence) {
   103  		// Use double @ to distinguish from Cockroach column ordinals.
   104  		ctx.Printf("@@%d", c.id)
   105  		return
   106  	}
   107  
   108  	if ctx.HasFlags(tree.FmtShowTableAliases) && c.table.ObjectName != "" {
   109  		if c.table.ExplicitSchema && c.table.SchemaName != "" {
   110  			if c.table.ExplicitCatalog && c.table.CatalogName != "" {
   111  				ctx.FormatNode(&c.table.CatalogName)
   112  				ctx.WriteByte('.')
   113  			}
   114  			ctx.FormatNode(&c.table.SchemaName)
   115  			ctx.WriteByte('.')
   116  		}
   117  
   118  		ctx.FormatNode(&c.table.ObjectName)
   119  		ctx.WriteByte('.')
   120  	}
   121  	ctx.FormatNode(&c.name)
   122  }
   123  
   124  // Walk is part of the tree.Expr interface.
   125  func (c *scopeColumn) Walk(v tree.Visitor) tree.Expr {
   126  	return c
   127  }
   128  
   129  // TypeCheck is part of the tree.Expr interface.
   130  func (c *scopeColumn) TypeCheck(
   131  	_ context.Context, _ *tree.SemaContext, desired *types.T,
   132  ) (tree.TypedExpr, error) {
   133  	return c, nil
   134  }
   135  
   136  // ResolvedType is part of the tree.TypedExpr interface.
   137  func (c *scopeColumn) ResolvedType() *types.T {
   138  	return c.typ
   139  }
   140  
   141  // Eval is part of the tree.TypedExpr interface.
   142  func (*scopeColumn) Eval(_ *tree.EvalContext) (tree.Datum, error) {
   143  	panic(errors.AssertionFailedf("scopeColumn must be replaced before evaluation"))
   144  }
   145  
   146  // Variable is part of the tree.VariableExpr interface. This prevents the
   147  // column from being evaluated during normalization.
   148  func (*scopeColumn) Variable() {}