feat(数据集): SQL 数据集参数支持绑定系统变量

This commit is contained in:
taojinlong 2024-12-26 17:48:52 +08:00 committed by dataeaseShu
parent 47e69cfd0d
commit c31573e4d3
5 changed files with 113 additions and 33 deletions

View File

@ -1,6 +1,9 @@
package io.dataease.commons.utils;
import com.fasterxml.jackson.core.type.TypeReference;
import io.dataease.api.permissions.user.vo.UserFormVO;
import io.dataease.api.permissions.variable.dto.SysVariableValueDto;
import io.dataease.api.permissions.variable.dto.SysVariableValueItem;
import io.dataease.exception.DEException;
import io.dataease.extensions.datasource.api.PluginManageApi;
import io.dataease.extensions.datasource.dto.DatasourceSchemaDTO;
@ -37,6 +40,7 @@ import static org.apache.calcite.sql.SqlKind.*;
public class SqlparserUtils {
public static final String regex = "\\$\\{(.*?)\\}";
public static final String regex2 = "\\$\\[(.*?)\\]";
private static final String SubstitutedParams = "DATAEASE_PATAMS_BI";
private static final String SubstitutedSql = " 'DE-BI' = 'DE-BI' ";
private static final String SubstitutedSqlVirtualData = " 1 > 2 ";
@ -50,6 +54,14 @@ public class SqlparserUtils {
hasVariables = true;
tmpSql = tmpSql.replace(matcher.group(), SubstitutedParams);
}
pattern = Pattern.compile(regex2);
matcher = pattern.matcher(tmpSql);
while (matcher.find()) {
hasVariables = true;
tmpSql = tmpSql.replace(matcher.group(), SubstitutedParams);
}
if (!hasVariables && !tmpSql.contains(SubstitutedParams)) {
return tmpSql;
}
@ -494,7 +506,7 @@ public class SqlparserUtils {
}
}
public static SqlShuttle getSqlShuttle() {
private static SqlShuttle getSqlShuttle() {
return new SqlShuttle() {
@Override
@ -515,7 +527,7 @@ public class SqlparserUtils {
};
}
public static String handleVariableDefaultValue(String sql, String sqlVariableDetails, boolean isEdit, boolean isFromDataSet, List<SqlVariableDetails> parameters, boolean isCross, Map<Long, DatasourceSchemaDTO> dsMap, PluginManageApi pluginManage) {
public static String handleVariableDefaultValue(String sql, String sqlVariableDetails, boolean isEdit, boolean isFromDataSet, List<SqlVariableDetails> parameters, boolean isCross, Map<Long, DatasourceSchemaDTO> dsMap, PluginManageApi pluginManage, UserFormVO userEntity) {
if (StringUtils.isEmpty(sql)) {
DEException.throwException(Translator.get("i18n_sql_not_empty"));
}
@ -567,6 +579,28 @@ public class SqlparserUtils {
}
}
}
sql = sql.replace("$[sysParams.userId]", userEntity.getAccount());
sql = sql.replace("$[sysParams.userEmail]", userEntity.getEmail());
sql = sql.replace("$[sysParams.userName]", userEntity.getName());
for (SysVariableValueItem variable : userEntity.getVariables()) {
String value = null;
if (!variable.isValid()) {
continue;
}
if (variable.getSysVariableDto().getType().equalsIgnoreCase("text")) {
for (SysVariableValueDto sysVariableValueDto : variable.getValueList()) {
if (sysVariableValueDto.getId().equals(variable.getVariableValueId())) {
value = sysVariableValueDto.getValue();
break;
}
}
} else {
value = variable.getVariableValue();
}
if (StringUtils.isNotEmpty(value)) {
sql = sql.replace("$[" + variable.getVariableId() + "]", value);
}
}
try {
DatasourceSchemaDTO ds = dsMap.entrySet().iterator().next().getValue();
@ -611,7 +645,6 @@ public class SqlparserUtils {
return sql;
}
private static String transFilter(SqlVariableDetails sqlVariableDetails, Map<Long, DatasourceSchemaDTO> dsMap) {
if (sqlVariableDetails.getOperator().equals("in")) {
if (StringUtils.equalsIgnoreCase(dsMap.entrySet().iterator().next().getValue().getType(), DatasourceConfiguration.DatasourceType.sqlServer.getType())

View File

@ -5,7 +5,9 @@ import io.dataease.api.dataset.dto.*;
import io.dataease.api.dataset.union.DatasetGroupInfoDTO;
import io.dataease.api.dataset.union.DatasetTableInfoDTO;
import io.dataease.api.permissions.auth.dto.BusiPerCheckDTO;
import io.dataease.api.permissions.dataset.api.RowPermissionsApi;
import io.dataease.api.permissions.dataset.dto.DataSetRowPermissionsTreeDTO;
import io.dataease.api.permissions.user.vo.UserFormVO;
import io.dataease.auth.bo.TokenUserBO;
import io.dataease.chart.utils.ChartDataBuild;
import io.dataease.commons.utils.SqlparserUtils;
@ -80,12 +82,17 @@ public class DatasetDataManage {
private PluginManageApi pluginManage;
@Resource
private CorePermissionManage corePermissionManage;
@Autowired(required = false)
private RowPermissionsApi rowPermissionsApi;
@Resource
private DataSourceManage dataSourceManage;
private static Logger logger = LoggerFactory.getLogger(DatasetDataManage.class);
private RowPermissionsApi getRowPermissionsApi() {
return rowPermissionsApi;
}
public static final List<String> notFullDs = List.of("mysql", "mariadb", "Excel", "API");
public List<DatasetTableFieldDTO> getTableFields(DatasetTableDTO datasetTableDTO) throws Exception {
@ -118,7 +125,8 @@ public class DatasetDataManage {
} else {
// parser sql params and replace default value
String s = new String(Base64.getDecoder().decode(tableInfoDTO.getSql()));
String originSql = SqlparserUtils.handleVariableDefaultValue(s, datasetTableDTO.getSqlVariableDetails(), false, false, null, false, datasourceRequest.getDsList(), pluginManage);
UserFormVO userEntity = getRowPermissionsApi().getUserById(AuthUtils.getUser().getUserId());
String originSql = SqlparserUtils.handleVariableDefaultValue(s, datasetTableDTO.getSqlVariableDetails(), false, false, null, false, datasourceRequest.getDsList(), pluginManage, userEntity);
originSql = provider.replaceComment(originSql);
// add sql table schema
@ -409,7 +417,8 @@ public class DatasetDataManage {
// parser sql params and replace default value
String s = new String(Base64.getDecoder().decode(dto.getSql()));
String originSql = SqlparserUtils.handleVariableDefaultValue(datasetSQLManage.subPrefixSuffixChar(s), dto.getSqlVariableDetails(), true, true, null, false, dsMap, pluginManage);
UserFormVO userEntity = getRowPermissionsApi().getUserById(AuthUtils.getUser().getUserId());
String originSql = SqlparserUtils.handleVariableDefaultValue(datasetSQLManage.subPrefixSuffixChar(s), dto.getSqlVariableDetails(), true, true, null, false, dsMap, pluginManage, userEntity);
originSql = provider.replaceComment(originSql);
// sql 作为临时表外层加上limit

View File

@ -2,6 +2,8 @@ package io.dataease.dataset.manage;
import io.dataease.api.dataset.union.*;
import io.dataease.api.permissions.auth.dto.BusiPerCheckDTO;
import io.dataease.api.permissions.dataset.api.RowPermissionsApi;
import io.dataease.api.permissions.user.vo.UserFormVO;
import io.dataease.commons.utils.SqlparserUtils;
import io.dataease.constant.AuthEnum;
import io.dataease.dataset.constant.DatasetTableType;
@ -31,6 +33,7 @@ import io.dataease.extensions.view.dto.SqlVariableDetails;
import io.dataease.i18n.Translator;
import io.dataease.license.utils.LicenseUtil;
import io.dataease.system.manage.CorePermissionManage;
import io.dataease.utils.AuthUtils;
import io.dataease.utils.BeanUtils;
import io.dataease.utils.JsonUtil;
import jakarta.annotation.Resource;
@ -62,10 +65,13 @@ public class DatasetSQLManage {
@Autowired(required = false)
private PluginManageApi pluginManage;
@Autowired(required = false)
private RowPermissionsApi rowPermissionsApi;
@Resource
private DataSourceManage dataSourceManage;
private RowPermissionsApi getRowPermissionsApi() {
return rowPermissionsApi;
}
private static Logger logger = LoggerFactory.getLogger(DatasetSQLManage.class);
private List<SqlVariableDetails> filterParameters(ChartExtRequest chartExtRequest, Long datasetTableId) {
@ -464,7 +470,8 @@ public class DatasetSQLManage {
Provider provider = ProviderFactory.getProvider(dsMap.entrySet().iterator().next().getValue().getType());
// parser sql params and replace default value
String s = new String(Base64.getDecoder().decode(infoDTO.getSql()));
String sql = SqlparserUtils.handleVariableDefaultValue(s, currentDs.getSqlVariableDetails(), false, isFromDataSet, parameters, isCross, dsMap, pluginManage);
UserFormVO userEntity = getRowPermissionsApi().getUserById(AuthUtils.getUser().getUserId());
String sql = SqlparserUtils.handleVariableDefaultValue(s, currentDs.getSqlVariableDetails(), false, isFromDataSet, parameters, isCross, dsMap, pluginManage, userEntity);
sql = provider.replaceComment(sql);
// add table schema
if (isCross) {

View File

@ -246,6 +246,7 @@ public class PermissionManage {
for (SysVariableValueDto sysVariableValueDto : variable.getValueList()) {
if (sysVariableValueDto.getId().equals(variable.getVariableValueId())) {
value = sysVariableValueDto.getValue();
break;
}
}
}

View File

@ -43,6 +43,10 @@ import { EmptyBackground } from '@/components/empty-background'
import { timestampFormatDate, defaultValueScopeList, fieldOptions } from './util'
import { fieldType } from '@/utils/attr'
import { iconFieldMap } from '@/components/icon-group/field-list'
import { isDesktop } from '@/utils/ModelUtil'
import field_text from '@/assets/svg/field_text.svg'
import field_value from '@/assets/svg/field_value.svg'
import field_time from '@/assets/svg/field_time.svg'
export interface SqlNode {
sql: string
tableName: string
@ -140,28 +144,54 @@ const fieldFormList = ref([])
const builtInList = ref([
{
id: 8,
id: 'sysParams.userId',
name: t('system.account')
},
{
id: 17,
id: 'sysParams.userName',
name: t('datasource.user_name')
},
{
id: 9,
id: 'sysParams.userEmail',
name: t('commons.email')
}
])
const iconName = type => {
if (type === 'text') {
return field_text
}
if (type === 'num') {
return field_value
}
if (type === 'time') {
return field_time
}
}
const iconClassName = type => {
if (type === 'text') {
return 'field-icon-text'
}
if (type === 'num') {
return 'field-icon-value'
}
if (type === 'time') {
return 'field-icon-time'
}
}
const fieldFormListComputed = computed(() => {
return fieldFormList.value.filter(ele =>
ele.name.toLowerCase().includes(searchField.value.toLowerCase())
)
})
const desktop = isDesktop()
const showSysParams = ref(false)
const searchField = ref('')
const sysParams = () => {
showSysParams.value = true
handleSearchVariableApi()
}
const insertFieldToCodeMirror = (value: string) => {
@ -515,7 +545,7 @@ const mousedownDrag = () => {
</template>
{{ t('data_set.parameter_settings') }}
</el-button>
<el-button v-if="false" @click="sysParams" class="system-text_bg" text>
<el-button v-if="!desktop" @click="sysParams" class="system-text_bg" text>
<template #icon>
<el-icon>
<Icon><icon_preferences_outlined class="svg-icon" /></Icon>
@ -864,7 +894,7 @@ const mousedownDrag = () => {
</div>
<div
class="variable-item"
@click="insertFieldToCodeMirror(`[${fieldForm.name}]`)"
@click="insertFieldToCodeMirror(`$[${fieldForm.id}]`)"
v-for="fieldForm in builtInList"
:key="fieldForm.id"
>
@ -877,15 +907,15 @@ const mousedownDrag = () => {
class="variable-item flex-align-center"
v-for="fieldForm in fieldFormListComputed"
:key="fieldForm.id"
@click="insertFieldToCodeMirror(`[${fieldForm.name}]`)"
@click="insertFieldToCodeMirror(`$[${fieldForm.id}]`)"
:class="[2, 3].includes(fieldForm.deType) && 'with-type'"
>
<el-icon>
<Icon
><component
class="svg-icon"
:class="`field-icon-${fieldType[fieldForm.deType]}`"
:is="iconFieldMap[fieldType[fieldForm.deType]]"
:class="iconClassName(fieldForm.type)"
:is="iconName(fieldForm.type)"
></component
></Icon>
</el-icon>