mirror of
https://github.com/alibaba/druid.git
synced 2023-03-04 19:17:16 +00:00
improved sql parser.
This commit is contained in:
@@ -2072,6 +2072,7 @@ public class DruidDataSource extends DruidAbstractDataSource implements DruidDat
|
||||
setFailContinuous(false);
|
||||
} catch (SQLException e) {
|
||||
LOG.error("create connection error, url: " + jdbcUrl, e);
|
||||
System.out.println();
|
||||
|
||||
errorCount++;
|
||||
if (errorCount > connectionErrorRetryAttempts && timeBetweenConnectErrorMillis > 0) {
|
||||
|
||||
@@ -19,19 +19,7 @@ import java.util.List;
|
||||
|
||||
import com.alibaba.druid.sql.ast.*;
|
||||
import com.alibaba.druid.sql.ast.expr.SQLIdentifierExpr;
|
||||
import com.alibaba.druid.sql.ast.statement.SQLExprTableSource;
|
||||
import com.alibaba.druid.sql.ast.statement.SQLJoinTableSource;
|
||||
import com.alibaba.druid.sql.ast.statement.SQLSelect;
|
||||
import com.alibaba.druid.sql.ast.statement.SQLSelectGroupByClause;
|
||||
import com.alibaba.druid.sql.ast.statement.SQLSelectItem;
|
||||
import com.alibaba.druid.sql.ast.statement.SQLSelectQuery;
|
||||
import com.alibaba.druid.sql.ast.statement.SQLSelectQueryBlock;
|
||||
import com.alibaba.druid.sql.ast.statement.SQLSubqueryTableSource;
|
||||
import com.alibaba.druid.sql.ast.statement.SQLTableSource;
|
||||
import com.alibaba.druid.sql.ast.statement.SQLUnionOperator;
|
||||
import com.alibaba.druid.sql.ast.statement.SQLUnionQuery;
|
||||
import com.alibaba.druid.sql.ast.statement.SQLUnionQueryTableSource;
|
||||
import com.alibaba.druid.sql.ast.statement.SQLWithSubqueryClause;
|
||||
import com.alibaba.druid.sql.ast.statement.*;
|
||||
import com.alibaba.druid.sql.dialect.mysql.ast.expr.MySqlOrderingExpr;
|
||||
import com.alibaba.druid.util.JdbcConstants;
|
||||
|
||||
@@ -579,6 +567,26 @@ public class SQLSelectParser extends SQLParser {
|
||||
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) {
|
||||
|
||||
@@ -784,6 +784,40 @@ public class SQLASTOutputVisitor extends SQLASTVisitorAdapter implements Paramet
|
||||
return printName(x, name, shardingSupport);
|
||||
}
|
||||
|
||||
public String unwrapShardingTable(String name) {
|
||||
char c0 = name.charAt(0);
|
||||
char c_last = name.charAt(name.length() - 1);
|
||||
final boolean quote = (c0 == '`' && c_last == '`') || (c0 == '"' && c_last == '"');
|
||||
|
||||
int end = name.length();
|
||||
if (quote) {
|
||||
end--;
|
||||
}
|
||||
|
||||
int num_cnt = 0, postfixed_cnt = 0;
|
||||
for (int i = end - 1; i > 0; --i, postfixed_cnt++) {
|
||||
char ch = name.charAt(i);
|
||||
if (ch >= '0' && ch <= '9') {
|
||||
num_cnt++;
|
||||
}
|
||||
|
||||
if (ch != '_' && (ch < '0' || ch > '9')) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (num_cnt < 1 || postfixed_cnt < 2) {
|
||||
return name;
|
||||
}
|
||||
|
||||
int start = end - postfixed_cnt;
|
||||
if (start < 1) {
|
||||
return name;
|
||||
}
|
||||
|
||||
String realName = name.substring(quote ? 1 : 0, start);
|
||||
return realName;
|
||||
}
|
||||
|
||||
private boolean printName(SQLName x, String name, boolean shardingSupport) {
|
||||
|
||||
if (shardingSupport) {
|
||||
@@ -796,89 +830,37 @@ public class SQLASTOutputVisitor extends SQLASTVisitorAdapter implements Paramet
|
||||
}
|
||||
|
||||
if (shardingSupport) {
|
||||
int pos = name.lastIndexOf('_');
|
||||
if (pos != -1 && pos != name.length() - 1) {
|
||||
boolean quote = name.charAt(0) == '`' && name.charAt(name.length() - 1) == '`';
|
||||
boolean isNumber = true;
|
||||
final boolean quote = name.charAt(0) == '`' && name.charAt(name.length() - 1) == '`';
|
||||
|
||||
int end = name.length();
|
||||
if (quote) {
|
||||
end--;
|
||||
}
|
||||
for (int i = pos + 1; i < end; ++i) {
|
||||
char ch = name.charAt(i);
|
||||
if (ch < '0' || ch > '9') {
|
||||
isNumber = false;
|
||||
String unwrappedName = unwrapShardingTable(name);
|
||||
if (unwrappedName != name) {
|
||||
boolean isAlias = false;
|
||||
for (SQLObject parent = x.getParent(); parent != null; parent = parent.getParent()) {
|
||||
if (parent instanceof SQLSelectQueryBlock) {
|
||||
SQLTableSource from = ((SQLSelectQueryBlock) parent).getFrom();
|
||||
if (quote) {
|
||||
String name2 = name.substring(1, name.length() - 1);
|
||||
if (isTableSourceAlias(from, name, name2)) {
|
||||
isAlias = true;
|
||||
}
|
||||
} else {
|
||||
if (isTableSourceAlias(from, name)) {
|
||||
isAlias = true;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (isNumber) {
|
||||
int pos2 = name.lastIndexOf('_', pos - 1);
|
||||
if (pos2 != -1) {
|
||||
boolean isNumber2 = true;
|
||||
for (int i = pos2 + 1; i < pos; ++i) {
|
||||
char ch = name.charAt(i);
|
||||
if (ch < '0' || ch > '9') {
|
||||
isNumber2 = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (isNumber2) {
|
||||
pos = pos2;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (isNumber) {
|
||||
boolean isAlias = false;
|
||||
for (SQLObject parent = x.getParent();parent != null; parent = parent.getParent()) {
|
||||
if (parent instanceof SQLSelectQueryBlock) {
|
||||
SQLTableSource from = ((SQLSelectQueryBlock) parent).getFrom();
|
||||
if (quote) {
|
||||
String name2 = name.substring(1, name.length() - 1);
|
||||
if (isTableSourceAlias(from, name, name2)) {
|
||||
isAlias = true;
|
||||
}
|
||||
} else {
|
||||
if (isTableSourceAlias(from, name)) {
|
||||
isAlias = true;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!isAlias) {
|
||||
int start = quote ? 1 : 0;
|
||||
String realName = name.substring(start, pos);
|
||||
print0(realName);
|
||||
incrementReplaceCunt();
|
||||
return false;
|
||||
} else {
|
||||
print0(name);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int numberCount = 0;
|
||||
for (int i = name.length() - 1; i >= 0; --i) {
|
||||
char ch = name.charAt(i);
|
||||
if (ch < '0' || ch > '9') {
|
||||
break;
|
||||
if (!isAlias) {
|
||||
print0(unwrappedName);
|
||||
incrementReplaceCunt();
|
||||
return false;
|
||||
} else {
|
||||
numberCount++;
|
||||
print0(name);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (numberCount > 1) {
|
||||
int numPos = name.length() - numberCount;
|
||||
String realName = name.substring(0, numPos);
|
||||
print0(realName);
|
||||
incrementReplaceCunt();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
print0(name);
|
||||
return false;
|
||||
@@ -2125,7 +2107,7 @@ public class SQLASTOutputVisitor extends SQLASTVisitorAdapter implements Paramet
|
||||
public boolean visit(SQLUnionQuery x) {
|
||||
SQLUnionOperator operator = x.getOperator();
|
||||
|
||||
boolean bracket = x.isBracket();
|
||||
boolean bracket = x.isBracket() && !(x.getParent() instanceof SQLUnionQueryTableSource);
|
||||
|
||||
if (bracket) {
|
||||
print('(');
|
||||
|
||||
@@ -39,9 +39,9 @@ public class LogFactory {
|
||||
}
|
||||
}
|
||||
// 优先选择log4j,而非Apache Common Logging. 因为后者无法设置真实Log调用者的信息
|
||||
tryImplementation("org.slf4j.Logger", "com.alibaba.druid.support.logging.SLF4JImpl");
|
||||
tryImplementation("org.apache.log4j.Logger", "com.alibaba.druid.support.logging.Log4jImpl");
|
||||
tryImplementation("org.apache.logging.log4j.Logger", "com.alibaba.druid.support.logging.Log4j2Impl");
|
||||
tryImplementation("org.slf4j.Logger", "com.alibaba.druid.support.logging.SLF4JImpl");
|
||||
tryImplementation("org.apache.commons.logging.LogFactory",
|
||||
"com.alibaba.druid.support.logging.JakartaCommonsLoggingImpl");
|
||||
tryImplementation("java.util.logging.Logger", "com.alibaba.druid.support.logging.Jdk14LoggingImpl");
|
||||
|
||||
Reference in New Issue
Block a user