/** * Copyright (c) 2011-2020, hubin (jobob@qq.com). * <p> * Licensed under the Apache License, Version 2.0 (the "License"); you may not * use this file except in compliance with the License. You may obtain a copy of * the License at * <p> * http://www.apache.org/licenses/LICENSE-2.0 * <p> * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the * License for the specific language governing permissions and limitations under * the License. */ package com.baomidou.mybatisplus.toolkit; import com.baomidou.mybatisplus.entity.CountOptimize; import com.baomidou.mybatisplus.enums.Optimize; import com.baomidou.mybatisplus.enums.SqlLike; import com.baomidou.mybatisplus.plugins.pagination.Pagination; /** * <p> * SqlUtils工具类 * </p> * * @author Caratacus * @Date 2016-11-13 */ public class SqlUtils { public static final String SQL_BASE_COUNT = "SELECT COUNT(1) FROM ( %s ) TOTAL"; private final static SqlFormatter sqlFormatter = new SqlFormatter(); /** * 获取CountOptimize * * @param originalSql * 需要计算Count SQL * @param optimizeType * count优化方式 * @param isOptimizeCount * 是否需要优化Count * @return CountOptimize */ public static CountOptimize getCountOptimize(String originalSql, String optimizeType, String dialectType, boolean isOptimizeCount) { CountOptimize countOptimize = CountOptimize.newInstance(); // 获取优化类型 Optimize opType = Optimize.getOptimizeType(optimizeType); // 调整SQL便于解析 String tempSql = originalSql.replaceAll("(?i)ORDER[\\s]+BY", "ORDER BY").replaceAll("(?i)GROUP[\\s]+BY", "GROUP BY"); String indexOfSql = tempSql.toUpperCase(); // 有排序情况 int orderByIndex = indexOfSql.lastIndexOf("ORDER BY"); // 只针对 ALI_DRUID DEFAULT 这2种情况 if (orderByIndex > -1) { countOptimize.setOrderBy(false); } if (!isOptimizeCount && opType.equals(Optimize.DEFAULT)) { countOptimize.setCountSQL(String.format(SQL_BASE_COUNT, originalSql)); return countOptimize; } switch (opType) { case ALI_DRUID: /** * 调用ali druid方式 插件dbType一定要设置为小写与JdbcConstants保持一致 * * @see com.alibaba.druid.util.JdbcConstants */ String aliCountSql = DruidUtils.count(originalSql, dialectType); countOptimize.setCountSQL(aliCountSql); break; case JSQLPARSER: /** * 调用JsqlParser方式 */ JsqlParserUtils.jsqlparserCount(countOptimize, originalSql); break; default: StringBuilder countSql = new StringBuilder("SELECT COUNT(1) "); boolean optimize = false; if (!indexOfSql.contains("DISTINCT") && !indexOfSql.contains("GROUP BY")) { int formIndex = indexOfSql.indexOf("FROM"); if (formIndex > -1) { if (orderByIndex > -1) { tempSql = tempSql.substring(0, orderByIndex); countSql.append(tempSql.substring(formIndex)); // 无排序情况 } else { countSql.append(tempSql.substring(formIndex)); } // 执行优化 optimize = true; } } if (!optimize) { // 无优化SQL countSql.append("FROM ( ").append(originalSql).append(" ) TOTAL"); } countOptimize.setCountSQL(countSql.toString()); } return countOptimize; } /** * 查询SQL拼接Order By * * @param originalSql * 需要拼接的SQL * @param page * page对象 * @param orderBy * 是否需要拼接Order By * @return */ public static String concatOrderBy(String originalSql, Pagination page, boolean orderBy) { if (orderBy && StringUtils.isNotEmpty(page.getOrderByField()) && page.isOpenSort()) { StringBuilder buildSql = new StringBuilder(originalSql); buildSql.append(" ORDER BY ").append(page.getOrderByField()); buildSql.append(page.isAsc() ? " ASC " : " DESC "); return buildSql.toString(); } return originalSql; } /** * 格式sql * * @param boundSql * @param format * @return */ public static String sqlFormat(String boundSql, boolean format) { if (format) { return sqlFormatter.format(boundSql); } else { return boundSql.replaceAll("[\\s]+", " "); } } /** * <p> * 用%连接like * </p> * * @param str * 原字符串 * @return */ public static String concatLike(String str, SqlLike type) { StringBuilder builder = new StringBuilder(str.length() + 3); switch (type) { case LEFT: builder.append("%").append(str); break; case RIGHT: builder.append(str).append("%"); break; case CUSTOM: builder.append(str); break; default: builder.append("%").append(str).append("%"); } return builder.toString(); } }