improved sql parser.

This commit is contained in:
wenshao
2017-08-13 21:05:08 +08:00
parent e693b08304
commit e1a6d99c1c
13 changed files with 566 additions and 123 deletions
@@ -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");