@@ -1350,7 +1350,7 @@ else if ("!".equals(ce.getKey())) {
13501350 if (joinList != null ) {
13511351
13521352 String newWs = "" ;
1353- String ws = "" + whereString ;
1353+ String ws = whereString ;
13541354
13551355 List <Object > newPvl = new ArrayList <>();
13561356 List <Object > pvl = new ArrayList <>(preparedValueList );
@@ -1371,6 +1371,8 @@ else if ("!".equals(ce.getKey())) {
13711371 case "|" : // FULL JOIN 不支持 <>, [] ,避免太多符号
13721372 case "&" : // INNER JOIN
13731373 case "!" : // OUTTER JOIN
1374+ case "(" : // ANTI JOIN
1375+ case ")" : // FOREIGN JOIN
13741376 case "^" : // SIDE JOIN
13751377 case "*" : // CROSS JOIN
13761378 jc = j .getJoinConfig ();
@@ -1379,7 +1381,18 @@ else if ("!".equals(ce.getKey())) {
13791381 js = jc .getWhereString (false );
13801382 jc .setMain (isMain );
13811383
1384+ boolean isWsEmpty = StringUtil .isEmpty (ws , true );
1385+
13821386 if (StringUtil .isEmpty (js , true )) {
1387+ if (")" .equals (j .getJoinType ())) { // FOREIGN JOIN: B & ! A
1388+ if (isWsEmpty ) {
1389+ throw new NotExistException ("no result for ) FOREIGN JOIN(A & ! B) while both A and B are empty!" );
1390+ }
1391+
1392+ newWs += " ( " + getCondition (true , ws ) + " ) " ;
1393+ newPvl .addAll (pvl );
1394+ changed = true ;
1395+ }
13831396 continue ;
13841397 }
13851398
@@ -1388,27 +1401,42 @@ else if ("!".equals(ce.getKey())) {
13881401 }
13891402
13901403 //MySQL 因为 NULL 值处理问题,(A & ! B) | (B & ! A) 与 ! (A & B) 返回结果不一样,后者往往更多
1391- if ("^" .equals (j .getJoinType ())) { // (A & ! B) | (B & ! A)
1392- newWs += " ( ( " + ws + ( StringUtil .isEmpty (ws , true ) ? "" : AND + NOT ) + " ( " + js + " ) ) "
1393- + OR
1394- + " ( " + js + AND + NOT + " ( " + ws + " ) ) ) " ;
1395-
1396- newPvl .addAll (pvl );
1397- newPvl .addAll (jc .getPreparedValueList ());
1398- newPvl .addAll (jc .getPreparedValueList ());
1399- newPvl .addAll (pvl );
1404+ if ("^" .equals (j .getJoinType ())) { //SIDE JOIN: (A & ! B) | (B & ! A)
1405+ if (isWsEmpty ) {
1406+ newWs += js ;
1407+
1408+ newPvl .addAll (pvl );
1409+ newPvl .addAll (jc .getPreparedValueList ());
1410+ }
1411+ else {
1412+ newWs += " ( ( " + ws + AND + NOT + " ( " + js + " ) ) "
1413+ + OR
1414+ + " ( " + js + AND + NOT + " ( " + ws + " ) ) ) " ;
1415+
1416+ newPvl .addAll (pvl );
1417+ newPvl .addAll (jc .getPreparedValueList ());
1418+ newPvl .addAll (jc .getPreparedValueList ());
1419+ newPvl .addAll (pvl );
1420+ }
14001421 }
14011422 else {
1402- logic = Logic .getType (j .getJoinType ());
1403-
1404- newWs += " ( "
1405- + getCondition (
1406- Logic .isNot (logic ),
1407- ws
1408- + ( StringUtil .isEmpty (ws , true ) ? "" : (Logic .isAnd (logic ) ? AND : OR ) )
1409- + " ( " + js + " ) "
1410- )
1411- + " ) " ;
1423+ if ("(" .equals (j .getJoinType ())) { // ANTI JOIN: A & ! B
1424+ newWs += " ( " + ( isWsEmpty ? "" : ws + AND ) + NOT + " ( " + js + " ) " + " ) " ;
1425+ }
1426+ else if (")" .equals (j .getJoinType ())) { // FOREIGN JOIN: B & ! A
1427+ newWs += " ( " + " ( " + js + " ) " + ( isWsEmpty ? "" : AND + NOT + ws ) + " ) " ;
1428+ }
1429+ else { // & INNER JOIN: A & B; | FULL JOIN: A | B; OUTER JOIN: ! (A & B)
1430+ logic = Logic .getType (j .getJoinType ());
1431+ newWs += " ( "
1432+ + getCondition (
1433+ Logic .isNot (logic ),
1434+ ws
1435+ + ( isWsEmpty ? "" : (Logic .isAnd (logic ) ? AND : OR ) )
1436+ + " ( " + js + " ) "
1437+ )
1438+ + " ) " ;
1439+ }
14121440
14131441 newPvl .addAll (pvl );
14141442 newPvl .addAll (jc .getPreparedValueList ());
@@ -1417,7 +1445,11 @@ else if ("!".equals(ce.getKey())) {
14171445 changed = true ;
14181446 break ;
14191447 default :
1420- throw new UnsupportedOperationException ("join:value 中 value 里的 " + j .getJoinType () + "/" + j .getPath () + "错误!不支持 " + j .getJoinType () + " 等 [@ APP, < LEFT, > RIGHT, | FULL, & INNER, ! OUTTER, ^ SIDE, * CROSS] 之外的JOIN类型 !" );
1448+ throw new UnsupportedOperationException (
1449+ "join:value 中 value 里的 " + j .getJoinType () + "/" + j .getPath ()
1450+ + "错误!不支持 " + j .getJoinType () + " 等 [ @ APP, < LEFT, > RIGHT, | FULL, & INNER, ! OUTTER"
1451+ + ", ( ANTI, ) FOREIGN, ^ SIDE, * CROSS ] 之外的JOIN类型 !"
1452+ );
14211453 }
14221454 }
14231455
@@ -1427,7 +1459,7 @@ else if ("!".equals(ce.getKey())) {
14271459 }
14281460 }
14291461
1430- String s = whereString .isEmpty () ? "" : (hasPrefix ? " WHERE " : "" ) + whereString ;
1462+ String s = StringUtil .isEmpty (whereString , true ) ? "" : (hasPrefix ? " WHERE " : "" ) + whereString ;
14311463
14321464 if (s .isEmpty () && RequestMethod .isQueryMethod (method ) == false ) {
14331465 throw new UnsupportedOperationException ("写操作请求必须带条件!!!" );
@@ -2313,13 +2345,18 @@ public String getJoinString() throws Exception {
23132345 case "&" : // INNER JOIN
23142346 case "!" : // OUTTER JOIN
23152347 case "^" : // SIDE JOIN
2348+ case "(" : // ANTI JOIN
2349+ case ")" : // FOREIGN JOIN
23162350 //场景少且性能差,默认禁用 case "*": // CROSS JOIN
23172351 sql = ("*" .equals (j .getJoinType ()) ? " CROSS JOIN " : " INNER JOIN " ) + jc .getTablePath ()
23182352 + " ON " + quote + jt + quote + "." + quote + j .getKey () + quote + " = " + quote + tn + quote + "." + quote + j .getTargetKey () + quote ;
23192353 break ;
23202354 default :
2321- throw new UnsupportedOperationException ("join:value 中 value 里的 " + j .getJoinType () + "/" + j .getPath () + "错误!不支持 " + j .getJoinType () + " 等 [@ APP, < LEFT, > RIGHT, | FULL, & INNER, ! OUTTER, ^ SIDE, * CROSS] 之外的JOIN类型 !" );
2322- }
2355+ throw new UnsupportedOperationException (
2356+ "join:value 中 value 里的 " + j .getJoinType () + "/" + j .getPath ()
2357+ + "错误!不支持 " + j .getJoinType () + " 等 [ @ APP, < LEFT, > RIGHT, | FULL, & INNER, ! OUTTER"
2358+ + ", ( ANTI, ) FOREIGN, ^ SIDE, * CROSS ] 之外的JOIN类型 !"
2359+ ); }
23232360
23242361 joinOns += " \n " + sql ;
23252362 }
0 commit comments