Skip to content

Commit c6c0e79

Browse files
committed
Add support for hugeint mergeWith
1 parent c2a52d0 commit c6c0e79

3 files changed

Lines changed: 117 additions & 0 deletions

File tree

velox/type/Filter.cpp

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1909,6 +1909,34 @@ std::unique_ptr<Filter> TimestampRange::mergeWith(const Filter* other) const {
19091909
}
19101910
}
19111911

1912+
std::unique_ptr<Filter> HugeintRange::mergeWith(const Filter* other) const {
1913+
switch (other->kind()) {
1914+
case FilterKind::kAlwaysTrue:
1915+
case FilterKind::kAlwaysFalse:
1916+
case FilterKind::kIsNull:
1917+
return other->mergeWith(this);
1918+
case FilterKind::kIsNotNull:
1919+
return this->clone(false);
1920+
case FilterKind::kHugeintRange: {
1921+
const bool bothNullAllowed = nullAllowed_ && other->testNull();
1922+
const auto* otherRange = static_cast<const HugeintRange*>(other);
1923+
1924+
const auto lower = std::max(lower_, otherRange->lower_);
1925+
const auto upper = std::min(upper_, otherRange->upper_);
1926+
1927+
if (lower <= upper) {
1928+
return std::make_unique<HugeintRange>(lower, upper, bothNullAllowed);
1929+
}
1930+
1931+
return nullOrFalse(bothNullAllowed);
1932+
}
1933+
case FilterKind::kHugeintValuesUsingHashTable:
1934+
return other->mergeWith(this);
1935+
default:
1936+
VELOX_UNREACHABLE();
1937+
}
1938+
}
1939+
19121940
std::unique_ptr<Filter> NegatedBigintRange::mergeWith(
19131941
const Filter* other) const {
19141942
switch (other->kind()) {
@@ -2100,6 +2128,32 @@ std::unique_ptr<Filter> BigintValuesUsingHashTable::mergeWith(
21002128
return createBigintValues(valuesToKeep, bothNullAllowed);
21012129
}
21022130

2131+
std::unique_ptr<Filter> HugeintValuesUsingHashTable::mergeWith(
2132+
const Filter* other) const {
2133+
switch (other->kind()) {
2134+
case FilterKind::kAlwaysTrue:
2135+
case FilterKind::kAlwaysFalse:
2136+
case FilterKind::kIsNull:
2137+
return other->mergeWith(this);
2138+
case FilterKind::kIsNotNull:
2139+
return this->clone(false);
2140+
case FilterKind::kHugeintRange:
2141+
case FilterKind::kHugeintValuesUsingHashTable: {
2142+
const bool bothNullAllowed = nullAllowed_ && other->testNull();
2143+
std::vector<int128_t> valuesToKeep;
2144+
valuesToKeep.reserve(values_.size());
2145+
for (const auto value : values_) {
2146+
if (other->testInt128(value)) {
2147+
valuesToKeep.push_back(value);
2148+
}
2149+
}
2150+
return createHugeintValues(valuesToKeep, bothNullAllowed);
2151+
}
2152+
default:
2153+
VELOX_UNREACHABLE();
2154+
}
2155+
}
2156+
21032157
std::unique_ptr<Filter> BigintValuesUsingBitmask::mergeWith(
21042158
const Filter* other) const {
21052159
switch (other->kind()) {

velox/type/Filter.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -980,6 +980,8 @@ class HugeintRange final : public Filter {
980980
nullAllowed_ ? "with nulls" : "no nulls");
981981
}
982982

983+
std::unique_ptr<Filter> mergeWith(const Filter* other) const final;
984+
983985
bool testingEquals(const Filter& other) const final;
984986

985987
private:
@@ -1202,6 +1204,8 @@ class HugeintValuesUsingHashTable final : public Filter {
12021204

12031205
bool testInt128(const int128_t& value) const final;
12041206

1207+
std::unique_ptr<Filter> mergeWith(const Filter* other) const final;
1208+
12051209
bool testingEquals(const Filter& other) const final;
12061210

12071211
int128_t min() const {

velox/type/tests/FilterTest.cpp

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -271,6 +271,65 @@ TEST(FilterTest, createHugeintValuesEmpty) {
271271
EXPECT_FALSE(filter->testInt128(0));
272272
}
273273

274+
TEST(FilterTest, mergeWithHugeintValuesUsingHashTable) {
275+
auto valueAt = [](uint64_t highBits) {
276+
return HugeInt::build(highBits, /*lowBits=*/42);
277+
};
278+
279+
const auto value1 = valueAt(1);
280+
const auto value2 = valueAt(2);
281+
const auto value3 = valueAt(3);
282+
const auto value4 = valueAt(4);
283+
284+
auto test =
285+
[](const Filter& left, const Filter& right, const Filter& expected) {
286+
auto merged = left.mergeWith(&right);
287+
ASSERT_TRUE(merged->testingEquals(expected));
288+
auto reverseMerged = right.mergeWith(&left);
289+
ASSERT_TRUE(reverseMerged->testingEquals(expected));
290+
};
291+
292+
{
293+
SCOPED_TRACE("HugeintValuesUsingHashTable");
294+
auto left = createHugeintValues({value1, value2, value3}, true);
295+
auto right = createHugeintValues({value2, value4}, false);
296+
auto expected = createHugeintValues({value2}, false);
297+
test(*left, *right, *expected);
298+
}
299+
300+
{
301+
SCOPED_TRACE("HugeintRange");
302+
auto values = createHugeintValues({value1, value2, value3}, true);
303+
auto range = betweenHugeint(value2, value4, true);
304+
auto expected = createHugeintValues({value2, value3}, true);
305+
test(*values, *range, *expected);
306+
}
307+
308+
{
309+
SCOPED_TRACE("HugeintRange intersection");
310+
auto left = betweenHugeint(value1, value3, true);
311+
auto right = betweenHugeint(value2, value4, false);
312+
auto expected = betweenHugeint(value2, value3, false);
313+
test(*left, *right, *expected);
314+
}
315+
316+
{
317+
SCOPED_TRACE("Disjoint ranges with nulls");
318+
auto left = betweenHugeint(value1, value1, true);
319+
auto right = betweenHugeint(value2, value4, true);
320+
IsNull expected;
321+
test(*left, *right, expected);
322+
}
323+
324+
{
325+
SCOPED_TRACE("Disjoint values with nulls");
326+
auto left = createHugeintValues({value1}, true);
327+
auto right = createHugeintValues({value2}, true);
328+
IsNull expected;
329+
test(*left, *right, expected);
330+
}
331+
}
332+
274333
TEST(FilterTest, negatedBigintRange) {
275334
auto filter = notEqual(1, false);
276335
EXPECT_FALSE(filter->testNull());

0 commit comments

Comments
 (0)