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.QueryWrapper; 019 020/** 021 * limit 和 offset 参数的处理器 022 */ 023public interface LimitOffsetProcesser { 024 025 /** 026 * MySql 的处理器 027 * 适合 {@link DbType#MYSQL,DbType#MARIADB,DbType#H2,DbType#CLICK_HOUSE,DbType#XCloud} 028 */ 029 LimitOffsetProcesser MYSQL = (sql, queryWrapper, limitRows, limitOffset) -> { 030 if (limitRows != null && limitOffset != null) { 031 sql.append(" LIMIT ").append(limitOffset).append(", ").append(limitRows); 032 } else if (limitRows != null) { 033 sql.append(" LIMIT ").append(limitRows); 034 } 035 return sql; 036 }; 037 038 /** 039 * Postgresql 的处理器 040 * 适合 {@link DbType#POSTGRE_SQL,DbType#SQLITE,DbType#H2,DbType#HSQL,DbType#KINGBASE_ES,DbType#PHOENIX} 041 * 适合 {@link DbType#SAP_HANA,DbType#IMPALA,DbType#HIGH_GO,DbType#VERTICA,DbType#REDSHIFT} 042 * 适合 {@link DbType#OPENGAUSS,DbType#TDENGINE,DbType#UXDB} 043 */ 044 LimitOffsetProcesser POSTGRESQL = (sql, queryWrapper, limitRows, limitOffset) -> { 045 if (limitRows != null && limitOffset != null) { 046 sql.append(" LIMIT ").append(limitRows).append(" OFFSET ").append(limitOffset); 047 } else if (limitRows != null) { 048 sql.append(" LIMIT ").append(limitRows); 049 } 050 return sql; 051 }; 052 053 /** 054 * derby 的处理器 055 * 适合 {@link DbType#DERBY,DbType#ORACLE_12C,DbType#SQLSERVER ,DbType#POSTGRE_SQL} 056 */ 057 LimitOffsetProcesser DERBY = (sql, queryWrapper, limitRows, limitOffset) -> { 058 if (limitRows != null && limitOffset != null) { 059 // OFFSET ** ROWS FETCH NEXT ** ROWS ONLY") 060 sql.append(" OFFSET ").append(limitOffset).append(" ROWS FETCH NEXT ").append(limitRows).append(" ROWS ONLY"); 061 } else if (limitRows != null) { 062 // FETCH FIRST 20 ROWS ONLY 063 sql.append(" FETCH FIRST ").append(limitRows).append(" ROWS ONLY"); 064 } 065 return sql; 066 }; 067 068 /** 069 * db2 的处理器 070 * 适合 {@link DbType#DB2,DbType#SQLSERVER_2005} 071 */ 072 LimitOffsetProcesser DB2 = (sql, queryWrapper, limitRows, limitOffset) -> { 073 if (limitRows != null && limitOffset != null) { 074 // OFFSET ** ROWS FETCH NEXT ** ROWS ONLY") 075 sql.append(" OFFSET ").append(limitOffset).append(" ROWS FETCH NEXT ").append(limitRows).append(" ROWS ONLY"); 076 } else if (limitRows != null) { 077 // FETCH FIRST 20 ROWS ONLY 078 sql.append(" FETCH FIRST ").append(limitRows).append(" ROWS ONLY"); 079 } 080 return sql; 081 }; 082 083 /** 084 * Informix 的处理器 085 * 适合 {@link DbType#INFORMIX} 086 * 文档 {@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>} 087 */ 088 LimitOffsetProcesser INFORMIX = (sql, queryWrapper, limitRows, limitOffset) -> { 089 if (limitRows != null && limitOffset != null) { 090 // SELECT SKIP 2 FIRST 1 * FROM 091 sql.insert(6, " SKIP " + limitOffset + " FIRST " + limitRows); 092 } else if (limitRows != null) { 093 sql.insert(6, " FIRST " + limitRows); 094 } 095 return sql; 096 }; 097 098 /** 099 * Firebird 的处理器 100 * 适合 {@link DbType#FIREBIRD} 101 */ 102 LimitOffsetProcesser FIREBIRD = (sql, queryWrapper, limitRows, limitOffset) -> { 103 if (limitRows != null && limitOffset != null) { 104 // ROWS 2 TO 3 105 sql.append(" ROWS ").append(limitOffset).append(" TO ").append(limitOffset + limitRows); 106 } else if (limitRows != null) { 107 sql.insert(6, " FIRST " + limitRows); 108 } 109 return sql; 110 }; 111 112 /** 113 * Oracle11g及以下数据库的处理器 114 * 适合 {@link DbType#ORACLE,DbType#DM,DbType#GAUSS} 115 */ 116 LimitOffsetProcesser ORACLE = (sql, queryWrapper, limitRows, limitOffset) -> { 117 if (limitRows != null) { 118 if (limitOffset == null) { 119 limitOffset = 0; 120 } 121 StringBuilder newSql = new StringBuilder("SELECT * FROM (SELECT TEMP_DATAS.*, ROWNUM RN FROM ("); 122 newSql.append(sql); 123 newSql.append(") TEMP_DATAS WHERE ROWNUM <=").append(limitOffset + limitRows).append(") WHERE RN >").append(limitOffset); 124 return newSql; 125 } 126 return sql; 127 }; 128 129 /** 130 * Sybase 处理器 131 * 适合 {@link DbType#SYBASE} 132 */ 133 LimitOffsetProcesser SYBASE = (sql, queryWrapper, limitRows, limitOffset) -> { 134 if (limitRows != null && limitOffset != null) { 135 //SELECT TOP 1 START AT 3 * FROM 136 sql.insert(6, " TOP " + limitRows + " START AT " + (limitOffset + 1)); 137 } else if (limitRows != null) { 138 sql.insert(6, " TOP " + limitRows); 139 } 140 return sql; 141 }; 142 143 144 /** 145 * 处理构建 limit 和 offset 146 * 147 * @param sql 已经构建的 sql 148 * @param queryWrapper 参数内容 149 * @param limitRows 用户传入的 limit 参数 可能为 null 150 * @param limitOffset 用户传入的 offset 参数,可能为 null 151 */ 152 StringBuilder process(StringBuilder sql, QueryWrapper queryWrapper, Integer limitRows, Integer limitOffset); 153}