Skip to content

Commit

Permalink
Everything compiles.
Browse files Browse the repository at this point in the history
TODO:
* Binary search expressions (at least partially).

* Fix unit tests
* Clean everything up.
  • Loading branch information
joka921 committed Jul 5, 2024
1 parent 9c73759 commit 05089b7
Show file tree
Hide file tree
Showing 9 changed files with 99 additions and 39 deletions.
2 changes: 1 addition & 1 deletion benchmark/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,6 @@ addAndLinkBenchmark(JoinAlgorithmBenchmark testUtil memorySize)

addAndLinkBenchmark(IdTableCompressedWriterBenchmark engine testUtil)

addAndLinkBenchmark(ParallelMergeBenchmark)
addAndLinkBenchmark(ParallelMergeBenchmark testUtil)

addAndLinkBenchmark(GroupByHashMapBenchmark engine testUtil gtest gmock)
19 changes: 12 additions & 7 deletions src/engine/LocalVocab.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -81,15 +81,20 @@ std::vector<LocalVocab::LiteralOrIri> LocalVocab::getAllWordsForTesting()

// TODO<joka921> Consider moving the cheap case (if precomputed) into the
// header.
std::pair<VocabIndex, bool> LocalVocabEntry::lowerBoundInIndex() const {
auto LocalVocabEntry::lowerBoundInIndex() const -> BoundsInIndex {
if (indexStatus != IndexStatus::NOT_LOOKED_UP) {
return {lowerBoundInIndex_, indexStatus == EQUAL};
return {lowerBoundInIndex_, upperBoundInIndex_, exactMatchInIndex_,
indexStatus == EQUAL};
}
const IndexImpl& index = IndexImpl::staticGlobalSingletonIndex();
std::pair<VocabIndex, bool> result;
auto& [vocabIndex, isContained] = result;
isContained = index.getVocab().getId(toStringRepresentation(), &vocabIndex);
indexStatus = isContained ? IndexStatus::EQUAL : IndexStatus::GREATER;
lowerBoundInIndex_ = vocabIndex;
BoundsInIndex result;
const auto& vocab = index.getVocab();
result.lowerBound_ = vocab.lower_bound(toStringRepresentation());
result.upperBound_ = vocab.upper_bound(toStringRepresentation());
result.isContained_ =
index.getVocab().getId(toStringRepresentation(), &result.exactMatch_);
indexStatus = result.isContained_ ? IndexStatus::EQUAL : IndexStatus::GREATER;
lowerBoundInIndex_ = result.lowerBound_;
upperBoundInIndex_ = result.upperBound_;
return result;
}
3 changes: 0 additions & 3 deletions src/engine/sparqlExpressions/RelationalExpressionHelpers.h
Original file line number Diff line number Diff line change
Expand Up @@ -160,10 +160,7 @@ auto makeValueId(const S& value, const EvaluationContext* context) {

} else {
static_assert(ad_utility::isSimilar<S, LocalVocabEntry>);
// TODO<joka921> We have to reinstate the correct handling of the equal
// ranges.
return Id::makeFromLocalVocabIndex(&value);
// return getRangeFromVocab(value, context);
}
};

Expand Down
10 changes: 9 additions & 1 deletion src/global/IndexTypes.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,12 +34,20 @@ class alignas(16) LocalVocabEntry
private:
using Base = ad_utility::triple_component::LiteralOrIri;
mutable CopyableAtomic<VocabIndex> lowerBoundInIndex_;
mutable CopyableAtomic<VocabIndex> upperBoundInIndex_;
mutable CopyableAtomic<VocabIndex> exactMatchInIndex_;
enum IndexStatus { NOT_LOOKED_UP, GREATER, EQUAL };
mutable CopyableAtomic<IndexStatus> indexStatus = NOT_LOOKED_UP;

public:
struct BoundsInIndex {
VocabIndex lowerBound_;
VocabIndex upperBound_;
VocabIndex exactMatch_;
bool isContained_;
};
using Base::Base;
std::pair<VocabIndex, bool> lowerBoundInIndex() const;
BoundsInIndex lowerBoundInIndex() const;

LocalVocabEntry(const Base& base) : Base{base} {}
LocalVocabEntry(Base&& base) noexcept : Base{std::move(base)} {}
Expand Down
64 changes: 50 additions & 14 deletions src/global/ValueId.h
Original file line number Diff line number Diff line change
Expand Up @@ -137,14 +137,12 @@ class ValueId {
if (type == LocalVocabIndex && otherType == LocalVocabIndex) [[unlikely]] {
return *getLocalVocabIndex() == *other.getLocalVocabIndex();
} else if (type == VocabIndex) {
auto [lowerBound, isContained] =
(other.getLocalVocabIndex())->lowerBoundInIndex();
return isContained && lowerBound == getVocabIndex();
auto x = (other.getLocalVocabIndex())->lowerBoundInIndex();
return x.isContained_ && x.exactMatch_ == getVocabIndex();
} else if (otherType == VocabIndex) {
// TODO<joka921> Code duplication.
auto [lowerBound, isContained] =
(getLocalVocabIndex())->lowerBoundInIndex();
return isContained && lowerBound == other.getVocabIndex();
auto x = (getLocalVocabIndex())->lowerBoundInIndex();
return x.isContained_ && x.lowerBound_ == other.getVocabIndex();
}
return _bits == other._bits;
}
Expand All @@ -167,28 +165,66 @@ class ValueId {
if (type == LocalVocabIndex && otherType == LocalVocabIndex) [[unlikely]] {
return *getLocalVocabIndex() <=> *other.getLocalVocabIndex();
} else if (type == VocabIndex) {
auto [lowerBound, isContained] =
(other.getLocalVocabIndex())->lowerBoundInIndex();
auto x = (other.getLocalVocabIndex())->lowerBoundInIndex();
auto lowerBound = x.exactMatch_;
if (lowerBound == getVocabIndex()) {
return isContained ? std::strong_ordering::equal
: std::strong_ordering::less;
return x.isContained_ ? std::strong_ordering::equal
: std::strong_ordering::less;
} else {
return getVocabIndex() <=> lowerBound;
}
} else if (otherType == VocabIndex) {
// TODO<joka921> Code duplication.
auto [lowerBound, isContained] =
(getLocalVocabIndex())->lowerBoundInIndex();
auto x = (getLocalVocabIndex())->lowerBoundInIndex();
auto lowerBound = x.exactMatch_;
if (lowerBound == other.getVocabIndex()) {
return isContained ? std::strong_ordering::equal
: std::strong_ordering::greater;
return x.isContained_ ? std::strong_ordering::equal
: std::strong_ordering::greater;
} else {
return lowerBound <=> other.getVocabIndex();
}
}
return _bits <=> other._bits;
}

constexpr std::strong_ordering compareQuarternary(
const ValueId& other) const {
using enum Datatype;
auto type = getDatatype();
auto otherType = other.getDatatype();
if (type != LocalVocabIndex && otherType != LocalVocabIndex) {
return _bits <=> other._bits;
}
if (type == LocalVocabIndex && otherType == LocalVocabIndex) [[unlikely]] {
return *getLocalVocabIndex() <=> *other.getLocalVocabIndex();
} else if (type == VocabIndex) {
auto x = (other.getLocalVocabIndex())->lowerBoundInIndex();
auto lowerBound = x.lowerBound_;
auto upperBound = x.upperBound_;
auto idx = getVocabIndex();
if (idx < lowerBound) {
return std::strong_ordering::less;
} else if (idx >= upperBound) {
return std::strong_ordering::greater;
} else {
return std::strong_ordering::equal;
}
} else if (otherType == VocabIndex) {
// TODO<joka921> Code duplication.
auto x = (getLocalVocabIndex())->lowerBoundInIndex();
auto lowerBound = x.lowerBound_;
auto upperBound = x.upperBound_;
if (upperBound <= other.getVocabIndex()) {
return std::strong_ordering::less;
} else if (lowerBound > other.getVocabIndex()) {
return std::strong_ordering::greater;
} else {
return std::strong_ordering::equal;
}
}
return _bits <=> other._bits;
}

/// Get the underlying bit representation, e.g. for compression etc.
[[nodiscard]] constexpr T getBits() const noexcept { return _bits; }
/// Construct from the underlying bit representation. `bits` must have been
Expand Down
12 changes: 11 additions & 1 deletion src/global/ValueIdComparators.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,15 @@ namespace valueIdComparators {
// Equal, NotEqual, GreaterEqual, GreaterThan.
enum struct Comparison { LT, LE, EQ, NE, GE, GT };

inline int orderingToInt(std::strong_ordering o) {
if (o == std::strong_ordering::less) {
return -1;
} else if (o == std::strong_ordering::greater) {
return 1;
}
return 0;
}

// This enum can be used to configure the behavior of the `compareIds` method
// below in the case when two `Id`s have incompatible datatypes (e.g.
// `VocabIndex` and a numeric type, or `Undefined` and any other type).
Expand Down Expand Up @@ -470,7 +479,8 @@ ComparisonResult compareIdsImpl(ValueId a, ValueId b, auto comparator) {
// on ValueIds already does the right thing.
if (a.getDatatype() == Datatype::LocalVocabIndex ||
b.getDatatype() == Datatype::LocalVocabIndex) {
return fromBool(std::invoke(comparator, a, b));
return fromBool(
std::invoke(comparator, orderingToInt(a.compareQuarternary(b)), 0));
}

auto visitor = [comparator]<typename A, typename B>(
Expand Down
3 changes: 2 additions & 1 deletion src/index/Vocabulary.h
Original file line number Diff line number Diff line change
Expand Up @@ -244,7 +244,8 @@ class Vocabulary {
const SortLevel level = SortLevel::QUARTERNARY) const;

// _______________________________________________________________
IndexType upper_bound(const string& word, const SortLevel level) const;
IndexType upper_bound(const string& word,
const SortLevel level = SortLevel::QUARTERNARY) const;

const ExternalVocabulary& getExternalVocab() const {
return externalVocabulary_;
Expand Down
16 changes: 8 additions & 8 deletions test/RandomExpressionTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -100,8 +100,8 @@ TEST(UuidExpression, evaluateStrUuidExpression) {
// check that none of the results equals all previous results
std::unordered_set<std::string> strUuids;
for (auto uuid : resultVector) {
ASSERT_TRUE(std::holds_alternative<LiteralOrIri>(uuid));
LiteralOrIri litUuid = std::get<LiteralOrIri>(uuid);
ASSERT_TRUE(std::holds_alternative<LocalVocabEntry>(uuid));
LiteralOrIri litUuid = std::get<LocalVocabEntry>(uuid);
ASSERT_TRUE(litUuid.isLiteral());
std::string_view strUuid =
asStringViewUnsafe(litUuid.getLiteral().getContent());
Expand All @@ -113,8 +113,8 @@ TEST(UuidExpression, evaluateStrUuidExpression) {
auto resultAsVariant2 = StrUuidExpression{}.evaluate(&evaluationContext);
ASSERT_TRUE(std::holds_alternative<IdOrLiteralOrIri>(resultAsVariant2));
IdOrLiteralOrIri litOrIriUuid = std::get<IdOrLiteralOrIri>(resultAsVariant2);
ASSERT_TRUE(std::holds_alternative<LiteralOrIri>(litOrIriUuid));
ASSERT_TRUE(std::get<LiteralOrIri>(litOrIriUuid).isLiteral());
ASSERT_TRUE(std::holds_alternative<LocalVocabEntry>(litOrIriUuid));
ASSERT_TRUE(std::get<LocalVocabEntry>(litOrIriUuid).isLiteral());
}

TEST(UuidExpression, evaluateUuidExpression) {
Expand All @@ -132,8 +132,8 @@ TEST(UuidExpression, evaluateUuidExpression) {
// check that none of the results equals all of the other results
std::unordered_set<std::string> strUuids;
for (auto uuid : resultVector) {
ASSERT_TRUE(std::holds_alternative<LiteralOrIri>(uuid));
LiteralOrIri litUuid = std::get<LiteralOrIri>(uuid);
ASSERT_TRUE(std::holds_alternative<LocalVocabEntry>(uuid));
LiteralOrIri litUuid = std::get<LocalVocabEntry>(uuid);
ASSERT_TRUE(litUuid.isIri());
std::string_view iriUuid =
asStringViewUnsafe(litUuid.getIri().getContent());
Expand All @@ -145,6 +145,6 @@ TEST(UuidExpression, evaluateUuidExpression) {
auto resultAsVariant2 = UuidExpression{}.evaluate(&evaluationContext);
ASSERT_TRUE(std::holds_alternative<IdOrLiteralOrIri>(resultAsVariant2));
IdOrLiteralOrIri litOrIriUuid = std::get<IdOrLiteralOrIri>(resultAsVariant2);
ASSERT_TRUE(std::holds_alternative<LiteralOrIri>(litOrIriUuid));
ASSERT_TRUE(std::get<LiteralOrIri>(litOrIriUuid).isIri());
ASSERT_TRUE(std::holds_alternative<LocalVocabEntry>(litOrIriUuid));
ASSERT_TRUE(std::get<LocalVocabEntry>(litOrIriUuid).isIri());
}
9 changes: 6 additions & 3 deletions test/RelationalExpressionTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -472,9 +472,12 @@ auto testNotComparableHelper(T leftValue, U rightValue,
LocalVocab localVocab;
IdTable table{alloc};
sparqlExpression::EvaluationContext context{
*getQec(), map,
table, alloc,
localVocab, std::make_shared<ad_utility::CancellationHandle<>>()};
*TestContext{}.qec,
map,
table,
alloc,
localVocab,
std::make_shared<ad_utility::CancellationHandle<>>()};
AD_CONTRACT_CHECK(rightValue.size() == 5);
context._beginIndex = 0;
context._endIndex = 5;
Expand Down

0 comments on commit 05089b7

Please sign in to comment.