优化 where 和 JOIN 解析代码

This commit is contained in:
TommyLemon 2022-03-06 20:53:29 +08:00
parent cf7bdd74e4
commit 3ea3e61215

View File

@ -2585,6 +2585,87 @@ public abstract class AbstractSQLConfig implements SQLConfig {
setPreparedValueList(prepreadValues);
}
whereString = concatJoinWhereString(whereString);
String result = StringUtil.isEmpty(whereString, true) ? "" : (hasPrefix ? " WHERE " : "") + whereString;
if (result.isEmpty() && RequestMethod.isQueryMethod(method) == false) {
throw new UnsupportedOperationException("写操作请求必须带条件!!!");
}
return result;
}
public String getWhereString(boolean hasPrefix, RequestMethod method, Map<String, Object> where, Map<String, List<String>> combine, List<Join> joinList, boolean verifyName) throws Exception {
Set<Entry<String, List<String>>> combineSet = combine == null ? null : combine.entrySet();
if (combineSet == null || combineSet.isEmpty()) {
Log.w(TAG, "getWhereString combineSet == null || combineSet.isEmpty() >> return \"\";");
return "";
}
List<String> keyList;
String whereString = "";
boolean isCombineFirst = true;
int logic;
boolean isItemFirst;
String c;
String cs;
for (Entry<String, List<String>> ce : combineSet) {
keyList = ce == null ? null : ce.getValue();
if (keyList == null || keyList.isEmpty()) {
continue;
}
if ("|".equals(ce.getKey())) {
logic = Logic.TYPE_OR;
}
else if ("!".equals(ce.getKey())) {
logic = Logic.TYPE_NOT;
}
else {
logic = Logic.TYPE_AND;
}
isItemFirst = true;
cs = "";
for (String key : keyList) {
c = getWhereItem(key, where.get(key), method, verifyName);
if (StringUtil.isEmpty(c, true)) {//避免SQL条件连接错误
continue;
}
cs += (isItemFirst ? "" : (Logic.isAnd(logic) ? AND : OR)) + "(" + c + ")";
isItemFirst = false;
}
if (StringUtil.isEmpty(cs, true)) {//避免SQL条件连接错误
continue;
}
whereString += (isCombineFirst ? "" : AND) + (Logic.isNot(logic) ? NOT : "") + " ( " + cs + " ) ";
isCombineFirst = false;
}
whereString = concatJoinWhereString(whereString);
String s = StringUtil.isEmpty(whereString, true) ? "" : (hasPrefix ? " WHERE " : "") + whereString;
if (s.isEmpty() && RequestMethod.isQueryMethod(method) == false) {
throw new UnsupportedOperationException("写操作请求必须带条件!!!");
}
return s;
}
protected String concatJoinWhereString(String whereString) throws Exception {
List<Join> joinList = getJoinList();
if (joinList != null) {
String newWs = "";
@ -2711,208 +2792,10 @@ public abstract class AbstractSQLConfig implements SQLConfig {
}
}
String result = StringUtil.isEmpty(whereString, true) ? "" : (hasPrefix ? " WHERE " : "") + whereString;
if (result.isEmpty() && RequestMethod.isQueryMethod(method) == false) {
throw new UnsupportedOperationException("写操作请求必须带条件!!!");
}
return result;
return whereString;
}
public String getWhereString(boolean hasPrefix, RequestMethod method, Map<String, Object> where, Map<String, List<String>> combine, List<Join> joinList, boolean verifyName) throws Exception {
Set<Entry<String, List<String>>> combineSet = combine == null ? null : combine.entrySet();
if (combineSet == null || combineSet.isEmpty()) {
Log.w(TAG, "getWhereString combineSet == null || combineSet.isEmpty() >> return \"\";");
return "";
}
List<String> keyList;
String whereString = "";
boolean isCombineFirst = true;
int logic;
boolean isItemFirst;
String c;
String cs;
for (Entry<String, List<String>> ce : combineSet) {
keyList = ce == null ? null : ce.getValue();
if (keyList == null || keyList.isEmpty()) {
continue;
}
if ("|".equals(ce.getKey())) {
logic = Logic.TYPE_OR;
}
else if ("!".equals(ce.getKey())) {
logic = Logic.TYPE_NOT;
}
else {
logic = Logic.TYPE_AND;
}
isItemFirst = true;
cs = "";
for (String key : keyList) {
c = getWhereItem(key, where.get(key), method, verifyName);
if (StringUtil.isEmpty(c, true)) {//避免SQL条件连接错误
continue;
}
cs += (isItemFirst ? "" : (Logic.isAnd(logic) ? AND : OR)) + "(" + c + ")";
isItemFirst = false;
}
if (StringUtil.isEmpty(cs, true)) {//避免SQL条件连接错误
continue;
}
whereString += (isCombineFirst ? "" : AND) + (Logic.isNot(logic) ? NOT : "") + " ( " + cs + " ) ";
isCombineFirst = false;
}
if (joinList != null) {
String newWs = "";
String ws = whereString;
List<Object> newPvl = new ArrayList<>();
List<Object> pvl = new ArrayList<>(preparedValueList);
SQLConfig jc;
String js;
boolean changed = false;
//各种 JOIN 没办法统一用 & | 连接只能按优先级 @combine 一样?
for (Join j : joinList) {
String jt = j.getJoinType();
switch (jt) {
case "*": // CROSS JOIN
case "@": // APP JOIN
case "<": // LEFT JOIN
case ">": // RIGHT JOIN
break;
case "&": // INNER JOIN: A & B
case "": // FULL JOIN: A | B
case "|": // FULL JOIN: A | B
case "!": // OUTER JOIN: ! (A | B)
case "^": // SIDE JOIN: ! (A & B)
case "(": // ANTI JOIN: A & ! B
case ")": // FOREIGN JOIN: B & ! A
jc = j.getJoinConfig();
boolean isMain = jc.isMain();
jc.setMain(false).setPrepared(isPrepared()).setPreparedValueList(new ArrayList<Object>());
js = jc.getWhereString(false);
jc.setMain(isMain);
boolean isOuterJoin = "!".equals(jt);
boolean isSideJoin = "^".equals(jt);
boolean isAntiJoin = "(".equals(jt);
boolean isForeignJoin = ")".equals(jt);
boolean isWsEmpty = StringUtil.isEmpty(ws, true);
if (isWsEmpty) {
if (isOuterJoin) { // ! OUTER JOIN: ! (A | B)
throw new NotExistException("no result for ! OUTER JOIN( ! (A | B) ) when A or B is empty!");
}
if (isForeignJoin) { // ) FOREIGN JOIN: B & ! A
throw new NotExistException("no result for ) FOREIGN JOIN( B & ! A ) when A is empty!");
}
}
if (StringUtil.isEmpty(js, true)) {
if (isOuterJoin) { // ! OUTER JOIN: ! (A | B)
throw new NotExistException("no result for ! OUTER JOIN( ! (A | B) ) when A or B is empty!");
}
if (isAntiJoin) { // ( ANTI JOIN: A & ! B
throw new NotExistException("no result for ( ANTI JOIN( A & ! B ) when B is empty!");
}
if (isWsEmpty) {
if (isSideJoin) {
throw new NotExistException("no result for ^ SIDE JOIN( ! (A & B) ) when both A and B are empty!");
}
}
else {
if (isSideJoin || isForeignJoin) {
newWs += " ( " + getCondition(true, ws) + " ) ";
newPvl.addAll(pvl);
newPvl.addAll(jc.getPreparedValueList());
changed = true;
}
}
continue;
}
if (StringUtil.isEmpty(newWs, true) == false) {
newWs += AND;
}
if (isAntiJoin) { // ( ANTI JOIN: A & ! B
newWs += " ( " + ( isWsEmpty ? "" : ws + AND ) + NOT + " ( " + js + " ) " + " ) ";
}
else if (isForeignJoin) { // ) FOREIGN JOIN: (! A) & B // preparedValueList.add 不好反过来 B & ! A
newWs += " ( " + NOT + " ( " + ws + " ) ) " + AND + " ( " + js + " ) ";
}
else if (isSideJoin) { // ^ SIDE JOIN: ! (A & B)
//MySQL 因为 NULL 值处理问题(A & ! B) | (B & ! A) ! (A & B) 返回结果不一样后者往往更多
newWs += " ( " + getCondition(
true,
( isWsEmpty ? "" : ws + AND ) + " ( " + js + " ) "
) + " ) ";
}
else { // & INNER JOIN: A & B; | FULL JOIN: A | B; OUTER JOIN: ! (A | B)
logic = Logic.getType(jt);
newWs += " ( "
+ getCondition(
Logic.isNot(logic),
ws
+ ( isWsEmpty ? "" : (Logic.isAnd(logic) ? AND : OR) )
+ " ( " + js + " ) "
)
+ " ) ";
}
newPvl.addAll(pvl);
newPvl.addAll(jc.getPreparedValueList());
changed = true;
break;
default:
throw new UnsupportedOperationException(
"join:value 中 value 里的 " + jt + "/" + j.getPath()
+ "错误!不支持 " + jt + " 等 [ @ APP, < LEFT, > RIGHT, * CROSS"
+ ", & INNER, | FULL, ! OUTER, ^ SIDE, ( ANTI, ) FOREIGN ] 之外的 JOIN 类型 !"
);
}
}
if (changed) {
whereString = newWs;
preparedValueList = newPvl;
}
}
String s = StringUtil.isEmpty(whereString, true) ? "" : (hasPrefix ? " WHERE " : "") + whereString;
if (s.isEmpty() && RequestMethod.isQueryMethod(method) == false) {
throw new UnsupportedOperationException("写操作请求必须带条件!!!");
}
return s;
}
/**
* @param key
* @param value