Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
package fr.inria.corese.core.next.query.impl.sparql.bridge;

import fr.inria.corese.core.next.query.impl.sparql.ast.ConstraintAst;
import fr.inria.corese.core.next.query.impl.sparql.ast.FilterAst;
import fr.inria.corese.core.next.query.impl.sparql.ast.TermAst;
import fr.inria.corese.core.next.query.impl.sparql.ast.*;
import fr.inria.corese.core.next.query.kgram.api.core.Filter;
import fr.inria.corese.core.next.query.kgram.core.Exp;
import fr.inria.corese.core.next.query.kgram.core.Query;

import java.util.Objects;

Expand All @@ -15,6 +15,40 @@ public final class CoreseAstQueryBuilder {
public CoreseAstQueryBuilder() {
}

private final WhereCompiler whereCompiler = new WhereCompiler();

/**
* Builds a KGRAM {@link Query} from a SPARQL {@code ASK} query AST.
*/
public Query toQuery(AskQueryAst ask) {
Objects.requireNonNull(ask, "ask");
rejectUnsupportedClauses(ask);

Exp body = whereCompiler.compile(ask.whereClause());
Query query = Query.create(body);
query.setAsk(true);

return query;
}

private static void rejectUnsupportedClauses(AskQueryAst ask) {
DatasetClauseAst dataset = ask.datasetClause();
if (!dataset.graphs().isEmpty() || !dataset.namedGraphs().isEmpty()) {
throw new UnsupportedOperationException(
"FROM / FROM NAMED is not supported yet for ASK (dataset handling is a follow-up)");
}
if (!ask.valuesClause().mappings().isEmpty()) {
throw new UnsupportedOperationException(
"Inline VALUES is not supported yet for ASK (values handling is a follow-up)");
}
SolutionModifierAst mod = ask.solutionModifier();
if (mod.hasOrderBy() || mod.hasGroupBy() || mod.hasHaving()
|| mod.hasLimit() || mod.hasOffset() || mod.distinct() || mod.reduced()) {
throw new UnsupportedOperationException(
"Solution modifiers (ORDER BY, GROUP BY, HAVING, LIMIT, OFFSET, DISTINCT, REDUCED) are not supported for ASK");
}
}

/**
* Converts a SPARQL {@code FILTER} clause by converting {@link FilterAst#operator()} the same way as
* {@link #toNextFilter(TermAst)}.
Expand Down Expand Up @@ -44,4 +78,4 @@ public Filter toNextFilter(ConstraintAst filterExpression) {
return SparqlAstToExpression.toNextFilter(filterExpression);
}

}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,9 @@
import fr.inria.corese.core.next.query.kgram.api.core.Filter;
import fr.inria.corese.core.next.util.StringUtils;
import fr.inria.corese.core.sparql.datatype.RDF;
import fr.inria.corese.core.sparql.triple.parser.Constant;
import fr.inria.corese.core.sparql.triple.parser.Expression;
import fr.inria.corese.core.sparql.triple.parser.Processor;
import fr.inria.corese.core.sparql.triple.parser.Term;
import fr.inria.corese.core.sparql.triple.parser.Variable;
import fr.inria.corese.core.sparql.triple.parser.*;

import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.Optional;
Expand Down Expand Up @@ -60,10 +57,23 @@ public static Filter toNextFilter(FilterAst filterClause) {
*/
public static Filter toNextFilter(TermAst filterExpression) {
Expression exprTree = convert(filterExpression);
initializeExpList(exprTree);
AstBackedExpr expr = new AstBackedExpr(exprTree, Optional.of(filterExpression));
return expr.getFilter();
}

/**
* Initializes the {@code Expr} list ({@code lExp}) of every {@link Term} in the tree.
*/
private static void initializeExpList(Expression expression) {
if (expression instanceof Term term) {
for (Expression arg : term.getArgs()) {
initializeExpList(arg);
}
term.setExpList(new ArrayList<>(term.getArgs()));
}
}

private static Constant literalToConstant(LiteralAst l) {
if (l.lang() != null && !l.lang().isEmpty()) {
return Constant.create(unquoteLexical(l.lexical()), RDF.rdflangString, l.lang());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,7 @@ public static DQPFactory getFactory() {
private boolean isInsert = false;
boolean isDelete = false;
boolean isUpdate = false;
boolean isAsk = false;
boolean isCheckLoop = false;
boolean isListGroup = false;
boolean isListPath = true;
Expand Down Expand Up @@ -685,6 +686,14 @@ public void setUpdate(boolean b) {
isUpdate = b;
}

public boolean isAsk() {
return isAsk;
}

public void setAsk(boolean b) {
isAsk = b;
}

public boolean isTest() {
return isTest;
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
package fr.inria.corese.core.next.query.impl.sparql.bridge;

import fr.inria.corese.core.next.query.impl.sparql.ast.*;
import fr.inria.corese.core.next.query.impl.sparql.ast.constraint.GreaterThanAst;
import fr.inria.corese.core.next.query.kgram.core.Query;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;

import java.util.List;
import java.util.Map;
import java.util.Set;

import static org.junit.jupiter.api.Assertions.*;

class CoreseAstQueryBuilderAskTest {

private final CoreseAstQueryBuilder builder = new CoreseAstQueryBuilder();

private static GroupGraphPatternAst whereOneTriple() {
return new GroupGraphPatternAst(List.of(
new BgpAst(List.of(
new TriplePatternAst(new VarAst("s"), new VarAst("p"), new VarAst("o"))))));
}

@Test
@DisplayName("Query body is the compiled WHERE and the query is flagged as ASK")
void buildsBodyAndAskFlag() {
AskQueryAst ask = new AskQueryAst(DatasetClauseAst.none(), whereOneTriple());

Query query = builder.toQuery(ask);

assertNotNull(query.getBody(), "body set from WHERE");
assertTrue(query.getBody().isAnd(), "group compiles to AND");
assertTrue(query.getBody().get(0).isBGP(), "containing the BGP");
assertTrue(query.isAsk(), "query flagged as ASK");
}

@Test
@DisplayName("A FILTER in the WHERE no longer throws an NPE (lExp fix)")
void buildsAskWithFilter() {
FilterAst filter = new FilterAst(new GreaterThanAst(List.of(
new VarAst("o"), new LiteralAst("5", null, null))));
GroupGraphPatternAst where = new GroupGraphPatternAst(List.of(
new BgpAst(List.of(
new TriplePatternAst(new VarAst("s"), new VarAst("p"), new VarAst("o")))),
filter));
AskQueryAst ask = new AskQueryAst(DatasetClauseAst.none(), where);

Query query = builder.toQuery(ask);

assertTrue(query.isAsk());
assertTrue(query.getBody().get(1).isFilter(), "FILTER compiled into the body");
}

@Test
@DisplayName("FROM is not supported yet → UnsupportedOperationException")
void rejectsFromClause() {
DatasetClauseAst dataset = new DatasetClauseAst(
Set.of(new IriAst("http://example.org/g")), Set.of());
AskQueryAst ask = new AskQueryAst(dataset, whereOneTriple());

assertThrows(UnsupportedOperationException.class, () -> builder.toQuery(ask));
}

@Test
@DisplayName("FROM NAMED is not supported yet → UnsupportedOperationException")
void rejectsFromNamedClause() {
DatasetClauseAst dataset = new DatasetClauseAst(
Set.of(), Set.of(new IriAst("http://example.org/g")));
AskQueryAst ask = new AskQueryAst(dataset, whereOneTriple());

assertThrows(UnsupportedOperationException.class, () -> builder.toQuery(ask));
}

@Test
@DisplayName("Inline VALUES is not supported yet → UnsupportedOperationException")
void rejectsValuesClause() {
ValuesAst values = new ValuesAst(List.of(
new ValueMappingAst(Map.of(new VarAst("s"), new IriAst("http://example.org/x")))));
AskQueryAst ask = new AskQueryAst(
DatasetClauseAst.none(), whereOneTriple(), null, null, values);

assertThrows(UnsupportedOperationException.class, () -> builder.toQuery(ask));
}

@Test
@DisplayName("toQuery(null) throws NullPointerException")
void rejectsNullAsk() {
assertThrows(NullPointerException.class, () -> builder.toQuery(null));
}

@Test
@DisplayName("ASK {} with empty WHERE compiles to an empty AND body")
void buildsAskWithEmptyWhere() {
AskQueryAst ask = new AskQueryAst(DatasetClauseAst.none(),
new GroupGraphPatternAst(List.of()));

Query query = builder.toQuery(ask);

assertNotNull(query.getBody());
assertTrue(query.getBody().isAnd());
assertEquals(0, query.getBody().size(), "empty AND — no children");
assertTrue(query.isAsk());
}

@Test
@DisplayName("Solution modifiers (LIMIT) are not supported yet → UnsupportedOperationException")
void rejectsSolutionModifier() {
SolutionModifierAst mod = SolutionModifierAst.withoutGroupBy(false, false, List.of(), 10L, null);
AskQueryAst ask = new AskQueryAst(DatasetClauseAst.none(), whereOneTriple(), mod, null, null);

assertThrows(UnsupportedOperationException.class, () -> builder.toQuery(ask));
}
}
Loading