diff --git a/src/engine/Union.cpp b/src/engine/Union.cpp index 06bd763dab..ef6aaf600f 100644 --- a/src/engine/Union.cpp +++ b/src/engine/Union.cpp @@ -252,7 +252,7 @@ std::vector Union::computePermutation() const { originIndex = startOfUndefColumns; startOfUndefColumns++; } - permutation[originIndex] = targetColIdx; + permutation[targetColIdx] = originIndex; } return permutation; } diff --git a/test/UnionTest.cpp b/test/UnionTest.cpp index de7ebb65ae..2bbe554fe6 100644 --- a/test/UnionTest.cpp +++ b/test/UnionTest.cpp @@ -20,7 +20,7 @@ using Vars = std::vector>; } // namespace // A simple test for computing a union. -TEST(UnionTest, computeUnion) { +TEST(Union, computeUnion) { auto* qec = ad_utility::testing::getQec(); IdTable left = makeIdTableFromVector({{V(1)}, {V(2)}, {V(3)}}); auto leftT = ad_utility::makeExecutionTree( @@ -30,7 +30,7 @@ TEST(UnionTest, computeUnion) { auto rightT = ad_utility::makeExecutionTree( qec, right.clone(), Vars{Variable{"?u"}, Variable{"?x"}}); - Union u{ad_utility::testing::getQec(), leftT, rightT}; + Union u{qec, leftT, rightT}; auto resultTable = u.computeResultOnlyForTesting(); const auto& result = resultTable.idTable(); @@ -42,7 +42,7 @@ TEST(UnionTest, computeUnion) { // A test with large inputs to test the chunked writing that is caused by the // timeout checks. -TEST(UnionTest, computeUnionLarge) { +TEST(Union, computeUnionLarge) { auto* qec = ad_utility::testing::getQec(); VectorTable leftInput, rightInput, expected; size_t numInputsL = 1'500'000u; @@ -65,7 +65,7 @@ TEST(UnionTest, computeUnionLarge) { auto rightT = ad_utility::makeExecutionTree( qec, makeIdTableFromVector(rightInput), Vars{Variable{"?u"}}); - Union u{ad_utility::testing::getQec(), leftT, rightT}; + Union u{qec, leftT, rightT}; auto resultTable = u.computeResultOnlyForTesting(); const auto& result = resultTable.idTable(); @@ -73,7 +73,7 @@ TEST(UnionTest, computeUnionLarge) { } // _____________________________________________________________________________ -TEST(UnionTest, computeUnionLazy) { +TEST(Union, computeUnionLazy) { auto runTest = [](bool nonLazyChilds, ad_utility::source_location loc = ad_utility::source_location::current()) { @@ -90,7 +90,7 @@ TEST(UnionTest, computeUnionLazy) { qec, std::move(right), Vars{Variable{"?u"}, Variable{"?x"}}, false, std::vector{}, LocalVocab{}, std::nullopt, nonLazyChilds); - Union u{ad_utility::testing::getQec(), std::move(leftT), std::move(rightT)}; + Union u{qec, std::move(leftT), std::move(rightT)}; auto resultTable = u.computeResultOnlyForTesting(true); ASSERT_FALSE(resultTable.isFullyMaterialized()); auto& result = resultTable.idTables(); @@ -113,3 +113,50 @@ TEST(UnionTest, computeUnionLazy) { runTest(false); runTest(true); } + +// _____________________________________________________________________________ +TEST(Union, ensurePermutationIsAppliedCorrectly) { + using Var = Variable; + auto* qec = ad_utility::testing::getQec(); + auto leftT = ad_utility::makeExecutionTree( + qec, makeIdTableFromVector({{1, 2, 3, 4, 5}}), + Vars{Var{"?a"}, Var{"?b"}, Var{"?c"}, Var{"?d"}, Var{"?e"}}); + + auto rightT = ad_utility::makeExecutionTree( + qec, makeIdTableFromVector({{6, 7, 8}}), + Vars{Var{"?b"}, Var{"?a"}, Var{"?e"}}); + + Union u{qec, std::move(leftT), std::move(rightT)}; + + { + qec->getQueryTreeCache().clearAll(); + auto resultTable = u.computeResultOnlyForTesting(true); + ASSERT_FALSE(resultTable.isFullyMaterialized()); + auto& result = resultTable.idTables(); + + auto U = Id::makeUndefined(); + auto expected1 = makeIdTableFromVector({{1, 2, 3, 4, 5}}); + auto expected2 = makeIdTableFromVector({{V(7), V(6), U, U, V(8)}}); + + auto iterator = result.begin(); + ASSERT_NE(iterator, result.end()); + ASSERT_EQ(*iterator, expected1); + + ++iterator; + ASSERT_NE(iterator, result.end()); + ASSERT_EQ(*iterator, expected2); + + ASSERT_EQ(++iterator, result.end()); + } + + { + qec->getQueryTreeCache().clearAll(); + auto resultTable = u.computeResultOnlyForTesting(); + ASSERT_TRUE(resultTable.isFullyMaterialized()); + + auto U = Id::makeUndefined(); + auto expected = + makeIdTableFromVector({{1, 2, 3, 4, 5}, {V(7), V(6), U, U, V(8)}}); + EXPECT_EQ(resultTable.idTable(), expected); + } +}