Skip to content
Merged
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
Expand Up @@ -302,4 +302,14 @@ public void enterCreate(SparqlParser.CreateContext ctx) {
public void exitCreate(SparqlParser.CreateContext ctx) {
for (var d : delegates) d.exitCreate(ctx);
}

@Override
public void enterDrop(SparqlParser.DropContext ctx) {
for (var d : delegates) d.enterDrop(ctx);
}

@Override
public void exitDrop(SparqlParser.DropContext ctx) {
for (var d : delegates) d.exitDrop(ctx);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -160,6 +160,7 @@ private QueryAst buildAst(
SparqlListenerDispatcher updateListener = new SparqlListenerDispatcher(List.of(
new ClearUpdateAstListener(updateBuilder),
new CreateUpdateAstListener(updateBuilder),
new DropUpdateAstListener(updateBuilder),
new LoadUpdateAstListener(updateBuilder),
new BgpAstListener(updateBuilder),
new BindAstListener(updateBuilder),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,19 @@ public ClearRequestAst cleartoAst(SparqlParser.ClearContext ctx) {
}
}

public DropRequestAst dropToAst(SparqlParser.DropContext ctx) {
GraphRefAst targetGraphRef = null;
boolean silentFlag = ctx.SILENT() != null;
if (ctx.graphRefAll() != null) {
targetGraphRef = this.graphRefFromGraphRefAll(ctx.graphRefAll());
}
if (targetGraphRef != null) {
return new DropRequestAst(targetGraphRef, silentFlag);
} else {
throw new QueryEvaluationException("No target graph reference found in DROP query");
}
}

public CreateRequestAst createToAst(SparqlParser.CreateContext ctx) {
boolean silentFlag = ctx.SILENT() != null;
if (ctx.graphRef() != null) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package fr.inria.corese.core.next.query.impl.parser.listener;

import fr.inria.corese.core.next.impl.parser.antlr.SparqlParser;
import fr.inria.corese.core.next.query.impl.parser.SparqlUpdateAstBuilder;
import fr.inria.corese.core.next.query.impl.sparql.ast.DropRequestAst;

/**
* AST feature listener for DROP SPARQL update query
*/
public class DropUpdateAstListener extends AbstractSparqlUpdateAstListener {
public DropUpdateAstListener(SparqlUpdateAstBuilder builder) {
super(builder);
}

@Override
public void enterDrop(SparqlParser.DropContext ctx) {
DropRequestAst dropRequestAst = this.updateBuilder().dropToAst(ctx);
this.updateBuilder().addRequest(dropRequestAst);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package fr.inria.corese.core.next.query.impl.sparql.ast;

import fr.inria.corese.core.next.query.impl.parser.semantic.support.AstVisitor;

/**
* Represents the DROP operation as defined in the <a href="https://www.w3.org/TR/2013/REC-sparql11-update-20130321/#drop">SPARQL 1.1 recommendation</a>.
* @param graphRef targeted graph to be dropped
* @param silent Determine if the resolution of the query must be resolved silently or not.
*/
public record DropRequestAst(GraphRefAst graphRef, boolean silent) implements UpdateRequestUnitAst {
/**
* Construct DROP query with a silent flag to false.
* @param graphRef targeted graph to be dropped
*/
public DropRequestAst(GraphRefAst graphRef) {
this(graphRef, false);
}

@Override
public void accept(AstVisitor visitor) {
visitor.visit(this);
this.graphRef.accept(visitor);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,5 +5,5 @@
/**
* Root interface for all operations related to the SPARQL Update operations listed in <a href="https://www.w3.org/TR/sparql11-update/">SPARQL 1.1 Update</a>.
*/
public sealed interface UpdateRequestUnitAst extends VisitableAst permits LoadRequestAst, ClearRequestAst, CreateRequestAst {
public sealed interface UpdateRequestUnitAst extends VisitableAst permits LoadRequestAst, ClearRequestAst, CreateRequestAst, DropRequestAst {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,215 @@
package fr.inria.corese.core.next.query.impl.parser;

import fr.inria.corese.core.next.query.api.exception.QuerySyntaxException;
import fr.inria.corese.core.next.query.impl.parser.QueryParser;
import fr.inria.corese.core.next.query.impl.sparql.ast.DropRequestAst;
import fr.inria.corese.core.next.query.impl.sparql.ast.IriAst;
import fr.inria.corese.core.next.query.impl.sparql.ast.QueryAst;
import fr.inria.corese.core.next.query.impl.sparql.ast.UpdateRequestAst;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;

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

public class SparqlParserDropQueryTest extends AbstractSparqlParserFeatureTest {

@Test
@DisplayName("should parse DROP GRAPH <iri>")
void graphQueryTest() {
QueryParser parser = newParserDefault();
String query = """
DROP GRAPH <http://ns.inria.fr/test>
""";

QueryAst queryAst = parser.parse(query);
assertInstanceOf(UpdateRequestAst.class, queryAst);
UpdateRequestAst updateRequestAst = (UpdateRequestAst) queryAst;
assertEquals(1, updateRequestAst.operations().size());
assertInstanceOf(DropRequestAst.class, updateRequestAst.operations().getFirst());
DropRequestAst dropQueryAst = (DropRequestAst) updateRequestAst.operations().getFirst();
assertNotNull(dropQueryAst.graphRef());
IriAst graphIri = dropQueryAst.graphRef().graph();
assertEquals("<http://ns.inria.fr/test>", graphIri.raw());
assertFalse(dropQueryAst.silent());
}

@Test
@DisplayName("should parse DROP SILENT GRAPH <iri> and set the silent flag")
void graphSilentQueryTest() {
QueryParser parser = newParserDefault();
String query = """
DROP SILENT GRAPH <http://ns.inria.fr/test>
""";

QueryAst queryAst = parser.parse(query);
assertInstanceOf(UpdateRequestAst.class, queryAst);
UpdateRequestAst updateRequestAst = (UpdateRequestAst) queryAst;
assertEquals(1, updateRequestAst.operations().size());
assertInstanceOf(DropRequestAst.class, updateRequestAst.operations().getFirst());
DropRequestAst dropQueryAst = (DropRequestAst) updateRequestAst.operations().getFirst();
assertNotNull(dropQueryAst.graphRef());
IriAst graphIri = dropQueryAst.graphRef().graph();
assertEquals("<http://ns.inria.fr/test>", graphIri.raw());
assertTrue(dropQueryAst.silent());
}

@Test
@DisplayName("should parse DROP NAMED")
void namedQueryTest() {
QueryParser parser = newParserDefault();
String query = """
DROP NAMED
""";

QueryAst queryAst = parser.parse(query);
assertInstanceOf(UpdateRequestAst.class, queryAst);
UpdateRequestAst updateRequestAst = (UpdateRequestAst) queryAst;
assertEquals(1, updateRequestAst.operations().size());
assertInstanceOf(DropRequestAst.class, updateRequestAst.operations().getFirst());
DropRequestAst dropQueryAst = (DropRequestAst) updateRequestAst.operations().getFirst();
assertNotNull(dropQueryAst.graphRef());
assertTrue(dropQueryAst.graphRef().named());
assertFalse(dropQueryAst.silent());
}

@Test
@DisplayName("should parse DROP SILENT NAMED and set the silent flag")
void namedSilentQueryTest() {
QueryParser parser = newParserDefault();
String query = """
DROP SILENT NAMED
""";

QueryAst queryAst = parser.parse(query);
assertInstanceOf(UpdateRequestAst.class, queryAst);
UpdateRequestAst updateRequestAst = (UpdateRequestAst) queryAst;
assertEquals(1, updateRequestAst.operations().size());
assertInstanceOf(DropRequestAst.class, updateRequestAst.operations().getFirst());
DropRequestAst dropQueryAst = (DropRequestAst) updateRequestAst.operations().getFirst();
assertNotNull(dropQueryAst.graphRef());
assertTrue(dropQueryAst.graphRef().named());
assertTrue(dropQueryAst.silent());
}

@Test
@DisplayName("should parse DROP DEFAULT")
void defaultQueryTest() {
QueryParser parser = newParserDefault();
String query = """
DROP DEFAULT
""";

QueryAst queryAst = parser.parse(query);
assertInstanceOf(UpdateRequestAst.class, queryAst);
UpdateRequestAst updateRequestAst = (UpdateRequestAst) queryAst;
assertEquals(1, updateRequestAst.operations().size());
assertInstanceOf(DropRequestAst.class, updateRequestAst.operations().getFirst());
DropRequestAst dropQueryAst = (DropRequestAst) updateRequestAst.operations().getFirst();
assertNotNull(dropQueryAst.graphRef());
assertTrue(dropQueryAst.graphRef().defaultGraph());
assertFalse(dropQueryAst.silent());
}

@Test
@DisplayName("should parse DROP SILENT DEFAULT and set the silent flag")
void defaultSilentQueryTest() {
QueryParser parser = newParserDefault();
String query = """
DROP SILENT DEFAULT
""";

QueryAst queryAst = parser.parse(query);
assertInstanceOf(UpdateRequestAst.class, queryAst);
UpdateRequestAst updateRequestAst = (UpdateRequestAst) queryAst;
assertEquals(1, updateRequestAst.operations().size());
assertInstanceOf(DropRequestAst.class, updateRequestAst.operations().getFirst());
DropRequestAst dropQueryAst = (DropRequestAst) updateRequestAst.operations().getFirst();
assertNotNull(dropQueryAst.graphRef());
assertTrue(dropQueryAst.graphRef().defaultGraph());
assertTrue(dropQueryAst.silent());
}

@Test
@DisplayName("should parse DROP ALL")
void allQueryTest() {
QueryParser parser = newParserDefault();
String query = """
DROP ALL
""";

QueryAst queryAst = parser.parse(query);
assertInstanceOf(UpdateRequestAst.class, queryAst);
UpdateRequestAst updateRequestAst = (UpdateRequestAst) queryAst;
assertEquals(1, updateRequestAst.operations().size());
assertInstanceOf(DropRequestAst.class, updateRequestAst.operations().getFirst());
DropRequestAst dropQueryAst = (DropRequestAst) updateRequestAst.operations().getFirst();
assertNotNull(dropQueryAst.graphRef());
assertTrue(dropQueryAst.graphRef().all());
assertFalse(dropQueryAst.silent());
}

@Test
@DisplayName("should parse DROP SILENT ALL and set the silent flag")
void allSilentQueryTest() {
QueryParser parser = newParserDefault();
String query = """
DROP SILENT ALL
""";

QueryAst queryAst = parser.parse(query);
assertInstanceOf(UpdateRequestAst.class, queryAst);
UpdateRequestAst updateRequestAst = (UpdateRequestAst) queryAst;
assertEquals(1, updateRequestAst.operations().size());
assertInstanceOf(DropRequestAst.class, updateRequestAst.operations().getFirst());
DropRequestAst dropQueryAst = (DropRequestAst) updateRequestAst.operations().getFirst();
assertNotNull(dropQueryAst.graphRef());
assertTrue(dropQueryAst.graphRef().all());
assertTrue(dropQueryAst.silent());
}

@Test
@DisplayName("should parse two chained DROP operations separated by ';'")
void chainedDropShouldCreateTwoUpdateOperations() {
QueryParser parser = newParserDefault();
String query = """
DROP GRAPH <http://example.org/g1> ;
DROP SILENT GRAPH <http://example.org/g2>
""";

QueryAst queryAst = parser.parse(query);
UpdateRequestAst update = assertInstanceOf(UpdateRequestAst.class, queryAst);
assertEquals(2, update.operations().size());

DropRequestAst first = assertInstanceOf(DropRequestAst.class, update.operations().getFirst());
assertEquals("<http://example.org/g1>", first.graphRef().graph().raw());
assertFalse(first.silent());

DropRequestAst second = assertInstanceOf(DropRequestAst.class, update.operations().get(1));
assertEquals("<http://example.org/g2>", second.graphRef().graph().raw());
assertTrue(second.silent());
}

@Test
@DisplayName("should keep the prologue when DROP uses a prefixed graph name")
void dropMustKeepItsPrologue() {
QueryParser parser = newParserDefault();
QueryAst ast = parser.parse("PREFIX ex: <http://example.org/> DROP GRAPH ex:g");
UpdateRequestAst update = assertInstanceOf(UpdateRequestAst.class, ast);

assertEquals(1, update.operations().size());
assertInstanceOf(DropRequestAst.class, update.operations().getFirst());
assertNotNull(update.prologue());
assertEquals(1, update.prologue().prefixDeclarations().size());
}

@Test
@DisplayName("should reject invalid DROP syntax with multiple graph references")
void failingTooManyQueryTest() {
QueryParser parser = newParserDefault();
String query = """
DROP SILENT ALL NAMED GRAPH <http://ns.inria.fr/test>
""";

assertThrows(QuerySyntaxException.class, () -> parser.parse(query));
}
}
Loading