Skip to content

Commit 8bf6c52

Browse files
author
Christopher Wall
committed
Add logical NOT support
1 parent 405ea8b commit 8bf6c52

File tree

4 files changed

+156
-3
lines changed

4 files changed

+156
-3
lines changed

schema/src/main/java/com/introproventures/graphql/jpa/query/schema/impl/GraphQLJpaQueryFactory.java

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1605,12 +1605,24 @@ private Predicate getCompoundPredicate(CriteriaBuilder cb, List<Predicate> predi
16051605
if (predicates.isEmpty()) return cb.disjunction();
16061606

16071607
if (predicates.size() == 1) {
1608+
if(logical == Logical.NOT){
1609+
return cb.not(predicates.get(0));
1610+
}
16081611
return predicates.get(0);
16091612
}
16101613

1611-
return (logical == Logical.OR)
1612-
? cb.or(predicates.toArray(new Predicate[0]))
1613-
: cb.and(predicates.toArray(new Predicate[0]));
1614+
switch (logical){
1615+
case OR:
1616+
return cb.or(predicates.toArray(new Predicate[0]));
1617+
case AND:
1618+
case EXISTS:
1619+
case NOT_EXISTS:
1620+
return cb.and(predicates.toArray(new Predicate[0]));
1621+
case NOT:
1622+
throw new RuntimeException("NOT expression cannot be applied to multiple predicates at once");
1623+
default:
1624+
throw new RuntimeException("Unable to resolve applicable compound predicate for logical operand "+logical);
1625+
}
16141626
}
16151627

16161628
private PredicateFilter getPredicateFilter(

schema/src/main/java/com/introproventures/graphql/jpa/query/schema/impl/GraphQLJpaSchemaBuilder.java

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -722,6 +722,14 @@ private GraphQLArgument computeWhereArgument(ManagedType<?> managedType) {
722722
.type(new GraphQLList(new GraphQLTypeReference(type)))
723723
.build()
724724
)
725+
.field(
726+
GraphQLInputObjectField
727+
.newInputObjectField()
728+
.name(Logical.NOT.name())
729+
.description("Logical operation for expression")
730+
.type(new GraphQLTypeReference(type))
731+
.build()
732+
)
725733
.field(
726734
GraphQLInputObjectField
727735
.newInputObjectField()
@@ -815,6 +823,14 @@ private GraphQLInputObjectType computeSubqueryInputType(ManagedType<?> managedTy
815823
.type(new GraphQLList(new GraphQLTypeReference(type)))
816824
.build()
817825
)
826+
.field(
827+
GraphQLInputObjectField
828+
.newInputObjectField()
829+
.name(Logical.NOT.name())
830+
.description("Logical operation for expression")
831+
.type(new GraphQLTypeReference(type))
832+
.build()
833+
)
818834
.field(
819835
GraphQLInputObjectField
820836
.newInputObjectField()
@@ -896,6 +912,14 @@ private GraphQLInputObjectType computeWhereInputType(ManagedType<?> managedType)
896912
.type(new GraphQLList(new GraphQLTypeReference(type)))
897913
.build()
898914
)
915+
.field(
916+
GraphQLInputObjectField
917+
.newInputObjectField()
918+
.name(Logical.NOT.name())
919+
.description("Logical operation for expression")
920+
.type(new GraphQLTypeReference(type))
921+
.build()
922+
)
899923
.field(
900924
GraphQLInputObjectField
901925
.newInputObjectField()
@@ -1008,6 +1032,14 @@ private GraphQLInputType getWhereAttributeType(Attribute<?, ?> attribute) {
10081032
.type(new GraphQLList(new GraphQLTypeReference(type)))
10091033
.build()
10101034
)
1035+
.field(
1036+
GraphQLInputObjectField
1037+
.newInputObjectField()
1038+
.name(Logical.NOT.name())
1039+
.description("Logical NOT criteria expression")
1040+
.type(new GraphQLTypeReference(type))
1041+
.build()
1042+
)
10111043
.field(
10121044
GraphQLInputObjectField
10131045
.newInputObjectField()

schema/src/main/java/com/introproventures/graphql/jpa/query/schema/impl/Logical.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
enum Logical {
2424
AND,
2525
OR,
26+
NOT,
2627
EXISTS,
2728
NOT_EXISTS;
2829

schema/src/test/java/com/introproventures/graphql/jpa/query/support/GraphQLExecutorTestsSupport.java

Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -393,6 +393,23 @@ public void queryForEnumNe() {
393393
assertThat(result.toString()).isEqualTo(expected);
394394
}
395395

396+
@Test
397+
public void queryForEnumNotEq() {
398+
//given
399+
String query = "{ Books(where: {genre: {NOT: {EQ:PLAY}}}) { select { id title, genre } }}";
400+
401+
String expected = "{Books={select=["
402+
+ "{id=2, title=War and Peace, genre=NOVEL}, "
403+
+ "{id=3, title=Anna Karenina, genre=NOVEL}"
404+
+ "]}}";
405+
406+
//when
407+
Object result = executor.execute(query).getData();
408+
409+
// then
410+
assertThat(result.toString()).isEqualTo(expected);
411+
}
412+
396413
@Test
397414
public void queryForEnumNin() {
398415
//given
@@ -411,6 +428,23 @@ public void queryForEnumNin() {
411428
assertThat(result.toString()).isEqualTo(expected);
412429
}
413430

431+
@Test
432+
public void queryForEnumNotIn() {
433+
//given
434+
String query = "{ Books(where: {genre: {NOT: {IN: PLAY}}}) { select { id title, genre } }}";
435+
436+
String expected = "{Books={select=["
437+
+ "{id=2, title=War and Peace, genre=NOVEL}, "
438+
+ "{id=3, title=Anna Karenina, genre=NOVEL}"
439+
+ "]}}";
440+
441+
//when
442+
Object result = executor.execute(query).getData();
443+
444+
// then
445+
assertThat(result.toString()).isEqualTo(expected);
446+
}
447+
414448
@Test
415449
public void queryForParentWithEnum() {
416450
//given
@@ -467,6 +501,80 @@ public void queryAuthorBooksWithExplictOptional() {
467501
assertThat(result.toString()).isEqualTo(expected);
468502
}
469503

504+
@Test
505+
public void queryAuthorBooksWithExplictOptionalNotLike() {
506+
//given
507+
String query = "query { "
508+
+ "Authors(" +
509+
" where: {" +
510+
" books: {" +
511+
" title: {NOT: {LIKE: \"Th\"}}" +
512+
" }" +
513+
" }" +
514+
" ) {" +
515+
" select {" +
516+
" id" +
517+
" name" +
518+
" books(optional: true) {" +
519+
" id" +
520+
" title(orderBy: ASC)" +
521+
" genre" +
522+
" }" +
523+
" }" +
524+
" }"
525+
+ "}";
526+
527+
String expected = "{Authors={select=["
528+
+ "{id=1, name=Leo Tolstoy, books=["
529+
+ "{id=3, title=Anna Karenina, genre=NOVEL}, "
530+
+ "{id=2, title=War and Peace, genre=NOVEL}]}"
531+
+ "]}}";
532+
533+
//when
534+
Object result = executor.execute(query).getData();
535+
536+
// then
537+
assertThat(result.toString()).isEqualTo(expected);
538+
}
539+
540+
@Test
541+
public void queryAuthorBooksWithExplictOptionalNotLikeConjunction() {
542+
//given
543+
String query = "query { "
544+
+ "Authors(" +
545+
" where: {" +
546+
" books: {" +
547+
" AND: [{title: {NOT: {LIKE: \"War\"}}} {title: {NOT: {LIKE: \"Anna\"}}}]" +
548+
" }" +
549+
" }" +
550+
" ) {" +
551+
" select {" +
552+
" id" +
553+
" name" +
554+
" books(optional: true) {" +
555+
" id" +
556+
" title(orderBy: ASC)" +
557+
" genre" +
558+
" }" +
559+
" }" +
560+
" }"
561+
+ "}";
562+
563+
String expected = "{Authors={select=["
564+
+ "{id=4, name=Anton Chekhov, books=["
565+
+ "{id=5, title=The Cherry Orchard, genre=PLAY}, "
566+
+ "{id=6, title=The Seagull, genre=PLAY}, "
567+
+ "{id=7, title=Three Sisters, genre=PLAY}"
568+
+ "]}"
569+
+ "]}}";
570+
571+
//when
572+
Object result = executor.execute(query).getData();
573+
574+
// then
575+
assertThat(result.toString()).isEqualTo(expected);
576+
}
577+
470578
@Test
471579
public void queryAuthorBooksWithExplictOptionalEXISTS() {
472580
//given

0 commit comments

Comments
 (0)