From b38009fa37af136842d0b5540effdeae079846c4 Mon Sep 17 00:00:00 2001 From: tjlygdx Date: Wed, 10 Jun 2026 16:28:13 +0800 Subject: [PATCH] =?UTF-8?q?fix:=20=E7=B3=BB=E7=BB=9F=E5=8F=98=E9=87=8F=20S?= =?UTF-8?q?QL=20=E6=9B=BF=E6=8D=A2=E6=9C=AA=E5=8F=82=E6=95=B0=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../commons/utils/DeSqlparserUtils.java | 138 ++++++++------ .../commons/utils/SqlparserUtils.java | 172 +++++++++++++----- 2 files changed, 211 insertions(+), 99 deletions(-) diff --git a/core/core-backend/src/main/java/io/dataease/commons/utils/DeSqlparserUtils.java b/core/core-backend/src/main/java/io/dataease/commons/utils/DeSqlparserUtils.java index de52d1f000..3006a5e530 100644 --- a/core/core-backend/src/main/java/io/dataease/commons/utils/DeSqlparserUtils.java +++ b/core/core-backend/src/main/java/io/dataease/commons/utils/DeSqlparserUtils.java @@ -37,9 +37,12 @@ public class DeSqlparserUtils { public static final String sqlParamsRegex = "\\$\\[(.*?)\\]"; public static final String sysVariableRegex = "\\$f2cde\\[(.*?)\\]"; private static final String SysParamsSubstitutedParams = "DeSysParams_"; + private static final String PREPARED_BINDING_TOKEN_PREFIX = "DE_BIND_"; private UserFormVO userEntity; private static final String SubstitutedSql = " 'DE-BI' = 'DE-BI' "; private final List> sysParams = new ArrayList<>(); + private final Map preparedBindings = new LinkedHashMap<>(); + private int preparedBindingIndex; TypeReference> listTypeReference = new TypeReference>() { }; private List defaultsSqlVariableDetails = new ArrayList<>(); @@ -54,6 +57,8 @@ public class DeSqlparserUtils { DEException.throwException(Translator.get("i18n_sql_not_empty")); } this.userEntity = userEntity; + this.preparedBindings.clear(); + this.preparedBindingIndex = 0; sql = sql.trim(); if (sql.endsWith(";")) { sql = sql.substring(0, sql.length() - 1); @@ -134,14 +139,15 @@ public class DeSqlparserUtils { sqlItem = sqlItem.replace(m.group(), SysParamsSubstitutedParams + sysVariableId); try { Expression expression = CCJSqlParserUtil.parseCondExpression(sqlItem); - String value = null; + PreparedSqlFragment preparedSqlFragment = null; if (expression instanceof InExpression) { - value = handleSubstitutedSqlForIn(sysVariableId); + preparedSqlFragment = buildPreparedSysSqlFragment(sysVariableId, true); } else { - value = handleSubstitutedSql(sysVariableId); + preparedSqlFragment = buildPreparedSysSqlFragment(sysVariableId, false); } - if (StringUtils.isNotEmpty(value)) { - sqlItem = sqlItem.replace(SysParamsSubstitutedParams + sysVariableId, value); + if (preparedSqlFragment != null) { + sqlItem = sqlItem.replace(SysParamsSubstitutedParams + sysVariableId, preparedSqlFragment.replacement()); + sqlItemFieldWithValues.addAll(preparedSqlFragment.tableFieldWithValues()); replaceParamItem = true; } } catch (Exception e) { @@ -201,9 +207,7 @@ public class DeSqlparserUtils { } catch (Exception e) { e.printStackTrace(); } - SqlVariableHandleResult result = new SqlVariableHandleResult(sql); - result.setTableFieldWithValues(tableFieldWithValues); - return result; + return finalizePreparedSql(sql); } private static boolean isParams(String paramId) { @@ -311,7 +315,7 @@ public class DeSqlparserUtils { tableFieldWithValue.setType(Types.VARCHAR); tableFieldWithValue.setColumnTypeName("VARCHAR"); tableFieldWithValue.setValue(preparedValueBuilder.toString()); - return new PreparedSqlFragment("?", Collections.singletonList(tableFieldWithValue)); + return buildPreparedSqlFragment(Collections.singletonList(tableFieldWithValue)); } private String resolveQuotedLiteralVariableValue(String variableName, List parameters, boolean isEdit, boolean isFromDataSet) { @@ -376,13 +380,11 @@ public class DeSqlparserUtils { private PreparedSqlFragment buildPreparedSqlFragment(SqlVariableDetails sqlVariableDetails) { List values = new ArrayList<>(); - List replacements = new ArrayList<>(); List preparedValues = resolvePreparedValues(sqlVariableDetails); for (String preparedValue : preparedValues) { values.add(buildPreparedValue(sqlVariableDetails, preparedValue)); - replacements.add("?"); } - return new PreparedSqlFragment(String.join(",", replacements), values); + return buildPreparedSqlFragment(values); } private PreparedSqlFragment buildPreparedSqlFragmentForDefaultValue(SqlVariableDetails sqlVariableDetails) { @@ -458,6 +460,35 @@ public class DeSqlparserUtils { return tableFieldWithValue; } + private PreparedSqlFragment buildPreparedSqlFragment(List tableFieldWithValues) { + List replacements = new ArrayList<>(); + for (TableFieldWithValue tableFieldWithValue : tableFieldWithValues) { + replacements.add(registerPreparedBinding(tableFieldWithValue)); + } + return new PreparedSqlFragment(String.join(",", replacements), tableFieldWithValues); + } + + private String registerPreparedBinding(TableFieldWithValue tableFieldWithValue) { + String token = PREPARED_BINDING_TOKEN_PREFIX + preparedBindingIndex++; + preparedBindings.put(token, tableFieldWithValue); + return "'" + token + "'"; + } + + private SqlVariableHandleResult finalizePreparedSql(String sql) { + Pattern tokenPattern = Pattern.compile("'(" + PREPARED_BINDING_TOKEN_PREFIX + "\\d+)'"); + Matcher matcher = tokenPattern.matcher(sql); + StringBuilder sqlBuilder = new StringBuilder(); + List orderedBindings = new ArrayList<>(); + while (matcher.find()) { + orderedBindings.add(preparedBindings.get(matcher.group(1))); + matcher.appendReplacement(sqlBuilder, "?"); + } + matcher.appendTail(sqlBuilder); + SqlVariableHandleResult result = new SqlVariableHandleResult(sqlBuilder.toString()); + result.setTableFieldWithValues(orderedBindings); + return result; + } + private record PreparedSqlFragment(String replacement, List tableFieldWithValues) { } @@ -467,48 +498,37 @@ public class DeSqlparserUtils { private record LiteralSegment(boolean variable, String content) { } - private String handleSubstitutedSql(String sysVariableId) { - if (userEntity != null) { - if (sysVariableId.equalsIgnoreCase("sysParams.userId")) { - return userEntity.getAccount(); - } - if (sysVariableId.equalsIgnoreCase("sysParams.userEmail")) { - return userEntity.getEmail(); - } - if (sysVariableId.equalsIgnoreCase("sysParams.userName")) { - return userEntity.getName(); - } - if (sysVariableId.equalsIgnoreCase("sysParams.userPhone")) { - return userEntity.getPhone(); - } - for (SysVariableValueItem variable : userEntity.getVariables()) { - if (!variable.isValid()) { - continue; - } - if (!sysVariableId.equalsIgnoreCase(variable.getVariableId().toString())) { - continue; - } - if (variable.getSysVariableDto().getType().equalsIgnoreCase("text")) { - for (SysVariableValueDto sysVariableValueDto : variable.getValueList()) { - if (variable.getVariableValueIds().contains(sysVariableValueDto.getId().toString())) { - return sysVariableValueDto.getValue(); - } - } - } else { - return variable.getVariableValue(); - } - } - return null; - } else { + private PreparedSqlFragment buildPreparedSysSqlFragment(String sysVariableId, boolean inOperator) { + SysVariableBinding sysVariableBinding = resolveSysVariableBinding(sysVariableId, inOperator); + if (sysVariableBinding == null || CollectionUtils.isEmpty(sysVariableBinding.values())) { return null; } + List values = new ArrayList<>(); + for (String value : sysVariableBinding.values()) { + SqlVariableDetails sqlVariableDetails = new SqlVariableDetails(); + sqlVariableDetails.setVariableName(sysVariableId); + sqlVariableDetails.setOperator(inOperator ? "in" : "eq"); + sqlVariableDetails.setDeType(sysVariableBinding.deType()); + values.add(buildPreparedValue(sqlVariableDetails, value)); + } + return buildPreparedSqlFragment(values); } - - private String handleSubstitutedSqlForIn(String sysVariableId) { + private SysVariableBinding resolveSysVariableBinding(String sysVariableId, boolean inOperator) { if (userEntity != null) { + if (sysVariableId.equalsIgnoreCase("sysParams.userId")) { + return buildSysVariableBinding(0, inOperator ? Collections.singletonList(userEntity.getAccount()) : Collections.singletonList(userEntity.getAccount())); + } + if (sysVariableId.equalsIgnoreCase("sysParams.userEmail")) { + return buildSysVariableBinding(0, Collections.singletonList(userEntity.getEmail())); + } + if (sysVariableId.equalsIgnoreCase("sysParams.userName")) { + return buildSysVariableBinding(0, Collections.singletonList(userEntity.getName())); + } + if (sysVariableId.equalsIgnoreCase("sysParams.userPhone")) { + return buildSysVariableBinding(0, Collections.singletonList(userEntity.getPhone())); + } for (SysVariableValueItem variable : userEntity.getVariables()) { - List values = new ArrayList<>(); if (!variable.isValid()) { continue; } @@ -516,14 +536,19 @@ public class DeSqlparserUtils { continue; } if (variable.getSysVariableDto().getType().equalsIgnoreCase("text")) { + List values = new ArrayList<>(); for (SysVariableValueDto sysVariableValueDto : variable.getValueList()) { if (variable.getVariableValueIds().contains(sysVariableValueDto.getId().toString())) { values.add(sysVariableValueDto.getValue()); + if (!inOperator) { + break; + } } } - } - if (CollectionUtils.isNotEmpty(values)) { - return "'" + String.join("','", values) + "'"; + return buildSysVariableBinding(0, values); + } else { + int deType = variable.getSysVariableDto().getType().equalsIgnoreCase("num") ? 2 : 1; + return buildSysVariableBinding(deType, Collections.singletonList(variable.getVariableValue())); } } return null; @@ -531,4 +556,15 @@ public class DeSqlparserUtils { return null; } } + + private SysVariableBinding buildSysVariableBinding(int deType, List values) { + List validValues = values == null ? Collections.emptyList() : values.stream().filter(StringUtils::isNotEmpty).toList(); + if (CollectionUtils.isEmpty(validValues)) { + return null; + } + return new SysVariableBinding(deType, validValues); + } + + private record SysVariableBinding(int deType, List values) { + } } diff --git a/core/core-backend/src/main/java/io/dataease/commons/utils/SqlparserUtils.java b/core/core-backend/src/main/java/io/dataease/commons/utils/SqlparserUtils.java index 9692321ae9..2b8bde846c 100644 --- a/core/core-backend/src/main/java/io/dataease/commons/utils/SqlparserUtils.java +++ b/core/core-backend/src/main/java/io/dataease/commons/utils/SqlparserUtils.java @@ -46,11 +46,14 @@ public class SqlparserUtils { public static final String regex2 = "\\$f2cde\\[(.*?)\\]"; private static final String SubstitutedParams = "DATAEASE_PATAMS_BI"; private static final String SysParamsSubstitutedParams = "DeSysParams_"; + private static final String PREPARED_BINDING_TOKEN_PREFIX = "DE_BIND_"; private static final String SubstitutedSql = " 'DE-BI' = 'DE-BI' "; private boolean removeSysParams; boolean hasVariables = false; private UserFormVO userEntity; private final List> sysParams = new ArrayList<>(); + private final Map preparedBindings = new LinkedHashMap<>(); + private int preparedBindingIndex; private static final String deVariablePattern = "\\$DE_PARAM\\{(.*?)\\}"; private List defaultsSqlVariableDetails = new ArrayList<>(); @@ -70,6 +73,8 @@ public class SqlparserUtils { DEException.throwException(Translator.get("i18n_sql_not_empty")); } this.userEntity = userEntity; + this.preparedBindings.clear(); + this.preparedBindingIndex = 0; hasVariables = false; sql = sql.trim(); if (sql.endsWith(";")) { @@ -165,9 +170,7 @@ public class SqlparserUtils { } catch (Exception e) { e.printStackTrace(); } - SqlVariableHandleResult result = new SqlVariableHandleResult(sql); - result.setTableFieldWithValues(tableFieldWithValues); - return result; + return finalizePreparedSql(sql); } private static boolean isParams(String paramId) { @@ -796,7 +799,7 @@ public class SqlparserUtils { tableFieldWithValue.setType(Types.VARCHAR); tableFieldWithValue.setColumnTypeName("VARCHAR"); tableFieldWithValue.setValue(preparedValueBuilder.toString()); - return new PreparedSqlFragment("?", Collections.singletonList(tableFieldWithValue)); + return buildPreparedSqlFragment(Collections.singletonList(tableFieldWithValue)); } private String resolveQuotedLiteralVariableValue(String variableName, List parameters, boolean isEdit, boolean isFromDataSet) { @@ -861,13 +864,11 @@ public class SqlparserUtils { private PreparedSqlFragment buildPreparedSqlFragment(SqlVariableDetails sqlVariableDetails) { List values = new ArrayList<>(); - List replacements = new ArrayList<>(); List preparedValues = resolvePreparedValues(sqlVariableDetails); for (String preparedValue : preparedValues) { values.add(buildPreparedValue(sqlVariableDetails, preparedValue)); - replacements.add("?"); } - return new PreparedSqlFragment(String.join(",", replacements), values); + return buildPreparedSqlFragment(values); } private PreparedSqlFragment buildPreparedSqlFragmentForDefaultValue(SqlVariableDetails sqlVariableDetails) { @@ -943,6 +944,35 @@ public class SqlparserUtils { return tableFieldWithValue; } + private PreparedSqlFragment buildPreparedSqlFragment(List tableFieldWithValues) { + List replacements = new ArrayList<>(); + for (TableFieldWithValue tableFieldWithValue : tableFieldWithValues) { + replacements.add(registerPreparedBinding(tableFieldWithValue)); + } + return new PreparedSqlFragment(String.join(",", replacements), tableFieldWithValues); + } + + private String registerPreparedBinding(TableFieldWithValue tableFieldWithValue) { + String token = PREPARED_BINDING_TOKEN_PREFIX + preparedBindingIndex++; + preparedBindings.put(token, tableFieldWithValue); + return "'" + token + "'"; + } + + private SqlVariableHandleResult finalizePreparedSql(String sql) { + Pattern tokenPattern = Pattern.compile("'(" + PREPARED_BINDING_TOKEN_PREFIX + "\\d+)'"); + Matcher matcher = tokenPattern.matcher(sql); + StringBuilder sqlBuilder = new StringBuilder(); + List orderedBindings = new ArrayList<>(); + while (matcher.find()) { + orderedBindings.add(preparedBindings.get(matcher.group(1))); + matcher.appendReplacement(sqlBuilder, "?"); + } + matcher.appendTail(sqlBuilder); + SqlVariableHandleResult result = new SqlVariableHandleResult(sqlBuilder.toString()); + result.setTableFieldWithValues(orderedBindings); + return result; + } + private record PreparedSqlFragment(String replacement, List tableFieldWithValues) { } @@ -954,32 +984,17 @@ public class SqlparserUtils { private String handleSubstitutedSql(String sql) { if (sql.contains(SysParamsSubstitutedParams) && userEntity != null) { - sql = sql.replace(SysParamsSubstitutedParams + "sysParams.userId", userEntity.getAccount()); - sql = sql.replace(SysParamsSubstitutedParams + "sysParams.userEmail", userEntity.getEmail()); - sql = sql.replace(SysParamsSubstitutedParams + "sysParams.userName", Translator.get(userEntity.getName())); - if (StringUtils.isNotEmpty(userEntity.getPhone())) { - sql = sql.replace(SysParamsSubstitutedParams + "sysParams.userPhone", Translator.get(userEntity.getPhone())); + Matcher matcher = Pattern.compile(Pattern.quote(SysParamsSubstitutedParams) + "([A-Za-z0-9_.]+)").matcher(sql); + StringBuffer sqlBuffer = new StringBuffer(); + while (matcher.find()) { + PreparedSqlFragment preparedSqlFragment = buildPreparedSysSqlFragment(matcher.group(1), false); + if (preparedSqlFragment == null) { + return SubstitutedSql; + } + matcher.appendReplacement(sqlBuffer, Matcher.quoteReplacement(preparedSqlFragment.replacement())); } - for (SysVariableValueItem variable : userEntity.getVariables()) { - String value = null; - if (!variable.isValid()) { - continue; - } - if (variable.getSysVariableDto().getType().equalsIgnoreCase("text")) { - for (SysVariableValueDto sysVariableValueDto : variable.getValueList()) { - if (variable.getVariableValueIds().contains(sysVariableValueDto.getId().toString())) { - value = sysVariableValueDto.getValue(); - break; - } - } - } else { - value = variable.getVariableValue(); - } - if (StringUtils.isNotEmpty(value)) { - sql = sql.replace(SysParamsSubstitutedParams + variable.getVariableId(), value); - } - } - return sql; + matcher.appendTail(sqlBuffer); + return sqlBuffer.toString(); } else { return SubstitutedSql; } @@ -988,26 +1003,87 @@ public class SqlparserUtils { private String handleSubstitutedSqlForIn(String sql) { if (sql.contains(SysParamsSubstitutedParams) && userEntity != null) { - for (SysVariableValueItem variable : userEntity.getVariables()) { - List values = new ArrayList<>(); - if (!variable.isValid()) { - continue; - } - if (variable.getSysVariableDto().getType().equalsIgnoreCase("text")) { - - for (SysVariableValueDto sysVariableValueDto : variable.getValueList()) { - if (variable.getVariableValueIds().contains(sysVariableValueDto.getId().toString())) { - values.add(sysVariableValueDto.getValue()); - } - } - } - if (CollectionUtils.isNotEmpty(values)) { - sql = sql.replace(SysParamsSubstitutedParams + variable.getVariableId(), "'" + String.join("','", values) + "'"); + Matcher matcher = Pattern.compile(Pattern.quote(SysParamsSubstitutedParams) + "([A-Za-z0-9_.]+)").matcher(sql); + StringBuffer sqlBuffer = new StringBuffer(); + while (matcher.find()) { + PreparedSqlFragment preparedSqlFragment = buildPreparedSysSqlFragment(matcher.group(1), true); + if (preparedSqlFragment == null) { + return SubstitutedSql; } + matcher.appendReplacement(sqlBuffer, Matcher.quoteReplacement(preparedSqlFragment.replacement())); } - return sql; + matcher.appendTail(sqlBuffer); + return sqlBuffer.toString(); } else { return SubstitutedSql; } } + + private PreparedSqlFragment buildPreparedSysSqlFragment(String sysVariableId, boolean inOperator) { + SysVariableBinding sysVariableBinding = resolveSysVariableBinding(sysVariableId, inOperator); + if (sysVariableBinding == null || CollectionUtils.isEmpty(sysVariableBinding.values())) { + return null; + } + List values = new ArrayList<>(); + for (String value : sysVariableBinding.values()) { + SqlVariableDetails sqlVariableDetails = new SqlVariableDetails(); + sqlVariableDetails.setVariableName(sysVariableId); + sqlVariableDetails.setOperator(inOperator ? "in" : "eq"); + sqlVariableDetails.setDeType(sysVariableBinding.deType()); + values.add(buildPreparedValue(sqlVariableDetails, value)); + } + return buildPreparedSqlFragment(values); + } + + private SysVariableBinding resolveSysVariableBinding(String sysVariableId, boolean inOperator) { + if (userEntity == null) { + return null; + } + if (sysVariableId.equalsIgnoreCase("sysParams.userId")) { + return buildSysVariableBinding(0, Collections.singletonList(userEntity.getAccount())); + } + if (sysVariableId.equalsIgnoreCase("sysParams.userEmail")) { + return buildSysVariableBinding(0, Collections.singletonList(userEntity.getEmail())); + } + if (sysVariableId.equalsIgnoreCase("sysParams.userName")) { + return buildSysVariableBinding(0, Collections.singletonList(Translator.get(userEntity.getName()))); + } + if (sysVariableId.equalsIgnoreCase("sysParams.userPhone")) { + return buildSysVariableBinding(0, Collections.singletonList(Translator.get(userEntity.getPhone()))); + } + if (CollectionUtils.isEmpty(userEntity.getVariables())) { + return null; + } + for (SysVariableValueItem variable : userEntity.getVariables()) { + if (!variable.isValid() || !sysVariableId.equalsIgnoreCase(String.valueOf(variable.getVariableId()))) { + continue; + } + if (variable.getSysVariableDto().getType().equalsIgnoreCase("text")) { + List values = new ArrayList<>(); + for (SysVariableValueDto sysVariableValueDto : variable.getValueList()) { + if (variable.getVariableValueIds().contains(sysVariableValueDto.getId().toString())) { + values.add(sysVariableValueDto.getValue()); + if (!inOperator) { + break; + } + } + } + return buildSysVariableBinding(0, values); + } + int deType = variable.getSysVariableDto().getType().equalsIgnoreCase("num") ? 2 : 1; + return buildSysVariableBinding(deType, Collections.singletonList(variable.getVariableValue())); + } + return null; + } + + private SysVariableBinding buildSysVariableBinding(int deType, List values) { + List validValues = values == null ? Collections.emptyList() : values.stream().filter(StringUtils::isNotEmpty).toList(); + if (CollectionUtils.isEmpty(validValues)) { + return null; + } + return new SysVariableBinding(deType, validValues); + } + + private record SysVariableBinding(int deType, List values) { + } }