Update AbstractSQLExecutor.java

This commit is contained in:
TommyLemon 2022-10-17 21:28:27 +08:00 committed by GitHub
parent 47fbbdabc0
commit 74a7717dd7
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

@ -263,7 +263,7 @@ public abstract class AbstractSQLExecutor implements SQLExecutor {
Log.i(TAG, ">>> execute result = getCache('" + sql + "', " + position + ") = " + result);
if (result != null) {
cachedSQLCount ++;
List<JSONObject> cache = getCache(sql, config);
List<JSONObject> cache = getCache(sql, config);
if (cache != null && cache.size() > 1) {
result.put(KEY_RAW_LIST, cache);
}
@ -525,17 +525,17 @@ public abstract class AbstractSQLExecutor implements SQLExecutor {
SQLConfig viceConfig = curJoin != null && curJoin.isSQLJoin() ? curJoin.getCacheConfig() : null;
if (viceConfig != null) { //FIXME 只有和主表关联才能用 item否则应该从 childMap 查其它副表数据
List<On> onList = curJoin.getOnList();
int size = onList == null ? 0 : onList.size();
int size = onList == null ? 0 : onList.size();
if (size > 0) {
for (int j = size - 1; j >= 0; j--) {
On on = onList.get(j);
String ok = on == null ? null : on.getOriginKey();
if (ok == null) {
throw new NullPointerException("服务器内部错误List<Join> 中 Join.onList[" + j + (on == null ? "] = null" : ".getOriginKey() = null"));
for (int j = size - 1; j >= 0; j--) {
On on = onList.get(j);
String ok = on == null ? null : on.getOriginKey();
if (ok == null) {
throw new NullPointerException("服务器内部错误List<Join> 中 Join.onList[" + j + (on == null ? "] = null" : ".getOriginKey() = null"));
}
viceConfig.putWhere(ok.substring(0, ok.length() - 1), item.get(on.getTargetKey()), true);
}
viceConfig.putWhere(ok.substring(0, ok.length() - 1), item.get(on.getTargetKey()), true);
}
}
}
String viceSql = viceConfig == null ? null : viceConfig.getSQL(false); //TODO SQLConfig 缓存 SQL减少大量的重复生成
@ -651,7 +651,7 @@ public abstract class AbstractSQLExecutor implements SQLExecutor {
continue;
}
SQLConfig cc = join.getCacheConfig(); //这里用config改了getSQL后再还原很麻烦所以提前给一个config2更好
SQLConfig cc = join.getCacheConfig(); //这里用config改了getSQL后再还原很麻烦所以提前给一个config2更好
if (cc == null) {
if (Log.DEBUG) {
throw new NullPointerException("服务器内部错误, executeAppJoin cc == null ! 导致不能缓存 @ APP JOIN 的副表数据!");
@ -659,110 +659,110 @@ public abstract class AbstractSQLExecutor implements SQLExecutor {
continue;
}
SQLConfig jc = join.getJoinConfig();
SQLConfig jc = join.getJoinConfig();
List<On> onList = join.getOnList();
On on = onList == null || onList.isEmpty() ? null : onList.get(0); // APP JOIN 应该有且只有一个 ON 条件
String originKey = on == null ? null : on.getOriginKey();
if (originKey == null) {
throw new NullPointerException("服务器内部错误List<Join> 中 Join.onList[0" + (on == null ? "] = null" : ".getOriginKey() = null"));
}
String key = on.getKey();
if (key == null) {
throw new NullPointerException("服务器内部错误List<Join> 中 Join.onList[0" + (on == null ? "] = null" : ".getKey() = null"));
}
On on = onList == null || onList.isEmpty() ? null : onList.get(0); // APP JOIN 应该有且只有一个 ON 条件
String originKey = on == null ? null : on.getOriginKey();
if (originKey == null) {
throw new NullPointerException("服务器内部错误List<Join> 中 Join.onList[0" + (on == null ? "] = null" : ".getOriginKey() = null"));
}
String key = on.getKey();
if (key == null) {
throw new NullPointerException("服务器内部错误List<Join> 中 Join.onList[0" + (on == null ? "] = null" : ".getKey() = null"));
}
// 取出 "id@": "@/User/userId" 中所有 userId 的值
List<Object> targetValueList = new ArrayList<>();
// 取出 "id@": "@/User/userId" 中所有 userId 的值
List<Object> targetValueList = new ArrayList<>();
for (int i = 0; i < resultList.size(); i++) {
JSONObject mainTable = resultList.get(i);
Object targetValue = mainTable == null ? null : mainTable.get(on.getTargetKey());
for (int i = 0; i < resultList.size(); i++) {
JSONObject mainTable = resultList.get(i);
Object targetValue = mainTable == null ? null : mainTable.get(on.getTargetKey());
if (targetValue != null && targetValueList.contains(targetValue) == false) {
targetValueList.add(targetValue);
}
}
if (targetValue != null && targetValueList.contains(targetValue) == false) {
targetValueList.add(targetValue);
}
}
if (targetValueList.isEmpty() && config.isExplain() == false) {
throw new NotExistException("targetValueList.isEmpty() && config.isExplain() == false");
}
if (targetValueList.isEmpty() && config.isExplain() == false) {
throw new NotExistException("targetValueList.isEmpty() && config.isExplain() == false");
}
// 替换为 "id{}": [userId1, userId2, userId3...]
jc.putWhere(originKey, null, false); // remove originKey
jc.putWhere(key + "{}", targetValueList, true); // add originKey{} }
// 替换为 "id{}": [userId1, userId2, userId3...]
jc.putWhere(originKey, null, false); // remove originKey
jc.putWhere(key + "{}", targetValueList, true); // add originKey{} }
jc.setMain(true).setPreparedValueList(new ArrayList<>());
jc.setMain(true).setPreparedValueList(new ArrayList<>());
// 放一块逻辑更清晰也避免解析 * 等不支持或性能开销
// String q = jc.getQuote();
// if (allChildCount > 0 && jc.getCount() <= 0) {
// List<String> column = jc.getColumn();
// if (column == null || column.isEmpty()) {
// column = Arrays.asList("*;row_number()OVER(PARTITION BY " + q + key + q + " ORDER BY " + q + key + q + " ASC):_row_num_");
// }
// else {
// column.add("row_number()OVER(PARTITION BY " + q + key + q + " ORDER BY " + q + key + q + " ASC):_row_num_");
// }
// jc.setColumn(column);
// }
// 放一块逻辑更清晰也避免解析 * 等不支持或性能开销
// String q = jc.getQuote();
// if (allChildCount > 0 && jc.getCount() <= 0) {
// List<String> column = jc.getColumn();
// if (column == null || column.isEmpty()) {
// column = Arrays.asList("*;row_number()OVER(PARTITION BY " + q + key + q + " ORDER BY " + q + key + q + " ASC):_row_num_");
// }
// else {
// column.add("row_number()OVER(PARTITION BY " + q + key + q + " ORDER BY " + q + key + q + " ASC):_row_num_");
// }
// jc.setColumn(column);
// }
int childCount = cc.getCount();
int allChildCount = childCount*config.getCount(); // 所有分组子项数量总和
boolean isOne2Many = childCount != 1 || join.isOne2Many();
// 一对多会漏副表数据 TODO 似乎一对一走以下优化 row_number() <= childCount 逻辑也没问题
// if (isOne2Many == false && allChildCount > 0 && jc.getCount() < allChildCount) {
// jc.setCount(allChildCount);
// }
int childCount = cc.getCount();
int allChildCount = childCount*config.getCount(); // 所有分组子项数量总和
boolean isOne2Many = childCount != 1 || join.isOne2Many();
// 一对多会漏副表数据 TODO 似乎一对一走以下优化 row_number() <= childCount 逻辑也没问题
// if (isOne2Many == false && allChildCount > 0 && jc.getCount() < allChildCount) {
// jc.setCount(allChildCount);
// }
boolean prepared = jc.isPrepared();
String sql = jc.getSQL(false);
String sql = jc.getSQL(false);
jc.setPrepared(prepared);
if (StringUtil.isEmpty(sql, true)) {
throw new NullPointerException(TAG + ".executeAppJoin StringUtil.isEmpty(sql, true) >> return null;");
}
String sql2 = null;
if (childCount > 0 && isOne2Many && (jc.isMySQL() == false || jc.getDBVersionNums()[0] >= 8)) {
// row_number 字段并不会导致 count 等聚合函数统计出错结果偏大SQL JOIN 才会之前没发现是因为缓存失效 bug
// boolean noAggrFun = true;
// List<String> column = jc.getColumn();
// if (column != null) {
// for (String c : column) {
// int start = c == null ? -1 : c.indexOf("(");
// int end = start <= 0 ? -1 : c.lastIndexOf(")");
// if (start > 0 && end > start) {
// String fun = c.substring(0, start);
// if (AbstractSQLConfig.SQL_AGGREGATE_FUNCTION_MAP.containsKey(fun)) {
// noAggrFun = false;
// break;
// }
// }
// }
// }
//
// if (noAggrFun) { // row_number 字段会导致 count 等聚合函数统计出错结果偏大
String q = jc.getQuote();
sql2 = prepared ? jc.getSQL(true) : sql;
String sql2 = null;
if (childCount > 0 && isOne2Many && (jc.isMySQL() == false || jc.getDBVersionNums()[0] >= 8)) {
// row_number 字段并不会导致 count 等聚合函数统计出错结果偏大SQL JOIN 才会之前没发现是因为缓存失效 bug
// boolean noAggrFun = true;
// List<String> column = jc.getColumn();
// if (column != null) {
// for (String c : column) {
// int start = c == null ? -1 : c.indexOf("(");
// int end = start <= 0 ? -1 : c.lastIndexOf(")");
// if (start > 0 && end > start) {
// String fun = c.substring(0, start);
// if (AbstractSQLConfig.SQL_AGGREGATE_FUNCTION_MAP.containsKey(fun)) {
// noAggrFun = false;
// break;
// }
// }
// }
// }
//
// if (noAggrFun) { // row_number 字段会导致 count 等聚合函数统计出错结果偏大
String q = jc.getQuote();
sql2 = prepared ? jc.getSQL(true) : sql;
String prefix = "SELECT * FROM(";
String rnStr = ", row_number() OVER (PARTITION BY " + q + key + q + ((AbstractSQLConfig) jc).getOrderString(true) + ") _row_num_ FROM ";
String suffix = ") _t WHERE ( (_row_num_ <= " + childCount + ") )" + (allChildCount > 0 ? " LIMIT " + allChildCount : "");
String prefix = "SELECT * FROM(";
String rnStr = ", row_number() OVER (PARTITION BY " + q + key + q + ((AbstractSQLConfig) jc).getOrderString(true) + ") _row_num_ FROM ";
String suffix = ") _t WHERE ( (_row_num_ <= " + childCount + ") )" + (allChildCount > 0 ? " LIMIT " + allChildCount : "");
sql2 = prefix
// 放一块逻辑更清晰也避免解析 * 等不支持或性能开销 + sql
+ sql2.replaceFirst(" FROM ", rnStr) // * 居然只能放在 row_number() 前面放后面就报错 "SELECT ", rnStr)
+ suffix;
sql2 = prefix
// 放一块逻辑更清晰也避免解析 * 等不支持或性能开销 + sql
+ sql2.replaceFirst(" FROM ", rnStr) // * 居然只能放在 row_number() 前面放后面就报错 "SELECT ", rnStr)
+ suffix;
sql = prepared ? (prefix + sql.replaceFirst(" FROM ", rnStr) + suffix) : sql2;
// }
}
sql = prepared ? (prefix + sql.replaceFirst(" FROM ", rnStr) + suffix) : sql2;
// }
}
boolean isExplain = jc.isExplain();
if (isExplain == false) {
generatedSQLCount ++;
}
boolean isExplain = jc.isExplain();
if (isExplain == false) {
generatedSQLCount ++;
}
long startTime = System.currentTimeMillis();
Log.d(TAG, "\n<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<"
@ -773,17 +773,17 @@ public abstract class AbstractSQLExecutor implements SQLExecutor {
//执行副表的批量查询 缓存到 childMap
ResultSet rs = null;
try {
long executedSQLStartTime = 0;
if (isExplain == false) { //只有 SELECT 才能 EXPLAIN
executedSQLCount ++;
executedSQLStartTime = System.currentTimeMillis();
}
rs = executeQuery(jc, sql2);
if (isExplain == false) {
executedSQLDuration += System.currentTimeMillis() - executedSQLStartTime;
}
long executedSQLStartTime = 0;
if (isExplain == false) { //只有 SELECT 才能 EXPLAIN
executedSQLCount ++;
executedSQLStartTime = System.currentTimeMillis();
}
rs = executeQuery(jc, sql2);
if (isExplain == false) {
executedSQLDuration += System.currentTimeMillis() - executedSQLStartTime;
}
int count = 0;
int count = 0;
int index = -1;
@ -792,7 +792,7 @@ public abstract class AbstractSQLExecutor implements SQLExecutor {
final int length = rsmd.getColumnCount();
sqlResultDuration += System.currentTimeMillis() - startTime2;
Map<String, Boolean> skipMap = new HashMap<>();
Map<String, Boolean> skipMap = new HashMap<>();
long lastCursorTime = System.currentTimeMillis();
while ((allChildCount <= 0 || count < allChildCount) && rs.next()) { //FIXME 同时有 @ APP JOIN < SQL JOIN next = false 总是无法进入循环导致缓存失效可能是连接池或线程问题
@ -802,7 +802,7 @@ public abstract class AbstractSQLExecutor implements SQLExecutor {
index ++;
Log.d(TAG, "\n\n<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\n executeAppJoin while (rs.next()){ index = " + index + "\n\n");
JSONObject result = new JSONObject(true);
JSONObject result = new JSONObject(true);
for (int i = 1; i <= length; i++) {
result = onPutColumn(jc, rs, rsmd, index, result, i, null, null);
@ -813,26 +813,26 @@ public abstract class AbstractSQLExecutor implements SQLExecutor {
Log.d(TAG, "\n executeAppJoin while (rs.next()) { resultList.put(" + index + ", result); "
+ "\n >>>>>>>>>>>>>>>>>>>>>>>>>>> \n\n");
//TODO 兼容复杂关联
cc.putWhere(key, result.get(key), true); // APP JOIN 应该有且只有一个 ON 条件
String cacheSql = cc.getSQL(false);
List<JSONObject> results = childMap.get(cacheSql);
//TODO 兼容复杂关联
cc.putWhere(key, result.get(key), true); // APP JOIN 应该有且只有一个 ON 条件
String cacheSql = cc.getSQL(false);
List<JSONObject> results = childMap.get(cacheSql);
if (results == null || skipMap.get(cacheSql) == null) { // 避免添加重复数据
results = new ArrayList<>(childCount);
childMap.put(cacheSql, results);
skipMap.put(cacheSql, Boolean.TRUE);
}
if (results == null || skipMap.get(cacheSql) == null) { // 避免添加重复数据
results = new ArrayList<>(childCount);
childMap.put(cacheSql, results);
skipMap.put(cacheSql, Boolean.TRUE);
}
if (childCount <= 0 || results.size() < childCount) { // 避免超过子数组每页数量
// if (count == 1 && results.isEmpty() == false) { // 避免添加重复数据
// results.clear();
// }
results.add(result); //缓存到 childMap
count ++;
Log.d(TAG, ">>> executeAppJoin childMap.put('" + cacheSql + "', result); childMap.size() = " + childMap.size());
}
}
if (childCount <= 0 || results.size() < childCount) { // 避免超过子数组每页数量
// if (count == 1 && results.isEmpty() == false) { // 避免添加重复数据
// results.clear();
// }
results.add(result); //缓存到 childMap
count ++;
Log.d(TAG, ">>> executeAppJoin childMap.put('" + cacheSql + "', result); childMap.size() = " + childMap.size());
}
}
}
finally {
if (rs != null) {
@ -971,9 +971,9 @@ public abstract class AbstractSQLExecutor implements SQLExecutor {
else if (value instanceof Date) { // java.sql.Date java.sql.Time 都继承 java.util.Date
value = ((Date) value).toString();
}
else if (value instanceof LocalDateTime) {
value = ((LocalDateTime) value).toString();
}
else if (value instanceof LocalDateTime) {
value = ((LocalDateTime) value).toString();
}
else if (value instanceof Year) {
value = ((Year) value).getValue();
}
@ -1058,13 +1058,13 @@ public abstract class AbstractSQLExecutor implements SQLExecutor {
@Override // 重写是为了返回类型从 Statement 改为 PreparedStatement避免其它方法出错
public PreparedStatement getStatement(@NotNull SQLConfig config) throws Exception {
return getStatement(config, null);
}
return getStatement(config, null);
}
@Override
public PreparedStatement getStatement(@NotNull SQLConfig config, String sql) throws Exception {
if (StringUtil.isEmpty(sql)) {
sql = config.getSQL(config.isPrepared());
}
if (StringUtil.isEmpty(sql)) {
sql = config.getSQL(config.isPrepared());
}
PreparedStatement statement; //创建Statement对象
if (config.getMethod() == RequestMethod.POST && config.getId() == null) { //自增id
@ -1120,7 +1120,7 @@ public abstract class AbstractSQLExecutor implements SQLExecutor {
connectionMap.put(connectionKey, connection);
}
// TDengine 驱动内部事务处理方法都是空实现手动 commit 无效
// TDengine 驱动内部事务处理方法都是空实现手动 commit 无效
int ti = config.isTDengine() ? Connection.TRANSACTION_NONE : getTransactionIsolation();
if (ti != Connection.TRANSACTION_NONE) { //java.sql.SQLException: Transaction isolation level NONE not supported by MySQL
begin(ti);
@ -1219,11 +1219,11 @@ public abstract class AbstractSQLExecutor implements SQLExecutor {
@Override
public ResultSet executeQuery(@NotNull SQLConfig config, String sql) throws Exception {
if (config.isTDengine()) {
Connection conn = getConnection(config);
Statement stt = conn.createStatement();
return executeQuery(stt, StringUtil.isEmpty(sql) ? config.getSQL(false) : sql);
}
if (config.isTDengine()) {
Connection conn = getConnection(config);
Statement stt = conn.createStatement();
return executeQuery(stt, StringUtil.isEmpty(sql) ? config.getSQL(false) : sql);
}
PreparedStatement stt = getStatement(config, sql);
ResultSet rs = stt.executeQuery(); //PreparedStatement 不用传 SQL
@ -1237,17 +1237,17 @@ public abstract class AbstractSQLExecutor implements SQLExecutor {
@Override
public int executeUpdate(@NotNull SQLConfig config, String sql) throws Exception {
Statement stt;
int count;
if (config.isTDengine()) {
Connection conn = getConnection(config);
stt = conn.createStatement();
count = stt.executeUpdate(StringUtil.isEmpty(sql) ? config.getSQL(false) : sql);
}
else {
stt = getStatement(config);
count = ((PreparedStatement) stt).executeUpdate(); // PreparedStatement 不用传 SQL
}
Statement stt;
int count;
if (config.isTDengine()) {
Connection conn = getConnection(config);
stt = conn.createStatement();
count = stt.executeUpdate(StringUtil.isEmpty(sql) ? config.getSQL(false) : sql);
}
else {
stt = getStatement(config);
count = ((PreparedStatement) stt).executeUpdate(); // PreparedStatement 不用传 SQL
}
if (count <= 0 && config.isHive()) {
count = 1;