Skip to content

Commit

Permalink
Fix another bug.
Browse files Browse the repository at this point in the history
Signed-off-by: Johannes Kalmbach <[email protected]>
  • Loading branch information
joka921 committed Jan 8, 2025
1 parent c03f3e5 commit 2da52ab
Show file tree
Hide file tree
Showing 10 changed files with 80 additions and 54 deletions.
4 changes: 2 additions & 2 deletions src/engine/Bind.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
#include "Bind.h"

#include "engine/CallFixedSize.h"
#include "engine/ExistsScan.h"
#include "engine/ExistsJoin.h"
#include "engine/QueryExecutionTree.h"
#include "engine/sparqlExpressions/SparqlExpression.h"
#include "engine/sparqlExpressions/SparqlExpressionGenerators.h"
Expand All @@ -16,7 +16,7 @@
Bind::Bind(QueryExecutionContext* qec,
std::shared_ptr<QueryExecutionTree> subtree, parsedQuery::Bind b)
: Operation(qec), _subtree(std::move(subtree)), _bind(std::move(b)) {
_subtree = ExistsScan::addExistsScansToSubtree(
_subtree = ExistsJoin::addExistsScansToSubtree(
_bind._expression, std::move(_subtree), getExecutionContext(),
cancellationHandle_);
}
Expand Down
2 changes: 1 addition & 1 deletion src/engine/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -14,5 +14,5 @@ add_library(engine
CartesianProductJoin.cpp TextIndexScanForWord.cpp TextIndexScanForEntity.cpp
TextLimit.cpp LazyGroupBy.cpp GroupByHashMapOptimization.cpp SpatialJoin.cpp
CountConnectedSubgraphs.cpp SpatialJoinAlgorithms.cpp PathSearch.cpp ExecuteUpdate.cpp
Describe.cpp ExistsScan.cpp)
Describe.cpp ExistsJoin.cpp)
qlever_target_link_libraries(engine util index parser sparqlExpressions http SortPerformanceEstimator Boost::iostreams s2)
26 changes: 13 additions & 13 deletions src/engine/ExistsScan.cpp → src/engine/ExistsJoin.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,15 @@
// Chair of Algorithms and Data Structures.
// Author: Johannes Kalmbach <[email protected]>

#include "engine/ExistsScan.h"
#include "engine/ExistsJoin.h"

#include "engine/QueryPlanner.h"
#include "engine/sparqlExpressions/ExistsExpression.h"
#include "engine/sparqlExpressions/SparqlExpression.h"
#include "util/JoinAlgorithms/JoinAlgorithms.h"

// _____________________________________________________________________________
ExistsScan::ExistsScan(QueryExecutionContext* qec,
ExistsJoin::ExistsJoin(QueryExecutionContext* qec,
std::shared_ptr<QueryExecutionTree> left,
std::shared_ptr<QueryExecutionTree> right,
Variable existsVariable)
Expand All @@ -24,16 +24,16 @@ ExistsScan::ExistsScan(QueryExecutionContext* qec,
}

// _____________________________________________________________________________
string ExistsScan::getCacheKeyImpl() const {
string ExistsJoin::getCacheKeyImpl() const {
return absl::StrCat("EXISTS SCAN left: ", left_->getCacheKey(),
" right: ", right_->getCacheKey());
}

// _____________________________________________________________________________
string ExistsScan::getDescriptor() const { return "EXISTS scan"; }
string ExistsJoin::getDescriptor() const { return "EXISTS scan"; }

// ____________________________________________________________________________
VariableToColumnMap ExistsScan::computeVariableToColumnMap() const {
VariableToColumnMap ExistsJoin::computeVariableToColumnMap() const {
auto res = left_->getVariableColumns();
AD_CONTRACT_CHECK(
!res.contains(existsVariable_),
Expand All @@ -43,18 +43,18 @@ VariableToColumnMap ExistsScan::computeVariableToColumnMap() const {
}

// ____________________________________________________________________________
size_t ExistsScan::getResultWidth() const {
size_t ExistsJoin::getResultWidth() const {
// We add one column to the input.
return left_->getResultWidth() + 1;
}

// ____________________________________________________________________________
vector<ColumnIndex> ExistsScan::resultSortedOn() const {
vector<ColumnIndex> ExistsJoin::resultSortedOn() const {
return left_->resultSortedOn();
}

// ____________________________________________________________________________
float ExistsScan::getMultiplicity(size_t col) {
float ExistsJoin::getMultiplicity(size_t col) {
if (col < getResultWidth() - 1) {
return left_->getMultiplicity(col);
}
Expand All @@ -64,18 +64,18 @@ float ExistsScan::getMultiplicity(size_t col) {
}

// ____________________________________________________________________________
uint64_t ExistsScan::getSizeEstimateBeforeLimit() {
uint64_t ExistsJoin::getSizeEstimateBeforeLimit() {
return left_->getSizeEstimate();
}

// ____________________________________________________________________________
size_t ExistsScan::getCostEstimate() {
size_t ExistsJoin::getCostEstimate() {
return left_->getCostEstimate() + right_->getCostEstimate() +
left_->getSizeEstimate() + right_->getSizeEstimate();
}

// ____________________________________________________________________________
ProtoResult ExistsScan::computeResult([[maybe_unused]] bool requestLaziness) {
ProtoResult ExistsJoin::computeResult([[maybe_unused]] bool requestLaziness) {
auto leftRes = left_->getResult();
auto rightRes = right_->getResult();
const auto& left = leftRes->idTable();
Expand Down Expand Up @@ -139,7 +139,7 @@ ProtoResult ExistsScan::computeResult([[maybe_unused]] bool requestLaziness) {
}

Check warning on line 139 in src/engine/ExistsJoin.cpp

View check run for this annotation

Codecov / codecov/patch

src/engine/ExistsJoin.cpp#L136-L139

Added lines #L136 - L139 were not covered by tests

// _____________________________________________________________________________
std::shared_ptr<QueryExecutionTree> ExistsScan::addExistsScansToSubtree(
std::shared_ptr<QueryExecutionTree> ExistsJoin::addExistsScansToSubtree(
const sparqlExpression::SparqlExpressionPimpl& expression,
std::shared_ptr<QueryExecutionTree> subtree, QueryExecutionContext* qec,
const ad_utility::SharedCancellationHandle& cancellationHandle) {
Expand All @@ -158,7 +158,7 @@ std::shared_ptr<QueryExecutionTree> ExistsScan::addExistsScansToSubtree(
auto pq = exists.argument();
auto tree =
std::make_shared<QueryExecutionTree>(qp.createExecutionTree(pq));
subtree = ad_utility::makeExecutionTree<ExistsScan>(
subtree = ad_utility::makeExecutionTree<ExistsJoin>(
qec, std::move(subtree), std::move(tree), exists.variable());
}
return subtree;
Expand Down
4 changes: 2 additions & 2 deletions src/engine/ExistsScan.h → src/engine/ExistsJoin.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
#include "engine/Operation.h"
#include "engine/QueryExecutionTree.h"

class ExistsScan : public Operation {
class ExistsJoin : public Operation {
private:
std::shared_ptr<QueryExecutionTree> left_;
std::shared_ptr<QueryExecutionTree> right_;
Expand All @@ -19,7 +19,7 @@ class ExistsScan : public Operation {
std::vector<std::array<ColumnIndex, 2>> _matchedColumns;

public:
ExistsScan(QueryExecutionContext* qec,
ExistsJoin(QueryExecutionContext* qec,
std::shared_ptr<QueryExecutionTree> left,
std::shared_ptr<QueryExecutionTree> right,
Variable existsVariable);
Expand Down
4 changes: 2 additions & 2 deletions src/engine/Filter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@

#include "backports/algorithm.h"
#include "engine/CallFixedSize.h"
#include "engine/ExistsScan.h"
#include "engine/ExistsJoin.h"
#include "engine/QueryExecutionTree.h"
#include "engine/QueryPlanner.h"
#include "engine/sparqlExpressions/SparqlExpression.h"
Expand All @@ -31,7 +31,7 @@ Filter::Filter(QueryExecutionContext* qec,
: Operation(qec),
_subtree(std::move(subtree)),
_expression{std::move(expression)} {
_subtree = ExistsScan::addExistsScansToSubtree(
_subtree = ExistsJoin::addExistsScansToSubtree(
_expression, std::move(_subtree), getExecutionContext(),
cancellationHandle_);
setPrefilterExpressionForChildren();
Expand Down
4 changes: 2 additions & 2 deletions src/engine/GroupBy.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
#include <absl/strings/str_join.h>

#include "engine/CallFixedSize.h"
#include "engine/ExistsScan.h"
#include "engine/ExistsJoin.h"
#include "engine/IndexScan.h"
#include "engine/Join.h"
#include "engine/LazyGroupBy.h"
Expand Down Expand Up @@ -55,7 +55,7 @@ GroupBy::GroupBy(QueryExecutionContext* qec, vector<Variable> groupByVariables,
auto sortColumns = computeSortColumns(subtree.get());

for (const auto& alias : _aliases) {
subtree = ExistsScan::addExistsScansToSubtree(
subtree = ExistsJoin::addExistsScansToSubtree(
alias._expression, std::move(subtree), getExecutionContext(),
cancellationHandle_);
}
Expand Down
31 changes: 0 additions & 31 deletions src/util/JoinAlgorithms/FindUndefRanges.h
Original file line number Diff line number Diff line change
Expand Up @@ -196,35 +196,4 @@ struct FindSmallerUndefRanges {
}
};
constexpr FindSmallerUndefRanges findSmallerUndefRanges;
/*
template <std::random_access_iterator It>
auto findSmallerUndefRanges(const auto& row, It begin, It end,
bool& resultMightBeUnsorted)
-> cppcoro::generator<It> {
size_t numLastUndefined = 0;
assert(row.size() > 0);
auto it = ql::ranges::rbegin(row);
auto rend = ql::ranges::rend(row);
for (; it < rend; ++it) {
if (*it != Id::makeUndefined()) {
break;
}
++numLastUndefined;
}
for (; it < rend; ++it) {
if (*it == Id::makeUndefined()) {
return findSmallerUndefRangesArbitrary(row, begin, end,
resultMightBeUnsorted);
}
}
if (numLastUndefined == 0) {
return findSmallerUndefRangesForRowsWithoutUndef(row, begin, end,
resultMightBeUnsorted);
} else {
return findSmallerUndefRangesForRowsWithUndefInLastColumns(
row, numLastUndefined, begin, end, resultMightBeUnsorted);
}
}
*/
} // namespace ad_utility
13 changes: 12 additions & 1 deletion test/QueryPlannerTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2906,10 +2906,21 @@ TEST(QueryPlanner, Describe) {
}

// ____________________________________________________________________________
TEST(QueryPlanner, GroupByRedundanteParensAndVariables) {
TEST(QueryPlanner, GroupByRedundantParensAndVariables) {
auto matcher = h::GroupBy({Variable{"?x"}}, {},
h::IndexScanFromStrings("?x", "?y", "?z"));
h::expect("SELECT ?x { ?x ?y ?z} GROUP BY (?x)", matcher);
h::expect("SELECT ?x { ?x ?y ?z} GROUP BY ?x ?x", matcher);
h::expect("SELECT ?x { ?x ?y ?z} GROUP BY ?x ?x (?x)", matcher);
}

// ____________________________________________________________________________
TEST(QueryPlanner, Exists) {
auto xyz = h::IndexScanFromStrings("?x", "?y", "?z");
auto a = h::IndexScanFromStrings("?x", "?y", "?z");
h::expect(
"SELECT * { ?x ?y ?z FILTER EXISTS {?a ?b ?c}}",
h::Filter("EXISTS {?a ?b ?c}",
h::ExistsJoin(h::IndexScanFromStrings("?x", "?y", "?z"),
h::IndexScanFromStrings("?a", "?b", "?c"))));
}
7 changes: 7 additions & 0 deletions test/QueryPlannerTestHelpers.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
#include "engine/CartesianProductJoin.h"
#include "engine/CountAvailablePredicates.h"
#include "engine/Describe.h"
#include "engine/ExistsJoin.h"
#include "engine/Filter.h"
#include "engine/GroupBy.h"
#include "engine/IndexScan.h"
Expand Down Expand Up @@ -405,6 +406,12 @@ inline QetMatcher Describe(
AD_PROPERTY(::Describe, getDescribe, describeMatcher)));
}

// Match an `ExistsJoin`
inline QetMatcher ExistsJoin(const QetMatcher& leftChild,
const QetMatcher& rightChild) {
return RootOperation<::ExistsJoin>(AllOf(children(leftChild, rightChild)));
}

//
inline QetMatcher QetWithWarnings(
const std::vector<std::string>& warningSubstrings,
Expand Down
39 changes: 39 additions & 0 deletions test/SparqlAntlrParserTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
// Julian Mundhahs <[email protected]>
// Hannah Bast <[email protected]>

#include <engine/sparqlExpressions/ExistsExpression.h>
#include <gtest/gtest.h>

#include <iostream>
Expand All @@ -14,6 +15,7 @@
#include "./SparqlExpressionTestHelpers.h"
#include "./util/GTestHelpers.h"
#include "./util/TripleComponentTestHelpers.h"
#include "QueryPlannerTestHelpers.h"
#include "SparqlAntlrParserTestHelpers.h"
#include "engine/sparqlExpressions/CountStarExpression.h"
#include "engine/sparqlExpressions/GroupConcatExpression.h"
Expand Down Expand Up @@ -1860,6 +1862,43 @@ TEST(SparqlParser, binaryStringExpressions) {
expectBuiltInCall("STRBEFORE(?x, ?y)", makeMatcher(&makeStrBeforeExpression));
}

// Matchers for EXISTS and NOT EXISTS functions.
namespace existsTestHelpers {
using namespace sparqlExpression;
using namespace ::testing;

// Match an EXISTS function
auto existsMatcher(Matcher<const ParsedQuery&> pattern) {
return Pointee(WhenDynamicCastTo<const ExistsExpression&>(
AD_PROPERTY(ExistsExpression, argument, pattern)));
}
// Match a NOT EXISTS function
auto notExistsMatcher(Matcher<const ParsedQuery&> pattern) {
return builtInCallTestHelpers::matchNaryWithChildrenMatchers(
&makeUnaryNegateExpression, existsMatcher(pattern));
}
} // namespace existsTestHelpers

// _____________________________________________________________________________
TEST(SparqlParser, Exists) {
using namespace existsTestHelpers;
auto expectBuiltInCall = ExpectCompleteParse<&Parser::builtInCall>{};
// A matcher that matches the query `SELECT * { ?x <bar> ?foo}`, where the
// FROM and FROM NAMED clauses can still be specified via arguments.
using Graphs = ScanSpecificationAsTripleComponent::Graphs;
auto selectABarFooMatcher = [](Graphs defaultGraphs = std::nullopt,
Graphs namedGraphs = std::nullopt) {
return testing::AllOf(m::SelectQuery(
m::AsteriskSelect(),
m::GraphPattern(m::Triples({{Var{"?a"}, "<bar>", Var{"?foo"}}})),
defaultGraphs, namedGraphs));
};
expectBuiltInCall("EXISTS {?a <bar> ?foo}",
existsMatcher(selectABarFooMatcher()));
expectBuiltInCall("NOT EXISTS {?a <bar> ?foo}",
notExistsMatcher(selectABarFooMatcher()));
}

namespace aggregateTestHelpers {
using namespace sparqlExpression;

Expand Down

0 comments on commit 2da52ab

Please sign in to comment.