TypeCheck implements the Expr interface.
( ctx context.Context, semaCtx *SemaContext, desired *types.T, )
| 839 | |
| 840 | // TypeCheck implements the Expr interface. |
| 841 | func (expr *FuncExpr) TypeCheck( |
| 842 | ctx context.Context, semaCtx *SemaContext, desired *types.T, |
| 843 | ) (TypedExpr, error) { |
| 844 | var searchPath sessiondata.SearchPath |
| 845 | if semaCtx != nil { |
| 846 | searchPath = semaCtx.SearchPath |
| 847 | } |
| 848 | def, err := expr.Func.Resolve(searchPath) |
| 849 | if err != nil { |
| 850 | return nil, err |
| 851 | } |
| 852 | |
| 853 | if err := semaCtx.checkFunctionUsage(expr, def); err != nil { |
| 854 | return nil, pgerror.Wrapf(err, pgcode.InvalidParameterValue, |
| 855 | "%s()", def.Name) |
| 856 | } |
| 857 | if semaCtx != nil { |
| 858 | // We'll need to remember we are in a function application to |
| 859 | // generate suitable errors in checkFunctionUsage(). We cannot |
| 860 | // set ctx.inFuncExpr earlier (in particular not before the call |
| 861 | // to checkFunctionUsage() above) because the top-level FuncExpr |
| 862 | // must be acceptable even if it is a SRF and |
| 863 | // RejectNestedGenerators is set. |
| 864 | defer func(semaCtx *SemaContext, prevFunc bool, prevWindow bool) { |
| 865 | semaCtx.Properties.Derived.inFuncExpr = prevFunc |
| 866 | semaCtx.Properties.Derived.InWindowFunc = prevWindow |
| 867 | }( |
| 868 | semaCtx, |
| 869 | semaCtx.Properties.Derived.inFuncExpr, |
| 870 | semaCtx.Properties.Derived.InWindowFunc, |
| 871 | ) |
| 872 | semaCtx.Properties.Derived.inFuncExpr = true |
| 873 | if expr.WindowDef != nil { |
| 874 | semaCtx.Properties.Derived.InWindowFunc = true |
| 875 | } |
| 876 | } |
| 877 | |
| 878 | typedSubExprs, fns, err := typeCheckOverloadedExprs(ctx, semaCtx, desired, def.Definition, false, expr.Exprs...) |
| 879 | if err != nil { |
| 880 | return nil, pgerror.Wrapf(err, pgcode.InvalidParameterValue, "%s()", def.Name) |
| 881 | } |
| 882 | |
| 883 | // If the function is an aggregate that does not accept null arguments and we |
| 884 | // have arguments of unknown type, see if we can assign type string instead. |
| 885 | // TODO(rytaft): If there are no overloads with string inputs, Postgres |
| 886 | // chooses the overload with preferred type for the given category. For |
| 887 | // example, float8 is the preferred type for the numeric category in Postgres. |
| 888 | // To match Postgres' behavior, we should add that logic here too. |
| 889 | if !def.NullableArgs && def.FunctionProperties.Class == AggregateClass { |
| 890 | for i := range typedSubExprs { |
| 891 | if typedSubExprs[i].ResolvedType().Family() == types.UnknownFamily { |
| 892 | var filtered []overloadImpl |
| 893 | for j := range fns { |
| 894 | if fns[j].params().GetAt(i).Equivalent(types.String) { |
| 895 | if filtered == nil { |
| 896 | filtered = make([]overloadImpl, 0, len(fns)-j) |
| 897 | } |
| 898 | filtered = append(filtered, fns[j]) |
nothing calls this directly
no test coverage detected