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  }