github.com/cockroachdb/cockroach@v20.2.0-alpha.1+incompatible/pkg/sql/sqlbase/select_name_resolution.go (about) 1 // Copyright 2016 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 // This file implements the select code that deals with column references 12 // and resolving column names in expressions. 13 14 package sqlbase 15 16 import ( 17 "context" 18 19 "github.com/cockroachdb/cockroach/pkg/sql/sem/tree" 20 "github.com/cockroachdb/cockroach/pkg/sql/sessiondata" 21 ) 22 23 // NameResolutionVisitor is a tree.Visitor implementation used to 24 // resolve the column names in an expression. 25 type NameResolutionVisitor struct { 26 err error 27 iVarHelper tree.IndexedVarHelper 28 searchPath sessiondata.SearchPath 29 resolver ColumnResolver 30 } 31 32 var _ tree.Visitor = &NameResolutionVisitor{} 33 34 // VisitPre implements tree.Visitor. 35 func (v *NameResolutionVisitor) VisitPre(expr tree.Expr) (recurse bool, newNode tree.Expr) { 36 if v.err != nil { 37 return false, expr 38 } 39 40 switch t := expr.(type) { 41 case *tree.IndexedVar: 42 // If the indexed var is a standalone ordinal reference, ensure it 43 // becomes a fully bound indexed var. 44 t, v.err = v.iVarHelper.BindIfUnbound(t) 45 if v.err != nil { 46 return false, expr 47 } 48 49 return false, t 50 51 case *tree.UnresolvedName: 52 vn, err := t.NormalizeVarName() 53 if err != nil { 54 v.err = err 55 return false, expr 56 } 57 return v.VisitPre(vn) 58 59 case *tree.ColumnItem: 60 _, err := t.Resolve(context.TODO(), &v.resolver) 61 if err != nil { 62 v.err = err 63 return false, expr 64 } 65 66 colIdx := v.resolver.ResolverState.ColIdx 67 ivar := v.iVarHelper.IndexedVar(colIdx) 68 return true, ivar 69 70 case *tree.FuncExpr: 71 // Check for invalid use of *, which, if it is an argument, is the only argument. 72 if len(t.Exprs) != 1 { 73 break 74 } 75 vn, ok := t.Exprs[0].(tree.VarName) 76 if !ok { 77 break 78 } 79 vn, v.err = vn.NormalizeVarName() 80 if v.err != nil { 81 return false, expr 82 } 83 // Save back to avoid re-doing the work later. 84 t.Exprs[0] = vn 85 return true, t 86 } 87 88 return true, expr 89 } 90 91 // VisitPost implements tree.Visitor. 92 func (*NameResolutionVisitor) VisitPost(expr tree.Expr) tree.Expr { return expr } 93 94 // ResolveNames is a wrapper around ResolveNamesUsingVisitor. 95 func ResolveNames( 96 expr tree.Expr, 97 source *DataSourceInfo, 98 ivarHelper tree.IndexedVarHelper, 99 searchPath sessiondata.SearchPath, 100 ) (tree.Expr, error) { 101 var v NameResolutionVisitor 102 return ResolveNamesUsingVisitor(&v, expr, source, ivarHelper, searchPath) 103 } 104 105 // ResolveNamesUsingVisitor resolves the names in the given expression. 106 func ResolveNamesUsingVisitor( 107 v *NameResolutionVisitor, 108 expr tree.Expr, 109 source *DataSourceInfo, 110 ivarHelper tree.IndexedVarHelper, 111 searchPath sessiondata.SearchPath, 112 ) (tree.Expr, error) { 113 *v = NameResolutionVisitor{ 114 iVarHelper: ivarHelper, 115 searchPath: searchPath, 116 resolver: ColumnResolver{ 117 Source: source, 118 }, 119 } 120 121 expr, _ = tree.WalkExpr(v, expr) 122 return expr, v.err 123 }