@@ -422,7 +422,7 @@ public String getGroupString(boolean hasPrefix) {
422
422
continue ;
423
423
}
424
424
425
- cfg = j .isLeftOrRightJoin () ? j .getOutterConfig () : j .getJoinConfig ();
425
+ cfg = j .isLeftOrRightJoin () ? j .getOuterConfig () : j .getJoinConfig ();
426
426
if (StringUtil .isEmpty (cfg .getAlias (), true )) {
427
427
cfg .setAlias (cfg .getTable ());
428
428
}
@@ -484,7 +484,7 @@ public String getHavingString(boolean hasPrefix) {
484
484
continue ;
485
485
}
486
486
487
- cfg = j .isLeftOrRightJoin () ? j .getOutterConfig () : j .getJoinConfig ();
487
+ cfg = j .isLeftOrRightJoin () ? j .getOuterConfig () : j .getJoinConfig ();
488
488
if (StringUtil .isEmpty (cfg .getAlias (), true )) {
489
489
cfg .setAlias (cfg .getTable ());
490
490
}
@@ -594,7 +594,7 @@ public String getOrderString(boolean hasPrefix) {
594
594
continue ;
595
595
}
596
596
597
- cfg = j .isLeftOrRightJoin () ? j .getOutterConfig () : j .getJoinConfig ();
597
+ cfg = j .isLeftOrRightJoin () ? j .getOuterConfig () : j .getJoinConfig ();
598
598
if (StringUtil .isEmpty (cfg .getAlias (), true )) {
599
599
cfg .setAlias (cfg .getTable ());
600
600
}
@@ -766,7 +766,7 @@ public String getColumnString(boolean inSQLJoin) throws Exception {
766
766
continue ;
767
767
}
768
768
769
- ecfg = j .getOutterConfig ();
769
+ ecfg = j .getOuterConfig ();
770
770
if (ecfg != null && ecfg .getColumn () != null ) { //优先级更高
771
771
cfg = ecfg ;
772
772
}
@@ -1361,94 +1361,108 @@ else if ("!".equals(ce.getKey())) {
1361
1361
boolean changed = false ;
1362
1362
//各种 JOIN 没办法统一用 & | !连接,只能按优先级,和 @combine 一样?
1363
1363
for (Join j : joinList ) {
1364
- switch (j .getJoinType ()) {
1364
+ String jt = j .getJoinType ();
1365
+
1366
+ switch (jt ) {
1367
+ case "*" : // CROSS JOIN
1365
1368
case "@" : // APP JOIN
1366
1369
case "<" : // LEFT JOIN
1367
1370
case ">" : // RIGHT JOIN
1368
1371
break ;
1369
1372
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
1378
1380
jc = j .getJoinConfig ();
1379
1381
boolean isMain = jc .isMain ();
1380
1382
jc .setMain (false ).setPrepared (isPrepared ()).setPreparedValueList (new ArrayList <Object >());
1381
1383
js = jc .getWhereString (false );
1382
1384
jc .setMain (isMain );
1383
1385
1386
+ boolean isOuterJoin = "!" .equals (jt );
1387
+ boolean isSideJoin = "^" .equals (jt );
1388
+ boolean isAntiJoin = "(" .equals (jt );
1389
+ boolean isForeignJoin = ")" .equals (jt );
1384
1390
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
+
1386
1401
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 ;
1390
1421
}
1391
-
1392
- newWs += " ( " + getCondition (true , ws ) + " ) " ;
1393
- newPvl .addAll (pvl );
1394
- changed = true ;
1395
1422
}
1423
+
1396
1424
continue ;
1397
1425
}
1398
1426
1399
1427
if (StringUtil .isEmpty (newWs , true ) == false ) {
1400
1428
newWs += AND ;
1401
1429
}
1402
1430
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 + " ) " + " ) " ;
1421
1433
}
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
+ + " ) " ;
1443
1454
}
1444
1455
1456
+ newPvl .addAll (pvl );
1457
+ newPvl .addAll (jc .getPreparedValueList ());
1458
+
1445
1459
changed = true ;
1446
1460
break ;
1447
1461
default :
1448
1462
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 类型 !"
1452
1466
);
1453
1467
}
1454
1468
}
@@ -2307,6 +2321,7 @@ public String getJoinString() throws Exception {
2307
2321
if (j .isAppJoin ()) { // APP JOIN,只是作为一个标记,执行完主表的查询后自动执行副表的查询 User.id IN($commentIdList)
2308
2322
continue ;
2309
2323
}
2324
+ String type = j .getJoinType ();
2310
2325
2311
2326
//LEFT JOIN sys.apijson_user AS User ON User.id = Moment.userId, 都是用 = ,通过relateType处理缓存
2312
2327
// <"INNER JOIN User ON User.id = Moment.userId", UserConfig> TODO AS 放 getSQLTable 内
@@ -2322,41 +2337,42 @@ public String getJoinString() throws Exception {
2322
2337
// tn = tn.toLowerCase();
2323
2338
// }
2324
2339
2325
- switch (j . getJoinType ()) { //TODO $ SELF JOIN
2326
- // case "@": // APP JOIN
2340
+ switch (type ) {
2341
+ //前面已跳过 case "@": // APP JOIN
2327
2342
// continue;
2328
2343
2344
+ case "*" : // CROSS JOIN
2345
+ onGetCrossJoinString (j );
2329
2346
case "<" : // LEFT JOIN
2330
2347
case ">" : // RIGHT JOIN
2331
2348
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 "
2333
2351
+ quote + jt + quote + " ON " + quote + jt + quote + "." + quote + j .getKey () + quote + " = "
2334
2352
+ quote + tn + quote + "." + quote + j .getTargetKey () + quote ;
2335
2353
jc .setMain (false ).setKeyPrefix (true );
2336
2354
2337
- // preparedValueList.addAll(jc.getPreparedValueList());
2338
-
2339
2355
pvl .addAll (jc .getPreparedValueList ());
2340
2356
changed = true ;
2341
2357
break ;
2342
2358
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 ()
2352
2367
+ " ON " + quote + jt + quote + "." + quote + j .getKey () + quote + " = " + quote + tn + quote + "." + quote + j .getTargetKey () + quote ;
2353
2368
break ;
2354
2369
default :
2355
2370
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
+ }
2360
2376
2361
2377
joinOns += " \n " + sql ;
2362
2378
}
@@ -2372,6 +2388,10 @@ public String getJoinString() throws Exception {
2372
2388
return joinOns ;
2373
2389
}
2374
2390
2391
+ protected void onGetCrossJoinString (Join j ) throws UnsupportedOperationException {
2392
+ throw new UnsupportedOperationException ("已禁用 * CROSS JOIN !性能很差、需求极少,如要取消禁用可在后端重写相关方法!" );
2393
+ }
2394
+
2375
2395
/**新建SQL配置
2376
2396
* @param table
2377
2397
* @param request
@@ -2752,9 +2772,9 @@ else if (joinConfig.getDatabase().equals(config.getDatabase()) == false) {
2752
2772
joinConfig .setMain (false ).setKeyPrefix (true );
2753
2773
2754
2774
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 );
2756
2776
outterConfig .setMain (false ).setKeyPrefix (true ).setDatabase (joinConfig .getDatabase ()).setSchema (joinConfig .getSchema ()); //解决主表 JOIN 副表,引号不一致
2757
- j .setOutterConfig (outterConfig );
2777
+ j .setOuterConfig (outterConfig );
2758
2778
}
2759
2779
}
2760
2780
0 commit comments