CCJSqlParserUtil工具是强大,难用也是真的,得分析sql的各种各样的表达式。从中递归找出业务需要的。
public class SqlExpressionAnalyzer {public static void main(String[] args) {String sql = "select id,user_name from sys_user t1,sys_office t2 where t1.id=t2.id and mobile =? and user_name like '%abc%' and user_name like ? and user_name like ? and position=? and bbb in ('1','2') and ccc in (?,?) and sex='1' and (photo='abc' or headImg='abc' or user_name like '%abc%') and nation='2'" +" and id in (select id from relation_user where acc=?) and user_name in (select user_name from table_3 where user_name in (?,?,?,?,?) and user_name in ('1','3','4')) " +"and mobile =(case when is_using=1 then '1' when is_using=0 then '2' else '3' end)";String updateSql = "update sys_user set mobile=?,user_name='张三' where mobile='1' and id='1'";String insertSql = "insert into sys_user (id,mobile,user_name) values (?,?,?)";String delSql = "delete from sys_user where mobile=? and user_name=? and mobile in (?,?,?,?,?) and user_name in ('李四','张三')";AnalyzerResult analyzerResult = parse(delSql);System.out.println(analyzerResult);}public static AnalyzerResult parse(BoundSql boundSql) {return null != boundSql ? parse(boundSql.getSql()) : AnalyzerResult.empty();}public static AnalyzerResult parse(String sql) {Statement statement;try {statement = CCJSqlParserUtil.parse(sql);} catch (JSQLParserException e) {throw new LocalException(e.getMessage());}if (statement instanceof Select) {return analyzeSelect((Select) statement);} else if (statement instanceof Update) {return analyzeUpdate((Update) statement);} else if (statement instanceof Insert) {return analyzerInsert((Insert) statement);} else if (statement instanceof Delete) {return analyzerDelete((Delete) statement);}return AnalyzerResult.empty();}private static AnalyzerResult analyzerInsert(Insert insert) {AnalyzerResult analyzerResult = new AnalyzerResult(insert.getTable());List<Column> columns = insert.getColumns();List<Expression> setExpressionList = insert.getSetExpressionList();if (null != setExpressionList && setExpressionList.size() == columns.size()) {analyzerResult.putResults(columns, setExpressionList);} else {ItemsList itemsList = insert.getItemsList();if (itemsList instanceof ExpressionList) {ExpressionList expressionList = (ExpressionList) itemsList;List<Expression> expressions = expressionList.getExpressions();analyzerResult.putResults(columns, expressions);} else if (itemsList instanceof MultiExpressionList) {MultiExpressionList multiExpressionList = (MultiExpressionList) itemsList;List<ExpressionList> exprList = multiExpressionList.getExprList();for (ExpressionList expressionList : exprList) {List<Expression> expressions = expressionList.getExpressions();analyzerResult.putResults(columns, expressions);}}}return analyzerResult;}private static AnalyzerResult analyzerDelete(Delete delete) {AnalyzerResult result = new AnalyzerResult(delete.getTable());Expression where = delete.getWhere();analyzeWhere(where, result);if (result.isExitReplaceStr()) {result.setReplaceSql(delete.toString());}return result;}private static AnalyzerResult analyzeUpdate(Update update) {List<Table> tables = update.getTables();if (tables.isEmpty()) {return AnalyzerResult.empty();}AnalyzerResult result = new AnalyzerResult(tables.get(FIRST));List<Column> columns = update.getColumns();List<Expression> expressions = update.getExpressions();result.putResults(columns, expressions);Expression where = update.getWhere();analyzeWhere(where, result);if (result.isExitReplaceStr()) {result.setReplaceSql(update.toString());}return result;}private static AnalyzerResult analyzeSelect(Select select) {PlainSelect plainSelect = (PlainSelect) select.getSelectBody();// 分析表达式AnalyzerResult result = new AnalyzerResult((Table) plainSelect.getFromItem());analyzeWhere(plainSelect.getWhere(), result);// 替换sqlif (result.isExitReplaceStr()) {result.setReplaceSql(plainSelect.toString());}return result;}private static void analyzeWhere(Expression expression, AnalyzerResult result) {if (null == expression) {return;}// 正常xxx xxx xxxif (expression instanceof BinaryExpression) {BinaryExpression binaryExpression = (BinaryExpression) expression;Expression leftExpression = binaryExpression.getLeftExpression();Expression rightExpression = binaryExpression.getRightExpression();boolean isColumn = leftExpression instanceof Column;boolean isString = rightExpression instanceof StringValue;boolean isJdbc = rightExpression instanceof JdbcParameter;boolean isValue = isString || isJdbc;if (isColumn && isValue) {Column column = (Column) leftExpression;boolean isLike = expression instanceof LikeExpression;result.putResult(column, rightExpression, isLike);} else {analyzeWhere(leftExpression, result);analyzeWhere(rightExpression, result);}// in查询} else if (expression instanceof InExpression) {InExpression binaryExpression = (InExpression) expression;Expression leftExpression = binaryExpression.getLeftExpression();ItemsList rightItemsList = binaryExpression.getRightItemsList();ItemsList leftItemsList = binaryExpression.getLeftItemsList();if (leftExpression instanceof Column) {Column column = (Column) leftExpression;boolean isInValue = false;ExpressionList expressionList = null;if (rightItemsList instanceof ExpressionList) {isInValue = true;expressionList = (ExpressionList) rightItemsList;} else if (leftItemsList instanceof ExpressionList) {isInValue = true;expressionList = (ExpressionList) leftItemsList;}if (isInValue) {result.putResults(column, expressionList.getExpressions());} else {if (rightItemsList instanceof Expression) {analyzeWhere((Expression) rightItemsList, result);}if (leftItemsList instanceof Expression) {analyzeWhere((Expression) leftItemsList, result);}}}// 子语句} else if (expression instanceof Parenthesis) {Parenthesis parenthesis = (Parenthesis) expression;Expression parenthesisExpression = parenthesis.getExpression();analyzeWhere(parenthesisExpression, result);// 子查询} else if (expression instanceof SubSelect) {SubSelect subSelect = (SubSelect) expression;PlainSelect selectBody = (PlainSelect) subSelect.getSelectBody();Expression where = selectBody.getWhere();analyzeWhere(where, result);// case when里面的when条件} else if (expression instanceof CaseExpression) {CaseExpression caseExpression = (CaseExpression) expression;List<WhenClause> whenClauses = caseExpression.getWhenClauses();if (ZYListUtils.isNotEmptyList(whenClauses)) {for (WhenClause whenClause : whenClauses) {Expression whenExpression = whenClause.getWhenExpression();analyzeWhere(whenExpression, result);}}} else {log.warn("not handle expression" + expression.getClass());}}}
@Data
public class AnalyzerResult {private boolean exitReplaceStr = false;private String replaceSql;private String tableName;private List<ColumnInfo> jdbcColumnInfos = new ArrayList<>();private List<ColumnInfo> signJdbcColumnInfos = new ArrayList<>();public AnalyzerResult(Table table) {this.tableName = table.getName();}public AnalyzerResult() {}public Set<Integer> getCryptIndexs() {Set<Integer> cryptIndexs = new HashSet<>();for (ColumnInfo jdbcColumnInfo : jdbcColumnInfos) {cryptIndexs.add(jdbcColumnInfo.getJdbcIndex());}return cryptIndexs;}public void putResults(Column column, List<Expression> expressions) {if (null != expressions) {for (Expression expression : expressions) {putResult(column, expression, false);}}}public void putResults(List<Column> columns, List<Expression> expressions) {if (ZYListUtils.isSingletonList(columns) || ZYListUtils.isEmptyList(expressions)) {return;}for (int i = 0; i < columns.size(); i++) {Column column = columns.get(i);Expression expression = expressions.get(i);this.putResult(column, expression);}}public void putResult(Column column, Expression expression) {putResult(column, expression, false);}public void putResult(Column column, Expression expression, boolean isLike) {if (SecurityColumnProviders.matchSecret(this.tableName, column)) {if (expression instanceof JdbcParameter) {JdbcParameter jdbcParameter = (JdbcParameter) expression;this.jdbcColumnInfos.add(new ColumnInfo(column, jdbcParameter));} else if (expression instanceof StringValue) {this.setExitReplace();toReplaceString((StringValue) expression, isLike);}}if (SecurityColumnProviders.matchSign(this.tableName, column)) {if (expression instanceof JdbcParameter) {JdbcParameter jdbcParameter = (JdbcParameter) expression;this.signJdbcColumnInfos.add(new ColumnInfo(column, jdbcParameter));}}}private void toReplaceString(StringValue rightExpression, boolean isLike) {String value = rightExpression.getValue();if (ZYStrUtils.isNull(value)) {return;}SecretProviders secretProviders = ZYSpringUtils.getBean(SecretProviders.class);if (null == secretProviders) {throw new LocalException("secretProviders is null");}if (isLike && value.startsWith("%") && value.endsWith("%")) {String valueItem = value.substring(1, value.length() - 2);String encryptValue = secretProviders.encrypt(valueItem);rightExpression.setValue("%" + encryptValue + "%");} else {rightExpression.setValue(secretProviders.encrypt(value));}}private void setExitReplace() {this.exitReplaceStr = true;}public static AnalyzerResult empty() {return new AnalyzerResult();}
}