/** * Alipay.com Inc. * Copyright (c) 2004-2012 All Rights Reserved. */ package com.alipay.zdal.parser.sql.visitor; import java.util.List; import com.alipay.zdal.parser.sql.ast.SQLExpr; import com.alipay.zdal.parser.sql.ast.SQLStatement; import com.alipay.zdal.parser.sql.ast.expr.SQLBinaryOpExpr; import com.alipay.zdal.parser.sql.ast.expr.SQLBinaryOperator; import com.alipay.zdal.parser.sql.ast.expr.SQLInListExpr; import com.alipay.zdal.parser.sql.ast.expr.SQLLiteralExpr; import com.alipay.zdal.parser.sql.ast.expr.SQLVariantRefExpr; import com.alipay.zdal.parser.sql.dialect.mysql.visitor.MySqlParameterizedOutputVisitor; import com.alipay.zdal.parser.sql.dialect.oracle.visitor.OracleParameterizedOutputVisitor; import com.alipay.zdal.parser.sql.parser.SQLParserUtils; import com.alipay.zdal.parser.sql.parser.SQLStatementParser; import com.alipay.zdal.parser.sql.util.JdbcUtils; /** * * @author ���� * @version $Id: ParameterizedOutputVisitorUtils.java, v 0.1 2012-11-17 ����3:56:10 Exp $ */ 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); 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(out); } if (JdbcUtils.MYSQL.equals(dbType)) { return new MySqlParameterizedOutputVisitor(out); } return new ParameterizedOutputVisitor(out); } 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; } }