in core/src/main/java/com/alibaba/druid/sql/parser/SQLExprParser.java [1708:1976]
protected SQLExpr methodRest(SQLExpr expr, boolean acceptLPAREN) {
if (acceptLPAREN) {
accept(Token.LPAREN);
}
boolean distinct = false;
if (lexer.token == Token.DISTINCT) {
lexer.nextToken();
distinct = true;
if (lexer.token == Token.RPAREN || lexer.token == Token.COMMA) {
throw new ParserException(lexer.info());
}
}
String methodName = null;
String aggMethodName = null;
SQLMethodInvokeExpr methodInvokeExpr = null;
SQLExpr owner = null;
String trimOption = null;
long hash_lower = 0L;
if (expr instanceof SQLIdentifierExpr) {
SQLIdentifierExpr identifierExpr = (SQLIdentifierExpr) expr;
methodName = identifierExpr.getName();
hash_lower = identifierExpr.nameHashCode64();
if (allowIdentifierMethod) {
if (hash_lower == FnvHash.Constants.TRIM) {
if (lexer.identifierEquals(FnvHash.Constants.LEADING)) {
trimOption = lexer.stringVal();
lexer.nextToken();
} else if (lexer.identifierEquals(FnvHash.Constants.BOTH)) {
trimOption = lexer.stringVal();
lexer.nextToken();
} else if (lexer.identifierEquals(FnvHash.Constants.TRAILING)) {
trimOption = lexer.stringVal();
lexer.nextToken();
}
} else if (hash_lower == FnvHash.Constants.TRY_CAST) {
SQLCastExpr cast = new SQLCastExpr();
cast.setTry(true);
cast.setExpr(expr());
accept(Token.AS);
cast.setDataType(parseDataType(false));
accept(Token.RPAREN);
return cast;
} else {
SQLExpr resultExpr = methodRestAllowIdentifierMethodSpecific(methodName, hash_lower, methodInvokeExpr);
if (resultExpr != null) {
return resultExpr;
}
}
}
if (distinct) {
aggMethodName = methodName;
} else {
aggMethodName = getAggregateFunction(hash_lower);
}
} else if (expr instanceof SQLPropertyExpr) {
methodName = ((SQLPropertyExpr) expr).getSimpleName();
aggMethodName = SQLUtils.normalize(methodName);
hash_lower = FnvHash.fnv1a_64_lower(aggMethodName);
aggMethodName = getAggregateFunction(hash_lower);
owner = ((SQLPropertyExpr) expr).getOwner();
} else if (expr instanceof SQLDefaultExpr) {
methodName = "DEFAULT";
} else if (expr instanceof SQLCharExpr) {
methodName = ((SQLCharExpr) expr).getText();
if (isAggregateFunction(methodName)) {
aggMethodName = methodName;
}
} else if (expr instanceof SQLDbLinkExpr) {
SQLDbLinkExpr dbLinkExpr = (SQLDbLinkExpr) expr;
methodName = dbLinkExpr.toString();
}
if (aggMethodName != null) {
SQLAggregateExpr aggregateExpr = parseAggregateExpr(methodName);
if (distinct) {
aggregateExpr.setOption(SQLAggregateOption.DISTINCT);
}
if (lexer.token == Token.COLONCOLON) {
return primaryRest(aggregateExpr);
}
return primaryRest(aggregateExpr);
}
methodInvokeExpr = new SQLMethodInvokeExpr(methodName, hash_lower);
if (lexer.keepSourceLocation) {
int line, column;
if (lexer.keepSourceLocation) {
lexer.computeRowAndColumn();
}
if (expr instanceof SQLObjectImpl) {
line = expr.getSourceLine();
column = expr.getSourceColumn();
} else {
line = lexer.getPosLine();
column = lexer.getPosColumn();
}
methodInvokeExpr.setSource(line, column);
}
if (owner != null) {
methodInvokeExpr.setOwner(owner);
}
if (trimOption != null) {
methodInvokeExpr.setTrimOption(trimOption);
}
Token token = lexer.token;
if ("XMLSERIALIZE".equals(methodName) && lexer.identifierEquals("CONTENT")) {
SQLExpr contentExpr = expr();
methodInvokeExpr.setContent(contentExpr);
}
if ("XMLELEMENT".equals(methodName) && lexer.identifierEquals("NAME")) {
Lexer.SavePoint mark = lexer.markOut();
lexer.nextToken(); // Skip NAME if it is a keyword
if (lexer.token != Token.IDENTIFIER) {
// No other identifier name comes after NAME, so NAME itself is
// the xml element name. Reset lexer to NAME
lexer.reset(mark);
}
}
if (token != Token.RPAREN && token != Token.FROM) {
exprList(methodInvokeExpr.getArguments(), methodInvokeExpr);
if (lexer.token == Token.RPAREN) {
Lexer.SavePoint mark = lexer.mark();
lexer.nextToken();
if (lexer.token == Token.LPAREN) {
//for clickhouse parametric functions
//处理类似偏函数的语法 func(x,y)(a,b,c)
lexer.nextToken();
SQLParametricMethodInvokeExpr parametricExpr =
new SQLParametricMethodInvokeExpr(methodName, hash_lower);
methodInvokeExpr.cloneTo(parametricExpr);
methodInvokeExpr = parametricExpr;
exprList(((SQLParametricMethodInvokeExpr) methodInvokeExpr).getSecondArguments(), methodInvokeExpr);
} else {
lexer.reset(mark);
}
}
}
if (hash_lower == FnvHash.Constants.EXIST
&& methodInvokeExpr.getArguments().size() == 1
&& methodInvokeExpr.getArguments().get(0) instanceof SQLQueryExpr) {
throw new ParserException("exists syntax error.");
}
if (lexer.token == Token.FROM) {
lexer.nextToken();
SQLExpr from = this.expr();
methodInvokeExpr.setFrom(from);
if (lexer.token == Token.FOR) {
lexer.nextToken();
SQLExpr forExpr = expr();
methodInvokeExpr.setFor(forExpr);
}
}
if (lexer.token == Token.USING || lexer.identifierEquals(FnvHash.Constants.USING)) {
lexer.nextToken();
SQLExpr using;
if (lexer.token == Token.STAR) {
lexer.nextToken();
using = new SQLAllColumnExpr();
} else if (lexer.token == Token.BINARY) {
using = new SQLIdentifierExpr(lexer.stringVal());
lexer.nextToken();
} else {
using = this.primary();
}
methodInvokeExpr.setUsing(using);
}
// mysql
if (hash_lower == FnvHash.Constants.WEIGHT_STRING) {
if (lexer.token == Token.AS) {
lexer.nextToken();
SQLDataType as = this.parseDataType();
methodInvokeExpr.putAttribute("as", as);
}
if (lexer.identifierEquals(FnvHash.Constants.LEVEL)) {
lexer.nextToken();
List<SQLSelectOrderByItem> levels = new ArrayList<SQLSelectOrderByItem>();
for (; ; ) {
SQLSelectOrderByItem level = this.parseSelectOrderByItem();
levels.add(level);
if (lexer.token == Token.COMMA) {
lexer.nextToken();
continue;
}
break;
}
methodInvokeExpr.putAttribute("levels", levels);
}
if (lexer.identifierEquals(FnvHash.Constants.REVERSE)) {
lexer.nextToken();
methodInvokeExpr.putAttribute("reverse", true);
}
}
if (lexer.token == Token.AS || lexer.identifierEquals(FnvHash.Constants.AS)) {
lexer.nextToken();
final SQLExpr as = this.primary();
methodInvokeExpr.setAs(as);
}
SQLAggregateExpr aggregateExpr = null;
if (lexer.token == Token.ORDER) {
lexer.nextToken();
accept(Token.BY);
aggregateExpr = new SQLAggregateExpr(methodName);
aggregateExpr.getArguments().addAll(methodInvokeExpr.getArguments());
SQLOrderBy orderBy = new SQLOrderBy();
this.orderBy(orderBy.getItems(), orderBy);
aggregateExpr.setOrderBy(orderBy);
}
accept(Token.RPAREN);
methodRestUsing(methodInvokeExpr);
if (lexer.identifierEquals(FnvHash.Constants.FILTER)) {
if (aggregateExpr == null) {
Lexer.SavePoint mark = lexer.mark();
lexer.nextToken();
Token nextToken = lexer.token;
lexer.reset(mark);
if (nextToken == Token.LPAREN) {
aggregateExpr = new SQLAggregateExpr(methodName);
aggregateExpr.getArguments().addAll(methodInvokeExpr.getArguments());
filter(aggregateExpr);
}
} else {
filter(aggregateExpr);
}
}
if (lexer.token == Token.OVER) {
if (aggregateExpr == null) {
aggregateExpr = new SQLAggregateExpr(methodName);
aggregateExpr.addArguments(methodInvokeExpr.getArguments());
}
over(aggregateExpr);
}
if (aggregateExpr != null) {
return primaryRest(aggregateExpr);
}
if (lexer.token == Token.LPAREN) {
return methodInvokeExpr;
}
return primaryRest(methodInvokeExpr);
//throw new ParserException("not support token:" + lexer.token + ", " + lexer.info());
}