Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
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
46 changes: 31 additions & 15 deletions src/index/DeltaTriples.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -167,8 +167,8 @@ DeltaTriplesCount DeltaTriples::getCounts() const {
}

// _____________________________________________________________________________
DeltaTriples::Triples DeltaTriples::makeInternalTriples(
const Triples& triples) {
DeltaTriples::Triples DeltaTriples::makeInternalTriples(const Triples& triples,
bool insertion) {
// NOTE: If this logic is ever changed, you need to also change the code
// in `IndexBuilderTypes.h`, the function `getIdMapLambdas` specifically,
// which adds the same extra triples for language tags to the internal triples
Expand All @@ -177,6 +177,14 @@ DeltaTriples::Triples DeltaTriples::makeInternalTriples(
constexpr size_t predicateCacheSize = 50;
ad_utility::util::LRUCache<Id::T, ad_utility::triple_component::Iri>
predicateCache{predicateCacheSize};

// Don't compute the id if it's not used by the code below.
Id languagePredicate =
insertion ? TripleComponent{ad_utility::triple_component::Iri::fromIriref(
LANGUAGE_PREDICATE)}
.toValueId(index_.getVocab(), localVocab_,
index_.encodedIriManager())
: Id::makeUndefined();
for (const auto& triple : triples) {
const auto& ids = triple.ids();
Id objectId = ids.at(2);
Expand All @@ -195,21 +203,29 @@ DeltaTriples::Triples DeltaTriples::makeInternalTriples(
AD_CORRECTNESS_CHECK(optionalPredicate.value().isIri());
return std::move(optionalPredicate.value().getIri());
});
auto specialPredicate = ad_utility::convertToLanguageTaggedPredicate(
predicate,
asStringViewUnsafe(optionalLiteralOrIri.value().getLanguageTag()));
auto langtag =
asStringViewUnsafe(optionalLiteralOrIri.value().getLanguageTag());
auto specialPredicate =
ad_utility::convertToLanguageTaggedPredicate(predicate, langtag);
Id specialId = TripleComponent{std::move(specialPredicate)}.toValueId(
index_.getVocab(), localVocab_, index_.encodedIriManager());
// NOTE: We currently only add one of the language triples, specifically
// `<subject> @language@<predicate> "object"@language` because it is
// directly tied to a regular triple, so insertion and removal work exactly
// the same. `<object> ql:langtag <@language>` on the other hand needs
// either some sort of reference counting or we have to keep it
// indefinitely, even if the object is removed. This means that some queries
// will return no results for entries with language tags that were inserted
// via an UPDATE operation.
// Extra triple `<subject> @language@<predicate> "object"@language`.
internalTriples.push_back(
IdTriple<0>{std::array{ids.at(0), specialId, ids.at(2), ids.at(3)}});
Id langtagId =
TripleComponent{ad_utility::convertLangtagToEntityUri(langtag)}
.toValueId(index_.getVocab(), localVocab_,
index_.encodedIriManager());
// Because we don't track the exact counts of existing objects, we just
// conservatively add these internal triples on insertion, and never remove
// them. This is inefficient, but never wrong because queries that use these
// internal triples will always join these internal triples with a regular
// index scan.
if (insertion) {
// Extra triple `<object> ql:langtag <@language>`.
internalTriples.push_back(IdTriple<0>{
std::array{ids.at(2), languagePredicate, langtagId, ids.at(3)}});
}
}
// Because of the special predicates, we need to re-sort the triples.
ql::ranges::sort(internalTriples);
Expand All @@ -221,7 +237,7 @@ void DeltaTriples::insertTriples(CancellationHandle cancellationHandle,
Triples triples,
ad_utility::timer::TimeTracer& tracer) {
tracer.beginTrace("makeInternalTriples");
auto internalTriples = makeInternalTriples(triples);
auto internalTriples = makeInternalTriples(triples, true);
tracer.endTrace("makeInternalTriples");
tracer.beginTrace("externalPermutation");
modifyTriplesImpl<false, true>(cancellationHandle, std::move(triples),
Expand All @@ -240,7 +256,7 @@ void DeltaTriples::deleteTriples(CancellationHandle cancellationHandle,
Triples triples,
ad_utility::timer::TimeTracer& tracer) {
tracer.beginTrace("makeInternalTriples");
auto internalTriples = makeInternalTriples(triples);
auto internalTriples = makeInternalTriples(triples, false);
tracer.endTrace("makeInternalTriples");
tracer.beginTrace("externalPermutation");
modifyTriplesImpl<false, false>(cancellationHandle, std::move(triples),
Expand Down
7 changes: 5 additions & 2 deletions src/index/DeltaTriples.h
Original file line number Diff line number Diff line change
Expand Up @@ -213,8 +213,11 @@ class DeltaTriples {
// bunch of triples to be inserted into the internal permutation to make
// things like efficient language filters work. This currently performs a
// lookup from disk to check the language tag, but in the future this may be
// implemented more efficiently.
Triples makeInternalTriples(const Triples& triples);
// implemented more efficiently. If `insertion` is false, then some internal
// triples will not be created, in particular the triple of the form
// `<object> ql:langtag <@language>`, which is not always safe to delete,
// but doesn't cause issues when it's present.
Triples makeInternalTriples(const Triples& triples, bool insertion);

// Insert triples.
void insertTriples(CancellationHandle cancellationHandle, Triples triples,
Expand Down
15 changes: 13 additions & 2 deletions test/DeltaTriplesTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -443,6 +443,10 @@ TEST_F(DeltaTriplesTest, insertTriplesAndDeleteTriples) {
"<a> <other> \"def\"@de", "<a> <other> \"def\"@es"}));
auto a = iri("<a>");
auto b = iri("<b>");
auto lp = iri(LANGUAGE_PREDICATE);
auto de = TripleComponent{ad_utility::convertLangtagToEntityUri("de")};
auto en = TripleComponent{ad_utility::convertLangtagToEntityUri("en")};
auto es = TripleComponent{ad_utility::convertLangtagToEntityUri("es")};
EXPECT_THAT(deltaTriples,
TriplesAre({{a, b, TripleComponent{1}},
{a, b, lit("\"abc\"")},
Expand All @@ -453,7 +457,11 @@ TEST_F(DeltaTriplesTest, insertTriplesAndDeleteTriples) {
{a, iri("<other>"), lit("\"def\"@de")},
{a, iri("<other>"), lit("\"def\"@es")}},
{},
{{a, iri("@de@<b>"), lit("\"abc\"@de")},
{{lit("\"abc\"@de"), lp, de},
{lit("\"abc\"@en"), lp, en},
{lit("\"def\"@de"), lp, de},
{lit("\"def\"@es"), lp, es},
{a, iri("@de@<b>"), lit("\"abc\"@de")},
{a, iri("@en@<b>"), lit("\"abc\"@en")},
{a, iri("@de@<other>"), lit("\"def\"@de")},
{a, iri("@es@<other>"), lit("\"def\"@es")}},
Expand All @@ -477,7 +485,10 @@ TEST_F(DeltaTriplesTest, insertTriplesAndDeleteTriples) {
{a, b, iri("<abc>")},
{a, iri("<other>"), lit("\"def\"@de")},
{a, iri("<other>"), lit("\"def\"@es")}},
{},
{{lit("\"abc\"@de"), lp, de},
{lit("\"abc\"@en"), lp, en},
{lit("\"def\"@de"), lp, de},
{lit("\"def\"@es"), lp, es}},
{{a, iri("@de@<b>"), lit("\"abc\"@de")},
{a, iri("@en@<b>"), lit("\"abc\"@en")},
{a, iri("@de@<other>"), lit("\"def\"@de")},
Expand Down
14 changes: 7 additions & 7 deletions test/ExecuteUpdateTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -162,14 +162,14 @@ TEST(ExecuteUpdate, executeUpdate) {
expectExecuteUpdate("DROP SILENT ALL", NumTriples(0, 8, 8, 0, 1));
expectExecuteUpdate("ADD <x> TO <x>", NumTriples(0, 0, 0));
expectExecuteUpdate("ADD SILENT <x> TO DEFAULT", NumTriples(0, 0, 0));
expectExecuteUpdate("ADD DEFAULT TO <x>", NumTriples(8, 0, 8, 1, 0));
expectExecuteUpdate("ADD DEFAULT TO <x>", NumTriples(8, 0, 8, 2, 0));
expectExecuteUpdate("ADD SILENT DEFAULT TO DEFAULT", NumTriples(0, 0, 0));
expectExecuteUpdate("MOVE SILENT DEFAULT TO DEFAULT", NumTriples(0, 0, 0));
expectExecuteUpdate("MOVE GRAPH <x> TO <x>", NumTriples(0, 0, 0));
expectExecuteUpdate("MOVE <x> TO DEFAULT", NumTriples(0, 8, 8, 0, 1));
expectExecuteUpdate("MOVE DEFAULT TO GRAPH <x>",
NumTriples(8, 8, 16, 1, 1));
expectExecuteUpdate("COPY DEFAULT TO <x>", NumTriples(8, 0, 8, 1, 0));
NumTriples(8, 8, 16, 2, 1));
expectExecuteUpdate("COPY DEFAULT TO <x>", NumTriples(8, 0, 8, 2, 0));
expectExecuteUpdate("COPY DEFAULT TO DEFAULT", NumTriples(0, 0, 0));
expectExecuteUpdate("COPY <x> TO DEFAULT", NumTriples(0, 8, 8, 0, 1));
expectExecuteUpdate("CREATE SILENT GRAPH <x>", NumTriples(0, 0, 0));
Expand Down Expand Up @@ -198,17 +198,17 @@ TEST(ExecuteUpdate, executeUpdate) {
expectExecuteUpdate("DROP SILENT ALL", NumTriples(0, 7, 7, 0, 3));
expectExecuteUpdate("ADD <q> TO <q>", NumTriples(0, 0, 0));
expectExecuteUpdate("ADD <a> TO <q>", NumTriples(0, 0, 0));
expectExecuteUpdate("ADD SILENT <q> TO DEFAULT", NumTriples(3, 0, 3, 2, 0));
expectExecuteUpdate("ADD SILENT <q> TO DEFAULT", NumTriples(3, 0, 3, 4, 0));
expectExecuteUpdate("ADD DEFAULT TO <q>", NumTriples(1, 0, 1));
expectExecuteUpdate("ADD SILENT DEFAULT TO DEFAULT", NumTriples(0, 0, 0));
expectExecuteUpdate("MOVE SILENT DEFAULT TO DEFAULT", NumTriples(0, 0, 0));
expectExecuteUpdate("MOVE GRAPH <q> TO <t>", NumTriples(3, 3, 6, 2, 2));
expectExecuteUpdate("MOVE <q> TO DEFAULT", NumTriples(3, 4, 7, 2, 2));
expectExecuteUpdate("MOVE GRAPH <q> TO <t>", NumTriples(3, 3, 6, 4, 2));
expectExecuteUpdate("MOVE <q> TO DEFAULT", NumTriples(3, 4, 7, 4, 2));
expectExecuteUpdate("MOVE DEFAULT TO GRAPH <t>", NumTriples(1, 1, 2));
expectExecuteUpdate("MOVE DEFAULT TO GRAPH <q>", NumTriples(1, 4, 5, 0, 2));
expectExecuteUpdate("COPY DEFAULT TO <q>", NumTriples(1, 3, 4, 0, 2));
expectExecuteUpdate("COPY DEFAULT TO DEFAULT", NumTriples(0, 0, 0));
expectExecuteUpdate("COPY <q> TO DEFAULT", NumTriples(3, 1, 4, 2, 0));
expectExecuteUpdate("COPY <q> TO DEFAULT", NumTriples(3, 1, 4, 4, 0));
expectExecuteUpdate("CREATE SILENT GRAPH <x>", NumTriples(0, 0, 0));
expectExecuteUpdate("CREATE GRAPH <y>", NumTriples(0, 0, 0));
}
Expand Down
2 changes: 1 addition & 1 deletion test/IndexTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -713,7 +713,7 @@ TEST(IndexImpl, recomputeStatistics) {
auto newStats = indexImpl.recomputeStatistics(
index.deltaTriplesManager().getCurrentLocatedTriplesSharedState());
EXPECT_NE(newStats, indexImpl.configurationJson_);
EXPECT_EQ(newStats["num-triples"], NNAI(5, 6));
EXPECT_EQ(newStats["num-triples"], NNAI(5, 7));
EXPECT_EQ(newStats["num-predicates"], NNAI(2, 4));
if (loadAllPermutations) {
EXPECT_EQ(newStats["num-subjects"], NNAI(4, 0));
Expand Down
Loading