use of org.eclipse.rdf4j.query.algebra.TupleExpr in project rdf4j by eclipse.
the class AbstractQueryBuilder method query.
/**
* @inheritDoc
*/
public T query() {
UnaryTupleOperator aRoot = null;
UnaryTupleOperator aCurr = null;
if (mLimit != -1 || mOffset != -1) {
Slice aSlice = new Slice();
if (mLimit != -1) {
aSlice.setLimit(mLimit);
}
if (mOffset != -1) {
aSlice.setOffset(mOffset);
}
aRoot = aCurr = aSlice;
}
if (mOrderByElems != null && !mOrderByElems.isEmpty()) {
Order aOrder = new Order();
aOrder.addElements(mOrderByElems);
if (aRoot == null) {
aRoot = aCurr = aOrder;
} else {
aCurr.setArg(aOrder);
aCurr = aOrder;
}
}
if (mDistinct) {
Distinct aDistinct = new Distinct();
if (aRoot == null) {
aRoot = aCurr = aDistinct;
} else {
aCurr.setArg(aDistinct);
aCurr = aDistinct;
}
}
if (mReduced) {
Reduced aReduced = new Reduced();
if (aRoot == null) {
aRoot = aCurr = aReduced;
} else {
aCurr.setArg(aReduced);
aCurr = aReduced;
}
}
TupleExpr aJoin = join();
if (mQuery instanceof ParsedTupleQuery && mProjectionVars.isEmpty()) {
VarNameCollector aCollector = new VarNameCollector();
aJoin.visit(aCollector);
mProjectionVars.addAll(aCollector.getVarNames());
} else if (mQuery instanceof ParsedGraphQuery && mProjectionPatterns.isEmpty()) {
StatementPatternCollector aCollector = new StatementPatternCollector();
aJoin.visit(aCollector);
mProjectionPatterns.addAll(aCollector.getStatementPatterns());
}
UnaryTupleOperator aProjection = projection();
if (aRoot == null) {
aRoot = aCurr = aProjection;
} else {
aCurr.setArg(aProjection);
}
if (aProjection.getArg() == null) {
aCurr = aProjection;
} else {
// I think this is always a safe cast
aCurr = (UnaryTupleOperator) aProjection.getArg();
}
if (aJoin != null) {
aCurr.setArg(aJoin);
}
mQuery.setTupleExpr(aRoot);
if (!mFrom.isEmpty() || !mFromNamed.isEmpty()) {
SimpleDataset aDataset = new SimpleDataset();
for (IRI aFrom : mFrom) {
aDataset.addDefaultGraph(aFrom);
}
for (IRI aFrom : mFromNamed) {
aDataset.addNamedGraph(aFrom);
}
mQuery.setDataset(aDataset);
}
return mQuery;
}
use of org.eclipse.rdf4j.query.algebra.TupleExpr in project rdf4j by eclipse.
the class AbstractQueryBuilder method groupAsJoin.
private TupleExpr groupAsJoin(List<Group> theList) {
BinaryTupleOperator aJoin = new Join();
Filter aFilter = null;
for (Group aGroup : theList) {
TupleExpr aExpr = aGroup.expr();
if (aExpr == null) {
continue;
}
if (aExpr instanceof Filter && (((Filter) aExpr).getArg() == null || ((Filter) aExpr).getArg() instanceof EmptySet)) {
if (aFilter == null) {
aFilter = (Filter) aExpr;
} else {
// if we already have a filter w/ an empty arg, let's And the
// conditions together.
aFilter.setCondition(new And(aFilter.getCondition(), ((Filter) aExpr).getCondition()));
}
continue;
}
if (aFilter != null) {
aFilter.setArg(aExpr);
aExpr = aFilter;
aFilter = null;
}
if (aGroup.isOptional()) {
LeftJoin lj = new LeftJoin();
TupleExpr aLeft = joinOrExpr(aJoin);
if (aLeft != null) {
lj.setLeftArg(aLeft);
lj.setRightArg(aExpr);
aJoin = lj;
continue;
}
}
if (aJoin.getLeftArg() == null) {
aJoin.setLeftArg(aExpr);
} else if (aJoin.getRightArg() == null) {
aJoin.setRightArg(aExpr);
} else {
Join aNewJoin = new Join();
aNewJoin.setLeftArg(aJoin);
aNewJoin.setRightArg(aExpr);
aJoin = aNewJoin;
}
}
TupleExpr aExpr = joinOrExpr(aJoin);
if (aFilter != null) {
aFilter.setArg(aExpr);
aExpr = aFilter;
}
return aExpr;
}
use of org.eclipse.rdf4j.query.algebra.TupleExpr in project rdf4j by eclipse.
the class TupleExprBuilder method visit.
@Override
public Object visit(ASTPathSequence pathSeqNode, Object data) throws VisitorException {
ValueExpr subject = (ValueExpr) data;
Var subjVar = mapValueExprToVar(subject);
// check if we should invert subject and object.
boolean invertSequence = checkInverse(pathSeqNode);
@SuppressWarnings("unchecked") List<ValueExpr> objectList = (List<ValueExpr>) getObjectList(pathSeqNode).jjtAccept(this, null);
List<ASTPathElt> pathElements = pathSeqNode.getPathElements();
int pathLength = pathElements.size();
GraphPattern pathSequencePattern = new GraphPattern(graphPattern);
Scope scope = pathSequencePattern.getStatementPatternScope();
Var contextVar = pathSequencePattern.getContextVar();
Var startVar = subjVar;
for (int i = 0; i < pathLength; i++) {
ASTPathElt pathElement = pathElements.get(i);
ASTPathMod pathMod = pathElement.getPathMod();
long lowerBound = Long.MIN_VALUE;
long upperBound = Long.MIN_VALUE;
if (pathMod != null) {
lowerBound = pathMod.getLowerBound();
upperBound = pathMod.getUpperBound();
if (upperBound == Long.MIN_VALUE) {
upperBound = lowerBound;
} else if (lowerBound == Long.MIN_VALUE) {
lowerBound = upperBound;
}
}
if (pathElement.isNegatedPropertySet()) {
// create a temporary negated property set object and set the
// correct subject and object vars to continue
// the path sequence.
NegatedPropertySet nps = new NegatedPropertySet();
nps.setScope(scope);
nps.setSubjectVar(startVar);
nps.setContextVar(contextVar);
for (Node child : pathElement.jjtGetChildren()) {
if (child instanceof ASTPathMod) {
// skip the modifier
continue;
}
nps.addPropertySetElem((PropertySetElem) child.jjtAccept(this, data));
}
Var[] objVarReplacement = null;
if (i == pathLength - 1) {
if (objectList.contains(subjVar)) {
// See SES-1685
Var objVar = mapValueExprToVar(objectList.get(objectList.indexOf(subjVar)));
objVarReplacement = new Var[] { objVar, createAnonVar() };
objectList.remove(objVar);
objectList.add(objVarReplacement[1]);
} else {
nps.setObjectList(objectList);
}
} else {
// not last element in path.
Var nextVar = createAnonVar();
List<ValueExpr> nextVarList = new ArrayList<ValueExpr>();
nextVarList.add(nextVar);
nps.setObjectList(nextVarList);
startVar = nextVar;
}
// convert the NegatedPropertySet to a proper TupleExpr
TupleExpr te = createTupleExprForNegatedPropertySet(nps, i);
if (objVarReplacement != null) {
SameTerm condition = new SameTerm(objVarReplacement[0], objVarReplacement[1]);
pathSequencePattern.addConstraint(condition);
}
for (ValueExpr object : objectList) {
Var objVar = mapValueExprToVar(object);
te = handlePathModifiers(scope, subjVar, te, objVar, contextVar, lowerBound, upperBound);
}
pathSequencePattern.addRequiredTE(te);
} else if (pathElement.isNestedPath()) {
GraphPattern parentGP = graphPattern;
graphPattern = new GraphPattern(parentGP);
if (i == pathLength - 1) {
// last element in the path
pathElement.jjtGetChild(0).jjtAccept(this, startVar);
TupleExpr te = graphPattern.buildTupleExpr();
for (ValueExpr object : objectList) {
Var objVar = mapValueExprToVar(object);
if (objVar.equals(subjVar)) {
// see SES-1685
Var objVarReplacement = createAnonVar();
te = handlePathModifiers(scope, startVar, te, objVarReplacement, contextVar, lowerBound, upperBound);
SameTerm condition = new SameTerm(objVar, objVarReplacement);
pathSequencePattern.addConstraint(condition);
} else {
te = handlePathModifiers(scope, startVar, te, objVar, contextVar, lowerBound, upperBound);
}
pathSequencePattern.addRequiredTE(te);
}
} else {
// not the last element in the path, introduce an anonymous
// var
// to connect.
Var nextVar = createAnonVar();
pathElement.jjtGetChild(0).jjtAccept(this, startVar);
TupleExpr te = graphPattern.buildTupleExpr();
// replace all object list occurrences with the intermediate
// var.
te = replaceVarOccurrence(te, objectList, nextVar);
te = handlePathModifiers(scope, startVar, te, nextVar, contextVar, lowerBound, upperBound);
pathSequencePattern.addRequiredTE(te);
startVar = nextVar;
}
graphPattern = parentGP;
} else {
ValueExpr pred = (ValueExpr) pathElement.jjtAccept(this, data);
Var predVar = mapValueExprToVar(pred);
TupleExpr te;
if (i == pathLength - 1) {
// objects
for (ValueExpr object : objectList) {
Var objVar = mapValueExprToVar(object);
boolean replaced = false;
// to avoid problems in cyclic paths
if (objVar.equals(subjVar)) {
objVar = createAnonVar();
replaced = true;
}
Var endVar = objVar;
if (invertSequence) {
endVar = subjVar;
if (startVar.equals(subjVar)) {
// inverted path sequence of length 1.
startVar = objVar;
}
}
if (pathElement.isInverse()) {
te = new StatementPattern(scope, endVar, predVar, startVar, contextVar);
te = handlePathModifiers(scope, endVar, te, startVar, contextVar, lowerBound, upperBound);
} else {
te = new StatementPattern(scope, startVar, predVar, endVar, contextVar);
te = handlePathModifiers(scope, startVar, te, endVar, contextVar, lowerBound, upperBound);
}
if (replaced) {
SameTerm condition = new SameTerm(objVar, mapValueExprToVar(object));
pathSequencePattern.addConstraint(condition);
}
pathSequencePattern.addRequiredTE(te);
}
} else {
// not the last element in the path, introduce an anonymous
// var
// to connect.
Var nextVar = createAnonVar();
if (invertSequence && startVar.equals(subjVar)) {
// sequence
for (ValueExpr object : objectList) {
Var objVar = mapValueExprToVar(object);
startVar = objVar;
if (pathElement.isInverse()) {
Var temp = startVar;
startVar = nextVar;
nextVar = temp;
}
te = new StatementPattern(scope, startVar, predVar, nextVar, contextVar);
te = handlePathModifiers(scope, startVar, te, nextVar, contextVar, lowerBound, upperBound);
pathSequencePattern.addRequiredTE(te);
}
} else {
if (pathElement.isInverse()) {
final Var oldStartVar = startVar;
startVar = nextVar;
nextVar = oldStartVar;
}
te = new StatementPattern(scope, startVar, predVar, nextVar, contextVar);
te = handlePathModifiers(scope, startVar, te, nextVar, contextVar, lowerBound, upperBound);
pathSequencePattern.addRequiredTE(te);
}
// set the subject for the next element in the path.
startVar = (pathElement.isInverse() ? startVar : nextVar);
}
}
}
// add the created path sequence to the graph pattern.
for (TupleExpr te : pathSequencePattern.getRequiredTEs()) {
graphPattern.addRequiredTE(te);
}
if (pathSequencePattern.getConstraints() != null) {
for (ValueExpr constraint : pathSequencePattern.getConstraints()) {
graphPattern.addConstraint(constraint);
}
}
return null;
}
use of org.eclipse.rdf4j.query.algebra.TupleExpr in project rdf4j by eclipse.
the class TupleExprBuilder method visit.
@Override
public Object visit(ASTMinusGraphPattern node, Object data) throws VisitorException {
GraphPattern parentGP = graphPattern;
TupleExpr leftArg = graphPattern.buildTupleExpr();
graphPattern = new GraphPattern(parentGP);
node.jjtGetChild(0).jjtAccept(this, null);
TupleExpr rightArg = graphPattern.buildTupleExpr();
parentGP = new GraphPattern();
parentGP.addRequiredTE(new Difference(leftArg, rightArg));
graphPattern = parentGP;
return null;
}
use of org.eclipse.rdf4j.query.algebra.TupleExpr in project rdf4j by eclipse.
the class TupleExprBuilder method visit.
@Override
public Object visit(ASTBind node, Object data) throws VisitorException {
// bind expression
ValueExpr ve = (ValueExpr) node.jjtGetChild(0).jjtAccept(this, data);
// name to bind the expression outcome to
Node aliasNode = node.jjtGetChild(1);
String alias = ((ASTVar) aliasNode).getName();
Extension extension = new Extension();
extension.addElement(new ExtensionElem(ve, alias));
TupleExpr result = null;
TupleExpr arg = graphPattern.buildTupleExpr();
// check if alias is not previously used.
if (arg.getBindingNames().contains(alias)) {
// SES-2314 we need to doublecheck that the reused varname is not
// just
// for an anonymous var or a constant.
VarCollector collector = new VarCollector();
arg.visit(collector);
for (Var v : collector.getCollectedVars()) {
if (alias.equals(v.getName())) {
if (!v.isConstant() && !v.isAnonymous()) {
throw new VisitorException(String.format("BIND clause alias '%s' was previously used", alias));
}
break;
}
}
}
if (arg instanceof Filter) {
result = arg;
// the BIND expression.
while (((Filter) arg).getArg() instanceof Filter) {
arg = ((Filter) arg).getArg();
}
extension.setArg(((Filter) arg).getArg());
((Filter) arg).setArg(extension);
} else {
extension.setArg(arg);
result = extension;
}
GraphPattern replacementGP = new GraphPattern(graphPattern);
replacementGP.addRequiredTE(result);
graphPattern = replacementGP;
return result;
}
Aggregations