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}