package org.quickbundle.tools.helper; import java.io.File; import java.lang.reflect.Array; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.regex.Pattern; import org.quickbundle.ICoreConstants; import org.quickbundle.config.RmBaseConfig; public class RmSqlHelper { /** * NAME='张三' */ public final static int TYPE_CHAR_EQUAL = 0; /** * NAME like '%张三%' */ public final static int TYPE_CHAR_LIKE = 1; /** * NAME like '张三%' */ public final static int TYPE_CHAR_LIKE_START = 6; /** * AGE = 18 */ public final static int TYPE_NUMBER_EQUAL = 7; /** * AGE >= 18 */ public final static int TYPE_NUMBER_GREATER_EQUAL = 2; /** * AGE <= 18 */ public final static int TYPE_NUMBER_LESS_EQUAL = 3; /** * BIRTH >= 1990-01-01 */ public final static int TYPE_DATE_GREATER_EQUAL = 4; /** * BIRTH <= 1990-01-01 */ public final static int TYPE_DATE_LESS_EQUAL = 5; /** * 自定义类型 {int type(类型) [, String prefixValue(指定的查询值前缀), String affixValue(指定的查询值后缀)]} */ public final static int TYPE_CUSTOM = 99; /** * escape转义sql输入值,防止sql注入 * * @param inputValue 待转移的输入值 * @param type 类型 * @return 转义后的sql值 */ public static String escapeSqlValue(Object inputValue, int type) { if(inputValue == null) { return null; } String value = inputValue.toString(); switch (type) { //字符串和日期:转义',保证输入值在''中间,就是安全的 case TYPE_CHAR_EQUAL: case TYPE_CHAR_LIKE: case TYPE_CHAR_LIKE_START: case TYPE_DATE_GREATER_EQUAL: case TYPE_DATE_LESS_EQUAL : value = value.replaceAll("(['])", "'$1"); break; //数字:去掉空白类符号,就是安全的 case TYPE_NUMBER_EQUAL: case TYPE_NUMBER_GREATER_EQUAL: case TYPE_NUMBER_LESS_EQUAL: //空白符忽略 value = value.replaceAll("(\\s+)", ""); //疑似函数的一律忽略 value = value.replaceAll("([\\w_]+\\(.*\\))", ""); break; default: break; } return value; } /** * 构建SQL查询条件 * * @param columnName COLUMN的名称 * @param value 查询值 * @param type 数据库 * @param args {int type(类型) [, String prefixValue(指定的查询值前缀), String affixValue(指定的查询值后缀)]} * @return */ public static String buildQueryStr(String columnName, Object inputValue, Object... args) { int type = TYPE_CHAR_EQUAL; if(args.length > 0) { type = (Integer)args[0]; } String value = escapeSqlValue(inputValue, type); if(value != null && value.toString().length() > 0) { StringBuilder sb = new StringBuilder(); sb.append(columnName); sb.append(" "); switch (type) { case TYPE_CHAR_EQUAL: sb.append("= '"); sb.append(value); sb.append("'"); break; case TYPE_CHAR_LIKE: case TYPE_CHAR_LIKE_START: sb.append("like '"); if(type == TYPE_CHAR_LIKE) { //LIKE开头加%,而LIKE_START开头不加% sb.append("%"); } //如果value中含有%或_,对其转义 if(value.indexOf("%") > -1 || value.indexOf("_") > -1) { sb.append(value.replaceAll("([%_/])", "/$1")); sb.append("%'"); sb.append(" ESCAPE '/'"); } else { sb.append(value); sb.append("%'"); } break; case TYPE_NUMBER_EQUAL: sb.append("= "); sb.append(value); break; case TYPE_NUMBER_GREATER_EQUAL: sb.append(">= "); sb.append(value); break; case TYPE_NUMBER_LESS_EQUAL: sb.append("<= "); sb.append(value); break; case TYPE_DATE_GREATER_EQUAL: String dateStr1 = getSqlDateStr(value.toString()); if(dateStr1.length() == 0) { return ""; } sb.append(">= "); sb.append(dateStr1); break; case TYPE_DATE_LESS_EQUAL: if(value.toString().length() == 10) { value = value.toString() + " 23:59:59"; } String dateStr2 = getSqlDateStr(value.toString()); if(dateStr2.length() == 0) { return ""; } sb.append("<= "); sb.append(dateStr2); break; case TYPE_CUSTOM: sb.append(args[1]); sb.append(value); sb.append(args[2]); break; default: break; } return sb.toString(); } else { return ""; } } /** * 获得SQL中日期的查询字符串 * * @param value * @return */ public static String getSqlDateStr(Object value) { if(value == null || value.toString().trim().length() == 0) { return ""; } StringBuilder sb = new StringBuilder(); if(ICoreConstants.DatabaseProductType.ORACLE.getDatabaseProductName().equalsIgnoreCase(RmBaseConfig.getSingleton().getDatabaseProductName())) { String valueStr = value.toString().trim(); sb.append("to_date('"); switch (valueStr.length()) { case 4: //2010 sb.append(valueStr); sb.append("', 'YYYY')"); break; case 7: //2010-01 sb.append(valueStr); sb.append("', 'YYYY-MM')"); break; case 10: //2010-01-01 sb.append(valueStr); sb.append("', 'YYYY-MM-DD')"); break; case 19: //2010-01-01 01:01:01 sb.append(valueStr); sb.append("', 'YYYY-MM-DD HH24:MI:SS')"); break; case 23: //2010-01-01 01:01:01 001 sb.append(valueStr.substring(0, 19)); sb.append("', 'YYYY-MM-DD HH24:MI:SS')"); break; default: return ""; } } else { sb.append("'"); sb.append(value.toString().trim()); sb.append("'"); } return sb.toString(); } /** * 构建完整SQL查询片段,不带where * * @param aQueryStr 类似new String[]{"NAME like '%张三%'"}, {"AGE=18"} } * @return */ public static String appendQueryStr(String[] aQueryStr) { StringBuilder sb = new StringBuilder(); for (String queryStr : aQueryStr) { if(queryStr == null || queryStr.trim().length() == 0) { continue; } if (sb.length() == 0) { // 第一个条件不加and } else { sb.append(" and"); } sb.append(" "); sb.append(queryStr); } return sb.toString(); } /** * 从.sql文件中提取sql语句 * * @param sqlFile * @return */ public static String[] loadSql(String sqlFile) { String str = RmStringHelper.readStringFromFile(new File(sqlFile), RmBaseConfig.getSingleton().getDefaultEncode()); str = Pattern.compile("/\\*.*?\\*/", Pattern.DOTALL).matcher(str).replaceAll(""); str = Pattern.compile("^\\s*(#|\\-\\-).*", Pattern.MULTILINE).matcher(str).replaceAll(""); String[] aSql = Pattern.compile(";|(^\\s*/\\s*$)|(\\n\\s*go(\\s*\\n|$))", Pattern.MULTILINE|Pattern.CASE_INSENSITIVE).split(str); List<String> lSql = new ArrayList<String>(); for (int i = 0; i < aSql.length; i++) { if(aSql[i].trim().length() > 0) { lSql.add(Pattern.compile("^\\s*(.*?)\\s*$", Pattern.DOTALL|Pattern.MULTILINE).matcher(aSql[i]).replaceAll("$1")); } } return lSql.toArray(new String[0]); } public static String getSqlPage4Mysql(String strsql, int startIndex, int size) { return strsql + " limit " + (startIndex - 1) + "," + size; } public static String getSqlPage4Oracle(String strsql, int startIndex, int size) { return "select * from (select rownum as rmrn, a.* from(" + strsql + ") a where rownum<=" + (startIndex + size - 1) + ")where rmrn >=" + startIndex; } /** * 153ms-176ms select * from(select row_number() over(order by uid asc) as rownumber, * from moa_user ) as tb where rownumber between 100000 and 100200 156ms-210ms select top 200 * from(select row_number() over(order by uid asc) as rownumber,* from moa_user ) as tb where rownumber>100000 135ms select top 200 * FROM moa_user WHERE (uid > (SELECT MAX(uid) FROM (SELECT TOP 100000 uid FROM moa_user ORDER BY uid) AS temp_moa_user)) ORDER BY uid 270ms-290ms select top 200 * from moa_user a where uid not in(select top 100000 uid from moa_user b order by uid) 950ms select * from ( select top 200 * from ( select TOP 100000 * from moa_user order by uid) as amoaUser ORDER BY uid DESC ) as bmoaUser ORDER BY uid ASC * * @param strsql * @param startIndex * @param size * @return */ static String getSqlPage4Sqlserver(String strsql, int startIndex, int size) { return null; } /** * 得到数据库常用函数 * @param func 函数名枚举值 * @param databaseProductName 数据库名称 * @param args 可选的参数列表 * @return */ public static String getFunction(Function func, String databaseProductName, Object... args) { if(ICoreConstants.DatabaseProductType.MYSQL.getDatabaseProductName().equals(databaseProductName)) { return getFunctionMysql(func, args); } else if(ICoreConstants.DatabaseProductType.ORACLE.getDatabaseProductName().equals(databaseProductName)) { return getFunctionOracle(func, args); } else if(ICoreConstants.DatabaseProductType.SQLSERVER.getDatabaseProductName().equals(databaseProductName)) { return getFunctionSqlserver(func, args); } return null; } /** * 常用函数名枚举 */ public enum Function { TO_NUMBER, TO_CHAR, SYSDATE, LENGTH, SUBSTR, NVL, CONCAT, WM_CONCAT } static String getFunctionOracle(Function func, Object... args) { StringBuilder result = new StringBuilder(); if(Function.TO_NUMBER.name().equals(func.name())) { result.append("to_number("); result.append(args[0]); result.append(")"); return result.toString(); } else if(Function.TO_CHAR.name().equals(func.name())) { result.append("to_char("); result.append(args[0]); result.append(")"); return result.toString(); } else if(Function.SYSDATE.name().equals(func.name())) { return "sysdate"; } else if(Function.LENGTH.name().equals(func.name())) { return "length"; } else if(Function.SUBSTR.name().equals(func.name())) { return "substr"; } else if(Function.NVL.name().equals(func.name())) { return "nvl"; } else if(Function.CONCAT.name().equals(func.name())) { for(int i=0; args!=null && i<args.length; i++) { if(i > 0) { result.append("||"); } result.append(args[i]); } return result.toString(); } else if(Function.WM_CONCAT.name().equals(func.name())) { return "wm_concat"; } return null; } static String getFunctionMysql(Function func, Object... args) { StringBuilder result = new StringBuilder(); if(Function.TO_NUMBER.name().equals(func.name())) { result.append("cast("); result.append(args[0]); result.append(" as signed integer)"); return result.toString(); } else if(Function.TO_CHAR.name().equals(func.name())) { result.append("cast("); result.append(args[0]); result.append(" as char)"); return result.toString(); } else if(Function.SYSDATE.name().equals(func.name())) { return "sysdate()"; } else if(Function.LENGTH.name().equals(func.name())) { return "length"; } else if(Function.SUBSTR.name().equals(func.name())) { return "substring"; } else if(Function.NVL.name().equals(func.name())) { return "ifnull"; } else if(Function.CONCAT.name().equals(func.name())) { result.append("concat("); for(int i=0; args!=null && i<args.length; i++) { if(i > 0) { result.append(","); } result.append(args[i]); } result.append(")"); return result.toString(); } else if(Function.WM_CONCAT.name().equals(func.name())) { return "group_concat"; } return null; } static String getFunctionSqlserver(Function func, Object... args) { StringBuilder result = new StringBuilder(); if(Function.TO_NUMBER.name().equals(func.name())) { result.append("cast("); result.append(args[0]); result.append(" as decimal(30,2))"); return result.toString(); } else if(Function.TO_CHAR.name().equals(func.name())) { result.append("cast("); result.append(args[0]); result.append(" as char)"); return result.toString(); } else if(Function.SYSDATE.name().equals(func.name())) { return "getdate()"; } else if(Function.LENGTH.name().equals(func.name())) { return "len"; } else if(Function.SUBSTR.name().equals(func.name())) { return "substring"; } else if(Function.NVL.name().equals(func.name())) { return "isnull"; } else if(Function.CONCAT.name().equals(func.name())) { for(int i=0; args!=null && i<args.length; i++) { if(i > 0) { result.append("+"); } result.append(args[i]); } return result.toString(); } else if(Function.WM_CONCAT.name().equals(func.name())) { return "group_concat"; } return null; } @SuppressWarnings("unchecked") public static<T> List<T[]> splitPagingArray(T[] array, int maxSqlInCount) { if(array == null) { return null; } List<T[]> result = new ArrayList<T[]>(); int position = 0; while(position < array.length) { int end = position + maxSqlInCount; if(end > array.length) { end = array.length; } T[] split = copyOfRange(array, position, end, (Class<T[]>)array.getClass()); result.add(split); position += maxSqlInCount; } return result; } @SuppressWarnings("unchecked") public static <T,U> T[] copyOfRange(U[] original, int from, int to, Class<? extends T[]> newType) { int newLength = to - from; if (newLength < 0) throw new IllegalArgumentException(from + " > " + to); T[] copy = ((Object)newType == (Object)Object[].class) ? (T[]) new Object[newLength] : (T[]) Array.newInstance(newType.getComponentType(), newLength); System.arraycopy(original, from, copy, 0, Math.min(original.length - from, newLength)); return copy; } public static void main(String[] args) { List<String> lvo = new ArrayList<String>(); for(int i=1; i<=1000; i++) { lvo.add(i + ""); } System.out.println(lvo); List<String[]> result = splitPagingArray(lvo.toArray(new String[0]), 100); for(String[] array : result) { System.out.println(Arrays.deepToString(array)); } } }