Skip to content

Commit babdea0

Browse files
authored
GH-5009: Fix position of OPTIONAL in RelationMapBuilder (#5010)
2 parents 6413b02 + 9e0b5b2 commit babdea0

2 files changed

Lines changed: 76 additions & 10 deletions

File tree

spring-components/rdf4j-spring/src/main/java/org/eclipse/rdf4j/spring/dao/support/RelationMapBuilder.java

Lines changed: 13 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -146,14 +146,17 @@ private IRI getRelationValueOrNothing(BindingSet b) {
146146

147147
private TupleQueryEvaluationBuilder makeTupleQueryBuilder() {
148148
return rdf4JTemplate
149-
.tupleQuery(
150-
Queries.SELECT(getProjection())
151-
.where(getWhereClause())
152-
.distinct()
153-
.getQueryString())
149+
.tupleQuery(makeQueryString())
154150
.withBindings(bindingsBuilder.build());
155151
}
156152

153+
String makeQueryString() {
154+
return Queries.SELECT(getProjection())
155+
.where(getWhereClause())
156+
.distinct()
157+
.getQueryString();
158+
}
159+
157160
private Projectable[] getProjection() {
158161
if (this.isSubjectKeyed) {
159162
return new Projectable[] {
@@ -168,14 +171,14 @@ private Projectable[] getProjection() {
168171

169172
private GraphPattern[] getWhereClause() {
170173
TriplePattern tp = _relSubject.has(predicate, _relObject);
174+
GraphPattern[] ret = new GraphPattern[constraints.length + 1];
171175
if (this.isRelationOptional) {
172-
GraphPattern[] ret = new GraphPattern[constraints.length + 1];
173-
ret[0] = tp.optional();
174-
System.arraycopy(constraints, 0, ret, 1, constraints.length);
175-
return ret;
176+
ret[constraints.length] = tp.optional();
176177
} else {
177-
return new GraphPattern[] { tp.and(constraints) };
178+
ret[constraints.length] = tp;
178179
}
180+
System.arraycopy(constraints, 0, ret, 0, constraints.length);
181+
return ret;
179182
}
180183

181184
public RelationMapBuilder withBinding(Variable key, Value value) {
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
/*******************************************************************************
2+
* Copyright (c) 2024 Eclipse RDF4J contributors.
3+
*
4+
* All rights reserved. This program and the accompanying materials
5+
* are made available under the terms of the Eclipse Distribution License v1.0
6+
* which accompanies this distribution, and is available at
7+
* http://www.eclipse.org/org/documents/edl-v10.php.
8+
*
9+
* SPDX-License-Identifier: BSD-3-Clause
10+
*******************************************************************************/
11+
package org.eclipse.rdf4j.spring.dao.support;
12+
13+
import static org.junit.jupiter.api.Assertions.assertEquals;
14+
15+
import org.eclipse.rdf4j.model.vocabulary.SKOS;
16+
import org.eclipse.rdf4j.spring.RDF4JSpringTestBase;
17+
import org.eclipse.rdf4j.spring.dao.support.RelationMapBuilder;
18+
import org.eclipse.rdf4j.spring.domain.model.EX;
19+
import org.eclipse.rdf4j.spring.support.RDF4JTemplate;
20+
import org.junit.jupiter.api.Test;
21+
import org.springframework.beans.factory.annotation.Autowired;
22+
23+
public class RelationMapBuilderTests extends RDF4JSpringTestBase {
24+
25+
@Autowired
26+
RDF4JTemplate rdf4JTemplate;
27+
28+
@Test
29+
public void testRelationOnly() {
30+
RelationMapBuilder rmb = new RelationMapBuilder(this.rdf4JTemplate, SKOS.BROADER);
31+
assertEquals(normalize(
32+
"SELECT DISTINCT ( ?rel_subject AS ?rel_key ) ( ?rel_object AS ?rel_value )\n"
33+
+ "WHERE { ?rel_subject <http://www.w3.org/2004/02/skos/core#broader> ?rel_object . }"),
34+
normalize(rmb.makeQueryString()));
35+
}
36+
37+
@Test
38+
public void testRelationWithConstraints() {
39+
RelationMapBuilder rmb = new RelationMapBuilder(this.rdf4JTemplate, EX.creatorOf)
40+
.constraints(RelationMapBuilder._relSubject.isA(
41+
EX.Artist));
42+
assertEquals(normalize("SELECT DISTINCT ( ?rel_subject AS ?rel_key ) ( ?rel_object AS ?rel_value )\n"
43+
+ "WHERE { ?rel_subject a <http://example.org/Artist> .\n"
44+
+ "?rel_subject <http://example.org/creatorOf> ?rel_object . }"), normalize(rmb.makeQueryString()));
45+
}
46+
47+
@Test
48+
public void testOptionalRelationWithPattern() {
49+
RelationMapBuilder rmb = new RelationMapBuilder(this.rdf4JTemplate, EX.creatorOf)
50+
.constraints(RelationMapBuilder._relSubject.isA(
51+
EX.Artist))
52+
.relationIsOptional();
53+
assertEquals(normalize(
54+
"SELECT DISTINCT ( ?rel_subject AS ?rel_key ) ( ?rel_object AS ?rel_value )\n"
55+
+ "WHERE { ?rel_subject a <http://example.org/Artist> .\n"
56+
+ "OPTIONAL { ?rel_subject <http://example.org/creatorOf> ?rel_object . } }\n"),
57+
normalize(rmb.makeQueryString()));
58+
}
59+
60+
private String normalize(String s) {
61+
return s.replaceAll("\n", " ").replaceAll("\\s+", " ").trim();
62+
}
63+
}

0 commit comments

Comments
 (0)