Skip to content

371 [SPARQL 1.1 Update] - Parser and AST : LOAD and CLEAR Query#452

Open
MaillPierre wants to merge 7 commits into
feature/corese-nextfrom
feature/371-sparql-11-update---parser-and-ast-clear-query
Open

371 [SPARQL 1.1 Update] - Parser and AST : LOAD and CLEAR Query#452
MaillPierre wants to merge 7 commits into
feature/corese-nextfrom
feature/371-sparql-11-update---parser-and-ast-clear-query

Conversation

@MaillPierre
Copy link
Copy Markdown
Contributor

This aims to add the update queries LOAD and CLEAR.

Breaking change: A new sub-interface SPARQLQueryAst is inserted between QueryAst and the SELECT, CONSTRUCT, etc queries. A new sub-interface for update queries is also added at the same level.
Furthermore, the declaration of a prologue or of a where clause is delegated to interfaces that can be used both in updates and regular queries.

Explanation:
Update queries can be graph management queries (such as LOAD) or graph update queries (INSERT,DELETE). Graph management have no prologue and no WHERE clause.

@MaillPierre MaillPierre self-assigned this May 21, 2026
@MaillPierre MaillPierre added the Refactoring Issue created during the 2025 refactoring effort label May 21, 2026
@github-actions
Copy link
Copy Markdown

Overall Project 48.05% -0.03% 🍏
Files changed 82.07% 🍏

File Coverage
OrderByScopeValidationRule.java 100% 🍏
SparqlListener.java 100% 🍏
LoadQueryFeature.java 100% 🍏
ClearQueryFeature.java 100% 🍏
DescribeQueryAst.java 100% 🍏
ClearQueryAst.java 100% 🍏
ASTConstants.java 99.01% 🍏
AskQueryAst.java 95.92% 🍏
SparqlQueryAnalyzer.java 94.38% 🍏
GraphRefAsts.java 89.66% -10.34% 🍏
VariableScopeAnalyzer.java 88.46% 🍏
SparqlAstBuilder.java 82.69% -1.84% 🍏
SelectQueryAst.java 81.94% 🍏
GraphRefAst.java 71.01% -28.99% 🍏
LoadQueryAst.java 56% -44%
ConstructQueryAst.java 47.83% 🍏

@github-actions
Copy link
Copy Markdown

github-actions Bot commented May 21, 2026

Test Results

  413 files  + 2    413 suites  +2   21s ⏱️ +2s
2 262 tests +19  2 262 ✅ +19  0 💤 ±0  0 ❌ ±0 
2 276 runs  +19  2 276 ✅ +19  0 💤 ±0  0 ❌ ±0 

Results for commit 12a9589. ± Comparison against base commit 28151b2.

♻️ This comment has been updated with latest results.

@remiceres remiceres force-pushed the feature/371-sparql-11-update---parser-and-ast-clear-query branch from 162c4a8 to 12a9589 Compare May 22, 2026 12:04
@github-actions
Copy link
Copy Markdown

Overall Project 48.05% -0.03% 🍏
Files changed 82.07% 🍏

File Coverage
OrderByScopeValidationRule.java 100% 🍏
SparqlListener.java 100% 🍏
LoadQueryFeature.java 100% 🍏
ClearQueryFeature.java 100% 🍏
DescribeQueryAst.java 100% 🍏
ClearQueryAst.java 100% 🍏
ASTConstants.java 99.01% 🍏
AskQueryAst.java 95.92% 🍏
SparqlQueryAnalyzer.java 94.38% 🍏
GraphRefAsts.java 89.66% -10.34% 🍏
VariableScopeAnalyzer.java 88.46% 🍏
SparqlAstBuilder.java 82.69% -1.84% 🍏
SelectQueryAst.java 81.94% 🍏
GraphRefAst.java 71.01% -28.99% 🍏
LoadQueryAst.java 56% -44%
ConstructQueryAst.java 47.83% 🍏

default -> throw new QueryEvaluationException("Could not determine the type of query during parsing");
};
} else { // Update query
return switch (this.queryType) {
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.

The grammar allows chained updates, but the builder returns only one update operation.

Example:

LOAD <a> INTO GRAPH <g> ;
LOAD <b>

A fix would be to build an update request AST with a list of update operations, and create one AST node per update.

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.

@Test
void chainedLoadShouldCreateTwoUpdateOperations() {
    QueryParser parser = newParserDefault();
    String query = """
            LOAD <http://example.org/a> INTO GRAPH <http://example.org/g> ;
            LOAD <http://example.org/b>
            """;

    QueryAst queryAst = parser.parse(query);
    UpdateRequestAst update = assertInstanceOf(UpdateRequestAst.class, queryAst);

    assertEquals(2, update.operations().size());

    LoadQueryAst first = assertInstanceOf(LoadQueryAst.class, update.operations().get(0));
    assertEquals("<http://example.org/a>", first.fromClause().graph().raw());
    assertNotNull(first.toClause());
    assertEquals("<http://example.org/g>", first.toClause().graph().raw());

    LoadQueryAst second = assertInstanceOf(LoadQueryAst.class, update.operations().get(1));
    assertEquals("<http://example.org/b>", second.fromClause().graph().raw());
    assertNull(second.toClause());
}

/**
* Root interface for all queries related to the SPARQL Update queries listed in <a href="https://www.w3.org/TR/sparql11-update/">SPARQL 1.1 Update</>.
*/
public sealed interface UpdateQueryAst extends QueryAst permits LoadQueryAst, ClearQueryAst {
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.

Updates can start with BASE and PREFIX, but the update AST does not keep the prologue.

Example:

PREFIX ex: <http://example.org/>
LOAD ex:data

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.

@Test
void updateShouldKeepPrologue() {
    QueryParser parser = newParserDefault();
    String query = """
            PREFIX ex: <http://example.org/>
            LOAD ex:data
            """;

    QueryAst queryAst = parser.parse(query);
    UpdateRequestAst update = assertInstanceOf(UpdateRequestAst.class, queryAst);

    assertEquals(1, update.operations().size());
    assertTrue(update.prologue().prefixDeclarations().stream()
            .anyMatch(prefixDecl ->
                    prefixDecl.prefix().equals("ex")
                            && prefixDecl.namespace().raw().equals("http://example.org/")));

    assertInstanceOf(LoadQueryAst.class, update.operations().get(0));
}

super(builder);
}

public void exitLoad(SparqlParser.LoadContext ctx) {
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.

Add the "@OverRide" annotation above this method signature

@@ -5,10 +5,7 @@
import org.slf4j.Logger;
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.

The import org.slf4j.Logger is never used

@@ -5,10 +5,7 @@
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
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.

Remove this unused import 'org.slf4j.LoggerFactory'.

@@ -20,7 +20,7 @@ public void inlineSyntaxTest() {
VALUES ?var { "test" <http://ns.inria.fr/test> }
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.

Remove this unused import 'fr.inria.corese.core.next.query.api.exception.QueryEvaluationException'.

Comment on lines 21 to 22
}
""";
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.

Remove this unused "logger" private field.

@@ -20,7 +20,7 @@ public void inlineSyntaxTest() {
VALUES ?var { "test" <http://ns.inria.fr/test> }
}
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.

Remove this unused import 'fr.inria.corese.core.next.query.api.exception.QuerySyntaxException'.

@@ -385,7 +385,7 @@ void whereClauseAccessor() {
GroupGraphPatternAst where = new GroupGraphPatternAst(List.of(
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.

The import fr.inria.corese.core.next.query.impl.sparql.ast is never used

import java.util.ArrayList;
import java.util.List;

public record GraphRefAst(IriAst graph, boolean named, boolean all, boolean defaultGraph) {
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.

This constructor allows invalid mixed states such as an explicit graph together with named, all, or defaultGraph.
It may be safer to reject these combinations here as well.

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

Labels

Refactoring Issue created during the 2025 refactoring effort

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[SPARQL 1.1 Update] - Parser and AST : CLEAR Query [SPARQL 1.1 Update] - Parser and AST : LOAD Query

2 participants