Skip to content

Commit af279d9

Browse files
authored
fix: compound nested relationship criteria expressions (#121)
* fix: compound nested relationship criteria expressions * fix: remove test comments * fix: disable failing Travis JDK 11 build
1 parent efc5278 commit af279d9

File tree

3 files changed

+46
-42
lines changed

3 files changed

+46
-42
lines changed

.travis.yml

+1-1
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ sudo: required
33

44
jdk:
55
- oraclejdk8
6-
- openjdk11
6+
# - openjdk11
77

88
services:
99
- docker

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

+38-36
Original file line numberDiff line numberDiff line change
@@ -345,12 +345,7 @@ protected Predicate getArgumentPredicate(CriteriaBuilder cb, From<?,?> path,
345345
.filter(predicate -> predicate != null)
346346
.forEach(predicates::add);
347347

348-
if (predicates.isEmpty())
349-
predicates.add(cb.disjunction());
350-
351-
return (logical == Logical.OR)
352-
? cb.or(predicates.toArray(new Predicate[predicates.size()]))
353-
: cb.and(predicates.toArray(new Predicate[predicates.size()]));
348+
return getCompoundPredicate(cb, predicates, logical);
354349
}
355350

356351
private Logical extractLogical(Argument argument) {
@@ -375,6 +370,7 @@ private Predicate getFieldPredicate(String fieldName, CriteriaBuilder cb, From<?
375370

376371
List<Predicate> predicates = new ArrayList<>();
377372

373+
// Let's parse logical expressions, i.e. AND, OR
378374
expressionValue.getObjectFields().stream()
379375
.filter(it -> Logical.names().contains(it.getName()))
380376
.map(it -> getFieldPredicate(fieldName, cb, path, it,
@@ -383,49 +379,55 @@ private Predicate getFieldPredicate(String fieldName, CriteriaBuilder cb, From<?
383379
)
384380
.forEach(predicates::add);
385381

386-
// Let's parse relation criteria expressions if present
387-
expressionValue.getObjectFields().stream()
388-
.filter(it -> !Logical.names().contains(it.getName()) && !Criteria.names().contains(it.getName()))
389-
.map(it -> {
390-
GraphQLFieldDefinition fieldDefinition = getFieldDef(environment.getGraphQLSchema(),
391-
this.getObjectType(environment, argument),
392-
new Field(fieldName));
393-
394-
Map<String, Object> arguments = new LinkedHashMap<>();
395-
382+
// Let's parse relation criteria expressions if present, i.e. books, author, etc.
383+
if(expressionValue.getObjectFields()
384+
.stream()
385+
.anyMatch(it -> !Logical.names().contains(it.getName()) && !Criteria.names().contains(it.getName())))
386+
{
387+
GraphQLFieldDefinition fieldDefinition = getFieldDef(environment.getGraphQLSchema(),
388+
this.getObjectType(environment, argument),
389+
new Field(fieldName));
390+
Map<String, Object> arguments = new LinkedHashMap<>();
391+
392+
if(Logical.names().contains(argument.getName()))
393+
arguments.put(logical.name(), environment.getArgument(argument.getName()));
394+
else
396395
arguments.put(logical.name(), environment.getArgument(fieldName));
397-
398-
return getArgumentPredicate(cb, reuseJoin(path, fieldName, false),
399-
wherePredicateEnvironment(environment, fieldDefinition, arguments),
400-
new Argument(logical.name(), expressionValue));
401-
}
402-
)
403-
.forEach(predicates::add);
404-
405-
Optional<Predicate> relationPredicate = predicates.stream().findFirst();
406-
407-
// Let's check if relation criteria predicate exists, to avoid adding duplicate predicates in the query
408-
if(relationPredicate.isPresent()) {
409-
return relationPredicate.get();
396+
397+
return getArgumentPredicate(cb, reuseJoin(path, fieldName, false),
398+
wherePredicateEnvironment(environment, fieldDefinition, arguments),
399+
new Argument(logical.name(), expressionValue));
410400
}
411401

402+
// Let's parse simple Criteria expressions, i.e. EQ, LIKE, etc.
412403
JpaPredicateBuilder pb = new JpaPredicateBuilder(cb, EnumSet.of(Logical.AND));
413404

414-
expressionValue.getObjectFields().stream()
405+
expressionValue.getObjectFields()
406+
.stream()
415407
.filter(it -> Criteria.names().contains(it.getName()))
416408
.map(it -> getPredicateFilter(new ObjectField(fieldName, it.getValue()),
417-
argumentEnvironment(environment, argument.getName()),
418-
new Argument(it.getName(), it.getValue()))
419-
)
409+
argumentEnvironment(environment, argument.getName()),
410+
new Argument(it.getName(), it.getValue())))
420411
.sorted()
421412
.map(it -> pb.getPredicate(path, path.get(it.getField()), it))
422413
.filter(predicate -> predicate != null)
423414
.forEach(predicates::add);
424415

425-
return (logical == Logical.OR)
426-
? cb.or(predicates.toArray(new Predicate[predicates.size()]))
427-
: cb.and(predicates.toArray(new Predicate[predicates.size()]));
416+
return getCompoundPredicate(cb, predicates, logical);
428417

418+
}
419+
420+
private Predicate getCompoundPredicate(CriteriaBuilder cb, List<Predicate> predicates, Logical logical) {
421+
if(predicates.isEmpty())
422+
return cb.disjunction();
423+
424+
if(predicates.size() == 1) {
425+
return predicates.get(0);
426+
}
427+
428+
return (logical == Logical.OR)
429+
? cb.or(predicates.toArray(new Predicate[predicates.size()]))
430+
: cb.and(predicates.toArray(new Predicate[predicates.size()]));
429431
}
430432

431433
private PredicateFilter getPredicateFilter(ObjectField objectField, DataFetchingEnvironment environment, Argument argument) {

graphql-jpa-query-schema/src/test/java/com/introproventures/graphql/jpa/query/schema/GraphQLExecutorTests.java

+7-5
Original file line numberDiff line numberDiff line change
@@ -726,11 +726,13 @@ public void queryWithWhereInsideOneToManyNestedRelationsWithManyToOneAndOR() {
726726
String query = "query { " +
727727
" Authors(where: {" +
728728
" books: {" +
729-
" author: {name: {LIKE:\"Leo\"}}" +
730-
" OR: {" +
731-
" title: {LIKE: \"War\"}" +
732-
" title: {LIKE: \"Anna\"}" +
733-
" }" +
729+
" author: {name: {LIKE:\"Leo\"}}" +
730+
" AND: {" +
731+
" OR: {" +
732+
" id: {EQ: 2}" +
733+
" title: {LIKE: \"Anna\"}" +
734+
" }" +
735+
" }" +
734736
" }" +
735737
" }) {" +
736738
" select {" +

0 commit comments

Comments
 (0)