Skip to content
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

Parse update queries #1354

Merged
merged 17 commits into from
Jun 5, 2024
15 changes: 13 additions & 2 deletions src/parser/SparqlTriple.h
Original file line number Diff line number Diff line change
Expand Up @@ -61,8 +61,8 @@ class SparqlTriple : public SparqlTripleBase<PropertyPath> {
using Base::Base;

// ___________________________________________________________________________
SparqlTriple(TripleComponent s, const std::string& p_iri, TripleComponent o)
: Base{std::move(s), PropertyPath::fromIri(p_iri), std::move(o)} {}
SparqlTriple(TripleComponent s, const std::string& iri, TripleComponent o)
: Base{std::move(s), PropertyPath::fromIri(iri), std::move(o)} {}

// ___________________________________________________________________________
[[nodiscard]] string asString() const;
Expand All @@ -77,4 +77,15 @@ class SparqlTriple : public SparqlTripleBase<PropertyPath> {
: TripleComponent(TripleComponent::Iri::fromIriref(p_._iri));
return {s_, p, o_, additionalScanColumns_};
}

// Constructs SparqlTriple from a simple triple. Fails with an exception if
// the predicate is neither a variable nor an iri.
static SparqlTriple fromSimple(const SparqlTripleSimple& triple) {
AD_CONTRACT_CHECK(triple.p_.isVariable() || triple.p_.isIri());
PropertyPath p = triple.p_.isVariable()
? PropertyPath::fromVariable(triple.p_.getVariable())
: PropertyPath::fromIri(
triple.p_.getIri().toStringRepresentation());
return {triple.s_, p, triple.o_};
}
};
17 changes: 17 additions & 0 deletions src/parser/data/GraphRef.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
// Copyright 2024, University of Freiburg,
// Chair of Algorithms and Data Structures.
// Author: Julian Mundhahs (mundhahj@informatik.uni-freiburg.de)

#pragma once

#include <variant>

#include "parser/Iri.h"

using GraphRef = TripleComponent::Iri;
struct DEFAULT {};
struct NAMED {};
struct ALL {};

using GraphRefAll = std::variant<GraphRef, DEFAULT, NAMED, ALL>;
using GraphOrDefault = std::variant<GraphRef, DEFAULT>;
152 changes: 92 additions & 60 deletions src/parser/sparqlParser/SparqlQleverVisitor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -329,74 +329,86 @@
ParsedQuery Visitor::visit(Parser::UpdateContext* ctx) {
visit(ctx->prologue());

auto query = visit(ctx->update1());

if (ctx->update()) {
parsedQuery_ = ParsedQuery{};
reportNotSupported(ctx->update(), "Multiple updates in one query are");
}
return visit(ctx->update1());

return query;
}

// ____________________________________________________________________________________
ParsedQuery Visitor::visit(Parser::Update1Context* ctx) {
if (ctx->modify()) {
return visit(ctx->modify());
} else if (ctx->clear()) {
return visit(ctx->clear());
}

// TODO: updates can be chained; think about how to enable this

parsedQuery_._clause = parsedQuery::UpdateClause();

if (ctx->insertData()) {
parsedQuery_.updateClause().toInsert_ = visit(ctx->insertData());
} else if (ctx->deleteData()) {
parsedQuery_.updateClause().toDelete_ = visit(ctx->deleteData());
if (ctx->insertData() || ctx->deleteData()) {
// handles insertData and deleteData cases
visitIf(&parsedQuery_.updateClause().toInsert_, ctx->insertData());
visitIf(&parsedQuery_.updateClause().toDelete_, ctx->deleteData());
} else if (ctx->deleteWhere()) {
auto [toDelete, pattern] = visit(ctx->deleteWhere());
parsedQuery_.updateClause().toDelete_ = std::move(toDelete);
parsedQuery_._rootGraphPattern = std::move(pattern);
} else if (ctx->modify()) {
// updates the internal state of `parsedQuery_`
visit(ctx->modify());
} else {
visitAlternative<void>(ctx->load(), ctx->clear(), ctx->drop(), ctx->add(),
ctx->move(), ctx->copy(), ctx->create());
visitAlternative<void>(ctx->load(), ctx->drop(), ctx->add(), ctx->move(),
ctx->copy(), ctx->create());
AD_FAIL();
}

return parsedQuery_;
}

// ____________________________________________________________________________________
void Visitor::visit(Parser::LoadContext* ctx) {
void Visitor::visit(const Parser::LoadContext* ctx) const {
reportNotSupported(ctx, "SPARQL 1.1 Update Load is");
}

// ____________________________________________________________________________________
void Visitor::visit(Parser::ClearContext* ctx) {
reportNotSupported(ctx, "SPARQL 1.1 Update Clear is");
ParsedQuery Visitor::visit(Parser::ClearContext* ctx) {
auto graphRef = visit(ctx->graphRefAll());

if (holds_alternative<DEFAULT>(graphRef)) {
parsedQuery_._clause = parsedQuery::UpdateClause();
parsedQuery_.updateClause().toDelete_ = {
{Variable("?s"), Variable("?p"), Variable("?o")}};
parsedQuery_._rootGraphPattern._graphPatterns.emplace_back(
BasicGraphPattern{{{Variable("?s"), "?p", Variable("?o")}}});
return parsedQuery_;
} else {
reportNotSupported(ctx, "Named Graphs are");
}
}
Qup42 marked this conversation as resolved.
Show resolved Hide resolved

// ____________________________________________________________________________________
void Visitor::visit(Parser::DropContext* ctx) {
void Visitor::visit(const Parser::DropContext* ctx) const {
reportNotSupported(ctx, "SPARQL 1.1 Update Drop is");
}
Qup42 marked this conversation as resolved.
Show resolved Hide resolved

// ____________________________________________________________________________________
void Visitor::visit(Parser::CreateContext* ctx) {
void Visitor::visit(const Parser::CreateContext* ctx) const {
reportNotSupported(ctx, "SPARQL 1.1 Update Create is");
}

// ____________________________________________________________________________________
void Visitor::visit(Parser::AddContext* ctx) {
void Visitor::visit(const Parser::AddContext* ctx) const {
reportNotSupported(ctx, "SPARQL 1.1 Update Add is");
}

// ____________________________________________________________________________________
void Visitor::visit(Parser::MoveContext* ctx) {
void Visitor::visit(const Parser::MoveContext* ctx) const {
reportNotSupported(ctx, "SPARQL 1.1 Update Move is");
}

// ____________________________________________________________________________________
void Visitor::visit(Parser::CopyContext* ctx) {
void Visitor::visit(const Parser::CopyContext* ctx) const {
reportNotSupported(ctx, "SPARQL 1.1 Update Copy is");
}

Expand All @@ -414,31 +426,35 @@
std::pair<vector<SparqlTripleSimple>, ParsedQuery::GraphPattern> Visitor::visit(
Parser::DeleteWhereContext* ctx) {
auto triples = visit(ctx->quadPattern());
auto transformTriple =
[&ctx](const SparqlTripleSimple& triple) -> SparqlTriple {
if (triple.p_.isVariable()) {
return {triple.s_, PropertyPath::fromVariable(triple.p_.getVariable()),
triple.o_};
} else if (triple.p_.isIri()) {
return {
triple.s_,
PropertyPath::fromIri(triple.p_.getIri().toStringRepresentation()),
triple.o_};
} else {
reportError(ctx, "Predicate must a PropertyPath");
auto registerIfVariable = [this](const TripleComponent& component) {
if (component.isVariable()) {
addVisibleVariable(component.getVariable());
}
};
auto transformAndRegisterTriple =
[registerIfVariable](const SparqlTripleSimple& triple) {
registerIfVariable(triple.s_);
registerIfVariable(triple.p_);
registerIfVariable(triple.o_);

if (triple.p_.isVariable() || triple.p_.isIri()) {
return SparqlTriple::fromSimple(triple);
} else {
// The predicate comes from a rule in the grammar (`verb`) which only
// allows variables and IRIs.
AD_FAIL();
}

Check warning on line 446 in src/parser/sparqlParser/SparqlQleverVisitor.cpp

View check run for this annotation

Codecov / codecov/patch

src/parser/sparqlParser/SparqlQleverVisitor.cpp#L445-L446

Added lines #L445 - L446 were not covered by tests
Qup42 marked this conversation as resolved.
Show resolved Hide resolved
};
GraphPattern pattern;
pattern._graphPatterns.emplace_back(
BasicGraphPattern{ad_utility::transform(triples, transformTriple)});
pattern._graphPatterns.emplace_back(BasicGraphPattern{
ad_utility::transform(triples, transformAndRegisterTriple)});

return {std::move(triples), std::move(pattern)};
}
Qup42 marked this conversation as resolved.
Show resolved Hide resolved

// ____________________________________________________________________________________
ParsedQuery Visitor::visit(Parser::ModifyContext* ctx) {
if (ctx->iri()) {
// Could also be default; disallow completely for now.
reportNotSupported(ctx->iri(), "Named graphs are");
}
if (!ctx->usingClause().empty()) {
Expand All @@ -449,12 +465,8 @@
parsedQuery_._rootGraphPattern = visit(ctx->groupGraphPattern());

parsedQuery_._clause = parsedQuery::UpdateClause();
if (ctx->deleteClause()) {
parsedQuery_.updateClause().toDelete_ = visit(ctx->deleteClause());
}
if (ctx->insertClause()) {
parsedQuery_.updateClause().toInsert_ = visit(ctx->insertClause());
}
visitIf(&parsedQuery_.updateClause().toInsert_, ctx->insertClause());
visitIf(&parsedQuery_.updateClause().toDelete_, ctx->deleteClause());

return parsedQuery_;
}
Expand All @@ -469,6 +481,35 @@
return visit(ctx->quadPattern());
}

// ____________________________________________________________________________________
GraphOrDefault Visitor::visit(Parser::GraphOrDefaultContext* ctx) {
if (ctx->iri()) {
return visit(ctx->iri());
} else {
return DEFAULT{};
}
}

// ____________________________________________________________________________________
GraphRef Visitor::visit(Parser::GraphRefContext* ctx) {
return visit(ctx->iri());
}

// ____________________________________________________________________________________
GraphRefAll Visitor::visit(Parser::GraphRefAllContext* ctx) {
if (ctx->graphRef()) {
return visit(ctx->graphRef());
} else if (ctx->DEFAULT()) {
return DEFAULT{};
} else if (ctx->NAMED()) {
return NAMED{};
} else if (ctx->ALL()) {
return ALL{};
} else {
AD_FAIL();
}

Check warning on line 510 in src/parser/sparqlParser/SparqlQleverVisitor.cpp

View check run for this annotation

Codecov / codecov/patch

src/parser/sparqlParser/SparqlQleverVisitor.cpp#L509-L510

Added lines #L509 - L510 were not covered by tests
}

// ____________________________________________________________________________________
vector<SparqlTripleSimple> Visitor::visit(Parser::QuadPatternContext* ctx) {
return visit(ctx->quads());
Expand Down Expand Up @@ -502,19 +543,13 @@

AD_CORRECTNESS_CHECK(ctx->triplesTemplate().size() == 1);

auto convertAndRegisterTriple =
[this](const std::array<GraphTerm, 3>& triple) -> SparqlTripleSimple {
// TODO:
registerIfVariable(triple[0]);
registerIfVariable(triple[1]);
registerIfVariable(triple[2]);

auto convertTriple =
[](const std::array<GraphTerm, 3>& triple) -> SparqlTripleSimple {
return {visitGraphTerm(triple[0]), visitGraphTerm(triple[1]),
visitGraphTerm(triple[2])};
};

return ad_utility::transform(visit(ctx->triplesTemplate(0)),
convertAndRegisterTriple);
return ad_utility::transform(visit(ctx->triplesTemplate(0)), convertTriple);
}

// ____________________________________________________________________________________
Expand Down Expand Up @@ -615,10 +650,14 @@
propertyPathIdentity},
varOrPath);
};

auto registerIfVariable = [this](const auto& variant) {
if (holds_alternative<Variable>(variant)) {
addVisibleVariable(std::get<Variable>(variant));
}
};
auto convertAndRegisterTriple =
[this,
&visitVarOrPath](const TripleWithPropertyPath& triple) -> SparqlTriple {
[&visitVarOrPath, &registerIfVariable](
const TripleWithPropertyPath& triple) -> SparqlTriple {
registerIfVariable(triple.subject_);
registerIfVariable(triple.predicate_);
registerIfVariable(triple.object_);
Expand Down Expand Up @@ -2351,17 +2390,10 @@
if constexpr (std::is_same_v<T, Variable>) {
return element;
} else if constexpr (std::is_same_v<T, Literal> || std::is_same_v<T, Iri>) {
return TurtleStringParser<TokenizerCtre>::parseTripleObject(
element.toSparql());
} else {
return element.toSparql();
}

Check warning on line 2397 in src/parser/sparqlParser/SparqlQleverVisitor.cpp

View check run for this annotation

Codecov / codecov/patch

src/parser/sparqlParser/SparqlQleverVisitor.cpp#L2393-L2397

Added lines #L2393 - L2397 were not covered by tests
});
}

// _____________________________________________________________________________
void SparqlQleverVisitor::registerIfVariable(const auto& variant) {
if (holds_alternative<Variable>(variant)) {
addVisibleVariable(std::get<Variable>(variant));
}
}
Loading
Loading