@@ -422,7 +422,7 @@ public String getGroupString(boolean hasPrefix) {
422422 continue ;
423423 }
424424
425- cfg = j .isLeftOrRightJoin () ? j .getOutterConfig () : j .getJoinConfig ();
425+ cfg = j .isLeftOrRightJoin () ? j .getOuterConfig () : j .getJoinConfig ();
426426 if (StringUtil .isEmpty (cfg .getAlias (), true )) {
427427 cfg .setAlias (cfg .getTable ());
428428 }
@@ -484,7 +484,7 @@ public String getHavingString(boolean hasPrefix) {
484484 continue ;
485485 }
486486
487- cfg = j .isLeftOrRightJoin () ? j .getOutterConfig () : j .getJoinConfig ();
487+ cfg = j .isLeftOrRightJoin () ? j .getOuterConfig () : j .getJoinConfig ();
488488 if (StringUtil .isEmpty (cfg .getAlias (), true )) {
489489 cfg .setAlias (cfg .getTable ());
490490 }
@@ -594,7 +594,7 @@ public String getOrderString(boolean hasPrefix) {
594594 continue ;
595595 }
596596
597- cfg = j .isLeftOrRightJoin () ? j .getOutterConfig () : j .getJoinConfig ();
597+ cfg = j .isLeftOrRightJoin () ? j .getOuterConfig () : j .getJoinConfig ();
598598 if (StringUtil .isEmpty (cfg .getAlias (), true )) {
599599 cfg .setAlias (cfg .getTable ());
600600 }
@@ -766,7 +766,7 @@ public String getColumnString(boolean inSQLJoin) throws Exception {
766766 continue ;
767767 }
768768
769- ecfg = j .getOutterConfig ();
769+ ecfg = j .getOuterConfig ();
770770 if (ecfg != null && ecfg .getColumn () != null ) { //优先级更高
771771 cfg = ecfg ;
772772 }
@@ -1361,94 +1361,108 @@ else if ("!".equals(ce.getKey())) {
13611361 boolean changed = false ;
13621362 //各种 JOIN 没办法统一用 & | !连接,只能按优先级,和 @combine 一样?
13631363 for (Join j : joinList ) {
1364- switch (j .getJoinType ()) {
1364+ String jt = j .getJoinType ();
1365+
1366+ switch (jt ) {
1367+ case "*" : // CROSS JOIN
13651368 case "@" : // APP JOIN
13661369 case "<" : // LEFT JOIN
13671370 case ">" : // RIGHT JOIN
13681371 break ;
13691372
1370- case "" : // FULL JOIN
1371- case "|" : // FULL JOIN 不支持 <>, [] ,避免太多符号
1372- case "&" : // INNER JOIN
1373- case "!" : // OUTTER JOIN
1374- case "(" : // ANTI JOIN
1375- case ")" : // FOREIGN JOIN
1376- case "^" : // SIDE JOIN
1377- case "*" : // CROSS JOIN
1373+ case "&" : // INNER JOIN: A & B
1374+ case "" : // FULL JOIN: A | B
1375+ case "|" : // FULL JOIN: A | B
1376+ case "!" : // OUTER JOIN: ! (A | B)
1377+ case "^" : // SIDE JOIN: ! (A & B)
1378+ case "(" : // ANTI JOIN: A & ! B
1379+ case ")" : // FOREIGN JOIN: B & ! A
13781380 jc = j .getJoinConfig ();
13791381 boolean isMain = jc .isMain ();
13801382 jc .setMain (false ).setPrepared (isPrepared ()).setPreparedValueList (new ArrayList <Object >());
13811383 js = jc .getWhereString (false );
13821384 jc .setMain (isMain );
13831385
1386+ boolean isOuterJoin = "!" .equals (jt );
1387+ boolean isSideJoin = "^" .equals (jt );
1388+ boolean isAntiJoin = "(" .equals (jt );
1389+ boolean isForeignJoin = ")" .equals (jt );
13841390 boolean isWsEmpty = StringUtil .isEmpty (ws , true );
1385-
1391+
1392+ if (isWsEmpty ) {
1393+ if (isOuterJoin ) { // ! OUTER JOIN: ! (A | B)
1394+ throw new NotExistException ("no result for ! OUTER JOIN( ! (A | B) ) when A or B is empty!" );
1395+ }
1396+ if (isForeignJoin ) { // ) FOREIGN JOIN: B & ! A
1397+ throw new NotExistException ("no result for ) FOREIGN JOIN( B & ! A ) when A is empty!" );
1398+ }
1399+ }
1400+
13861401 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!" );
1402+ if (isOuterJoin ) { // ! OUTER JOIN: ! (A | B)
1403+ throw new NotExistException ("no result for ! OUTER JOIN( ! (A | B) ) when A or B is empty!" );
1404+ }
1405+ if (isAntiJoin ) { // ( ANTI JOIN: A & ! B
1406+ throw new NotExistException ("no result for ( ANTI JOIN( A & ! B ) when B is empty!" );
1407+ }
1408+
1409+ if (isWsEmpty ) {
1410+ if (isSideJoin ) {
1411+ throw new NotExistException ("no result for ^ SIDE JOIN( ! (A & B) ) when both A and B are empty!" );
1412+ }
1413+ }
1414+ else {
1415+ if (isSideJoin || isForeignJoin ) {
1416+ newWs += " ( " + getCondition (true , ws ) + " ) " ;
1417+
1418+ newPvl .addAll (pvl );
1419+ newPvl .addAll (jc .getPreparedValueList ());
1420+ changed = true ;
13901421 }
1391-
1392- newWs += " ( " + getCondition (true , ws ) + " ) " ;
1393- newPvl .addAll (pvl );
1394- changed = true ;
13951422 }
1423+
13961424 continue ;
13971425 }
13981426
13991427 if (StringUtil .isEmpty (newWs , true ) == false ) {
14001428 newWs += AND ;
14011429 }
14021430
1403- //MySQL 因为 NULL 值处理问题,(A & ! B) | (B & ! A) 与 ! (A & B) 返回结果不一样,后者往往更多
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- }
1431+ if (isAntiJoin ) { // ( ANTI JOIN: A & ! B
1432+ newWs += " ( " + ( isWsEmpty ? "" : ws + AND ) + NOT + " ( " + js + " ) " + " ) " ;
14211433 }
1422- else {
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- }
1440-
1441- newPvl .addAll (pvl );
1442- newPvl .addAll (jc .getPreparedValueList ());
1434+ else if (isForeignJoin ) { // ) FOREIGN JOIN: B & ! A
1435+ newWs += " ( " + " ( " + js + " ) " + ( isWsEmpty ? "" : AND + NOT + ws ) + " ) " ;
1436+ }
1437+ else if (isSideJoin ) { // ^ SIDE JOIN: ! (A & B)
1438+ //MySQL 因为 NULL 值处理问题,(A & ! B) | (B & ! A) 与 ! (A & B) 返回结果不一样,后者往往更多
1439+ newWs += " ( " + getCondition (
1440+ true ,
1441+ ( isWsEmpty ? "" : ws + AND ) + " ( " + js + " ) "
1442+ ) + " ) " ;
1443+ }
1444+ else { // & INNER JOIN: A & B; | FULL JOIN: A | B; OUTER JOIN: ! (A | B)
1445+ logic = Logic .getType (jt );
1446+ newWs += " ( "
1447+ + getCondition (
1448+ Logic .isNot (logic ),
1449+ ws
1450+ + ( isWsEmpty ? "" : (Logic .isAnd (logic ) ? AND : OR ) )
1451+ + " ( " + js + " ) "
1452+ )
1453+ + " ) " ;
14431454 }
14441455
1456+ newPvl .addAll (pvl );
1457+ newPvl .addAll (jc .getPreparedValueList ());
1458+
14451459 changed = true ;
14461460 break ;
14471461 default :
14481462 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类型 !"
1463+ "join:value 中 value 里的 " + jt + "/" + j .getPath ()
1464+ + "错误!不支持 " + jt + " 等 [ @ APP, < LEFT, > RIGHT, * CROSS "
1465+ + ", & INNER, | FULL, ! OUTER, ^ SIDE, ( ANTI, ) FOREIGN ] 之外的 JOIN 类型 !"
14521466 );
14531467 }
14541468 }
@@ -2307,6 +2321,7 @@ public String getJoinString() throws Exception {
23072321 if (j .isAppJoin ()) { // APP JOIN,只是作为一个标记,执行完主表的查询后自动执行副表的查询 User.id IN($commentIdList)
23082322 continue ;
23092323 }
2324+ String type = j .getJoinType ();
23102325
23112326 //LEFT JOIN sys.apijson_user AS User ON User.id = Moment.userId, 都是用 = ,通过relateType处理缓存
23122327 // <"INNER JOIN User ON User.id = Moment.userId", UserConfig> TODO AS 放 getSQLTable 内
@@ -2322,41 +2337,42 @@ public String getJoinString() throws Exception {
23222337 // tn = tn.toLowerCase();
23232338 // }
23242339
2325- switch (j . getJoinType ()) { //TODO $ SELF JOIN
2326- // case "@": // APP JOIN
2340+ switch (type ) {
2341+ //前面已跳过 case "@": // APP JOIN
23272342 // continue;
23282343
2344+ case "*" : // CROSS JOIN
2345+ onGetCrossJoinString (j );
23292346 case "<" : // LEFT JOIN
23302347 case ">" : // RIGHT JOIN
23312348 jc .setMain (true ).setKeyPrefix (false );
2332- sql = ( ">" .equals (j .getJoinType ()) ? " RIGHT" : " LEFT" ) + " JOIN ( " + jc .getSQL (isPrepared ()) + " ) AS "
2349+ sql = ( "<" .equals (type ) ? " LEFT" : (">" .equals (type ) ? " RIGHT" : " CROSS" ) )
2350+ + " JOIN ( " + jc .getSQL (isPrepared ()) + " ) AS "
23332351 + quote + jt + quote + " ON " + quote + jt + quote + "." + quote + j .getKey () + quote + " = "
23342352 + quote + tn + quote + "." + quote + j .getTargetKey () + quote ;
23352353 jc .setMain (false ).setKeyPrefix (true );
23362354
2337- // preparedValueList.addAll(jc.getPreparedValueList());
2338-
23392355 pvl .addAll (jc .getPreparedValueList ());
23402356 changed = true ;
23412357 break ;
23422358
2343- case "" : // FULL JOIN
2344- case "|" : // FULL JOIN 不支持 <>, [] ,避免太多符号
2345- case "&" : // INNER JOIN
2346- case "!" : // OUTTER JOIN
2347- case "^" : // SIDE JOIN
2348- case "(" : // ANTI JOIN
2349- case ")" : // FOREIGN JOIN
2350- //场景少且性能差,默认禁用 case "*": // CROSS JOIN
2351- sql = ("*" .equals (j .getJoinType ()) ? " CROSS JOIN " : " INNER JOIN " ) + jc .getTablePath ()
2359+ case "&" : // INNER JOIN: A & B
2360+ case "" : // FULL JOIN: A | B
2361+ case "|" : // FULL JOIN: A | B
2362+ case "!" : // OUTER JOIN: ! (A | B)
2363+ case "^" : // SIDE JOIN: ! (A & B)
2364+ case "(" : // ANTI JOIN: A & ! B
2365+ case ")" : // FOREIGN JOIN: B & ! A
2366+ sql = " INNER JOIN " + jc .getTablePath ()
23522367 + " ON " + quote + jt + quote + "." + quote + j .getKey () + quote + " = " + quote + tn + quote + "." + quote + j .getTargetKey () + quote ;
23532368 break ;
23542369 default :
23552370 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- ); }
2371+ "join:value 中 value 里的 " + jt + "/" + j .getPath ()
2372+ + "错误!不支持 " + jt + " 等 [ @ APP, < LEFT, > RIGHT, * CROSS"
2373+ + ", & INNER, | FULL, ! OUTER, ^ SIDE, ( ANTI, ) FOREIGN ] 之外的 JOIN 类型 !"
2374+ );
2375+ }
23602376
23612377 joinOns += " \n " + sql ;
23622378 }
@@ -2372,6 +2388,10 @@ public String getJoinString() throws Exception {
23722388 return joinOns ;
23732389 }
23742390
2391+ protected void onGetCrossJoinString (Join j ) throws UnsupportedOperationException {
2392+ throw new UnsupportedOperationException ("已禁用 * CROSS JOIN !性能很差、需求极少,如要取消禁用可在后端重写相关方法!" );
2393+ }
2394+
23752395 /**新建SQL配置
23762396 * @param table
23772397 * @param request
@@ -2752,9 +2772,9 @@ else if (joinConfig.getDatabase().equals(config.getDatabase()) == false) {
27522772 joinConfig .setMain (false ).setKeyPrefix (true );
27532773
27542774 if (j .isLeftOrRightJoin ()) {
2755- SQLConfig outterConfig = newSQLConfig (method , table , alias , j .getOutter (), null , false , callback );
2775+ SQLConfig outterConfig = newSQLConfig (method , table , alias , j .getOuter (), null , false , callback );
27562776 outterConfig .setMain (false ).setKeyPrefix (true ).setDatabase (joinConfig .getDatabase ()).setSchema (joinConfig .getSchema ()); //解决主表 JOIN 副表,引号不一致
2757- j .setOutterConfig (outterConfig );
2777+ j .setOuterConfig (outterConfig );
27582778 }
27592779 }
27602780
0 commit comments