github.com/cockroachdb/cockroachdb-parser@v0.23.3-0.20240213214944-911057d40c9a/pkg/sql/sem/tree/function_name.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  package tree
    12  
    13  import (
    14  	"context"
    15  	"fmt"
    16  	"strings"
    17  
    18  	"github.com/cockroachdb/cockroachdb-parser/pkg/sql/pgwire/pgcode"
    19  	"github.com/cockroachdb/cockroachdb-parser/pkg/sql/pgwire/pgerror"
    20  	"github.com/cockroachdb/cockroachdb-parser/pkg/sql/sem/catconstants"
    21  	"github.com/cockroachdb/errors"
    22  	"github.com/lib/pq/oid"
    23  )
    24  
    25  // ErrRoutineUndefined indicates that the required function is not found. It is
    26  // used as the cause of the errors thrown when function resolution cannot find a
    27  // required function.
    28  var ErrRoutineUndefined = pgerror.Newf(pgcode.UndefinedFunction, "routine undefined")
    29  
    30  // Function names are used in expressions in the FuncExpr node.
    31  // General syntax:
    32  //    [ <context-prefix> . ] <function-name>
    33  //
    34  // The other syntax nodes hold a mutable ResolvableFunctionReference
    35  // attribute.  This is populated during parsing with an
    36  // UnresolvedName, and gets assigned a FunctionDefinition upon the
    37  // first call to its ResolveFunction() method.
    38  
    39  // FunctionReferenceResolver is the interface that provides the ability to
    40  // resolve built-in or user-defined function definitions from unresolved names.
    41  type FunctionReferenceResolver interface {
    42  	// ResolveFunction resolves a group of overloads with the given function name
    43  	// within a search path. An error with ErrRoutineUndefined cause is returned
    44  	// if function does not exist.
    45  	//
    46  	// TODO(Chengxiong): Consider adding an optional slice of argument types to
    47  	// the input of this method, so that we can try to narrow down the scope of
    48  	// overloads a bit earlier and decrease the possibility of ambiguous error
    49  	// on function properties.
    50  	ResolveFunction(
    51  		ctx context.Context, name UnresolvedRoutineName, path SearchPath,
    52  	) (*ResolvedFunctionDefinition, error)
    53  
    54  	// ResolveFunctionByOID looks up a function overload by using a given oid.
    55  	// Function name is returned together with the overload. Error is thrown if
    56  	// there is no function with the same oid.
    57  	ResolveFunctionByOID(
    58  		ctx context.Context, oid oid.Oid,
    59  	) (*RoutineName, *Overload, error)
    60  }
    61  
    62  // ResolvableFunctionReference implements the editable reference call of a
    63  // FuncExpr.
    64  type ResolvableFunctionReference struct {
    65  	// ReferenceByName keeps track of the name that was used to resolve the
    66  	// function, if one was used. This is used for metadata dependency tracking.
    67  	ReferenceByName *UnresolvedObjectName
    68  	FunctionReference
    69  }
    70  
    71  // Resolve converts a ResolvableFunctionReference into a *FunctionDefinition. If
    72  // the reference has already been resolved, it simply returns the definition. If
    73  // a FunctionReferenceResolver is provided, it will be used to resolve the
    74  // function definition. Otherwise, the default resolution of
    75  // UnresolvedName.ResolveFunction is used.
    76  func (ref *ResolvableFunctionReference) Resolve(
    77  	ctx context.Context, path SearchPath, resolver FunctionReferenceResolver,
    78  ) (*ResolvedFunctionDefinition, error) {
    79  	switch t := ref.FunctionReference.(type) {
    80  	case *ResolvedFunctionDefinition:
    81  		return t, nil
    82  	case *FunctionDefinition:
    83  		// TODO(Chengxiong): get rid of FunctionDefinition entirely.
    84  		parts := strings.Split(t.Name, ".")
    85  		if len(parts) > 2 {
    86  			// In theory, this should not happen since all builtin functions are
    87  			// defined within virtual schema and don't belong to any database catalog.
    88  			return nil, errors.AssertionFailedf("invalid builtin function name: %q", t.Name)
    89  		}
    90  		fullName := t.Name
    91  		if len(parts) == 1 {
    92  			fullName = catconstants.PgCatalogName + "." + t.Name
    93  		}
    94  		fd := ResolvedBuiltinFuncDefs[fullName]
    95  		ref.FunctionReference = fd
    96  		return fd, nil
    97  	case *UnresolvedName:
    98  		if resolver == nil {
    99  			// If a resolver is not provided, just try to fetch a builtin function.
   100  			fn, err := t.ToRoutineName()
   101  			if err != nil {
   102  				return nil, err
   103  			}
   104  			fd, err := GetBuiltinFuncDefinitionOrFail(fn, path)
   105  			if err != nil {
   106  				return nil, err
   107  			}
   108  			ref.FunctionReference = fd
   109  			return fd, nil
   110  		}
   111  		// Use the resolver if it is provided.
   112  		fd, err := resolver.ResolveFunction(ctx, MakeUnresolvedFunctionName(t), path)
   113  		if err != nil {
   114  			return nil, err
   115  		}
   116  		referenceByName, _ := t.ToUnresolvedObjectName(NoAnnotation)
   117  		ref.ReferenceByName = &referenceByName
   118  		ref.FunctionReference = fd
   119  		return fd, nil
   120  	case *FunctionOID:
   121  		if resolver == nil {
   122  			return GetBuiltinFunctionByOIDOrFail(t.OID)
   123  		}
   124  		fnName, o, err := resolver.ResolveFunctionByOID(ctx, t.OID)
   125  		if err != nil {
   126  			return nil, err
   127  		}
   128  		fd := &ResolvedFunctionDefinition{
   129  			Name:      fnName.Object(),
   130  			Overloads: []QualifiedOverload{{Schema: fnName.Schema(), Overload: o}},
   131  		}
   132  		ref.FunctionReference = fd
   133  		return fd, nil
   134  	default:
   135  		return nil, errors.AssertionFailedf("unknown resolvable function reference type %s", t)
   136  	}
   137  }
   138  
   139  // WrapFunction creates a new ResolvableFunctionReference holding a pre-resolved
   140  // function from a built-in function name. Helper for grammar rules and
   141  // execbuilder.
   142  //
   143  // TODO(Chengxiong): get rid of FunctionDefinition entirely and use
   144  // ResolvedFunctionDefinition instead.
   145  func WrapFunction(n string) ResolvableFunctionReference {
   146  	fd, ok := FunDefs[n]
   147  	if !ok {
   148  		return ResolvableFunctionReference{
   149  			FunctionReference: &FunctionDefinition{
   150  				Name: n,
   151  			},
   152  		}
   153  	}
   154  	return ResolvableFunctionReference{FunctionReference: fd}
   155  }
   156  
   157  // FunctionReference is the common interface to UnresolvedName and QualifiedFunctionName.
   158  type FunctionReference interface {
   159  	fmt.Stringer
   160  	NodeFormatter
   161  	functionReference()
   162  }
   163  
   164  var _ FunctionReference = &UnresolvedName{}
   165  var _ FunctionReference = &FunctionDefinition{}
   166  var _ FunctionReference = &ResolvedFunctionDefinition{}
   167  
   168  func (*UnresolvedName) functionReference()             {}
   169  func (*FunctionDefinition) functionReference()         {}
   170  func (*ResolvedFunctionDefinition) functionReference() {}
   171  func (*FunctionOID) functionReference()                {}
   172  
   173  type FunctionOID struct {
   174  	OID oid.Oid
   175  }
   176  
   177  func (o *FunctionOID) String() string {
   178  	return AsString(o)
   179  }
   180  
   181  func (o *FunctionOID) Format(ctx *FmtCtx) {
   182  	ctx.WriteString(fmt.Sprintf("[FUNCTION %d]", o.OID))
   183  }