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