001/** 002 * Copyright (c) 2022-2023, Mybatis-Flex (fuhai999@gmail.com). 003 * <p> 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * <p> 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * <p> 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016package com.mybatisflex.core.dialect; 017 018import com.mybatisflex.core.query.CPI; 019import com.mybatisflex.core.query.QueryOrderBy; 020import com.mybatisflex.core.query.QueryWrapper; 021import com.mybatisflex.core.util.CollectionUtil; 022 023import java.util.List; 024 025/** 026 * limit 和 offset 参数的处理器 027 */ 028public interface LimitOffsetProcessor { 029 030 /** 031 * MySql 的处理器 032 * 适合 {@link DbType#MYSQL,DbType#MARIADB,DbType#H2,DbType#CLICK_HOUSE,DbType#XCloud} 033 */ 034 LimitOffsetProcessor MYSQL = (sql, queryWrapper, limitRows, limitOffset) -> { 035 if (limitRows != null && limitOffset != null) { 036 sql.append(" LIMIT ").append(limitOffset).append(", ").append(limitRows); 037 } else if (limitRows != null) { 038 sql.append(" LIMIT ").append(limitRows); 039 } 040 return sql; 041 }; 042 043 /** 044 * Postgresql 的处理器 045 * 适合 {@link DbType#POSTGRE_SQL,DbType#SQLITE,DbType#H2,DbType#HSQL,DbType#KINGBASE_ES,DbType#PHOENIX} 046 * 适合 {@link DbType#SAP_HANA,DbType#IMPALA,DbType#HIGH_GO,DbType#VERTICA,DbType#REDSHIFT} 047 * 适合 {@link DbType#OPENGAUSS,DbType#TDENGINE,DbType#UXDB} 048 */ 049 LimitOffsetProcessor POSTGRESQL = (sql, queryWrapper, limitRows, limitOffset) -> { 050 if (limitRows != null && limitOffset != null) { 051 sql.append(" LIMIT ").append(limitRows).append(" OFFSET ").append(limitOffset); 052 } else if (limitRows != null) { 053 sql.append(" LIMIT ").append(limitRows); 054 } 055 return sql; 056 }; 057 058 /** 059 * derby 的处理器 060 * 适合 {@link DbType#DERBY,DbType#ORACLE_12C,DbType#SQLSERVER ,DbType#POSTGRE_SQL} 061 */ 062 LimitOffsetProcessor DERBY = (sql, queryWrapper, limitRows, limitOffset) -> { 063 if (limitRows != null && limitOffset != null) { 064 // OFFSET ** ROWS FETCH NEXT ** ROWS ONLY") 065 sql.append(" OFFSET ").append(limitOffset).append(" ROWS FETCH NEXT ").append(limitRows).append(" ROWS ONLY"); 066 } else if (limitRows != null) { 067 sql.append(" OFFSET 0 ROWS FETCH NEXT ").append(limitRows).append(" ROWS ONLY"); 068 } 069 return sql; 070 }; 071 072 /** 073 * derby 的处理器 074 * 适合 {@link DbType#DERBY,DbType#ORACLE_12C,DbType#SQLSERVER ,DbType#POSTGRE_SQL} 075 */ 076 LimitOffsetProcessor SQLSERVER = (sql, queryWrapper, limitRows, limitOffset) -> { 077 if (limitRows != null && limitOffset != null) { 078 // OFFSET ** ROWS FETCH NEXT ** ROWS ONLY") 079 sql.append(" OFFSET ").append(limitOffset).append(" ROWS FETCH NEXT ").append(limitRows).append(" ROWS ONLY"); 080 } else if (limitRows != null) { 081 List<QueryOrderBy> orderBys = CPI.getOrderBys(queryWrapper); 082 if (CollectionUtil.isNotEmpty(orderBys)) { 083 sql.append(" OFFSET 0 ROWS FETCH NEXT ").append(limitRows).append(" ROWS ONLY"); 084 } else { 085 sql.insert(6, " TOP " + limitRows); 086 } 087 } 088 return sql; 089 }; 090 091 092 /** 093 * Informix 的处理器 094 * 适合 {@link DbType#INFORMIX} 095 * 文档 {@link <a href="https://www.ibm.com/docs/en/informix-servers/14.10?topic=clause-restricting-return-values-skip-limit-first-options">https://www.ibm.com/docs/en/informix-servers/14.10?topic=clause-restricting-return-values-skip-limit-first-options</a>} 096 */ 097 LimitOffsetProcessor INFORMIX = (sql, queryWrapper, limitRows, limitOffset) -> { 098 if (limitRows != null && limitOffset != null) { 099 // SELECT SKIP 2 FIRST 1 * FROM 100 sql.insert(6, " SKIP " + limitOffset + " FIRST " + limitRows); 101 } else if (limitRows != null) { 102 sql.insert(6, " FIRST " + limitRows); 103 } 104 return sql; 105 }; 106 107 /** 108 * Firebird 的处理器 109 * 适合 {@link DbType#FIREBIRD} 110 */ 111 LimitOffsetProcessor FIREBIRD = (sql, queryWrapper, limitRows, limitOffset) -> { 112 if (limitRows != null && limitOffset != null) { 113 // ROWS 2 TO 3 114 sql.append(" ROWS ").append(limitOffset).append(" TO ").append(limitOffset + limitRows); 115 } else if (limitRows != null) { 116 sql.insert(6, " FIRST " + limitRows); 117 } 118 return sql; 119 }; 120 121 /** 122 * Oracle11g及以下数据库的处理器 123 * 适合 {@link DbType#ORACLE,DbType#DM,DbType#GAUSS} 124 */ 125 LimitOffsetProcessor ORACLE = (sql, queryWrapper, limitRows, limitOffset) -> { 126 if (limitRows != null) { 127 if (limitOffset == null) { 128 limitOffset = 0; 129 } 130 StringBuilder newSql = new StringBuilder("SELECT * FROM (SELECT TEMP_DATAS.*, ROWNUM RN FROM ("); 131 newSql.append(sql); 132 newSql.append(") TEMP_DATAS WHERE ROWNUM <=").append(limitOffset + limitRows).append(") WHERE RN >").append(limitOffset); 133 return newSql; 134 } 135 return sql; 136 }; 137 138 /** 139 * Sybase 处理器 140 * 适合 {@link DbType#SYBASE} 141 */ 142 LimitOffsetProcessor SYBASE = (sql, queryWrapper, limitRows, limitOffset) -> { 143 if (limitRows != null && limitOffset != null) { 144 //SELECT TOP 1 START AT 3 * FROM 145 sql.insert(6, " TOP " + limitRows + " START AT " + (limitOffset + 1)); 146 } else if (limitRows != null) { 147 sql.insert(6, " TOP " + limitRows); 148 } 149 return sql; 150 }; 151 152 153 /** 154 * 处理构建 limit 和 offset 155 * 156 * @param sql 已经构建的 sql 157 * @param queryWrapper 参数内容 158 * @param limitRows 用户传入的 limit 参数 可能为 null 159 * @param limitOffset 用户传入的 offset 参数,可能为 null 160 */ 161 StringBuilder process(StringBuilder sql, QueryWrapper queryWrapper, Integer limitRows, Integer limitOffset); 162}