Search in sources :

Example 1 with ProjectionElemList

use of org.eclipse.rdf4j.query.algebra.ProjectionElemList in project rdf4j by eclipse.

the class TupleExprBuilder method visit.

@Override
public TupleExpr visit(ASTSelect node, Object data) throws VisitorException {
    TupleExpr result = (TupleExpr) data;
    final Order orderClause = result instanceof Order ? (Order) result : null;
    Extension extension = new Extension();
    ProjectionElemList projElemList = new ProjectionElemList();
    GroupFinder groupFinder = new GroupFinder();
    result.visit(groupFinder);
    Group group = groupFinder.getGroup();
    boolean existingGroup = group != null;
    List<String> aliasesInProjection = new ArrayList<String>();
    for (ASTProjectionElem projElemNode : node.getProjectionElemList()) {
        Node child = projElemNode.jjtGetChild(0);
        String alias = projElemNode.getAlias();
        if (alias != null) {
            // aliased projection element
            if (aliasesInProjection.contains(alias)) {
                throw new VisitorException("duplicate use of alias '" + alias + "' in projection.");
            }
            // check if alias is not previously used.
            if (result.getBindingNames().contains(alias)) {
                throw new VisitorException("projection alias '" + alias + "' was previously used");
            }
            aliasesInProjection.add(alias);
            ValueExpr valueExpr = (ValueExpr) child.jjtAccept(this, null);
            String targetName = alias;
            String sourceName = alias;
            if (child instanceof ASTVar) {
                sourceName = ((ASTVar) child).getName();
            }
            ProjectionElem elem = new ProjectionElem(sourceName, targetName);
            projElemList.addElement(elem);
            AggregateCollector collector = new AggregateCollector();
            valueExpr.visit(collector);
            if (collector.getOperators().size() > 0) {
                elem.setAggregateOperatorInExpression(true);
                for (AggregateOperator operator : collector.getOperators()) {
                    // Apply implicit grouping if necessary
                    if (group == null) {
                        group = new Group(result);
                    }
                    if (operator.equals(valueExpr)) {
                        group.addGroupElement(new GroupElem(alias, operator));
                        extension.setArg(group);
                    } else {
                        ValueExpr expr = (ValueExpr) operator.getParentNode();
                        Extension anonymousExtension = new Extension();
                        Var anonVar = createAnonVar();
                        expr.replaceChildNode(operator, anonVar);
                        anonymousExtension.addElement(new ExtensionElem(operator, anonVar.getName()));
                        anonymousExtension.setArg(result);
                        result = anonymousExtension;
                        group.addGroupElement(new GroupElem(anonVar.getName(), operator));
                    }
                    if (!existingGroup) {
                        result = group;
                    }
                }
            }
            // add extension element reference to the projection element and
            // to
            // the extension
            ExtensionElem extElem = new ExtensionElem(valueExpr, alias);
            extension.addElement(extElem);
            elem.setSourceExpression(extElem);
        } else if (child instanceof ASTVar) {
            Var projVar = (Var) child.jjtAccept(this, null);
            ProjectionElem elem = new ProjectionElem(projVar.getName());
            projElemList.addElement(elem);
            VarCollector whereClauseVarCollector = new VarCollector();
            result.visit(whereClauseVarCollector);
            if (!whereClauseVarCollector.collectedVars.contains(projVar)) {
                ExtensionElem extElem = new ExtensionElem(projVar, projVar.getName());
                extension.addElement(extElem);
                elem.setSourceExpression(extElem);
            }
        } else {
            throw new IllegalStateException("required alias for non-Var projection elements not found");
        }
    }
    if (!extension.getElements().isEmpty()) {
        if (orderClause != null) {
            // Extensions produced by SELECT expressions should be nested
            // inside
            // the ORDER BY clause, to make sure
            // sorting can work on the newly introduced variable. See
            // SES-892
            // and SES-1809.
            TupleExpr arg = orderClause.getArg();
            extension.setArg(arg);
            orderClause.setArg(extension);
            result = orderClause;
        } else {
            extension.setArg(result);
            result = extension;
        }
    }
    result = new Projection(result, projElemList);
    if (group != null) {
        for (ProjectionElem elem : projElemList.getElements()) {
            if (!elem.hasAggregateOperatorInExpression()) {
                Set<String> groupNames = group.getBindingNames();
                ExtensionElem extElem = elem.getSourceExpression();
                if (extElem != null) {
                    ValueExpr expr = extElem.getExpr();
                    VarCollector collector = new VarCollector();
                    expr.visit(collector);
                    for (Var var : collector.getCollectedVars()) {
                        if (!groupNames.contains(var.getName())) {
                            throw new VisitorException("variable '" + var.getName() + "' in projection not present in GROUP BY.");
                        }
                    }
                } else {
                    if (!groupNames.contains(elem.getTargetName())) {
                        throw new VisitorException("variable '" + elem.getTargetName() + "' in projection not present in GROUP BY.");
                    } else if (!groupNames.contains(elem.getSourceName())) {
                        throw new VisitorException("variable '" + elem.getSourceName() + "' in projection not present in GROUP BY.");
                    }
                }
            }
        }
    }
    if (node.isSubSelect()) {
        // set context var at the level of the projection. This allows us
        // to distinguish named graphs selected in the
        // outer query from named graphs selected as part of the sub-select.
        ((Projection) result).setProjectionContext(graphPattern.getContextVar());
    }
    if (node.isDistinct()) {
        result = new Distinct(result);
    } else if (node.isReduced()) {
        result = new Reduced(result);
    }
    return result;
}
Also used : ProjectionElemList(org.eclipse.rdf4j.query.algebra.ProjectionElemList) Group(org.eclipse.rdf4j.query.algebra.Group) Var(org.eclipse.rdf4j.query.algebra.Var) QueryModelNode(org.eclipse.rdf4j.query.algebra.QueryModelNode) IsBNode(org.eclipse.rdf4j.query.algebra.IsBNode) ArrayList(java.util.ArrayList) GroupElem(org.eclipse.rdf4j.query.algebra.GroupElem) ExtensionElem(org.eclipse.rdf4j.query.algebra.ExtensionElem) Projection(org.eclipse.rdf4j.query.algebra.Projection) MultiProjection(org.eclipse.rdf4j.query.algebra.MultiProjection) Reduced(org.eclipse.rdf4j.query.algebra.Reduced) Distinct(org.eclipse.rdf4j.query.algebra.Distinct) AggregateOperator(org.eclipse.rdf4j.query.algebra.AggregateOperator) Order(org.eclipse.rdf4j.query.algebra.Order) ValueExpr(org.eclipse.rdf4j.query.algebra.ValueExpr) TupleExpr(org.eclipse.rdf4j.query.algebra.TupleExpr) Extension(org.eclipse.rdf4j.query.algebra.Extension) ProjectionElem(org.eclipse.rdf4j.query.algebra.ProjectionElem)

Example 2 with ProjectionElemList

use of org.eclipse.rdf4j.query.algebra.ProjectionElemList in project rdf4j by eclipse.

the class TupleExprBuilder method visit.

@Override
public TupleExpr visit(ASTConstruct node, Object data) throws VisitorException {
    TupleExpr result = (TupleExpr) data;
    // Collect construct triples
    graphPattern = new GraphPattern();
    super.visit(node, null);
    TupleExpr constructExpr = graphPattern.buildTupleExpr();
    // Retrieve all StatementPatterns from the construct expression
    List<StatementPattern> statementPatterns = StatementPatternCollector.process(constructExpr);
    if (constructExpr instanceof Filter) {
        // sameTerm filters in construct (this can happen when there's a
        // cyclic
        // path defined, see SES-1685 and SES-2104)
        // we remove the sameTerm filters by simply replacing all mapped
        // variable occurrences
        Set<SameTerm> sameTermConstraints = getSameTermConstraints((Filter) constructExpr);
        statementPatterns = replaceSameTermVars(statementPatterns, sameTermConstraints);
    }
    Set<Var> constructVars = getConstructVars(statementPatterns);
    VarCollector whereClauseVarCollector = new VarCollector();
    result.visit(whereClauseVarCollector);
    // Create BNodeGenerators for all anonymous variables
    // NB: preserve order for a deterministic output
    Map<Var, ExtensionElem> extElemMap = new LinkedHashMap<Var, ExtensionElem>();
    for (Var var : constructVars) {
        if (var.isAnonymous() && !extElemMap.containsKey(var)) {
            ValueExpr valueExpr;
            if (var.hasValue()) {
                valueExpr = new ValueConstant(var.getValue());
            } else {
                valueExpr = new BNodeGenerator();
            }
            extElemMap.put(var, new ExtensionElem(valueExpr, var.getName()));
        } else if (!whereClauseVarCollector.collectedVars.contains(var)) {
            // non-anon var in construct clause not present in where clause
            if (!extElemMap.containsKey(var)) {
                // assign non-anonymous vars not present in where clause as
                // extension elements. This is necessary to make external
                // binding
                // assingnment possible (see SES-996)
                extElemMap.put(var, new ExtensionElem(var, var.getName()));
            }
        }
    }
    if (!extElemMap.isEmpty()) {
        result = new Extension(result, extElemMap.values());
    }
    // Create a Projection for each StatementPattern in the constructor
    List<ProjectionElemList> projList = new ArrayList<ProjectionElemList>();
    for (StatementPattern sp : statementPatterns) {
        ProjectionElemList projElemList = new ProjectionElemList();
        projElemList.addElement(new ProjectionElem(sp.getSubjectVar().getName(), "subject"));
        projElemList.addElement(new ProjectionElem(sp.getPredicateVar().getName(), "predicate"));
        projElemList.addElement(new ProjectionElem(sp.getObjectVar().getName(), "object"));
        if (sp.getContextVar() != null) {
            projElemList.addElement(new ProjectionElem(sp.getContextVar().getName(), "context"));
        }
        projList.add(projElemList);
    }
    if (projList.size() == 1) {
        result = new Projection(result, projList.get(0));
    } else if (projList.size() > 1) {
        result = new MultiProjection(result, projList);
    } else {
        // Empty constructor
        result = new EmptySet();
    }
    return new Reduced(result);
}
Also used : ProjectionElemList(org.eclipse.rdf4j.query.algebra.ProjectionElemList) Var(org.eclipse.rdf4j.query.algebra.Var) EmptySet(org.eclipse.rdf4j.query.algebra.EmptySet) ArrayList(java.util.ArrayList) ExtensionElem(org.eclipse.rdf4j.query.algebra.ExtensionElem) Projection(org.eclipse.rdf4j.query.algebra.Projection) MultiProjection(org.eclipse.rdf4j.query.algebra.MultiProjection) Reduced(org.eclipse.rdf4j.query.algebra.Reduced) LinkedHashMap(java.util.LinkedHashMap) StatementPattern(org.eclipse.rdf4j.query.algebra.StatementPattern) MultiProjection(org.eclipse.rdf4j.query.algebra.MultiProjection) ValueExpr(org.eclipse.rdf4j.query.algebra.ValueExpr) SameTerm(org.eclipse.rdf4j.query.algebra.SameTerm) TupleExpr(org.eclipse.rdf4j.query.algebra.TupleExpr) Extension(org.eclipse.rdf4j.query.algebra.Extension) BNodeGenerator(org.eclipse.rdf4j.query.algebra.BNodeGenerator) Filter(org.eclipse.rdf4j.query.algebra.Filter) ValueConstant(org.eclipse.rdf4j.query.algebra.ValueConstant) ProjectionElem(org.eclipse.rdf4j.query.algebra.ProjectionElem)

Example 3 with ProjectionElemList

use of org.eclipse.rdf4j.query.algebra.ProjectionElemList in project rdf4j by eclipse.

the class SPARQLParserTest method testParseWildcardSubselectInUpdate.

/**
 * Verify that an INSERT with a subselect using a wildcard correctly adds vars to projection
 * @see <a href="https://github.com/eclipse/rdf4j/issues/686">#686</a>
 */
@Test
public void testParseWildcardSubselectInUpdate() throws Exception {
    StringBuilder update = new StringBuilder();
    update.append("INSERT { <urn:a> <urn:b> <urn:c> . } WHERE { SELECT * {?s ?p ?o } }");
    ParsedUpdate parsedUpdate = parser.parseUpdate(update.toString(), null);
    List<UpdateExpr> exprs = parsedUpdate.getUpdateExprs();
    assertEquals(1, exprs.size());
    UpdateExpr expr = exprs.get(0);
    assertTrue(expr instanceof Modify);
    Modify m = (Modify) expr;
    TupleExpr whereClause = m.getWhereExpr();
    assertTrue(whereClause instanceof Projection);
    ProjectionElemList projectionElemList = ((Projection) whereClause).getProjectionElemList();
    assertNotNull(projectionElemList);
    List<ProjectionElem> elements = projectionElemList.getElements();
    assertNotNull(elements);
    assertEquals("projection should contain all three variables", 3, elements.size());
}
Also used : ProjectionElemList(org.eclipse.rdf4j.query.algebra.ProjectionElemList) ParsedUpdate(org.eclipse.rdf4j.query.parser.ParsedUpdate) UpdateExpr(org.eclipse.rdf4j.query.algebra.UpdateExpr) Projection(org.eclipse.rdf4j.query.algebra.Projection) Modify(org.eclipse.rdf4j.query.algebra.Modify) TupleExpr(org.eclipse.rdf4j.query.algebra.TupleExpr) ProjectionElem(org.eclipse.rdf4j.query.algebra.ProjectionElem) Test(org.junit.Test)

Example 4 with ProjectionElemList

use of org.eclipse.rdf4j.query.algebra.ProjectionElemList in project rdf4j by eclipse.

the class AbstractQueryBuilder method multiProjection.

private UnaryTupleOperator multiProjection() {
    MultiProjection aProjection = new MultiProjection();
    Extension aExt = null;
    for (StatementPattern aPattern : mProjectionPatterns) {
        ProjectionElemList aList = new ProjectionElemList();
        aList.addElement(new ProjectionElem(aPattern.getSubjectVar().getName(), "subject"));
        aList.addElement(new ProjectionElem(aPattern.getPredicateVar().getName(), "predicate"));
        aList.addElement(new ProjectionElem(aPattern.getObjectVar().getName(), "object"));
        if (aPattern.getSubjectVar().hasValue()) {
            if (aExt == null) {
                aExt = new Extension();
            }
            aExt.addElements(new ExtensionElem(new ValueConstant(aPattern.getSubjectVar().getValue()), aPattern.getSubjectVar().getName()));
        }
        if (aPattern.getPredicateVar().hasValue()) {
            if (aExt == null) {
                aExt = new Extension();
            }
            aExt.addElements(new ExtensionElem(new ValueConstant(aPattern.getPredicateVar().getValue()), aPattern.getPredicateVar().getName()));
        }
        if (aPattern.getObjectVar().hasValue()) {
            if (aExt == null) {
                aExt = new Extension();
            }
            aExt.addElements(new ExtensionElem(new ValueConstant(aPattern.getObjectVar().getValue()), aPattern.getObjectVar().getName()));
        }
        aProjection.addProjection(aList);
    }
    if (aExt != null) {
        aProjection.setArg(aExt);
    }
    return aProjection;
}
Also used : Extension(org.eclipse.rdf4j.query.algebra.Extension) ProjectionElemList(org.eclipse.rdf4j.query.algebra.ProjectionElemList) StatementPattern(org.eclipse.rdf4j.query.algebra.StatementPattern) ValueConstant(org.eclipse.rdf4j.query.algebra.ValueConstant) ExtensionElem(org.eclipse.rdf4j.query.algebra.ExtensionElem) MultiProjection(org.eclipse.rdf4j.query.algebra.MultiProjection) ProjectionElem(org.eclipse.rdf4j.query.algebra.ProjectionElem)

Example 5 with ProjectionElemList

use of org.eclipse.rdf4j.query.algebra.ProjectionElemList in project rdf4j by eclipse.

the class SerqlTupleExprRenderer method render.

/**
 * @inheritDoc
 */
public String render(TupleExpr theExpr) throws Exception {
    theExpr.visit(this);
    if (mBuffer.length() > 0) {
        return mBuffer.toString();
    }
    boolean aFirst = true;
    StringBuffer aQuery = new StringBuffer();
    if (!mProjection.isEmpty()) {
        if (isSelect()) {
            aQuery.append("select ");
        } else {
            aQuery.append("construct ");
        }
        if (mDistinct) {
            aQuery.append("distinct ");
        }
        if (mReduced && isSelect()) {
            aQuery.append("reduced ");
        }
        aFirst = true;
        if (!isSelect()) {
            aQuery.append("\n");
        }
        for (ProjectionElemList aList : mProjection) {
            if (isSPOElemList(aList)) {
                if (!aFirst) {
                    aQuery.append(",\n");
                } else {
                    aFirst = false;
                }
                aQuery.append(renderPattern(toStatementPattern(aList)));
            } else {
                for (ProjectionElem aElem : aList.getElements()) {
                    if (!aFirst) {
                        aQuery.append(", ");
                    } else {
                        aFirst = false;
                    }
                    aQuery.append(mExtensions.containsKey(aElem.getSourceName()) ? mValueExprRenderer.render(mExtensions.get(aElem.getSourceName())) : aElem.getSourceName());
                    if (!aElem.getSourceName().equals(aElem.getTargetName()) || (mExtensions.containsKey(aElem.getTargetName()) && !mExtensions.containsKey(aElem.getSourceName()))) {
                        aQuery.append(" as ").append(mExtensions.containsKey(aElem.getTargetName()) ? mValueExprRenderer.render(mExtensions.get(aElem.getTargetName())) : aElem.getTargetName());
                    }
                }
            }
        }
        aQuery.append("\n");
    }
    if (mJoinBuffer.length() > 0) {
        mJoinBuffer.setCharAt(mJoinBuffer.lastIndexOf(","), ' ');
        aQuery.append("from\n");
        aQuery.append(mJoinBuffer);
    }
    if (mFilter != null) {
        aQuery.append("where\n");
        aQuery.append(mValueExprRenderer.render(mFilter));
    }
    if (!mOrdering.isEmpty()) {
        aQuery.append("\norder by ");
        aFirst = true;
        for (OrderElem aOrder : mOrdering) {
            if (!aFirst) {
                aQuery.append(", ");
            } else {
                aFirst = false;
            }
            aQuery.append(aOrder.getExpr());
            aQuery.append(" ");
            if (aOrder.isAscending()) {
                aQuery.append("asc");
            } else {
                aQuery.append("desc");
            }
        }
    }
    if (mLimit != -1) {
        aQuery.append("\nlimit ").append(mLimit);
    }
    if (mOffset != -1) {
        aQuery.append("\noffset ").append(mOffset);
    }
    return aQuery.toString();
}
Also used : ProjectionElemList(org.eclipse.rdf4j.query.algebra.ProjectionElemList) OrderElem(org.eclipse.rdf4j.query.algebra.OrderElem) ProjectionElem(org.eclipse.rdf4j.query.algebra.ProjectionElem)

Aggregations

ProjectionElem (org.eclipse.rdf4j.query.algebra.ProjectionElem)12 ProjectionElemList (org.eclipse.rdf4j.query.algebra.ProjectionElemList)12 Projection (org.eclipse.rdf4j.query.algebra.Projection)9 Extension (org.eclipse.rdf4j.query.algebra.Extension)8 MultiProjection (org.eclipse.rdf4j.query.algebra.MultiProjection)8 TupleExpr (org.eclipse.rdf4j.query.algebra.TupleExpr)8 ExtensionElem (org.eclipse.rdf4j.query.algebra.ExtensionElem)7 ValueExpr (org.eclipse.rdf4j.query.algebra.ValueExpr)6 Var (org.eclipse.rdf4j.query.algebra.Var)6 Distinct (org.eclipse.rdf4j.query.algebra.Distinct)5 Reduced (org.eclipse.rdf4j.query.algebra.Reduced)5 ArrayList (java.util.ArrayList)4 StatementPattern (org.eclipse.rdf4j.query.algebra.StatementPattern)4 ValueConstant (org.eclipse.rdf4j.query.algebra.ValueConstant)4 BNodeGenerator (org.eclipse.rdf4j.query.algebra.BNodeGenerator)3 EmptySet (org.eclipse.rdf4j.query.algebra.EmptySet)3 HashMap (java.util.HashMap)2 OrderElem (org.eclipse.rdf4j.query.algebra.OrderElem)2 LinkedHashMap (java.util.LinkedHashMap)1 IRI (org.eclipse.rdf4j.model.IRI)1