diff --git a/mybatis-flex-core/src/main/java/com/mybatisflex/core/dialect/DbType.java b/mybatis-flex-core/src/main/java/com/mybatisflex/core/dialect/DbType.java index 5ec2a4f6..3a47a421 100644 --- a/mybatis-flex-core/src/main/java/com/mybatisflex/core/dialect/DbType.java +++ b/mybatis-flex-core/src/main/java/com/mybatisflex/core/dialect/DbType.java @@ -58,6 +58,10 @@ public enum DbType { * SQLSERVER */ SQLSERVER("sqlserver", "SQLServer 数据库"), + /** + * SqlServer 2005 数据库 + */ + SQLSERVER_2005("sqlserver_2005", "SQLServer 数据库"), /** * DM */ diff --git a/mybatis-flex-core/src/main/java/com/mybatisflex/core/dialect/DbTypeUtil.java b/mybatis-flex-core/src/main/java/com/mybatisflex/core/dialect/DbTypeUtil.java index be7f58b3..ace38626 100644 --- a/mybatis-flex-core/src/main/java/com/mybatisflex/core/dialect/DbTypeUtil.java +++ b/mybatis-flex-core/src/main/java/com/mybatisflex/core/dialect/DbTypeUtil.java @@ -31,148 +31,151 @@ import java.util.regex.Pattern; */ public class DbTypeUtil { - private DbTypeUtil() {} + private DbTypeUtil() { + } - /** - * 获取当前配置的 DbType - */ - public static DbType getDbType(DataSource dataSource) { - String jdbcUrl = getJdbcUrl(dataSource); + /** + * 获取当前配置的 DbType + */ + public static DbType getDbType(DataSource dataSource) { + String jdbcUrl = getJdbcUrl(dataSource); - if (StringUtil.isNotBlank(jdbcUrl)) { - return parseDbType(jdbcUrl); - } + if (StringUtil.isNotBlank(jdbcUrl)) { + return parseDbType(jdbcUrl); + } - throw new IllegalStateException("Can not get dataSource jdbcUrl: " + dataSource.getClass().getName()); - } + throw new IllegalStateException("Can not get dataSource jdbcUrl: " + dataSource.getClass().getName()); + } - /** - * 通过数据源中获取 jdbc 的 url 配置 - * 符合 HikariCP, druid, c3p0, DBCP, beecp 数据源框架 以及 MyBatis UnpooledDataSource 的获取规则 - * UnpooledDataSource 参考 @{@link UnpooledDataSource#getUrl()} - * - * @return jdbc url 配置 - */ - public static String getJdbcUrl(DataSource dataSource) { - String[] methodNames = new String[]{"getUrl", "getJdbcUrl"}; - for (String methodName : methodNames) { - try { - Method method = dataSource.getClass().getMethod(methodName); - return (String) method.invoke(dataSource); - } catch (Exception e) { - //ignore - } - } + /** + * 通过数据源中获取 jdbc 的 url 配置 + * 符合 HikariCP, druid, c3p0, DBCP, beecp 数据源框架 以及 MyBatis UnpooledDataSource 的获取规则 + * UnpooledDataSource 参考 @{@link UnpooledDataSource#getUrl()} + * + * @return jdbc url 配置 + */ + public static String getJdbcUrl(DataSource dataSource) { + String[] methodNames = new String[]{"getUrl", "getJdbcUrl"}; + for (String methodName : methodNames) { + try { + Method method = dataSource.getClass().getMethod(methodName); + return (String) method.invoke(dataSource); + } catch (Exception e) { + //ignore + } + } - Connection connection = null; - try { - connection = dataSource.getConnection(); - return connection.getMetaData().getURL(); - } catch (Exception e) { - throw FlexExceptions.wrap("Can not get the dataSource jdbcUrl", e); - } finally { - if (connection != null) { - try { - connection.close(); - } catch (SQLException e) { //ignore - } - } - } - } + Connection connection = null; + try { + connection = dataSource.getConnection(); + return connection.getMetaData().getURL(); + } catch (Exception e) { + throw FlexExceptions.wrap("Can not get the dataSource jdbcUrl", e); + } finally { + if (connection != null) { + try { + connection.close(); + } catch (SQLException e) { //ignore + } + } + } + } - /** - * 参考 druid 和 MyBatis-plus 的 JdbcUtils - * {@link com.alibaba.druid.util.JdbcUtils#getDbType(String, String)} - * {@link com.baomidou.mybatisplus.extension.toolkit.JdbcUtils#getDbType(String)} - * - * @param jdbcUrl jdbcURL - * @return 返回数据库类型 - */ - public static DbType parseDbType(String jdbcUrl) { - jdbcUrl = jdbcUrl.toLowerCase(); - if (jdbcUrl.contains(":mysql:") || jdbcUrl.contains(":cobar:")) { - return DbType.MYSQL; - } else if (jdbcUrl.contains(":mariadb:")) { - return DbType.MARIADB; - } else if (jdbcUrl.contains(":oracle:")) { - return DbType.ORACLE; - } else if (jdbcUrl.contains(":sqlserver:") || jdbcUrl.contains(":microsoft:") || jdbcUrl.contains(":sqlserver2012:")) { - return DbType.SQLSERVER; - } else if (jdbcUrl.contains(":postgresql:")) { - return DbType.POSTGRE_SQL; - } else if (jdbcUrl.contains(":hsqldb:")) { - return DbType.HSQL; - } else if (jdbcUrl.contains(":db2:")) { - return DbType.DB2; - } else if (jdbcUrl.contains(":sqlite:")) { - return DbType.SQLITE; - } else if (jdbcUrl.contains(":h2:")) { - return DbType.H2; - } else if (isMatchedRegex(":dm\\d*:", jdbcUrl)) { - return DbType.DM; - } else if (jdbcUrl.contains(":xugu:")) { - return DbType.XUGU; - } else if (isMatchedRegex(":kingbase\\d*:", jdbcUrl)) { - return DbType.KINGBASE_ES; - } else if (jdbcUrl.contains(":phoenix:")) { - return DbType.PHOENIX; - } else if (jdbcUrl.contains(":zenith:")) { - return DbType.GAUSS; - } else if (jdbcUrl.contains(":gbase:")) { - return DbType.GBASE; - } else if (jdbcUrl.contains(":gbasedbt-sqli:") || jdbcUrl.contains(":informix-sqli:")) { - return DbType.GBASE_8S; - } else if (jdbcUrl.contains(":ch:") || jdbcUrl.contains(":clickhouse:")) { - return DbType.CLICK_HOUSE; - } else if (jdbcUrl.contains(":oscar:")) { - return DbType.OSCAR; - } else if (jdbcUrl.contains(":sybase:")) { - return DbType.SYBASE; - } else if (jdbcUrl.contains(":oceanbase:")) { - return DbType.OCEAN_BASE; - } else if (jdbcUrl.contains(":highgo:")) { - return DbType.HIGH_GO; - } else if (jdbcUrl.contains(":cubrid:")) { - return DbType.CUBRID; - } else if (jdbcUrl.contains(":goldilocks:")) { - return DbType.GOLDILOCKS; - } else if (jdbcUrl.contains(":csiidb:")) { - return DbType.CSIIDB; - } else if (jdbcUrl.contains(":sap:")) { - return DbType.SAP_HANA; - } else if (jdbcUrl.contains(":impala:")) { - return DbType.IMPALA; - } else if (jdbcUrl.contains(":vertica:")) { - return DbType.VERTICA; - } else if (jdbcUrl.contains(":xcloud:")) { - return DbType.XCloud; - } else if (jdbcUrl.contains(":firebirdsql:")) { - return DbType.FIREBIRD; - } else if (jdbcUrl.contains(":redshift:")) { - return DbType.REDSHIFT; - } else if (jdbcUrl.contains(":opengauss:")) { - return DbType.OPENGAUSS; - } else if (jdbcUrl.contains(":taos:") || jdbcUrl.contains(":taos-rs:")) { - return DbType.TDENGINE; - } else if (jdbcUrl.contains(":informix")) { - return DbType.INFORMIX; - } else if (jdbcUrl.contains(":uxdb:")) { - return DbType.UXDB; - } else if (jdbcUrl.contains(":greenplum:")) { - return DbType.GREENPLUM; - } else { - return DbType.OTHER; - } - } + /** + * 参考 druid 和 MyBatis-plus 的 JdbcUtils + * {@link com.alibaba.druid.util.JdbcUtils#getDbType(String, String)} + * {@link com.baomidou.mybatisplus.extension.toolkit.JdbcUtils#getDbType(String)} + * + * @param jdbcUrl jdbcURL + * @return 返回数据库类型 + */ + public static DbType parseDbType(String jdbcUrl) { + jdbcUrl = jdbcUrl.toLowerCase(); + if (jdbcUrl.contains(":mysql:") || jdbcUrl.contains(":cobar:")) { + return DbType.MYSQL; + } else if (jdbcUrl.contains(":mariadb:")) { + return DbType.MARIADB; + } else if (jdbcUrl.contains(":oracle:")) { + return DbType.ORACLE; + } else if (jdbcUrl.contains(":sqlserver2012:")) { + return DbType.SQLSERVER; + } else if (jdbcUrl.contains(":sqlserver:") || jdbcUrl.contains(":microsoft:")) { + return DbType.SQLSERVER_2005; + } else if (jdbcUrl.contains(":postgresql:")) { + return DbType.POSTGRE_SQL; + } else if (jdbcUrl.contains(":hsqldb:")) { + return DbType.HSQL; + } else if (jdbcUrl.contains(":db2:")) { + return DbType.DB2; + } else if (jdbcUrl.contains(":sqlite:")) { + return DbType.SQLITE; + } else if (jdbcUrl.contains(":h2:")) { + return DbType.H2; + } else if (isMatchedRegex(":dm\\d*:", jdbcUrl)) { + return DbType.DM; + } else if (jdbcUrl.contains(":xugu:")) { + return DbType.XUGU; + } else if (isMatchedRegex(":kingbase\\d*:", jdbcUrl)) { + return DbType.KINGBASE_ES; + } else if (jdbcUrl.contains(":phoenix:")) { + return DbType.PHOENIX; + } else if (jdbcUrl.contains(":zenith:")) { + return DbType.GAUSS; + } else if (jdbcUrl.contains(":gbase:")) { + return DbType.GBASE; + } else if (jdbcUrl.contains(":gbasedbt-sqli:") || jdbcUrl.contains(":informix-sqli:")) { + return DbType.GBASE_8S; + } else if (jdbcUrl.contains(":ch:") || jdbcUrl.contains(":clickhouse:")) { + return DbType.CLICK_HOUSE; + } else if (jdbcUrl.contains(":oscar:")) { + return DbType.OSCAR; + } else if (jdbcUrl.contains(":sybase:")) { + return DbType.SYBASE; + } else if (jdbcUrl.contains(":oceanbase:")) { + return DbType.OCEAN_BASE; + } else if (jdbcUrl.contains(":highgo:")) { + return DbType.HIGH_GO; + } else if (jdbcUrl.contains(":cubrid:")) { + return DbType.CUBRID; + } else if (jdbcUrl.contains(":goldilocks:")) { + return DbType.GOLDILOCKS; + } else if (jdbcUrl.contains(":csiidb:")) { + return DbType.CSIIDB; + } else if (jdbcUrl.contains(":sap:")) { + return DbType.SAP_HANA; + } else if (jdbcUrl.contains(":impala:")) { + return DbType.IMPALA; + } else if (jdbcUrl.contains(":vertica:")) { + return DbType.VERTICA; + } else if (jdbcUrl.contains(":xcloud:")) { + return DbType.XCloud; + } else if (jdbcUrl.contains(":firebirdsql:")) { + return DbType.FIREBIRD; + } else if (jdbcUrl.contains(":redshift:")) { + return DbType.REDSHIFT; + } else if (jdbcUrl.contains(":opengauss:")) { + return DbType.OPENGAUSS; + } else if (jdbcUrl.contains(":taos:") || jdbcUrl.contains(":taos-rs:")) { + return DbType.TDENGINE; + } else if (jdbcUrl.contains(":informix")) { + return DbType.INFORMIX; + } else if (jdbcUrl.contains(":uxdb:")) { + return DbType.UXDB; + } else if (jdbcUrl.contains(":greenplum:")) { + return DbType.GREENPLUM; + } else { + return DbType.OTHER; + } + } - /** - * 正则匹配,验证成功返回 true,验证失败返回 false - */ - public static boolean isMatchedRegex(String regex, String jdbcUrl) { - if (null == jdbcUrl) { - return false; - } - return Pattern.compile(regex).matcher(jdbcUrl).find(); - } + /** + * 正则匹配,验证成功返回 true,验证失败返回 false + */ + public static boolean isMatchedRegex(String regex, String jdbcUrl) { + if (null == jdbcUrl) { + return false; + } + return Pattern.compile(regex).matcher(jdbcUrl).find(); + } } diff --git a/mybatis-flex-core/src/main/java/com/mybatisflex/core/dialect/DialectFactory.java b/mybatis-flex-core/src/main/java/com/mybatisflex/core/dialect/DialectFactory.java index 78a72a4e..f94f21ec 100644 --- a/mybatis-flex-core/src/main/java/com/mybatisflex/core/dialect/DialectFactory.java +++ b/mybatis-flex-core/src/main/java/com/mybatisflex/core/dialect/DialectFactory.java @@ -134,6 +134,8 @@ public class DialectFactory { return new CommonsDialectImpl(KeywordWrap.DOUBLE_QUOTATION, LimitOffsetProcessor.DERBY); case SQLSERVER: return new CommonsDialectImpl(KeywordWrap.SQUARE_BRACKETS, LimitOffsetProcessor.SQLSERVER); + case SQLSERVER_2005: + return new CommonsDialectImpl(KeywordWrap.SQUARE_BRACKETS, LimitOffsetProcessor.SQLSERVER_2005); case INFORMIX: return new CommonsDialectImpl(KeywordWrap.DOUBLE_QUOTATION, LimitOffsetProcessor.INFORMIX); case SYBASE: diff --git a/mybatis-flex-core/src/main/java/com/mybatisflex/core/dialect/LimitOffsetProcessor.java b/mybatis-flex-core/src/main/java/com/mybatisflex/core/dialect/LimitOffsetProcessor.java index db312d92..416d3c4c 100644 --- a/mybatis-flex-core/src/main/java/com/mybatisflex/core/dialect/LimitOffsetProcessor.java +++ b/mybatis-flex-core/src/main/java/com/mybatisflex/core/dialect/LimitOffsetProcessor.java @@ -29,136 +29,152 @@ import static com.mybatisflex.core.constant.SqlConsts.*; */ public interface LimitOffsetProcessor { - /** - * MySql 的处理器 - * 适合 {@link DbType#MYSQL,DbType#MARIADB,DbType#H2,DbType#CLICK_HOUSE,DbType#XCloud} - */ - LimitOffsetProcessor MYSQL = (sql, queryWrapper, limitRows, limitOffset) -> { - if (limitRows != null && limitOffset != null) { - sql.append(LIMIT).append(limitOffset).append(DELIMITER).append(limitRows); - } else if (limitRows != null) { - sql.append(LIMIT).append(limitRows); - } - return sql; - }; + /** + * MySql 的处理器 + * 适合 {@link DbType#MYSQL,DbType#MARIADB,DbType#H2,DbType#CLICK_HOUSE,DbType#XCloud} + */ + LimitOffsetProcessor MYSQL = (sql, queryWrapper, limitRows, limitOffset) -> { + if (limitRows != null && limitOffset != null) { + sql.append(LIMIT).append(limitOffset).append(DELIMITER).append(limitRows); + } else if (limitRows != null) { + sql.append(LIMIT).append(limitRows); + } + return sql; + }; - /** - * Postgresql 的处理器 - * 适合 {@link DbType#POSTGRE_SQL,DbType#SQLITE,DbType#H2,DbType#HSQL,DbType#KINGBASE_ES,DbType#PHOENIX} - * 适合 {@link DbType#SAP_HANA,DbType#IMPALA,DbType#HIGH_GO,DbType#VERTICA,DbType#REDSHIFT} - * 适合 {@link DbType#OPENGAUSS,DbType#TDENGINE,DbType#UXDB} - */ - LimitOffsetProcessor POSTGRESQL = (sql, queryWrapper, limitRows, limitOffset) -> { - if (limitRows != null && limitOffset != null) { - sql.append(LIMIT).append(limitRows).append(OFFSET).append(limitOffset); - } else if (limitRows != null) { - sql.append(LIMIT).append(limitRows); - } - return sql; - }; + /** + * Postgresql 的处理器 + * 适合 {@link DbType#POSTGRE_SQL,DbType#SQLITE,DbType#H2,DbType#HSQL,DbType#KINGBASE_ES,DbType#PHOENIX} + * 适合 {@link DbType#SAP_HANA,DbType#IMPALA,DbType#HIGH_GO,DbType#VERTICA,DbType#REDSHIFT} + * 适合 {@link DbType#OPENGAUSS,DbType#TDENGINE,DbType#UXDB} + */ + LimitOffsetProcessor POSTGRESQL = (sql, queryWrapper, limitRows, limitOffset) -> { + if (limitRows != null && limitOffset != null) { + sql.append(LIMIT).append(limitRows).append(OFFSET).append(limitOffset); + } else if (limitRows != null) { + sql.append(LIMIT).append(limitRows); + } + return sql; + }; - /** - * derby 的处理器 - * 适合 {@link DbType#DERBY,DbType#ORACLE_12C,DbType#SQLSERVER ,DbType#POSTGRE_SQL} - */ - LimitOffsetProcessor DERBY = (sql, queryWrapper, limitRows, limitOffset) -> { - if (limitRows != null && limitOffset != null) { - // OFFSET ** ROWS FETCH NEXT ** ROWS ONLY") - sql.append(OFFSET).append(limitOffset).append(ROWS_FETCH_NEXT).append(limitRows).append(ROWS_ONLY); - } else if (limitRows != null) { - sql.append(OFFSET).append(0).append(ROWS_FETCH_NEXT).append(limitRows).append(ROWS_ONLY); - } - return sql; - }; + /** + * derby 的处理器 + * 适合 {@link DbType#DERBY,DbType#ORACLE_12C,DbType#SQLSERVER ,DbType#POSTGRE_SQL} + */ + LimitOffsetProcessor DERBY = (sql, queryWrapper, limitRows, limitOffset) -> { + if (limitRows != null && limitOffset != null) { + // OFFSET ** ROWS FETCH NEXT ** ROWS ONLY") + sql.append(OFFSET).append(limitOffset).append(ROWS_FETCH_NEXT).append(limitRows).append(ROWS_ONLY); + } else if (limitRows != null) { + sql.append(OFFSET).append(0).append(ROWS_FETCH_NEXT).append(limitRows).append(ROWS_ONLY); + } + return sql; + }; - /** - * derby 的处理器 - * 适合 {@link DbType#DERBY,DbType#ORACLE_12C,DbType#SQLSERVER ,DbType#POSTGRE_SQL} - */ - LimitOffsetProcessor SQLSERVER = (sql, queryWrapper, limitRows, limitOffset) -> { - if (limitRows != null && limitOffset != null) { - // OFFSET ** ROWS FETCH NEXT ** ROWS ONLY") - sql.append(OFFSET).append(limitOffset).append(ROWS_FETCH_NEXT).append(limitRows).append(ROWS_ONLY); - } else if (limitRows != null) { - List orderBys = CPI.getOrderBys(queryWrapper); - if (CollectionUtil.isNotEmpty(orderBys)) { - sql.append(OFFSET).append(0).append(ROWS_FETCH_NEXT).append(limitRows).append(ROWS_ONLY); - } else { - sql.insert(6, TOP + limitRows); - } - } - return sql; - }; + /** + * derby 的处理器 + * 适合 {@link DbType#DERBY,DbType#ORACLE_12C,DbType#SQLSERVER ,DbType#POSTGRE_SQL} + */ + LimitOffsetProcessor SQLSERVER = (sql, queryWrapper, limitRows, limitOffset) -> { + if (limitRows != null && limitOffset != null) { + // OFFSET ** ROWS FETCH NEXT ** ROWS ONLY") + sql.append(OFFSET).append(limitOffset).append(ROWS_FETCH_NEXT).append(limitRows).append(ROWS_ONLY); + } else if (limitRows != null) { + List orderBys = CPI.getOrderBys(queryWrapper); + if (CollectionUtil.isNotEmpty(orderBys)) { + sql.append(OFFSET).append(0).append(ROWS_FETCH_NEXT).append(limitRows).append(ROWS_ONLY); + } else { + sql.insert(6, TOP + limitRows); + } + } + return sql; + }; - /** - * Informix 的处理器 - * 适合 {@link DbType#INFORMIX} - * 文档 {@link https://www.ibm.com/docs/en/informix-servers/14.10?topic=clause-restricting-return-values-skip-limit-first-options} - */ - LimitOffsetProcessor INFORMIX = (sql, queryWrapper, limitRows, limitOffset) -> { - if (limitRows != null && limitOffset != null) { - // SELECT SKIP 2 FIRST 1 * FROM - sql.insert(6, SKIP + limitOffset + FIRST + limitRows); - } else if (limitRows != null) { - sql.insert(6, FIRST + limitRows); - } - return sql; - }; - - /** - * Firebird 的处理器 - * 适合 {@link DbType#FIREBIRD} - */ - LimitOffsetProcessor FIREBIRD = (sql, queryWrapper, limitRows, limitOffset) -> { - if (limitRows != null && limitOffset != null) { - // ROWS 2 TO 3 - sql.append(ROWS).append(limitOffset).append(TO).append(limitOffset + limitRows); - } else if (limitRows != null) { - sql.insert(6, FIRST + limitRows); - } - return sql; - }; - - /** - * Oracle11g及以下数据库的处理器 - * 适合 {@link DbType#ORACLE,DbType#DM,DbType#GAUSS} - */ - LimitOffsetProcessor ORACLE = (sql, queryWrapper, limitRows, limitOffset) -> { - if (limitRows != null) { - if (limitOffset == null) { - limitOffset = 0; - } - StringBuilder newSql = new StringBuilder("SELECT * FROM (SELECT TEMP_DATAS.*, ROWNUM RN FROM ("); - newSql.append(sql); - newSql.append(") TEMP_DATAS WHERE ROWNUM <= ").append(limitOffset + limitRows).append(") WHERE RN > ").append(limitOffset); - return newSql; - } - return sql; - }; - - /** - * Sybase 处理器 - * 适合 {@link DbType#SYBASE} - */ - LimitOffsetProcessor SYBASE = (sql, queryWrapper, limitRows, limitOffset) -> { - if (limitRows != null && limitOffset != null) { - //SELECT TOP 1 START AT 3 * FROM - sql.insert(6, TOP + limitRows + START_AT + (limitOffset + 1)); - } else if (limitRows != null) { - sql.insert(6, TOP + limitRows); - } - return sql; - }; + /** + * SqlServer 2005 limit 处理器 + */ + LimitOffsetProcessor SQLSERVER_2005 = (sql, queryWrapper, limitRows, limitOffset) -> { + if (limitRows != null) { + if (limitOffset == null) { + limitOffset = 0; + } + StringBuilder newSql = new StringBuilder("SELECT * FROM (SELECT TEMP_DATAS.*, ROW_NUMBER() OVER() AS RN FROM ("); + newSql.append(sql).append(") AS TEMP_DATAS) WHERE RN > ").append(limitOffset).append(" AND RN <= ").append(limitRows + limitRows); + return newSql; + } + return sql; + }; - /** - * 处理构建 limit 和 offset - * - * @param sql 已经构建的 sql - * @param queryWrapper 参数内容 - * @param limitRows 用户传入的 limit 参数 可能为 null - * @param limitOffset 用户传入的 offset 参数,可能为 null - */ - StringBuilder process(StringBuilder sql, QueryWrapper queryWrapper, Integer limitRows, Integer limitOffset); + /** + * Informix 的处理器 + * 适合 {@link DbType#INFORMIX} + * 文档 {@link https://www.ibm.com/docs/en/informix-servers/14.10?topic=clause-restricting-return-values-skip-limit-first-options} + */ + LimitOffsetProcessor INFORMIX = (sql, queryWrapper, limitRows, limitOffset) -> { + if (limitRows != null && limitOffset != null) { + // SELECT SKIP 2 FIRST 1 * FROM + sql.insert(6, SKIP + limitOffset + FIRST + limitRows); + } else if (limitRows != null) { + sql.insert(6, FIRST + limitRows); + } + return sql; + }; + + /** + * Firebird 的处理器 + * 适合 {@link DbType#FIREBIRD} + */ + LimitOffsetProcessor FIREBIRD = (sql, queryWrapper, limitRows, limitOffset) -> { + if (limitRows != null && limitOffset != null) { + // ROWS 2 TO 3 + sql.append(ROWS).append(limitOffset).append(TO).append(limitOffset + limitRows); + } else if (limitRows != null) { + sql.insert(6, FIRST + limitRows); + } + return sql; + }; + + /** + * Oracle11g及以下数据库的处理器 + * 适合 {@link DbType#ORACLE,DbType#DM,DbType#GAUSS} + */ + LimitOffsetProcessor ORACLE = (sql, queryWrapper, limitRows, limitOffset) -> { + if (limitRows != null) { + if (limitOffset == null) { + limitOffset = 0; + } + StringBuilder newSql = new StringBuilder("SELECT * FROM (SELECT TEMP_DATAS.*, ROWNUM RN FROM ("); + newSql.append(sql); + newSql.append(") TEMP_DATAS WHERE ROWNUM <= ").append(limitOffset + limitRows).append(") WHERE RN > ").append(limitOffset); + return newSql; + } + return sql; + }; + + /** + * Sybase 处理器 + * 适合 {@link DbType#SYBASE} + */ + LimitOffsetProcessor SYBASE = (sql, queryWrapper, limitRows, limitOffset) -> { + if (limitRows != null && limitOffset != null) { + //SELECT TOP 1 START AT 3 * FROM + sql.insert(6, TOP + limitRows + START_AT + (limitOffset + 1)); + } else if (limitRows != null) { + sql.insert(6, TOP + limitRows); + } + return sql; + }; + + + /** + * 处理构建 limit 和 offset + * + * @param sql 已经构建的 sql + * @param queryWrapper 参数内容 + * @param limitRows 用户传入的 limit 参数 可能为 null + * @param limitOffset 用户传入的 offset 参数,可能为 null + */ + StringBuilder process(StringBuilder sql, QueryWrapper queryWrapper, Integer limitRows, Integer limitOffset); }