Skip to content

Feature/384 bridge where compiler#466

Merged
abdessamad-abdoun merged 4 commits into
feature/corese-nextfrom
feature/384-bridge-where-compiler
Jun 25, 2026
Merged

Feature/384 bridge where compiler#466
abdessamad-abdoun merged 4 commits into
feature/corese-nextfrom
feature/384-bridge-where-compiler

Conversation

@abdessamad-abdoun

Copy link
Copy Markdown
Contributor

No description provided.

@abdessamad-abdoun abdessamad-abdoun self-assigned this Jun 23, 2026
@abdessamad-abdoun abdessamad-abdoun marked this pull request as draft June 23, 2026 08:42
@github-actions

Copy link
Copy Markdown
Overall Project 49.04% -0.03% 🍏
Files changed 75.31% 🍏

File Coverage
WhereCompiler.java 80.91% -19.09% 🍏
Term.java 64.3% 🍏
AstBackedEdge.java 36.21% -63.79%

@github-actions

github-actions Bot commented Jun 23, 2026

Copy link
Copy Markdown

Test Results

  424 files    424 suites   31s ⏱️
2 391 tests 2 391 ✅ 0 💤 0 ❌
2 405 runs  2 405 ✅ 0 💤 0 ❌

Results for commit 2123acc.

♻️ This comment has been updated with latest results.

@remiceres remiceres requested a review from MaillPierre June 23, 2026 09:06
@remiceres remiceres marked this pull request as ready for review June 23, 2026 09:07
* A query-side {@link Edge} produced by the WHERE compiler from a
* {@link fr.inria.corese.core.next.query.impl.sparql.ast.TriplePatternAst}.
*/
final class AstBackedEdge implements Edge {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

AstBackedEdge currently inherits the default Edge.contains(Node) implementation, which always returns false. For query edges we probably need contains() to match subject/object, otherwise some runtime logic may not see that this pattern carries these variables.

@Test
void edgeContainsSubjectAndObject() {
    Node subject = new NodeImpl(Variable.create("s"));
    Node predicate = new NodeImpl(Variable.create("p"));
    Node object = new NodeImpl(Variable.create("o"));

    AstBackedEdge edge = new AstBackedEdge(subject, predicate, object);

    assertTrue(edge.contains(subject));
    assertTrue(edge.contains(object));
}

Node endpoint = toNode(service.endpoint());
Exp endpointNode = Exp.create(Type.NODE, endpoint);
Exp body = compile(service.pattern());
Exp exp = Exp.create(Type.SERVICE, endpointNode, body);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

SERVICE is currently compiled with a plain AND body. However, next runtime seems to execute SERVICE through exp.rest().getQuery(), which is null for an AND. So the current structure looks valid in the unit test, but may not match the runtime contract expected for service execution.

Replace SERVICE(endpoint, AND(...)) by SERVICE(endpoint, QUERY(...))

@Test
void serviceRestShouldExposeAQueryForRuntime() {
    ServiceAst service = new ServiceAst(
            new IriAst("<http://example.org/>"),
            false,
            group(new BgpAst(List.of(
                    new TriplePatternAst(new VarAst("s"), new VarAst("p"), new VarAst("o"))))));

    Exp serviceExp = new WhereCompiler().compile(service);

    assertTrue(serviceExp.isService());
    assertNotNull(serviceExp.rest().getQuery(), "SERVICE runtime expects a query body");
}

Node variable = toNode(bind.variable());
Exp exp = Exp.create(Type.BIND);
exp.setFilter(filter);
exp.setNode(variable);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

BIND does not propagate the filter functional flag here. For Corese-specific expressions such as unnest or sql (not standard SPARQL), filter.isFunctional() becomes true, but exp.isFunctional() stays false, so runtime may take the non-functional execution path.

@Test
void bindShouldPropagateFunctionalFlag() {
    BindAst bind = new BindAst(
            new FunctionCallAst(new IriAst("<http://example.org/unnest>"), List.of(new VarAst("x"))),
            new VarAst("y"));

    Exp bindExp = new WhereCompiler().compile(bind);

    assertTrue(bindExp.getFilter().isFunctional());
    assertTrue(bindExp.isFunctional(), "BIND exp should propagate functional flag");
}

* {@link fr.inria.corese.core.next.query.impl.sparql.ast.TriplePatternAst}.
*/
final class AstBackedEdge implements Edge {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For variable predicates, AstBackedEdge does not expose the predicate through getEdgeVariable(). next runtime uses edge.getEdgeVariable() in query bookkeeping, so a pattern like ?s ?p ?o may not register ?p the same way as existing query edges do.

@Test
void edgeExposesVariablePredicateAsEdgeVariable() {
    Exp bgp = new WhereCompiler().compile(new BgpAst(List.of(
            new TriplePatternAst(new VarAst("s"), new VarAst("p"), new VarAst("o")))));

    Exp edgeExp = bgp.get(0);
    assertNotNull(edgeExp.getEdge().getEdgeVariable(), "variable predicate should be exposed as edge variable");
    assertTrue(edgeExp.getEdge().getEdgeVariable().isVariable());
}

@github-actions

Copy link
Copy Markdown
Overall Project 49.08% -0.02% 🍏
Files changed 79.69% 🍏

File Coverage
WhereCompiler.java 81.19% -18.81% 🍏
AstBackedEdge.java 70.83% -29.17% 🍏
Term.java 64.3% 🍏

@remiceres remiceres linked an issue Jun 24, 2026 that may be closed by this pull request

@MaillPierre MaillPierre left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Auto-approve on comment reply

}

@Override
public Node getGraph() {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should it return something ? either the default graph or the encompassing graph

SELECT * {
<a> <b> <c>
}

The <a> <b> <c> edge graph is either null of DefaultGraphURI

SELECT * {
GRAPH <g> {
<a> <b> <c>
}
}

The <a> <b> <c> edge graph is <g>

@abdessamad-abdoun abdessamad-abdoun force-pushed the feature/384-bridge-where-compiler branch from 81576ac to 32fe0bf Compare June 24, 2026 14:39
@github-actions

Copy link
Copy Markdown
Overall Project 49.16% -0.02% 🍏
Files changed 79.69% 🍏

File Coverage
WhereCompiler.java 81.19% -18.81% 🍏
AstBackedEdge.java 70.83% -29.17% 🍏
Term.java 64.3% 🍏

@abdessamad-abdoun abdessamad-abdoun force-pushed the feature/384-bridge-where-compiler branch from 32fe0bf to 2123acc Compare June 25, 2026 08:07
@github-actions

Copy link
Copy Markdown
Overall Project 49.17% -0.02% 🍏
Files changed 79.69% 🍏

File Coverage
WhereCompiler.java 81.19% -18.81% 🍏
AstBackedEdge.java 70.83% -29.17% 🍏
Term.java 64.3% 🍏

@abdessamad-abdoun abdessamad-abdoun merged commit 0650dff into feature/corese-next Jun 25, 2026
1 check passed
private Exp compileService(ServiceAst service) {
Node endpoint = toNode(service.endpoint());
Exp endpointNode = Exp.create(Type.NODE, endpoint);
Query body = Query.create(compile(service.pattern()));

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

SERVICE now wraps its body in a Query, which fixes exp.rest().getQuery(), but the body query is still not marked as a service query. In the legacy compiler we explicitly call q.setService(true), and that matters because non-service queries may inherit outer FROM / NAMED clauses. So the current shape may still execute SERVICE with the wrong dataset later. For consistency with the legacy compiler, it may also be worth propagating the SILENT flag to the body query.

@Test
void serviceBodyShouldBeMarkedAsServiceQuery() {
    ServiceAst service = new ServiceAst(
            new IriAst("<http://example.org/>"),
            false,
            group(new BgpAst(List.of(
                    new TriplePatternAst(new VarAst("s"), new VarAst("p"), new VarAst("o"))))));

    Exp serviceExp = new WhereCompiler().compile(service);

    assertTrue(serviceExp.rest().getQuery().isService(),
            "SERVICE body query should be marked as service");
}
private Exp compileService(ServiceAst service) {
    Node endpoint = toNode(service.endpoint());
    Exp endpointNode = Exp.create(Type.NODE, endpoint);
    Query body = Query.create(compile(service.pattern()));
    body.setService(true);
    body.setSilent(service.silent());
    Exp exp = Exp.create(Type.SERVICE, endpointNode, body);
    exp.setSilent(service.silent());
    return exp;
}

@github-actions

Copy link
Copy Markdown
Overall Project 49.17% -0.02% 🍏
Files changed 80.61% 🍏

File Coverage
WhereCompiler.java 81.19% -18.81% 🍏
AstBackedEdge.java 75.7% -24.3% 🍏
Term.java 64.3% 🍏

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[BRIDGE] WHERE Compiler

3 participants