@@ -142,6 +142,7 @@ public Select select(Selection selection) {
142
142
Selection postProcess (Selection selection ) {
143
143
return distinct ? new DistinctSelection (selection ) : selection ;
144
144
}
145
+
145
146
};
146
147
}
147
148
@@ -299,6 +300,7 @@ public static WhereStep where(Origin source, PropertyPath path) {
299
300
public static WhereStep where (Expression rhs ) {
300
301
301
302
return new WhereStep () {
303
+
302
304
@ Override
303
305
public Predicate between (Expression lower , Expression upper ) {
304
306
return new BetweenPredicate (rhs , lower , upper );
@@ -393,6 +395,7 @@ public Predicate eq(Expression value) {
393
395
public Predicate neq (Expression value ) {
394
396
return new OperatorPredicate (rhs , "!=" , value );
395
397
}
398
+
396
399
};
397
400
}
398
401
@@ -506,7 +509,9 @@ default Select select(JpqlQueryBuilder.PathExpression path) {
506
509
}
507
510
508
511
public interface Selection {
512
+
509
513
String render (RenderContext context );
514
+
510
515
}
511
516
512
517
/**
@@ -525,6 +530,7 @@ public String render(RenderContext context) {
525
530
public String toString () {
526
531
return render (RenderContext .EMPTY );
527
532
}
533
+
528
534
}
529
535
530
536
static PathAndOrigin path (Origin origin , String path ) {
@@ -538,29 +544,28 @@ static PathAndOrigin path(Origin origin, String path) {
538
544
throw new RuntimeException (e );
539
545
}
540
546
}
547
+
541
548
if (origin instanceof Join join ) {
542
549
543
550
Origin parent = join .source ;
544
551
List <String > segments = new ArrayList <>();
545
552
segments .add (join .path );
546
553
while (!(parent instanceof Entity )) {
547
- if (parent instanceof Join pj ) {
548
- parent = pj .source ;
549
- segments .add (pj .path );
554
+ if (parent instanceof Join parentJoin ) {
555
+ parent = parentJoin .source ;
556
+ segments .add (parentJoin .path );
550
557
} else {
551
558
parent = null ;
552
559
}
553
560
}
554
561
555
- if (parent instanceof Entity ) {
556
- Collections .reverse (segments );
557
- segments .add (path );
558
- PathAndOrigin path1 = path (parent , StringUtils .collectionToDelimitedString (segments , "." ));
559
- return new PathAndOrigin (path1 .path ().getLeafProperty (), origin , false );
560
- }
562
+ Collections .reverse (segments );
563
+ segments .add (path );
564
+ PathAndOrigin joinedPath = path (parent , StringUtils .collectionToDelimitedString (segments , "." ));
565
+ return new PathAndOrigin (joinedPath .path ().getLeafProperty (), origin , false );
561
566
}
562
- throw new IllegalStateException (" oh no " );
563
567
568
+ throw new IllegalStateException ("🙈 Unsupported origin type: " + origin );
564
569
}
565
570
566
571
/**
@@ -579,6 +584,7 @@ public String render(RenderContext context) {
579
584
public String toString () {
580
585
return render (RenderContext .EMPTY );
581
586
}
587
+
582
588
}
583
589
584
590
/**
@@ -598,6 +604,7 @@ public String render(RenderContext context) {
598
604
public String toString () {
599
605
return render (RenderContext .EMPTY );
600
606
}
607
+
601
608
}
602
609
603
610
/**
@@ -618,6 +625,7 @@ public String render(RenderContext context) {
618
625
public String toString () {
619
626
return render (RenderContext .EMPTY );
620
627
}
628
+
621
629
}
622
630
623
631
/**
@@ -652,21 +660,29 @@ public String render(RenderContext context) {
652
660
public String toString () {
653
661
return render (RenderContext .EMPTY );
654
662
}
663
+
655
664
}
656
665
657
666
/**
658
- * {@code WHERE} predicate .
667
+ * Interface specifying a predicate or expression that can be rendered to {@code String} .
659
668
*/
660
- public interface Predicate {
669
+ public interface Renderable {
661
670
662
671
/**
663
- * Render the predicate given {@link RenderContext}.
672
+ * Render the predicate or expression given {@link RenderContext}.
664
673
*
665
674
* @param context
666
675
* @return
667
676
*/
668
677
String render (RenderContext context );
669
678
679
+ }
680
+
681
+ /**
682
+ * {@code WHERE} predicate.
683
+ */
684
+ public interface Predicate extends Renderable {
685
+
670
686
/**
671
687
* {@code OR}-concatenate this predicate with {@code other}.
672
688
*
@@ -701,21 +717,21 @@ default Predicate and(Predicate other) { // don't like the structuring of this a
701
717
default Predicate nest () {
702
718
return new NestedPredicate (this );
703
719
}
720
+
704
721
}
705
722
706
723
/**
707
724
* Interface specifying an expression that can be rendered to {@code String}.
708
725
*/
709
- public interface Expression {
726
+ public interface Expression extends Renderable {
710
727
711
728
/**
712
- * Render the expression given {@link RenderContext}.
729
+ * Create an {@link AliasedExpression} with the given {@code alias}. If the expression is already aliased, the
730
+ * previous alias is discarded and replaced with the new one.
713
731
*
714
- * @param context
732
+ * @param alias
715
733
* @return
716
734
*/
717
- String render (RenderContext context );
718
-
719
735
default AliasedExpression as (String alias ) {
720
736
721
737
if (this instanceof DefaultAliasedExpression de ) {
@@ -724,6 +740,7 @@ default AliasedExpression as(String alias) {
724
740
725
741
return new DefaultAliasedExpression (this , alias );
726
742
}
743
+
727
744
}
728
745
729
746
/**
@@ -756,6 +773,7 @@ public String getAlias() {
756
773
public String toString () {
757
774
return render (RenderContext .EMPTY );
758
775
}
776
+
759
777
}
760
778
761
779
/**
@@ -768,6 +786,7 @@ public interface PathExpression extends Expression {
768
786
* @return the associated {@link PropertyPath}.
769
787
*/
770
788
PropertyPath getPropertyPath ();
789
+
771
790
}
772
791
773
792
/**
@@ -865,6 +884,7 @@ String render() {
865
884
866
885
return result .toString ();
867
886
}
887
+
868
888
}
869
889
870
890
/**
@@ -889,6 +909,7 @@ public AbstractJpqlQuery where(Predicate predicate) {
889
909
public String toString () {
890
910
return render ();
891
911
}
912
+
892
913
}
893
914
894
915
record OrderExpression (Expression sortExpression , @ org .springframework .lang .Nullable Sort .Direction direction ,
@@ -915,6 +936,7 @@ public String render(RenderContext context) {
915
936
916
937
return builder .toString ();
917
938
}
939
+
918
940
}
919
941
920
942
/**
@@ -966,6 +988,7 @@ public String prefixWithAlias(Origin source, String fragment) {
966
988
public boolean isConstructorContext () {
967
989
return false ;
968
990
}
991
+
969
992
}
970
993
971
994
static class ConstructorContext extends RenderContext {
@@ -978,6 +1001,7 @@ static class ConstructorContext extends RenderContext {
978
1001
public boolean isConstructorContext () {
979
1002
return true ;
980
1003
}
1004
+
981
1005
}
982
1006
983
1007
/**
@@ -992,6 +1016,7 @@ public interface Origin {
992
1016
* @return the simple name of the origin (e.g. {@link Class#getSimpleName()})
993
1017
*/
994
1018
String getName ();
1019
+
995
1020
}
996
1021
997
1022
/**
@@ -1001,6 +1026,7 @@ public interface Origin {
1001
1026
public interface Bindable {
1002
1027
1003
1028
boolean isRoot ();
1029
+
1004
1030
}
1005
1031
1006
1032
/**
@@ -1283,6 +1309,7 @@ default Predicate like(String value, String escape) {
1283
1309
* @return
1284
1310
*/
1285
1311
Predicate neq (Expression value );
1312
+
1286
1313
}
1287
1314
1288
1315
record LiteralExpression (String expression ) implements Expression {
@@ -1296,6 +1323,7 @@ public String render(RenderContext context) {
1296
1323
public String toString () {
1297
1324
return render (RenderContext .EMPTY );
1298
1325
}
1326
+
1299
1327
}
1300
1328
1301
1329
record StringLiteralExpression (String literal ) implements Expression {
@@ -1313,6 +1341,7 @@ public String raw() {
1313
1341
public String toString () {
1314
1342
return render (RenderContext .EMPTY );
1315
1343
}
1344
+
1316
1345
}
1317
1346
1318
1347
record ParameterExpression (ParameterPlaceholder parameter ) implements Expression {
@@ -1326,6 +1355,7 @@ public String render(RenderContext context) {
1326
1355
public String toString () {
1327
1356
return render (RenderContext .EMPTY );
1328
1357
}
1358
+
1329
1359
}
1330
1360
1331
1361
record FunctionExpression (String function , List <Expression > arguments ) implements Expression {
@@ -1351,6 +1381,7 @@ public String render(RenderContext context) {
1351
1381
public String toString () {
1352
1382
return render (RenderContext .EMPTY );
1353
1383
}
1384
+
1354
1385
}
1355
1386
1356
1387
record OperatorPredicate (Expression path , String operator , Expression predicate ) implements Predicate {
@@ -1364,6 +1395,7 @@ public String render(RenderContext context) {
1364
1395
public String toString () {
1365
1396
return render (RenderContext .EMPTY );
1366
1397
}
1398
+
1367
1399
}
1368
1400
1369
1401
record MemberOfPredicate (Expression path , String operator , Expression predicate ) implements Predicate {
@@ -1377,6 +1409,7 @@ public String render(RenderContext context) {
1377
1409
public String toString () {
1378
1410
return render (RenderContext .EMPTY );
1379
1411
}
1412
+
1380
1413
}
1381
1414
1382
1415
record LhsPredicate (Expression path , String predicate ) implements Predicate {
@@ -1390,6 +1423,7 @@ public String render(RenderContext context) {
1390
1423
public String toString () {
1391
1424
return render (RenderContext .EMPTY );
1392
1425
}
1426
+
1393
1427
}
1394
1428
1395
1429
record BetweenPredicate (Expression path , Expression lower , Expression upper ) implements Predicate {
@@ -1403,6 +1437,7 @@ public String render(RenderContext context) {
1403
1437
public String toString () {
1404
1438
return render (RenderContext .EMPTY );
1405
1439
}
1440
+
1406
1441
}
1407
1442
1408
1443
record LikePredicate (Expression left , String operator , Expression right , String escape ) implements Predicate {
@@ -1416,27 +1451,29 @@ public String render(RenderContext context) {
1416
1451
public String toString () {
1417
1452
return render (RenderContext .EMPTY );
1418
1453
}
1454
+
1419
1455
}
1420
1456
1421
1457
record InPredicate (Expression path , String operator , Expression predicate ) implements Predicate {
1422
1458
1423
1459
@ Override
1424
1460
public String render (RenderContext context ) {
1425
1461
1426
- String predicateStr = predicate .render (context );
1427
-
1428
- // Avoid double parentheses if predicate string already starts and ends with parentheses
1429
- if (predicateStr .startsWith ("(" ) && predicateStr .endsWith (")" )) {
1430
- return "%s %s %s" .formatted (path .render (context ), operator , predicateStr );
1431
- }
1432
-
1433
- return "%s %s (%s)" .formatted (path .render (context ), operator , predicateStr );
1462
+ Expression predicate = this .predicate ;
1463
+ String rendered = predicate .render (context );
1464
+
1465
+ return (hasParenthesis (rendered ) ? "%s %s %s" : "%s %s (%s)" ).formatted (path .render (context ), operator , rendered );
1434
1466
}
1435
1467
1436
1468
@ Override
1437
1469
public String toString () {
1438
1470
return render (RenderContext .EMPTY );
1439
1471
}
1472
+
1473
+ private static boolean hasParenthesis (String str ) {
1474
+ return str .startsWith ("(" ) && str .endsWith (")" );
1475
+ }
1476
+
1440
1477
}
1441
1478
1442
1479
record AndPredicate (Predicate left , Predicate right ) implements Predicate {
@@ -1450,6 +1487,7 @@ public String render(RenderContext context) {
1450
1487
public String toString () {
1451
1488
return render (RenderContext .EMPTY );
1452
1489
}
1490
+
1453
1491
}
1454
1492
1455
1493
record OrPredicate (Predicate left , Predicate right ) implements Predicate {
@@ -1463,6 +1501,7 @@ public String render(RenderContext context) {
1463
1501
public String toString () {
1464
1502
return render (RenderContext .EMPTY );
1465
1503
}
1504
+
1466
1505
}
1467
1506
1468
1507
record NestedPredicate (Predicate delegate ) implements Predicate {
@@ -1476,6 +1515,7 @@ public String render(RenderContext context) {
1476
1515
public String toString () {
1477
1516
return render (RenderContext .EMPTY );
1478
1517
}
1518
+
1479
1519
}
1480
1520
1481
1521
/**
@@ -1507,6 +1547,7 @@ public String render(RenderContext context) {
1507
1547
public String getAlias () {
1508
1548
return path ().getSegment ();
1509
1549
}
1550
+
1510
1551
}
1511
1552
1512
1553
/**
@@ -1541,5 +1582,7 @@ public static ParameterPlaceholder named(String name) {
1541
1582
Assert .hasText (name , "Placeholder name must not be empty" );
1542
1583
return new ParameterPlaceholder (":%s" .formatted (name ));
1543
1584
}
1585
+
1544
1586
}
1587
+
1545
1588
}
0 commit comments