001package com.mybatisflex.core.dialect.impl; 002 003import static com.mybatisflex.core.constant.SqlConsts.DELIMITER; 004import static com.mybatisflex.core.constant.SqlConsts.NULLS_FIRST; 005import static com.mybatisflex.core.constant.SqlConsts.NULLS_LAST; 006import static com.mybatisflex.core.constant.SqlConsts.ORDER_BY; 007import java.util.List; 008import java.util.regex.Matcher; 009import java.util.regex.Pattern; 010import com.mybatisflex.core.dialect.KeywordWrap; 011import com.mybatisflex.core.dialect.LimitOffsetProcessor; 012import com.mybatisflex.core.query.CPI; 013import com.mybatisflex.core.query.QueryOrderBy; 014import com.mybatisflex.core.query.QueryTable; 015import com.mybatisflex.core.query.QueryWrapper; 016 017public class DB2105Dialect extends CommonsDialectImpl { 018 //TODO: 根据DatabaseMetaData获取数据库厂商名和版本号 019 public static final String DB2_1005_PRODUCT_VERSION = "1005"; 020 public static final String DB2_PRODUCT_NAME = "DB2"; 021 private static final Pattern pattern = Pattern.compile("(\\S+)\\s+(\\S*)\\s*("+NULLS_FIRST.trim()+"|"+NULLS_LAST.trim()+")"); 022 023 024 public DB2105Dialect(KeywordWrap keywordWrap, LimitOffsetProcessor limitOffsetProcessor) { 025 super(keywordWrap, limitOffsetProcessor); 026 } 027 028 @Override 029 protected void buildOrderBySql(StringBuilder sqlBuilder, QueryWrapper queryWrapper, List<QueryTable> queryTables) { 030 List<QueryOrderBy> orderBys = CPI.getOrderBys(queryWrapper); 031 if (orderBys != null && !orderBys.isEmpty()) { 032 sqlBuilder.append(ORDER_BY); 033 int index = 0; 034 for (QueryOrderBy orderBy : orderBys) { 035 String orderBySql = orderBy.toSql(queryTables, this); 036 orderBySql = convertOderbySqlForDB2105(orderBySql); // 转换SQL语句 037 sqlBuilder.append(orderBySql); 038 if (index != orderBys.size() - 1) { 039 sqlBuilder.append(DELIMITER); 040 } 041 index++; 042 } 043 } 044 } 045 046 private String convertOderbySqlForDB2105(String sql) { 047 Matcher matcher = pattern.matcher(sql); 048 if (matcher.find()) { 049 String column = matcher.group(1); 050 String orderType = matcher.group(2); 051 String nullOrder = matcher.group(3); 052 if (NULLS_FIRST.trim().equals(nullOrder)) { 053 sql = "CASE WHEN " + column + " IS NULL THEN 0 ELSE 1 END, " + column+" "+orderType; 054 } else if (NULLS_LAST.trim().equals(nullOrder)) { 055 sql = "CASE WHEN " + column + " IS NULL THEN 1 ELSE 0 END, " + column+" "+orderType; 056 } 057 } 058 return sql; 059 } 060 061 062 public interface DB2105LimitOffsetProcessor { 063 LimitOffsetProcessor DB2105 = (dialect, sql, queryWrapper, limitRows, limitOffset) -> { 064 StringBuilder limitSqlFragment = new StringBuilder( 065 "select * from ( select u_.*,rownumber() over() as rn from ( "); 066 limitSqlFragment.append(sql); 067 limitSqlFragment.append(" )u_ ) temp_ where temp_.rn between "); 068 069 if (limitRows != null && limitOffset != null) { 070 limitSqlFragment.append(limitOffset + 1); 071 limitSqlFragment.append(" and "); 072 limitSqlFragment.append(limitRows + limitOffset); 073 } else if (limitRows != null) { 074 limitSqlFragment.append("1 and "); 075 limitSqlFragment.append(limitRows); 076 } else { 077 return sql; 078 } 079 return limitSqlFragment; 080 }; 081 } 082}