fix:调整sql解析,表名、列名等不可用"?"占位的地方使用{{...}}传参,可使用"?"展位的地方使用{{?...}} 传参
2个文件已修改
99 ■■■■ 已修改文件
aiflowy-modules/aiflowy-module-ai/src/main/java/tech/aiflowy/ai/node/SqlNode.java 95 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
aiflowy-ui-react/src/pages/ai/workflowDesign/customNode/sqlNode.ts 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
aiflowy-modules/aiflowy-module-ai/src/main/java/tech/aiflowy/ai/node/SqlNode.java
@@ -1,5 +1,6 @@
package tech.aiflowy.ai.node;
import com.agentsflex.core.chain.Chain;
import com.agentsflex.core.chain.Parameter;
import com.agentsflex.core.chain.node.BaseNode;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
@@ -13,6 +14,7 @@
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.StringUtils;
import tech.aiflowy.common.util.Maps;
import tech.aiflowy.common.web.exceptions.BusinessException;
import java.util.*;
@@ -41,7 +43,9 @@
        Map<String, Object> map = chain.getParameterValues(this);
        Map<String, Object> res = new HashMap<>();
        Map<String, Object> formatSqlMap = formatSql(sql);
        Map<String, Object> formatSqlMap = formatSql(sql,map);
        String formatSql = (String)formatSqlMap.get("replacedSql");
        Statement statement = null;
@@ -68,46 +72,91 @@
        List<Row> rows = Db.selectListBySql(formatSql, paramValues.toArray());
        res.put("queryData", rows);
        if (rows == null || rows.isEmpty()) {
            return Collections.emptyMap();
        }
        res.put("queryData",rows);
        return res;
    }
    private Map<String,Object> formatSql(String sql) {
    private Map<String, Object> formatSql(String rawSql, Map<String, Object> paramMap) {
        if (!StringUtils.hasLength(sql)){
        if (!StringUtils.hasLength(rawSql)) {
            logger.error("sql解析报错:sql为空");
            throw new BusinessException("sql 不能为空!");
        }
        // 用来提取参数名
        Pattern pattern = Pattern.compile("\\{\\{([^}]+)}}");
        Matcher matcher = pattern.matcher(sql);
        // 匹配 {{?...}} 表示可用占位符的参数
        Pattern paramPattern = Pattern.compile("\\{\\{\\?([^}]+)}}");
        // 匹配 {{...}} 表示直接替换的参数(非占位符)
        Pattern directPattern = Pattern.compile("\\{\\{([^}?][^}]*)}}");
        List<String> paramNames = new ArrayList<>();
        StringBuffer sqlBuffer = new StringBuffer();
        // 构建替换后的 SQL
        StringBuffer replacedSql = new StringBuffer();
        while (matcher.find()) {
            paramNames.add(matcher.group(1)); // 获取 {{...}} 中的内容
            matcher.appendReplacement(replacedSql, "?");
        // 替换 {{?...}}  ->  ?
        Matcher paramMatcher = paramPattern.matcher(rawSql);
        while (paramMatcher.find()) {
            String paramName = paramMatcher.group(1).trim();
            paramNames.add(paramName);
            paramMatcher.appendReplacement(sqlBuffer, "?");
        }
        paramMatcher.appendTail(sqlBuffer);
        String intermediateSql = sqlBuffer.toString();
        matcher.appendTail(replacedSql);
        HashMap<String, Object> formatSqlMap = new HashMap<>();
        String formatSql = replacedSql.toString();
        // 替换 {{...}}  -> 实际值(用于表名/列名等)
        sqlBuffer = new StringBuffer(); // 清空 buffer 重新处理
        Matcher directMatcher = directPattern.matcher(intermediateSql);
        while (directMatcher.find()) {
            String key = directMatcher.group(1).trim();
            Object value = paramMap.get(key);
            if (value == null) {
                logger.error("未找到参数:" + key);
                throw new BusinessException("sql解析失败,请确保sql语法正确!");
            }
        if (formatSql.endsWith(";") || formatSql.endsWith(";")) {
            formatSql = formatSql.substring(0, formatSql.length() - 1);
            String safeValue = value.toString();
            directMatcher.appendReplacement(sqlBuffer, Matcher.quoteReplacement(safeValue));
        }
        directMatcher.appendTail(sqlBuffer);
        formatSql =  formatSql.replace("“" ,"\"").replace("”","\"");
        String finalSql = sqlBuffer.toString().trim();
        logger.info("Replaced SQL: {}", replacedSql);
        logger.info("Parameter names: {}", paramNames);
        formatSqlMap.put("replacedSql",formatSql );
        formatSqlMap.put("paramNames", paramNames);
        return   formatSqlMap;
        // 清理末尾分号与中文引号
        if (finalSql.endsWith(";") || finalSql.endsWith(";")) {
            finalSql = finalSql.substring(0, finalSql.length() - 1);
        }
        finalSql = finalSql.replace("“", "\"").replace("”", "\"");
        logger.info("Final SQL: {}", finalSql);
        logger.info("Param names: {}", paramNames);
        Map<String, Object> result = new HashMap<>();
        result.put("replacedSql", finalSql);
        result.put("paramNames", paramNames);
        return result;
    }
    @Override
    public String toString() {
        return "SqlNode{" +
                "sql='" + sql + '\'' +
                ", outputDefs=" + outputDefs +
                ", parameters=" + parameters +
                ", id='" + id + '\'' +
                ", name='" + name + '\'' +
                ", description='" + description + '\'' +
                ", async=" + async +
                ", inwardEdges=" + inwardEdges +
                ", outwardEdges=" + outwardEdges +
                ", condition=" + condition +
                ", memory=" + memory +
                ", nodeStatus=" + nodeStatus +
                '}';
    }
}
aiflowy-ui-react/src/pages/ai/workflowDesign/customNode/sqlNode.ts
@@ -7,7 +7,7 @@
        icon:'<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="rgba(37,99,235,1)"><path d="M5 12.5C5 12.8134 5.46101 13.3584 6.53047 13.8931C7.91405 14.5849 9.87677 15 12 15C14.1232 15 16.0859 14.5849 17.4695 13.8931C18.539 13.3584 19 12.8134 19 12.5V10.3287C17.35 11.3482 14.8273 12 12 12C9.17273 12 6.64996 11.3482 5 10.3287V12.5ZM19 15.3287C17.35 16.3482 14.8273 17 12 17C9.17273 17 6.64996 16.3482 5 15.3287V17.5C5 17.8134 5.46101 18.3584 6.53047 18.8931C7.91405 19.5849 9.87677 20 12 20C14.1232 20 16.0859 19.5849 17.4695 18.8931C18.539 18.3584 19 17.8134 19 17.5V15.3287ZM3 17.5V7.5C3 5.01472 7.02944 3 12 3C16.9706 3 21 5.01472 21 7.5V17.5C21 19.9853 16.9706 22 12 22C7.02944 22 3 19.9853 3 17.5ZM12 10C14.1232 10 16.0859 9.58492 17.4695 8.89313C18.539 8.3584 19 7.81342 19 7.5C19 7.18658 18.539 6.6416 17.4695 6.10687C16.0859 5.41508 14.1232 5 12 5C9.87677 5 7.91405 5.41508 6.53047 6.10687C5.46101 6.6416 5 7.18658 5 7.5C5 7.81342 5.46101 8.3584 6.53047 8.89313C7.91405 9.58492 9.87677 10 12 10Z"></path></svg>',
        sortNo: 803,
        parametersAddEnable: true,
        outputDefsAddEnable: false,
        outputDefsAddEnable: true,
        parameters: [],
        forms:[
            {
@@ -21,7 +21,7 @@
            {
                name: 'queryData',
                title: '查询结果',
                dataType: 'String',
                dataType: 'Array',
                dataTypeDisabled:true,
                required: true,
                parametersAddEnable: false,