in query/sql/sql_parser.go [956:1018]
func (v *ASTBuilder) VisitFunctionCall(ctx *antlrgen.FunctionCallContext) interface{} {
v.Logger.Debugf("VisitFunctionCall: %s", ctx.GetText())
// 1. timebucket and numbericbucket are only from groupBy clause
// 2. timefilter is only from where clause
location := v.getLocation(ctx)
name := v.getText(ctx.QualifiedName())
udfDef, ok := util.UdfTable[name]
if ok {
if ctx.SetQuantifier() != nil || ctx.Filter() != nil || len(ctx.AllSortItem()) != 0 || ctx.AllExpression() == nil {
panic(fmt.Errorf("quantifier/filter/over/sort not supported in %s function at (line:%d, col:%d)",
name, location.Line, location.CharPosition))
}
if len(ctx.AllExpression()) != udfDef.ArgsNum {
panic(fmt.Errorf("%s should have %d parameters at (line:%d, col:%d)",
name, udfDef.ArgsNum, location.Line, location.CharPosition))
}
if v.hasORInPath(ctx.BaseParserRuleContext) == tree.OR {
panic(fmt.Errorf("function %s can not appear in OR logicalBinaryExpression at (line:%d, col:%d)",
name, location.Line, location.CharPosition))
}
if (udfDef.Type == util.Timebucket || udfDef.Type == util.Numericbucket) && v.SQL2AqlCtx.exprOrigin != ExprOriginGroupBy {
panic(fmt.Errorf("function %s at (line:%d, col:%d) can only appear in group by clause",
name, location.Line, location.CharPosition))
}
if udfDef.Type == util.Timefilter && v.SQL2AqlCtx.exprOrigin != ExprOriginWhere {
panic(fmt.Errorf("function %s at (line:%d, col:%d) can only appear in where clause",
name, location.Line, location.CharPosition))
}
switch udfDef.Type {
case util.Timefilter:
v.setTimefilter(ctx.AllExpression())
case util.TimeNow:
v.setTimeNow(ctx.AllExpression())
case util.Timebucket:
v.SQL2AqlCtx.MapDimensions[v.SQL2AqlCtx.mapKey] = append(
v.SQL2AqlCtx.MapDimensions[v.SQL2AqlCtx.mapKey],
queryCom.Dimension{
Expr: util.TrimQuote(v.getText(ctx.Expression(0))),
TimeBucketizer: util.TrimQuote(udfDef.Definition),
TimeUnit: util.TrimQuote(v.getText(ctx.Expression(1))),
})
if len(v.SQL2AqlCtx.timezone) == 0 {
v.SQL2AqlCtx.timezone = util.TrimQuote(v.getText(ctx.Expression(2)))
} else if v.SQL2AqlCtx.timezone != util.TrimQuote(v.getText(ctx.Expression(2))) {
panic(fmt.Errorf("different timebucket timezone %s at (line:%d, col:%d)",
v.getText(ctx.Expression(2)), location.Line, location.CharPosition))
}
case util.Numericbucket:
v.setNumericBucketizer(ctx.AllExpression(), udfDef.Definition)
}
} else if strings.HasPrefix(name, _aqlPrefix) {
panic(fmt.Errorf("function %s at (line:%d, col:%d) is not registered in AQL udf",
name, location.Line, location.CharPosition))
}
if exist := util.AggregateFunctions[name]; exist {
v.aggFuncExists = true
}
return tree.NewExpression(v.getLocation(ctx))
}