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() {}