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

executeUpdate #1592

Draft
wants to merge 7 commits into
base: master
Choose a base branch
from
Draft
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
2 changes: 2 additions & 0 deletions src/engine/ExportQueryExecutionTrees.h
Original file line number Diff line number Diff line change
Expand Up @@ -192,9 +192,11 @@ class ExportQueryExecutionTrees {
// Return a range that contains the indices of the rows that have to be
// exported from the `idTable` given the `LimitOffsetClause`. It takes into
// account the LIMIT, the OFFSET, and the actual size of the `idTable`
public:
static cppcoro::generator<TableWithRange> getRowIndices(
LimitOffsetClause limitOffset, const Result& result);

private:
FRIEND_TEST(ExportQueryExecutionTrees, getIdTablesReturnsSingletonIterator);
FRIEND_TEST(ExportQueryExecutionTrees, getIdTablesMirrorsGenerator);
FRIEND_TEST(ExportQueryExecutionTrees, ensureCorrectSlicingOfSingleIdTable);
Expand Down
135 changes: 135 additions & 0 deletions src/engine/Server.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@

#include "engine/Server.h"

#include <index/DeltaTriples.h>

#include <boost/url.hpp>
#include <sstream>
#include <string>
Expand Down Expand Up @@ -492,6 +494,139 @@
parsedHttpRequest.operation_);
}

// _____________________________________________________________________________
Awaitable<void> Server::executeUpdate(
const ParsedQuery& query, const QueryExecutionTree& qet,
const ad_utility::Timer& requestTimer,
SharedCancellationHandle cancellationHandle) {
AD_CONTRACT_CHECK(query.hasUpdateClause());
auto updateClause = query.updateClause();

Check warning on line 503 in src/engine/Server.cpp

View check run for this annotation

Codecov / codecov/patch

src/engine/Server.cpp#L501-L503

Added lines #L501 - L503 were not covered by tests
if (!std::holds_alternative<updateClause::GraphUpdate>(updateClause.op_)) {
throw std::runtime_error(
"Only INSERT/DELETE update operations are currently supported.");
}
auto graphUpdate = std::get<updateClause::GraphUpdate>(updateClause.op_);
auto res = qet.getResult(true);

Check warning on line 509 in src/engine/Server.cpp

View check run for this annotation

Codecov / codecov/patch

src/engine/Server.cpp#L505-L509

Added lines #L505 - L509 were not covered by tests

auto& vocab = index_.getVocab();

Check warning on line 511 in src/engine/Server.cpp

View check run for this annotation

Codecov / codecov/patch

src/engine/Server.cpp#L511

Added line #L511 was not covered by tests
// DeltaTriples transfers the IDs that are actually inserted to its own
// LocalVocab. This LocalVocab only contains IDs that are related to the
// template. Most of the IDs will be added to the DeltaTriples' LocalVocab. An
// ID will not be added if it belongs to a Quad with a variable that has no
// solutions.
LocalVocab localVocab = {};

Check warning on line 517 in src/engine/Server.cpp

View check run for this annotation

Codecov / codecov/patch

src/engine/Server.cpp#L517

Added line #L517 was not covered by tests
// The GraphUpdate consist of a template of `SparqlTripleSimpleWithGraph` and
// in some cases also an GraphPattern. The template contains
// `TripleComponent`s (s, p and o) and a `Graph` (graph). First transform
// everything except Variables in the template to IDs.
using IdOrVariable = std::variant<Id, Variable>;
auto transformSparqlTripleComponent =
[&vocab, &localVocab](TripleComponent component) -> IdOrVariable {

Check warning on line 524 in src/engine/Server.cpp

View check run for this annotation

Codecov / codecov/patch

src/engine/Server.cpp#L522-L524

Added lines #L522 - L524 were not covered by tests
if (component.isVariable()) {
return std::move(component.getVariable());
} else {
return std::move(component).toValueId(vocab, localVocab);
}
};
auto transformGraph =
[&vocab,
&localVocab](SparqlTripleSimpleWithGraph::Graph graph) -> IdOrVariable {
return std::visit(
ad_utility::OverloadCallOperator{
[](const std::monostate&) -> IdOrVariable {
AD_CORRECTNESS_CHECK(
qlever::specialIds().contains(DEFAULT_GRAPH_IRI));
return qlever::specialIds().at(DEFAULT_GRAPH_IRI);
},
[&vocab, &localVocab](const Iri& iri) -> IdOrVariable {
ad_utility::triple_component::Iri i =
ad_utility::triple_component::Iri::fromIriref(iri.iri());
return TripleComponent(i).toValueId(vocab, localVocab);
},
[](const Variable& var) -> IdOrVariable { return var; }},
graph);
};
auto transformSparqlTripleSimple =
[&transformSparqlTripleComponent,
&transformGraph](SparqlTripleSimpleWithGraph triple) {
return std::array{transformSparqlTripleComponent(std::move(triple.s_)),
transformSparqlTripleComponent(std::move(triple.p_)),
transformSparqlTripleComponent(std::move(triple.o_)),
transformGraph(std::move(triple.g_))};
};
std::vector<std::array<IdOrVariable, 4>> toInsertTemplates =
ad_utility::transform(std::move(graphUpdate.toInsert_),
transformSparqlTripleSimple);
std::vector<std::array<IdOrVariable, 4>> toDeleteTemplates =
ad_utility::transform(std::move(graphUpdate.toDelete_),
transformSparqlTripleSimple);

Check warning on line 562 in src/engine/Server.cpp

View check run for this annotation

Codecov / codecov/patch

src/engine/Server.cpp#L526-L562

Added lines #L526 - L562 were not covered by tests

// To calculate the set of quads for the update, for each row in the template
// resolve the variables using each row of the result to obtain a quad without
// variables. These quads can then be used with `DeltaTriples`.
auto resolveVariable = [](const IdTable& idTable, const size_t& row,
const VariableToColumnMap& variableColumns,
IdOrVariable idOrVar) -> std::optional<Id> {

Check warning on line 569 in src/engine/Server.cpp

View check run for this annotation

Codecov / codecov/patch

src/engine/Server.cpp#L567-L569

Added lines #L567 - L569 were not covered by tests
if (std::holds_alternative<Variable>(idOrVar)) {
auto var = std::get<Variable>(std::move(idOrVar));

Check warning on line 571 in src/engine/Server.cpp

View check run for this annotation

Codecov / codecov/patch

src/engine/Server.cpp#L571

Added line #L571 was not covered by tests
if (!variableColumns.contains(var)) {
return std::nullopt;
} else {
return idTable(row, variableColumns.at(var).columnIndex_);
}

Check warning on line 576 in src/engine/Server.cpp

View check run for this annotation

Codecov / codecov/patch

src/engine/Server.cpp#L573-L576

Added lines #L573 - L576 were not covered by tests
} else if (std::holds_alternative<Id>(idOrVar)) {
return std::get<Id>(idOrVar);
} else {
AD_FAIL();
}
};
auto computeQuadsForResultRow = [&resolveVariable](
auto& templates, auto& result,
const IdTable& idTable, uint64_t row,
const VariableToColumnMap&
variableColumns) {

Check warning on line 587 in src/engine/Server.cpp

View check run for this annotation

Codecov / codecov/patch

src/engine/Server.cpp#L578-L587

Added lines #L578 - L587 were not covered by tests
for (const auto& [s, p, o, g] : templates) {
auto subject = resolveVariable(idTable, row, variableColumns, s);
auto predicate = resolveVariable(idTable, row, variableColumns, p);
auto object = resolveVariable(idTable, row, variableColumns, o);
auto graph = resolveVariable(idTable, row, variableColumns, g);

Check warning on line 592 in src/engine/Server.cpp

View check run for this annotation

Codecov / codecov/patch

src/engine/Server.cpp#L589-L592

Added lines #L589 - L592 were not covered by tests

if (!subject.has_value() || !predicate.has_value() ||
!object.has_value() || !graph.has_value()) {
continue;
}
result.emplace_back(std::array{*subject, *predicate, *object, *graph});
}
return result;
};
std::vector<IdTriple<>> toInsert;
std::vector<IdTriple<>> toDelete;

Check warning on line 603 in src/engine/Server.cpp

View check run for this annotation

Codecov / codecov/patch

src/engine/Server.cpp#L596-L603

Added lines #L596 - L603 were not covered by tests
// The maximum result size is size(query result) x num template rows. The
// actual result can be smaller if there are template rows with variables for
// which a result row does not have a value.
toInsert.reserve(res->idTable().size() * toInsertTemplates.size());
toDelete.reserve(res->idTable().size() * toDeleteTemplates.size());

Check warning on line 608 in src/engine/Server.cpp

View check run for this annotation

Codecov / codecov/patch

src/engine/Server.cpp#L607-L608

Added lines #L607 - L608 were not covered by tests
for (const auto& [pair, range] :
ExportQueryExecutionTrees::getRowIndices(query._limitOffset, *res)) {
auto& idTable = pair.idTable_;

Check warning on line 611 in src/engine/Server.cpp

View check run for this annotation

Codecov / codecov/patch

src/engine/Server.cpp#L610-L611

Added lines #L610 - L611 were not covered by tests
for (uint64_t i : range) {
computeQuadsForResultRow(toInsertTemplates, toInsert, idTable, i,
qet.getVariableColumns());
cancellationHandle->throwIfCancelled();

Check warning on line 615 in src/engine/Server.cpp

View check run for this annotation

Codecov / codecov/patch

src/engine/Server.cpp#L613-L615

Added lines #L613 - L615 were not covered by tests

computeQuadsForResultRow(toDeleteTemplates, toDelete, idTable, i,
qet.getVariableColumns());
cancellationHandle->throwIfCancelled();
}
}

Check warning on line 621 in src/engine/Server.cpp

View check run for this annotation

Codecov / codecov/patch

src/engine/Server.cpp#L617-L621

Added lines #L617 - L621 were not covered by tests

// TODO<qup42> use the actual DeltaTriples object
DeltaTriples deltaTriples = DeltaTriples{index_};
deltaTriples.insertTriples(cancellationHandle, std::move(toInsert));
deltaTriples.deleteTriples(cancellationHandle, std::move(toDelete));

Check warning on line 626 in src/engine/Server.cpp

View check run for this annotation

Codecov / codecov/patch

src/engine/Server.cpp#L624-L626

Added lines #L624 - L626 were not covered by tests

co_return;
}

Check warning on line 629 in src/engine/Server.cpp

View check run for this annotation

Codecov / codecov/patch

src/engine/Server.cpp#L628-L629

Added lines #L628 - L629 were not covered by tests
// _____________________________________________________________________________
json Server::composeErrorResponseJson(
const string& query, const std::string& errorMsg,
Expand Down
7 changes: 7 additions & 0 deletions src/engine/Server.h
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,13 @@ class Server {
const ad_utility::httpUtils::HttpRequest auto& request, auto&& send,
TimeLimit timeLimit);

// Execute an update and send a response for the request. This function is
// comparable to `sendStreamableResponse` for queries.
Awaitable<void> executeUpdate(const ParsedQuery& query,
const QueryExecutionTree& qet,
const ad_utility::Timer& requestTimer,
SharedCancellationHandle cancellationHandle);

static json composeErrorResponseJson(
const string& query, const std::string& errorMsg,
ad_utility::Timer& requestTimer,
Expand Down
Loading