Skip to content

Commit

Permalink
GH-4811 process also optional TEs when handling BIND (#4829)
Browse files Browse the repository at this point in the history
  • Loading branch information
hmottestad authored Nov 7, 2023
2 parents a19d5c1 + 334042e commit d81918d
Show file tree
Hide file tree
Showing 3 changed files with 50 additions and 5 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,7 @@ public void addRequiredTE(TupleExpr te) {
*/
void clearRequiredTEs() {
requiredTEs.clear();
optionalTEs.clear();
}

public void addRequiredSP(Var subjVar, Var predVar, Var objVar) {
Expand Down Expand Up @@ -173,6 +174,18 @@ public void clear() {
public TupleExpr buildTupleExpr() {
TupleExpr result = buildJoinFromRequiredTEs();

result = buildOptionalTE(result);

for (ValueExpr constraint : constraints) {
result = new Filter(result, constraint);
}
return result;
}

/**
* Build optionals to the supplied TE
*/
public TupleExpr buildOptionalTE(TupleExpr result) {
for (Map.Entry<TupleExpr, List<ValueExpr>> entry : optionalTEs) {
List<ValueExpr> constraints = entry.getValue();
if (constraints != null && !constraints.isEmpty()) {
Expand All @@ -186,11 +199,6 @@ public TupleExpr buildTupleExpr() {
result = new LeftJoin(result, entry.getKey());
}
}

for (ValueExpr constraint : constraints) {
result = new Filter(result, constraint);
}

return result;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2378,6 +2378,8 @@ public Object visit(ASTBind node, Object data) throws VisitorException {

// get a tupleExpr that represents the basic graph pattern, sofar.
TupleExpr arg = graphPattern.buildJoinFromRequiredTEs();
// apply optionals, if any
arg = graphPattern.buildOptionalTE(arg);

// check if alias is not previously used in the BGP
if (arg.getBindingNames().contains(alias)) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -266,6 +266,41 @@ public void testServiceGraphPatternChopping() throws Exception {

}

@Test
public void testOtionalBindCoalesce() throws Exception {
StringBuilder qb = new StringBuilder();
qb.append("SELECT ?result \n");
qb.append("WHERE { \n");
qb.append("OPTIONAL {\n" +
" OPTIONAL {\n" +
" BIND(\"value\" AS ?foo)\n" +
" }\n" +
" BIND(COALESCE(?foo, \"no value\") AS ?result)\n" +
" }");
qb.append(" } ");

ASTQueryContainer qc = SyntaxTreeBuilder.parseQuery(qb.toString());
TupleExpr result = builder.visit(qc, null);
String expected = "Projection\n" +
" ProjectionElemList\n" +
" ProjectionElem \"result\"\n" +
" LeftJoin\n" +
" SingletonSet\n" +
" Extension\n" +
" LeftJoin\n" +
" SingletonSet\n" +
" Extension\n" +
" SingletonSet\n" +
" ExtensionElem (foo)\n" +
" ValueConstant (value=\"value\")\n" +
" ExtensionElem (result)\n" +
" Coalesce\n" +
" Var (name=foo)\n" +
" ValueConstant (value=\"no value\")\n";
assertEquals(expected.replace("\r\n", "\n"), result.toString().replace("\r\n", "\n"));
// System.out.println(result);
}

private class ServiceNodeFinder extends AbstractASTVisitor {

private final List<String> graphPatterns = new ArrayList<>();
Expand Down

0 comments on commit d81918d

Please sign in to comment.