improve SQL Visitor

This commit is contained in:
wenshao
2012-11-13 14:43:09 +08:00
parent 795beb3451
commit 54b83c55e9
10 changed files with 455 additions and 52 deletions
@@ -228,6 +228,8 @@ public abstract class DruidAbstractDataSource extends WrapperAdapter implements
protected AtomicLong createCount = new AtomicLong();
protected AtomicLong destroyCount = new AtomicLong();
private Boolean useUnfairLock = null;
public DruidAbstractDataSource(boolean lockFair){
lock = new ReentrantLock(lockFair);
@@ -246,6 +248,32 @@ public abstract class DruidAbstractDataSource extends WrapperAdapter implements
this.isOracle = isOracle;
}
public boolean isUseUnfairLock() {
return lock.isFair();
}
public void setUseUnfairLock(boolean useUnfairLock) {
if (lock.isFair() == !useUnfairLock) {
return;
}
if (!this.inited) {
final ReentrantLock lock = this.lock;
lock.lock();
try {
if (!this.inited) {
this.lock = new ReentrantLock(!useUnfairLock);
this.notEmpty = this.lock.newCondition();
this.empty = this.lock.newCondition();
this.useUnfairLock = useUnfairLock;
}
} finally {
lock.unlock();
}
}
}
public boolean isUseOracleImplicitCache() {
return useOracleImplicitCache;
}
@@ -794,7 +822,7 @@ public abstract class DruidAbstractDataSource extends WrapperAdapter implements
return;
}
if (maxWaitMillis > 0 && !this.inited) {
if (maxWaitMillis > 0 && useUnfairLock == null && !this.inited) {
final ReentrantLock lock = this.lock;
lock.lock();
try {
@@ -20,6 +20,7 @@ import static com.alibaba.druid.sql.parser.CharTypes.isIdentifierChar;
import static com.alibaba.druid.sql.parser.LayoutCharacters.EOI;
import static com.alibaba.druid.sql.parser.Token.LITERAL_CHARS;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
@@ -35,9 +36,9 @@ public class MySqlLexer extends Lexer {
static {
Map<String, Token> map = new HashMap<String, Token>();
map.putAll(Keywords.DEFAULT_KEYWORDS.getKeywords());
map.put("DUAL", Token.DUAL);
map.put("FALSE", Token.FALSE);
map.put("IDENTIFIED", Token.IDENTIFIED);
@@ -46,7 +47,7 @@ public class MySqlLexer extends Lexer {
map.put("LIMIT", Token.LIMIT);
map.put("TRUE", Token.TRUE);
DEFAULT_MYSQL_KEYWORDS = new Keywords(map);
}
@@ -97,28 +98,28 @@ public class MySqlLexer extends Lexer {
stringVal = subString(mark, bufPos);
token = Token.VARIANT;
} else if (charAt(pos + 1) == '{') {
++pos;
++bufPos;
char ch;
for (;;) {
ch = charAt(++pos);
if (ch == '}') {
bufPos++;
ch = charAt(++pos);
break;
} else if (ch == EOI) {
throw new SQLParseException("illegal identifier");
}
++pos;
++bufPos;
char ch;
for (;;) {
ch = charAt(++pos);
if (ch == '}') {
bufPos++;
continue;
ch = charAt(++pos);
break;
} else if (ch == EOI) {
throw new SQLParseException("illegal identifier");
}
this.ch = charAt(pos);
stringVal = subString(mark, bufPos);
token = Token.VARIANT;
bufPos++;
continue;
}
this.ch = charAt(pos);
stringVal = subString(mark, bufPos);
token = Token.VARIANT;
} else {
for (;;) {
ch = charAt(++pos);
@@ -222,9 +223,7 @@ public class MySqlLexer extends Lexer {
if (ch == '\\') {
scanChar();
if (!hasSpecial) {
if (buf == null) {
buf = new char[32];
}
initBuff(bufPos);
arraycopy(mark + 1, buf, 0, bufPos);
hasSpecial = true;
}
@@ -270,9 +269,7 @@ public class MySqlLexer extends Lexer {
token = LITERAL_CHARS;
break;
} else {
if (buf == null) {
buf = new char[32];
}
initBuff(bufPos);
arraycopy(mark + 1, buf, 0, bufPos);
hasSpecial = true;
putChar('\'');
@@ -298,7 +295,7 @@ public class MySqlLexer extends Lexer {
stringVal = new String(buf, 0, bufPos);
}
}
public void scanComment() {
if (ch != '/' && ch != '-') {
throw new IllegalStateException();
@@ -345,14 +342,14 @@ public class MySqlLexer extends Lexer {
stringVal = subString(mark, bufPos);
token = Token.MULTI_LINE_COMMENT;
}
if (token != Token.HINT && !isAllowComment()) {
throw new NotAllowCommentException();
}
return;
}
if (!isAllowComment()) {
throw new NotAllowCommentException();
}
@@ -488,7 +488,15 @@ public class MySqlOutputVisitor extends SQLASTOutputVisitor implements MySqlASTV
}
public boolean visit(SQLCharExpr x) {
print(x.toString());
print('\'');
String text = x.getText();
text = text.replaceAll("'", "''");
text = text.replaceAll("\\\\", "\\\\");
print(text);
print('\'');
return false;
}
@@ -643,6 +643,12 @@ public class OracleSelectParser extends SQLSelectParser {
if (identifierEquals("NOCYCLE")) {
hierachical.setNoCycle(true);
lexer.nextToken();
if (lexer.token() == Token.PRIOR) {
lexer.nextToken();
hierachical.setPrior(true);
}
}
hierachical.setConnectBy(this.exprParser.expr());
}
@@ -672,6 +678,12 @@ public class OracleSelectParser extends SQLSelectParser {
if (identifierEquals("NOCYCLE")) {
hierachical.setNoCycle(true);
lexer.nextToken();
if (lexer.token() == Token.PRIOR) {
lexer.nextToken();
hierachical.setPrior(true);
}
}
hierachical.setConnectBy(this.exprParser.expr());
}
@@ -84,9 +84,7 @@ public class PGLexer extends Lexer {
if (ch == '\\') {
scanChar();
if (!hasSpecial) {
if (buf == null) {
buf = new char[32];
}
initBuff(bufPos);
arraycopy(mark + 1, buf, 0, bufPos);
hasSpecial = true;
}
@@ -132,6 +130,7 @@ public class PGLexer extends Lexer {
token = LITERAL_CHARS;
break;
} else {
initBuff(bufPos);
arraycopy(mark + 1, buf, 0, bufPos);
hasSpecial = true;
putChar('\'');
@@ -34,6 +34,7 @@ import static com.alibaba.druid.sql.parser.Token.RPAREN;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.Arrays;
/**
* @author wenshao<szujobs@hotmail.com>
@@ -85,6 +86,18 @@ public class Lexer {
public final String subString(int offset, int count) {
return text.substring(offset, offset + count);
}
protected void initBuff(int size) {
if (buf == null) {
if (size < 32) {
buf = new char[32];
} else {
buf = new char[size + 32];
}
} else if(buf.length < size) {
buf = Arrays.copyOf(buf, size);
}
}
public void arraycopy(int srcPos, char[] dest, int destPos, int length) {
text.getChars(srcPos, srcPos + length, dest, destPos);
@@ -494,9 +507,7 @@ public class Lexer {
break;
} else {
if (!hasSpecial) {
if (buf == null) {
buf = new char[32];
}
initBuff(bufPos);
arraycopy(mark + 1, buf, 0, bufPos);
hasSpecial = true;
}
@@ -306,6 +306,10 @@ public class SQLSelectParser extends SQLParser {
} else if (identifierEquals("STRAIGHT_JOIN")) {
lexer.nextToken();
joinType = SQLJoinTableSource.JoinType.STRAIGHT_JOIN;
} else if (identifierEquals("CROSS")) {
lexer.nextToken();
accept(Token.JOIN);
joinType = SQLJoinTableSource.JoinType.CROSS_JOIN;
}
if (joinType != null) {
@@ -97,8 +97,9 @@ import com.alibaba.druid.sql.ast.statement.SQLUseStatement;
public class SQLASTOutputVisitor extends SQLASTVisitorAdapter {
protected final Appendable appender;
private String indent = "\t";
private int indentCount = 0;
private String indent = "\t";
private int indentCount = 0;
private boolean prettyFormat = true;
public SQLASTOutputVisitor(Appendable appender){
this.appender = appender;
@@ -112,6 +113,14 @@ public class SQLASTOutputVisitor extends SQLASTVisitorAdapter {
return appender;
}
public boolean isPrettyFormat() {
return prettyFormat;
}
public void setPrettyFormat(boolean prettyFormat) {
this.prettyFormat = prettyFormat;
}
public void decrementIndent() {
this.indentCount -= 1;
}
@@ -193,6 +202,11 @@ public class SQLASTOutputVisitor extends SQLASTVisitorAdapter {
}
public void println() {
if (!isPrettyFormat()) {
print(' ');
return;
}
print("\n");
printIndent();
}
@@ -309,6 +309,316 @@ public class SQLEvalVisitorUtils {
String result = strValue.toLowerCase();
x.putAttribute(EVAL_VALUE, result);
} else if ("mod".equalsIgnoreCase(x.getMethodName())) {
if (x.getParameters().size() != 2) {
return false;
}
SQLExpr param0 = x.getParameters().get(0);
SQLExpr param1 = x.getParameters().get(1);
param0.accept(visitor);
param1.accept(visitor);
Object param0Value = param0.getAttributes().get(EVAL_VALUE);
Object param1Value = param1.getAttributes().get(EVAL_VALUE);
if (param0Value == null || param1Value == null) {
return false;
}
int intValue0 = _int(param0Value);
int intValue1 = _int(param1Value);
int result = intValue0 % intValue1;
x.putAttribute(EVAL_VALUE, result);
} else if ("abs".equalsIgnoreCase(x.getMethodName())) {
if (x.getParameters().size() != 1) {
return false;
}
SQLExpr param0 = x.getParameters().get(0);
param0.accept(visitor);
Object paramValue = param0.getAttributes().get(EVAL_VALUE);
if (paramValue == null) {
return false;
}
Object result;
if (paramValue instanceof Integer) {
result = Math.abs(((Integer) paramValue).intValue());
} else if (paramValue instanceof Long) {
result = Math.abs(((Long) paramValue).longValue());
} else {
result = _decimal(paramValue).abs();
}
x.putAttribute(EVAL_VALUE, result);
} else if ("acos".equalsIgnoreCase(x.getMethodName())) {
if (x.getParameters().size() != 1) {
return false;
}
SQLExpr param0 = x.getParameters().get(0);
param0.accept(visitor);
Object paramValue = param0.getAttributes().get(EVAL_VALUE);
if (paramValue == null) {
return false;
}
double doubleValue = _double(paramValue);
double result = Math.acos(doubleValue);
if (Double.isNaN(result)) {
x.putAttribute(EVAL_VALUE, null);
} else {
x.putAttribute(EVAL_VALUE, result);
}
} else if ("asin".equalsIgnoreCase(x.getMethodName())) {
if (x.getParameters().size() != 1) {
return false;
}
SQLExpr param0 = x.getParameters().get(0);
param0.accept(visitor);
Object paramValue = param0.getAttributes().get(EVAL_VALUE);
if (paramValue == null) {
return false;
}
double doubleValue = _double(paramValue);
double result = Math.asin(doubleValue);
if (Double.isNaN(result)) {
x.putAttribute(EVAL_VALUE, null);
} else {
x.putAttribute(EVAL_VALUE, result);
}
} else if ("atan".equalsIgnoreCase(x.getMethodName())) {
if (x.getParameters().size() != 1) {
return false;
}
SQLExpr param0 = x.getParameters().get(0);
param0.accept(visitor);
Object paramValue = param0.getAttributes().get(EVAL_VALUE);
if (paramValue == null) {
return false;
}
double doubleValue = _double(paramValue);
double result = Math.atan(doubleValue);
if (Double.isNaN(result)) {
x.putAttribute(EVAL_VALUE, null);
} else {
x.putAttribute(EVAL_VALUE, result);
}
} else if ("atan2".equalsIgnoreCase(x.getMethodName())) {
if (x.getParameters().size() != 2) {
return false;
}
SQLExpr param0 = x.getParameters().get(0);
SQLExpr param1 = x.getParameters().get(1);
param0.accept(visitor);
param1.accept(visitor);
Object param0Value = param0.getAttributes().get(EVAL_VALUE);
Object param1Value = param1.getAttributes().get(EVAL_VALUE);
if (param0Value == null || param1Value == null) {
return false;
}
double doubleValue0 = _double(param0Value);
double doubleValue1 = _double(param1Value);
double result = Math.atan2(doubleValue0, doubleValue1);
if (Double.isNaN(result)) {
x.putAttribute(EVAL_VALUE, null);
} else {
x.putAttribute(EVAL_VALUE, result);
}
} else if ("ceil".equalsIgnoreCase(x.getMethodName()) || "ceiling".equalsIgnoreCase(x.getMethodName())) {
if (x.getParameters().size() != 1) {
return false;
}
SQLExpr param0 = x.getParameters().get(0);
param0.accept(visitor);
Object paramValue = param0.getAttributes().get(EVAL_VALUE);
if (paramValue == null) {
return false;
}
double doubleValue = _double(paramValue);
int result = (int) Math.ceil(doubleValue);
if (Double.isNaN(result)) {
x.putAttribute(EVAL_VALUE, null);
} else {
x.putAttribute(EVAL_VALUE, result);
}
} else if ("cos".equalsIgnoreCase(x.getMethodName())) {
if (x.getParameters().size() != 1) {
return false;
}
SQLExpr param0 = x.getParameters().get(0);
param0.accept(visitor);
Object paramValue = param0.getAttributes().get(EVAL_VALUE);
if (paramValue == null) {
return false;
}
double doubleValue = _double(paramValue);
int result = (int) Math.cos(doubleValue);
if (Double.isNaN(result)) {
x.putAttribute(EVAL_VALUE, null);
} else {
x.putAttribute(EVAL_VALUE, result);
}
} else if ("sin".equalsIgnoreCase(x.getMethodName())) {
if (x.getParameters().size() != 1) {
return false;
}
SQLExpr param0 = x.getParameters().get(0);
param0.accept(visitor);
Object paramValue = param0.getAttributes().get(EVAL_VALUE);
if (paramValue == null) {
return false;
}
double doubleValue = _double(paramValue);
int result = (int) Math.sin(doubleValue);
if (Double.isNaN(result)) {
x.putAttribute(EVAL_VALUE, null);
} else {
x.putAttribute(EVAL_VALUE, result);
}
} else if ("log".equalsIgnoreCase(x.getMethodName())) {
if (x.getParameters().size() != 1) {
return false;
}
SQLExpr param0 = x.getParameters().get(0);
param0.accept(visitor);
Object paramValue = param0.getAttributes().get(EVAL_VALUE);
if (paramValue == null) {
return false;
}
double doubleValue = _double(paramValue);
int result = (int) Math.log(doubleValue);
if (Double.isNaN(result)) {
x.putAttribute(EVAL_VALUE, null);
} else {
x.putAttribute(EVAL_VALUE, result);
}
} else if ("log10".equalsIgnoreCase(x.getMethodName())) {
if (x.getParameters().size() != 1) {
return false;
}
SQLExpr param0 = x.getParameters().get(0);
param0.accept(visitor);
Object paramValue = param0.getAttributes().get(EVAL_VALUE);
if (paramValue == null) {
return false;
}
double doubleValue = _double(paramValue);
int result = (int) Math.log10(doubleValue);
if (Double.isNaN(result)) {
x.putAttribute(EVAL_VALUE, null);
} else {
x.putAttribute(EVAL_VALUE, result);
}
} else if ("tan".equalsIgnoreCase(x.getMethodName())) {
if (x.getParameters().size() != 1) {
return false;
}
SQLExpr param0 = x.getParameters().get(0);
param0.accept(visitor);
Object paramValue = param0.getAttributes().get(EVAL_VALUE);
if (paramValue == null) {
return false;
}
double doubleValue = _double(paramValue);
int result = (int) Math.tan(doubleValue);
if (Double.isNaN(result)) {
x.putAttribute(EVAL_VALUE, null);
} else {
x.putAttribute(EVAL_VALUE, result);
}
} else if ("sqrt".equalsIgnoreCase(x.getMethodName())) {
if (x.getParameters().size() != 1) {
return false;
}
SQLExpr param0 = x.getParameters().get(0);
param0.accept(visitor);
Object paramValue = param0.getAttributes().get(EVAL_VALUE);
if (paramValue == null) {
return false;
}
double doubleValue = _double(paramValue);
int result = (int) Math.sqrt(doubleValue);
if (Double.isNaN(result)) {
x.putAttribute(EVAL_VALUE, null);
} else {
x.putAttribute(EVAL_VALUE, result);
}
} else if ("power".equalsIgnoreCase(x.getMethodName())) {
if (x.getParameters().size() != 2) {
return false;
}
SQLExpr param0 = x.getParameters().get(0);
SQLExpr param1 = x.getParameters().get(1);
param0.accept(visitor);
param1.accept(visitor);
Object param0Value = param0.getAttributes().get(EVAL_VALUE);
Object param1Value = param1.getAttributes().get(EVAL_VALUE);
if (param0Value == null || param1Value == null) {
return false;
}
double doubleValue0 = _double(param0Value);
double doubleValue1 = _double(param1Value);
double result = Math.pow(doubleValue0, doubleValue1);
if (Double.isNaN(result)) {
x.putAttribute(EVAL_VALUE, null);
} else {
x.putAttribute(EVAL_VALUE, result);
}
} else if ("pi".equalsIgnoreCase(x.getMethodName())) {
x.putAttribute(EVAL_VALUE, Math.PI);
} else if ("rand".equalsIgnoreCase(x.getMethodName())) {
x.putAttribute(EVAL_VALUE, Math.random());
}
return false;
}
@@ -361,14 +671,19 @@ public class SQLEvalVisitorUtils {
}
public static boolean visit(SQLEvalVisitor visitor, SQLCaseExpr x) {
x.getValueExpr().accept(visitor);
Object value;
if (x.getValueExpr() != null) {
x.getValueExpr().accept(visitor);
if (!x.getValueExpr().getAttributes().containsKey(EVAL_VALUE)) {
return false;
if (!x.getValueExpr().getAttributes().containsKey(EVAL_VALUE)) {
return false;
}
value = x.getValueExpr().getAttribute(EVAL_VALUE);
} else {
value = null;
}
Object value = x.getValueExpr().getAttribute(EVAL_VALUE);
for (SQLCaseExpr.Item item : x.getItems()) {
item.getConditionExpr().accept(visitor);
@@ -427,7 +742,7 @@ public class SQLEvalVisitorUtils {
public static boolean visit(SQLEvalVisitor visitor, SQLQueryExpr x) {
if (x.getSubQuery().getQuery() instanceof SQLSelectQueryBlock) {
SQLSelectQueryBlock queryBlock = (SQLSelectQueryBlock) x.getSubQuery().getQuery();
boolean nullFrom = false;
if (queryBlock.getFrom() == null) {
nullFrom = true;
@@ -439,7 +754,7 @@ public class SQLEvalVisitorUtils {
}
}
}
if (nullFrom) {
List<Object> row = new ArrayList<Object>(queryBlock.getSelectList().size());
for (int i = 0; i < queryBlock.getSelectList().size(); ++i) {
@@ -450,16 +765,16 @@ public class SQLEvalVisitorUtils {
}
List<List<Object>> rows = new ArrayList<List<Object>>(1);
rows.add(row);
Object result = rows;
queryBlock.putAttribute(EVAL_VALUE, result);
x.getSubQuery().putAttribute(EVAL_VALUE, result);
x.putAttribute(EVAL_VALUE, result);
return false;
}
}
return false;
}
@@ -1,3 +1,18 @@
/*
* Copyright 1999-2011 Alibaba Group Holding Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.alibaba.druid.util;
public interface JdbcConstants {