From 21c681dd0f6b297fbc7fdf13df3ee308bc7d0a09 Mon Sep 17 00:00:00 2001 From: wenshao Date: Tue, 30 Jul 2013 23:25:56 +0800 Subject: [PATCH] improve parser & wall-filter --- .../DB2ParameterizedOutputVisitor.java | 18 +- .../mysql/visitor/MySqlOutputVisitor.java | 32 +- .../MySqlParameterizedOutputVisitor.java | 351 ++++++++---------- .../OracleParameterizedOutputVisitor.java | 200 +++++----- .../visitor/PGParameterizedOutputVisitor.java | 25 +- .../SQLServerParameterizedOutputVisitor.java | 18 +- .../visitor/ParameterizedOutputVisitor.java | 17 +- .../sql/visitor/ParameterizedVisitor.java | 8 + .../com/alibaba/druid/wall/WallProvider.java | 20 +- .../MySqlParameterizedOutputVisitorTest.java | 156 ++++---- 10 files changed, 455 insertions(+), 390 deletions(-) create mode 100644 src/main/java/com/alibaba/druid/sql/visitor/ParameterizedVisitor.java diff --git a/src/main/java/com/alibaba/druid/sql/dialect/db2/visitor/DB2ParameterizedOutputVisitor.java b/src/main/java/com/alibaba/druid/sql/dialect/db2/visitor/DB2ParameterizedOutputVisitor.java index 3235266edf..c1bc7c7036 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/db2/visitor/DB2ParameterizedOutputVisitor.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/db2/visitor/DB2ParameterizedOutputVisitor.java @@ -23,8 +23,11 @@ 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; +import com.alibaba.druid.sql.visitor.ParameterizedVisitor; -public class DB2ParameterizedOutputVisitor extends DB2OutputVisitor { +public class DB2ParameterizedOutputVisitor extends DB2OutputVisitor implements ParameterizedVisitor { + + private int replaceCount; public DB2ParameterizedOutputVisitor(){ this(new StringBuilder()); @@ -34,6 +37,14 @@ public class DB2ParameterizedOutputVisitor extends DB2OutputVisitor { super(appender); } + public int getReplaceCount() { + return this.replaceCount; + } + + public void incrementReplaceCunt() { + replaceCount++; + } + public boolean visit(SQLInListExpr x) { return ParameterizedOutputVisitorUtils.visit(this, x); } @@ -46,6 +57,7 @@ public class DB2ParameterizedOutputVisitor extends DB2OutputVisitor { public boolean visit(SQLNullExpr x) { print('?'); + incrementReplaceCunt(); return false; } @@ -55,6 +67,7 @@ public class DB2ParameterizedOutputVisitor extends DB2OutputVisitor { } print('?'); + incrementReplaceCunt(); return false; } @@ -64,6 +77,7 @@ public class DB2ParameterizedOutputVisitor extends DB2OutputVisitor { } print('?'); + incrementReplaceCunt(); return false; } @@ -73,6 +87,7 @@ public class DB2ParameterizedOutputVisitor extends DB2OutputVisitor { } print('?'); + incrementReplaceCunt(); return false; } @@ -82,6 +97,7 @@ public class DB2ParameterizedOutputVisitor extends DB2OutputVisitor { } print('?'); + incrementReplaceCunt(); return false; } diff --git a/src/main/java/com/alibaba/druid/sql/dialect/mysql/visitor/MySqlOutputVisitor.java b/src/main/java/com/alibaba/druid/sql/dialect/mysql/visitor/MySqlOutputVisitor.java index 3bb2c34bad..dd7cc9ceeb 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/mysql/visitor/MySqlOutputVisitor.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/mysql/visitor/MySqlOutputVisitor.java @@ -901,20 +901,7 @@ public class MySqlOutputVisitor extends SQLASTOutputVisitor implements MySqlASTV if (x.getValuesList().size() != 0) { println(); - print("VALUES "); - if (x.getValuesList().size() > 1) { - incrementIndent(); - } - for (int i = 0, size = x.getValuesList().size(); i < size; ++i) { - if (i != 0) { - print(","); - println(); - } - x.getValuesList().get(i).accept(this); - } - if (x.getValuesList().size() > 1) { - decrementIndent(); - } + printValuesList(x); } if (x.getQuery() != null) { @@ -939,6 +926,23 @@ public class MySqlOutputVisitor extends SQLASTOutputVisitor implements MySqlASTV return false; } + protected void printValuesList(MySqlInsertStatement x) { + print("VALUES "); + if (x.getValuesList().size() > 1) { + incrementIndent(); + } + for (int i = 0, size = x.getValuesList().size(); i < size; ++i) { + if (i != 0) { + print(","); + println(); + } + x.getValuesList().get(i).accept(this); + } + if (x.getValuesList().size() > 1) { + decrementIndent(); + } + } + @Override public void endVisit(MySqlLoadDataInFileStatement x) { diff --git a/src/main/java/com/alibaba/druid/sql/dialect/mysql/visitor/MySqlParameterizedOutputVisitor.java b/src/main/java/com/alibaba/druid/sql/dialect/mysql/visitor/MySqlParameterizedOutputVisitor.java index d74c9045d5..e3698f6e37 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/mysql/visitor/MySqlParameterizedOutputVisitor.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/mysql/visitor/MySqlParameterizedOutputVisitor.java @@ -1,194 +1,157 @@ -/* - * 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.sql.dialect.mysql.visitor; - -import com.alibaba.druid.sql.ast.expr.SQLBinaryOpExpr; -import com.alibaba.druid.sql.ast.expr.SQLCharExpr; -import com.alibaba.druid.sql.ast.expr.SQLIdentifierExpr; -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.ast.expr.SQLPropertyExpr; -import com.alibaba.druid.sql.ast.statement.SQLExprTableSource; -import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlInsertStatement; -import com.alibaba.druid.sql.visitor.ParameterizedOutputVisitorUtils; - -public class MySqlParameterizedOutputVisitor extends MySqlOutputVisitor { - - public MySqlParameterizedOutputVisitor(){ - this(new StringBuilder()); - } - - public MySqlParameterizedOutputVisitor(Appendable appender){ - super(appender); - } - - public boolean visit(SQLInListExpr x) { - return ParameterizedOutputVisitorUtils.visit(this, x); - } - - public boolean visit(SQLIdentifierExpr x) { - String name = x.getName(); - if (x.getParent() instanceof SQLExprTableSource || x.getParent() instanceof SQLPropertyExpr) { - int pos = name.lastIndexOf('_'); - if (pos != -1 && pos != name.length()) { - boolean isNumber = true; - for (int i = pos + 1; i < name.length(); ++i) { - char ch = name.charAt(i); - if (ch < '0' || ch > '9') { - isNumber = false; - break; - } - } - if (isNumber) { - String realName = name.substring(0, pos); - print(realName); - 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; - } else { - numberCount++; - } - } - - if (numberCount > 1) { - int numPos = name.length() - numberCount; - String realName = name.substring(0, numPos); - print(realName); - return false; - } - } - print(name); - return false; - } - - 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; - } - - @Override - public boolean visit(MySqlInsertStatement x) { - print("INSERT "); - - if (x.isLowPriority()) { - print("LOW_PRIORITY "); - } - - if (x.isDelayed()) { - print("DELAYED "); - } - - if (x.isHighPriority()) { - print("HIGH_PRIORITY "); - } - - if (x.isIgnore()) { - print("IGNORE "); - } - - print("INTO "); - - x.getTableSource().accept(this); - - if (x.getColumns().size() > 0) { - print(" ("); - for (int i = 0, size = x.getColumns().size(); i < size; ++i) { - if (i != 0) { - print(", "); - } - x.getColumns().get(i).accept(this); - } - print(")"); - } - - if (x.getValuesList().size() != 0) { - print(" VALUES "); - int size = x.getValuesList().size(); - if (size == 0) { - print("()"); - } else { - for (int i = 0; i < 1; ++i) { - if (i != 0) { - print(", "); - } - x.getValuesList().get(i).accept(this); - } - } - } - if (x.getQuery() != null) { - print(" "); - x.getQuery().accept(this); - } - - if (x.getDuplicateKeyUpdate().size() != 0) { - print(" ON DUPLICATE KEY UPDATE "); - printAndAccept(x.getDuplicateKeyUpdate(), ", "); - } - - return false; - } -} +/* + * 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.sql.dialect.mysql.visitor; + +import com.alibaba.druid.sql.ast.expr.SQLBinaryOpExpr; +import com.alibaba.druid.sql.ast.expr.SQLCharExpr; +import com.alibaba.druid.sql.ast.expr.SQLIdentifierExpr; +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.ast.expr.SQLPropertyExpr; +import com.alibaba.druid.sql.ast.statement.SQLExprTableSource; +import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlInsertStatement; +import com.alibaba.druid.sql.visitor.ParameterizedOutputVisitorUtils; +import com.alibaba.druid.sql.visitor.ParameterizedVisitor; + +public class MySqlParameterizedOutputVisitor extends MySqlOutputVisitor implements ParameterizedVisitor { + + private int replaceCount; + + public MySqlParameterizedOutputVisitor(){ + this(new StringBuilder()); + } + + public MySqlParameterizedOutputVisitor(Appendable appender){ + super(appender); + } + + public int getReplaceCount() { + return this.replaceCount; + } + + public void incrementReplaceCunt() { + replaceCount++; + } + + public boolean visit(SQLInListExpr x) { + return ParameterizedOutputVisitorUtils.visit(this, x); + } + + public boolean visit(SQLIdentifierExpr x) { + final String name = x.getName(); + if (x.getParent() instanceof SQLExprTableSource || x.getParent() instanceof SQLPropertyExpr) { + int pos = name.lastIndexOf('_'); + if (pos != -1 && pos != name.length()) { + boolean isNumber = true; + for (int i = pos + 1; i < name.length(); ++i) { + char ch = name.charAt(i); + if (ch < '0' || ch > '9') { + isNumber = false; + break; + } + } + if (isNumber) { + String realName = name.substring(0, pos); + print(realName); + incrementReplaceCunt(); + 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; + } else { + numberCount++; + } + } + + if (numberCount > 1) { + int numPos = name.length() - numberCount; + String realName = name.substring(0, numPos); + print(realName); + incrementReplaceCunt(); + return false; + } + } + print(name); + return false; + } + + public boolean visit(SQLBinaryOpExpr x) { + x = ParameterizedOutputVisitorUtils.merge(x); + + return super.visit(x); + } + + public boolean visit(SQLNullExpr x) { + print('?'); + incrementReplaceCunt(); + return false; + } + + public boolean visit(SQLIntegerExpr x) { + if (Boolean.TRUE.equals(x.getAttribute(ParameterizedOutputVisitorUtils.ATTR_PARAMS_SKIP))) { + return super.visit(x); + } + + print('?'); + incrementReplaceCunt(); + return false; + } + + public boolean visit(SQLNumberExpr x) { + if (Boolean.TRUE.equals(x.getAttribute(ParameterizedOutputVisitorUtils.ATTR_PARAMS_SKIP))) { + return super.visit(x); + } + + print('?'); + incrementReplaceCunt(); + return false; + } + + public boolean visit(SQLCharExpr x) { + if (Boolean.TRUE.equals(x.getAttribute(ParameterizedOutputVisitorUtils.ATTR_PARAMS_SKIP))) { + return super.visit(x); + } + + print('?'); + incrementReplaceCunt(); + return false; + } + + public boolean visit(SQLNCharExpr x) { + if (Boolean.TRUE.equals(x.getAttribute(ParameterizedOutputVisitorUtils.ATTR_PARAMS_SKIP))) { + return super.visit(x); + } + + print('?'); + incrementReplaceCunt(); + return false; + } + + protected void printValuesList(MySqlInsertStatement x) { + print("VALUES "); + incrementIndent(); + x.getValuesList().get(0).accept(this); + decrementIndent(); + } +} diff --git a/src/main/java/com/alibaba/druid/sql/dialect/oracle/visitor/OracleParameterizedOutputVisitor.java b/src/main/java/com/alibaba/druid/sql/dialect/oracle/visitor/OracleParameterizedOutputVisitor.java index cc1ca8fef9..355134ef98 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/oracle/visitor/OracleParameterizedOutputVisitor.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/oracle/visitor/OracleParameterizedOutputVisitor.java @@ -1,92 +1,108 @@ -/* - * 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.sql.dialect.oracle.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 OracleParameterizedOutputVisitor extends OracleOutputVisitor { - - public OracleParameterizedOutputVisitor() { - this (new StringBuilder()); - } - - public OracleParameterizedOutputVisitor(Appendable appender){ - super(appender); - } - - public OracleParameterizedOutputVisitor(Appendable appender, boolean printPostSemi){ - super (appender, printPostSemi); - } - - 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; - } - -} +/* + * 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.sql.dialect.oracle.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; +import com.alibaba.druid.sql.visitor.ParameterizedVisitor; + +public class OracleParameterizedOutputVisitor extends OracleOutputVisitor implements ParameterizedVisitor { + + private int replaceCount; + + public OracleParameterizedOutputVisitor(){ + this(new StringBuilder()); + } + + public OracleParameterizedOutputVisitor(Appendable appender){ + super(appender); + } + + public OracleParameterizedOutputVisitor(Appendable appender, boolean printPostSemi){ + super(appender, printPostSemi); + } + + public int getReplaceCount() { + return this.replaceCount; + } + + public void incrementReplaceCunt() { + replaceCount++; + } + + 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('?'); + incrementReplaceCunt(); + return false; + } + + public boolean visit(SQLIntegerExpr x) { + if (Boolean.TRUE.equals(x.getAttribute(ParameterizedOutputVisitorUtils.ATTR_PARAMS_SKIP))) { + return super.visit(x); + } + + print('?'); + incrementReplaceCunt(); + return false; + } + + public boolean visit(SQLNumberExpr x) { + if (Boolean.TRUE.equals(x.getAttribute(ParameterizedOutputVisitorUtils.ATTR_PARAMS_SKIP))) { + return super.visit(x); + } + + print('?'); + incrementReplaceCunt(); + return false; + } + + public boolean visit(SQLCharExpr x) { + if (Boolean.TRUE.equals(x.getAttribute(ParameterizedOutputVisitorUtils.ATTR_PARAMS_SKIP))) { + return super.visit(x); + } + + print('?'); + incrementReplaceCunt(); + return false; + } + + public boolean visit(SQLNCharExpr x) { + if (Boolean.TRUE.equals(x.getAttribute(ParameterizedOutputVisitorUtils.ATTR_PARAMS_SKIP))) { + return super.visit(x); + } + + print('?'); + incrementReplaceCunt(); + return false; + } + +} diff --git a/src/main/java/com/alibaba/druid/sql/dialect/postgresql/visitor/PGParameterizedOutputVisitor.java b/src/main/java/com/alibaba/druid/sql/dialect/postgresql/visitor/PGParameterizedOutputVisitor.java index 848c900540..e99d27de5e 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/postgresql/visitor/PGParameterizedOutputVisitor.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/postgresql/visitor/PGParameterizedOutputVisitor.java @@ -23,16 +23,28 @@ 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; +import com.alibaba.druid.sql.visitor.ParameterizedVisitor; -public class PGParameterizedOutputVisitor extends PGOutputVisitor { - public PGParameterizedOutputVisitor() { - this (new StringBuilder()); +public class PGParameterizedOutputVisitor extends PGOutputVisitor implements ParameterizedVisitor { + + private int replaceCount; + + public PGParameterizedOutputVisitor(){ + this(new StringBuilder()); } - + public PGParameterizedOutputVisitor(Appendable appender){ super(appender); } + public int getReplaceCount() { + return this.replaceCount; + } + + public void incrementReplaceCunt() { + replaceCount++; + } + public boolean visit(SQLInListExpr x) { return ParameterizedOutputVisitorUtils.visit(this, x); } @@ -45,6 +57,7 @@ public class PGParameterizedOutputVisitor extends PGOutputVisitor { public boolean visit(SQLNullExpr x) { print('?'); + incrementReplaceCunt(); return false; } @@ -54,6 +67,7 @@ public class PGParameterizedOutputVisitor extends PGOutputVisitor { } print('?'); + incrementReplaceCunt(); return false; } @@ -63,6 +77,7 @@ public class PGParameterizedOutputVisitor extends PGOutputVisitor { } print('?'); + incrementReplaceCunt(); return false; } @@ -72,6 +87,7 @@ public class PGParameterizedOutputVisitor extends PGOutputVisitor { } print('?'); + incrementReplaceCunt(); return false; } @@ -81,6 +97,7 @@ public class PGParameterizedOutputVisitor extends PGOutputVisitor { } print('?'); + incrementReplaceCunt(); return false; } diff --git a/src/main/java/com/alibaba/druid/sql/dialect/sqlserver/visitor/SQLServerParameterizedOutputVisitor.java b/src/main/java/com/alibaba/druid/sql/dialect/sqlserver/visitor/SQLServerParameterizedOutputVisitor.java index 83ec6f9377..3a9a9a8578 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/sqlserver/visitor/SQLServerParameterizedOutputVisitor.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/sqlserver/visitor/SQLServerParameterizedOutputVisitor.java @@ -23,13 +23,24 @@ 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; +import com.alibaba.druid.sql.visitor.ParameterizedVisitor; -public class SQLServerParameterizedOutputVisitor extends SQLServerOutputVisitor { +public class SQLServerParameterizedOutputVisitor extends SQLServerOutputVisitor implements ParameterizedVisitor { + + private int replaceCount; public SQLServerParameterizedOutputVisitor(Appendable appender){ super(appender); } + public int getReplaceCount() { + return this.replaceCount; + } + + public void incrementReplaceCunt() { + replaceCount++; + } + public boolean visit(SQLInListExpr x) { return ParameterizedOutputVisitorUtils.visit(this, x); } @@ -42,6 +53,7 @@ public class SQLServerParameterizedOutputVisitor extends SQLServerOutputVisitor public boolean visit(SQLNullExpr x) { print('?'); + incrementReplaceCunt(); return false; } @@ -51,6 +63,7 @@ public class SQLServerParameterizedOutputVisitor extends SQLServerOutputVisitor } print('?'); + incrementReplaceCunt(); return false; } @@ -60,6 +73,7 @@ public class SQLServerParameterizedOutputVisitor extends SQLServerOutputVisitor } print('?'); + incrementReplaceCunt(); return false; } @@ -69,6 +83,7 @@ public class SQLServerParameterizedOutputVisitor extends SQLServerOutputVisitor } print('?'); + incrementReplaceCunt(); return false; } @@ -78,6 +93,7 @@ public class SQLServerParameterizedOutputVisitor extends SQLServerOutputVisitor } print('?'); + incrementReplaceCunt(); return false; } } diff --git a/src/main/java/com/alibaba/druid/sql/visitor/ParameterizedOutputVisitor.java b/src/main/java/com/alibaba/druid/sql/visitor/ParameterizedOutputVisitor.java index e8c8595b64..15c687f6a8 100644 --- a/src/main/java/com/alibaba/druid/sql/visitor/ParameterizedOutputVisitor.java +++ b/src/main/java/com/alibaba/druid/sql/visitor/ParameterizedOutputVisitor.java @@ -23,7 +23,9 @@ 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 class ParameterizedOutputVisitor extends SQLASTOutputVisitor implements ParameterizedVisitor { + private int replaceCount; + public ParameterizedOutputVisitor() { this (new StringBuilder()); } @@ -31,6 +33,14 @@ public class ParameterizedOutputVisitor extends SQLASTOutputVisitor { public ParameterizedOutputVisitor(Appendable appender){ super(appender); } + + public int getReplaceCount() { + return this.replaceCount; + } + + public void incrementReplaceCunt() { + replaceCount++; + } public boolean visit(SQLInListExpr x) { return ParameterizedOutputVisitorUtils.visit(this, x); @@ -44,6 +54,7 @@ public class ParameterizedOutputVisitor extends SQLASTOutputVisitor { public boolean visit(SQLNullExpr x) { print('?'); + incrementReplaceCunt(); return false; } @@ -53,6 +64,7 @@ public class ParameterizedOutputVisitor extends SQLASTOutputVisitor { } print('?'); + incrementReplaceCunt(); return false; } @@ -62,6 +74,7 @@ public class ParameterizedOutputVisitor extends SQLASTOutputVisitor { } print('?'); + incrementReplaceCunt(); return false; } @@ -71,6 +84,7 @@ public class ParameterizedOutputVisitor extends SQLASTOutputVisitor { } print('?'); + incrementReplaceCunt(); return false; } @@ -80,6 +94,7 @@ public class ParameterizedOutputVisitor extends SQLASTOutputVisitor { } print('?'); + incrementReplaceCunt(); return false; } } diff --git a/src/main/java/com/alibaba/druid/sql/visitor/ParameterizedVisitor.java b/src/main/java/com/alibaba/druid/sql/visitor/ParameterizedVisitor.java new file mode 100644 index 0000000000..19473b0b1b --- /dev/null +++ b/src/main/java/com/alibaba/druid/sql/visitor/ParameterizedVisitor.java @@ -0,0 +1,8 @@ +package com.alibaba.druid.sql.visitor; + +public interface ParameterizedVisitor extends SQLASTVisitor { + + int getReplaceCount(); + + void incrementReplaceCunt(); +} diff --git a/src/main/java/com/alibaba/druid/wall/WallProvider.java b/src/main/java/com/alibaba/druid/wall/WallProvider.java index 31daf86e33..ab46ceebb5 100644 --- a/src/main/java/com/alibaba/druid/wall/WallProvider.java +++ b/src/main/java/com/alibaba/druid/wall/WallProvider.java @@ -227,7 +227,12 @@ public abstract class WallProvider { WallSqlStat wallStat = whiteList.get(sql); if (wallStat == null) { - String mergedSql = ParameterizedOutputVisitorUtils.parameterize(sql, dbType); + String mergedSql; + try { + mergedSql = ParameterizedOutputVisitorUtils.parameterize(sql, dbType); + } catch (Exception ex) { + mergedSql = sql; + } wallStat = sqlList.get(mergedSql); if (wallStat == null) { wallStat = new WallSqlStat(tableStats, functionStats, syntaxError); @@ -259,7 +264,12 @@ public abstract class WallProvider { WallSqlStat wallStat = blackList.get(sql); if (wallStat == null) { - String mergedSql = ParameterizedOutputVisitorUtils.parameterize(sql, dbType); + String mergedSql; + try { + mergedSql = ParameterizedOutputVisitorUtils.parameterize(sql, dbType); + } catch (Exception ex) { + mergedSql = sql; + } wallStat = sqlList.get(mergedSql); if (wallStat == null) { wallStat = new WallSqlStat(tableStats, functionStats, violations, syntaxError); @@ -289,7 +299,7 @@ public abstract class WallProvider { return Collections. unmodifiableSet(hashSet); } - + public Set getSqlList() { Set hashSet = new HashSet(); lock.readLock().lock(); @@ -352,11 +362,11 @@ public abstract class WallProvider { if (whiteList != null) { whiteList = null; } - + if (blackList != null) { blackList = null; } - + if (sqlList != null) { sqlList = null; } diff --git a/src/test/java/com/alibaba/druid/bvt/sql/mysql/MySqlParameterizedOutputVisitorTest.java b/src/test/java/com/alibaba/druid/bvt/sql/mysql/MySqlParameterizedOutputVisitorTest.java index fc26af7fa8..5b310eab88 100644 --- a/src/test/java/com/alibaba/druid/bvt/sql/mysql/MySqlParameterizedOutputVisitorTest.java +++ b/src/test/java/com/alibaba/druid/bvt/sql/mysql/MySqlParameterizedOutputVisitorTest.java @@ -1,78 +1,78 @@ -/* - * 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.bvt.sql.mysql; - -import java.util.List; - -import junit.framework.Assert; -import junit.framework.TestCase; - -import com.alibaba.druid.sql.ast.SQLStatement; -import com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser; -import com.alibaba.druid.sql.dialect.mysql.visitor.MySqlParameterizedOutputVisitor; -import com.alibaba.druid.sql.dialect.oracle.parser.OracleStatementParser; -import com.alibaba.druid.sql.dialect.oracle.visitor.OracleParameterizedOutputVisitor; - -public class MySqlParameterizedOutputVisitorTest extends TestCase { - - public void test_0() throws Exception { - validate("SELECT * FROM T WHERE ID IN (?, ?, ?)", "SELECT *\nFROM T\nWHERE ID IN (?)"); - validate("SELECT * FROM T WHERE ID = 5", "SELECT *\nFROM T\nWHERE ID = ?"); - validate("SELECT * FROM T WHERE 1 = 0 AND ID = 5", "SELECT *\nFROM T\nWHERE 1 = 0\n\tAND ID = ?"); - validate("SELECT * FROM T WHERE ID = ? OR ID = ?", "SELECT *\nFROM T\nWHERE ID = ?"); - validate("SELECT * FROM T WHERE A.ID = ? OR A.ID = ?", "SELECT *\nFROM T\nWHERE A.ID = ?"); - validate("SELECT * FROM T WHERE 1 = 0 OR a.id = ? OR a.id = ? OR a.id = ? OR a.id = ?", - "SELECT *\nFROM T\nWHERE 1 = 0\n\tOR a.id = ?"); - validateOracle("SELECT * FROM T WHERE 1 = 0 OR a.id = ? OR a.id = ? OR a.id = ? OR a.id = ?", - "SELECT *\nFROM T\nWHERE 1 = 0\n\tOR a.id = ?"); - validateOracle("SELECT * FROM T WHERE A.ID = ? OR A.ID = ?", "SELECT *\nFROM T\nWHERE A.ID = ?"); - validate("INSERT INTO T (F1, F2) VALUES(?, ?), (?, ?), (?, ?)", "INSERT INTO T (F1, F2) VALUES (?, ?)"); - validate("update net_device d, sys_user u set d.resp_user_id=u.id where d.resp_user_login_name=u.username and d.id in (42354)", // - "UPDATE net_device d, sys_user u\nSET d.resp_user_id = u.id\nWHERE d.resp_user_login_name = u.username\n\tAND d.id IN (?)"); - - // System.out.println("SELECT * FORM A WHERE ID = (##)".replaceAll("##", "?")); - } - - void validate(String sql, String expect) { - - MySqlStatementParser parser = new MySqlStatementParser(sql); - List statementList = parser.parseStatementList(); - SQLStatement statemen = statementList.get(0); - - Assert.assertEquals(1, statementList.size()); - - StringBuilder out = new StringBuilder(); - MySqlParameterizedOutputVisitor visitor = new MySqlParameterizedOutputVisitor(out); - statemen.accept(visitor); - - Assert.assertEquals(expect, out.toString()); - } - - void validateOracle(String sql, String expect) { - - OracleStatementParser parser = new OracleStatementParser(sql); - List statementList = parser.parseStatementList(); - SQLStatement statemen = statementList.get(0); - - Assert.assertEquals(1, statementList.size()); - - StringBuilder out = new StringBuilder(); - OracleParameterizedOutputVisitor visitor = new OracleParameterizedOutputVisitor(out, false); - statemen.accept(visitor); - - Assert.assertEquals(expect, out.toString()); - } -} +/* + * 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.bvt.sql.mysql; + +import java.util.List; + +import junit.framework.Assert; +import junit.framework.TestCase; + +import com.alibaba.druid.sql.ast.SQLStatement; +import com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser; +import com.alibaba.druid.sql.dialect.mysql.visitor.MySqlParameterizedOutputVisitor; +import com.alibaba.druid.sql.dialect.oracle.parser.OracleStatementParser; +import com.alibaba.druid.sql.dialect.oracle.visitor.OracleParameterizedOutputVisitor; + +public class MySqlParameterizedOutputVisitorTest extends TestCase { + + public void test_0() throws Exception { + validate("SELECT * FROM T WHERE ID IN (?, ?, ?)", "SELECT *\nFROM T\nWHERE ID IN (?)"); + validate("SELECT * FROM T WHERE ID = 5", "SELECT *\nFROM T\nWHERE ID = ?"); + validate("SELECT * FROM T WHERE 1 = 0 AND ID = 5", "SELECT *\nFROM T\nWHERE 1 = 0\n\tAND ID = ?"); + validate("SELECT * FROM T WHERE ID = ? OR ID = ?", "SELECT *\nFROM T\nWHERE ID = ?"); + validate("SELECT * FROM T WHERE A.ID = ? OR A.ID = ?", "SELECT *\nFROM T\nWHERE A.ID = ?"); + validate("SELECT * FROM T WHERE 1 = 0 OR a.id = ? OR a.id = ? OR a.id = ? OR a.id = ?", + "SELECT *\nFROM T\nWHERE 1 = 0\n\tOR a.id = ?"); + validateOracle("SELECT * FROM T WHERE 1 = 0 OR a.id = ? OR a.id = ? OR a.id = ? OR a.id = ?", + "SELECT *\nFROM T\nWHERE 1 = 0\n\tOR a.id = ?"); + validateOracle("SELECT * FROM T WHERE A.ID = ? OR A.ID = ?", "SELECT *\nFROM T\nWHERE A.ID = ?"); + validate("INSERT INTO T (F1, F2) VALUES(?, ?), (?, ?), (?, ?)", "INSERT INTO T (F1, F2)\nVALUES (?, ?)"); + validate("update net_device d, sys_user u set d.resp_user_id=u.id where d.resp_user_login_name=u.username and d.id in (42354)", // + "UPDATE net_device d, sys_user u\nSET d.resp_user_id = u.id\nWHERE d.resp_user_login_name = u.username\n\tAND d.id IN (?)"); + + // System.out.println("SELECT * FORM A WHERE ID = (##)".replaceAll("##", "?")); + } + + void validate(String sql, String expect) { + + MySqlStatementParser parser = new MySqlStatementParser(sql); + List statementList = parser.parseStatementList(); + SQLStatement statemen = statementList.get(0); + + Assert.assertEquals(1, statementList.size()); + + StringBuilder out = new StringBuilder(); + MySqlParameterizedOutputVisitor visitor = new MySqlParameterizedOutputVisitor(out); + statemen.accept(visitor); + + Assert.assertEquals(expect, out.toString()); + } + + void validateOracle(String sql, String expect) { + + OracleStatementParser parser = new OracleStatementParser(sql); + List statementList = parser.parseStatementList(); + SQLStatement statemen = statementList.get(0); + + Assert.assertEquals(1, statementList.size()); + + StringBuilder out = new StringBuilder(); + OracleParameterizedOutputVisitor visitor = new OracleParameterizedOutputVisitor(out, false); + statemen.accept(visitor); + + Assert.assertEquals(expect, out.toString()); + } +}