mirror of
https://github.com/alibaba/druid.git
synced 2023-03-04 19:17:16 +00:00
add merge sql stat filter
This commit is contained in:
@@ -42,6 +42,7 @@ import com.alibaba.druid.proxy.jdbc.JdbcParameter;
|
||||
import com.alibaba.druid.proxy.jdbc.PreparedStatementProxy;
|
||||
import com.alibaba.druid.proxy.jdbc.ResultSetProxy;
|
||||
import com.alibaba.druid.proxy.jdbc.StatementProxy;
|
||||
import com.alibaba.druid.sql.visitor.ParameterizedOutputVisitorUtils;
|
||||
import com.alibaba.druid.stat.JdbcConnectionStat;
|
||||
import com.alibaba.druid.stat.JdbcDataSourceStat;
|
||||
import com.alibaba.druid.stat.JdbcResultSetStat;
|
||||
@@ -77,9 +78,21 @@ public class StatFilter extends FilterEventAdapter implements StatFilterMBean {
|
||||
// 3 seconds is slow sql
|
||||
protected long slowSqlMillis = 3 * 1000;
|
||||
|
||||
private String dbType;
|
||||
|
||||
private boolean mergeSql = false;
|
||||
|
||||
public StatFilter(){
|
||||
}
|
||||
|
||||
public String getDbType() {
|
||||
return dbType;
|
||||
}
|
||||
|
||||
public void setDbType(String dbType) {
|
||||
this.dbType = dbType;
|
||||
}
|
||||
|
||||
public boolean isConnectionStackTraceEnable() {
|
||||
return connectionStackTraceEnable;
|
||||
}
|
||||
@@ -102,11 +115,67 @@ public class StatFilter extends FilterEventAdapter implements StatFilterMBean {
|
||||
return resetCount.get();
|
||||
}
|
||||
|
||||
public boolean isMergeSql() {
|
||||
return mergeSql;
|
||||
}
|
||||
|
||||
public void setMergeSql(boolean mergeSql) {
|
||||
this.mergeSql = mergeSql;
|
||||
}
|
||||
|
||||
public String mergeSql(String sql) {
|
||||
if (!mergeSql) {
|
||||
return sql;
|
||||
}
|
||||
|
||||
try {
|
||||
sql = ParameterizedOutputVisitorUtils.parameterize(sql, dbType);
|
||||
} catch (Exception e) {
|
||||
LOG.error("merge sql error", e);
|
||||
}
|
||||
|
||||
return sql;
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized void init(DataSourceProxy dataSource) {
|
||||
this.dataSource = dataSource;
|
||||
|
||||
this.dataSourceStat = dataSource.getDataSourceStat();
|
||||
|
||||
if (this.dbType == null || this.dbType.trim().length() == 0) {
|
||||
this.dbType = dataSource.getDbType();
|
||||
}
|
||||
|
||||
initFromProperties(dataSource.getConnectProperties());
|
||||
initFromProperties(System.getProperties());
|
||||
}
|
||||
|
||||
private void initFromProperties(Properties properties) {
|
||||
if (properties == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
{
|
||||
String property = properties.getProperty("druid.stat.mergeSql");
|
||||
if ("true".equals(property)) {
|
||||
this.mergeSql = true;
|
||||
} else if ("false".equals(property)) {
|
||||
this.mergeSql = false;
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
String property = properties.getProperty("druid.stat.slowSqlMillis");
|
||||
if (property != null && property.trim().length() > 0) {
|
||||
property = property.trim();
|
||||
try {
|
||||
this.slowSqlMillis = Long.parseLong(property);
|
||||
} catch (Exception e) {
|
||||
LOG.error("property 'druid.stat.slowSqlMillis' format error");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -86,6 +86,8 @@ public class MultiDataSource extends DataSourceAdapter implements MultiDataSourc
|
||||
|
||||
private JdbcDataSourceStat dataSourceStat;
|
||||
|
||||
protected Properties connectionProperties = new Properties();
|
||||
|
||||
public long getMaxWaitMillis() {
|
||||
return maxWaitMillis;
|
||||
}
|
||||
@@ -171,7 +173,7 @@ public class MultiDataSource extends DataSourceAdapter implements MultiDataSourc
|
||||
if (inited) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
dataSourceStat = new JdbcDataSourceStat(name, null);
|
||||
|
||||
this.balancer.init(this);
|
||||
@@ -501,4 +503,10 @@ public class MultiDataSource extends DataSourceAdapter implements MultiDataSourc
|
||||
public JdbcDataSourceStat getDataSourceStat() {
|
||||
return dataSourceStat;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Properties getConnectProperties() {
|
||||
return connectionProperties;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -17,6 +17,7 @@ package com.alibaba.druid.proxy.jdbc;
|
||||
|
||||
import java.sql.Driver;
|
||||
import java.util.List;
|
||||
import java.util.Properties;
|
||||
|
||||
import com.alibaba.druid.filter.Filter;
|
||||
import com.alibaba.druid.stat.JdbcDataSourceStat;
|
||||
@@ -25,6 +26,7 @@ import com.alibaba.druid.stat.JdbcDataSourceStat;
|
||||
* @author wenshao<szujobs@hotmail.com>
|
||||
*/
|
||||
public interface DataSourceProxy {
|
||||
|
||||
JdbcDataSourceStat getDataSourceStat();
|
||||
|
||||
String getName();
|
||||
@@ -46,4 +48,6 @@ public interface DataSourceProxy {
|
||||
long createResultSetId();
|
||||
|
||||
long createTransactionId();
|
||||
|
||||
Properties getConnectProperties();
|
||||
}
|
||||
|
||||
@@ -183,6 +183,10 @@ public class DataSourceProxyImpl implements DataSourceProxy, DataSourceProxyImpl
|
||||
return properties.toString();
|
||||
}
|
||||
|
||||
public Properties getConnectProperties() {
|
||||
return properties;
|
||||
}
|
||||
|
||||
public CompositeDataSupport getCompositeData() throws JMException {
|
||||
StatFilter statFilter = null;
|
||||
JdbcDataSourceStat stat = null;
|
||||
|
||||
+10
-119
@@ -1,40 +1,31 @@
|
||||
package com.alibaba.druid.sql.dialect.mysql.visitor;
|
||||
|
||||
import com.alibaba.druid.sql.ast.SQLExpr;
|
||||
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.SQLInListExpr;
|
||||
import com.alibaba.druid.sql.ast.expr.SQLIntegerExpr;
|
||||
import com.alibaba.druid.sql.ast.expr.SQLLiteralExpr;
|
||||
import com.alibaba.druid.sql.ast.expr.SQLNCharExpr;
|
||||
import com.alibaba.druid.sql.ast.expr.SQLNullExpr;
|
||||
import com.alibaba.druid.sql.ast.expr.SQLNumberExpr;
|
||||
import com.alibaba.druid.sql.ast.expr.SQLVariantRefExpr;
|
||||
import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlInsertStatement;
|
||||
import com.alibaba.druid.sql.visitor.ParameterizedOutputVisitorUtils;
|
||||
|
||||
public class MySqlParameterizedOutputVisitor extends MySqlOutputVisitor {
|
||||
|
||||
private static final String ATTR_PARAMS_SKIP = "_params.skip_";
|
||||
public MySqlParameterizedOutputVisitor() {
|
||||
this(new StringBuilder());
|
||||
}
|
||||
|
||||
public MySqlParameterizedOutputVisitor(Appendable appender){
|
||||
super(appender);
|
||||
}
|
||||
|
||||
public boolean visit(SQLInListExpr x) {
|
||||
x.getExpr().accept(this);
|
||||
|
||||
if (x.isNot()) {
|
||||
print(" NOT IN (?)");
|
||||
} else {
|
||||
print(" IN (?)");
|
||||
}
|
||||
|
||||
return false;
|
||||
return ParameterizedOutputVisitorUtils.visit(this, x);
|
||||
}
|
||||
|
||||
public boolean visit(SQLBinaryOpExpr x) {
|
||||
x = merge(x);
|
||||
x = ParameterizedOutputVisitorUtils.merge(x);
|
||||
|
||||
return super.visit(x);
|
||||
}
|
||||
@@ -44,108 +35,8 @@ public class MySqlParameterizedOutputVisitor extends MySqlOutputVisitor {
|
||||
return false;
|
||||
}
|
||||
|
||||
public SQLBinaryOpExpr merge(SQLBinaryOpExpr x) {
|
||||
if (x.getLeft() instanceof SQLLiteralExpr && x.getRight() instanceof SQLLiteralExpr) {
|
||||
if (x.getOperator() == SQLBinaryOperator.Equality || x.getOperator() == SQLBinaryOperator.NotEqual) {
|
||||
x.getLeft().getAttributes().put(ATTR_PARAMS_SKIP, true);
|
||||
x.getRight().getAttributes().put(ATTR_PARAMS_SKIP, true);
|
||||
}
|
||||
return x;
|
||||
}
|
||||
|
||||
if (x.getRight() instanceof SQLLiteralExpr) {
|
||||
x = new SQLBinaryOpExpr(x.getLeft(), x.getOperator(), new SQLVariantRefExpr("?"));
|
||||
}
|
||||
|
||||
if (x.getLeft() instanceof SQLLiteralExpr) {
|
||||
x = new SQLBinaryOpExpr(new SQLVariantRefExpr("?"), x.getOperator(), x.getRight());
|
||||
}
|
||||
|
||||
for (;;) {
|
||||
if (x.getRight() instanceof SQLBinaryOpExpr) {
|
||||
if (x.getLeft() instanceof SQLBinaryOpExpr) {
|
||||
SQLBinaryOpExpr leftBinaryExpr = (SQLBinaryOpExpr) x.getLeft();
|
||||
if (leftBinaryExpr.getRight().equals(x.getRight())) {
|
||||
x = leftBinaryExpr;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
x = new SQLBinaryOpExpr(x.getLeft(), x.getOperator(), merge((SQLBinaryOpExpr) x.getRight()));
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
if (x.getLeft() instanceof SQLBinaryOpExpr) {
|
||||
x = new SQLBinaryOpExpr(merge((SQLBinaryOpExpr) x.getLeft()), x.getOperator(), x.getRight());
|
||||
}
|
||||
|
||||
// ID = ? OR ID = ? => ID = ?
|
||||
if (x.getOperator() == SQLBinaryOperator.BooleanOr) {
|
||||
if ((x.getLeft() instanceof SQLBinaryOpExpr) && (x.getRight() instanceof SQLBinaryOpExpr)) {
|
||||
SQLBinaryOpExpr left = (SQLBinaryOpExpr) x.getLeft();
|
||||
SQLBinaryOpExpr right = (SQLBinaryOpExpr) x.getRight();
|
||||
|
||||
if (mergeEqual(left, right)) {
|
||||
return left;
|
||||
}
|
||||
|
||||
if (isLiteralExpr(left.getLeft()) && left.getOperator() == SQLBinaryOperator.BooleanOr) {
|
||||
if (mergeEqual(left.getRight(), right)) {
|
||||
return left;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return x;
|
||||
}
|
||||
|
||||
private boolean mergeEqual(SQLExpr a, SQLExpr b) {
|
||||
if (!(a instanceof SQLBinaryOpExpr)) {
|
||||
return false;
|
||||
}
|
||||
if (!(b instanceof SQLBinaryOpExpr)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
SQLBinaryOpExpr binaryA = (SQLBinaryOpExpr) a;
|
||||
SQLBinaryOpExpr binaryB = (SQLBinaryOpExpr) b;
|
||||
|
||||
if (binaryA.getOperator() != SQLBinaryOperator.Equality) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (binaryB.getOperator() != SQLBinaryOperator.Equality) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!(binaryA.getRight() instanceof SQLLiteralExpr || binaryA.getRight() instanceof SQLVariantRefExpr)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!(binaryB.getRight() instanceof SQLLiteralExpr || binaryB.getRight() instanceof SQLVariantRefExpr)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return binaryA.getLeft().toString().equals(binaryB.getLeft().toString());
|
||||
}
|
||||
|
||||
private boolean isLiteralExpr(SQLExpr expr) {
|
||||
if (expr instanceof SQLLiteralExpr) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (expr instanceof SQLBinaryOpExpr) {
|
||||
SQLBinaryOpExpr binary = (SQLBinaryOpExpr) expr;
|
||||
return isLiteralExpr(binary.getLeft()) && isLiteralExpr(binary.getRight());
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean visit(SQLIntegerExpr x) {
|
||||
if (Boolean.TRUE.equals(x.getAttribute(ATTR_PARAMS_SKIP))) {
|
||||
if (Boolean.TRUE.equals(x.getAttribute(ParameterizedOutputVisitorUtils.ATTR_PARAMS_SKIP))) {
|
||||
return super.visit(x);
|
||||
}
|
||||
|
||||
@@ -154,7 +45,7 @@ public class MySqlParameterizedOutputVisitor extends MySqlOutputVisitor {
|
||||
}
|
||||
|
||||
public boolean visit(SQLNumberExpr x) {
|
||||
if (Boolean.TRUE.equals(x.getAttribute(ATTR_PARAMS_SKIP))) {
|
||||
if (Boolean.TRUE.equals(x.getAttribute(ParameterizedOutputVisitorUtils.ATTR_PARAMS_SKIP))) {
|
||||
return super.visit(x);
|
||||
}
|
||||
|
||||
@@ -163,7 +54,7 @@ public class MySqlParameterizedOutputVisitor extends MySqlOutputVisitor {
|
||||
}
|
||||
|
||||
public boolean visit(SQLCharExpr x) {
|
||||
if (Boolean.TRUE.equals(x.getAttribute(ATTR_PARAMS_SKIP))) {
|
||||
if (Boolean.TRUE.equals(x.getAttribute(ParameterizedOutputVisitorUtils.ATTR_PARAMS_SKIP))) {
|
||||
return super.visit(x);
|
||||
}
|
||||
|
||||
@@ -172,7 +63,7 @@ public class MySqlParameterizedOutputVisitor extends MySqlOutputVisitor {
|
||||
}
|
||||
|
||||
public boolean visit(SQLNCharExpr x) {
|
||||
if (Boolean.TRUE.equals(x.getAttribute(ATTR_PARAMS_SKIP))) {
|
||||
if (Boolean.TRUE.equals(x.getAttribute(ParameterizedOutputVisitorUtils.ATTR_PARAMS_SKIP))) {
|
||||
return super.visit(x);
|
||||
}
|
||||
|
||||
|
||||
+10
-119
@@ -1,20 +1,19 @@
|
||||
package com.alibaba.druid.sql.dialect.oracle.visitor;
|
||||
|
||||
import com.alibaba.druid.sql.ast.SQLExpr;
|
||||
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.SQLInListExpr;
|
||||
import com.alibaba.druid.sql.ast.expr.SQLIntegerExpr;
|
||||
import com.alibaba.druid.sql.ast.expr.SQLLiteralExpr;
|
||||
import com.alibaba.druid.sql.ast.expr.SQLNCharExpr;
|
||||
import com.alibaba.druid.sql.ast.expr.SQLNullExpr;
|
||||
import com.alibaba.druid.sql.ast.expr.SQLNumberExpr;
|
||||
import com.alibaba.druid.sql.ast.expr.SQLVariantRefExpr;
|
||||
import com.alibaba.druid.sql.visitor.ParameterizedOutputVisitorUtils;
|
||||
|
||||
public class OracleParameterizedOutputVisitor extends OracleOutputVisitor {
|
||||
|
||||
private static final String ATTR_PARAMS_SKIP = "_params.skip_";
|
||||
public OracleParameterizedOutputVisitor() {
|
||||
this (new StringBuilder());
|
||||
}
|
||||
|
||||
public OracleParameterizedOutputVisitor(Appendable appender){
|
||||
super(appender);
|
||||
@@ -25,19 +24,11 @@ public class OracleParameterizedOutputVisitor extends OracleOutputVisitor {
|
||||
}
|
||||
|
||||
public boolean visit(SQLInListExpr x) {
|
||||
x.getExpr().accept(this);
|
||||
|
||||
if (x.isNot()) {
|
||||
print(" NOT IN (?)");
|
||||
} else {
|
||||
print(" IN (?)");
|
||||
}
|
||||
|
||||
return false;
|
||||
return ParameterizedOutputVisitorUtils.visit(this, x);
|
||||
}
|
||||
|
||||
public boolean visit(SQLBinaryOpExpr x) {
|
||||
x = merge(x);
|
||||
x = ParameterizedOutputVisitorUtils.merge(x);
|
||||
|
||||
return super.visit(x);
|
||||
}
|
||||
@@ -47,108 +38,8 @@ public class OracleParameterizedOutputVisitor extends OracleOutputVisitor {
|
||||
return false;
|
||||
}
|
||||
|
||||
public SQLBinaryOpExpr merge(SQLBinaryOpExpr x) {
|
||||
if (x.getLeft() instanceof SQLLiteralExpr && x.getRight() instanceof SQLLiteralExpr) {
|
||||
if (x.getOperator() == SQLBinaryOperator.Equality || x.getOperator() == SQLBinaryOperator.NotEqual) {
|
||||
x.getLeft().getAttributes().put(ATTR_PARAMS_SKIP, true);
|
||||
x.getRight().getAttributes().put(ATTR_PARAMS_SKIP, true);
|
||||
}
|
||||
return x;
|
||||
}
|
||||
|
||||
if (x.getRight() instanceof SQLLiteralExpr) {
|
||||
x = new SQLBinaryOpExpr(x.getLeft(), x.getOperator(), new SQLVariantRefExpr("?"));
|
||||
}
|
||||
|
||||
if (x.getLeft() instanceof SQLLiteralExpr) {
|
||||
x = new SQLBinaryOpExpr(new SQLVariantRefExpr("?"), x.getOperator(), x.getRight());
|
||||
}
|
||||
|
||||
for (;;) {
|
||||
if (x.getRight() instanceof SQLBinaryOpExpr) {
|
||||
if (x.getLeft() instanceof SQLBinaryOpExpr) {
|
||||
SQLBinaryOpExpr leftBinaryExpr = (SQLBinaryOpExpr) x.getLeft();
|
||||
if (leftBinaryExpr.getRight().equals(x.getRight())) {
|
||||
x = leftBinaryExpr;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
x = new SQLBinaryOpExpr(x.getLeft(), x.getOperator(), merge((SQLBinaryOpExpr) x.getRight()));
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
if (x.getLeft() instanceof SQLBinaryOpExpr) {
|
||||
x = new SQLBinaryOpExpr(merge((SQLBinaryOpExpr) x.getLeft()), x.getOperator(), x.getRight());
|
||||
}
|
||||
|
||||
// ID = ? OR ID = ? => ID = ?
|
||||
if (x.getOperator() == SQLBinaryOperator.BooleanOr) {
|
||||
if ((x.getLeft() instanceof SQLBinaryOpExpr) && (x.getRight() instanceof SQLBinaryOpExpr)) {
|
||||
SQLBinaryOpExpr left = (SQLBinaryOpExpr) x.getLeft();
|
||||
SQLBinaryOpExpr right = (SQLBinaryOpExpr) x.getRight();
|
||||
|
||||
if (mergeEqual(left, right)) {
|
||||
return left;
|
||||
}
|
||||
|
||||
if (isLiteralExpr(left.getLeft()) && left.getOperator() == SQLBinaryOperator.BooleanOr) {
|
||||
if (mergeEqual(left.getRight(), right)) {
|
||||
return left;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return x;
|
||||
}
|
||||
|
||||
private boolean mergeEqual(SQLExpr a, SQLExpr b) {
|
||||
if (!(a instanceof SQLBinaryOpExpr)) {
|
||||
return false;
|
||||
}
|
||||
if (!(b instanceof SQLBinaryOpExpr)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
SQLBinaryOpExpr binaryA = (SQLBinaryOpExpr) a;
|
||||
SQLBinaryOpExpr binaryB = (SQLBinaryOpExpr) b;
|
||||
|
||||
if (binaryA.getOperator() != SQLBinaryOperator.Equality) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (binaryB.getOperator() != SQLBinaryOperator.Equality) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!(binaryA.getRight() instanceof SQLLiteralExpr || binaryA.getRight() instanceof SQLVariantRefExpr)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!(binaryB.getRight() instanceof SQLLiteralExpr || binaryB.getRight() instanceof SQLVariantRefExpr)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return binaryA.getLeft().toString().equals(binaryB.getLeft().toString());
|
||||
}
|
||||
|
||||
private boolean isLiteralExpr(SQLExpr expr) {
|
||||
if (expr instanceof SQLLiteralExpr) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (expr instanceof SQLBinaryOpExpr) {
|
||||
SQLBinaryOpExpr binary = (SQLBinaryOpExpr) expr;
|
||||
return isLiteralExpr(binary.getLeft()) && isLiteralExpr(binary.getRight());
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean visit(SQLIntegerExpr x) {
|
||||
if (Boolean.TRUE.equals(x.getAttribute(ATTR_PARAMS_SKIP))) {
|
||||
if (Boolean.TRUE.equals(x.getAttribute(ParameterizedOutputVisitorUtils.ATTR_PARAMS_SKIP))) {
|
||||
return super.visit(x);
|
||||
}
|
||||
|
||||
@@ -157,7 +48,7 @@ public class OracleParameterizedOutputVisitor extends OracleOutputVisitor {
|
||||
}
|
||||
|
||||
public boolean visit(SQLNumberExpr x) {
|
||||
if (Boolean.TRUE.equals(x.getAttribute(ATTR_PARAMS_SKIP))) {
|
||||
if (Boolean.TRUE.equals(x.getAttribute(ParameterizedOutputVisitorUtils.ATTR_PARAMS_SKIP))) {
|
||||
return super.visit(x);
|
||||
}
|
||||
|
||||
@@ -166,7 +57,7 @@ public class OracleParameterizedOutputVisitor extends OracleOutputVisitor {
|
||||
}
|
||||
|
||||
public boolean visit(SQLCharExpr x) {
|
||||
if (Boolean.TRUE.equals(x.getAttribute(ATTR_PARAMS_SKIP))) {
|
||||
if (Boolean.TRUE.equals(x.getAttribute(ParameterizedOutputVisitorUtils.ATTR_PARAMS_SKIP))) {
|
||||
return super.visit(x);
|
||||
}
|
||||
|
||||
@@ -175,7 +66,7 @@ public class OracleParameterizedOutputVisitor extends OracleOutputVisitor {
|
||||
}
|
||||
|
||||
public boolean visit(SQLNCharExpr x) {
|
||||
if (Boolean.TRUE.equals(x.getAttribute(ATTR_PARAMS_SKIP))) {
|
||||
if (Boolean.TRUE.equals(x.getAttribute(ParameterizedOutputVisitorUtils.ATTR_PARAMS_SKIP))) {
|
||||
return super.visit(x);
|
||||
}
|
||||
|
||||
|
||||
+72
@@ -0,0 +1,72 @@
|
||||
package com.alibaba.druid.sql.dialect.postgresql.visitor;
|
||||
|
||||
import com.alibaba.druid.sql.ast.expr.SQLBinaryOpExpr;
|
||||
import com.alibaba.druid.sql.ast.expr.SQLCharExpr;
|
||||
import com.alibaba.druid.sql.ast.expr.SQLInListExpr;
|
||||
import com.alibaba.druid.sql.ast.expr.SQLIntegerExpr;
|
||||
import com.alibaba.druid.sql.ast.expr.SQLNCharExpr;
|
||||
import com.alibaba.druid.sql.ast.expr.SQLNullExpr;
|
||||
import com.alibaba.druid.sql.ast.expr.SQLNumberExpr;
|
||||
import com.alibaba.druid.sql.visitor.ParameterizedOutputVisitorUtils;
|
||||
|
||||
public class PGParameterizedOutputVisitor extends PGOutputVisitor {
|
||||
public PGParameterizedOutputVisitor() {
|
||||
this (new StringBuilder());
|
||||
}
|
||||
|
||||
public PGParameterizedOutputVisitor(Appendable appender){
|
||||
super(appender);
|
||||
}
|
||||
|
||||
public boolean visit(SQLInListExpr x) {
|
||||
return ParameterizedOutputVisitorUtils.visit(this, x);
|
||||
}
|
||||
|
||||
public boolean visit(SQLBinaryOpExpr x) {
|
||||
x = ParameterizedOutputVisitorUtils.merge(x);
|
||||
|
||||
return super.visit(x);
|
||||
}
|
||||
|
||||
public boolean visit(SQLNullExpr x) {
|
||||
print('?');
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean visit(SQLIntegerExpr x) {
|
||||
if (Boolean.TRUE.equals(x.getAttribute(ParameterizedOutputVisitorUtils.ATTR_PARAMS_SKIP))) {
|
||||
return super.visit(x);
|
||||
}
|
||||
|
||||
print('?');
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean visit(SQLNumberExpr x) {
|
||||
if (Boolean.TRUE.equals(x.getAttribute(ParameterizedOutputVisitorUtils.ATTR_PARAMS_SKIP))) {
|
||||
return super.visit(x);
|
||||
}
|
||||
|
||||
print('?');
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean visit(SQLCharExpr x) {
|
||||
if (Boolean.TRUE.equals(x.getAttribute(ParameterizedOutputVisitorUtils.ATTR_PARAMS_SKIP))) {
|
||||
return super.visit(x);
|
||||
}
|
||||
|
||||
print('?');
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean visit(SQLNCharExpr x) {
|
||||
if (Boolean.TRUE.equals(x.getAttribute(ParameterizedOutputVisitorUtils.ATTR_PARAMS_SKIP))) {
|
||||
return super.visit(x);
|
||||
}
|
||||
|
||||
print('?');
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
package com.alibaba.druid.sql.parser;
|
||||
|
||||
import com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser;
|
||||
import com.alibaba.druid.sql.dialect.oracle.parser.OracleStatementParser;
|
||||
import com.alibaba.druid.sql.dialect.postgresql.parser.PGSQLStatementParser;
|
||||
import com.alibaba.druid.sql.dialect.sqlserver.parser.SQLServerStatementParser;
|
||||
import com.alibaba.druid.util.JdbcUtils;
|
||||
|
||||
|
||||
public class SQLParserUtils {
|
||||
public static SQLStatementParser createSQLStatementParser(String sql, String dbType) {
|
||||
if (JdbcUtils.ORACLE.equals(dbType)) {
|
||||
return new OracleStatementParser(sql);
|
||||
}
|
||||
|
||||
if (JdbcUtils.MYSQL.equals(dbType)) {
|
||||
return new MySqlStatementParser(sql);
|
||||
}
|
||||
|
||||
if (JdbcUtils.POSTGRESQL.equals(dbType)) {
|
||||
return new PGSQLStatementParser(sql);
|
||||
}
|
||||
|
||||
if (JdbcUtils.SQL_SERVER.equals(dbType)) {
|
||||
return new SQLServerStatementParser(sql);
|
||||
}
|
||||
|
||||
return new SQLStatementParser(sql);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,70 @@
|
||||
package com.alibaba.druid.sql.visitor;
|
||||
|
||||
import com.alibaba.druid.sql.ast.expr.SQLBinaryOpExpr;
|
||||
import com.alibaba.druid.sql.ast.expr.SQLCharExpr;
|
||||
import com.alibaba.druid.sql.ast.expr.SQLInListExpr;
|
||||
import com.alibaba.druid.sql.ast.expr.SQLIntegerExpr;
|
||||
import com.alibaba.druid.sql.ast.expr.SQLNCharExpr;
|
||||
import com.alibaba.druid.sql.ast.expr.SQLNullExpr;
|
||||
import com.alibaba.druid.sql.ast.expr.SQLNumberExpr;
|
||||
|
||||
public class ParameterizedOutputVisitor extends SQLASTOutputVisitor {
|
||||
public ParameterizedOutputVisitor() {
|
||||
this (new StringBuilder());
|
||||
}
|
||||
|
||||
public ParameterizedOutputVisitor(Appendable appender){
|
||||
super(appender);
|
||||
}
|
||||
|
||||
public boolean visit(SQLInListExpr x) {
|
||||
return ParameterizedOutputVisitorUtils.visit(this, x);
|
||||
}
|
||||
|
||||
public boolean visit(SQLBinaryOpExpr x) {
|
||||
x = ParameterizedOutputVisitorUtils.merge(x);
|
||||
|
||||
return super.visit(x);
|
||||
}
|
||||
|
||||
public boolean visit(SQLNullExpr x) {
|
||||
print('?');
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean visit(SQLIntegerExpr x) {
|
||||
if (Boolean.TRUE.equals(x.getAttribute(ParameterizedOutputVisitorUtils.ATTR_PARAMS_SKIP))) {
|
||||
return super.visit(x);
|
||||
}
|
||||
|
||||
print('?');
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean visit(SQLNumberExpr x) {
|
||||
if (Boolean.TRUE.equals(x.getAttribute(ParameterizedOutputVisitorUtils.ATTR_PARAMS_SKIP))) {
|
||||
return super.visit(x);
|
||||
}
|
||||
|
||||
print('?');
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean visit(SQLCharExpr x) {
|
||||
if (Boolean.TRUE.equals(x.getAttribute(ParameterizedOutputVisitorUtils.ATTR_PARAMS_SKIP))) {
|
||||
return super.visit(x);
|
||||
}
|
||||
|
||||
print('?');
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean visit(SQLNCharExpr x) {
|
||||
if (Boolean.TRUE.equals(x.getAttribute(ParameterizedOutputVisitorUtils.ATTR_PARAMS_SKIP))) {
|
||||
return super.visit(x);
|
||||
}
|
||||
|
||||
print('?');
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,166 @@
|
||||
package com.alibaba.druid.sql.visitor;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import junit.framework.Assert;
|
||||
|
||||
import com.alibaba.druid.sql.ast.SQLExpr;
|
||||
import com.alibaba.druid.sql.ast.SQLStatement;
|
||||
import com.alibaba.druid.sql.ast.expr.SQLBinaryOpExpr;
|
||||
import com.alibaba.druid.sql.ast.expr.SQLBinaryOperator;
|
||||
import com.alibaba.druid.sql.ast.expr.SQLInListExpr;
|
||||
import com.alibaba.druid.sql.ast.expr.SQLLiteralExpr;
|
||||
import com.alibaba.druid.sql.ast.expr.SQLVariantRefExpr;
|
||||
import com.alibaba.druid.sql.dialect.mysql.visitor.MySqlParameterizedOutputVisitor;
|
||||
import com.alibaba.druid.sql.dialect.oracle.visitor.OracleParameterizedOutputVisitor;
|
||||
import com.alibaba.druid.sql.dialect.postgresql.visitor.PGParameterizedOutputVisitor;
|
||||
import com.alibaba.druid.sql.parser.SQLParserUtils;
|
||||
import com.alibaba.druid.sql.parser.SQLStatementParser;
|
||||
import com.alibaba.druid.util.JdbcUtils;
|
||||
|
||||
public class ParameterizedOutputVisitorUtils {
|
||||
|
||||
public static final String ATTR_PARAMS_SKIP = "druid.parameterized.skip";
|
||||
|
||||
public static String parameterize(String sql, String dbType) {
|
||||
SQLStatementParser parser = SQLParserUtils.createSQLStatementParser(sql, dbType);
|
||||
List<SQLStatement> statementList = parser.parseStatementList();
|
||||
SQLStatement statemen = statementList.get(0);
|
||||
|
||||
Assert.assertEquals(1, statementList.size());
|
||||
|
||||
StringBuilder out = new StringBuilder();
|
||||
SQLASTOutputVisitor visitor = createParameterizedOutputVisitor(out, dbType);
|
||||
statemen.accept(visitor);
|
||||
|
||||
return out.toString();
|
||||
}
|
||||
|
||||
public static SQLASTOutputVisitor createParameterizedOutputVisitor(Appendable out, String dbType) {
|
||||
if (JdbcUtils.ORACLE.equals(dbType)) {
|
||||
return new OracleParameterizedOutputVisitor();
|
||||
}
|
||||
|
||||
if (JdbcUtils.MYSQL.equals(dbType)) {
|
||||
return new MySqlParameterizedOutputVisitor();
|
||||
}
|
||||
|
||||
if (JdbcUtils.POSTGRESQL.equals(dbType)) {
|
||||
return new PGParameterizedOutputVisitor();
|
||||
}
|
||||
|
||||
return new ParameterizedOutputVisitor();
|
||||
}
|
||||
|
||||
public static boolean visit(SQLASTOutputVisitor v, SQLInListExpr x) {
|
||||
x.getExpr().accept(v);
|
||||
|
||||
if (x.isNot()) {
|
||||
v.print(" NOT IN (?)");
|
||||
} else {
|
||||
v.print(" IN (?)");
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public static SQLBinaryOpExpr merge(SQLBinaryOpExpr x) {
|
||||
if (x.getLeft() instanceof SQLLiteralExpr && x.getRight() instanceof SQLLiteralExpr) {
|
||||
if (x.getOperator() == SQLBinaryOperator.Equality || x.getOperator() == SQLBinaryOperator.NotEqual) {
|
||||
x.getLeft().getAttributes().put(ATTR_PARAMS_SKIP, true);
|
||||
x.getRight().getAttributes().put(ATTR_PARAMS_SKIP, true);
|
||||
}
|
||||
return x;
|
||||
}
|
||||
|
||||
if (x.getRight() instanceof SQLLiteralExpr) {
|
||||
x = new SQLBinaryOpExpr(x.getLeft(), x.getOperator(), new SQLVariantRefExpr("?"));
|
||||
}
|
||||
|
||||
if (x.getLeft() instanceof SQLLiteralExpr) {
|
||||
x = new SQLBinaryOpExpr(new SQLVariantRefExpr("?"), x.getOperator(), x.getRight());
|
||||
}
|
||||
|
||||
for (;;) {
|
||||
if (x.getRight() instanceof SQLBinaryOpExpr) {
|
||||
if (x.getLeft() instanceof SQLBinaryOpExpr) {
|
||||
SQLBinaryOpExpr leftBinaryExpr = (SQLBinaryOpExpr) x.getLeft();
|
||||
if (leftBinaryExpr.getRight().equals(x.getRight())) {
|
||||
x = leftBinaryExpr;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
x = new SQLBinaryOpExpr(x.getLeft(), x.getOperator(), merge((SQLBinaryOpExpr) x.getRight()));
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
if (x.getLeft() instanceof SQLBinaryOpExpr) {
|
||||
x = new SQLBinaryOpExpr(merge((SQLBinaryOpExpr) x.getLeft()), x.getOperator(), x.getRight());
|
||||
}
|
||||
|
||||
// ID = ? OR ID = ? => ID = ?
|
||||
if (x.getOperator() == SQLBinaryOperator.BooleanOr) {
|
||||
if ((x.getLeft() instanceof SQLBinaryOpExpr) && (x.getRight() instanceof SQLBinaryOpExpr)) {
|
||||
SQLBinaryOpExpr left = (SQLBinaryOpExpr) x.getLeft();
|
||||
SQLBinaryOpExpr right = (SQLBinaryOpExpr) x.getRight();
|
||||
|
||||
if (mergeEqual(left, right)) {
|
||||
return left;
|
||||
}
|
||||
|
||||
if (isLiteralExpr(left.getLeft()) && left.getOperator() == SQLBinaryOperator.BooleanOr) {
|
||||
if (mergeEqual(left.getRight(), right)) {
|
||||
return left;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return x;
|
||||
}
|
||||
|
||||
private static boolean mergeEqual(SQLExpr a, SQLExpr b) {
|
||||
if (!(a instanceof SQLBinaryOpExpr)) {
|
||||
return false;
|
||||
}
|
||||
if (!(b instanceof SQLBinaryOpExpr)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
SQLBinaryOpExpr binaryA = (SQLBinaryOpExpr) a;
|
||||
SQLBinaryOpExpr binaryB = (SQLBinaryOpExpr) b;
|
||||
|
||||
if (binaryA.getOperator() != SQLBinaryOperator.Equality) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (binaryB.getOperator() != SQLBinaryOperator.Equality) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!(binaryA.getRight() instanceof SQLLiteralExpr || binaryA.getRight() instanceof SQLVariantRefExpr)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!(binaryB.getRight() instanceof SQLLiteralExpr || binaryB.getRight() instanceof SQLVariantRefExpr)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return binaryA.getLeft().toString().equals(binaryB.getLeft().toString());
|
||||
}
|
||||
|
||||
private static boolean isLiteralExpr(SQLExpr expr) {
|
||||
if (expr instanceof SQLLiteralExpr) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (expr instanceof SQLBinaryOpExpr) {
|
||||
SQLBinaryOpExpr binary = (SQLBinaryOpExpr) expr;
|
||||
return isLiteralExpr(binary.getLeft()) && isLiteralExpr(binary.getRight());
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user