Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -1603,12 +1603,26 @@ private Predicate getCompoundPredicate(CriteriaBuilder cb, List<Predicate> predi
if (predicates.isEmpty()) return cb.disjunction();

if (predicates.size() == 1) {
if (logical == Logical.NOT) {
return cb.not(predicates.get(0));
}
return predicates.get(0);
}

return (logical == Logical.OR)
? cb.or(predicates.toArray(new Predicate[0]))
: cb.and(predicates.toArray(new Predicate[0]));
switch (logical) {
case OR:
return cb.or(predicates.toArray(new Predicate[0]));
case AND:
case EXISTS:
case NOT_EXISTS:
return cb.and(predicates.toArray(new Predicate[0]));
case NOT:
throw new RuntimeException("NOT expression cannot be applied to multiple predicates at once");
default:
throw new RuntimeException(
"Unable to resolve applicable compound predicate for logical operand " + logical
);
}
}

private PredicateFilter getPredicateFilter(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -722,6 +722,14 @@ private GraphQLArgument computeWhereArgument(ManagedType<?> managedType) {
.type(new GraphQLList(new GraphQLTypeReference(type)))
.build()
)
.field(
GraphQLInputObjectField
.newInputObjectField()
.name(Logical.NOT.name())
.description("Logical operation for expression")
.type(new GraphQLTypeReference(type))
.build()
)
.field(
GraphQLInputObjectField
.newInputObjectField()
Expand Down Expand Up @@ -815,6 +823,14 @@ private GraphQLInputObjectType computeSubqueryInputType(ManagedType<?> managedTy
.type(new GraphQLList(new GraphQLTypeReference(type)))
.build()
)
.field(
GraphQLInputObjectField
.newInputObjectField()
.name(Logical.NOT.name())
.description("Logical operation for expression")
.type(new GraphQLTypeReference(type))
.build()
)
.field(
GraphQLInputObjectField
.newInputObjectField()
Expand Down Expand Up @@ -896,6 +912,14 @@ private GraphQLInputObjectType computeWhereInputType(ManagedType<?> managedType)
.type(new GraphQLList(new GraphQLTypeReference(type)))
.build()
)
.field(
GraphQLInputObjectField
.newInputObjectField()
.name(Logical.NOT.name())
.description("Logical operation for expression")
.type(new GraphQLTypeReference(type))
.build()
)
.field(
GraphQLInputObjectField
.newInputObjectField()
Expand Down Expand Up @@ -1008,6 +1032,14 @@ private GraphQLInputType getWhereAttributeType(Attribute<?, ?> attribute) {
.type(new GraphQLList(new GraphQLTypeReference(type)))
.build()
)
.field(
GraphQLInputObjectField
.newInputObjectField()
.name(Logical.NOT.name())
.description("Logical NOT criteria expression")
.type(new GraphQLTypeReference(type))
.build()
)
.field(
GraphQLInputObjectField
.newInputObjectField()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
enum Logical {
AND,
OR,
NOT,
EXISTS,
NOT_EXISTS;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -393,6 +393,24 @@ public void queryForEnumNe() {
assertThat(result.toString()).isEqualTo(expected);
}

@Test
public void queryForEnumNotEq() {
//given
String query = "{ Books(where: {genre: {NOT: {EQ:PLAY}}}) { select { id title, genre } }}";

String expected =
"{Books={select=[" +
"{id=2, title=War and Peace, genre=NOVEL}, " +
"{id=3, title=Anna Karenina, genre=NOVEL}" +
"]}}";

//when
Object result = executor.execute(query).getData();

// then
assertThat(result.toString()).isEqualTo(expected);
}

@Test
public void queryForEnumNin() {
//given
Expand All @@ -411,6 +429,24 @@ public void queryForEnumNin() {
assertThat(result.toString()).isEqualTo(expected);
}

@Test
public void queryForEnumNotIn() {
//given
String query = "{ Books(where: {genre: {NOT: {IN: PLAY}}}) { select { id title, genre } }}";

String expected =
"{Books={select=[" +
"{id=2, title=War and Peace, genre=NOVEL}, " +
"{id=3, title=Anna Karenina, genre=NOVEL}" +
"]}}";

//when
Object result = executor.execute(query).getData();

// then
assertThat(result.toString()).isEqualTo(expected);
}

@Test
public void queryForParentWithEnum() {
//given
Expand Down Expand Up @@ -467,6 +503,165 @@ public void queryAuthorBooksWithExplictOptional() {
assertThat(result.toString()).isEqualTo(expected);
}

@Test
public void queryAuthorBooksWithExplictOptionalNotLike() {
//given
String query =
"query { " +
"Authors(" +
" where: {" +
" books: {" +
" title: {NOT: {LIKE: \"Th\"}}" +
" }" +
" }" +
" ) {" +
" select {" +
" id" +
" name" +
" books(optional: true) {" +
" id" +
" title(orderBy: ASC)" +
" genre" +
" }" +
" }" +
" }" +
"}";

String expected =
"{Authors={select=[" +
"{id=1, name=Leo Tolstoy, books=[" +
"{id=3, title=Anna Karenina, genre=NOVEL}, " +
"{id=2, title=War and Peace, genre=NOVEL}]}" +
"]}}";

//when
Object result = executor.execute(query).getData();

// then
assertThat(result.toString()).isEqualTo(expected);
}

@Test
public void queryAuthorBooksWithExplictOptionalNotLikeConjunction() {
//given
String query =
"query { " +
"Authors(" +
" where: {" +
" books: {" +
" AND: [{title: {NOT: {LIKE: \"War\"}}} {title: {NOT: {LIKE: \"Anna\"}}}]" +
" }" +
" }" +
" ) {" +
" select {" +
" id" +
" name" +
" books(optional: true) {" +
" id" +
" title(orderBy: ASC)" +
" genre" +
" }" +
" }" +
" }" +
"}";

String expected =
"{Authors={select=[" +
"{id=4, name=Anton Chekhov, books=[" +
"{id=5, title=The Cherry Orchard, genre=PLAY}, " +
"{id=6, title=The Seagull, genre=PLAY}, " +
"{id=7, title=Three Sisters, genre=PLAY}" +
"]}" +
"]}}";

//when
Object result = executor.execute(query).getData();

// then
assertThat(result.toString()).isEqualTo(expected);
}

@Test
public void queryAuthorBooksWithNotOutsideOfLikeDisjunction() {
//should be the same result as queryAuthorBooksWithExplictOptionalNotLikeConjunction above
//due to logical inversion AND(Not Like A, Not Like B) => NOT(OR(Like a, Like b))
//given
String query =
"query { " +
"Authors(" +
" where: {" +
" books: {" +
" NOT: {OR: [{title: {LIKE: \"War\"}} {title: {LIKE: \"Anna\"}}]}" +
" }" +
" }" +
" ) {" +
" select {" +
" id" +
" name" +
" books(optional: true) {" +
" id" +
" title(orderBy: ASC)" +
" genre" +
" }" +
" }" +
" }" +
"}";

String expected =
"{Authors={select=[" +
"{id=4, name=Anton Chekhov, books=[" +
"{id=5, title=The Cherry Orchard, genre=PLAY}, " +
"{id=6, title=The Seagull, genre=PLAY}, " +
"{id=7, title=Three Sisters, genre=PLAY}" +
"]}" +
"]}}";

//when
Object result = executor.execute(query).getData();

// then
assertThat(result.toString()).isEqualTo(expected);
}

@Test
public void queryAuthorBooksWithNotOutsideOfConjunction() {
//given
String query =
"query { " +
"Authors(" +
" where: {" +
" books: {" +
" NOT: {AND: [{id: {GE: 4}} {genre: {EQ: PLAY}}]}" +
" }" +
" }" +
" ) {" +
" select {" +
" id" +
" name" +
" books(optional: true) {" +
" id" +
" title(orderBy: ASC)" +
" genre" +
" }" +
" }" +
" }" +
"}";

String expected =
"{Authors={select=[" +
"{id=1, name=Leo Tolstoy, books=[" +
"{id=3, title=Anna Karenina, genre=NOVEL}, " +
"{id=2, title=War and Peace, genre=NOVEL}" +
"]}" +
"]}}";

//when
Object result = executor.execute(query).getData();

// then
assertThat(result.toString()).isEqualTo(expected);
}

@Test
public void queryAuthorBooksWithExplictOptionalEXISTS() {
//given
Expand Down Expand Up @@ -506,6 +701,51 @@ public void queryAuthorBooksWithExplictOptionalEXISTS() {
assertThat(result.toString()).isEqualTo(expected);
}

@Test
public void queryAuthorBooksWithExplictOptionalNotEXISTS() {
//given
String query =
"query { " +
"Authors(" +
" where: {" +
" NOT: {" +
" EXISTS: {" +
" books: {" +
" title: {LIKE: \"War\"}" +
" }" +
" }" +
" }" +
" }" +
" ) {" +
" select {" +
" id" +
" name" +
" books(optional: true) {" +
" id" +
" title(orderBy: ASC)" +
" genre" +
" }" +
" }" +
" }" +
"}";

String expected =
"{Authors={select=[" +
"{id=4, name=Anton Chekhov, books=[" +
"{id=5, title=The Cherry Orchard, genre=PLAY}," +
" {id=6, title=The Seagull, genre=PLAY}," +
" {id=7, title=Three Sisters, genre=PLAY}" +
"]}, " +
"{id=8, name=Igor Dianov, books=[]}" +
"]}}";

//when
Object result = executor.execute(query).getData();

// then
assertThat(result.toString()).isEqualTo(expected);
}

@Test
public void queryAuthorBooksWithCollectionOrderBy() {
//given
Expand Down Expand Up @@ -2055,6 +2295,22 @@ public void ignoreOrder() {
.contains(ErrorType.ValidationError, Arrays.asList("Books", "select", "description"));
}

@Test
public void logicalNotOnlySupportsSingleOperand() {
//given
String query = "{ Books(where: {NOT: [{id: {EQ: 1}} {id: {EQ: 2}}]}){ select { id description } }}";

List<GraphQLError> result = executor.execute(query).getErrors();

//then
assertThat(result).hasSize(1);
assertThat(result.get(0))
.isExactlyInstanceOf(ValidationError.class)
.extracting(ValidationError.class::cast)
.extracting("errorType", "queryPath")
.contains(ErrorType.ValidationError, Arrays.asList("Books"));
}

@Test
public void titleOrder() {
//given
Expand Down
Loading