TypeCheck implements the Expr interface.
( ctx context.Context, semaCtx *SemaContext, desired *types.T, )
| 583 | |
| 584 | // TypeCheck implements the Expr interface. |
| 585 | func (expr *ColumnAccessExpr) TypeCheck( |
| 586 | ctx context.Context, semaCtx *SemaContext, desired *types.T, |
| 587 | ) (TypedExpr, error) { |
| 588 | // If the context requires types T, we need to ask "Any tuple with |
| 589 | // at least this label and the element type T for this label" from |
| 590 | // the sub-expression. Of course, our type system does not support |
| 591 | // this. So drop the type constraint instead. |
| 592 | subExpr, err := expr.Expr.TypeCheck(ctx, semaCtx, types.Any) |
| 593 | if err != nil { |
| 594 | return nil, err |
| 595 | } |
| 596 | |
| 597 | expr.Expr = subExpr |
| 598 | resolvedType := subExpr.ResolvedType() |
| 599 | |
| 600 | if resolvedType.Family() != types.TupleFamily || (!expr.ByIndex && len(resolvedType.TupleLabels()) == 0) { |
| 601 | return nil, NewTypeIsNotCompositeError(resolvedType) |
| 602 | } |
| 603 | |
| 604 | if expr.ByIndex { |
| 605 | // By-index reference. Verify that the index is valid. |
| 606 | if expr.ColIndex < 0 || expr.ColIndex >= len(resolvedType.TupleContents()) { |
| 607 | return nil, pgerror.Newf(pgcode.Syntax, "tuple column %d does not exist", expr.ColIndex+1) |
| 608 | } |
| 609 | } else { |
| 610 | // Go through all of the labels to find a match. |
| 611 | expr.ColIndex = -1 |
| 612 | for i, label := range resolvedType.TupleLabels() { |
| 613 | if label == expr.ColName { |
| 614 | if expr.ColIndex != -1 { |
| 615 | // Found a duplicate label. |
| 616 | return nil, pgerror.Newf(pgcode.AmbiguousColumn, "column reference %q is ambiguous", label) |
| 617 | } |
| 618 | expr.ColIndex = i |
| 619 | } |
| 620 | } |
| 621 | if expr.ColIndex < 0 { |
| 622 | return nil, pgerror.Newf(pgcode.DatatypeMismatch, |
| 623 | "could not identify column %q in %s", |
| 624 | ErrNameStringP(&expr.ColName), resolvedType, |
| 625 | ) |
| 626 | } |
| 627 | } |
| 628 | |
| 629 | // Optimization: if the expression is actually a tuple, then |
| 630 | // simplify the tuple straight away. |
| 631 | if tExpr, ok := expr.Expr.(*Tuple); ok { |
| 632 | return tExpr.Exprs[expr.ColIndex].(TypedExpr), nil |
| 633 | } |
| 634 | |
| 635 | // Otherwise, let the expression be, it's probably more complex. |
| 636 | // Just annotate the type of the result properly. |
| 637 | expr.typ = resolvedType.TupleContents()[expr.ColIndex] |
| 638 | return expr, nil |
| 639 | } |
| 640 | |
| 641 | // TypeCheck implements the Expr interface. |
| 642 | func (expr *CoalesceExpr) TypeCheck( |
nothing calls this directly
no test coverage detected