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;
}
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);
}
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());
}
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;
}
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();
}
Aggregations