public SQLTableSource parseTableSourceRest()

in core/src/main/java/com/alibaba/druid/sql/parser/SQLSelectParser.java [1515:2081]


    public SQLTableSource parseTableSourceRest(SQLTableSource tableSource) {
        parseTableSourceSample(tableSource);
        if (lexer.hasComment()
                && lexer.isKeepComments()
                && !(tableSource instanceof SQLSubqueryTableSource)) {
            tableSource.addAfterComment(lexer.readAndResetComments());
        }

        if (tableSource.getAlias() == null || tableSource.getAlias().length() == 0) {
            Token token = lexer.token;
            long hash;
            switch (token) {
                case LEFT:
                case RIGHT:
                case FULL: {
                    Lexer.SavePoint mark = lexer.mark();
                    String strVal = lexer.stringVal();
                    lexer.nextToken();
                    if (lexer.token == Token.OUTER
                            || lexer.token == Token.JOIN
                            || lexer.identifierEquals(FnvHash.Constants.ANTI)
                            || lexer.identifierEquals(FnvHash.Constants.ARRAY)
                            || lexer.identifierEquals(FnvHash.Constants.SEMI)) {
                        lexer.reset(mark);
                    } else {
                        tableSource.setAlias(strVal);
                    }
                }
                break;
                case OUTER:
                    break;
                default:
                    if (identifierEquals("ARRAY")) {
                        Lexer.SavePoint mark = lexer.mark();
                        String strVal = lexer.stringVal();
                        lexer.nextToken();
                        if (lexer.token == Token.JOIN) {
                            lexer.reset(mark);
                        } else {
                            tableSource.setAlias(strVal);
                        }
                        break;
                    }
                    if (identifierEquals("PIVOT") || identifierEquals("UNPIVOT")) {
                        parsePivot(tableSource);
                    } else if (!(token == Token.IDENTIFIER
                            && ((hash = lexer.hashLCase()) == FnvHash.Constants.STRAIGHT_JOIN
                            || hash == FnvHash.Constants.CROSS))) {
                        boolean must = false;
                        if (lexer.token == Token.AS) {
                            lexer.nextToken();
                            must = true;
                        }
                        String alias = tableAlias(must);
                        if (alias != null) {
                            if (isEnabled(SQLParserFeature.IgnoreNameQuotes) && alias.length() > 1) {
                                alias = StringUtils.removeNameQuotes(alias);
                            }
                            tableSource.setAlias(alias);

                            if (lexer.token == Token.HINT) {
                                tableSource.addAfterComment("/*" + lexer.stringVal + "*/");
                                lexer.nextToken();
                            }

                            if ((tableSource instanceof SQLValuesTableSource)
                                    && ((SQLValuesTableSource) tableSource).getColumns().isEmpty()) {
                                SQLValuesTableSource values = (SQLValuesTableSource) tableSource;
                                accept(Token.LPAREN);
                                this.exprParser.names(values.getColumns(), values);
                                accept(Token.RPAREN);
                            } else if (tableSource instanceof SQLSubqueryTableSource) {
                                SQLSubqueryTableSource subQuery = (SQLSubqueryTableSource) tableSource;
                                if (lexer.token == Token.LPAREN) {
                                    lexer.nextToken();
                                    this.exprParser.names(subQuery.getColumns(), subQuery);
                                    accept(Token.RPAREN);
                                }
                            } else if (tableSource instanceof SQLUnionQueryTableSource) {
                                SQLUnionQueryTableSource union = (SQLUnionQueryTableSource) tableSource;
                                if (lexer.token == Token.LPAREN) {
                                    lexer.nextToken();
                                    this.exprParser.names(union.getColumns(), union);
                                    accept(Token.RPAREN);
                                }
                            } else if (lexer.token == Token.LPAREN
                                    && tableSource instanceof SQLExprTableSource
                                    && (((SQLExprTableSource) tableSource).getExpr() instanceof SQLVariantRefExpr
                                    || ((SQLExprTableSource) tableSource).getExpr() instanceof SQLIdentifierExpr
                            )
                            ) {
                                lexer.nextToken();
                                SQLExprTableSource exprTableSource = (SQLExprTableSource) tableSource;
                                this.exprParser.names(exprTableSource.getColumns(), exprTableSource);
                                accept(Token.RPAREN);
                            }

                            if (lexer.token == Token.WHERE) {
                                return tableSource;
                            }

                            return parseTableSourceRest(tableSource);
                        }
                    }
                    break;
            }

        } else if (identifierEquals("PIVOT") || identifierEquals("UNPIVOT")) {
            parsePivot(tableSource);
        }

        SQLJoinTableSource.JoinType joinType = null;

        boolean natural = lexer.identifierEquals(FnvHash.Constants.NATURAL);
        if (natural) {
            lexer.nextToken();
        }

        boolean asof = false;
        if (lexer.identifierEquals(FnvHash.Constants.ASOF) && dialectFeatureEnabled(AsofJoin)) {
            lexer.nextToken();
            asof = true;
        }

        if (lexer.token == Token.OUTER) {
            Lexer.SavePoint mark = lexer.mark();
            String str = lexer.stringVal();
            lexer.nextToken();
            if (tableSource.getAlias() == null &&
                    !lexer.identifierEquals(FnvHash.Constants.APPLY)) {
                tableSource.setAlias(str);
            } else {
                lexer.reset(mark);
            }
        }

        boolean global = false;
        if (dialectFeatureEnabled(GlobalJoin)) {
            if (lexer.token == Token.GLOBAL) {
                lexer.nextToken();
                global = true;
            }
        }
        if (identifierEquals("ARRAY")) {
            lexer.nextToken();
            accept(Token.JOIN);
            joinType = SQLJoinTableSource.JoinType.ARRAY_JOIN;
        }
        switch (lexer.token) {
            case LEFT:
                lexer.nextToken();

                if (lexer.identifierEquals(FnvHash.Constants.SEMI)) {
                    lexer.nextToken();
                    joinType = SQLJoinTableSource.JoinType.LEFT_SEMI_JOIN;
                } else if (lexer.identifierEquals(FnvHash.Constants.ANTI)) {
                    lexer.nextToken();
                    joinType = SQLJoinTableSource.JoinType.LEFT_ANTI_JOIN;
                } else if (lexer.identifierEquals(FnvHash.Constants.ARRAY)) {
                    lexer.nextToken();
                    joinType = SQLJoinTableSource.JoinType.LEFT_ARRAY_JOIN;
                } else if (lexer.token == Token.OUTER) {
                    lexer.nextToken();
                    joinType = natural ? SQLJoinTableSource.JoinType.NATURAL_LEFT_JOIN : SQLJoinTableSource.JoinType.LEFT_OUTER_JOIN;
                } else {
                    joinType = natural ? SQLJoinTableSource.JoinType.NATURAL_LEFT_JOIN : SQLJoinTableSource.JoinType.LEFT_OUTER_JOIN;
                }

                if (dialectFeatureEnabled(JoinAt) && lexer.token == Token.IDENTIFIER && lexer.stringVal().startsWith("join@")) {
                    lexer.stringVal = lexer.stringVal().substring(5);
                    break;
                }

                accept(Token.JOIN);
                break;
            case RIGHT:
                lexer.nextToken();
                if (lexer.token == Token.OUTER) {
                    lexer.nextToken();
                }
                accept(Token.JOIN);
                joinType = SQLJoinTableSource.JoinType.RIGHT_OUTER_JOIN;
                break;
            case FULL:
                lexer.nextToken();
                if (lexer.token == Token.OUTER) {
                    lexer.nextToken();
                }
                accept(Token.JOIN);
                joinType = SQLJoinTableSource.JoinType.FULL_OUTER_JOIN;
                break;
            case INNER:
                lexer.nextToken();
                accept(Token.JOIN);
                joinType = SQLJoinTableSource.JoinType.INNER_JOIN;
                break;
            case JOIN:
                lexer.nextIf(Token.JOIN);
                joinType = natural ? SQLJoinTableSource.JoinType.NATURAL_JOIN : SQLJoinTableSource.JoinType.JOIN;
                break;
            case COMMA:
                lexer.nextToken();
                joinType = SQLJoinTableSource.JoinType.COMMA;
                break;
            case OUTER:
                lexer.nextToken();
                if (lexer.identifierEquals(FnvHash.Constants.APPLY)) {
                    lexer.nextToken();
                    joinType = SQLJoinTableSource.JoinType.OUTER_APPLY;
                }
                break;
            case CROSS:
                lexer.nextToken();
                accept(Token.JOIN);
                joinType = natural ? SQLJoinTableSource.JoinType.NATURAL_CROSS_JOIN : SQLJoinTableSource.JoinType.CROSS_JOIN;
                break;
            case STRAIGHT_JOIN:
            case IDENTIFIER:
                final long hash = lexer.hashLCase;
                if (hash == FnvHash.Constants.STRAIGHT_JOIN) {
                    lexer.nextToken();
                    joinType = SQLJoinTableSource.JoinType.STRAIGHT_JOIN;
                } else if (hash == FnvHash.Constants.STRAIGHT) {
                    lexer.nextToken();
                    accept(Token.JOIN);
                    joinType = SQLJoinTableSource.JoinType.STRAIGHT_JOIN;
                } else if (hash == FnvHash.Constants.CROSS) {
                    lexer.nextToken();
                    if (lexer.token == Token.JOIN) {
                        lexer.nextToken();
                        joinType = natural ? SQLJoinTableSource.JoinType.NATURAL_CROSS_JOIN : SQLJoinTableSource.JoinType.CROSS_JOIN;
                    } else if (lexer.identifierEquals(FnvHash.Constants.APPLY)) {
                        lexer.nextToken();
                        joinType = SQLJoinTableSource.JoinType.CROSS_APPLY;
                    }
                }
                break;
            default:
                break;
        }

        if (joinType != null) {
            SQLJoinTableSource join = new SQLJoinTableSource();
            join.setLeft(tableSource);
            join.setJoinType(joinType);
            join.setGlobal(global);
            if (asof) {
                join.setAsof(true);
            }

            boolean isBrace = false;
            if (SQLJoinTableSource.JoinType.COMMA == joinType) {
                if (lexer.token == Token.LBRACE) {
                    lexer.nextToken();
                    acceptIdentifier("OJ");
                    isBrace = true;
                }
            }

            parseJoinHint(join);

            SQLTableSource rightTableSource = null;
            if (lexer.token == Token.LPAREN) {
                lexer.nextToken();
                if (lexer.token == Token.SELECT
                        || (lexer.token == Token.WITH && dialectFeatureEnabled(JoinRightTableWith))
                        || (lexer.token == Token.FROM && dialectFeatureEnabled(JoinRightTableFrom))) {
                    SQLSelect select = this.select();
                    rightTableSource = SQLSubqueryTableSource.fixParenthesized(new SQLSubqueryTableSource(select));
                } else {
                    rightTableSource = this.parseTableSource();
                    if (rightTableSource instanceof SQLExprTableSource) {
                        SQLExprTableSource sqlExprTableSource = (SQLExprTableSource) rightTableSource;
                        if (sqlExprTableSource.getExpr() instanceof SQLQueryExpr) {
                            SQLQueryExpr expr = (SQLQueryExpr) sqlExprTableSource.getExpr();
                            expr.setParenthesized(true);
                        }
                    }
                }
                if (lexer.token == Token.UNION
                        || lexer.token == Token.EXCEPT
                        || lexer.token == Token.MINUS
                        || lexer.token == Token.INTERSECT) {
                    if (rightTableSource instanceof SQLSubqueryTableSource) {
                        SQLSelect select = ((SQLSubqueryTableSource) rightTableSource).getSelect();
                        SQLSelectQuery query = queryRest(select.getQuery(), true);
                        select.setQuery(query);
                    } else if (rightTableSource instanceof SQLUnionQueryTableSource) {
                        SQLUnionQueryTableSource unionTableSrc = (SQLUnionQueryTableSource) rightTableSource;
                        unionTableSrc.setUnion((SQLUnionQuery)
                                queryRest(
                                        unionTableSrc.getUnion()
                                )
                        );
                    }
                }

                accept(Token.RPAREN);

                if (rightTableSource instanceof SQLValuesTableSource
                        && (lexer.token == Token.AS || lexer.token == Token.IDENTIFIER)
                        && rightTableSource.getAlias() == null
                        && ((SQLValuesTableSource) rightTableSource).getColumns().isEmpty()
                ) {
                    if (lexer.token == Token.AS) {
                        lexer.nextToken();
                    }
                    rightTableSource.setAlias(tableAlias(true));

                    if (lexer.token == Token.LPAREN) {
                        lexer.nextToken();
                        this.exprParser.names(((SQLValuesTableSource) rightTableSource).getColumns(), rightTableSource);
                        accept(Token.RPAREN);
                    }
                }
            } else {
                if (lexer.token == Token.VALUES) {
                    rightTableSource = this.parseValues();
                } else {
                    SQLTableSource unnestTableSource = parseUnnestTableSource();
                    if (unnestTableSource != null) {
                        if (lexer.identifierEquals(FnvHash.Constants.CROSS)
                                || lexer.token == Token.CROSS
                                || lexer.token == Token.LEFT
                                || lexer.token == Token.RIGHT
                                || lexer.token == Token.COMMA
                                || lexer.token == Token.INNER
                                || lexer.token == Token.JOIN
                                || lexer.token == Token.FULL
                        ) {
                            rightTableSource = unnestTableSource;
                        } else {
                            rightTableSource = parseTableSourceRest(unnestTableSource);
                        }
                    }
                }

                if (rightTableSource == null) {
                    boolean aliasToken = lexer.token == Token.LITERAL_ALIAS;
                    SQLExpr expr;
                    switch (lexer.token) {
                        case ALL:
                        case LITERAL_CHARS:
                        case LITERAL_ALIAS:
                            expr = this.exprParser.name();
                            break;
                        default:
                            expr = this.expr();
                            break;
                    }

                    if (aliasToken && expr instanceof SQLCharExpr) {
                        expr = new SQLIdentifierExpr(((SQLCharExpr) expr).getText());
                    }
                    SQLExprTableSource exprTableSource = new SQLExprTableSource(expr);

                    if (expr instanceof SQLMethodInvokeExpr && lexer.token == Token.AS) {
                        lexer.nextToken();
                        String alias = this.tableAlias(true);
                        exprTableSource.setAlias(alias);

                        if (lexer.token == Token.LPAREN) {
                            lexer.nextToken();

                            this.exprParser.names(exprTableSource.getColumns(), exprTableSource);
                            accept(Token.RPAREN);
                        }
                    }

                    rightTableSource = exprTableSource;
                }
                rightTableSource = primaryTableSourceRest(rightTableSource);
            }

            if (lexer.token == Token.USING
                    || lexer.identifierEquals(FnvHash.Constants.USING)) {
                Lexer.SavePoint savePoint = lexer.mark();
                lexer.nextToken();

                if (lexer.token == Token.LPAREN) {
                    lexer.nextToken();
                    join.setRight(rightTableSource);
                    this.exprParser.exprList(join.getUsing(), join);
                    accept(Token.RPAREN);
                } else if (lexer.token == Token.IDENTIFIER) {
                    if (JoinType.COMMA.equals(joinType)) {
                        lexer.reset(savePoint);
                        join.setRight(rightTableSource);
                        return join;
                    } else {
                        join.setRight(rightTableSource);
                        this.exprParser.exprList(join.getUsing(), join);
                        }
                } else {
                    join.setAlias(this.tableAlias());
                }
            } else if (lexer.token == Token.STRAIGHT_JOIN || lexer.identifierEquals(FnvHash.Constants.STRAIGHT_JOIN)) {
                primaryTableSourceRest(rightTableSource);

            } else if (rightTableSource.getAlias() == null && !(rightTableSource instanceof SQLValuesTableSource)) {
                int line = lexer.line;
                String tableAlias;
                if (lexer.token == Token.AS) {
                    lexer.nextToken();

                    if (lexer.token != Token.ON) {
                        if (dialectFeatureEnabled(JoinRightTableAlias) && rightTableSource instanceof SQLExprTableSource) {
                            SQLExprTableSource exprTableSource = (SQLExprTableSource) rightTableSource;
                            exprTableSource.setNeedAsTokenForAlias(true);
                        }
                        tableAlias = this.tableAlias(true);
                    } else {
                        tableAlias = null;
                    }
                } else {
                    tableAlias = this.tableAlias(false);
                }

                if (tableAlias != null) {
                    rightTableSource.setAlias(tableAlias);

                    if (line + 1 == lexer.line
                            && lexer.hasComment()
                            && lexer.getComments().get(0).startsWith("--")) {
                        rightTableSource.addAfterComment(lexer.readAndResetComments());
                    }

                    if (lexer.token == Token.LPAREN) {
                        if (rightTableSource instanceof SQLSubqueryTableSource) {
                            lexer.nextToken();
                            List<SQLName> columns = ((SQLSubqueryTableSource) rightTableSource).getColumns();
                            this.exprParser.names(columns, rightTableSource);
                            accept(Token.RPAREN);
                        } else if (rightTableSource instanceof SQLExprTableSource
                                && ((SQLExprTableSource) rightTableSource).getExpr() instanceof SQLMethodInvokeExpr) {
                            List<SQLName> columns = ((SQLExprTableSource) rightTableSource).getColumns();
                            if (columns.isEmpty()) {
                                lexer.nextToken();
                                this.exprParser.names(columns, rightTableSource);
                                accept(Token.RPAREN);
                            }
                        }
                    }
                }

                rightTableSource = primaryTableSourceRest(rightTableSource);
            }

            if (lexer.token == Token.WITH) {
                lexer.nextToken();
                accept(Token.LPAREN);

                for (; ; ) {
                    SQLExpr hintExpr = this.expr();
                    SQLExprHint hint = new SQLExprHint(hintExpr);
                    hint.setParent(tableSource);
                    rightTableSource.getHints().add(hint);
                    if (lexer.token == Token.COMMA) {
                        lexer.nextToken();
                        continue;
                    } else {
                        break;
                    }
                }

                accept(Token.RPAREN);
            }

            join.setRight(rightTableSource);

            if (!natural) {
                if (!StringUtils.isEmpty(tableSource.getAlias())
                        && tableSource.aliasHashCode64() == FnvHash.Constants.NATURAL && dialectFeatureEnabled(
                        PostNaturalJoin)) {
                    tableSource.setAlias(null);
                    natural = true;
                    if (natural && join.getJoinType() == SQLJoinTableSource.JoinType.LEFT_OUTER_JOIN) {
                        join.setJoinType(SQLJoinTableSource.JoinType.NATURAL_LEFT_JOIN);
                    }
                    if (natural && join.getJoinType() == JoinType.RIGHT_OUTER_JOIN) {
                        join.setJoinType(SQLJoinTableSource.JoinType.NATURAL_RIGHT_JOIN);
                    }
                    if (natural && join.getJoinType() == JoinType.INNER_JOIN) {
                        join.setJoinType(SQLJoinTableSource.JoinType.NATURAL_INNER_JOIN);
                    }
                }
            }
            join.setNatural(natural);

            if (lexer.token == Token.ON) {
                lexer.nextToken();
                SQLExpr joinOn = expr();
                join.setCondition(joinOn);

                while (lexer.token == Token.ON
                        && dialectFeatureEnabled(MultipleJoinOn)) {
                    lexer.nextToken();

                    SQLExpr joinOn2 = expr();
                    join.addCondition(joinOn2);
                }

                if (dialectFeatureEnabled(UDJ) && lexer.identifierEquals(FnvHash.Constants.USING)) {
                    SQLJoinTableSource.UDJ udj = new SQLJoinTableSource.UDJ();
                    lexer.nextToken();
                    udj.setFunction(this.exprParser.name());
                    accept(Token.LPAREN);
                    this.exprParser.exprList(udj.getArguments(), udj);
                    accept(Token.RPAREN);

                    if (lexer.token != Token.AS) {
                        udj.setAlias(alias());
                    }

                    accept(Token.AS);
                    accept(Token.LPAREN);
                    this.exprParser.names(udj.getColumns(), udj);
                    accept(Token.RPAREN);

                    if (lexer.identifierEquals(FnvHash.Constants.SORT)) {
                        lexer.nextToken();
                        accept(Token.BY);
                        this.exprParser.orderBy(udj.getSortBy(), udj);
                    }

                    if (lexer.token == Token.WITH) {
                        lexer.nextToken();
                        acceptIdentifier("UDFPROPERTIES");
                        this.exprParser.parseAssignItem(udj.getProperties(), udj);
                    }

                    join.setUdj(udj);
                }
            } else if (lexer.token == Token.USING
                    || lexer.identifierEquals(FnvHash.Constants.USING)) {
                Lexer.SavePoint savePoint = lexer.mark();
                lexer.nextToken();
                if (lexer.token == Token.LPAREN) {
                    lexer.nextToken();
                    this.exprParser.exprList(join.getUsing(), join);
                    accept(Token.RPAREN);
                } else {
                    lexer.reset(savePoint);
                }
            }
            SQLTableSource tableSourceReturn = parseTableSourceRest(join);

            if (isBrace) {
                accept(Token.RBRACE);
            }

            return parseTableSourceRest(tableSourceReturn);
        }

        if ((tableSource.aliasHashCode64() == FnvHash.Constants.LATERAL || lexer.token == Token.LATERAL)
                && lexer.token() == Token.VIEW) {
            return parseLateralView(tableSource);
        }

        if (lexer.identifierEquals(FnvHash.Constants.LATERAL) || lexer.token == Token.LATERAL) {
            lexer.nextToken();
            return parseLateralView(tableSource);
        }

        parseAfterTableSourceRest(tableSource);
        return tableSource;
    }