Skip to content

Commit ac2accd

Browse files
authored
GH-4990: support for zero-length path expression in FedX (#4991)
2 parents 192b4ea + 4d903e4 commit ac2accd

File tree

10 files changed

+1348
-10
lines changed

10 files changed

+1348
-10
lines changed
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
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.federated.algebra;
12+
13+
import java.util.List;
14+
15+
import org.eclipse.rdf4j.federated.structures.QueryInfo;
16+
import org.eclipse.rdf4j.federated.util.QueryAlgebraUtil;
17+
import org.eclipse.rdf4j.query.algebra.ArbitraryLengthPath;
18+
import org.eclipse.rdf4j.query.algebra.Var;
19+
20+
/**
21+
* A specialization of {@link ArbitraryLengthPath} to maintain the {@link QueryInfo}
22+
*
23+
* @author Andreas Schwarte
24+
*/
25+
public class FedXArbitraryLengthPath extends ArbitraryLengthPath implements FedXTupleExpr {
26+
27+
private static final long serialVersionUID = -7512248084095130084L;
28+
29+
private final QueryInfo queryInfo;
30+
31+
public FedXArbitraryLengthPath(ArbitraryLengthPath path, QueryInfo queryInfo) {
32+
super(path.getScope(), clone(path.getSubjectVar()), path.getPathExpression(), clone(path.getObjectVar()),
33+
clone(path.getContextVar()), path.getMinLength());
34+
this.queryInfo = queryInfo;
35+
}
36+
37+
private static Var clone(Var var) {
38+
if (var == null) {
39+
return null;
40+
}
41+
return var.clone();
42+
}
43+
44+
@Override
45+
public List<String> getFreeVars() {
46+
return List.copyOf(QueryAlgebraUtil.getFreeVars(getPathExpression()));
47+
}
48+
49+
@Override
50+
public QueryInfo getQueryInfo() {
51+
return queryInfo;
52+
}
53+
54+
}
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
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.federated.algebra;
12+
13+
import java.util.List;
14+
15+
import org.eclipse.rdf4j.federated.structures.QueryInfo;
16+
import org.eclipse.rdf4j.query.algebra.StatementPattern.Scope;
17+
import org.eclipse.rdf4j.query.algebra.Var;
18+
import org.eclipse.rdf4j.query.algebra.ZeroLengthPath;
19+
20+
/**
21+
* A specialization of {@link ZeroLengthPath} that keeps track of {@link QueryInfo} and statement sources.
22+
*
23+
* @author Andreas Schwarte
24+
*/
25+
public class FedXZeroLengthPath extends ZeroLengthPath implements QueryRef {
26+
27+
private static final long serialVersionUID = 2241037911187178861L;
28+
29+
private final QueryInfo queryInfo;
30+
31+
private final List<StatementSource> statementSources;
32+
33+
public FedXZeroLengthPath(Scope scope, Var subjVar, Var objVar, Var conVar, QueryInfo queryInfo,
34+
List<StatementSource> statementSources) {
35+
super(scope, subjVar, objVar, conVar);
36+
this.queryInfo = queryInfo;
37+
this.statementSources = statementSources;
38+
}
39+
40+
public List<StatementSource> getStatementSources() {
41+
return statementSources;
42+
}
43+
44+
@Override
45+
public QueryInfo getQueryInfo() {
46+
return queryInfo;
47+
}
48+
49+
}
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
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.federated.algebra;
12+
13+
import org.eclipse.rdf4j.query.algebra.AbstractQueryModelNode;
14+
import org.eclipse.rdf4j.query.algebra.QueryModelNode;
15+
import org.eclipse.rdf4j.query.algebra.QueryModelVisitor;
16+
17+
/**
18+
* An artificial holder node serving as parent holder to allow replacement.
19+
*/
20+
public class HolderNode extends AbstractQueryModelNode {
21+
22+
private static final long serialVersionUID = -4689963986499825771L;
23+
private QueryModelNode child;
24+
25+
public HolderNode(QueryModelNode child) {
26+
super();
27+
setChild(child);
28+
}
29+
30+
public void setChild(QueryModelNode child) {
31+
this.child = child;
32+
this.child.setParentNode(this);
33+
}
34+
35+
@Override
36+
public <X extends Exception> void visitChildren(QueryModelVisitor<X> visitor) throws X {
37+
child.visit(visitor);
38+
}
39+
40+
@Override
41+
public <X extends Exception> void visit(QueryModelVisitor<X> visitor) throws X {
42+
visitor.meetOther(this);
43+
}
44+
45+
@Override
46+
public void replaceChildNode(QueryModelNode current, QueryModelNode replacement) {
47+
if (child.equals(current)) {
48+
setChild(replacement);
49+
50+
}
51+
}
52+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
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.federated.evaluation;
12+
13+
import java.util.List;
14+
import java.util.function.Supplier;
15+
16+
import org.eclipse.rdf4j.common.iteration.CloseableIteration;
17+
import org.eclipse.rdf4j.federated.algebra.FedXZeroLengthPath;
18+
import org.eclipse.rdf4j.federated.algebra.StatementSource;
19+
import org.eclipse.rdf4j.federated.evaluation.iterator.FedXZeroLengthPathIteration;
20+
import org.eclipse.rdf4j.federated.structures.QueryInfo;
21+
import org.eclipse.rdf4j.model.Value;
22+
import org.eclipse.rdf4j.query.BindingSet;
23+
import org.eclipse.rdf4j.query.QueryEvaluationException;
24+
import org.eclipse.rdf4j.query.algebra.Var;
25+
import org.eclipse.rdf4j.query.algebra.evaluation.EvaluationStrategy;
26+
import org.eclipse.rdf4j.query.algebra.evaluation.QueryEvaluationStep;
27+
import org.eclipse.rdf4j.query.algebra.evaluation.QueryValueEvaluationStep;
28+
import org.eclipse.rdf4j.query.algebra.evaluation.impl.QueryEvaluationContext;
29+
import org.eclipse.rdf4j.query.algebra.evaluation.impl.evaluationsteps.ZeroLengthPathEvaluationStep;
30+
31+
/**
32+
* An evaluation step used for {@link FedXZeroLengthPath}.
33+
*
34+
* @see ZeroLengthPathEvaluationStep
35+
*/
36+
public final class FedXZeroLengthPathEvaluationStep implements QueryEvaluationStep {
37+
private final Var subjectVar;
38+
private final Var objVar;
39+
private final Var contextVar;
40+
private final QueryValueEvaluationStep subPrep;
41+
private final QueryValueEvaluationStep objPrep;
42+
private final EvaluationStrategy strategy;
43+
private final QueryEvaluationContext context;
44+
45+
private final Supplier<List<StatementSource>> statementSources;
46+
private final Supplier<QueryInfo> queryInfo;
47+
48+
public FedXZeroLengthPathEvaluationStep(Var subjectVar, Var objVar, Var contextVar,
49+
QueryValueEvaluationStep subPrep,
50+
QueryValueEvaluationStep objPrep, EvaluationStrategy strategy, QueryEvaluationContext context,
51+
Supplier<List<StatementSource>> statementSources, Supplier<QueryInfo> queryInfo) {
52+
this.subjectVar = subjectVar;
53+
this.objVar = objVar;
54+
this.contextVar = contextVar;
55+
this.subPrep = subPrep;
56+
this.objPrep = objPrep;
57+
this.strategy = strategy;
58+
this.context = context;
59+
60+
this.statementSources = statementSources;
61+
this.queryInfo = queryInfo;
62+
}
63+
64+
@Override
65+
public CloseableIteration<BindingSet, QueryEvaluationException> evaluate(BindingSet bindings) {
66+
Value subj = null;
67+
try {
68+
subj = subPrep.evaluate(bindings);
69+
} catch (QueryEvaluationException ignored) {
70+
}
71+
72+
Value obj = null;
73+
try {
74+
obj = objPrep.evaluate(bindings);
75+
} catch (QueryEvaluationException ignored) {
76+
}
77+
78+
if (subj != null && obj != null) {
79+
if (!subj.equals(obj)) {
80+
return EMPTY_ITERATION;
81+
}
82+
}
83+
return getZeroLengthPathIterator(bindings, subjectVar, objVar, contextVar, subj, obj, context);
84+
}
85+
86+
protected FedXZeroLengthPathIteration getZeroLengthPathIterator(final BindingSet bindings, final Var subjectVar,
87+
final Var objVar, final Var contextVar, Value subj, Value obj, QueryEvaluationContext context) {
88+
return new FedXZeroLengthPathIteration(strategy, subjectVar, objVar, subj, obj, contextVar, bindings, context,
89+
queryInfo.get(), statementSources.get());
90+
}
91+
}

0 commit comments

Comments
 (0)