Skip to content

Commit 6df1ac1

Browse files
committed
updated test
1 parent 9e1001e commit 6df1ac1

1 file changed

Lines changed: 193 additions & 0 deletions

File tree

core/sail/memory/src/test/java/org/eclipse/rdf4j/sail/memory/MemoryStoreMinusScopingDebugTest.java

Lines changed: 193 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -134,6 +134,199 @@ public void testEmptyUnion() {
134134
}
135135
}
136136

137+
@Test
138+
public void complexMinus_rhsOptionalBindOfOuterVar_unsharedBindIgnored() throws IOException {
139+
String ttl = "@prefix : <http://ex/> .\n" +
140+
":a :p 1 ; :q 1, 2 .\n" +
141+
":b :p 3 ; :q 4 .\n" +
142+
":c :p 7 .";
143+
144+
try (SailRepositoryConnection conn = repository.getConnection()) {
145+
List<BindingSet> rows = selectWithData(conn, ttl, RDFFormat.TURTLE,
146+
"SELECT ?x WHERE {\n" +
147+
" ?x :p ?n .\n" +
148+
" MINUS { OPTIONAL { BIND(?n AS ?k) } ?x :q ?k }\n" +
149+
"} ORDER BY ?x");
150+
151+
// Only :c lacks :q; binding of out-of-scope ?n in the RHS is ignored for scoping,
152+
// and ?k is bound by ?x :q ?k when available. Thus :a and :b are removed.
153+
assertEquals(setOf("c"), names(rows, "x"));
154+
}
155+
}
156+
157+
@Test
158+
public void complexMinus_rhsUnionSharedAndUnsharedBranches_onlySharedAffects() throws IOException {
159+
String ttl = "@prefix : <http://ex/> .\n" +
160+
":a :p 10 ; :q 20 .\n" +
161+
":b :p 20 ; :q 30 .\n" +
162+
":c :p 30 .\n" +
163+
":z :q 999 .";
164+
165+
try (SailRepositoryConnection conn = repository.getConnection()) {
166+
List<BindingSet> rows = selectWithData(conn, ttl, RDFFormat.TURTLE,
167+
"SELECT ?x WHERE {\n" +
168+
" ?x :p ?v .\n" +
169+
" MINUS { { ?x :q ?v } UNION { ?y :q ?w } }\n" +
170+
"} ORDER BY ?x");
171+
172+
// Unshared UNION branch must not affect MINUS; only { ?x :q ?v } would remove rows
173+
// where q==p, which does not occur in the dataset. All subjects with :p remain.
174+
assertEquals(setOf("a", "b", "c"), names(rows, "x"));
175+
}
176+
}
177+
178+
@Test
179+
public void complexNotExists_overBareOptional_alwaysFalse() {
180+
try (SailRepositoryConnection conn = repository.getConnection()) {
181+
String query = "SELECT * WHERE { BIND(1 AS ?d) FILTER NOT EXISTS { OPTIONAL { BIND(1 AS ?z) } } }";
182+
TupleQuery tq = conn.prepareTupleQuery(QueryLanguage.SPARQL, query);
183+
try (TupleQueryResult r = tq.evaluate()) {
184+
assertNotNull(r);
185+
assertFalse(r.hasNext());
186+
}
187+
}
188+
}
189+
190+
@Test
191+
public void complexOptionalSubselect_noLeftBindings_emptyOptionalYieldsNoRow() {
192+
try (SailRepositoryConnection conn = repository.getConnection()) {
193+
String query = "SELECT ?flag WHERE { " +
194+
"OPTIONAL { SELECT ?v WHERE { VALUES ?u { } } } " +
195+
"BIND(IF(BOUND(?v), 'Y','N') AS ?flag) }";
196+
TupleQuery tq = conn.prepareTupleQuery(QueryLanguage.SPARQL, query);
197+
try (TupleQueryResult r = tq.evaluate()) {
198+
assertNotNull(r);
199+
assertFalse(r.hasNext());
200+
}
201+
}
202+
}
203+
204+
@Test
205+
public void complexMinus_rhsSubselectOrderLimitBindEquality_removesLimitedMatches() throws IOException {
206+
String ttl = "@prefix : <http://ex/> .\n" +
207+
":e :p 10 ; :q 10 .\n" +
208+
":f :p 20 ; :q 20 .\n" +
209+
":g :p 30 ; :q 99 .\n" +
210+
":h :p 40 ; :q 40 .";
211+
212+
try (SailRepositoryConnection conn = repository.getConnection()) {
213+
List<BindingSet> rows = selectWithData(conn, ttl, RDFFormat.TURTLE,
214+
"SELECT ?x WHERE {\n" +
215+
" ?x :p ?v .\n" +
216+
" MINUS { { SELECT ?x ?rv WHERE { ?x :q ?rv } ORDER BY ?rv LIMIT 2 } BIND(?rv AS ?v) }\n" +
217+
"} ORDER BY ?x");
218+
219+
// The two smallest q-values are 10 and 20; only e and f match q==p among those,
220+
// so they are removed. g and h remain.
221+
assertEquals(setOf("g", "h"), names(rows, "x"));
222+
}
223+
}
224+
225+
@Test
226+
public void graphIsolation_sameGraphNoRemovalWhenValuesDiffer() throws IOException {
227+
String trig = "@prefix : <http://ex/> .\n" +
228+
"GRAPH :g1 { :a :p 1 . }\n" +
229+
"GRAPH :g2 { :a :q 1 . :a :p 2 . }";
230+
231+
try (SailRepositoryConnection conn = repository.getConnection()) {
232+
List<BindingSet> rows = selectWithData(conn, trig, RDFFormat.TRIG,
233+
"SELECT ?g ?x ?n WHERE {\n" +
234+
" GRAPH ?g { ?x :p ?n }\n" +
235+
" MINUS { GRAPH ?g { ?x :q ?n } }\n" +
236+
"} ORDER BY ?g ?x ?n");
237+
assertEquals(setOf("g1|a|1", "g2|a|2"),
238+
rows.stream()
239+
.map(bs -> name(bs.getValue("g")) + "|" + name(bs.getValue("x")) + "|"
240+
+ name(bs.getValue("n")))
241+
.collect(Collectors.toCollection(LinkedHashSet::new)));
242+
}
243+
}
244+
245+
@Test
246+
public void graphIsolation_removesOnlyInGraphWithMatch() throws IOException {
247+
String trig = "@prefix : <http://ex/> .\n" +
248+
"GRAPH :g1 { :a :p 1 . }\n" +
249+
"GRAPH :g2 { :a :q 1 . :a :p 2 . :a :q 2 . }";
250+
251+
try (SailRepositoryConnection conn = repository.getConnection()) {
252+
List<BindingSet> rows = selectWithData(conn, trig, RDFFormat.TRIG,
253+
"SELECT ?g ?x ?n WHERE {\n" +
254+
" GRAPH ?g { ?x :p ?n }\n" +
255+
" MINUS { GRAPH ?g { ?x :q ?n } }\n" +
256+
"} ORDER BY ?g");
257+
assertEquals(setOf("g1|a|1"),
258+
rows.stream()
259+
.map(bs -> name(bs.getValue("g")) + "|" + name(bs.getValue("x")) + "|"
260+
+ name(bs.getValue("n")))
261+
.collect(Collectors.toCollection(LinkedHashSet::new)));
262+
}
263+
}
264+
265+
@Test
266+
public void valuesOnRight_sharedVarRemovesOnlyListedSubjects() throws IOException {
267+
String ttl = "@prefix : <http://ex/> .\n" +
268+
":a :p 1 . :b :p 2 . :c :p 3 .";
269+
try (SailRepositoryConnection conn = repository.getConnection()) {
270+
List<BindingSet> rows = selectWithData(conn, ttl, RDFFormat.TURTLE,
271+
"SELECT ?x WHERE { ?x :p ?v MINUS { VALUES ?x { :a :c } } } ORDER BY ?x");
272+
assertEquals(setOf("b"), names(rows, "x"));
273+
}
274+
}
275+
276+
@Test
277+
public void nestedNotExistsOverOptionalWithUnion_isAlwaysFalse() {
278+
try (SailRepositoryConnection conn = repository.getConnection()) {
279+
String q = "SELECT * WHERE { BIND(1 AS ?d) FILTER NOT EXISTS { OPTIONAL { { BIND(1 AS ?z) } UNION { BIND(2 AS ?z) FILTER(?z>1) } } } }";
280+
TupleQuery tq = conn.prepareTupleQuery(QueryLanguage.SPARQL, q);
281+
try (TupleQueryResult r = tq.evaluate()) {
282+
assertNotNull(r);
283+
assertFalse(r.hasNext());
284+
}
285+
}
286+
}
287+
288+
@Test
289+
public void optionalSubselectWithLeftBindings_keepsLeftRows() throws IOException {
290+
String ttl = "@prefix : <http://ex/> .\n" +
291+
":a :p 1 .";
292+
try (SailRepositoryConnection conn = repository.getConnection()) {
293+
List<BindingSet> rows = selectWithData(conn, ttl, RDFFormat.TURTLE,
294+
"SELECT ?x WHERE { ?x :p ?v OPTIONAL { SELECT ?z WHERE { FILTER(false) } } } ORDER BY ?x");
295+
assertEquals(setOf("a"), names(rows, "x"));
296+
}
297+
}
298+
299+
@Test
300+
public void minusRhsUnionSubselects_withGraphs_onlySameGraphBranchRemoves() throws IOException {
301+
String trig = "@prefix : <http://ex/> .\n" +
302+
"GRAPH :g1 { :a :p 1 . :a :q 1 . }\n" +
303+
"GRAPH :g2 { :b :p 2 . :c :q 2 . }";
304+
try (SailRepositoryConnection conn = repository.getConnection()) {
305+
List<BindingSet> rows = selectWithData(conn, trig, RDFFormat.TRIG,
306+
"SELECT ?g ?x ?n WHERE {\n" +
307+
" GRAPH ?g { ?x :p ?n }\n" +
308+
" MINUS { { GRAPH ?g { ?x :q ?n } } UNION { GRAPH :g2 { ?x :q ?n } } }\n" +
309+
"} ORDER BY ?g ?x ?n");
310+
assertEquals(setOf("g2|b|2"),
311+
rows.stream()
312+
.map(bs -> name(bs.getValue("g")) + "|" + name(bs.getValue("x")) + "|"
313+
+ name(bs.getValue("n")))
314+
.collect(Collectors.toCollection(LinkedHashSet::new)));
315+
}
316+
}
317+
318+
@Test
319+
public void bnodeOnRhsViaUnionAndSubselect_cannotMatchDataIds() throws IOException {
320+
String ttl = "@prefix : <http://ex/> .\n" +
321+
"_:b1 a [] . _:b2 a [] .\n" +
322+
":k :id _:b1 . :l :id _:b2 .";
323+
try (SailRepositoryConnection conn = repository.getConnection()) {
324+
List<BindingSet> rows = selectWithData(conn, ttl, RDFFormat.TURTLE,
325+
"SELECT ?s WHERE { ?s :id ?id MINUS { { BIND(BNODE() AS ?id) } UNION { SELECT ?id WHERE { BIND(BNODE() AS ?id) } } } } ORDER BY ?s");
326+
assertEquals(setOf("k", "l"), names(rows, "s"));
327+
}
328+
}
329+
137330
private List<BindingSet> selectWithData(RepositoryConnection conn, String data, RDFFormat format, String body)
138331
throws IOException {
139332
String sparql = PREFIX + body;

0 commit comments

Comments
 (0)