¶Ô±ÈÐÂÎļþ |
| | |
| | | package com.product.server.report.util; |
| | | |
| | | import com.alibaba.fastjson.JSONObject; |
| | | import com.google.common.collect.Lists; |
| | | import com.google.common.collect.Sets; |
| | | import com.product.core.dao.BaseDao; |
| | | import com.product.core.entity.DataTableEntity; |
| | | import com.product.core.entity.FieldSetEntity; |
| | | import com.product.core.exception.BaseException; |
| | | import com.product.data.config.ErrorCode; |
| | | import com.product.datasource.config.DataBaseType; |
| | | import com.product.datasource.dao.Dao; |
| | | import com.product.server.report.config.CmnConst; |
| | | import com.product.server.report.config.SystemCode; |
| | | import com.product.util.BaseUtil; |
| | | import org.apache.commons.lang3.StringUtils; |
| | | |
| | | import java.util.*; |
| | | |
| | | public class QuerySqlParseUtil { |
| | | |
| | | /** |
| | | * è·åä¸è¡¨ç¸å
³ç年表 SQLè¿æ»¤æ¡ä»¶ |
| | | * |
| | | * @param tableNames è¡¨åæ°ç» |
| | | * @return |
| | | */ |
| | | public static String getTableOfYearSQLFilter(Object[] tableNames) { |
| | | StringBuilder tableFilter = new StringBuilder(); |
| | | for (int i = 0; i < tableNames.length; i++) { |
| | | String tableName = (String) tableNames[i]; |
| | | if (!BaseUtil.strIsNull(tableName)) { |
| | | if (i > 0) { |
| | | tableFilter.append(" AND "); |
| | | } else { |
| | | tableFilter.append(" WHERE "); |
| | | } |
| | | tableFilter.append("table_name LIKE ?"); |
| | | } else { |
| | | throw new BaseException("", ""); |
| | | } |
| | | } |
| | | return tableFilter.toString(); |
| | | } |
| | | |
| | | /** |
| | | * çæéæ±SQL |
| | | * å¤çï¼å°ææå¹´è¡¨èåï¼çæä¸´æ¶æ¥è¯¢SQL |
| | | * æ¡ä¾ï¼WITH tableName1 AS (SELECT field1,field2... FROM tableName1_2022 UNION ALL SELECT field1,field2... FROM tableName1_2023), |
| | | * tableName2 AS (SELECT field3,field4... FROM tableName2_2022 UNION ALL SELECT field3,field4... FROM tableName2_2023) |
| | | * |
| | | * @param tableNames è¡¨åæ°ç» |
| | | * @param dtYearTable 表åä¸å¹´è¡¨åé |
| | | * @return |
| | | */ |
| | | public static String createFinalQuerySQL(Object[] tableNames, DataTableEntity dtYearTable) { |
| | | StringBuilder tableFilter = new StringBuilder(); |
| | | JSONObject jsonTableAndYear = convertJson(dtYearTable); |
| | | StringBuilder withSql = new StringBuilder(); |
| | | for (int i = 0; i < tableNames.length; i++) { |
| | | String tableName = (String) tableNames[i]; |
| | | String tableYear = (String) jsonTableAndYear.get(tableName); |
| | | if (!BaseUtil.strIsNull(tableYear)) { |
| | | if (i == 0) { |
| | | withSql.append(" WITH "); |
| | | } |
| | | withSql.append(tableName); |
| | | withSql.append(" AS("); |
| | | String[] tableYears = tableYear.split(","); |
| | | if (tableYear.length() > 1) { |
| | | for (int j = 0; j < tableYears.length; j++) { |
| | | withSql.append(" SELECT * FROM "); |
| | | withSql.append(tableYears[j]); |
| | | if (j < tableYears.length - 1) { |
| | | withSql.append(" UNION ALL "); |
| | | } |
| | | } |
| | | } else { |
| | | withSql.append(" SELECT * FROM "); |
| | | withSql.append(tableYears[0]); |
| | | } |
| | | withSql.append("),"); |
| | | } |
| | | } |
| | | if (tableFilter.toString().endsWith(",")) { |
| | | tableFilter.toString().substring(0, tableFilter.toString().length() - 1); |
| | | } |
| | | |
| | | return tableFilter.toString(); |
| | | } |
| | | |
| | | /** |
| | | * DataTableEntity 转 JSONObject |
| | | * JSONObject<表å,"表å_2022,表å_2023,表å_2024..."> |
| | | * |
| | | * @param dtYearTable |
| | | * @return |
| | | */ |
| | | public static JSONObject convertJson(DataTableEntity dtYearTable) { |
| | | JSONObject jsonTableAndYear = new JSONObject(); |
| | | for (int i = 0; i < dtYearTable.getRows(); i++) { |
| | | FieldSetEntity fseYearTable = dtYearTable.getFieldSetEntity(i); |
| | | String tableName = fseYearTable.getString(CmnConst.TABLE_NAME); |
| | | String tableYear = fseYearTable.getString("table_year"); |
| | | jsonTableAndYear.put(tableName, tableYear); |
| | | } |
| | | return jsonTableAndYear; |
| | | } |
| | | |
| | | /** |
| | | * è·åmysqlåºææè¡¨åï¼ä¾å¦ï¼ç»è¡¨åtestï¼è·åæ°æ®åºä¸ææçtest年份å表ï¼test_2019ï¼test_2020... |
| | | * |
| | | * @param dao |
| | | * @param dbName æ°æ®åºåç§° |
| | | * @param tableName 表å |
| | | * @return |
| | | */ |
| | | public static Set<String> getAllTableName(Dao dao, String dbName, String tableName) { |
| | | return getAllTableName(dao, null, dbName, tableName); |
| | | } |
| | | |
| | | public static Set<String> getAllTableName(BaseDao baseDao, String dbName, String tableName) { |
| | | return getAllTableName(null, baseDao, dbName, tableName); |
| | | } |
| | | |
| | | private static Set<String> getAllTableName(Dao dao, BaseDao baseDao, String dbName, String tableName) { |
| | | if (dao != null && !DataBaseType.MYSQL.equals(dao.getDataBaseType())) { |
| | | throw new BaseException(ErrorCode.NONSUPPORT_DATABASE_TYPE); |
| | | } |
| | | String sql = "select table_name from information_schema.`TABLES` where table_schema=? and table_name like concat(?,'%') order by table_name"; |
| | | DataTableEntity dte = new DataTableEntity(); |
| | | if (dao != null) { |
| | | dte = dao.getList(sql, new Object[]{dbName, tableName}); |
| | | } |
| | | if (baseDao != null) { |
| | | dte = baseDao.listTable(sql, new Object[]{dbName, tableName}); |
| | | } |
| | | Set<String> set = Sets.newLinkedHashSet(); |
| | | FieldSetEntity fse; |
| | | String curtableName; |
| | | for (int i = 0; i < dte.getRows(); i++) { |
| | | fse = dte.getFieldSetEntity(i); |
| | | curtableName = StringUtils.isEmpty(fse.getString("TABLE_NAME")) ? fse.getString("table_name") : fse.getString("TABLE_NAME"); |
| | | if (curtableName.matches(tableName + "_?\\d{4,6}")) { |
| | | set.add(curtableName); |
| | | } |
| | | } |
| | | return set; |
| | | } |
| | | |
| | | /** |
| | | * mysql-è·åwithèå表æ¥è¯¢sql |
| | | * |
| | | * @param tableAlias 表å«åï¼withä¹åçé£ä¸ª |
| | | * @param tableCollection å表éåï¼ä¾å¦å¹´ä»½å表ï¼å°±æ¯å¤ä¸ªå¹´ä»½è¡¨çéå |
| | | * @param fieldCollection æ¥è¯¢å段éåï¼æ²¡æå¯ä»¥ç´æ¥ç»nullï¼ä¼é»è®¤æ¥è¯¢ææå段ãç¹æ®ï¼è¥æ¯è¦æ¥è¯¢å½å表åï¼é£ä¹å段å为â{#table_name#}âï¼ä¹åçå«å为â_table_nameâ |
| | | * ä¹å°±æ¯è¯´åè®¾åæ®µä¸º name,{#table_name#} 表å为test_tableï¼é£ä¹è§£æçsql为âselect name,'test_table' _table_name from test_tableâ |
| | | * @param onlyStructureFlag åªæ¥è¯¢ç»æçæ è¯ï¼è¥ä¸ºtrueï¼ååªæ¥è¯¢ç»æï¼å³ä¸ºwith table_alias as (select * from table_name_1 union all select * from table_name_2 limit 1) |
| | | * @param filter è¿æ»¤æ¡ä»¶ |
| | | * @param tableAliasAlias 表å«åçå«åï¼å½withåå卿¥è¯¢ç¸åçè¡¨ä½æ¯æ¡ä»¶ä¸åçæ¶å使ç¨è¡¨å«åçå«åä½ä¸ºwithåçå«å |
| | | * @return |
| | | */ |
| | | public static StringBuilder getUnionTableSql(String tableAlias, Collection<String> tableCollection, Collection<String> fieldCollection, boolean onlyStructureFlag, String filter, String tableAliasAlias) { |
| | | StringBuilder sql = new StringBuilder(128); |
| | | if (StringUtils.isEmpty(tableAlias) || tableCollection == null || tableCollection.isEmpty()) { |
| | | return sql; |
| | | } |
| | | StringBuilder content = new StringBuilder(128); |
| | | tableCollection.forEach(tableName -> { |
| | | if (content.length() > 0) { |
| | | content.append("\n union all"); |
| | | } |
| | | String fieldContent = "*"; |
| | | if (fieldCollection != null && !fieldCollection.isEmpty()) { |
| | | fieldContent = BaseUtil.collection2String(fieldCollection); |
| | | fieldContent = fieldContent.replace("{#table_name#}", "'" + tableName + "' _table_name"); |
| | | } |
| | | content.append("\n select ").append(fieldContent).append(" from ").append(tableName); |
| | | if (!StringUtils.isEmpty(filter) && !StringUtils.isEmpty(filter.trim())) { |
| | | content.append(" ").append(filter.replaceAll("\\s*\\n\\s*", " ")); |
| | | } |
| | | }); |
| | | sql.append(tableAliasAlias).append(" as (").append(content); |
| | | if (onlyStructureFlag) { |
| | | sql.append(" limit 1"); |
| | | } |
| | | sql.append("\n)"); |
| | | return sql; |
| | | } |
| | | |
| | | public static StringBuilder getUnionTableSql(String tableAlias, Collection<String> tableCollection, Collection<String> fieldCollection, boolean onlyStructureFlag, String filter) { |
| | | return getUnionTableSql(tableAlias, tableCollection, fieldCollection, onlyStructureFlag, filter, tableAlias); |
| | | } |
| | | |
| | | public static StringBuilder getUnionTableSql(String tableAlias, Collection<String> tableCollection, Collection<String> fieldCollection, boolean onlyStructureFlag) { |
| | | return getUnionTableSql(tableAlias, tableCollection, fieldCollection, onlyStructureFlag, null); |
| | | } |
| | | |
| | | public static StringBuilder getUnionTableSql(String tableAlias, Collection<String> tableCollection, Collection<String> fieldCollection) { |
| | | return getUnionTableSql(tableAlias, tableCollection, fieldCollection, false); |
| | | } |
| | | |
| | | /** |
| | | * mysql-è·åwithèå表æ¥è¯¢sql |
| | | * |
| | | * @param tableAlias 表å«åï¼withä¹åçé£ä¸ª |
| | | * @param tableCollection å表éåï¼ä¾å¦å¹´ä»½å表ï¼å°±æ¯å¤ä¸ªå¹´ä»½è¡¨çéå |
| | | * @return |
| | | */ |
| | | public static StringBuilder getUnionTableSql(String tableAlias, Collection<String> tableCollection) { |
| | | return getUnionTableSql(tableAlias, tableCollection, null); |
| | | } |
| | | |
| | | /** |
| | | * è§£æsqlä¸çå表ï¼å°å
¶è½¬å为withè¯å¥ï¼å
¶ç¬¦å·å
çå
容ä½ä¸ºè¡¨å«åä½¿ç¨ |
| | | * |
| | | * @param baseDao |
| | | * @param sql å¾
è§£æçsql |
| | | * @param year æ¥è¯¢æè¿çå¹´æ°ï¼0æè
è´æ°è¡¨ç¤ºææï¼æç
§å½å为第ä¸å¹´ï¼åªæ¥è¯¢å½å¹´ï¼åç»1ï¼æ¥è¯¢å½ååå»å¹´ï¼åç»2ï¼æ¥è¯¢å½å¹´ãå»å¹´ãåå¹´ï¼åç»3ï¼ä»¥æ¤ç±»æ¨... |
| | | * @param onlyStructureFlag åªæ¥è¯¢ç»æçæ è¯ï¼è¥ä¸ºtrueï¼ååªæ¥è¯¢ç»æï¼å³ä¸ºwith table_alias as (select * from table_name_1 union all select * from table_name_2 limit 1) |
| | | * @return |
| | | */ |
| | | public static String parseSplitTableSql(BaseDao baseDao, String sql, int year, boolean onlyStructureFlag) { |
| | | boolean allTableFlag = year <= 0; |
| | | StringBuilder parseSql = new StringBuilder(128); |
| | | String regexp = "\\[=((?!\\[=).)*=\\]"; |
| | | List<String> suitList = BaseUtil.getSuitContent(sql, regexp, true); |
| | | if (suitList.isEmpty()) { |
| | | return sql; |
| | | } else { |
| | | Set<String> suitSet = Sets.newLinkedHashSet(); |
| | | suitSet.addAll(suitList); |
| | | |
| | | // è·åéè¦ç年份 |
| | | List<String> yearList = Lists.newArrayList(); |
| | | if (!allTableFlag) { |
| | | Calendar c = Calendar.getInstance(); |
| | | for (int i = 0; i < year; i++) { |
| | | yearList.add(String.valueOf(c.get(Calendar.YEAR))); |
| | | c.add(Calendar.YEAR, -1); |
| | | } |
| | | } |
| | | // è·å对åºåå¨è¡¨ |
| | | String tableInfo; |
| | | String tableAlias;// 表å«åï¼æ¥è¯¢ç¨çåç¼ï¼é常withåçå«å |
| | | String tableAliasAlias;// 表å«åçå«åï¼å½withåå卿¥è¯¢ç¸åçè¡¨ä½æ¯æ¡ä»¶ä¸åçæ¶å使ç¨è¡¨å«åçå«åä½ä¸ºwithåçå«å |
| | | Set<String> allTableSet; |
| | | Set<String> needTableSet; |
| | | for (String suitContent : suitSet) { |
| | | Set<String> fieldSet = Sets.newLinkedHashSet(); |
| | | String filterInfo = null; |
| | | needTableSet = Sets.newLinkedHashSet(); |
| | | tableInfo = suitContent.replace("[=", "").replace("=]", "").trim(); |
| | | if (tableInfo.contains("{")) { |
| | | tableAlias = tableInfo.substring(tableInfo.indexOf("{") + 1, tableInfo.indexOf("}")); |
| | | if (tableAlias.contains(" ")) { |
| | | tableAliasAlias = tableAlias.substring(tableAlias.lastIndexOf(" ") + 1); |
| | | tableAlias = tableAlias.substring(0, tableAlias.indexOf(" ")); |
| | | } else { |
| | | tableAliasAlias = tableAlias; |
| | | } |
| | | int fromIndex = tableInfo.indexOf("}") + 1; |
| | | if (tableInfo.indexOf("{", fromIndex) > -1) { |
| | | String fieldInfo = tableInfo.substring(tableInfo.indexOf("{", fromIndex) + 1, tableInfo.indexOf("}", fromIndex)); |
| | | if (!StringUtils.isEmpty(fieldInfo)) { |
| | | fieldSet.addAll(Arrays.asList(fieldInfo.split(","))); |
| | | } |
| | | fromIndex = tableInfo.indexOf("}", fromIndex) + 1; |
| | | if (tableInfo.indexOf("{", fromIndex) > -1) { |
| | | filterInfo = tableInfo.substring(tableInfo.indexOf("{", fromIndex) + 1, tableInfo.lastIndexOf("}")); |
| | | } |
| | | } |
| | | } else { |
| | | tableAlias = tableInfo; |
| | | tableAliasAlias = tableAlias; |
| | | } |
| | | sql = sql.replace(suitContent, tableAliasAlias); |
| | | allTableSet = getAllTableName(baseDao, baseDao.getDataBaseName(), tableAlias); |
| | | if (allTableFlag) { |
| | | needTableSet = allTableSet; |
| | | } else { |
| | | if (!yearList.isEmpty()) { |
| | | StringBuilder regexpSb = new StringBuilder(64); |
| | | for (String yearStr : yearList) { |
| | | if (regexpSb.length() > 0) { |
| | | regexpSb.append("|"); |
| | | } |
| | | regexpSb.append(tableAlias).append("_").append(yearStr).append("\\d{0,2}"); |
| | | } |
| | | regexp = regexpSb.toString(); |
| | | for (String tableName : allTableSet) { |
| | | if (tableName.matches(regexp)) { |
| | | needTableSet.add(tableName); |
| | | } |
| | | } |
| | | } |
| | | } |
| | | // è·åsql |
| | | StringBuilder contentSb = getUnionTableSql(tableAlias, needTableSet, fieldSet, onlyStructureFlag, filterInfo, tableAliasAlias); |
| | | if (contentSb.length() > 0) { |
| | | if (parseSql.length() > 0) { |
| | | parseSql.append(","); |
| | | } |
| | | parseSql.append(contentSb); |
| | | } else { |
| | | throw new BaseException(SystemCode.NO_MATCH_TABLE.getValue(), SystemCode.NO_MATCH_TABLE.getText() + " table_name:" + tableAlias); |
| | | } |
| | | } |
| | | return new StringBuilder().append("with ").append(parseSql).append("\n").append(sql).toString(); |
| | | } |
| | | } |
| | | |
| | | public static String parseSplitTableSql(BaseDao baseDao, String sql, int year) { |
| | | return parseSplitTableSql(baseDao, sql, year, false); |
| | | } |
| | | |
| | | public static String parseSplitTableSql(BaseDao baseDao, String sql, boolean onlyStructureFlag) { |
| | | return parseSplitTableSql(baseDao, sql, 0, onlyStructureFlag); |
| | | } |
| | | |
| | | public static String parseSplitTableSql(BaseDao baseDao, String sql) { |
| | | return parseSplitTableSql(baseDao, sql, 0, false); |
| | | } |
| | | |
| | | |
| | | } |