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

Implement construct PrefilterExpression from SparqlExpression. #1573

Closed
Show file tree
Hide file tree
Changes from 79 commits
Commits
Show all changes
86 commits
Select commit Hold shift + click to select a range
99da434
Added conversion str to int
realHannes Apr 25, 2024
424d023
templated function for toNumeric, add declaration to NaryExpression.h
realHannes Apr 25, 2024
0117e82
str to num for SparqlExpression implemented + added test
realHannes Apr 25, 2024
35fd0b1
Merge branch 'ad-freiburg:master' into master
realHannes Apr 26, 2024
94356c2
Update src/engine/sparqlExpressions/StringExpressions.cpp
realHannes Apr 26, 2024
decc8ba
Update src/engine/sparqlExpressions/StringExpressions.cpp
realHannes Apr 26, 2024
850152c
Update src/engine/sparqlExpressions/StringExpressions.cpp
realHannes Apr 26, 2024
d650d67
Update src/engine/sparqlExpressions/StringExpressions.cpp
realHannes Apr 26, 2024
46cc697
using now absl::from_chars() and stripping whitespaces for string to …
realHannes Apr 26, 2024
7fc5c28
added new functions to processIriFuntionCall() (for string to number)
realHannes Apr 26, 2024
efb0e24
renaming to: toIntExpression and toDoubleExpression for later more ge…
realHannes Apr 26, 2024
a88537c
made format (clang-format-16)
realHannes Apr 26, 2024
ca1e2e0
Update src/parser/sparqlParser/SparqlQleverVisitor.cpp
realHannes Apr 29, 2024
4adc831
Update src/parser/sparqlParser/SparqlQleverVisitor.cpp
realHannes Apr 29, 2024
d0f0d63
renaming in NaryExpression.h for accordance with other function, addi…
realHannes Apr 29, 2024
a118609
added test coverage for function calls makeIntExpression and make Dou…
realHannes Apr 29, 2024
062052e
toNumeric has now correct behavior and uses absl::from_chars() and st…
realHannes Apr 29, 2024
6d0f42a
made clang-format for NaryExpressionImpl.h
realHannes Apr 29, 2024
f90b8e2
Merge branch 'ad-freiburg:master' into master
realHannes May 6, 2024
fb88493
Merge branch 'ad-freiburg:master' into master
realHannes May 15, 2024
b2eb514
Merge remote-tracking branch 'upstream/master'
realHannes May 16, 2024
b165ac1
Merge branch 'ad-freiburg:master' into master
realHannes Jun 1, 2024
7a3dfb2
Merge branch 'master' of https://github.com/realHannes/qlever
realHannes Jun 1, 2024
fc0ad3a
Merge branch 'ad-freiburg:master' into master
realHannes Jun 6, 2024
f3e6086
Merge branch 'ad-freiburg:master' into master
realHannes Jun 7, 2024
fd4c351
Merge branch 'ad-freiburg:master' into master
realHannes Jun 10, 2024
220c9bf
Merge branch 'ad-freiburg:master' into master
realHannes Jun 12, 2024
a81cb8a
Merge branch 'ad-freiburg:master' into master
realHannes Jun 13, 2024
acc0109
Merge branch 'ad-freiburg:master' into master
realHannes Jun 14, 2024
cb8e560
Merge branch 'ad-freiburg:master' into master
realHannes Jun 20, 2024
2b39970
Merge branch 'ad-freiburg:master' into master
realHannes Jun 28, 2024
a0101e4
Merge branch 'ad-freiburg:master' into master
realHannes Jun 30, 2024
47dee1d
Merge branch 'ad-freiburg:master' into master
realHannes Sep 4, 2024
a8625f9
Merge branch 'ad-freiburg:master' into master
realHannes Sep 9, 2024
7f95069
Merge branch 'ad-freiburg:master' into master
realHannes Sep 12, 2024
28b8a69
Merge branch 'ad-freiburg:master' into master
realHannes Sep 13, 2024
7bb6e01
Merge branch 'ad-freiburg:master' into master
realHannes Sep 14, 2024
edc974a
Add implementation for pre-filtering blocks on their metadata
realHannes Sep 18, 2024
ca6c2ff
Merge branch 'master' into prefilter_on_metadata_relational
realHannes Sep 18, 2024
46be51a
fix spelling error
realHannes Sep 18, 2024
0385b56
add namespace for CompressedBlockPrefiltering.h
realHannes Sep 18, 2024
5707338
use std::ranges::set_union, std::ranges::upper_bound/lower_bound
realHannes Sep 18, 2024
c9687ec
move template specializations into namespace prefilterExpressions
realHannes Sep 18, 2024
d8246f7
fix
realHannes Sep 18, 2024
66b4872
hopefully fix namespace issue
realHannes Sep 18, 2024
e4eddc4
Merge branch 'ad-freiburg:master' into prefilter_on_metadata_relational
realHannes Sep 20, 2024
b5d7dd7
first adaptations regarding the comments
realHannes Sep 20, 2024
802e3aa
Merge branch 'ad-freiburg:master' into prefilter_on_metadata_relational
realHannes Sep 23, 2024
662b1d4
applied suggestions from review
realHannes Sep 24, 2024
510aa9e
fix std::move
realHannes Sep 24, 2024
0d7f75b
Merge branch 'ad-freiburg:master' into prefilter_on_metadata_relational
realHannes Sep 25, 2024
c119200
adjusted CompressedBlockPrefiltering
realHannes Sep 26, 2024
af17181
mark method with override
realHannes Sep 26, 2024
3d7238d
Merge branch 'master' into prefilter_on_metadata_relational
realHannes Oct 8, 2024
5af6138
make further changes to prefiltering procedure and its tests
realHannes Oct 8, 2024
b02dc57
add additional testing on IDs from other datatypes
realHannes Oct 8, 2024
eb86f1b
addition to test Not Expression with And and Or
realHannes Oct 8, 2024
69ed019
changes to test and fix index check fail
realHannes Oct 9, 2024
854322b
increase test coverage for Not expression
realHannes Oct 9, 2024
b2aa689
just add all mixed blocks
realHannes Oct 9, 2024
546c3b3
Merge branch 'ad-freiburg:master' into prefilter_on_metadata_relational
realHannes Oct 9, 2024
7e61cb1
remove unnecessary values in test context
realHannes Oct 9, 2024
009ebed
for sonar check
realHannes Oct 10, 2024
6c19bf6
Merge branch 'ad-freiburg:master' into prefilter_on_metadata_relational
realHannes Oct 10, 2024
bf733ce
Merge branch 'ad-freiburg:master' into environment_for_using_prefilte…
realHannes Oct 12, 2024
5b42c1f
methods to get PrefilterExpresssions from RelationalExpressions (Spar…
realHannes Oct 12, 2024
6cf6609
Completed the implementation for constructing PrefilterExpressions fr…
realHannes Oct 22, 2024
18c4c84
Merge branch 'master' into environment_for_using_prefiltering
realHannes Oct 22, 2024
e4be1fe
all builds should compile now
realHannes Oct 22, 2024
bde09cd
Merge branch 'ad-freiburg:master' into environment_for_using_prefilte…
realHannes Oct 22, 2024
74756fe
fix build issue and increase test coverage
realHannes Oct 22, 2024
1278d39
Merge branch 'master' into environment_for_using_prefiltering
realHannes Oct 22, 2024
47d3d56
Merge branch 'ad-freiburg:master' into environment_for_using_prefilte…
realHannes Oct 25, 2024
49de4d0
introduce test structure from PR1 (#1503)
realHannes Oct 25, 2024
fcefdf0
Merge branch 'master' into environment_for_using_prefiltering
realHannes Oct 28, 2024
9f0efc6
fix build
realHannes Oct 28, 2024
25f325a
implement proposed changes (2)
realHannes Oct 30, 2024
d65acc3
correction for codespell check
realHannes Oct 30, 2024
f85a96f
fix for codespell
realHannes Oct 30, 2024
0a188a5
Merge branch 'ad-freiburg:master' into environment_for_using_prefilte…
realHannes Oct 31, 2024
5f4e586
remove optionality (std::optional) for return value
realHannes Oct 31, 2024
8062753
Merge branch 'ad-freiburg:master' into environment_for_using_prefilte…
realHannes Nov 4, 2024
c06de60
implement proposed improvements (4)
realHannes Nov 4, 2024
95e9027
further adjustments + apply PrefilterExpressions in IndexScan
realHannes Nov 11, 2024
0992fab
Merge branch 'master' into environment_for_using_prefiltering
realHannes Nov 11, 2024
f489b24
few additional adaptations
realHannes Nov 11, 2024
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
10 changes: 5 additions & 5 deletions src/engine/sparqlExpressions/LiteralExpression.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ class LiteralExpression : public SparqlExpression {
mutable std::atomic<IdOrLiteralOrIri*> cachedResult_ = nullptr;

public:
// _________________________________________________________________________
// ___________________________________________________________________________
explicit LiteralExpression(T _value) : _value{std::move(_value)} {}
~LiteralExpression() override {
delete cachedResult_.load(std::memory_order_relaxed);
Expand Down Expand Up @@ -83,7 +83,7 @@ class LiteralExpression : public SparqlExpression {
}
}

// _________________________________________________________________________
// ___________________________________________________________________________
vector<Variable> getUnaggregatedVariables() const override {
if constexpr (std::is_same_v<T, ::Variable>) {
return {_value};
Expand All @@ -92,7 +92,7 @@ class LiteralExpression : public SparqlExpression {
}
}

// ______________________________________________________________________
// ___________________________________________________________________________
string getCacheKey(const VariableToColumnMap& varColMap) const override {
if constexpr (std::is_same_v<T, ::Variable>) {
if (!varColMap.contains(_value)) {
Expand All @@ -118,13 +118,13 @@ class LiteralExpression : public SparqlExpression {
}
}

// ______________________________________________________________________
// ___________________________________________________________________________
bool isConstantExpression() const override {
return !std::is_same_v<T, ::Variable>;
}

protected:
// _________________________________________________________________________
// ___________________________________________________________________________
std::optional<::Variable> getVariableOrNullopt() const override {
if constexpr (std::is_same_v<T, ::Variable>) {
return _value;
Expand Down
258 changes: 249 additions & 9 deletions src/engine/sparqlExpressions/NumericBinaryExpressions.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -34,14 +34,16 @@ inline auto subtract = makeNumericExpression<std::minus<>>();
NARY_EXPRESSION(SubtractExpression, 2,
FV<decltype(subtract), NumericValueGetter>);

// _____________________________________________________________________________
// Power.
inline auto powImpl = [](double base, double exp) {
return std::pow(base, exp);
};
inline auto pow = makeNumericExpression<decltype(powImpl)>();
NARY_EXPRESSION(PowExpression, 2, FV<decltype(pow), NumericValueGetter>);

// Or
// OR and AND
// _____________________________________________________________________________
inline auto orLambda = [](TernaryBool a, TernaryBool b) {
using enum TernaryBool;
if (a == True || b == True) {
Expand All @@ -53,11 +55,7 @@ inline auto orLambda = [](TernaryBool a, TernaryBool b) {
return Id::makeUndefined();
};

NARY_EXPRESSION(OrExpression, 2,
FV<decltype(orLambda), EffectiveBooleanValueGetter>,
SET<SetOfIntervals::Union>);

// And
// _____________________________________________________________________________
inline auto andLambda = [](TernaryBool a, TernaryBool b) {
using enum TernaryBool;
if (a == True && b == True) {
Expand All @@ -68,9 +66,249 @@ inline auto andLambda = [](TernaryBool a, TernaryBool b) {
}
return Id::makeUndefined();
};
NARY_EXPRESSION(AndExpression, 2,
FV<decltype(andLambda), EffectiveBooleanValueGetter>,
SET<SetOfIntervals::Intersection>);

namespace constructPrefilterExpr {
namespace {

// MERGE AND CONJUNCTION
// _____________________________________________________________________________
// For our pre-filtering logic over index scans, we need exactly one
// corresponding PrefilterExpression for each relevant Variable. Thus, if the
// left and right child contain a PrefilterExpression w.r.t. the same Variable,
// combine them here for an AND conjunction. In the following, three examples
// are given on how the following function merges the content of the left and
// right child.
//
// EXAMPLE 1
// left child: {<(>= 10), ?x>, <(!= 5), ?y>}; (?x >= 10 && ?y != 5)
// right child: {}; (std::nullopt)
// The AND conjunction can only evaluate to true, if both child expressions
// evaluate to true. For the given example, we have no PrefilterExpression
// for the right child, but we can certainly assume that the left child
// expression must evaluate to true.
// Thus, return {<(>= 10), ?x>, <(!= 5), ?y>}.
//
// EXAMPLE 2
// left child: {<(= 5), ?x>}; (?x = 5)
// right child: {<(= VocabId(10)), ?y>}; (?y = VocabId(10))
// Returns {<(= 5), ?x>, <(= VocabId(10)), ?y>}.
//
// EXAMPLE 3
// left child: {<(>= 10 AND <= 20), ?x>}; (?x >= 10 && ?x <= 20)
// right child: {<(!= 15), ?x>, <(= 10), ?y>}; (?x != 15 && ?y = 10)
// Returns {<((>= 10 AND <= 20) AND != 15), ?x>, <(= 10), ?y>}
//______________________________________________________________________________
template <typename BinaryPrefilterExpr>
realHannes marked this conversation as resolved.
Show resolved Hide resolved
std::optional<std::vector<PrefilterExprVariablePair>>
realHannes marked this conversation as resolved.
Show resolved Hide resolved
mergeChildrenForAndExpressionImpl(
std::vector<PrefilterExprVariablePair>&& leftChild,
std::vector<PrefilterExprVariablePair>&& rightChild) {
namespace pd = prefilterExpressions::detail;
pd::checkPropertiesForPrefilterConstruction(leftChild);
pd::checkPropertiesForPrefilterConstruction(rightChild);
// Merge the PrefilterExpression vectors from the left and right child.
// Remark: The vectors contain std::pairs, sorted by their respective
// Variable to the PrefilterExpression.
auto itLeft = leftChild.begin();
auto itRight = rightChild.begin();
std::vector<PrefilterExprVariablePair> resPairs;
while (itLeft != leftChild.end() && itRight != rightChild.end()) {
auto& [exprLeft, varLeft] = *itLeft;
auto& [exprRight, varRight] = *itRight;
if (varLeft == varRight) {
resPairs.emplace_back(std::make_unique<BinaryPrefilterExpr>(
std::move(exprLeft), std::move(exprRight)),
varLeft);
++itLeft;
++itRight;
} else if (varLeft < varRight) {
resPairs.emplace_back(std::move(*itLeft));
++itLeft;
} else {
resPairs.emplace_back(std::move(*itRight));
++itRight;
}
}
std::ranges::move(itLeft, leftChild.end(), std::back_inserter(resPairs));
std::ranges::move(itRight, rightChild.end(), std::back_inserter(resPairs));
if (resPairs.empty()) {
// No PrefilterExpression(s) available with this conjunction merge on the
// contents of left and right child.
return std::nullopt;
}
pd::checkPropertiesForPrefilterConstruction(resPairs);
return resPairs;
}

// MERGE OR CONJUNCTION
//______________________________________________________________________________
// Four examples on how this function (OR) merges the content of two children.
//
// EXAMPLE 1
// left child: {} (std::nullopt)
// right child: {<(<= 10), ?y>}
// Given that it is not possible to make a fixed value assumption (true or
// false) for the left (empty) child, it is also unclear if the right child
// must evaluate to true for this OR expression to become true.
// Hence, no PrefilterExpression (std::nullopt) will be returned.
//
// EXAMPLE 2
// left child: {<(= 5), ?y>}
// right child: {<(<= 3), ?x>}
// We want to pre-filter the blocks for the expression: ?y >= 5 || ?x <= 3
// No PrefilterExpression will be returned.
//
// EXAMPLE 3
// left child: {<(>= 5), ?x>}
// right child: {<(= 0), ?x>}
// We want to pre-filter the blocks to the expression: ?x >= 5 || ?x = 0
// The resulting PrefilterExpression is {<(>= 5 OR = 0), ?x>}
//
// EXAMPLE 4
// left child: {<(= 10), ?x), <(!= 0), ?y>}
// right child: {<(<= 0), ?x>}
// We have to construct a PrefilterExpression for (?x >= 10 && ?y != 0) ||
// ?x <= 0. If this OR expression yields true, at least ?x >= 10 || ?x <= 0
// must be staisifed; for this objective we can construct a
// PrefiterExpression. We can't make a distinct prediction w.r.t. ?y != 0
// => not relevant for the PrefilterExpression. Thus, we return the
// PrefilterExpresion {<(>= 10 OR <= 0), ?x>}.
//______________________________________________________________________________
template <typename BinaryPrefilterExpr>
realHannes marked this conversation as resolved.
Show resolved Hide resolved
joka921 marked this conversation as resolved.
Show resolved Hide resolved
std::optional<std::vector<PrefilterExprVariablePair>>
mergeChildrenForOrExpressionImpl(
std::vector<PrefilterExprVariablePair>&& leftChild,
std::vector<PrefilterExprVariablePair>&& rightChild) {
namespace pd = prefilterExpressions::detail;
pd::checkPropertiesForPrefilterConstruction(leftChild);
pd::checkPropertiesForPrefilterConstruction(rightChild);
auto itLeft = leftChild.begin();
auto itRight = rightChild.begin();
std::vector<PrefilterExprVariablePair> resPairs;
while (itLeft != leftChild.end() && itRight != rightChild.end()) {
auto& [exprLeft, varLeft] = *itLeft;
auto& [exprRight, varRight] = *itRight;
if (varLeft == varRight) {
resPairs.emplace_back(std::make_unique<BinaryPrefilterExpr>(
std::move(exprLeft), std::move(exprRight)),
varLeft);
joka921 marked this conversation as resolved.
Show resolved Hide resolved
++itLeft;
++itRight;
} else if (varLeft < varRight) {
++itLeft;
} else {
++itRight;
}
}
if (resPairs.empty()) {
// No PrefilterExpression(s) available with this conjunction merge on the
// contents of left and right child.
return std::nullopt;
}
realHannes marked this conversation as resolved.
Show resolved Hide resolved
pd::checkPropertiesForPrefilterConstruction(resPairs);
return resPairs;
}

joka921 marked this conversation as resolved.
Show resolved Hide resolved
// GET TEMPLATED MERGE FUNCTION (CONJUNCTION AND / OR)
//______________________________________________________________________________
// getMergeFunction (get the respective merging function) follows the
// principles of De Morgan's law. If this is a child of a NotExpression
// (NOT(!)), we have to swap the combination procedure (swap AND(&&) and
// OR(||) respectively). This equals a partial application of De Morgan's
// law. On the resulting PrefilterExpressions, NOT is applied in
// UnaryNegateExpression(Impl). For more details take a look at the
// implementation in NumericUnaryExpressions.cpp (see
// UnaryNegateExpressionImpl).
//
// EXAMPLE
// - How De-Morgan's law is applied in steps
// !((?y != 10 || ?x = 0) || (?x = 5 || ?x >= 10)) is the complete (Sparql
// expression). With De-Morgan's law applied:
// (?y = 10 && ?x != 0) && (?x != 5 && ?x < 10)
//
// {<expr1, var1>, ....<exprN, varN>} represents the PrefilterExpressions
// with their corresponding Variable.
//
// At the current step we have: isNegated = true; because of !(...) (NOT)
// left child: {<(!= 10), ?y>, <(!= 0), ?x>}; (?y != 10 || ?x != 0)
//
// Remark: The (child) expressions of the left and right child have been
// combined with the merging procedure AND
// (mergeChildrenForAndExpressionImpl<prefilterExpression::OrExpression>),
// because with isNegated = true, it is implied that De-Morgan's law is applied.
// Thus, the OR is logically an AND conjunction with its application.
//
// right child: {<((= 5) OR (>= 10)), ?x>} (?x = 5 || ?x >= 10)
//
// isNegated is true, hence we know that we have to partially apply
// De-Morgan's law. Given that, OR switches to an AND. Therefore we use
// mergeChildrenForAndExpressionImpl with OrExpression (PrefilterExpression)
// as a template value (BinaryPrefilterExpr).
// Call mergeChildrenAndExpressionImpl<prefilterExpression::OrExpression>
// with left and right child as args., we get their merged combination:
// {<(!= 10), ?y>, <((!= 0) OR ((= 5) OR (>= 10))), ?x>}
//
// Next their merged value is returned to UnaryNegateExpressionImpl
// (defined in NumericUnaryExpressions.cpp), where for each expression of
// the <PrefilterExpression, Variable> pairs, NOT (NotExpression) is
// applied.
// {<(!= 10), ?y>, <((!= 0) OR ((= 5) OR (>= 10))), ?x>}
// apply NotExpr.: {<!(!= 10), ?y>, <!((!= 0) OR ((= 5) OR (>= 10))), ?x>}
// This yields: {<(= 10), ?y>, <((= 0) AND ((!= 5) AND (< 10))), ?x>}
//______________________________________________________________________________
template <typename BinaryPrefilterExpr>
constexpr auto getMergeFunction(bool isNegated) {
if constexpr (std::is_same_v<BinaryPrefilterExpr,
prefilterExpressions::AndExpression>) {
return !isNegated ? mergeChildrenForAndExpressionImpl<BinaryPrefilterExpr>
: mergeChildrenForOrExpressionImpl<BinaryPrefilterExpr>;
} else {
static_assert(std::is_same_v<BinaryPrefilterExpr,
prefilterExpressions::OrExpression>);
return !isNegated ? mergeChildrenForOrExpressionImpl<BinaryPrefilterExpr>
: mergeChildrenForAndExpressionImpl<BinaryPrefilterExpr>;
}
}
realHannes marked this conversation as resolved.
Show resolved Hide resolved

} // namespace

//______________________________________________________________________________
template <typename BinaryPrefilterExpr, typename NaryOperation>
requires isOperation<NaryOperation>
class LogicalBinaryExpressionImpl : public NaryExpression<NaryOperation> {
public:
using NaryExpression<NaryOperation>::NaryExpression;

std::optional<std::vector<PrefilterExprVariablePair>>
getPrefilterExpressionForMetadata(bool isNegated) const override {
AD_CORRECTNESS_CHECK(this->N == 2);
auto leftChild =
this->getNthChild(0).value()->getPrefilterExpressionForMetadata(
isNegated);
auto rightChild =
this->getNthChild(1).value()->getPrefilterExpressionForMetadata(
isNegated);
return constructPrefilterExpr::getMergeFunction<BinaryPrefilterExpr>(
isNegated)(
leftChild.has_value() ? std::move(leftChild.value())
: std::vector<PrefilterExprVariablePair>{},
rightChild.has_value() ? std::move(rightChild.value())
: std::vector<PrefilterExprVariablePair>{});
realHannes marked this conversation as resolved.
Show resolved Hide resolved
}
};

} // namespace constructPrefilterExpr

//______________________________________________________________________________
using AndExpression = constructPrefilterExpr::LogicalBinaryExpressionImpl<
prefilterExpressions::AndExpression,
Operation<2, FV<decltype(andLambda), EffectiveBooleanValueGetter>,
SET<SetOfIntervals::Intersection>>>;

using OrExpression = constructPrefilterExpr::LogicalBinaryExpressionImpl<
prefilterExpressions::OrExpression,
Operation<2, FV<decltype(orLambda), EffectiveBooleanValueGetter>,
SET<SetOfIntervals::Union>>>;

} // namespace detail

Expand Down Expand Up @@ -100,6 +338,7 @@ SparqlExpression::Ptr makeAndExpression(SparqlExpression::Ptr child1,
SparqlExpression::Ptr child2) {
return std::make_unique<AndExpression>(std::move(child1), std::move(child2));
}

SparqlExpression::Ptr makeOrExpression(SparqlExpression::Ptr child1,
SparqlExpression::Ptr child2) {
return std::make_unique<OrExpression>(std::move(child1), std::move(child2));
Expand All @@ -109,4 +348,5 @@ SparqlExpression::Ptr makePowExpression(SparqlExpression::Ptr child1,
SparqlExpression::Ptr child2) {
return std::make_unique<PowExpression>(std::move(child1), std::move(child2));
}

} // namespace sparqlExpression
Loading
Loading