-
Notifications
You must be signed in to change notification settings - Fork 2
Add minimal next SELECT/ASK executor #491
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
abdessamad-abdoun
merged 5 commits into
feature/corese-next
from
feature/490-minimal-select-ask-executor
Jul 16, 2026
Merged
Changes from 4 commits
Commits
Show all changes
5 commits
Select commit
Hold shift + click to select a range
0a81833
Add minimal next SELECT ASK executor
remiceres 1da9a71
Keep default KGRAM process visitor
remiceres 0aca181
Add invalid query execution plan exception
remiceres 513fcb4
Revert "Add invalid query execution plan exception"
remiceres 4ec36ed
Add unit tests RdfTermMatcher
abdessamad-abdoun File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
112 changes: 112 additions & 0 deletions
112
...ava/fr/inria/corese/core/next/query/impl/sparql/execution/NextSparqlPipelineExecutor.java
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,112 @@ | ||
| package fr.inria.corese.core.next.query.impl.sparql.execution; | ||
|
|
||
| import fr.inria.corese.core.next.query.api.exception.QueryEvaluationException; | ||
| import fr.inria.corese.core.next.query.api.result.TupleQueryResult; | ||
| import fr.inria.corese.core.next.query.impl.parser.SparqlParser; | ||
| import fr.inria.corese.core.next.query.impl.result.CoreseTupleQueryResult; | ||
| import fr.inria.corese.core.next.query.impl.sparql.ast.AskQueryAst; | ||
| import fr.inria.corese.core.next.query.impl.sparql.ast.QueryAst; | ||
| import fr.inria.corese.core.next.query.impl.sparql.ast.SelectQueryAst; | ||
| import fr.inria.corese.core.next.query.impl.sparql.bridge.CoreseAstQueryBuilder; | ||
| import fr.inria.corese.core.next.query.kgram.core.Eval; | ||
| import fr.inria.corese.core.next.query.kgram.core.Mappings; | ||
| import fr.inria.corese.core.next.query.kgram.core.Query; | ||
| import fr.inria.corese.core.next.query.kgram.core.SparqlException; | ||
| import fr.inria.corese.core.next.query.kgram.execution.RdfTermMatcher; | ||
| import fr.inria.corese.core.next.query.kgram.execution.SparqlKgramEvaluator; | ||
| import fr.inria.corese.core.next.query.kgram.tool.StorageManagerProducer; | ||
| import fr.inria.corese.core.next.storagemanager.api.StorageManager; | ||
|
|
||
| import java.util.Objects; | ||
|
|
||
| /** | ||
| * Internal executor for the first autonomous Corese-next SPARQL query path. | ||
| * | ||
| * <p>This class is intentionally small and transitional. It validates the | ||
| * autonomous execution path:</p> | ||
| * | ||
| * <pre> | ||
| * SPARQL string -> next parser -> next AST -> next KGRAM -> StorageManagerProducer -> StorageManager | ||
| * </pre> | ||
| * | ||
| * <p>Only simple SELECT and ASK execution are supported here. A stable public | ||
| * query API, graph query execution, updates, and advanced SPARQL 1.1 runtime | ||
| * features still need to be designed separately.</p> | ||
| */ | ||
| public final class NextSparqlPipelineExecutor { | ||
|
|
||
| private final StorageManager storage; | ||
| private final SparqlParser parser; | ||
| private final CoreseAstQueryBuilder queryBuilder; | ||
|
|
||
| /** | ||
| * Creates an executor backed by the given next storage manager. | ||
| * | ||
| * @param storage storage manager used by {@link StorageManagerProducer} to | ||
| * read RDF statements during KGRAM evaluation | ||
| */ | ||
| public NextSparqlPipelineExecutor(StorageManager storage) { | ||
| this(storage, new SparqlParser(), new CoreseAstQueryBuilder()); | ||
| } | ||
|
|
||
| /** | ||
| * Creates an executor with explicit collaborators. | ||
| * | ||
| * <p>This constructor is package-private so tests can inject parser or bridge | ||
| * variants without exposing these transitional wiring details as public API.</p> | ||
| */ | ||
| NextSparqlPipelineExecutor( | ||
| StorageManager storage, | ||
| SparqlParser parser, | ||
| CoreseAstQueryBuilder queryBuilder) { | ||
| this.storage = Objects.requireNonNull(storage, "storage"); | ||
| this.parser = Objects.requireNonNull(parser, "parser"); | ||
| this.queryBuilder = Objects.requireNonNull(queryBuilder, "queryBuilder"); | ||
| } | ||
|
|
||
| /** | ||
| * Evaluates a SELECT query through the autonomous next pipeline. | ||
| * | ||
| * @param sparql SPARQL query string to parse and evaluate | ||
| * @return tuple result backed by the KGRAM mappings produced from next storage | ||
| * @throws IllegalArgumentException when the query is not a SELECT query | ||
| * @throws QueryEvaluationException when KGRAM evaluation fails | ||
| */ | ||
| public TupleQueryResult evaluateTuple(String sparql) { | ||
| QueryAst ast = parser.parse(sparql); | ||
| if (!(ast instanceof SelectQueryAst select)) { | ||
| throw new IllegalArgumentException("Tuple evaluation requires a SELECT query, got: " | ||
| + ast.getClass().getSimpleName()); | ||
| } | ||
| return new CoreseTupleQueryResult(evaluate(queryBuilder.toNextQuery(select))); | ||
| } | ||
|
|
||
| /** | ||
| * Evaluates an ASK query through the autonomous next pipeline. | ||
| * | ||
| * @param sparql SPARQL query string to parse and evaluate | ||
| * @return {@code true} when at least one mapping matches the ASK pattern | ||
| * @throws IllegalArgumentException when the query is not an ASK query | ||
| * @throws QueryEvaluationException when KGRAM evaluation fails | ||
| */ | ||
| public boolean evaluateBoolean(String sparql) { | ||
| QueryAst ast = parser.parse(sparql); | ||
| if (!(ast instanceof AskQueryAst ask)) { | ||
| throw new IllegalArgumentException("Boolean evaluation requires an ASK query, got: " | ||
| + ast.getClass().getSimpleName()); | ||
| } | ||
| return evaluate(queryBuilder.toNextQuery(ask)).size() > 0; | ||
| } | ||
|
|
||
| private Mappings evaluate(Query query) { | ||
| try { | ||
| Eval eval = Eval.create( | ||
| new StorageManagerProducer(storage), | ||
| new SparqlKgramEvaluator(), | ||
| new RdfTermMatcher()); | ||
| return eval.query(query); | ||
| } catch (SparqlException e) { | ||
| throw new QueryEvaluationException("Failed to evaluate query with the next pipeline: " + e.getMessage(), e); | ||
| } | ||
| } | ||
| } |
63 changes: 63 additions & 0 deletions
63
src/main/java/fr/inria/corese/core/next/query/kgram/execution/RdfTermMatcher.java
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,63 @@ | ||
| package fr.inria.corese.core.next.query.kgram.execution; | ||
|
|
||
| import fr.inria.corese.core.next.query.kgram.api.core.Edge; | ||
| import fr.inria.corese.core.next.query.kgram.api.core.Node; | ||
| import fr.inria.corese.core.next.query.kgram.api.query.Environment; | ||
| import fr.inria.corese.core.next.query.kgram.api.query.Matcher; | ||
|
|
||
| /** | ||
| * Matcher for RDF term comparisons during KGRAM graph pattern execution. | ||
| * | ||
| * <p>This implementation follows the strict RDF-term matching needed by SPARQL | ||
| * graph pattern evaluation: constants must match the candidate RDF term, | ||
| * unbound variables can bind to any candidate term, and already-bound variables | ||
| * must keep the same value.</p> | ||
| * | ||
| * <p>It intentionally does not perform entailment, type subsumption, or | ||
| * {@code owl:sameAs} expansion. Those semantics should be added explicitly, | ||
| * either by extending this matcher or by introducing a dedicated matcher.</p> | ||
| */ | ||
| public final class RdfTermMatcher implements Matcher { | ||
|
|
||
| private int mode = Matcher.UNDEF; | ||
|
|
||
| @Override | ||
| public boolean match(Edge query, Edge target, Environment environment) { | ||
| return match(query.getNode(0), target.getNode(0), environment) | ||
| && match(query.getNode(1), target.getNode(1), environment) | ||
| && match(predicateNode(query), target.getEdgeNode(), environment); | ||
| } | ||
|
|
||
| @Override | ||
| public boolean match(Node query, Node target, Environment environment) { | ||
| // Null is an absent KGRAM node, not a wildcard. Wildcards are represented by unbound variables. | ||
| if (query == null || target == null) { | ||
| return query == target; | ||
| } | ||
| if (query.isVariable()) { | ||
| Node bound = environment == null ? null : environment.getNode(query); | ||
| return bound == null || bound.match(target); | ||
| } | ||
| return query.match(target); | ||
| } | ||
|
|
||
| @Override | ||
| public boolean same(Node queryNode, Node left, Node right, Environment environment) { | ||
| // queryNode is unused for strict RDF-term equality, but richer matchers may need it. | ||
| return left != null && left.same(right); | ||
| } | ||
|
|
||
| @Override | ||
| public int getMode() { | ||
| return mode; | ||
| } | ||
|
|
||
| @Override | ||
| public void setMode(int mode) { | ||
| this.mode = mode; | ||
| } | ||
|
|
||
| private static Node predicateNode(Edge edge) { | ||
| return edge.getEdgeVariable() == null ? edge.getEdgeNode() : edge.getEdgeVariable(); | ||
| } | ||
| } |
58 changes: 58 additions & 0 deletions
58
src/main/java/fr/inria/corese/core/next/query/kgram/execution/SparqlKgramEvaluator.java
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,58 @@ | ||
| package fr.inria.corese.core.next.query.kgram.execution; | ||
|
|
||
| import fr.inria.corese.core.next.query.kgram.api.query.Environment; | ||
| import fr.inria.corese.core.next.query.kgram.api.query.Evaluator; | ||
| import fr.inria.corese.core.next.query.kgram.api.query.Producer; | ||
| import fr.inria.corese.core.next.query.kgram.core.Eval; | ||
|
|
||
| /** | ||
| * KGRAM evaluator for SPARQL query execution. | ||
| * | ||
| * <p>KGRAM requires an {@link Evaluator} even for simple basic graph patterns. | ||
| * This implementation currently covers expression-free graph pattern execution: | ||
| * edge enumeration is delegated to the producer, and RDF term comparison is | ||
| * delegated to the matcher.</p> | ||
| * | ||
| * <p>SPARQL expression features such as FILTER, BIND, and function calls should | ||
| * be added here when they enter the supported execution scope, so expression | ||
| * evaluation remains part of the same KGRAM runtime path.</p> | ||
| */ | ||
| public final class SparqlKgramEvaluator implements Evaluator { | ||
|
|
||
| private Mode mode = Mode.KGRAM_MODE; | ||
|
|
||
| @Override | ||
| public Mode getMode() { | ||
| return mode; | ||
| } | ||
|
|
||
| @Override | ||
| public void setMode(Mode mode) { | ||
| this.mode = mode; | ||
| } | ||
|
|
||
| @Override | ||
| public void setProducer(Producer producer) { | ||
| // Expression-free graph pattern execution does not need producer state here. | ||
| } | ||
|
|
||
| @Override | ||
| public void setKGRAM(Eval eval) { | ||
| // Eval is driven by the caller for the currently supported execution scope. | ||
| } | ||
|
|
||
| @Override | ||
| public void start(Environment environment) { | ||
| // Graph pattern execution currently needs no evaluator-side initialization. | ||
| } | ||
|
|
||
| @Override | ||
| public void finish(Environment environment) { | ||
| // Graph pattern execution currently needs no evaluator-side cleanup. | ||
| } | ||
|
|
||
| @Override | ||
| public void init(Environment environment) { | ||
| // Expression evaluation state will be initialized here when supported. | ||
| } | ||
| } |
8 changes: 8 additions & 0 deletions
8
src/main/java/fr/inria/corese/core/next/query/kgram/execution/package-info.java
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,8 @@ | ||
| /** | ||
| * Minimal runtime collaborators used to execute Corese-next queries with KGRAM. | ||
| * | ||
| * <p>This package contains execution components, not parser or storage helpers. | ||
| * The current implementations deliberately cover the first autonomous SELECT/ASK | ||
| * path and document their unsupported SPARQL features explicitly.</p> | ||
| */ | ||
| package fr.inria.corese.core.next.query.kgram.execution; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.