Skip to content

Commit

Permalink
Parse update queries (#1354)
Browse files Browse the repository at this point in the history
This commit extends SPARQL parser s.t. it can parse `SPARQL UPDATE` queries and store them as part of the `ParsedQuery`. The updates are not yet processed, but (as of now) still lead to an error message that updates are not yet supported.
  • Loading branch information
Qup42 committed Jun 5, 2024
1 parent f9c3132 commit a2ce6fa
Show file tree
Hide file tree
Showing 8 changed files with 668 additions and 246 deletions.
85 changes: 17 additions & 68 deletions src/parser/ParsedQuery.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
#include "parser/PropertyPath.h"
#include "parser/SelectClause.h"
#include "parser/TripleComponent.h"
#include "parser/UpdateClause.h"
#include "parser/data/GroupKey.h"
#include "parser/data/LimitOffsetClause.h"
#include "parser/data/OrderKey.h"
Expand Down Expand Up @@ -49,75 +50,8 @@ class SparqlPrefix {
bool operator==(const SparqlPrefix&) const = default;
};

inline bool isVariable(const string& elem) { return elem.starts_with("?"); }
inline bool isVariable(const TripleComponent& elem) {
return elem.isVariable();
}

inline bool isVariable(const PropertyPath& elem) {
return elem._operation == PropertyPath::Operation::IRI &&
isVariable(elem._iri);
}

std::ostream& operator<<(std::ostream& out, const PropertyPath& p);

// Data container for parsed triples from the where clause.
// It is templated on the predicate type, see the instantiations below.
template <typename Predicate>
class SparqlTripleBase {
public:
using AdditionalScanColumns = std::vector<std::pair<ColumnIndex, Variable>>;
SparqlTripleBase(TripleComponent s, Predicate p, TripleComponent o,
AdditionalScanColumns additionalScanColumns = {})
: s_(std::move(s)),
p_(std::move(p)),
o_(std::move(o)),
additionalScanColumns_(std::move(additionalScanColumns)) {}

bool operator==(const SparqlTripleBase& other) const = default;
TripleComponent s_;
Predicate p_;
TripleComponent o_;
// The additional columns (e.g. patterns) that are to be attached when
// performing an index scan using this triple.
// TODO<joka921> On this level we should not store `ColumnIndex`, but the
// special predicate IRIs that are to be attached here.
std::vector<std::pair<ColumnIndex, Variable>> additionalScanColumns_;
};

// A triple where the predicate is a `TripleComponent`, so a fixed entity or a
// variable, but not a property path.
class SparqlTripleSimple : public SparqlTripleBase<TripleComponent> {
using Base = SparqlTripleBase<TripleComponent>;
using Base::Base;
};

// A triple where the predicate is a `PropertyPath` (which technically still
// might be a variable or fixed entity in the current implementation).
class SparqlTriple : public SparqlTripleBase<PropertyPath> {
public:
using Base = 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)} {}

// ___________________________________________________________________________
[[nodiscard]] string asString() const;

// Convert to a simple triple. Fails with an exception if the predicate
// actually is a property path.
SparqlTripleSimple getSimple() const {
AD_CONTRACT_CHECK(p_.isIri());
TripleComponent p =
isVariable(p_._iri)
? TripleComponent{Variable{p_._iri}}
: TripleComponent(TripleComponent::Iri::fromIriref(p_._iri));
return {s_, p, o_, additionalScanColumns_};
}
};

// Forward declaration
namespace parsedQuery {
struct GraphPatternOperation;
Expand All @@ -132,6 +66,8 @@ class ParsedQuery {

using ConstructClause = parsedQuery::ConstructClause;

using UpdateClause = parsedQuery::UpdateClause;

ParsedQuery() = default;

GraphPattern _rootGraphPattern;
Expand All @@ -147,7 +83,8 @@ class ParsedQuery {

// explicit default initialisation because the constructor
// of SelectClause is private
std::variant<SelectClause, ConstructClause> _clause{SelectClause{}};
std::variant<SelectClause, ConstructClause, UpdateClause> _clause{
SelectClause{}};

[[nodiscard]] bool hasSelectClause() const {
return std::holds_alternative<SelectClause>(_clause);
Expand All @@ -157,6 +94,10 @@ class ParsedQuery {
return std::holds_alternative<ConstructClause>(_clause);
}

[[nodiscard]] bool hasUpdateClause() const {
return std::holds_alternative<UpdateClause>(_clause);
}

[[nodiscard]] decltype(auto) selectClause() const {
return std::get<SelectClause>(_clause);
}
Expand All @@ -165,6 +106,10 @@ class ParsedQuery {
return std::get<ConstructClause>(_clause);
}

[[nodiscard]] decltype(auto) updateClause() const {
return std::get<UpdateClause>(_clause);
}

[[nodiscard]] decltype(auto) selectClause() {
return std::get<SelectClause>(_clause);
}
Expand All @@ -173,6 +118,10 @@ class ParsedQuery {
return std::get<ConstructClause>(_clause);
}

[[nodiscard]] decltype(auto) updateClause() {
return std::get<UpdateClause>(_clause);
}

// Add a variable, that was found in the query body.
void registerVariableVisibleInQueryBody(const Variable& variable);

Expand Down
91 changes: 91 additions & 0 deletions src/parser/SparqlTriple.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
// Copyright 2024, University of Freiburg,
// Chair of Algorithms and Data Structures.
// Authors: Björn Buchhold (buchhold@informatik.uni-freiburg.de)
// Johannes Kalmbach <johannes.kalmbach@gmail.com>

#pragma once

#include <vector>

#include "PropertyPath.h"
#include "TripleComponent.h"
#include "global/Id.h"
#include "parser/data/Variable.h"

inline bool isVariable(const string& elem) { return elem.starts_with("?"); }
inline bool isVariable(const TripleComponent& elem) {
return elem.isVariable();
}

inline bool isVariable(const PropertyPath& elem) {
return elem._operation == PropertyPath::Operation::IRI &&
isVariable(elem._iri);
}

// Data container for parsed triples from the where clause.
// It is templated on the predicate type, see the instantiations below.
template <typename Predicate>
class SparqlTripleBase {
public:
using AdditionalScanColumns = std::vector<std::pair<ColumnIndex, Variable>>;
SparqlTripleBase(TripleComponent s, Predicate p, TripleComponent o,
AdditionalScanColumns additionalScanColumns = {})
: s_(std::move(s)),
p_(std::move(p)),
o_(std::move(o)),
additionalScanColumns_(std::move(additionalScanColumns)) {}

bool operator==(const SparqlTripleBase& other) const = default;
TripleComponent s_;
Predicate p_;
TripleComponent o_;
// The additional columns (e.g. patterns) that are to be attached when
// performing an index scan using this triple.
// TODO<joka921> On this level we should not store `ColumnIndex`, but the
// special predicate IRIs that are to be attached here.
std::vector<std::pair<ColumnIndex, Variable>> additionalScanColumns_;
};

// A triple where the predicate is a `TripleComponent`, so a fixed entity or a
// variable, but not a property path.
class SparqlTripleSimple : public SparqlTripleBase<TripleComponent> {
using Base = SparqlTripleBase<TripleComponent>;
using Base::Base;
};

// A triple where the predicate is a `PropertyPath` (which technically still
// might be a variable or fixed entity in the current implementation).
class SparqlTriple : public SparqlTripleBase<PropertyPath> {
public:
using Base = SparqlTripleBase<PropertyPath>;
using Base::Base;

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

// ___________________________________________________________________________
[[nodiscard]] string asString() const;

// Convert to a simple triple. Fails with an exception if the predicate
// actually is a property path.
SparqlTripleSimple getSimple() const {
AD_CONTRACT_CHECK(p_.isIri());
TripleComponent p =
isVariable(p_._iri)
? TripleComponent{Variable{p_._iri}}
: 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_};
}
};
21 changes: 21 additions & 0 deletions src/parser/UpdateClause.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
// Copyright 2024, University of Freiburg,
// Chair of Algorithms and Data Structures.
// Author: Julian Mundhahs (mundhahj@informatik.uni-freiburg.de)

#pragma once

#include "parser/SelectClause.h"
#include "parser/SparqlTriple.h"
#include "parser/data/Types.h"

namespace parsedQuery {
struct UpdateClause : ClauseBase {
std::vector<SparqlTripleSimple> toInsert_;
std::vector<SparqlTripleSimple> toDelete_;

UpdateClause() = default;
UpdateClause(std::vector<SparqlTripleSimple> toInsert,
std::vector<SparqlTripleSimple> toDelete)
: toInsert_{std::move(toInsert)}, toDelete_{std::move(toDelete)} {}
};
} // namespace parsedQuery
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>;

0 comments on commit a2ce6fa

Please sign in to comment.