Skip to content

Commit

Permalink
GH-4990: support for zero-length path expression in FedX (#4991)
Browse files Browse the repository at this point in the history
  • Loading branch information
hmottestad authored May 31, 2024
2 parents 192b4ea + 4d903e4 commit ac2accd
Show file tree
Hide file tree
Showing 10 changed files with 1,348 additions and 10 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
/*******************************************************************************
* Copyright (c) 2024 Eclipse RDF4J contributors.
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Distribution License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/org/documents/edl-v10.php.
*
* SPDX-License-Identifier: BSD-3-Clause
*******************************************************************************/
package org.eclipse.rdf4j.federated.algebra;

import java.util.List;

import org.eclipse.rdf4j.federated.structures.QueryInfo;
import org.eclipse.rdf4j.federated.util.QueryAlgebraUtil;
import org.eclipse.rdf4j.query.algebra.ArbitraryLengthPath;
import org.eclipse.rdf4j.query.algebra.Var;

/**
* A specialization of {@link ArbitraryLengthPath} to maintain the {@link QueryInfo}
*
* @author Andreas Schwarte
*/
public class FedXArbitraryLengthPath extends ArbitraryLengthPath implements FedXTupleExpr {

private static final long serialVersionUID = -7512248084095130084L;

private final QueryInfo queryInfo;

public FedXArbitraryLengthPath(ArbitraryLengthPath path, QueryInfo queryInfo) {
super(path.getScope(), clone(path.getSubjectVar()), path.getPathExpression(), clone(path.getObjectVar()),
clone(path.getContextVar()), path.getMinLength());
this.queryInfo = queryInfo;
}

private static Var clone(Var var) {
if (var == null) {
return null;
}
return var.clone();
}

@Override
public List<String> getFreeVars() {
return List.copyOf(QueryAlgebraUtil.getFreeVars(getPathExpression()));
}

@Override
public QueryInfo getQueryInfo() {
return queryInfo;
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
/*******************************************************************************
* Copyright (c) 2024 Eclipse RDF4J contributors.
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Distribution License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/org/documents/edl-v10.php.
*
* SPDX-License-Identifier: BSD-3-Clause
*******************************************************************************/
package org.eclipse.rdf4j.federated.algebra;

import java.util.List;

import org.eclipse.rdf4j.federated.structures.QueryInfo;
import org.eclipse.rdf4j.query.algebra.StatementPattern.Scope;
import org.eclipse.rdf4j.query.algebra.Var;
import org.eclipse.rdf4j.query.algebra.ZeroLengthPath;

/**
* A specialization of {@link ZeroLengthPath} that keeps track of {@link QueryInfo} and statement sources.
*
* @author Andreas Schwarte
*/
public class FedXZeroLengthPath extends ZeroLengthPath implements QueryRef {

private static final long serialVersionUID = 2241037911187178861L;

private final QueryInfo queryInfo;

private final List<StatementSource> statementSources;

public FedXZeroLengthPath(Scope scope, Var subjVar, Var objVar, Var conVar, QueryInfo queryInfo,
List<StatementSource> statementSources) {
super(scope, subjVar, objVar, conVar);
this.queryInfo = queryInfo;
this.statementSources = statementSources;
}

public List<StatementSource> getStatementSources() {
return statementSources;
}

@Override
public QueryInfo getQueryInfo() {
return queryInfo;
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
/*******************************************************************************
* Copyright (c) 2024 Eclipse RDF4J contributors.
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Distribution License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/org/documents/edl-v10.php.
*
* SPDX-License-Identifier: BSD-3-Clause
*******************************************************************************/
package org.eclipse.rdf4j.federated.algebra;

import org.eclipse.rdf4j.query.algebra.AbstractQueryModelNode;
import org.eclipse.rdf4j.query.algebra.QueryModelNode;
import org.eclipse.rdf4j.query.algebra.QueryModelVisitor;

/**
* An artificial holder node serving as parent holder to allow replacement.
*/
public class HolderNode extends AbstractQueryModelNode {

private static final long serialVersionUID = -4689963986499825771L;
private QueryModelNode child;

public HolderNode(QueryModelNode child) {
super();
setChild(child);
}

public void setChild(QueryModelNode child) {
this.child = child;
this.child.setParentNode(this);
}

@Override
public <X extends Exception> void visitChildren(QueryModelVisitor<X> visitor) throws X {
child.visit(visitor);
}

@Override
public <X extends Exception> void visit(QueryModelVisitor<X> visitor) throws X {
visitor.meetOther(this);
}

@Override
public void replaceChildNode(QueryModelNode current, QueryModelNode replacement) {
if (child.equals(current)) {
setChild(replacement);

}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
/*******************************************************************************
* Copyright (c) 2024 Eclipse RDF4J contributors.
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Distribution License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/org/documents/edl-v10.php.
*
* SPDX-License-Identifier: BSD-3-Clause
*******************************************************************************/
package org.eclipse.rdf4j.federated.evaluation;

import java.util.List;
import java.util.function.Supplier;

import org.eclipse.rdf4j.common.iteration.CloseableIteration;
import org.eclipse.rdf4j.federated.algebra.FedXZeroLengthPath;
import org.eclipse.rdf4j.federated.algebra.StatementSource;
import org.eclipse.rdf4j.federated.evaluation.iterator.FedXZeroLengthPathIteration;
import org.eclipse.rdf4j.federated.structures.QueryInfo;
import org.eclipse.rdf4j.model.Value;
import org.eclipse.rdf4j.query.BindingSet;
import org.eclipse.rdf4j.query.QueryEvaluationException;
import org.eclipse.rdf4j.query.algebra.Var;
import org.eclipse.rdf4j.query.algebra.evaluation.EvaluationStrategy;
import org.eclipse.rdf4j.query.algebra.evaluation.QueryEvaluationStep;
import org.eclipse.rdf4j.query.algebra.evaluation.QueryValueEvaluationStep;
import org.eclipse.rdf4j.query.algebra.evaluation.impl.QueryEvaluationContext;
import org.eclipse.rdf4j.query.algebra.evaluation.impl.evaluationsteps.ZeroLengthPathEvaluationStep;

/**
* An evaluation step used for {@link FedXZeroLengthPath}.
*
* @see ZeroLengthPathEvaluationStep
*/
public final class FedXZeroLengthPathEvaluationStep implements QueryEvaluationStep {
private final Var subjectVar;
private final Var objVar;
private final Var contextVar;
private final QueryValueEvaluationStep subPrep;
private final QueryValueEvaluationStep objPrep;
private final EvaluationStrategy strategy;
private final QueryEvaluationContext context;

private final Supplier<List<StatementSource>> statementSources;
private final Supplier<QueryInfo> queryInfo;

public FedXZeroLengthPathEvaluationStep(Var subjectVar, Var objVar, Var contextVar,
QueryValueEvaluationStep subPrep,
QueryValueEvaluationStep objPrep, EvaluationStrategy strategy, QueryEvaluationContext context,
Supplier<List<StatementSource>> statementSources, Supplier<QueryInfo> queryInfo) {
this.subjectVar = subjectVar;
this.objVar = objVar;
this.contextVar = contextVar;
this.subPrep = subPrep;
this.objPrep = objPrep;
this.strategy = strategy;
this.context = context;

this.statementSources = statementSources;
this.queryInfo = queryInfo;
}

@Override
public CloseableIteration<BindingSet, QueryEvaluationException> evaluate(BindingSet bindings) {
Value subj = null;
try {
subj = subPrep.evaluate(bindings);
} catch (QueryEvaluationException ignored) {
}

Value obj = null;
try {
obj = objPrep.evaluate(bindings);
} catch (QueryEvaluationException ignored) {
}

if (subj != null && obj != null) {
if (!subj.equals(obj)) {
return EMPTY_ITERATION;
}
}
return getZeroLengthPathIterator(bindings, subjectVar, objVar, contextVar, subj, obj, context);
}

protected FedXZeroLengthPathIteration getZeroLengthPathIterator(final BindingSet bindings, final Var subjectVar,
final Var objVar, final Var contextVar, Value subj, Value obj, QueryEvaluationContext context) {
return new FedXZeroLengthPathIteration(strategy, subjectVar, objVar, subj, obj, contextVar, bindings, context,
queryInfo.get(), statementSources.get());
}
}
Loading

0 comments on commit ac2accd

Please sign in to comment.