protected SQLExpr methodRest()

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());
    }