diff --git a/core/sparqlbuilder/src/main/java/org/eclipse/rdf4j/sparqlbuilder/graphpattern/GroupGraphPattern.java b/core/sparqlbuilder/src/main/java/org/eclipse/rdf4j/sparqlbuilder/graphpattern/GroupGraphPattern.java
index 31870505fd..21a5d4e248 100644
--- a/core/sparqlbuilder/src/main/java/org/eclipse/rdf4j/sparqlbuilder/graphpattern/GroupGraphPattern.java
+++ b/core/sparqlbuilder/src/main/java/org/eclipse/rdf4j/sparqlbuilder/graphpattern/GroupGraphPattern.java
@@ -58,7 +58,14 @@ protected void copy(GroupGraphPattern original) {
@Override
public GroupGraphPattern and(GraphPattern... patterns) {
if (isEmpty() && patterns.length == 1 && (isGGP(patterns[0]))) {
- copy(GraphPatterns.extractOrConvertToGGP(patterns[0]));
+ GroupGraphPattern ggp = GraphPatterns.extractOrConvertToGGP(patterns[0]);
+ // Only copy if it's a plain GroupGraphPattern, not a specialized subclass
+ // like FilterExistsGraphPattern or MinusGraphPattern which override getQueryString()
+ if (ggp.getClass() == GroupGraphPattern.class) {
+ copy(ggp);
+ } else {
+ addElements(patterns);
+ }
} else {
addElements(patterns);
}
diff --git a/core/sparqlbuilder/src/test/java/org/eclipse/rdf4j/sparqlbuilder/core/query/ModifyQueryTest.java b/core/sparqlbuilder/src/test/java/org/eclipse/rdf4j/sparqlbuilder/core/query/ModifyQueryTest.java
index fe272f7bf5..babe79ec0f 100644
--- a/core/sparqlbuilder/src/test/java/org/eclipse/rdf4j/sparqlbuilder/core/query/ModifyQueryTest.java
+++ b/core/sparqlbuilder/src/test/java/org/eclipse/rdf4j/sparqlbuilder/core/query/ModifyQueryTest.java
@@ -17,6 +17,7 @@
import org.eclipse.rdf4j.sparqlbuilder.core.SparqlBuilder;
import org.eclipse.rdf4j.sparqlbuilder.core.Variable;
import org.eclipse.rdf4j.sparqlbuilder.examples.BaseExamples;
+import org.eclipse.rdf4j.sparqlbuilder.graphpattern.GraphPatternNotTriples;
import org.eclipse.rdf4j.sparqlbuilder.graphpattern.GraphPatterns;
import org.eclipse.rdf4j.sparqlbuilder.graphpattern.TriplePattern;
import org.eclipse.rdf4j.sparqlbuilder.rdf.Iri;
@@ -53,4 +54,68 @@ public void example_issue_1481() {
"WHERE { OPTIONAL { ?subject ?predicate . }\n" +
"OPTIONAL { ?subject ?object . } }");
}
+
+ @Test
+ public void example_broken_filter_not_exists() {
+ // given
+ Iri subjectIri = iri("http://my-example.com/anyIRI/");
+ Iri classIri = iri("http://my-example.com/SomeClass/");
+ TriplePattern triple = subjectIri.isA(classIri);
+
+ String queryString = Queries.MODIFY()
+ .insert(triple)
+ .where(GraphPatterns.filterNotExists(triple))
+ .getQueryString();
+
+ assertEquals("INSERT { a . }\n" +
+ // the WHERE clause is incorrectly generated:
+ // "WHERE { a . }",
+ // should be:
+ "WHERE { FILTER NOT EXISTS { a . } }",
+ queryString
+ );
+ }
+
+ @Test
+ public void test_GraphPatternNotTriples_getQueryString() {
+ // given
+ Iri subjectIri = iri("http://my-example.com/anyIRI/");
+ Iri classIri = iri("http://my-example.com/SomeClass/");
+ TriplePattern triple = subjectIri.isA(classIri);
+
+ String queryString = GraphPatterns.filterNotExists(triple).getQueryString();
+
+ assertEquals(
+ "FILTER NOT EXISTS { a . }",
+ queryString
+ );
+ }
+
+ @Test
+ public void test_GraphPatterns_and_getQueryString() {
+ GraphPatternNotTriples actual = GraphPatterns.and();
+ assertEquals("{}", actual.getQueryString());
+ }
+
+ @Test
+ public void test_GraphPatterns_and_FilterExistsGraphPattern_getQueryString() {
+
+ TriplePattern triple = iri("http://my-example.com/anyIRI/").isA(iri("http://my-example.com/SomeClass/"));
+
+ // emptyGraphPattern by itself yields "{}", see test_GraphPatterns_and_getQueryString
+ GraphPatternNotTriples emptyGraphPattern = GraphPatterns.and();
+
+ // filterNotExists by itself yields "FILTER NOT EXISTS { ... }", see test_GraphPatternNotTriples_getQueryString
+ GraphPatternNotTriples filterNotExists = GraphPatterns.filterNotExists(triple);
+
+ // this is the cause oft the failing example_broken_filter_not_exists test
+ GraphPatternNotTriples withFilterNotExists = emptyGraphPattern.and(filterNotExists);
+
+ String actual = withFilterNotExists.getQueryString();
+
+ assertEquals(
+ "{ FILTER NOT EXISTS { a . } }",
+ actual
+ );
+ }
}