package com.ycsoft.report.query.sql; import java.io.Serializable; import java.util.ArrayList; import java.util.List; import java.util.regex.Matcher; import java.util.regex.Pattern; import com.ycsoft.commons.exception.ReportException; import com.ycsoft.report.bean.RepKeyCon; import com.ycsoft.report.commons.SystemConfig; import com.ycsoft.report.dto.RepKeyDto; import com.ycsoft.report.query.key.Impl.ConKeyValue; /** * sql拆分组装工厂 */ public class AnalyseSqlFactory implements Serializable{ /** * */ private static final long serialVersionUID = -6513684046350324826L; private String sql_splits[] = null; private String sql_groups[] = null; private final static String sql_regex = "[\\s\\)]+([oO][rR]|[aA][nN][dD]|[wW][hH][eE][rR][eE])\\s+([nN][oO][tT]\\s)?\\s*[eE][xX][iI][sS][tT][sS][\\s\\(]+|[\\s\\)]+([oO][rR]|[aA][nN][dD]|[wW][hH][eE][rR][eE]|[gG][rR][oO][uU][pP]|[oO][rR][dD][eE][rR]|[uU][nN][iI][oO][nN]|[bB][eE][tT][wW][eE][eE][nN])[\\s\\(]+"; private final static String sql_regex_where = "\\)[^,]*,[\\s\\(]*"; public AnalyseSqlFactory(String sql) throws ReportException{ init(sql); } public void init2(String sql) throws ReportException{ Pattern p = Pattern.compile(sql_regex); // 正则表达式拆分sql sql_splits = p.split(sql); // 定义拆分关键字的数组 sql_groups = new String[sql_splits.length - 1]; Matcher m = p.matcher(sql); int between_index = 0; // 初始化拆分关键字 for (; m.find(); between_index++) { if (between_index >= sql_splits.length - 1) throw new ReportException( "sql_regex_pattern_matcher_error_more.", sql); sql_groups[between_index] = m.group(); } if (between_index != sql_splits.length - 1) throw new ReportException("sql_regex_pattern_matcher_error_less.", sql); //分析'('和')'的数量 // 第一个和最后一个分组不需要分析 for (int i = 1; i < sql_splits.length - 1; i++) { char[] group_char = sql_splits[i].toCharArray(); int right = 0;// (的数量 int left = 0; // )的数量 for (char c : group_char) { if (c == '(') right++; if (c == ')') left++; } // 检测')'数量 for (int a = 0; a < right - left; a++) { int kuohao = sql_groups[i].indexOf(')'); if (kuohao > -1) { sql_splits[i] = sql_splits[i] + sql_groups[i].substring(0,kuohao+1); sql_groups[i] = sql_groups[i].substring(kuohao + 1); //sql_splits[i] = sql_splits[i] + ")"; } } // 检测'('数量 for (int a = 0; a < left - right; a++) { int kuohao = sql_groups[i - 1].lastIndexOf('('); if (kuohao > -1) { sql_splits[i] = sql_groups[i - 1].substring(kuohao) + sql_splits[i]; sql_groups[i - 1] = sql_groups[i - 1].substring(0, kuohao); } } } // 分析拆分关键字,如果是between则按对应的and重组sql_group和sql_between List<String> sql_group_list = new ArrayList<String>( sql_splits.length + 1); List<String> sql_split_list = new ArrayList<String>( sql_splits.length + 1); for (int i = 0; i < sql_groups.length; i++) { String sql_group = sql_groups[i].toUpperCase(); if (sql_group.indexOf("BETWEEN") > -1) { sql_group = sql_groups[i + 1].toUpperCase(); if (sql_group.indexOf("AND") < 0) throw new ReportException("between_and error.", sql); sql_split_list.add(sql_splits[i] + sql_groups[i] + sql_splits[i + 1] + sql_groups[i + 1] + sql_splits[i + 2]); i = i + 2; if (i < sql_groups.length) { sql_group_list.add(sql_groups[i]); } if (i == sql_groups.length - 1) { sql_split_list.add(sql_splits[i + 1]); } } else { sql_group_list.add(sql_groups[i]); sql_split_list.add(sql_splits[i]); if (i == sql_groups.length - 1) sql_split_list.add(sql_splits[i + 1]); } } if (sql_split_list.size() != sql_group_list.size() + 1) throw new ReportException("sql_split_and_group_error.", sql); sql_groups = new String[sql_group_list.size()]; sql_group_list.toArray(sql_groups); sql_splits = new String[sql_split_list.size()]; sql_split_list.toArray(sql_splits); } public void init(String sql) throws ReportException { Pattern p = Pattern.compile(sql_regex); // 正则表达式拆分sql sql_splits = p.split(sql); // 定义拆分关键字的数组 sql_groups = new String[sql_splits.length - 1]; Matcher m = p.matcher(sql); int between_index = 0; // 初始化拆分关键字 for (; m.find(); between_index++) { if (between_index >= sql_splits.length - 1) throw new ReportException( "sql_regex_pattern_matcher_error_more.", sql); sql_groups[between_index] = m.group(); } if (between_index != sql_splits.length - 1) throw new ReportException("sql_regex_pattern_matcher_error_less.", sql); // 分析where 前对应语句 用 ,号拆分 // 处理子查询可能会出现的问题 List<String> group_list = new ArrayList<String>(sql_splits.length + 1); List<String> split_list = new ArrayList<String>(sql_splits.length + 1); p = Pattern.compile(sql_regex_where); for (int i = 0; i < sql_groups.length; i++) { if (sql_groups[i].toUpperCase().indexOf("WHERE") > -1) { String sql_where_splits[] = p.split(sql_splits[i]); for (String sql_where_split : sql_where_splits) split_list.add(sql_where_split); m = p.matcher(sql_splits[i]); while (m.find()) group_list.add(m.group()); group_list.add(sql_groups[i]); } else { split_list.add(sql_splits[i]); group_list.add(sql_groups[i]); } if (i == sql_groups.length - 1) split_list.add(sql_splits[i + 1]); } //无查询条件不进行特殊化处理 if(split_list.size()==0&&group_list.size()==0){ return; } if (split_list.size() != group_list.size() + 1) throw new ReportException("sql_regex_pattern_matcher_error_less.", sql); sql_splits = new String[split_list.size()]; sql_groups = new String[group_list.size()]; split_list.toArray(sql_splits); group_list.toArray(sql_groups); // 分析拆分的字段租中的(和)的数量,确定拆分关键字和字段组是否需要重组 // 第一个和最后一个分组不需要分析 for (int i = 1; i < sql_splits.length - 1; i++) { char[] group_char = sql_splits[i].toCharArray(); int right = 0;// (的数量 int left = 0; // )的数量 for (char c : group_char) { if (c == '(') right++; if (c == ')') left++; } // 检测')'数量 for (int a = 0; a < right - left; a++) { int kuohao = sql_groups[i].indexOf(')'); if (kuohao > -1) { sql_splits[i] = sql_splits[i] + sql_groups[i].substring(0,kuohao+1); sql_groups[i] = sql_groups[i].substring(kuohao + 1); //sql_splits[i] = sql_splits[i] + ")"; } } // 检测'('数量 for (int a = 0; a < left - right; a++) { int kuohao = sql_groups[i - 1].lastIndexOf('('); if (kuohao > -1) { sql_splits[i] = sql_groups[i - 1].substring(kuohao) + sql_splits[i]; sql_groups[i - 1] = sql_groups[i - 1].substring(0, kuohao); } } } // 分析拆分关键字,如果是between则按对应的and重组sql_group和sql_between List<String> sql_group_list = new ArrayList<String>( sql_splits.length + 1); List<String> sql_split_list = new ArrayList<String>( sql_splits.length + 1); for (int i = 0; i < sql_groups.length; i++) { String sql_group = sql_groups[i].toUpperCase(); if (sql_group.indexOf("BETWEEN") > -1) { sql_group = sql_groups[i + 1].toUpperCase(); if (sql_group.indexOf("AND") < 0) throw new ReportException("between_and error.", sql); sql_split_list.add(sql_splits[i] + sql_groups[i] + sql_splits[i + 1] + sql_groups[i + 1] + sql_splits[i + 2]); i = i + 2; if (i < sql_groups.length) { sql_group_list.add(sql_groups[i]); } if (i == sql_groups.length - 1) { sql_split_list.add(sql_splits[i + 1]); } } else { sql_group_list.add(sql_groups[i]); sql_split_list.add(sql_splits[i]); if (i == sql_groups.length - 1) sql_split_list.add(sql_splits[i + 1]); } } if (sql_split_list.size() != sql_group_list.size() + 1) throw new ReportException("sql_split_and_group_error.", sql); sql_groups = new String[sql_group_list.size()]; sql_group_list.toArray(sql_groups); sql_splits = new String[sql_split_list.size()]; sql_split_list.toArray(sql_splits); } /** * 获得用页面传入值填充的sql * @param keylist * @return * @throws ReportException */ public String getAnaSql(List<ConKeyValue> keylist) throws ReportException { if(keylist==null) return getFormatSql(); String sql_splits_temp[] = new String[this.sql_splits.length]; System.arraycopy(this.sql_splits, 0, sql_splits_temp, 0, this.sql_splits.length); for (ConKeyValue fitcon : keylist) { for (int i = 0; i < sql_splits_temp.length; i++) { if (sql_splits_temp[i] != null && sql_splits_temp[i].indexOf(fitcon.getKey()) > -1) { if (fitcon.getValue() == null || "".equals(fitcon.getValue())) sql_splits_temp[i] = " 1=1 "; else if("fileupload".equals(SystemConfig.getConMap().get(fitcon.getKey()).getHtmlcode())){ //文件组件上传数据格式 RepKeyCon keycon=SystemConfig.getConMap().get(fitcon.getKey()); sql_splits_temp[i] = sql_splits_temp[i].replaceAll( fitcon.getKey(), keycon.getValuesql().replaceAll(keycon.getKey(), fitcon.getValue())); }else if ("like".equals(SystemConfig.getConMap().get(fitcon.getKey()).getType())) { String[] like_values = fitcon.getValue().split(","); String sql_like = ""; for (int a = 0; a < like_values.length; a++) { sql_like = sql_like + (a == 0 ? " ( " : " or ") + sql_splits_temp[i].replaceAll(fitcon .getKey(), "%" + like_values[a].trim() + "%"); if (a == like_values.length - 1) sql_like = sql_like + " ) "; } sql_splits_temp[i] = sql_like; } else { sql_splits_temp[i] = sql_splits_temp[i].replaceAll( fitcon.getKey(), fitcon.getValue()); } } } } return this.getSql(sql_splits_temp, sql_groups); } private String getSql(String sql_splits[], String sql_groups[]) throws ReportException { if(sql_splits==null||sql_splits.length==0) throw new ReportException("sql is null"); StringBuffer sb = new StringBuffer(); for (int i = 0; i < sql_splits.length; i++) { sb.append(sql_splits[i]); if (i < sql_groups.length) sb.append(sql_groups[i]); } return sb.toString(); } /** * 获得原始sql格式后的sql * @return * @throws ReportException */ public String getFormatSql() throws ReportException { return getSql(this.sql_splits, this.sql_groups); } /** * 获得用测试值填充的sql * @param keylist * @return * @throws ReportException */ public String getTestSql() throws ReportException { String sql_splits_temp[] = new String[this.sql_splits.length]; System.arraycopy(this.sql_splits, 0, sql_splits_temp, 0, this.sql_splits.length); for (RepKeyCon fitcon : SystemConfig.getConList()) { for (int i = 0; i < sql_splits_temp.length; i++) { if (sql_splits_temp[i] != null && sql_splits_temp[i].indexOf(fitcon.getKey()) > -1) { if (fitcon.getTestvalue() == null || "".equals(fitcon.getTestvalue())) sql_splits_temp[i] = " 1=1 "; else if("fileupload".equals(fitcon.getHtmlcode())){ //文件组件上传数据格式 sql_splits_temp[i] = sql_splits_temp[i].replaceAll( fitcon.getKey(), fitcon.getValuesql().replaceAll(fitcon.getKey(), fitcon.getTestvalue())); }else if ("like".equals(fitcon.getType())) { String[] like_values = fitcon.getTestvalue().split(","); String sql_like = ""; for (int a = 0; a < like_values.length; a++) { sql_like = sql_like + (a == 0 ? " ( " : " or ") + sql_splits_temp[i].replaceAll(fitcon .getKey(), "%" + like_values[a].trim() + "%"); if (a == like_values.length - 1) sql_like = sql_like + " ) "; } sql_splits_temp[i] = sql_like; } else { sql_splits_temp[i] = sql_splits_temp[i].replaceAll( fitcon.getKey(), fitcon.getTestvalue()); } } } } return this.getSql(sql_splits_temp, sql_groups); } /** * cube明细查询组装sql * @param keylist * @return * @throws ReportException */ public String getCubeDetail(List<ConKeyValue> keylist) throws ReportException{ if(keylist==null) return getFormatSql(); String sql_splits_temp[] = new String[this.sql_splits.length]; System.arraycopy(this.sql_splits, 0, sql_splits_temp, 0, this.sql_splits.length); for (ConKeyValue fitcon : keylist) { for (int i = 0; i < sql_splits_temp.length; i++) { if (sql_splits_temp[i] != null && sql_splits_temp[i].indexOf(fitcon.getKey()) > -1) { if (fitcon.getValue() == null || "".equals(fitcon.getValue())) sql_splits_temp[i] = " 1=1 "; else { sql_splits_temp[i] = sql_splits_temp[i].replaceAll( fitcon.getKey(), fitcon.getValue()); } } } } return this.getSql(sql_splits_temp, sql_groups); } }