TypeCheck implements the Expr interface.
( ctx context.Context, semaCtx *SemaContext, desired *types.T, )
| 264 | |
| 265 | // TypeCheck implements the Expr interface. |
| 266 | func (expr *BinaryExpr) TypeCheck( |
| 267 | ctx context.Context, semaCtx *SemaContext, desired *types.T, |
| 268 | ) (TypedExpr, error) { |
| 269 | ops := BinOps[expr.Operator] |
| 270 | |
| 271 | typedSubExprs, fns, err := typeCheckOverloadedExprs(ctx, semaCtx, desired, ops, true, expr.Left, expr.Right) |
| 272 | if err != nil { |
| 273 | return nil, err |
| 274 | } |
| 275 | |
| 276 | leftTyped, rightTyped := typedSubExprs[0], typedSubExprs[1] |
| 277 | leftReturn := leftTyped.ResolvedType() |
| 278 | rightReturn := rightTyped.ResolvedType() |
| 279 | |
| 280 | // Return NULL if at least one overload is possible, NULL is an argument, |
| 281 | // and none of the overloads accept NULL. |
| 282 | if leftReturn.Family() == types.UnknownFamily || rightReturn.Family() == types.UnknownFamily { |
| 283 | if len(fns) > 0 { |
| 284 | noneAcceptNull := true |
| 285 | for _, e := range fns { |
| 286 | if e.(*BinOp).NullableArgs { |
| 287 | noneAcceptNull = false |
| 288 | break |
| 289 | } |
| 290 | } |
| 291 | if noneAcceptNull { |
| 292 | return DNull, nil |
| 293 | } |
| 294 | } |
| 295 | } |
| 296 | |
| 297 | // Throw a typing error if overload resolution found either no compatible candidates |
| 298 | // or if it found an ambiguity. |
| 299 | if len(fns) != 1 { |
| 300 | var desStr string |
| 301 | if desired.Family() != types.AnyFamily { |
| 302 | desStr = fmt.Sprintf(" (desired <%s>)", desired) |
| 303 | } |
| 304 | sig := fmt.Sprintf("<%s> %s <%s>%s", leftReturn, expr.Operator, rightReturn, desStr) |
| 305 | if len(fns) == 0 { |
| 306 | return nil, |
| 307 | pgerror.Newf(pgcode.InvalidParameterValue, unsupportedBinaryOpErrFmt, sig) |
| 308 | } |
| 309 | fnsStr := formatCandidates(expr.Operator.String(), fns) |
| 310 | err = pgerror.Newf(pgcode.AmbiguousFunction, ambiguousBinaryOpErrFmt, sig) |
| 311 | err = errors.WithHintf(err, candidatesHintFmt, fnsStr) |
| 312 | return nil, err |
| 313 | } |
| 314 | |
| 315 | binOp := fns[0].(*BinOp) |
| 316 | if err := semaCtx.checkVolatility(binOp.Volatility); err != nil { |
| 317 | return nil, pgerror.Wrapf(err, pgcode.InvalidParameterValue, "%s", expr.Operator) |
| 318 | } |
| 319 | |
| 320 | expr.Left, expr.Right = leftTyped, rightTyped |
| 321 | expr.Fn = binOp |
| 322 | expr.typ = binOp.returnType()(typedSubExprs) |
| 323 | return expr, nil |
nothing calls this directly
no test coverage detected