Skip to content

Conversation

@RobinTF
Copy link
Collaborator

@RobinTF RobinTF commented Oct 23, 2025

This PR extends the DeltaTriples class to also store changes for internal triples. It also implements a hook that adds internal triples for every object literal with language literals so that these internal triples are filled when required.

This PR clashes with some changes in #2453

Currently WIP, unit tests are missing and some code might not be ideal yet.

@RobinTF RobinTF requested review from Qup42 and joka921 October 23, 2025 15:49
@codecov
Copy link

codecov bot commented Oct 23, 2025

Codecov Report

❌ Patch coverage is 93.27731% with 8 lines in your changes missing coverage. Please review.
✅ Project coverage is 91.04%. Comparing base (c4a8efb) to head (0d8daae).

Files with missing lines Patch % Lines
src/index/DeltaTriples.cpp 93.58% 1 Missing and 4 partials ⚠️
src/engine/ExportQueryExecutionTrees.cpp 71.42% 2 Missing ⚠️
src/index/Permutation.h 66.66% 0 Missing and 1 partial ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##           master    #2461      +/-   ##
==========================================
- Coverage   91.47%   91.04%   -0.43%     
==========================================
  Files         466      466              
  Lines       47158    39479    -7679     
  Branches     5260     5268       +8     
==========================================
- Hits        43137    35943    -7194     
+ Misses       2520     2031     -489     
- Partials     1501     1505       +4     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@sonarqubecloud
Copy link

Copy link
Member

@joka921 joka921 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A first round of 1-1 reviews.

Comment on lines +946 to +948
if (loadInternalPermutation) {
setMetadata(permutation.internalPermutation());
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This can be done directly by the permutation (if the permutation has an internal permutation, then it also registers that internal perm with the delta triples.

Comment on lines -933 to -937
// `Permutation`class, but we first have to deal with The delta triples for
// the additional permutations.
// The setting of the metadata doesn't affect the contents of the delta
// triples, so we don't need to call `writeToDisk`, therefore the second
// argument to `modify` is `false`.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

part of this comment should be kept.

using LocatedTriplesPerBlockAllPermutations =
std::array<LocatedTriplesPerBlock, Permutation::ALL.size()>;
using LocatedTriplesPerBlockInternalPermutations =
std::array<LocatedTriplesPerBlock, 2>;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This magic constant can also be computed.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Permutation::INTERNAL.size()

struct LocatedTripleHandles {
using It = LocatedTriples::iterator;
std::array<It, Permutation::ALL.size()> handles_;
std::array<It, internal ? 2 : Permutation::ALL.size()> handles_;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also no magic constant.


LocatedTriples::iterator& forPermutation(Permutation::Enum permutation);
};
template <bool internal>
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

really the bool, or rather the number of permutations:?

Id objectId = ids.at(2);
auto optionalLiteralOrIri = ExportQueryExecutionTrees::idToLiteralOrIri(
index_, objectId, localVocab_);
if (optionalLiteralOrIri.has_value() &&
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  1. if (! hasValue() ) continue;.

Comment on lines +135 to +136
auto predicate = ExportQueryExecutionTrees::idToLiteralOrIri(
index_, predicateId, localVocab_);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Best do some deduplication, don't look up the same predicate n times...

Comment on lines +159 to +163
modifyTriplesImpl(cancellationHandle, std::move(triples), true,
triplesInserted_, triplesDeleted_, tracer);
modifyTriplesImpl(std::move(cancellationHandle), std::move(internalTriples),
true, internalTriplesInserted_, internalTriplesDeleted_,
tracer);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can't this become part of mdofiyTriplesImpl (which then doesn't get the triplesInserted_ but retrieves them itself.?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Or a wrapper that reduces the code duplication.

return;
}
auto toRange = [](const TriplesToHandlesMap& map) {
auto toRange = [](const TriplesToHandlesMap<false>& map) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is a discussion (at least a TODO) whether we should store the internal triples, instead of doing the (potentially expensive) backup when restarting.

Comment on lines +122 to +123
return ExportQueryExecutionTrees::idToLiteral(
context->_qec.getIndex().getImpl(), id, context->_localVocab);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should be an additional overload, instead of having to update all the call sites.

Copy link
Member

@Qup42 Qup42 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A question and a change from me for the review.

My understanding is that for triples where the object has a language tag the internal permutations stores the that triple with the predicate also having the language tag. So simplified for <foo> <bar> "baz"@en" something like @en@ "baz"is stored. Is this used for anything else thanFILTER(LANG(?x) = "...")`?

LocatedTriples::iterator&
DeltaTriples::LocatedTripleHandles<internal>::forPermutation(
Permutation::Enum permutation) {
return handles_[static_cast<size_t>(permutation)];
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does this assumes that the internal permutations PSO and POS are first and second in the enum for the index into the array to work out?

Comment on lines 266 to +269
ql::ranges::for_each(locatedTriples(),
&LocatedTriplesPerBlock::updateAugmentedMetadata);
ql::ranges::for_each(internalLocatedTriples_,
&LocatedTriplesPerBlock::updateAugmentedMetadata);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Updating the metadata currently is somewhat (but not ludicrously) expensive. We'd only want to update it for the LocatedTriples that we actually changed. So here either locatedTriples() or internalLocatedTriples_. If there are no internal triples to update not at all.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants