nodeFuncExpr handles *tree.FuncExpr nodes.
(ctx *Context, node *tree.FuncExpr)
| 27 | |
| 28 | // nodeFuncExpr handles *tree.FuncExpr nodes. |
| 29 | func nodeFuncExpr(ctx *Context, node *tree.FuncExpr) (vitess.Expr, error) { |
| 30 | if node == nil { |
| 31 | return nil, nil |
| 32 | } |
| 33 | if node.Filter != nil { |
| 34 | return nil, errors.Errorf("function filters are not yet supported") |
| 35 | } |
| 36 | if node.AggType == tree.OrderedSetAgg { |
| 37 | return nil, errors.Errorf("WITHIN GROUP is not yet supported") |
| 38 | } |
| 39 | |
| 40 | var qualifier vitess.TableIdent |
| 41 | var name vitess.ColIdent |
| 42 | switch funcRef := node.Func.FunctionReference.(type) { |
| 43 | case *tree.FunctionDefinition: |
| 44 | name = vitess.NewColIdent(funcRef.Name) |
| 45 | case *tree.UnresolvedName: |
| 46 | colName, err := unresolvedNameToColName(funcRef) |
| 47 | if err != nil { |
| 48 | return nil, err |
| 49 | } |
| 50 | qualifier = colName.Qualifier.Name |
| 51 | name = colName.Name |
| 52 | default: |
| 53 | return nil, errors.Errorf("unknown function reference") |
| 54 | } |
| 55 | var distinct bool |
| 56 | switch node.Type { |
| 57 | case 0, tree.AllFuncType: |
| 58 | distinct = false |
| 59 | case tree.DistinctFuncType: |
| 60 | distinct = true |
| 61 | default: |
| 62 | return nil, errors.Errorf("unknown function spec type %d", node.Type) |
| 63 | } |
| 64 | windowDef, err := nodeWindowDef(ctx, node.WindowDef) |
| 65 | if err != nil { |
| 66 | return nil, err |
| 67 | } |
| 68 | exprs, err := nodeExprsToSelectExprs(ctx, node.Exprs) |
| 69 | if err != nil { |
| 70 | return nil, err |
| 71 | } |
| 72 | |
| 73 | switch strings.ToLower(name.String()) { |
| 74 | // special case for string_agg, which maps to the mysql aggregate function group_concat |
| 75 | case "string_agg": |
| 76 | if len(node.Exprs) != 2 { |
| 77 | return nil, errors.Errorf("string_agg requires two arguments") |
| 78 | } |
| 79 | |
| 80 | sepString := "" |
| 81 | if sep, ok := node.Exprs[1].(*tree.StrVal); ok { |
| 82 | sepString = strings.Trim(sep.String(), "'") |
| 83 | } else { |
| 84 | // TODO: need to support this function in doltgres |
| 85 | c, is := node.Exprs[1].(*tree.CastExpr) |
| 86 | if !is && c.Type.SQLString() != "TEXT" { |
no test coverage detected