fix auth plugin Page (#11300)
* Optimize paginated queries based on data sources * add startup conditions * user movkEnv * update Exception Class name * Optimize paginated queries based on data sources * update Exception Class name * Revert "add startup conditions" This reverts commit 4e2c85d7 * Optimize paginated queries based on data sources * add startup conditions * user movkEnv * update Exception Class name * Revert "add startup conditions" This reverts commit 4e2c85d7 * Revert "Revert "add startup conditions"" This reverts commit 4225891414851e501b0c055cc1c295561440307b. * DialectFactory add database supported * fix auth plugin Page, add dataSource plugin Dialect * description * remove dataSource plugin Dialect * detail adjustment * DefaultPageHandlerAdapter
This commit is contained in:
parent
7803e33574
commit
736948f495
@ -52,7 +52,4 @@ public class PersistenceConstant {
|
||||
|
||||
public static final String CONFIG_MODEL_RAFT_GROUP = "nacos_config";
|
||||
|
||||
public static final String OFFSET = "OFFSET";
|
||||
|
||||
public static final String LIMIT = "LIMIT";
|
||||
}
|
||||
|
@ -16,14 +16,12 @@
|
||||
|
||||
package com.alibaba.nacos.persistence.repository.embedded;
|
||||
|
||||
import com.alibaba.nacos.persistence.constants.PersistenceConstant;
|
||||
import com.alibaba.nacos.persistence.model.Page;
|
||||
import com.alibaba.nacos.persistence.repository.PaginationHelper;
|
||||
import com.alibaba.nacos.persistence.repository.embedded.operate.DatabaseOperate;
|
||||
import com.alibaba.nacos.plugin.datasource.model.MapperResult;
|
||||
import org.springframework.jdbc.core.RowMapper;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
@ -87,17 +85,7 @@ public class EmbeddedPaginationHelperImpl<E> implements PaginationHelper {
|
||||
return page;
|
||||
}
|
||||
|
||||
// fill the sql Page args
|
||||
String fetchSql = sqlFetchRows;
|
||||
if (!fetchSql.contains(PersistenceConstant.OFFSET)) {
|
||||
fetchSql += " OFFSET ? ROWS FETCH NEXT ? ROWS ONLY";
|
||||
Object[] newArgs = Arrays.copyOf(args, args.length + 2);
|
||||
newArgs[args.length] = (pageNo - 1) * pageSize;
|
||||
newArgs[args.length + 1] = pageSize;
|
||||
args = newArgs;
|
||||
}
|
||||
|
||||
List<E> result = databaseOperate.queryMany(fetchSql, args, rowMapper);
|
||||
List<E> result = databaseOperate.queryMany(sqlFetchRows, args, rowMapper);
|
||||
for (E item : result) {
|
||||
page.getPageItems().add(item);
|
||||
}
|
||||
|
@ -16,7 +16,6 @@
|
||||
|
||||
package com.alibaba.nacos.persistence.repository.extrnal;
|
||||
|
||||
import com.alibaba.nacos.persistence.constants.PersistenceConstant;
|
||||
import com.alibaba.nacos.persistence.model.Page;
|
||||
import com.alibaba.nacos.persistence.repository.PaginationHelper;
|
||||
import com.alibaba.nacos.persistence.repository.embedded.EmbeddedStorageContextHolder;
|
||||
@ -24,7 +23,6 @@ import com.alibaba.nacos.plugin.datasource.model.MapperResult;
|
||||
import org.springframework.jdbc.core.JdbcTemplate;
|
||||
import org.springframework.jdbc.core.RowMapper;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
@ -87,17 +85,7 @@ public class ExternalStoragePaginationHelperImpl<E> implements PaginationHelper
|
||||
return page;
|
||||
}
|
||||
|
||||
// fill the sql Page args
|
||||
String fetchSql = sqlFetchRows;
|
||||
if (!fetchSql.contains(PersistenceConstant.LIMIT)) {
|
||||
fetchSql += " LIMIT ?, ?";
|
||||
Object[] newArgs = Arrays.copyOf(args, args.length + 2);
|
||||
newArgs[args.length] = (pageNo - 1) * pageSize;
|
||||
newArgs[args.length + 1] = pageSize;
|
||||
args = newArgs;
|
||||
}
|
||||
|
||||
List<E> result = jdbcTemplate.query(fetchSql, args, rowMapper);
|
||||
List<E> result = jdbcTemplate.query(sqlFetchRows, args, rowMapper);
|
||||
for (E item : result) {
|
||||
page.getPageItems().add(item);
|
||||
}
|
||||
|
@ -0,0 +1,37 @@
|
||||
/*
|
||||
* Copyright 1999-2022 Alibaba Group Holding Ltd.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.alibaba.nacos.plugin.auth.impl.constant;
|
||||
|
||||
/**
|
||||
* Auth plugin page constant.
|
||||
*
|
||||
* @author huangKeming
|
||||
**/
|
||||
|
||||
public class AuthPageConstant {
|
||||
|
||||
public static final String OFFSET = "OFFSET";
|
||||
|
||||
public static final String OFFSET_ROWS = "OFFSET ? ROWS";
|
||||
|
||||
public static final String FETCH_NEXT = "FETCH NEXT ? ROWS ONLY";
|
||||
|
||||
public static final String LIMIT = "LIMIT";
|
||||
|
||||
public static final String LIMIT_SIZE = "LIMIT ?,?";
|
||||
|
||||
}
|
@ -0,0 +1,54 @@
|
||||
/*
|
||||
* Copyright 1999-2023 Alibaba Group Holding Ltd.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.alibaba.nacos.plugin.auth.impl.model;
|
||||
|
||||
/**
|
||||
* Paginated query statements and query parameters encapsulate the results.
|
||||
*
|
||||
* @author huangKeMing
|
||||
*/
|
||||
public class OffsetFetchResult {
|
||||
|
||||
String fetchSql;
|
||||
|
||||
Object[] newArgs;
|
||||
|
||||
public OffsetFetchResult() {
|
||||
}
|
||||
|
||||
public OffsetFetchResult(String fetchSql, Object[] newArgs) {
|
||||
this.fetchSql = fetchSql;
|
||||
this.newArgs = newArgs;
|
||||
}
|
||||
|
||||
public String getFetchSql() {
|
||||
return fetchSql;
|
||||
}
|
||||
|
||||
public void setFetchSql(String fetchSql) {
|
||||
this.fetchSql = fetchSql;
|
||||
}
|
||||
|
||||
public Object[] getNewArgs() {
|
||||
return newArgs;
|
||||
}
|
||||
|
||||
public void setNewArgs(Object[] newArgs) {
|
||||
this.newArgs = newArgs;
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,53 @@
|
||||
/*
|
||||
* Copyright 1999-2023 Alibaba Group Holding Ltd.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.alibaba.nacos.plugin.auth.impl.persistence;
|
||||
|
||||
import com.alibaba.nacos.persistence.model.Page;
|
||||
import com.alibaba.nacos.plugin.datasource.model.MapperResult;
|
||||
import org.springframework.jdbc.core.RowMapper;
|
||||
|
||||
|
||||
/**
|
||||
* Auth plugin Pagination Helper.
|
||||
*
|
||||
* @param <E> Generic class
|
||||
* @author huangKeMing
|
||||
*/
|
||||
@SuppressWarnings("PMD.AbstractMethodOrInterfaceMethodMustUseJavadocRule")
|
||||
public interface AuthPaginationHelper<E> {
|
||||
|
||||
Page<E> fetchPage(final String sqlCountRows, final String sqlFetchRows, final Object[] args, final int pageNo,
|
||||
final int pageSize, final RowMapper<E> rowMapper);
|
||||
|
||||
Page<E> fetchPage(final String sqlCountRows, final String sqlFetchRows, final Object[] args, final int pageNo,
|
||||
final int pageSize, final Long lastMaxId, final RowMapper<E> rowMapper);
|
||||
|
||||
Page<E> fetchPageLimit(final String sqlCountRows, final String sqlFetchRows, final Object[] args, final int pageNo,
|
||||
final int pageSize, final RowMapper<E> rowMapper);
|
||||
|
||||
Page<E> fetchPageLimit(final String sqlCountRows, final Object[] args1, final String sqlFetchRows,
|
||||
final Object[] args2, final int pageNo, final int pageSize, final RowMapper<E> rowMapper);
|
||||
|
||||
Page<E> fetchPageLimit(final String sqlFetchRows, final Object[] args, final int pageNo, final int pageSize,
|
||||
final RowMapper<E> rowMapper);
|
||||
|
||||
Page<E> fetchPageLimit(final MapperResult countMapperResult, final MapperResult mapperResult, final int pageNo,
|
||||
final int pageSize, final RowMapper<E> rowMapper);
|
||||
|
||||
void updateLimit(final String sql, final Object[] args);
|
||||
|
||||
}
|
@ -19,10 +19,9 @@ package com.alibaba.nacos.plugin.auth.impl.persistence;
|
||||
import com.alibaba.nacos.common.utils.StringUtils;
|
||||
import com.alibaba.nacos.persistence.configuration.condition.ConditionOnEmbeddedStorage;
|
||||
import com.alibaba.nacos.persistence.model.Page;
|
||||
import com.alibaba.nacos.persistence.repository.PaginationHelper;
|
||||
import com.alibaba.nacos.persistence.repository.embedded.EmbeddedPaginationHelperImpl;
|
||||
import com.alibaba.nacos.persistence.repository.embedded.EmbeddedStorageContextHolder;
|
||||
import com.alibaba.nacos.persistence.repository.embedded.operate.DatabaseOperate;
|
||||
import com.alibaba.nacos.plugin.auth.impl.persistence.embedded.AuthEmbeddedPaginationHelperImpl;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.annotation.Conditional;
|
||||
import org.springframework.stereotype.Component;
|
||||
@ -51,7 +50,7 @@ public class EmbeddedPermissionPersistServiceImpl implements PermissionPersistSe
|
||||
|
||||
@Override
|
||||
public Page<PermissionInfo> getPermissions(String role, int pageNo, int pageSize) {
|
||||
PaginationHelper<PermissionInfo> helper = createPaginationHelper();
|
||||
AuthPaginationHelper<PermissionInfo> helper = createPaginationHelper();
|
||||
|
||||
String sqlCountRows = "SELECT count(*) FROM permissions WHERE ";
|
||||
|
||||
@ -65,9 +64,8 @@ public class EmbeddedPermissionPersistServiceImpl implements PermissionPersistSe
|
||||
where = " 1=1 ";
|
||||
}
|
||||
|
||||
Page<PermissionInfo> pageInfo = helper
|
||||
.fetchPage(sqlCountRows + where, sqlFetchRows + where, params.toArray(), pageNo, pageSize,
|
||||
PERMISSION_ROW_MAPPER);
|
||||
Page<PermissionInfo> pageInfo = helper.fetchPage(sqlCountRows + where, sqlFetchRows + where, params.toArray(),
|
||||
pageNo, pageSize, PERMISSION_ROW_MAPPER);
|
||||
|
||||
if (pageInfo == null) {
|
||||
pageInfo = new Page<>();
|
||||
@ -107,7 +105,7 @@ public class EmbeddedPermissionPersistServiceImpl implements PermissionPersistSe
|
||||
|
||||
@Override
|
||||
public Page<PermissionInfo> findPermissionsLike4Page(String role, int pageNo, int pageSize) {
|
||||
PaginationHelper<PermissionInfo> helper = createPaginationHelper();
|
||||
AuthPaginationHelper<PermissionInfo> helper = createPaginationHelper();
|
||||
|
||||
String sqlCountRows = "SELECT count(*) FROM permissions ";
|
||||
|
||||
@ -121,9 +119,8 @@ public class EmbeddedPermissionPersistServiceImpl implements PermissionPersistSe
|
||||
params.add(generateLikeArgument(role));
|
||||
}
|
||||
|
||||
Page<PermissionInfo> pageInfo = helper
|
||||
.fetchPage(sqlCountRows + where, sqlFetchRows + where, params.toArray(), pageNo, pageSize,
|
||||
PERMISSION_ROW_MAPPER);
|
||||
Page<PermissionInfo> pageInfo = helper.fetchPage(sqlCountRows + where, sqlFetchRows + where, params.toArray(),
|
||||
pageNo, pageSize, PERMISSION_ROW_MAPPER);
|
||||
|
||||
if (pageInfo == null) {
|
||||
pageInfo = new Page<>();
|
||||
@ -149,7 +146,7 @@ public class EmbeddedPermissionPersistServiceImpl implements PermissionPersistSe
|
||||
}
|
||||
|
||||
@Override
|
||||
public <E> PaginationHelper<E> createPaginationHelper() {
|
||||
return new EmbeddedPaginationHelperImpl<>(databaseOperate);
|
||||
public <E> AuthPaginationHelper<E> createPaginationHelper() {
|
||||
return new AuthEmbeddedPaginationHelperImpl<>(databaseOperate);
|
||||
}
|
||||
}
|
||||
|
@ -20,10 +20,9 @@ import com.alibaba.nacos.common.utils.CollectionUtils;
|
||||
import com.alibaba.nacos.common.utils.StringUtils;
|
||||
import com.alibaba.nacos.persistence.configuration.condition.ConditionOnEmbeddedStorage;
|
||||
import com.alibaba.nacos.persistence.model.Page;
|
||||
import com.alibaba.nacos.persistence.repository.PaginationHelper;
|
||||
import com.alibaba.nacos.persistence.repository.embedded.EmbeddedPaginationHelperImpl;
|
||||
import com.alibaba.nacos.persistence.repository.embedded.EmbeddedStorageContextHolder;
|
||||
import com.alibaba.nacos.persistence.repository.embedded.operate.DatabaseOperate;
|
||||
import com.alibaba.nacos.plugin.auth.impl.persistence.embedded.AuthEmbeddedPaginationHelperImpl;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.annotation.Conditional;
|
||||
import org.springframework.stereotype.Component;
|
||||
@ -51,8 +50,8 @@ public class EmbeddedRolePersistServiceImpl implements RolePersistService {
|
||||
|
||||
@Override
|
||||
public Page<RoleInfo> getRoles(int pageNo, int pageSize) {
|
||||
|
||||
PaginationHelper<RoleInfo> helper = createPaginationHelper();
|
||||
|
||||
AuthPaginationHelper<RoleInfo> helper = createPaginationHelper();
|
||||
|
||||
String sqlCountRows = "SELECT count(*) FROM (SELECT DISTINCT role FROM roles) roles WHERE ";
|
||||
|
||||
@ -60,9 +59,8 @@ public class EmbeddedRolePersistServiceImpl implements RolePersistService {
|
||||
|
||||
String where = " 1=1 ";
|
||||
|
||||
Page<RoleInfo> pageInfo = helper
|
||||
.fetchPage(sqlCountRows + where, sqlFetchRows + where, new ArrayList<String>().toArray(), pageNo,
|
||||
pageSize, ROLE_INFO_ROW_MAPPER);
|
||||
Page<RoleInfo> pageInfo = helper.fetchPage(sqlCountRows + where, sqlFetchRows + where,
|
||||
new ArrayList<String>().toArray(), pageNo, pageSize, ROLE_INFO_ROW_MAPPER);
|
||||
if (pageInfo == null) {
|
||||
pageInfo = new Page<>();
|
||||
pageInfo.setTotalCount(0);
|
||||
@ -74,8 +72,8 @@ public class EmbeddedRolePersistServiceImpl implements RolePersistService {
|
||||
|
||||
@Override
|
||||
public Page<RoleInfo> getRolesByUserNameAndRoleName(String username, String role, int pageNo, int pageSize) {
|
||||
|
||||
PaginationHelper<RoleInfo> helper = createPaginationHelper();
|
||||
|
||||
AuthPaginationHelper<RoleInfo> helper = createPaginationHelper();
|
||||
|
||||
String sqlCountRows = "SELECT count(*) FROM roles ";
|
||||
|
||||
@ -188,14 +186,14 @@ public class EmbeddedRolePersistServiceImpl implements RolePersistService {
|
||||
}
|
||||
String sqlCountRows = "SELECT count(*) FROM roles";
|
||||
String sqlFetchRows = "SELECT role, username FROM roles";
|
||||
|
||||
PaginationHelper<RoleInfo> helper = createPaginationHelper();
|
||||
|
||||
AuthPaginationHelper<RoleInfo> helper = createPaginationHelper();
|
||||
return helper.fetchPage(sqlCountRows + where, sqlFetchRows + where, params.toArray(), pageNo, pageSize,
|
||||
ROLE_INFO_ROW_MAPPER);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <E> PaginationHelper<E> createPaginationHelper() {
|
||||
return new EmbeddedPaginationHelperImpl<>(databaseOperate);
|
||||
public <E> AuthPaginationHelper<E> createPaginationHelper() {
|
||||
return new AuthEmbeddedPaginationHelperImpl<>(databaseOperate);
|
||||
}
|
||||
}
|
||||
|
@ -19,10 +19,9 @@ package com.alibaba.nacos.plugin.auth.impl.persistence;
|
||||
import com.alibaba.nacos.common.utils.StringUtils;
|
||||
import com.alibaba.nacos.persistence.configuration.condition.ConditionOnEmbeddedStorage;
|
||||
import com.alibaba.nacos.persistence.model.Page;
|
||||
import com.alibaba.nacos.persistence.repository.PaginationHelper;
|
||||
import com.alibaba.nacos.persistence.repository.embedded.EmbeddedPaginationHelperImpl;
|
||||
import com.alibaba.nacos.persistence.repository.embedded.EmbeddedStorageContextHolder;
|
||||
import com.alibaba.nacos.persistence.repository.embedded.operate.DatabaseOperate;
|
||||
import com.alibaba.nacos.plugin.auth.impl.persistence.embedded.AuthEmbeddedPaginationHelperImpl;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.annotation.Conditional;
|
||||
import org.springframework.stereotype.Component;
|
||||
@ -107,8 +106,8 @@ public class EmbeddedUserPersistServiceImpl implements UserPersistService {
|
||||
|
||||
@Override
|
||||
public Page<User> getUsers(int pageNo, int pageSize, String username) {
|
||||
|
||||
PaginationHelper<User> helper = createPaginationHelper();
|
||||
|
||||
AuthPaginationHelper<User> helper = createPaginationHelper();
|
||||
|
||||
String sqlCountRows = "SELECT count(*) FROM users ";
|
||||
|
||||
@ -149,8 +148,8 @@ public class EmbeddedUserPersistServiceImpl implements UserPersistService {
|
||||
where.append(SQL_DERBY_ESCAPE_BACK_SLASH_FOR_LIKE);
|
||||
params.add(generateLikeArgument(username));
|
||||
}
|
||||
|
||||
PaginationHelper<User> helper = createPaginationHelper();
|
||||
|
||||
AuthPaginationHelper<User> helper = createPaginationHelper();
|
||||
return helper.fetchPage(sqlCountRows + where, sqlFetchRows + where, params.toArray(), pageNo, pageSize,
|
||||
USER_ROW_MAPPER);
|
||||
}
|
||||
@ -171,7 +170,7 @@ public class EmbeddedUserPersistServiceImpl implements UserPersistService {
|
||||
}
|
||||
|
||||
@Override
|
||||
public <E> PaginationHelper<E> createPaginationHelper() {
|
||||
return new EmbeddedPaginationHelperImpl<>(databaseOperate);
|
||||
public <E> AuthPaginationHelper<E> createPaginationHelper() {
|
||||
return new AuthEmbeddedPaginationHelperImpl<>(databaseOperate);
|
||||
}
|
||||
}
|
||||
|
@ -19,10 +19,10 @@ package com.alibaba.nacos.plugin.auth.impl.persistence;
|
||||
import com.alibaba.nacos.common.utils.StringUtils;
|
||||
import com.alibaba.nacos.config.server.utils.LogUtil;
|
||||
import com.alibaba.nacos.persistence.configuration.condition.ConditionOnExternalStorage;
|
||||
import com.alibaba.nacos.persistence.datasource.DataSourceService;
|
||||
import com.alibaba.nacos.persistence.datasource.DynamicDataSource;
|
||||
import com.alibaba.nacos.persistence.model.Page;
|
||||
import com.alibaba.nacos.persistence.repository.PaginationHelper;
|
||||
import com.alibaba.nacos.persistence.repository.extrnal.ExternalStoragePaginationHelperImpl;
|
||||
import com.alibaba.nacos.plugin.auth.impl.persistence.extrnal.AuthExternalPaginationHelperImpl;
|
||||
import org.springframework.context.annotation.Conditional;
|
||||
import org.springframework.jdbc.CannotGetJdbcConnectionException;
|
||||
import org.springframework.jdbc.core.JdbcTemplate;
|
||||
@ -46,16 +46,20 @@ public class ExternalPermissionPersistServiceImpl implements PermissionPersistSe
|
||||
|
||||
private JdbcTemplate jt;
|
||||
|
||||
private String dataSourceType = "";
|
||||
|
||||
private static final String PATTERN_STR = "*";
|
||||
|
||||
@PostConstruct
|
||||
protected void init() {
|
||||
jt = DynamicDataSource.getInstance().getDataSource().getJdbcTemplate();
|
||||
DataSourceService dataSource = DynamicDataSource.getInstance().getDataSource();
|
||||
jt = dataSource.getJdbcTemplate();
|
||||
dataSourceType = dataSource.getDataSourceType();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Page<PermissionInfo> getPermissions(String role, int pageNo, int pageSize) {
|
||||
PaginationHelper<PermissionInfo> helper = createPaginationHelper();
|
||||
AuthPaginationHelper<PermissionInfo> helper = createPaginationHelper();
|
||||
|
||||
String sqlCountRows = "SELECT count(*) FROM permissions WHERE ";
|
||||
String sqlFetchRows = "SELECT role,resource,action FROM permissions WHERE ";
|
||||
@ -69,9 +73,8 @@ public class ExternalPermissionPersistServiceImpl implements PermissionPersistSe
|
||||
}
|
||||
|
||||
try {
|
||||
Page<PermissionInfo> pageInfo = helper
|
||||
.fetchPage(sqlCountRows + where, sqlFetchRows + where, params.toArray(), pageNo, pageSize,
|
||||
PERMISSION_ROW_MAPPER);
|
||||
Page<PermissionInfo> pageInfo = helper.fetchPage(sqlCountRows + where, sqlFetchRows + where,
|
||||
params.toArray(), pageNo, pageSize, PERMISSION_ROW_MAPPER);
|
||||
|
||||
if (pageInfo == null) {
|
||||
pageInfo = new Page<>();
|
||||
@ -128,7 +131,7 @@ public class ExternalPermissionPersistServiceImpl implements PermissionPersistSe
|
||||
|
||||
@Override
|
||||
public Page<PermissionInfo> findPermissionsLike4Page(String role, int pageNo, int pageSize) {
|
||||
PaginationHelper<PermissionInfo> helper = createPaginationHelper();
|
||||
AuthPaginationHelper<PermissionInfo> helper = createPaginationHelper();
|
||||
|
||||
String sqlCountRows = "SELECT count(*) FROM permissions ";
|
||||
String sqlFetchRows = "SELECT role,resource,action FROM permissions ";
|
||||
@ -141,9 +144,8 @@ public class ExternalPermissionPersistServiceImpl implements PermissionPersistSe
|
||||
}
|
||||
|
||||
try {
|
||||
Page<PermissionInfo> pageInfo = helper
|
||||
.fetchPage(sqlCountRows + where, sqlFetchRows + where, params.toArray(), pageNo, pageSize,
|
||||
PERMISSION_ROW_MAPPER);
|
||||
Page<PermissionInfo> pageInfo = helper.fetchPage(sqlCountRows + where, sqlFetchRows + where,
|
||||
params.toArray(), pageNo, pageSize, PERMISSION_ROW_MAPPER);
|
||||
|
||||
if (pageInfo == null) {
|
||||
pageInfo = new Page<>();
|
||||
@ -175,7 +177,7 @@ public class ExternalPermissionPersistServiceImpl implements PermissionPersistSe
|
||||
}
|
||||
|
||||
@Override
|
||||
public <E> PaginationHelper<E> createPaginationHelper() {
|
||||
return new ExternalStoragePaginationHelperImpl<>(jt);
|
||||
public <E> AuthPaginationHelper<E> createPaginationHelper() {
|
||||
return new AuthExternalPaginationHelperImpl<E>(jt, dataSourceType);
|
||||
}
|
||||
}
|
||||
|
@ -19,10 +19,10 @@ package com.alibaba.nacos.plugin.auth.impl.persistence;
|
||||
import com.alibaba.nacos.common.utils.StringUtils;
|
||||
import com.alibaba.nacos.config.server.utils.LogUtil;
|
||||
import com.alibaba.nacos.persistence.configuration.condition.ConditionOnExternalStorage;
|
||||
import com.alibaba.nacos.persistence.datasource.DataSourceService;
|
||||
import com.alibaba.nacos.persistence.datasource.DynamicDataSource;
|
||||
import com.alibaba.nacos.persistence.model.Page;
|
||||
import com.alibaba.nacos.persistence.repository.PaginationHelper;
|
||||
import com.alibaba.nacos.persistence.repository.extrnal.ExternalStoragePaginationHelperImpl;
|
||||
import com.alibaba.nacos.plugin.auth.impl.persistence.extrnal.AuthExternalPaginationHelperImpl;
|
||||
import org.springframework.context.annotation.Conditional;
|
||||
import org.springframework.jdbc.CannotGetJdbcConnectionException;
|
||||
import org.springframework.jdbc.core.JdbcTemplate;
|
||||
@ -48,17 +48,21 @@ public class ExternalRolePersistServiceImpl implements RolePersistService {
|
||||
|
||||
private JdbcTemplate jt;
|
||||
|
||||
private String dataSourceType = "";
|
||||
|
||||
private static final String PATTERN_STR = "*";
|
||||
|
||||
@PostConstruct
|
||||
protected void init() {
|
||||
jt = DynamicDataSource.getInstance().getDataSource().getJdbcTemplate();
|
||||
DataSourceService dataSource = DynamicDataSource.getInstance().getDataSource();
|
||||
jt = dataSource.getJdbcTemplate();
|
||||
dataSourceType = dataSource.getDataSourceType();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Page<RoleInfo> getRoles(int pageNo, int pageSize) {
|
||||
|
||||
PaginationHelper<RoleInfo> helper = createPaginationHelper();
|
||||
|
||||
AuthPaginationHelper<RoleInfo> helper = createPaginationHelper();
|
||||
|
||||
String sqlCountRows = "SELECT count(*) FROM (SELECT DISTINCT role FROM roles) roles WHERE ";
|
||||
|
||||
@ -67,9 +71,8 @@ public class ExternalRolePersistServiceImpl implements RolePersistService {
|
||||
String where = " 1=1 ";
|
||||
|
||||
try {
|
||||
Page<RoleInfo> pageInfo = helper
|
||||
.fetchPage(sqlCountRows + where, sqlFetchRows + where, new ArrayList<String>().toArray(), pageNo,
|
||||
pageSize, ROLE_INFO_ROW_MAPPER);
|
||||
Page<RoleInfo> pageInfo = helper.fetchPage(sqlCountRows + where, sqlFetchRows + where,
|
||||
new ArrayList<String>().toArray(), pageNo, pageSize, ROLE_INFO_ROW_MAPPER);
|
||||
if (pageInfo == null) {
|
||||
pageInfo = new Page<>();
|
||||
pageInfo.setTotalCount(0);
|
||||
@ -84,8 +87,8 @@ public class ExternalRolePersistServiceImpl implements RolePersistService {
|
||||
|
||||
@Override
|
||||
public Page<RoleInfo> getRolesByUserNameAndRoleName(String username, String role, int pageNo, int pageSize) {
|
||||
|
||||
PaginationHelper<RoleInfo> helper = createPaginationHelper();
|
||||
|
||||
AuthPaginationHelper<RoleInfo> helper = createPaginationHelper();
|
||||
|
||||
String sqlCountRows = "SELECT count(*) FROM roles ";
|
||||
|
||||
@ -200,8 +203,8 @@ public class ExternalRolePersistServiceImpl implements RolePersistService {
|
||||
where.append(" AND role LIKE ? ");
|
||||
params.add(generateLikeArgument(role));
|
||||
}
|
||||
|
||||
PaginationHelper<RoleInfo> helper = createPaginationHelper();
|
||||
|
||||
AuthPaginationHelper<RoleInfo> helper = createPaginationHelper();
|
||||
try {
|
||||
return helper.fetchPage(sqlCountRows + where, sqlFetchRows + where, params.toArray(), pageNo, pageSize,
|
||||
ROLE_INFO_ROW_MAPPER);
|
||||
@ -212,8 +215,8 @@ public class ExternalRolePersistServiceImpl implements RolePersistService {
|
||||
}
|
||||
|
||||
@Override
|
||||
public <E> PaginationHelper<E> createPaginationHelper() {
|
||||
return new ExternalStoragePaginationHelperImpl<>(jt);
|
||||
public <E> AuthPaginationHelper<E> createPaginationHelper() {
|
||||
return new AuthExternalPaginationHelperImpl<>(jt, dataSourceType);
|
||||
}
|
||||
|
||||
private static final class RoleInfoRowMapper implements RowMapper<RoleInfo> {
|
||||
|
@ -19,10 +19,10 @@ package com.alibaba.nacos.plugin.auth.impl.persistence;
|
||||
import com.alibaba.nacos.common.utils.StringUtils;
|
||||
import com.alibaba.nacos.config.server.utils.LogUtil;
|
||||
import com.alibaba.nacos.persistence.configuration.condition.ConditionOnExternalStorage;
|
||||
import com.alibaba.nacos.persistence.datasource.DataSourceService;
|
||||
import com.alibaba.nacos.persistence.datasource.DynamicDataSource;
|
||||
import com.alibaba.nacos.persistence.model.Page;
|
||||
import com.alibaba.nacos.persistence.repository.PaginationHelper;
|
||||
import com.alibaba.nacos.persistence.repository.extrnal.ExternalStoragePaginationHelperImpl;
|
||||
import com.alibaba.nacos.plugin.auth.impl.persistence.extrnal.AuthExternalPaginationHelperImpl;
|
||||
import org.springframework.context.annotation.Conditional;
|
||||
import org.springframework.dao.EmptyResultDataAccessException;
|
||||
import org.springframework.jdbc.CannotGetJdbcConnectionException;
|
||||
@ -46,11 +46,15 @@ public class ExternalUserPersistServiceImpl implements UserPersistService {
|
||||
|
||||
private JdbcTemplate jt;
|
||||
|
||||
private String dataSourceType = "";
|
||||
|
||||
private static final String PATTERN_STR = "*";
|
||||
|
||||
@PostConstruct
|
||||
protected void init() {
|
||||
jt = DynamicDataSource.getInstance().getDataSource().getJdbcTemplate();
|
||||
DataSourceService dataSource = DynamicDataSource.getInstance().getDataSource();
|
||||
jt = dataSource.getJdbcTemplate();
|
||||
dataSourceType = dataSource.getDataSourceType();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -127,8 +131,8 @@ public class ExternalUserPersistServiceImpl implements UserPersistService {
|
||||
|
||||
@Override
|
||||
public Page<User> getUsers(int pageNo, int pageSize, String username) {
|
||||
|
||||
PaginationHelper<User> helper = createPaginationHelper();
|
||||
|
||||
AuthPaginationHelper<User> helper = createPaginationHelper();
|
||||
|
||||
String sqlCountRows = "SELECT count(*) FROM users ";
|
||||
|
||||
@ -142,9 +146,8 @@ public class ExternalUserPersistServiceImpl implements UserPersistService {
|
||||
}
|
||||
|
||||
try {
|
||||
Page<User> pageInfo = helper
|
||||
.fetchPage(sqlCountRows + where, sqlFetchRows + where, params.toArray(), pageNo, pageSize,
|
||||
USER_ROW_MAPPER);
|
||||
Page<User> pageInfo = helper.fetchPage(sqlCountRows + where, sqlFetchRows + where, params.toArray(), pageNo,
|
||||
pageSize, USER_ROW_MAPPER);
|
||||
if (pageInfo == null) {
|
||||
pageInfo = new Page<>();
|
||||
pageInfo.setTotalCount(0);
|
||||
@ -175,8 +178,8 @@ public class ExternalUserPersistServiceImpl implements UserPersistService {
|
||||
where.append(" AND username LIKE ? ");
|
||||
params.add(generateLikeArgument(username));
|
||||
}
|
||||
|
||||
PaginationHelper<User> helper = createPaginationHelper();
|
||||
|
||||
AuthPaginationHelper<User> helper = createPaginationHelper();
|
||||
try {
|
||||
return helper.fetchPage(sqlCountRows + where, sqlFetchRows + where, params.toArray(), pageNo, pageSize,
|
||||
USER_ROW_MAPPER);
|
||||
@ -202,7 +205,7 @@ public class ExternalUserPersistServiceImpl implements UserPersistService {
|
||||
}
|
||||
|
||||
@Override
|
||||
public <E> PaginationHelper<E> createPaginationHelper() {
|
||||
return new ExternalStoragePaginationHelperImpl<>(jt);
|
||||
public <E> AuthPaginationHelper<E> createPaginationHelper() {
|
||||
return new AuthExternalPaginationHelperImpl<>(jt, dataSourceType);
|
||||
}
|
||||
}
|
||||
|
@ -17,7 +17,6 @@
|
||||
package com.alibaba.nacos.plugin.auth.impl.persistence;
|
||||
|
||||
import com.alibaba.nacos.persistence.model.Page;
|
||||
import com.alibaba.nacos.persistence.repository.PaginationHelper;
|
||||
|
||||
/**
|
||||
* Permission CRUD service.
|
||||
@ -64,7 +63,7 @@ public interface PermissionPersistService {
|
||||
* create Pagination utils.
|
||||
*
|
||||
* @param <E> Generic object
|
||||
* @return {@link PaginationHelper}
|
||||
* @return {@link AuthPaginationHelper}
|
||||
*/
|
||||
<E> PaginationHelper<E> createPaginationHelper();
|
||||
<E> AuthPaginationHelper<E> createPaginationHelper();
|
||||
}
|
||||
|
@ -16,10 +16,9 @@
|
||||
|
||||
package com.alibaba.nacos.plugin.auth.impl.persistence;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import com.alibaba.nacos.persistence.model.Page;
|
||||
import com.alibaba.nacos.persistence.repository.PaginationHelper;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Role CRUD service.
|
||||
@ -102,7 +101,7 @@ public interface RolePersistService {
|
||||
* create Pagination utils.
|
||||
*
|
||||
* @param <E> Generic object
|
||||
* @return {@link PaginationHelper}
|
||||
* @return {@link AuthPaginationHelper}
|
||||
*/
|
||||
<E> PaginationHelper<E> createPaginationHelper();
|
||||
<E> AuthPaginationHelper<E> createPaginationHelper();
|
||||
}
|
||||
|
@ -17,7 +17,6 @@
|
||||
package com.alibaba.nacos.plugin.auth.impl.persistence;
|
||||
|
||||
import com.alibaba.nacos.persistence.model.Page;
|
||||
import com.alibaba.nacos.persistence.repository.PaginationHelper;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@ -86,7 +85,7 @@ public interface UserPersistService {
|
||||
* create Pagination utils.
|
||||
*
|
||||
* @param <E> Generic object
|
||||
* @return {@link PaginationHelper}
|
||||
* @return {@link AuthPaginationHelper}
|
||||
*/
|
||||
<E> PaginationHelper<E> createPaginationHelper();
|
||||
<E> AuthPaginationHelper<E> createPaginationHelper();
|
||||
}
|
||||
|
@ -0,0 +1,230 @@
|
||||
/*
|
||||
* Copyright 1999-2023 Alibaba Group Holding Ltd.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.alibaba.nacos.plugin.auth.impl.persistence.embedded;
|
||||
|
||||
import com.alibaba.nacos.plugin.auth.impl.persistence.handler.PageHandlerAdapterFactory;
|
||||
import com.alibaba.nacos.plugin.auth.impl.model.OffsetFetchResult;
|
||||
import com.alibaba.nacos.persistence.model.Page;
|
||||
import com.alibaba.nacos.persistence.repository.embedded.EmbeddedStorageContextHolder;
|
||||
import com.alibaba.nacos.persistence.repository.embedded.operate.DatabaseOperate;
|
||||
import com.alibaba.nacos.plugin.auth.impl.persistence.AuthPaginationHelper;
|
||||
import com.alibaba.nacos.plugin.auth.impl.persistence.handler.support.DerbyPageHandlerAdapter;
|
||||
import com.alibaba.nacos.plugin.datasource.model.MapperResult;
|
||||
import org.springframework.jdbc.core.RowMapper;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Auth plugin Pagination Utils For Apache Derby.
|
||||
*
|
||||
* @param <E> Generic class
|
||||
* @author huangKeMing
|
||||
*/
|
||||
public class AuthEmbeddedPaginationHelperImpl<E> implements AuthPaginationHelper<E> {
|
||||
|
||||
private final DatabaseOperate databaseOperate;
|
||||
|
||||
public AuthEmbeddedPaginationHelperImpl(DatabaseOperate databaseOperate) {
|
||||
this.databaseOperate = databaseOperate;
|
||||
}
|
||||
|
||||
/**
|
||||
* Take paging.
|
||||
*
|
||||
* @param sqlCountRows Query total SQL
|
||||
* @param sqlFetchRows Query data sql
|
||||
* @param args query args
|
||||
* @param pageNo page number
|
||||
* @param pageSize page size
|
||||
* @param rowMapper Entity mapping
|
||||
* @return Paging data
|
||||
*/
|
||||
@Override
|
||||
public Page<E> fetchPage(final String sqlCountRows, final String sqlFetchRows, final Object[] args,
|
||||
final int pageNo, final int pageSize, final RowMapper rowMapper) {
|
||||
return fetchPage(sqlCountRows, sqlFetchRows, args, pageNo, pageSize, null, rowMapper);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Page<E> fetchPage(final String sqlCountRows, final String sqlFetchRows, Object[] args, final int pageNo,
|
||||
final int pageSize, final Long lastMaxId, final RowMapper rowMapper) {
|
||||
if (pageNo <= 0 || pageSize <= 0) {
|
||||
throw new IllegalArgumentException("pageNo and pageSize must be greater than zero");
|
||||
}
|
||||
|
||||
// Query the total number of current records
|
||||
Integer rowCountInt = databaseOperate.queryOne(sqlCountRows, args, Integer.class);
|
||||
if (rowCountInt == null) {
|
||||
throw new IllegalArgumentException("fetchPageLimit error");
|
||||
}
|
||||
|
||||
// Count pages
|
||||
int pageCount = rowCountInt / pageSize;
|
||||
if (rowCountInt > pageSize * pageCount) {
|
||||
pageCount++;
|
||||
}
|
||||
|
||||
// Create Page object
|
||||
final Page<E> page = new Page<>();
|
||||
page.setPageNumber(pageNo);
|
||||
page.setPagesAvailable(pageCount);
|
||||
page.setTotalCount(rowCountInt);
|
||||
|
||||
if (pageNo > pageCount) {
|
||||
return page;
|
||||
}
|
||||
|
||||
// fill the sql Page args
|
||||
String fetchSql = sqlFetchRows;
|
||||
OffsetFetchResult offsetFetchResult = addOffsetAndFetchNext(fetchSql, args, pageNo, pageSize);
|
||||
fetchSql = offsetFetchResult.getFetchSql();
|
||||
args = offsetFetchResult.getNewArgs();
|
||||
|
||||
List<E> result = databaseOperate.queryMany(fetchSql, args, rowMapper);
|
||||
for (E item : result) {
|
||||
page.getPageItems().add(item);
|
||||
}
|
||||
return page;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Page<E> fetchPageLimit(final String sqlCountRows, final String sqlFetchRows, Object[] args, final int pageNo,
|
||||
final int pageSize, final RowMapper rowMapper) {
|
||||
if (pageNo <= 0 || pageSize <= 0) {
|
||||
throw new IllegalArgumentException("pageNo and pageSize must be greater than zero");
|
||||
}
|
||||
// Query the total number of current records
|
||||
Integer rowCountInt = databaseOperate.queryOne(sqlCountRows, Integer.class);
|
||||
if (rowCountInt == null) {
|
||||
throw new IllegalArgumentException("fetchPageLimit error");
|
||||
}
|
||||
|
||||
// Count pages
|
||||
int pageCount = rowCountInt / pageSize;
|
||||
if (rowCountInt > pageSize * pageCount) {
|
||||
pageCount++;
|
||||
}
|
||||
|
||||
// Create Page object
|
||||
final Page<E> page = new Page<>();
|
||||
page.setPageNumber(pageNo);
|
||||
page.setPagesAvailable(pageCount);
|
||||
page.setTotalCount(rowCountInt);
|
||||
|
||||
if (pageNo > pageCount) {
|
||||
return page;
|
||||
}
|
||||
|
||||
// fill the sql Page args
|
||||
String fetchSql = sqlFetchRows;
|
||||
OffsetFetchResult offsetFetchResult = addOffsetAndFetchNext(fetchSql, args, pageNo, pageSize);
|
||||
fetchSql = offsetFetchResult.getFetchSql();
|
||||
args = offsetFetchResult.getNewArgs();
|
||||
|
||||
List<E> result = databaseOperate.queryMany(fetchSql, args, rowMapper);
|
||||
for (E item : result) {
|
||||
page.getPageItems().add(item);
|
||||
}
|
||||
return page;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Page<E> fetchPageLimit(final String sqlCountRows, final Object[] args1, final String sqlFetchRows,
|
||||
Object[] args2, final int pageNo, final int pageSize, final RowMapper rowMapper) {
|
||||
if (pageNo <= 0 || pageSize <= 0) {
|
||||
throw new IllegalArgumentException("pageNo and pageSize must be greater than zero");
|
||||
}
|
||||
// Query the total number of current records
|
||||
Integer rowCountInt = databaseOperate.queryOne(sqlCountRows, args1, Integer.class);
|
||||
if (rowCountInt == null) {
|
||||
throw new IllegalArgumentException("fetchPageLimit error");
|
||||
}
|
||||
|
||||
// Count pages
|
||||
int pageCount = rowCountInt / pageSize;
|
||||
if (rowCountInt > pageSize * pageCount) {
|
||||
pageCount++;
|
||||
}
|
||||
|
||||
// Create Page object
|
||||
final Page<E> page = new Page<>();
|
||||
page.setPageNumber(pageNo);
|
||||
page.setPagesAvailable(pageCount);
|
||||
page.setTotalCount(rowCountInt);
|
||||
|
||||
if (pageNo > pageCount) {
|
||||
return page;
|
||||
}
|
||||
|
||||
// fill the sql Page args
|
||||
String fetchSql = sqlFetchRows;
|
||||
OffsetFetchResult offsetFetchResult = addOffsetAndFetchNext(fetchSql, args2, pageNo, pageSize);
|
||||
fetchSql = offsetFetchResult.getFetchSql();
|
||||
args2 = offsetFetchResult.getNewArgs();
|
||||
|
||||
List<E> result = databaseOperate.queryMany(fetchSql, args2, rowMapper);
|
||||
for (E item : result) {
|
||||
page.getPageItems().add(item);
|
||||
}
|
||||
return page;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Page<E> fetchPageLimit(final String sqlFetchRows, Object[] args, final int pageNo, final int pageSize,
|
||||
final RowMapper rowMapper) {
|
||||
if (pageNo <= 0 || pageSize <= 0) {
|
||||
throw new IllegalArgumentException("pageNo and pageSize must be greater than zero");
|
||||
}
|
||||
// Create Page object
|
||||
final Page<E> page = new Page<>();
|
||||
|
||||
// fill the sql Page args
|
||||
String fetchSql = sqlFetchRows;
|
||||
OffsetFetchResult offsetFetchResult = addOffsetAndFetchNext(fetchSql, args, pageNo, pageSize);
|
||||
fetchSql = offsetFetchResult.getFetchSql();
|
||||
args = offsetFetchResult.getNewArgs();
|
||||
|
||||
List<E> result = databaseOperate.queryMany(fetchSql, args, rowMapper);
|
||||
for (E item : result) {
|
||||
page.getPageItems().add(item);
|
||||
}
|
||||
return page;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Page fetchPageLimit(MapperResult countMapperResult, MapperResult mapperResult, int pageNo, int pageSize,
|
||||
RowMapper rowMapper) {
|
||||
return fetchPageLimit(countMapperResult.getSql(), countMapperResult.getParamList().toArray(),
|
||||
mapperResult.getSql(), mapperResult.getParamList().toArray(), pageNo, pageSize, rowMapper);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateLimit(final String sql, final Object[] args) {
|
||||
EmbeddedStorageContextHolder.addSqlContext(sql, args);
|
||||
try {
|
||||
databaseOperate.update(EmbeddedStorageContextHolder.getCurrentSqlContext());
|
||||
} finally {
|
||||
EmbeddedStorageContextHolder.cleanAllContext();
|
||||
}
|
||||
}
|
||||
|
||||
private OffsetFetchResult addOffsetAndFetchNext(String fetchSql, Object[] arg, int pageNo, int pageSize) {
|
||||
return PageHandlerAdapterFactory.getInstance().getHandlerAdapterMap()
|
||||
.get(DerbyPageHandlerAdapter.class.getName()).addOffsetAndFetchNext(fetchSql, arg, pageNo, pageSize);
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,267 @@
|
||||
/*
|
||||
* Copyright 1999-2023 Alibaba Group Holding Ltd.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.alibaba.nacos.plugin.auth.impl.persistence.extrnal;
|
||||
|
||||
import com.alibaba.nacos.persistence.model.Page;
|
||||
import com.alibaba.nacos.persistence.repository.embedded.EmbeddedStorageContextHolder;
|
||||
import com.alibaba.nacos.plugin.auth.impl.model.OffsetFetchResult;
|
||||
import com.alibaba.nacos.plugin.auth.impl.persistence.AuthPaginationHelper;
|
||||
import com.alibaba.nacos.plugin.auth.impl.persistence.handler.PageHandlerAdapter;
|
||||
import com.alibaba.nacos.plugin.auth.impl.persistence.handler.PageHandlerAdapterFactory;
|
||||
import com.alibaba.nacos.plugin.auth.impl.persistence.handler.support.DefaultPageHandlerAdapter;
|
||||
import com.alibaba.nacos.plugin.datasource.model.MapperResult;
|
||||
import org.springframework.jdbc.core.JdbcTemplate;
|
||||
import org.springframework.jdbc.core.RowMapper;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Auth plugin Pagination Utils For Apache External.
|
||||
*
|
||||
* @param <E> Generic class
|
||||
* @author huangKeMing
|
||||
*/
|
||||
public class AuthExternalPaginationHelperImpl<E> implements AuthPaginationHelper<E> {
|
||||
|
||||
private final JdbcTemplate jdbcTemplate;
|
||||
|
||||
private volatile String dataSourceType;
|
||||
|
||||
public AuthExternalPaginationHelperImpl(JdbcTemplate jdbcTemplate, String dataSourceType) {
|
||||
this.jdbcTemplate = jdbcTemplate;
|
||||
this.dataSourceType = dataSourceType;
|
||||
}
|
||||
|
||||
/**
|
||||
* Take paging.
|
||||
*
|
||||
* @param sqlCountRows query total SQL
|
||||
* @param sqlFetchRows query data sql
|
||||
* @param args query parameters
|
||||
* @param pageNo page number
|
||||
* @param pageSize page size
|
||||
* @param rowMapper {@link RowMapper}
|
||||
* @return Paginated data {@code <E>}
|
||||
*/
|
||||
@Override
|
||||
public Page<E> fetchPage(final String sqlCountRows, final String sqlFetchRows, final Object[] args,
|
||||
final int pageNo, final int pageSize, final RowMapper rowMapper) {
|
||||
return fetchPage(sqlCountRows, sqlFetchRows, args, pageNo, pageSize, null, rowMapper);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Page<E> fetchPage(final String sqlCountRows, final String sqlFetchRows, Object[] args, final int pageNo,
|
||||
final int pageSize, final Long lastMaxId, final RowMapper rowMapper) {
|
||||
if (pageNo <= 0 || pageSize <= 0) {
|
||||
throw new IllegalArgumentException("pageNo and pageSize must be greater than zero");
|
||||
}
|
||||
|
||||
// Query the total number of current records.
|
||||
Integer rowCountInt = jdbcTemplate.queryForObject(sqlCountRows, args, Integer.class);
|
||||
if (rowCountInt == null) {
|
||||
throw new IllegalArgumentException("fetchPageLimit error");
|
||||
}
|
||||
|
||||
// Compute pages count
|
||||
int pageCount = rowCountInt / pageSize;
|
||||
if (rowCountInt > pageSize * pageCount) {
|
||||
pageCount++;
|
||||
}
|
||||
|
||||
// Create Page object
|
||||
final Page<E> page = new Page<>();
|
||||
page.setPageNumber(pageNo);
|
||||
page.setPagesAvailable(pageCount);
|
||||
page.setTotalCount(rowCountInt);
|
||||
|
||||
if (pageNo > pageCount) {
|
||||
return page;
|
||||
}
|
||||
|
||||
// fill the sql Page args
|
||||
String fetchSql = sqlFetchRows;
|
||||
OffsetFetchResult offsetFetchResult = addOffsetAndFetchNext(fetchSql, args, pageNo, pageSize);
|
||||
fetchSql = offsetFetchResult.getFetchSql();
|
||||
args = offsetFetchResult.getNewArgs();
|
||||
|
||||
List<E> result = jdbcTemplate.query(fetchSql, args, rowMapper);
|
||||
for (E item : result) {
|
||||
page.getPageItems().add(item);
|
||||
}
|
||||
return page;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Page<E> fetchPageLimit(final String sqlCountRows, final String sqlFetchRows, Object[] args, final int pageNo,
|
||||
final int pageSize, final RowMapper rowMapper) {
|
||||
if (pageNo <= 0 || pageSize <= 0) {
|
||||
throw new IllegalArgumentException("pageNo and pageSize must be greater than zero");
|
||||
}
|
||||
// Query the total number of current records
|
||||
Integer rowCountInt = jdbcTemplate.queryForObject(sqlCountRows, Integer.class);
|
||||
if (rowCountInt == null) {
|
||||
throw new IllegalArgumentException("fetchPageLimit error");
|
||||
}
|
||||
|
||||
// Compute pages count
|
||||
int pageCount = rowCountInt / pageSize;
|
||||
if (rowCountInt > pageSize * pageCount) {
|
||||
pageCount++;
|
||||
}
|
||||
|
||||
// Create Page object
|
||||
final Page<E> page = new Page<>();
|
||||
page.setPageNumber(pageNo);
|
||||
page.setPagesAvailable(pageCount);
|
||||
page.setTotalCount(rowCountInt);
|
||||
|
||||
if (pageNo > pageCount) {
|
||||
return page;
|
||||
}
|
||||
|
||||
// fill the sql Page args
|
||||
String fetchSql = sqlFetchRows;
|
||||
OffsetFetchResult offsetFetchResult = addOffsetAndFetchNext(fetchSql, args, pageNo, pageSize);
|
||||
fetchSql = offsetFetchResult.getFetchSql();
|
||||
args = offsetFetchResult.getNewArgs();
|
||||
|
||||
List<E> result = jdbcTemplate.query(fetchSql, args, rowMapper);
|
||||
for (E item : result) {
|
||||
page.getPageItems().add(item);
|
||||
}
|
||||
return page;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Page fetchPageLimit(MapperResult countMapperResult, MapperResult mapperResult, int pageNo, int pageSize,
|
||||
RowMapper rowMapper) {
|
||||
return fetchPageLimit(countMapperResult.getSql(), countMapperResult.getParamList().toArray(),
|
||||
mapperResult.getSql(), mapperResult.getParamList().toArray(), pageNo, pageSize, rowMapper);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Page<E> fetchPageLimit(final String sqlCountRows, final Object[] args1, final String sqlFetchRows,
|
||||
Object[] args2, final int pageNo, final int pageSize, final RowMapper rowMapper) {
|
||||
if (pageNo <= 0 || pageSize <= 0) {
|
||||
throw new IllegalArgumentException("pageNo and pageSize must be greater than zero");
|
||||
}
|
||||
// Query the total number of current records
|
||||
Integer rowCountInt = jdbcTemplate.queryForObject(sqlCountRows, args1, Integer.class);
|
||||
if (rowCountInt == null) {
|
||||
throw new IllegalArgumentException("fetchPageLimit error");
|
||||
}
|
||||
|
||||
// Compute pages count
|
||||
int pageCount = rowCountInt / pageSize;
|
||||
if (rowCountInt > pageSize * pageCount) {
|
||||
pageCount++;
|
||||
}
|
||||
|
||||
// Create Page object
|
||||
final Page<E> page = new Page<>();
|
||||
page.setPageNumber(pageNo);
|
||||
page.setPagesAvailable(pageCount);
|
||||
page.setTotalCount(rowCountInt);
|
||||
|
||||
if (pageNo > pageCount) {
|
||||
return page;
|
||||
}
|
||||
// fill the sql Page args
|
||||
String fetchSql = sqlFetchRows;
|
||||
OffsetFetchResult offsetFetchResult = addOffsetAndFetchNext(fetchSql, args2, pageNo, pageSize);
|
||||
fetchSql = offsetFetchResult.getFetchSql();
|
||||
args2 = offsetFetchResult.getNewArgs();
|
||||
|
||||
List<E> result = jdbcTemplate.query(fetchSql, args2, rowMapper);
|
||||
for (E item : result) {
|
||||
page.getPageItems().add(item);
|
||||
}
|
||||
return page;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Page<E> fetchPageLimit(final String sqlFetchRows, Object[] args, final int pageNo, final int pageSize,
|
||||
final RowMapper rowMapper) {
|
||||
if (pageNo <= 0 || pageSize <= 0) {
|
||||
throw new IllegalArgumentException("pageNo and pageSize must be greater than zero");
|
||||
}
|
||||
// Create Page object
|
||||
final Page<E> page = new Page<>();
|
||||
|
||||
// fill the sql Page args
|
||||
String fetchSql = sqlFetchRows;
|
||||
OffsetFetchResult offsetFetchResult = addOffsetAndFetchNext(fetchSql, args, pageNo, pageSize);
|
||||
fetchSql = offsetFetchResult.getFetchSql();
|
||||
args = offsetFetchResult.getNewArgs();
|
||||
|
||||
List<E> result = jdbcTemplate.query(fetchSql, args, rowMapper);
|
||||
for (E item : result) {
|
||||
page.getPageItems().add(item);
|
||||
}
|
||||
return page;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateLimit(final String sql, final Object[] args) {
|
||||
try {
|
||||
jdbcTemplate.update(sql, args);
|
||||
} finally {
|
||||
EmbeddedStorageContextHolder.cleanAllContext();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Update limit with response.
|
||||
*
|
||||
* @param sql sql
|
||||
* @param args args
|
||||
* @return update row count
|
||||
*/
|
||||
public int updateLimitWithResponse(final String sql, final Object[] args) {
|
||||
String sqlUpdate = sql;
|
||||
|
||||
try {
|
||||
return jdbcTemplate.update(sqlUpdate, args);
|
||||
} finally {
|
||||
EmbeddedStorageContextHolder.cleanAllContext();
|
||||
}
|
||||
}
|
||||
|
||||
private OffsetFetchResult addOffsetAndFetchNext(String fetchSql, Object[] arg, int pageNo, int pageSize) {
|
||||
return getHandlerAdapter(dataSourceType).addOffsetAndFetchNext(fetchSql, arg, pageNo, pageSize);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get handler adapter.
|
||||
*
|
||||
* @param dataSourceType data source type.
|
||||
* @return
|
||||
*/
|
||||
protected PageHandlerAdapter getHandlerAdapter(String dataSourceType) {
|
||||
List<PageHandlerAdapter> handlerAdapters = PageHandlerAdapterFactory.getInstance().getHandlerAdapters();
|
||||
for (PageHandlerAdapter adapter : handlerAdapters) {
|
||||
if (adapter.supports(dataSourceType)) {
|
||||
return adapter;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return PageHandlerAdapterFactory.getInstance().getHandlerAdapterMap()
|
||||
.get(DefaultPageHandlerAdapter.class.getName());
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,46 @@
|
||||
/*
|
||||
* Copyright 1999-2023 Alibaba Group Holding Ltd.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.alibaba.nacos.plugin.auth.impl.persistence.handler;
|
||||
|
||||
import com.alibaba.nacos.plugin.auth.impl.model.OffsetFetchResult;
|
||||
|
||||
/**
|
||||
* Auth plugin page handler adapter.
|
||||
*
|
||||
* @author huangKeMing
|
||||
*/
|
||||
public interface PageHandlerAdapter {
|
||||
|
||||
/**
|
||||
* Determine whether the current data source supports paging.
|
||||
*
|
||||
* @param dataSourceType data source type
|
||||
* @return true if the current data source supports paging
|
||||
*/
|
||||
boolean supports(String dataSourceType);
|
||||
|
||||
/**
|
||||
* Add offset and fetch next.
|
||||
*
|
||||
* @param fetchSql fetch sql.
|
||||
* @param arg arguments.
|
||||
* @param pageNo page number.
|
||||
* @param pageSize page size.
|
||||
* @return
|
||||
*/
|
||||
OffsetFetchResult addOffsetAndFetchNext(String fetchSql, Object[] arg, int pageNo, int pageSize);
|
||||
}
|
@ -0,0 +1,83 @@
|
||||
/*
|
||||
* Copyright 1999-2023 Alibaba Group Holding Ltd.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.alibaba.nacos.plugin.auth.impl.persistence.handler;
|
||||
|
||||
import com.alibaba.nacos.plugin.auth.impl.persistence.handler.support.DerbyPageHandlerAdapter;
|
||||
import com.alibaba.nacos.plugin.auth.impl.persistence.handler.support.MysqlPageHandlerAdapter;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* pagination factory.
|
||||
*
|
||||
* @author huangKeMing
|
||||
*/
|
||||
public class PageHandlerAdapterFactory {
|
||||
|
||||
private static PageHandlerAdapterFactory instance;
|
||||
|
||||
private List<PageHandlerAdapter> handlerAdapters;
|
||||
|
||||
private Map<String, PageHandlerAdapter> handlerAdapterMap;
|
||||
|
||||
public List<PageHandlerAdapter> getHandlerAdapters() {
|
||||
return handlerAdapters;
|
||||
}
|
||||
|
||||
public Map<String, PageHandlerAdapter> getHandlerAdapterMap() {
|
||||
return handlerAdapterMap;
|
||||
}
|
||||
|
||||
private PageHandlerAdapterFactory() {
|
||||
handlerAdapters = new ArrayList<>(2);
|
||||
handlerAdapterMap = new HashMap<>(2);
|
||||
initHandlerAdapters();
|
||||
}
|
||||
|
||||
public static PageHandlerAdapterFactory getInstance() {
|
||||
if (instance == null) {
|
||||
synchronized (PageHandlerAdapterFactory.class) {
|
||||
if (instance == null) {
|
||||
instance = new PageHandlerAdapterFactory();
|
||||
}
|
||||
}
|
||||
}
|
||||
return instance;
|
||||
}
|
||||
|
||||
/**
|
||||
* init handler adapters.
|
||||
*/
|
||||
private void initHandlerAdapters() {
|
||||
// MysqlPageHandlerAdapter
|
||||
addHandlerAdapter(new MysqlPageHandlerAdapter());
|
||||
// DerbyPageHandlerAdapter
|
||||
addHandlerAdapter(new DerbyPageHandlerAdapter());
|
||||
// DefaultPageHandlerAdapter
|
||||
addHandlerAdapter(new DerbyPageHandlerAdapter());
|
||||
}
|
||||
|
||||
private void addHandlerAdapter(PageHandlerAdapter handlerAdapter) {
|
||||
handlerAdapters.add(handlerAdapter);
|
||||
handlerAdapterMap.put(handlerAdapter.getClass().getName(), handlerAdapter);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -0,0 +1,39 @@
|
||||
/*
|
||||
* Copyright 1999-2023 Alibaba Group Holding Ltd.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.alibaba.nacos.plugin.auth.impl.persistence.handler.support;
|
||||
|
||||
import com.alibaba.nacos.plugin.auth.impl.model.OffsetFetchResult;
|
||||
import com.alibaba.nacos.plugin.auth.impl.persistence.handler.PageHandlerAdapter;
|
||||
|
||||
/**
|
||||
* Default page handler adapter.
|
||||
*
|
||||
* @author huangKeMing
|
||||
*/
|
||||
public class DefaultPageHandlerAdapter implements PageHandlerAdapter {
|
||||
|
||||
@Override
|
||||
public boolean supports(String dataSourceType) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public OffsetFetchResult addOffsetAndFetchNext(String fetchSql, Object[] arg, int pageNo, int pageSize) {
|
||||
return new OffsetFetchResult(fetchSql, arg);
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,57 @@
|
||||
/*
|
||||
* Copyright 1999-2023 Alibaba Group Holding Ltd.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.alibaba.nacos.plugin.auth.impl.persistence.handler.support;
|
||||
|
||||
import com.alibaba.nacos.persistence.constants.PersistenceConstant;
|
||||
import com.alibaba.nacos.plugin.auth.impl.constant.AuthPageConstant;
|
||||
import com.alibaba.nacos.plugin.auth.impl.model.OffsetFetchResult;
|
||||
import com.alibaba.nacos.plugin.auth.impl.persistence.handler.PageHandlerAdapter;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* derby page handler adapter.
|
||||
*
|
||||
* @author huangKeMing
|
||||
*/
|
||||
public class DerbyPageHandlerAdapter implements PageHandlerAdapter {
|
||||
|
||||
@Override
|
||||
public boolean supports(String dataSourceType) {
|
||||
return PersistenceConstant.DERBY.equals(dataSourceType);
|
||||
}
|
||||
|
||||
@Override
|
||||
public OffsetFetchResult addOffsetAndFetchNext(String fetchSql, Object[] arg, int pageNo, int pageSize) {
|
||||
if (!fetchSql.contains(AuthPageConstant.OFFSET)) {
|
||||
fetchSql += " " + AuthPageConstant.OFFSET_ROWS + " " + AuthPageConstant.FETCH_NEXT;
|
||||
|
||||
List<Object> newArgsList = new ArrayList<>(Arrays.asList(arg));
|
||||
newArgsList.add((pageNo - 1) * pageSize);
|
||||
newArgsList.add(pageSize);
|
||||
|
||||
Object[] newArgs = newArgsList.toArray(new Object[newArgsList.size()]);
|
||||
|
||||
return new OffsetFetchResult(fetchSql, newArgs);
|
||||
}
|
||||
|
||||
return new OffsetFetchResult(fetchSql, arg);
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,55 @@
|
||||
/*
|
||||
* Copyright 1999-2023 Alibaba Group Holding Ltd.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.alibaba.nacos.plugin.auth.impl.persistence.handler.support;
|
||||
|
||||
import com.alibaba.nacos.persistence.constants.PersistenceConstant;
|
||||
import com.alibaba.nacos.plugin.auth.impl.constant.AuthPageConstant;
|
||||
import com.alibaba.nacos.plugin.auth.impl.model.OffsetFetchResult;
|
||||
import com.alibaba.nacos.plugin.auth.impl.persistence.handler.PageHandlerAdapter;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* mysql page handler adapter.
|
||||
*
|
||||
* @author huangKeMing
|
||||
*/
|
||||
public class MysqlPageHandlerAdapter implements PageHandlerAdapter {
|
||||
|
||||
@Override
|
||||
public boolean supports(String dataSourceType) {
|
||||
return PersistenceConstant.MYSQL.equals(dataSourceType);
|
||||
}
|
||||
|
||||
@Override
|
||||
public OffsetFetchResult addOffsetAndFetchNext(String fetchSql, Object[] arg, int pageNo, int pageSize) {
|
||||
if (!fetchSql.contains(AuthPageConstant.LIMIT)) {
|
||||
fetchSql += " " + AuthPageConstant.LIMIT_SIZE;
|
||||
List<Object> newArgsList = new ArrayList<>(Arrays.asList(arg));
|
||||
newArgsList.add((pageNo - 1) * pageSize);
|
||||
newArgsList.add(pageSize);
|
||||
|
||||
Object[] newArgs = newArgsList.toArray(new Object[newArgsList.size()]);
|
||||
return new OffsetFetchResult(fetchSql, newArgs);
|
||||
}
|
||||
|
||||
return new OffsetFetchResult(fetchSql, arg);
|
||||
}
|
||||
|
||||
}
|
Loading…
Reference in New Issue
Block a user