feat: add sqlServer 2005 LimitOffsetProcessor

This commit is contained in:
开源海哥 2023-07-10 11:57:35 +08:00
parent 81016ec601
commit 9582f88cf7
4 changed files with 286 additions and 261 deletions

View File

@ -58,6 +58,10 @@ public enum DbType {
* SQLSERVER
*/
SQLSERVER("sqlserver", "SQLServer 数据库"),
/**
* SqlServer 2005 数据库
*/
SQLSERVER_2005("sqlserver_2005", "SQLServer 数据库"),
/**
* DM
*/

View File

@ -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();
}
}

View File

@ -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:

View File

@ -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<QueryOrderBy> 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<QueryOrderBy> 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 <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>}
*/
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 <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>}
*/
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);
}