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);
}
}