perf: SQLBot 数据源接口 行列权限机制优化

This commit is contained in:
fit2cloud-chenyw
2025-09-08 17:25:29 +08:00
committed by fit2cloud-chenyw
parent c4fcd23f8b
commit ee1870a172
4 changed files with 149 additions and 30 deletions

View File

@@ -31,8 +31,10 @@ import io.dataease.engine.trans.WhereTree2Str;
import io.dataease.engine.utils.Utils;
import io.dataease.exception.DEException;
import io.dataease.extensions.datasource.api.PluginManageApi;
import io.dataease.extensions.datasource.dto.CalParam;
import io.dataease.extensions.datasource.dto.DatasetTableFieldDTO;
import io.dataease.extensions.datasource.dto.DatasourceSchemaDTO;
import io.dataease.extensions.datasource.dto.FieldGroupDTO;
import io.dataease.extensions.datasource.factory.ProviderFactory;
import io.dataease.extensions.datasource.model.SQLMeta;
import io.dataease.extensions.datasource.provider.Provider;
@@ -270,7 +272,11 @@ public class DatasetSQLBotManage {
}
}
private void rebuildTable(SQLBotAssistanTable table, List<DataSetColumnPermissionsDTO> columnPermissionsDTOS, List<DataSetRowPermissionsTreeDTO> rowPermissionsTree) {
TypeReference<List<FieldGroupDTO>> groupTokenType = new TypeReference<>() {
};
TypeReference<List<CalParam>> typeToken = new TypeReference<>() {
};
private void rebuildTable(SQLBotAssistanTable table, List<DataSetColumnPermissionsDTO> columnPermissionsDTOS, List<DataSetRowPermissionsTreeDTO> rowPermissionsTree, Map<String, Object> dsRowData) {
Map<String, Object> rowData = table.getRowData();
CoreDatasetGroup coreDatasetGroup = BeanUtils.mapToBean(rowData, CoreDatasetGroup.class);
@@ -287,6 +293,12 @@ public class DatasetSQLBotManage {
List<DatasetTableFieldDTO> dsFields = sqlbotFields.stream().map(field -> {
Map<String, Object> fieldRowData = field.getRowData();
DatasetTableFieldDTO fieldDTO = BeanUtils.mapToBean(fieldRowData, DatasetTableFieldDTO.class);
if (ObjectUtils.isNotEmpty(fieldRowData.get("group_list"))) {
fieldDTO.setGroupList(JsonUtil.parseList(fieldRowData.get("group_list").toString(), groupTokenType));
}
if (ObjectUtils.isNotEmpty(fieldRowData.get("params"))) {
fieldDTO.setParams(JsonUtil.parseList(fieldRowData.get("params").toString(), typeToken));
}
fieldDTO.setFieldShortName(fieldDTO.getDataeaseName());
return fieldDTO;
}).collect(Collectors.toList());
@@ -301,8 +313,16 @@ public class DatasetSQLBotManage {
}
Map<String, Object> sqlMap = null;
CoreDatasource coreDatasource = null;
String dsType = dsRowData.get("type").toString();
Configuration config = null;
if (dsType.contains(DatasourceConfiguration.DatasourceType.Excel.name()) || dsType.contains(DatasourceConfiguration.DatasourceType.API.name())) {
coreDatasource = deEngine;
} else {
coreDatasource = BeanUtils.mapToBean(dsRowData, CoreDatasource.class);
}
try {
sqlMap = datasetSQLManage.getUnionSQLForEdit(datasetGroupInfoDTO, null);
sqlMap = datasetSQLManage.getUnionSQLForEdit(datasetGroupInfoDTO, null, coreDatasource);
} catch (Exception e) {
throw new RuntimeException(e);
}
@@ -357,7 +377,7 @@ public class DatasetSQLBotManage {
Order2SQLObj.getOrders(sqlMeta, datasetGroupInfoDTO.getSortFields(), fields, false, dsMap, Utils.getParams(fields), null, pluginManage);
String querySQL;
querySQL = SQLProvider.createQuerySQL(sqlMeta, false, needOrder, false);
querySQL = provider.rebuildSQL(querySQL, sqlMeta, false, dsMap);
querySQL = provider.rebuildSQL(querySQL, sqlMeta, false, dsMap, true);
table.setSql(querySQL);
}
@@ -371,13 +391,18 @@ public class DatasetSQLBotManage {
return;
}
vos.forEach(vo -> {
Map<String, Object> dsRowData = vo.getRowData();
List<SQLBotAssistanTable> tables = vo.getTables();
tables.forEach(table -> {
Long datasetGroupId = table.getDatasetGroupId();
List<DataSetColumnPermissionsDTO> columnPermissionsDTOS = ObjectUtils.isEmpty(colPermissionMap) ? null : colPermissionMap.get(datasetGroupId);
List<DataSetRowPermissionsTreeDTO> rowPermissionsTreeDTOS = ObjectUtils.isEmpty(rowPermissionMap) ? null : rowPermissionMap.get(datasetGroupId);
if (table.isNeedTransform() || ObjectUtils.isNotEmpty(columnPermissionsDTOS) || ObjectUtils.isNotEmpty(rowPermissionsTreeDTOS)) {
rebuildTable(table, columnPermissionsDTOS, rowPermissionsTreeDTOS);
try {
rebuildTable(table, columnPermissionsDTOS, rowPermissionsTreeDTOS, dsRowData);
} catch (Exception e) {
LogUtil.error(e);
}
}
});
});
@@ -416,16 +441,17 @@ public class DatasetSQLBotManage {
dsHost = environment.getProperty("dataease.dataease-servers", String.class);
}
String dsType = row.get("cd_type").toString();
String config_json = null;
Configuration config = null;
if (dsType.contains(DatasourceConfiguration.DatasourceType.Excel.name()) || dsType.contains(DatasourceConfiguration.DatasourceType.API.name())) {
String config_json = EncryptUtils.aesDecrypt(deEngine.getConfiguration()).toString();
config_json = EncryptUtils.aesDecrypt(deEngine.getConfiguration()).toString();
config = JsonUtil.parseObject(config_json, Configuration.class);
if (StringUtils.isNotBlank(dsHost) && ObjectUtils.isNotEmpty(config)) {
config.setHost(dsHost);
}
dsType = deEngine.getType();
} else {
String config_json = EncryptUtils.aesDecrypt(dsConfig.toString()).toString();
config_json = EncryptUtils.aesDecrypt(dsConfig.toString()).toString();
config = JsonUtil.parseObject(config_json, Configuration.class);
}
DataSQLBotAssistantVO vo = new DataSQLBotAssistantVO();
@@ -439,7 +465,10 @@ public class DatasetSQLBotManage {
vo.setSchema(config.getSchema());
vo.setUser(config.getUsername());
vo.setPassword(config.getPassword());
vo.setRowData(buildRowData(row, 0));
row.put("cd_configuration", config_json);
Map<String, Object> rowData = buildRowData(row, 0);
rowData.put("id", Long.parseLong(row.get("cd_id").toString()));
vo.setRowData(rowData);
if (encryptEnabled) {
aesVO(vo);
}

View File

@@ -124,6 +124,10 @@ public class DatasetSQLManage {
}
public Map<String, Object> getUnionSQLForEdit(DatasetGroupInfoDTO dataTableInfoDTO, ChartExtRequest chartExtRequest) throws Exception {
return getUnionSQLForEdit(dataTableInfoDTO, chartExtRequest, null);
}
public Map<String, Object> getUnionSQLForEdit(DatasetGroupInfoDTO dataTableInfoDTO, ChartExtRequest chartExtRequest, CoreDatasource coreDatasource) throws Exception {
Map<Long, DatasourceSchemaDTO> dsMap = new LinkedHashMap<>();
List<UnionDTO> union = dataTableInfoDTO.getUnion();
// 所有选中的字段即select后的查询字段
@@ -146,7 +150,7 @@ public class DatasetSQLManage {
if (dsMap.containsKey(datasetTable.getDatasourceId())) {
schema = dsMap.get(datasetTable.getDatasourceId()).getSchemaAlias();
} else {
schema = putObj2Map(dsMap, datasetTable, isCross);
schema = putObj2Map(dsMap, datasetTable, isCross, coreDatasource);
}
SQLObj table = getUnionTable(datasetTable, tableInfo, schema, i, filterParameters(chartExtRequest, currentDs.getId()), chartExtRequest == null, isCross, dsMap);
if (i == 0) {
@@ -491,24 +495,29 @@ public class DatasetSQLManage {
}
public String putObj2Map(Map<Long, DatasourceSchemaDTO> dsMap, DatasetTableDTO ds, boolean isCross) {
return putObj2Map(dsMap, ds, isCross, null);
}
public String putObj2Map(Map<Long, DatasourceSchemaDTO> dsMap, DatasetTableDTO ds, boolean isCross, CoreDatasource coreDatasource) {
// 通过datasource id校验数据源权限
BusiPerCheckDTO dto = new BusiPerCheckDTO();
dto.setId(ds.getDatasourceId());
dto.setAuthEnum(AuthEnum.READ);
boolean checked = corePermissionManage.checkAuth(dto);
if (!checked) {
DEException.throwException(Translator.get("i18n_no_datasource_permission"));
if (ObjectUtils.isEmpty(coreDatasource)) {
BusiPerCheckDTO dto = new BusiPerCheckDTO();
dto.setId(ds.getDatasourceId());
dto.setAuthEnum(AuthEnum.READ);
boolean checked = corePermissionManage.checkAuth(dto);
if (!checked) {
DEException.throwException(Translator.get("i18n_no_datasource_permission"));
}
}
String schemaAlias;
if (StringUtils.equalsIgnoreCase(ds.getType(), DatasetTableType.DB) || StringUtils.equalsIgnoreCase(ds.getType(), DatasetTableType.SQL)) {
CoreDatasource coreDatasource = dataSourceManage.getCoreDatasource(ds.getDatasourceId());
if (coreDatasource == null) {
DEException.throwException(Translator.get("i18n_dataset_ds_error") + ",ID:" + ds.getDatasourceId());
}
if (coreDatasource.getType().contains(DatasourceConfiguration.DatasourceType.Excel.name()) || coreDatasource.getType().contains(DatasourceConfiguration.DatasourceType.API.name())) {
coreDatasource = engineManage.getDeEngine();
if (ObjectUtils.isEmpty(coreDatasource)) {
coreDatasource = dataSourceManage.getCoreDatasource(ds.getDatasourceId());
if (coreDatasource == null) {
DEException.throwException(Translator.get("i18n_dataset_ds_error") + ",ID:" + ds.getDatasourceId());
}
if (coreDatasource.getType().contains(DatasourceConfiguration.DatasourceType.Excel.name()) || coreDatasource.getType().contains(DatasourceConfiguration.DatasourceType.API.name())) {
coreDatasource = engineManage.getDeEngine();
}
}
Map map = JsonUtil.parseObject(coreDatasource.getConfiguration(), Map.class);
@@ -525,7 +534,9 @@ public class DatasetSQLManage {
dsMap.put(coreDatasource.getId(), datasourceSchemaDTO);
}
} else if (StringUtils.equalsIgnoreCase(ds.getType(), DatasetTableType.Es)) {
CoreDatasource coreDatasource = dataSourceManage.getCoreDatasource(ds.getDatasourceId());
if (ObjectUtils.isEmpty(coreDatasource)) {
coreDatasource = dataSourceManage.getCoreDatasource(ds.getDatasourceId());
}
schemaAlias = String.format(SQLConstants.SCHEMA, coreDatasource.getId());
if (!dsMap.containsKey(coreDatasource.getId())) {
DatasourceSchemaDTO datasourceSchemaDTO = new DatasourceSchemaDTO();
@@ -534,7 +545,9 @@ public class DatasetSQLManage {
dsMap.put(coreDatasource.getId(), datasourceSchemaDTO);
}
} else {
CoreDatasource coreDatasource = engineManage.getDeEngine();
if (ObjectUtils.isEmpty(coreDatasource)) {
coreDatasource = engineManage.getDeEngine();
}
schemaAlias = String.format(SQLConstants.SCHEMA, coreDatasource.getId());
if (!dsMap.containsKey(coreDatasource.getId())) {
DatasourceSchemaDTO datasourceSchemaDTO = new DatasourceSchemaDTO();

View File

@@ -108,16 +108,75 @@ public class BeanUtils {
// 查找Map中对应的key支持驼峰和下划线
Object value = findValueInMap(map, propertyName);
// 只有当值存在且有写入方法时才设置属性
if (value != null && descriptor.getWriteMethod() != null) {
descriptor.getWriteMethod().invoke(bean, value);
try {
// 可选:添加类型转换逻辑来处理类型不匹配的情况
Object convertedValue = convertTypeIfNeeded(value, descriptor.getPropertyType());
descriptor.getWriteMethod().invoke(bean, convertedValue);
} catch (IllegalArgumentException e) {
// 类型不匹配时跳过该属性,而不是抛出异常
System.err.println("类型不匹配跳过属性: " + propertyName + ", 期望类型: " +
descriptor.getPropertyType() + ", 实际类型: " + value.getClass());
}
}
}
return bean;
} catch (Exception e) {
e.printStackTrace();
throw new RuntimeException("Map转Bean失败", e);
}
}
private static Object convertTypeIfNeeded(Object value, Class<?> targetType) {
if (value == null) {
return null;
}
// 如果类型匹配,直接返回
if (targetType.isInstance(value)) {
return value;
}
// 添加常见的类型转换逻辑
try {
if (targetType == String.class) {
return value.toString();
} else if (targetType == Integer.class || targetType == int.class) {
if (value instanceof Number) {
return ((Number) value).intValue();
} else {
return Integer.parseInt(value.toString());
}
} else if (targetType == Long.class || targetType == long.class) {
if (value instanceof Number) {
return ((Number) value).longValue();
} else {
return Long.parseLong(value.toString());
}
} else if (targetType == Double.class || targetType == double.class) {
if (value instanceof Number) {
return ((Number) value).doubleValue();
} else {
return Double.parseDouble(value.toString());
}
} else if (targetType == Boolean.class || targetType == boolean.class) {
if (value instanceof Boolean) {
return value;
} else {
return Boolean.parseBoolean(value.toString());
}
}
// 可以继续添加其他类型的转换...
} catch (Exception e) {
// 转换失败时返回原值,让后续逻辑处理
System.err.println("类型转换失败: " + value + " to " + targetType);
}
return value; // 无法转换时返回原值
}
private static Object findValueInMap(Map<String, Object> map, String propertyName) {
Object value = map.get(propertyName);
if (value != null) return value;

View File

@@ -123,12 +123,15 @@ public abstract class Provider {
}
public String rebuildSQL(String sql, SQLMeta sqlMeta, boolean crossDs, Map<Long, DatasourceSchemaDTO> dsMap) {
return rebuildSQL(sql, sqlMeta, crossDs, dsMap, false);
}
public String rebuildSQL(String sql, SQLMeta sqlMeta, boolean crossDs, Map<Long, DatasourceSchemaDTO> dsMap, boolean forSqlbot) {
logger.debug("calcite sql: " + sql);
if (crossDs) {
return sql;
}
String s = transSqlDialect(sql, dsMap);
String s = transSqlDialect(sql, dsMap, forSqlbot);
String tableDialect = sqlMeta.getTableDialect();
s = replaceTablePlaceHolder(s, tableDialect);
s = replaceCalcFieldPlaceHolder(s, sqlMeta);
@@ -136,11 +139,18 @@ public abstract class Provider {
}
public String transSqlDialect(String sql, Map<Long, DatasourceSchemaDTO> dsMap) throws DEException {
return transSqlDialect(sql, dsMap, false);
}
public String transSqlDialect(String sql, Map<Long, DatasourceSchemaDTO> dsMap, boolean forSqlbot) throws DEException {
DatasourceSchemaDTO value = dsMap.entrySet().iterator().next().getValue();
try (ConnectionObj connection = getConnection(value)) {
// 获取数据库version
if (connection != null) {
value.setDsVersion(connection.getConnection().getMetaData().getDatabaseMajorVersion());
ConnectionObj connection = null;
try {
if (!forSqlbot) {
connection = getConnection(value);
// 获取数据库version
if (connection != null) {
value.setDsVersion(connection.getConnection().getMetaData().getDatabaseMajorVersion());
}
}
SqlParser parser = SqlParser.create(sql, SqlParser.Config.DEFAULT.withLex(Lex.JAVA));
SqlNode sqlNode = parser.parseStmt();
@@ -151,6 +161,14 @@ public abstract class Provider {
return dialect;
} catch (Exception e) {
DEException.throwException(e.getMessage());
} finally {
if (connection != null) {
try {
connection.close();
} catch (Exception e) {
throw new RuntimeException(e);
}
}
}
return null;
}