sql eval support

This commit is contained in:
温少
2012-05-18 16:17:24 +08:00
parent a30922e660
commit a61a5c8630
6 changed files with 827 additions and 9 deletions
@@ -21,6 +21,21 @@ import com.alibaba.druid.sql.visitor.SQLASTOutputVisitor;
import com.alibaba.druid.util.JdbcUtils;
public class SQLUtils {
public static String toSQLString(SQLObject sqlObject, String dbType) {
if (JdbcUtils.MYSQL.equals(dbType)) {
return toMySqlString(sqlObject);
}
if (JdbcUtils.ORACLE.equals(dbType)) {
return toOracleString(sqlObject);
}
if (JdbcUtils.POSTGRESQL.equals(dbType)) {
return toPGString(sqlObject);
}
return toSQLServerString(sqlObject);
}
public static String toSQLString(SQLObject sqlObject) {
StringBuilder out = new StringBuilder();
@@ -75,7 +90,7 @@ public class SQLUtils {
String sql = out.toString();
return sql;
}
public static String toSQLServerString(SQLObject sqlObject) {
StringBuilder out = new StringBuilder();
sqlObject.accept(new SQLServerOutputVisitor(out));
@@ -87,7 +102,7 @@ public class SQLUtils {
public static String formatPGSql(String sql) {
return format(sql, JdbcUtils.POSTGRESQL);
}
public static SQLExpr toSQLExpr(String sql) {
Lexer lexer = new Lexer(sql);
lexer.nextToken();
@@ -101,7 +116,7 @@ public class SQLUtils {
return expr;
}
public static String format(String sql, String dbType) {
SQLStatementParser parser = SQLParserUtils.createSQLStatementParser(sql, dbType);
List<SQLStatement> statementList = parser.parseStatementList();
@@ -115,8 +130,9 @@ public class SQLUtils {
return out.toString();
}
public static SQLASTOutputVisitor createFormatOutputVisitor(Appendable out, List<SQLStatement> statementList, String dbType) {
public static SQLASTOutputVisitor createFormatOutputVisitor(Appendable out, List<SQLStatement> statementList,
String dbType) {
if (JdbcUtils.ORACLE.equals(dbType)) {
if (statementList.size() == 1) {
return new OracleOutputVisitor(out, false);
@@ -124,19 +140,24 @@ public class SQLUtils {
return new OracleOutputVisitor(out, true);
}
}
if (JdbcUtils.MYSQL.equals(dbType)) {
return new MySqlOutputVisitor(out);
}
if (JdbcUtils.POSTGRESQL.equals(dbType)) {
return new PGOutputVisitor(out);
}
if (JdbcUtils.SQL_SERVER.equals(dbType)) {
return new SQLServerOutputVisitor(out);
}
return new SQLASTOutputVisitor(out);
}
public static List<SQLStatement> parseStatements(String sql, String dbType) {
SQLStatementParser parser = SQLParserUtils.createSQLStatementParser(sql, dbType);
return parser.parseStatementList();
}
}
@@ -0,0 +1,53 @@
package com.alibaba.druid.sql.dialect.mysql.visitor;
import java.util.ArrayList;
import java.util.List;
import com.alibaba.druid.sql.ast.expr.SQLBinaryOpExpr;
import com.alibaba.druid.sql.ast.expr.SQLCharExpr;
import com.alibaba.druid.sql.ast.expr.SQLVariantRefExpr;
import com.alibaba.druid.sql.visitor.SQLEvalVisitor;
import com.alibaba.druid.sql.visitor.SQLEvalVisitorUtils;
public class MySqlEvalVisitorImpl extends MySqlASTVisitorAdapter implements SQLEvalVisitor {
private List<Object> parameters = new ArrayList<Object>();
private int variantIndex = -1;
public MySqlEvalVisitorImpl(){
this(new ArrayList<Object>(1));
}
public MySqlEvalVisitorImpl(List<Object> parameters){
this.parameters = parameters;
}
public List<Object> getParameters() {
return parameters;
}
public void setParameters(List<Object> parameters) {
this.parameters = parameters;
}
public boolean visit(SQLCharExpr x) {
return SQLEvalVisitorUtils.visit(this, x);
}
public int incrementAndGetVariantIndex() {
return ++variantIndex;
}
public int getVariantIndex() {
return variantIndex;
}
public boolean visit(SQLVariantRefExpr x) {
return SQLEvalVisitorUtils.visit(this, x);
}
public boolean visit(SQLBinaryOpExpr x) {
return SQLEvalVisitorUtils.visit(this, x);
}
}
@@ -0,0 +1,16 @@
package com.alibaba.druid.sql.visitor;
import java.util.List;
public interface SQLEvalVisitor extends SQLASTVisitor {
public static final String EVAL_VAR_INDEX = "eval.varIndex";
public static final String EVAL_VALUE = "eval.value";
List<Object> getParameters();
void setParameters(List<Object> parameters);
int incrementAndGetVariantIndex();
}
@@ -0,0 +1,51 @@
package com.alibaba.druid.sql.visitor;
import java.util.ArrayList;
import java.util.List;
import com.alibaba.druid.sql.ast.expr.SQLBinaryOpExpr;
import com.alibaba.druid.sql.ast.expr.SQLCharExpr;
import com.alibaba.druid.sql.ast.expr.SQLVariantRefExpr;
public class SQLEvalVisitorImpl extends SQLASTVisitorAdapter implements SQLEvalVisitor {
private List<Object> parameters = new ArrayList<Object>();
private int variantIndex = -1;
public SQLEvalVisitorImpl(){
this(new ArrayList<Object>(1));
}
public SQLEvalVisitorImpl(List<Object> parameters){
this.parameters = parameters;
}
public List<Object> getParameters() {
return parameters;
}
public void setParameters(List<Object> parameters) {
this.parameters = parameters;
}
public boolean visit(SQLCharExpr x) {
return SQLEvalVisitorUtils.visit(this, x);
}
public int incrementAndGetVariantIndex() {
return ++variantIndex;
}
public int getVariantIndex() {
return variantIndex;
}
public boolean visit(SQLVariantRefExpr x) {
return SQLEvalVisitorUtils.visit(this, x);
}
public boolean visit(SQLBinaryOpExpr x) {
return SQLEvalVisitorUtils.visit(this, x);
}
}
@@ -0,0 +1,657 @@
package com.alibaba.druid.sql.visitor;
import static com.alibaba.druid.sql.visitor.SQLEvalVisitor.EVAL_VALUE;
import static com.alibaba.druid.sql.visitor.SQLEvalVisitor.EVAL_VAR_INDEX;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.math.RoundingMode;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.util.Map;
import com.alibaba.druid.DruidRuntimeException;
import com.alibaba.druid.sql.SQLUtils;
import com.alibaba.druid.sql.ast.SQLExpr;
import com.alibaba.druid.sql.ast.SQLObject;
import com.alibaba.druid.sql.ast.expr.SQLBinaryOpExpr;
import com.alibaba.druid.sql.ast.expr.SQLBinaryOperator;
import com.alibaba.druid.sql.ast.expr.SQLCharExpr;
import com.alibaba.druid.sql.ast.expr.SQLVariantRefExpr;
import com.alibaba.druid.sql.dialect.mysql.visitor.MySqlEvalVisitorImpl;
import com.alibaba.druid.util.JdbcUtils;
public class SQLEvalVisitorUtils {
public static Object evalExpr(String dbType, String expr, Object... parameters) {
SQLExpr sqlExpr = SQLUtils.toSQLExpr(expr);
return eval(dbType, sqlExpr, parameters);
}
public static Object evalExpr(String dbType, String expr, List<Object> parameters) {
SQLExpr sqlExpr = SQLUtils.toSQLExpr(expr);
return eval(dbType, sqlExpr, parameters);
}
public static Object eval(String dbType, SQLObject sqlObject, Object... parameters) {
return eval(dbType, sqlObject, Arrays.asList(parameters));
}
public static Object eval(String dbType, SQLObject sqlObject, List<Object> parameters) {
SQLEvalVisitor visitor = createEvalVisitor(dbType);
visitor.setParameters(parameters);
sqlObject.accept(visitor);
Object value = sqlObject.getAttributes().get(EVAL_VALUE);
if (value == null) {
if (!sqlObject.getAttributes().containsKey(EVAL_VALUE)) {
throw new DruidRuntimeException("eval error : " + SQLUtils.toSQLString(sqlObject, dbType));
}
}
return value;
}
public static SQLEvalVisitor createEvalVisitor(String dbType) {
if (JdbcUtils.MYSQL.equals(dbType)) {
return new MySqlEvalVisitorImpl();
}
return new SQLEvalVisitorImpl();
}
public static boolean visit(SQLEvalVisitor visitor, SQLCharExpr x) {
x.putAttribute(EVAL_VALUE, x.getText());
return true;
}
public static boolean visit(SQLEvalVisitor visitor, SQLBinaryOpExpr x) {
x.getLeft().accept(visitor);
x.getRight().accept(visitor);
if (!x.getLeft().getAttributes().containsKey(EVAL_VALUE)) {
return false;
}
if (!x.getRight().getAttributes().containsKey(EVAL_VALUE)) {
return false;
}
if (SQLBinaryOperator.Add.equals(x.getOperator())) {
Object value = _add(x.getLeft().getAttribute(EVAL_VALUE), x.getRight().getAttributes().get(EVAL_VALUE));
x.putAttribute(EVAL_VALUE, value);
}
return false;
}
public static boolean visit(SQLEvalVisitor visitor, SQLVariantRefExpr x) {
Map<String, Object> attributes = x.getAttributes();
Integer varIndex = (Integer) attributes.get(EVAL_VAR_INDEX);
if (varIndex == null) {
varIndex = visitor.incrementAndGetVariantIndex();
x.putAttribute(EVAL_VAR_INDEX, varIndex);
}
boolean containsValue = attributes.containsKey(EVAL_VALUE);
if (!containsValue) {
Object value = visitor.getParameters().get(varIndex.intValue());
attributes.put(EVAL_VALUE, value);
}
return false;
}
public static Boolean _bool(Object val) {
if (val == null) {
return null;
}
if (val instanceof Boolean) {
return (Boolean) val;
}
if (val instanceof Number) {
return ((Number) val).intValue() == 1;
}
throw new IllegalArgumentException();
}
public static String _string(Object val) {
Object value = val;
if (value == null) {
return null;
}
return value.toString();
}
public static Byte _byte(Object val) {
if (val == null) {
return null;
}
if (val instanceof Byte) {
return (Byte) val;
}
return ((Number) val).byteValue();
}
public static Short _short(Object val) {
if (val == null) {
return null;
}
if (val instanceof Short) {
return (Short) val;
}
return ((Number) val).shortValue();
}
public static Integer _int(Object val) {
if (val == null) {
return null;
}
if (val instanceof Integer) {
return (Integer) val;
}
return ((Number) val).intValue();
}
public static Long _long(Object val) {
if (val == null) {
return null;
}
if (val instanceof Long) {
return (Long) val;
}
return ((Number) val).longValue();
}
public static Float _float(Object val) {
if (val == null) {
return null;
}
if (val instanceof Float) {
return (Float) val;
}
return ((Number) val).floatValue();
}
public static Double _double(Object val) {
if (val == null) {
return null;
}
if (val instanceof Double) {
return (Double) val;
}
return ((Number) val).doubleValue();
}
public static BigInteger _bigInt(Object val) {
if (val == null) {
return null;
}
if (val instanceof BigInteger) {
return (BigInteger) val;
}
if (val instanceof String) {
return new BigInteger((String) val);
}
return BigInteger.valueOf(((Number) val).longValue());
}
public static Date _date(Object val) {
if (val == null) {
return null;
}
if (val instanceof Date) {
return (Date) val;
}
if (val instanceof Number) {
return new Date(((Number) val).longValue());
}
if (val instanceof String) {
return _date((String) val);
}
throw new DruidRuntimeException("can cast to date");
}
public static Date _date(String text) {
if (text == null || text.length() == 0) {
return null;
}
String format;
if (text.length() == "yyyy-MM-dd".length()) {
format = "yyyy-MM-dd";
} else {
format = "yyyy-MM-dd HH:mm:ss";
}
try {
return new SimpleDateFormat(format).parse(text);
} catch (ParseException e) {
throw new DruidRuntimeException("format : " + format + ", value : " + text);
}
}
public static BigDecimal _decimal(Object val) {
if (val == null) {
return null;
}
if (val instanceof BigDecimal) {
return (BigDecimal) val;
}
if (val instanceof String) {
return new BigDecimal((String) val);
}
if (val instanceof Float) {
return new BigDecimal((Float) val);
}
if (val instanceof Double) {
return new BigDecimal((Double) val);
}
return BigDecimal.valueOf(((Number) val).longValue());
}
public static Object _sum(Object a, Object b) {
if (a == null) {
return b;
}
if (b == null) {
return a;
}
if (a instanceof BigDecimal || b instanceof BigDecimal) {
return _decimal(a).add(_decimal(b));
}
if (a instanceof BigInteger || b instanceof BigInteger) {
return _bigInt(a).add(_bigInt(b));
}
if (a instanceof Long || b instanceof Long) {
return _long(a) + _long(b);
}
if (a instanceof Integer || b instanceof Integer) {
return _int(a) + _int(b);
}
if (a instanceof Short || b instanceof Short) {
return _short(a) + _short(b);
}
if (a instanceof Byte || b instanceof Byte) {
return _byte(a) + _byte(b);
}
throw new IllegalArgumentException();
}
public static Object _div(Object a, Object b) {
if (a == null || b == null) {
return null;
}
BigDecimal decimalA = _decimal(a);
BigDecimal decimalB = _decimal(b);
try {
return decimalA.divide(decimalB);
} catch (ArithmeticException ex) {
return decimalA.divide(decimalB, 4, RoundingMode.CEILING);
}
}
public static Object _div2(Object a, Object b) {
if (a == null || b == null) {
return null;
}
if (a instanceof BigDecimal || b instanceof BigDecimal) {
return _decimal(a).divide(_decimal(b));
}
if (a instanceof BigInteger || b instanceof BigInteger) {
return _bigInt(a).divide(_bigInt(b));
}
if (a instanceof Long || b instanceof Long) {
return _long(a) / _long(b);
}
if (a instanceof Integer || b instanceof Integer) {
return _int(a) / _int(b);
}
if (a instanceof Short || b instanceof Short) {
return _short(a) / _short(b);
}
if (a instanceof Byte || b instanceof Byte) {
return _byte(a) / _byte(b);
}
throw new IllegalArgumentException();
}
public static boolean _gt(Object a, Object b) {
if (a == null) {
return false;
}
if (b == null) {
return true;
}
if (a instanceof BigDecimal || b instanceof BigDecimal) {
return _decimal(a).compareTo(_decimal(b)) > 0;
}
if (a instanceof BigInteger || b instanceof BigInteger) {
return _bigInt(a).compareTo(_bigInt(b)) > 0;
}
if (a instanceof Long || b instanceof Long) {
return _long(a) > _long(b);
}
if (a instanceof Integer || b instanceof Integer) {
return _int(a) > _int(b);
}
if (a instanceof Short || b instanceof Short) {
return _short(a) > _short(b);
}
if (a instanceof Byte || b instanceof Byte) {
return _byte(a) > _byte(b);
}
if (a instanceof Date || b instanceof Date) {
Date d1 = _date(a);
Date d2 = _date(b);
if (d1 == d2) {
return false;
}
if (d1 == null) {
return false;
}
if (d2 == null) {
return true;
}
return d1.compareTo(d2) > 0;
}
throw new IllegalArgumentException();
}
public static boolean _gteq(Object a, Object b) {
if (_eq(a, b)) {
return true;
}
return _gt(a, b);
}
public static boolean _lt(Object a, Object b) {
if (a == null) {
return true;
}
if (b == null) {
return false;
}
if (a instanceof BigDecimal || b instanceof BigDecimal) {
return _decimal(a).compareTo(_decimal(b)) < 0;
}
if (a instanceof BigInteger || b instanceof BigInteger) {
return _bigInt(a).compareTo(_bigInt(b)) < 0;
}
if (a instanceof Long || b instanceof Long) {
return _long(a) < _long(b);
}
if (a instanceof Integer || b instanceof Integer) {
return _int(a) < _int(b);
}
if (a instanceof Short || b instanceof Short) {
return _short(a) < _short(b);
}
if (a instanceof Byte || b instanceof Byte) {
return _byte(a) < _byte(b);
}
if (a instanceof Date || b instanceof Date) {
Date d1 = _date(a);
Date d2 = _date(b);
if (d1 == d2) {
return false;
}
if (d1 == null) {
return true;
}
if (d2 == null) {
return false;
}
return d1.compareTo(d2) < 0;
}
throw new IllegalArgumentException();
}
public static boolean _lteq(Object a, Object b) {
if (_eq(a, b)) {
return true;
}
return _lt(a, b);
}
public static boolean _eq(Object a, Object b) {
if (a == b) {
return true;
}
if (a == null || b == null) {
return false;
}
if (a.equals(b)) {
return true;
}
if (a instanceof BigDecimal || b instanceof BigDecimal) {
return _decimal(a).compareTo(_decimal(b)) == 0;
}
if (a instanceof BigInteger || b instanceof BigInteger) {
return _bigInt(a).compareTo(_bigInt(b)) == 0;
}
if (a instanceof Long || b instanceof Long) {
return _long(a) == _long(b);
}
if (a instanceof Integer || b instanceof Integer) {
return _int(a) == _int(b);
}
if (a instanceof Short || b instanceof Short) {
return _short(a) == _short(b);
}
if (a instanceof Byte || b instanceof Byte) {
return _byte(a) == _byte(b);
}
if (a instanceof Date || b instanceof Date) {
Date d1 = _date(a);
Date d2 = _date(b);
if (d1 == d2) {
return true;
}
if (d1 == null || d2 == null) {
return false;
}
return d1.equals(d2);
}
throw new IllegalArgumentException();
}
public static Object _add(Object a, Object b) {
if (a == null) {
return b;
}
if (b == null) {
return a;
}
if (a instanceof BigDecimal || b instanceof BigDecimal) {
return _decimal(a).add(_decimal(b));
}
if (a instanceof BigInteger || b instanceof BigInteger) {
return _bigInt(a).add(_bigInt(b));
}
if (a instanceof Long || b instanceof Long) {
return _long(a) + _long(b);
}
if (a instanceof Integer || b instanceof Integer) {
return _int(a) + _int(b);
}
if (a instanceof Short || b instanceof Short) {
return _short(a) + _short(b);
}
if (a instanceof Byte || b instanceof Byte) {
return _byte(a) + _byte(b);
}
if (a instanceof String || b instanceof String) {
return _string(a) + _string(b);
}
throw new IllegalArgumentException();
}
public static Object _sub(Object a, Object b) {
if (a == null) {
return null;
}
if (b == null) {
return a;
}
if (a instanceof BigDecimal || b instanceof BigDecimal) {
return _decimal(a).subtract(_decimal(b));
}
if (a instanceof BigInteger || b instanceof BigInteger) {
return _bigInt(a).subtract(_bigInt(b));
}
if (a instanceof Long || b instanceof Long) {
return _long(a) - _long(b);
}
if (a instanceof Integer || b instanceof Integer) {
return _int(a) - _int(b);
}
if (a instanceof Short || b instanceof Short) {
return _short(a) - _short(b);
}
if (a instanceof Byte || b instanceof Byte) {
return _byte(a) - _byte(b);
}
throw new IllegalArgumentException();
}
public static Object _multi(Object a, Object b) {
if (a == null || b == null) {
return null;
}
if (a instanceof BigDecimal || b instanceof BigDecimal) {
return _decimal(a).multiply(_decimal(b));
}
if (a instanceof BigInteger || b instanceof BigInteger) {
return _bigInt(a).multiply(_bigInt(b));
}
if (a instanceof Long || b instanceof Long) {
return _long(a) * _long(b);
}
if (a instanceof Integer || b instanceof Integer) {
return _int(a) * _int(b);
}
if (a instanceof Short || b instanceof Short) {
return _short(a) * _short(b);
}
if (a instanceof Byte || b instanceof Byte) {
return _byte(a) * _byte(b);
}
throw new IllegalArgumentException();
}
}