diff --git a/src/main/java/fr/inria/corese/core/next/query/impl/parser/SparqlAstBuilder.java b/src/main/java/fr/inria/corese/core/next/query/impl/parser/SparqlAstBuilder.java index 55057535a..a4894804b 100644 --- a/src/main/java/fr/inria/corese/core/next/query/impl/parser/SparqlAstBuilder.java +++ b/src/main/java/fr/inria/corese/core/next/query/impl/parser/SparqlAstBuilder.java @@ -1261,6 +1261,8 @@ public TermAst termFromBuiltInCall(fr.inria.corese.core.next.impl.parser.antlr.S return new RandAst(); } else if (ctx.UUID() != null) { return new UuidAst(); + } else if (ctx.STRUUID() != null) { + return new StrUuidAst(); } else if (ctx.CONCAT() != null) { List args = ctx.expression().stream().map(this::termFromExpression).toList(); return this.createConstraint(ASTConstants.FUNCTION_CALL.CONCAT, args); diff --git a/src/main/java/fr/inria/corese/core/next/query/impl/sparql/ast/constraint/StrUuidAst.java b/src/main/java/fr/inria/corese/core/next/query/impl/sparql/ast/constraint/StrUuidAst.java new file mode 100644 index 000000000..7012a179c --- /dev/null +++ b/src/main/java/fr/inria/corese/core/next/query/impl/sparql/ast/constraint/StrUuidAst.java @@ -0,0 +1,9 @@ +package fr.inria.corese.core.next.query.impl.sparql.ast.constraint; + +import fr.inria.corese.core.next.query.impl.sparql.ast.ConstraintAst; + +/** + * Function {@code STRUUID()} in SPARQL 1.1 + * Returns a string form of a UUID. + */ +public record StrUuidAst() implements ConstraintAst {} \ No newline at end of file diff --git a/src/test/java/fr/inria/corese/core/next/query/impl/parser/SparqlParserStrUuidTest.java b/src/test/java/fr/inria/corese/core/next/query/impl/parser/SparqlParserStrUuidTest.java new file mode 100644 index 000000000..0c6e5cdb6 --- /dev/null +++ b/src/test/java/fr/inria/corese/core/next/query/impl/parser/SparqlParserStrUuidTest.java @@ -0,0 +1,78 @@ +package fr.inria.corese.core.next.query.impl.parser; + +import fr.inria.corese.core.next.query.impl.sparql.ast.BindAst; +import fr.inria.corese.core.next.query.impl.sparql.ast.FilterAst; +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.ast.VarAst; +import fr.inria.corese.core.next.query.impl.sparql.ast.constraint.EqualsAst; +import fr.inria.corese.core.next.query.impl.sparql.ast.constraint.StrAst; +import fr.inria.corese.core.next.query.impl.sparql.ast.constraint.StrUuidAst; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertInstanceOf; +import static org.junit.jupiter.api.Assertions.assertNotNull; + +@DisplayName("SPARQL 1.1 - Parser and AST : STRUUID") +class SparqlParserStrUuidTest extends AbstractSparqlParserFeatureTest { + + @Test + @DisplayName("BIND(STRUUID() AS ?id)") + void shouldParseStrUuid() { + SparqlParser parser = newParserDefault(); + + QueryAst ast = parser.parse(""" + SELECT * WHERE { + ?s ?p ?o . + BIND(STRUUID() AS ?id) + } + """); + + assertNotNull(ast); + BindAst bind = assertInstanceOf(BindAst.class, ast.whereClause().patterns().getLast()); + assertInstanceOf(StrUuidAst.class, bind.expression()); + assertEquals("id", bind.variable().name()); + } + + @Test + @DisplayName("FILTER(STRUUID() = STR(?s))") + void shouldParseStrUuidInFilter() { + SparqlParser parser = newParserDefault(); + + QueryAst ast = parser.parse(""" + SELECT * WHERE { + ?s ?p ?o . + FILTER(STRUUID() = STR(?s)) + } + """); + + assertNotNull(ast); + FilterAst filter = assertInstanceOf(FilterAst.class, ast.whereClause().patterns().getLast()); + EqualsAst equals = assertInstanceOf(EqualsAst.class, filter.operator()); + assertInstanceOf(StrUuidAst.class, equals.getLeftArgument()); + StrAst str = assertInstanceOf(StrAst.class, equals.getRightArgument()); + assertEquals("s", assertInstanceOf(VarAst.class, str.getArgument()).name()); + } + + @Test + @DisplayName("SELECT (STRUUID() AS ?id) ?s WHERE { ?s ?p ?o }") + void shouldParseStrUuidInProjectionBinding() { + SparqlParser parser = newParserDefault(); + + QueryAst ast = parser.parse(""" + SELECT (STRUUID() AS ?id) ?s WHERE { + ?s ?p ?o . + } + """); + + assertNotNull(ast); + SelectQueryAst selectAst = assertInstanceOf(SelectQueryAst.class, ast); + assertFalse(selectAst.projection().selectAll()); + assertEquals(2, selectAst.projection().variables().size()); + assertEquals("id", selectAst.projection().variables().getFirst().name()); + assertEquals("s", selectAst.projection().variables().getLast().name()); + } +} \ No newline at end of file