From 9c578e0c75eb661969d5bf770b2347940ab22f40 Mon Sep 17 00:00:00 2001 From: wenshao Date: Wed, 31 Jul 2013 00:11:11 +0800 Subject: [PATCH] improve sql parser --- .../ParameterizedOutputVisitorUtils.java | 46 +++++++++++++------ .../MySqlParameterizedOutputVisitorTest.java | 3 +- ...MySqlParameterizedOutputVisitorTest_1.java | 39 ++++++++++++++++ 3 files changed, 72 insertions(+), 16 deletions(-) create mode 100644 src/test/java/com/alibaba/druid/bvt/sql/mysql/MySqlParameterizedOutputVisitorTest_1.java diff --git a/src/main/java/com/alibaba/druid/sql/visitor/ParameterizedOutputVisitorUtils.java b/src/main/java/com/alibaba/druid/sql/visitor/ParameterizedOutputVisitorUtils.java index 3093ffc6e4..d292574b37 100644 --- a/src/main/java/com/alibaba/druid/sql/visitor/ParameterizedOutputVisitorUtils.java +++ b/src/main/java/com/alibaba/druid/sql/visitor/ParameterizedOutputVisitorUtils.java @@ -52,13 +52,17 @@ public class ParameterizedOutputVisitorUtils { SQLStatement stmt = statementList.get(0); StringBuilder out = new StringBuilder(); - SQLASTOutputVisitor visitor = createParameterizedOutputVisitor(out, dbType); + ParameterizedVisitor visitor = createParameterizedOutputVisitor(out, dbType); stmt.accept(visitor); - + + if (visitor.getReplaceCount() == 0) { + return sql; + } + return out.toString(); } - public static SQLASTOutputVisitor createParameterizedOutputVisitor(Appendable out, String dbType) { + public static ParameterizedVisitor createParameterizedOutputVisitor(Appendable out, String dbType) { if (JdbcUtils.ORACLE.equals(dbType) || JdbcUtils.ALI_ORACLE.equals(dbType)) { return new OracleParameterizedOutputVisitor(out); } @@ -91,6 +95,13 @@ public class ParameterizedOutputVisitorUtils { } public static boolean visit(ParameterizedVisitor v, SQLInListExpr x) { + List targetList = x.getTargetList(); + + boolean changed = true; + if (targetList.size() == 1 && targetList.get(0) instanceof SQLVariantRefExpr) { + changed = false; + } + x.getExpr().accept(v); if (x.isNot()) { @@ -99,6 +110,10 @@ public class ParameterizedOutputVisitorUtils { v.print(" IN (?)"); } + if (changed) { + v.incrementReplaceCunt(); + } + return false; } @@ -140,26 +155,21 @@ public class ParameterizedOutputVisitorUtils { return x; } - if (right instanceof SQLLiteralExpr) { - x = new SQLBinaryOpExpr(x.getLeft(), x.getOperator(), new SQLVariantRefExpr("?")); - x.setParent(parent); - } - - if (x.getLeft() instanceof SQLLiteralExpr) { - x = new SQLBinaryOpExpr(new SQLVariantRefExpr("?"), x.getOperator(), x.getRight()); - x.setParent(parent); - } - for (;;) { if (x.getRight() instanceof SQLBinaryOpExpr) { if (x.getLeft() instanceof SQLBinaryOpExpr) { SQLBinaryOpExpr leftBinaryExpr = (SQLBinaryOpExpr) x.getLeft(); if (leftBinaryExpr.getRight().equals(x.getRight())) { x = leftBinaryExpr; + v.incrementReplaceCunt(); continue; } } - x = new SQLBinaryOpExpr(x.getLeft(), x.getOperator(), merge(v, (SQLBinaryOpExpr) x.getRight())); + SQLExpr mergedRight = merge(v, (SQLBinaryOpExpr) x.getRight()); + if (mergedRight != x.getRight()) { + x = new SQLBinaryOpExpr(x.getLeft(), x.getOperator(), mergedRight); + v.incrementReplaceCunt(); + } x.setParent(parent); } @@ -167,7 +177,11 @@ public class ParameterizedOutputVisitorUtils { } if (x.getLeft() instanceof SQLBinaryOpExpr) { - x = new SQLBinaryOpExpr(merge(v, (SQLBinaryOpExpr) x.getLeft()), x.getOperator(), x.getRight()); + SQLExpr mergedLeft = merge(v, (SQLBinaryOpExpr) x.getLeft()); + if (mergedLeft != x.getLeft()) { + x = new SQLBinaryOpExpr(mergedLeft, x.getOperator(), x.getRight()); + v.incrementReplaceCunt(); + } x.setParent(parent); } @@ -178,12 +192,14 @@ public class ParameterizedOutputVisitorUtils { SQLBinaryOpExpr rightBinary = (SQLBinaryOpExpr) x.getRight(); if (mergeEqual(leftBinary, rightBinary)) { + v.incrementReplaceCunt(); return leftBinary; } if (isLiteralExpr(leftBinary.getLeft()) // && leftBinary.getOperator() == SQLBinaryOperator.BooleanOr) { if (mergeEqual(leftBinary.getRight(), right)) { + v.incrementReplaceCunt(); return leftBinary; } } 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 5b310eab88..7fd4cb8251 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 @@ -17,9 +17,10 @@ package com.alibaba.druid.bvt.sql.mysql; import java.util.List; -import junit.framework.Assert; import junit.framework.TestCase; +import org.junit.Assert; + 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; diff --git a/src/test/java/com/alibaba/druid/bvt/sql/mysql/MySqlParameterizedOutputVisitorTest_1.java b/src/test/java/com/alibaba/druid/bvt/sql/mysql/MySqlParameterizedOutputVisitorTest_1.java new file mode 100644 index 0000000000..b8cd7eb64e --- /dev/null +++ b/src/test/java/com/alibaba/druid/bvt/sql/mysql/MySqlParameterizedOutputVisitorTest_1.java @@ -0,0 +1,39 @@ +/* + * 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 junit.framework.TestCase; + +import org.junit.Assert; + +import com.alibaba.druid.sql.visitor.ParameterizedOutputVisitorUtils; +import com.alibaba.druid.util.JdbcConstants; + +public class MySqlParameterizedOutputVisitorTest_1 extends TestCase { + + public void test_0() throws Exception { + String sql = "SELECT * FROM T WHERE ID IN (?)"; + Assert.assertSame(ParameterizedOutputVisitorUtils.parameterize(sql, JdbcConstants.MYSQL), sql); + Assert.assertSame(ParameterizedOutputVisitorUtils.parameterize(sql, JdbcConstants.ORACLE), sql); + Assert.assertSame(ParameterizedOutputVisitorUtils.parameterize(sql, JdbcConstants.DB2), sql); + Assert.assertSame(ParameterizedOutputVisitorUtils.parameterize(sql, JdbcConstants.SQL_SERVER), sql); + Assert.assertSame(ParameterizedOutputVisitorUtils.parameterize(sql, JdbcConstants.POSTGRESQL), sql); + Assert.assertSame(ParameterizedOutputVisitorUtils.parameterize(sql, JdbcConstants.H2), sql); + Assert.assertSame(ParameterizedOutputVisitorUtils.parameterize(sql, JdbcConstants.DERBY), sql); + Assert.assertSame(ParameterizedOutputVisitorUtils.parameterize(sql, JdbcConstants.HSQL), sql); + } + +}