nodeSelectExpr handles tree.SelectExpr nodes.
(ctx *Context, node tree.SelectExpr)
| 98 | |
| 99 | // nodeSelectExpr handles tree.SelectExpr nodes. |
| 100 | func nodeSelectExpr(ctx *Context, node tree.SelectExpr) (vitess.SelectExpr, error) { |
| 101 | switch expr := node.Expr.(type) { |
| 102 | case *tree.AllColumnsSelector: |
| 103 | if expr.TableName.NumParts > 1 { |
| 104 | return nil, errors.Errorf("referencing items outside the schema or database is not yet supported") |
| 105 | } |
| 106 | return &vitess.StarExpr{ |
| 107 | TableName: vitess.TableName{ |
| 108 | Name: vitess.NewTableIdent(expr.TableName.Parts[0]), |
| 109 | }, |
| 110 | }, nil |
| 111 | case tree.UnqualifiedStar: |
| 112 | return &vitess.StarExpr{}, nil |
| 113 | case *tree.UnresolvedName: |
| 114 | colName, err := unresolvedNameToColName(expr) |
| 115 | if err != nil { |
| 116 | return nil, err |
| 117 | } |
| 118 | |
| 119 | if expr.Star { |
| 120 | return &vitess.StarExpr{ |
| 121 | TableName: colName.Qualifier, |
| 122 | }, nil |
| 123 | } |
| 124 | |
| 125 | // We don't set the InputExpression for ColName expressions. This matches the behavior in vitess's |
| 126 | // post-processing found in ast.go. Input expressions are load bearing for some parts of plan building |
| 127 | // so we need to match the behavior exactly. |
| 128 | return &vitess.AliasedExpr{ |
| 129 | Expr: colName, |
| 130 | As: vitess.NewColIdent(string(node.As)), |
| 131 | }, nil |
| 132 | default: |
| 133 | vitessExpr, err := nodeExpr(ctx, expr) |
| 134 | if err != nil { |
| 135 | return nil, err |
| 136 | } |
| 137 | |
| 138 | if ce, ok := expr.(*tree.CastExpr); ok && node.As == "" { |
| 139 | hasConst := false |
| 140 | _, _ = tree.SimpleVisit(expr, func(visitingExpr tree.Expr) (recurse bool, newExpr tree.Expr, err error) { |
| 141 | switch visitingExpr.(type) { |
| 142 | case tree.Constant: |
| 143 | hasConst = true |
| 144 | return false, visitingExpr, nil |
| 145 | } |
| 146 | return true, visitingExpr, nil |
| 147 | }) |
| 148 | if hasConst { |
| 149 | _, dt, err := nodeResolvableTypeReference(ctx, ce.Type, false) |
| 150 | if err != nil { |
| 151 | return nil, err |
| 152 | } |
| 153 | // constant value is not part of column name |
| 154 | // e.g. `1::INT2` should create column name as `int2`. |
| 155 | node.As = tree.UnrestrictedName(dt.Name()) |
| 156 | } else { |
| 157 | // cast type is not part of column name |
no test coverage detected