protected void initResultSet()

in src/main/java/com/aliyun/ha3engine/jdbc/Ha3PreparedStatement.java [472:651]


    protected void initResultSet(String sql) throws Ha3DriverException {
        if (this.ha3Connection.getHa3Config().isEnableDetailLog()) {
            logger.info("Ha3PreparedStatement sql:" + sql);
        }
        StringBuilder sqlBuilder = getSql(sql);
        String result;
        if (this.ha3Connection.getHa3Config().isEnableDynamicParams()) {
            String finalSql = sqlBuilder.toString();
            int finalSqlLength = finalSql.length();
            int kvpairLength = finalSql.lastIndexOf("&&kvpair=");
            String kvpairSize = finalSql.substring(kvpairLength, finalSqlLength);
            //开启sql动态参数化
            if (kvpairSize.length() > 9) {
                //sql带了kvpair,默认用户自己拼了动态参数等
                result = cloudClient.query(finalSql);
                this.ha3ResultSet = new Ha3ResultSet(result, this);
            } else {
                boolean canConvert = true;
                String originalSql = sql;

                // 正则表达式匹配 SELECT 关键字,忽略大小写
                Pattern selectPattern = Pattern.compile("\\bSELECT\\b", Pattern.CASE_INSENSITIVE);

                Matcher selectMatcher = selectPattern.matcher(sql);

                // 计算匹配到的 SELECT 关键字数量
                int selectCount = 0;
                while (selectMatcher.find()) {
                    selectCount++;
                }

                String beginSql = "";
                String endSql = "";
                int firstIndex = -1;
                int lastIndex = -1;
                if (selectCount > 1) {
                    firstIndex = sql.indexOf("(");
                    lastIndex = sql.lastIndexOf(")");
                    if (-1 != firstIndex && -1 != lastIndex) {
                        beginSql = sql.substring(0, firstIndex + 1);
                        endSql = sql.substring(lastIndex, sql.length());
                        sql = sql.substring(firstIndex + 1, lastIndex);
                    }
                }

                // 提取LIMIT子句中的常量值
                Pattern limitPattern = Pattern.compile("(?i)limit\\s+(\\d+)", Pattern.CASE_INSENSITIVE);
                Matcher limitMatcher = limitPattern.matcher(sql);
                int limitValue = -1;
                if (limitMatcher.find()) {
                    limitValue = Integer.parseInt(limitMatcher.group(1));
                    sql = sql.replaceFirst("(?i)limit\\s+\\d+", "");
                }

                // 提取OFFSET子句中的常量值
                Pattern offsetPattern = Pattern.compile("(?i)offset\\s+(\\d+)", Pattern.CASE_INSENSITIVE);
                Matcher offsetMatcher = offsetPattern.matcher(sql);
                int offsetValue = -1;
                if (offsetMatcher.find()) {
                    offsetValue = Integer.parseInt(offsetMatcher.group(1));
                    sql = sql.replaceFirst("(?i)offset\\s+\\d+", "");
                }

                // 创建不区分大小写的识别where的Pattern对象
                Pattern pattern = Pattern.compile(Pattern.quote("where"), Pattern.CASE_INSENSITIVE);
                Matcher matcher = pattern.matcher(sql);
                String firstPart = "";
                String secondPart = "";
                String thirdPart = "";
                if (matcher.find()) {
                    // 查询的第一部分
                    firstPart = sql.substring(0, matcher.start());
                    // 查询的第二部分
                    secondPart = sql.substring(matcher.start(), sql.length());
                    Pattern groupByPattern = Pattern.compile(Pattern.quote("group by"), Pattern.CASE_INSENSITIVE);
                    Matcher groupByMatcher = groupByPattern.matcher(secondPart);
                    if (groupByMatcher.find()) {
                        // 查询的第三部分
                        thirdPart = secondPart.substring(groupByMatcher.start(), secondPart.length());
                        // 查询的第二部分
                        secondPart = secondPart.substring(0, groupByMatcher.start());
                    }
                } else {
                    firstPart = sql;
                }

                // 创建不区分大小写的识别case when的Pattern对象
                Pattern caseWhenPattern = Pattern.compile(Pattern.quote("case when"), Pattern.CASE_INSENSITIVE);
                Matcher caseWhenMatcher = caseWhenPattern.matcher(secondPart);
                if (caseWhenMatcher.find()) {
                    canConvert = false;
                }

                // 创建不区分大小写的识别in的Pattern对象
                Pattern inPattern = Pattern.compile(Pattern.quote(" in"), Pattern.CASE_INSENSITIVE);
                Matcher inMatcher = inPattern.matcher(secondPart);
                if (inMatcher.find()) {
                    canConvert = false;
                }

                final DbType dbType = JdbcConstants.MYSQL;
                // 参数化SQL是输出的参数保存在这个List中
                List<Object> outParameters = new ArrayList<Object>();
                String psql = "";
                if (secondPart != null && StringUtils.isNotEmpty(secondPart)) {
                    secondPart = "select * from mock " + secondPart;
                    if (canConvert) {
                        try {
                            psql = ParameterizedOutputVisitorUtils.parameterize(secondPart, dbType, outParameters);
                        } catch (Exception e) {
                            logger.info("sql can not convert to dynamic params!");
                            canConvert = false;
                        }
                    } else {
                        logger.info("sql can not convert to dynamic params!");
                    }

                    psql = psql.replace("SELECT *\n"
                            + "FROM mock\n", "");
                }

                psql = firstPart + psql + " " + thirdPart;

                // 恢复LIMIT子句
                if (limitValue > 0) {
                    int limitIndex = psql.length();
                    psql = psql.substring(0, limitIndex) + " LIMIT " + limitValue;
                }

                // 恢复OFFSET子句
                if (offsetValue >= 0) {
                    int offsetIndex = psql.length();
                    psql = psql.substring(0, offsetIndex) + " OFFSET " + offsetValue;
                }

                if ((selectCount > 1) && (-1 != firstIndex && -1 != lastIndex)) {
                    psql = beginSql + psql + endSql;
                }

                if (canConvert) {
                    try {
                        PreparedStatement preparedStatement = this.ha3Connection.prepareStatement(psql);
                        for (int i = 0; i < outParameters.size(); i++) {
                            preparedStatement.setObject(i + 1, outParameters.get(i));
                        }
                        Ha3KvPairBuilder kvPairBuilder = new Ha3KvPairBuilder();
                        kvPairBuilder.enableCache();
                        kvPairBuilder.setPrepareLevel("jni.post.optimize");
                        kvPairBuilder.setFormatType("flatbuffers");
                        kvPairBuilder.setDatabaseName("general");
                        kvPairBuilder.enableUrlEncodeData();
                        if (outParameters.size() > 0) {
                            kvPairBuilder.setDynamicParams();
                        }
                        preparedStatement.setString(0, kvPairBuilder.getKvPairString());
                        this.ha3ResultSet = (Ha3ResultSet)preparedStatement.executeQuery();
                    } catch (SQLException e) {
                        e.printStackTrace();
                    }
                } else {
                    try {
                        PreparedStatement preparedStatement = this.ha3Connection.prepareStatement(originalSql);
                        Ha3KvPairBuilder kvPairBuilder = new Ha3KvPairBuilder();
                        kvPairBuilder.enableCache();
                        kvPairBuilder.setPrepareLevel("jni.post.optimize");
                        kvPairBuilder.setFormatType("flatbuffers");
                        kvPairBuilder.setDatabaseName("general");
                        kvPairBuilder.enableUrlEncodeData();
                        preparedStatement.setString(0, kvPairBuilder.getKvPairString());
                        this.ha3ResultSet = (Ha3ResultSet)preparedStatement.executeQuery();
                    } catch (SQLException e) {
                        e.printStackTrace();
                    }
                }
            }
        } else {
            result = cloudClient.query(sqlBuilder.toString());
            this.ha3ResultSet = new Ha3ResultSet(result, this);
        }
    }