blob: 9585a24da4a3ac3b6abd52d968cf19f87c988f2b [file] [log] [blame]
// Licensed to the Apache Software Foundation (ASF) under values[1]
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
#include "kudu/common/column_predicate.h"
#include <glog/logging.h>
#include <gtest/gtest.h>
#include <vector>
#include "kudu/common/schema.h"
#include "kudu/common/types.h"
#include "kudu/util/test_util.h"
namespace kudu {
class TestColumnPredicate : public KuduTest {
public:
// Test that when a is merged into b and vice versa, the result is equal to
// expected, and the resulting type is equal to type.
void TestMerge(const ColumnPredicate& a,
const ColumnPredicate& b,
const ColumnPredicate& expected,
PredicateType type) {
ColumnPredicate a_base(a);
ColumnPredicate b_base(b);
a_base.Merge(b);
b_base.Merge(a);
ASSERT_EQ(expected, a_base) << "expected: " << expected.ToString()
<< ", actual: " << a_base.ToString();
ASSERT_EQ(expected, b_base) << "expected: " << expected.ToString()
<< ", actual: " << b_base.ToString();
ASSERT_EQ(a_base, b_base) << "expected: " << a_base.ToString()
<< ", actual: " << b_base.ToString();
ASSERT_EQ(expected.predicate_type(), type);
ASSERT_EQ(a_base.predicate_type(), type);
ASSERT_EQ(b_base.predicate_type(), type);
}
template <typename T>
void TestMergeCombinations(const ColumnSchema& column, vector<T> values) {
// Range + Range
// [--------) AND
// [--------)
// =
// [--------)
TestMerge(ColumnPredicate::Range(column, &values[0], &values[4]),
ColumnPredicate::Range(column, &values[0], &values[4]),
ColumnPredicate::Range(column, &values[0], &values[4]),
PredicateType::Range);
// [--------) AND
// [----)
// =
// [----)
TestMerge(ColumnPredicate::Range(column, &values[0], &values[4]),
ColumnPredicate::Range(column, &values[0], &values[2]),
ColumnPredicate::Range(column, &values[0], &values[2]),
PredicateType::Range);
// [--------) AND
// [----)
// =
// [----)
TestMerge(ColumnPredicate::Range(column, &values[0], &values[4]),
ColumnPredicate::Range(column, &values[1], &values[3]),
ColumnPredicate::Range(column, &values[1], &values[3]),
PredicateType::Range);
// [-----) AND
// [------)
// =
// [---)
TestMerge(ColumnPredicate::Range(column, &values[0], &values[3]),
ColumnPredicate::Range(column, &values[1], &values[4]),
ColumnPredicate::Range(column, &values[1], &values[3]),
PredicateType::Range);
// [--) AND
// [---)
// =
// None
TestMerge(ColumnPredicate::Range(column, &values[0], &values[2]),
ColumnPredicate::Range(column, &values[2], &values[5]),
ColumnPredicate::None(column),
PredicateType::None);
// [--) AND
// [---)
// =
// None
TestMerge(ColumnPredicate::Range(column, &values[0], &values[2]),
ColumnPredicate::Range(column, &values[4], &values[6]),
ColumnPredicate::None(column),
PredicateType::None);
// Range + Equality
// [---) AND
// |
// =
// None
TestMerge(ColumnPredicate::Range(column, &values[3], &values[5]),
ColumnPredicate::Equality(column, &values[1]),
ColumnPredicate::None(column),
PredicateType::None);
// [---) AND
// |
// =
// |
TestMerge(ColumnPredicate::Range(column, &values[1], &values[5]),
ColumnPredicate::Equality(column, &values[1]),
ColumnPredicate::Equality(column, &values[1]),
PredicateType::Equality);
// [---) AND
// |
// =
// |
TestMerge(ColumnPredicate::Range(column, &values[1], &values[5]),
ColumnPredicate::Equality(column, &values[3]),
ColumnPredicate::Equality(column, &values[3]),
PredicateType::Equality);
// [---) AND
// |
// =
// None
TestMerge(ColumnPredicate::Range(column, &values[1], &values[5]),
ColumnPredicate::Equality(column, &values[5]),
ColumnPredicate::None(column),
PredicateType::None);
// [---) AND
// |
// =
// None
TestMerge(ColumnPredicate::Range(column, &values[1], &values[4]),
ColumnPredicate::Equality(column, &values[5]),
ColumnPredicate::None(column),
PredicateType::None);
// None
// None AND
// [----)
// =
// None
TestMerge(ColumnPredicate::None(column),
ColumnPredicate::Range(column, &values[1], &values[5]),
ColumnPredicate::None(column),
PredicateType::None);
// None AND
// |
// =
// None
TestMerge(ColumnPredicate::None(column),
ColumnPredicate::Equality(column, &values[1]),
ColumnPredicate::None(column),
PredicateType::None);
// None AND
// None
// =
// None
TestMerge(ColumnPredicate::None(column),
ColumnPredicate::None(column),
ColumnPredicate::None(column),
PredicateType::None);
// IS NOT NULL
// IS NOT NULL AND
// IS NOT NULL
// =
// IS NOT NULL
TestMerge(ColumnPredicate::IsNotNull(column),
ColumnPredicate::IsNotNull(column),
ColumnPredicate::IsNotNull(column),
PredicateType::IsNotNull);
// IS NOT NULL AND
// None
// =
// None
TestMerge(ColumnPredicate::IsNotNull(column),
ColumnPredicate::None(column),
ColumnPredicate::None(column),
PredicateType::None);
// IS NOT NULL AND
// |
// =
// |
TestMerge(ColumnPredicate::IsNotNull(column),
ColumnPredicate::Equality(column, &values[0]),
ColumnPredicate::Equality(column, &values[0]),
PredicateType::Equality);
// IS NOT NULL AND
// [------)
// =
// [------)
TestMerge(ColumnPredicate::IsNotNull(column),
ColumnPredicate::Range(column, &values[0], &values[2]),
ColumnPredicate::Range(column, &values[0], &values[2]),
PredicateType::Range);
}
};
TEST_F(TestColumnPredicate, TestMerge) {
TestMergeCombinations(ColumnSchema("c", INT8, true),
vector<int8_t> { 0, 1, 2, 3, 4, 5, 6 });
TestMergeCombinations(ColumnSchema("c", INT32, true),
vector<int32_t> { -100, -10, -1, 0, 1, 10, 100 });
TestMergeCombinations(ColumnSchema("c", STRING, true),
vector<Slice> { "a", "b", "c", "d", "e", "f", "g" });
TestMergeCombinations(ColumnSchema("c", BINARY, true),
vector<Slice> { Slice("", 0),
Slice("\0", 1),
Slice("\0\0", 2),
Slice("\0\0\0", 3),
Slice("\0\0\0\0", 4),
Slice("\0\0\0\0\0", 5),
Slice("\0\0\0\0\0\0", 6),
});
}
// Test that the range constructor handles equality and empty ranges.
TEST_F(TestColumnPredicate, TestRangeConstructor) {
{
ColumnSchema column("c", INT32);
int32_t zero = 0;
int32_t one = 1;
int32_t two = 2;
ASSERT_EQ(PredicateType::Range,
ColumnPredicate::Range(column, &zero, &two).predicate_type());
ASSERT_EQ(PredicateType::Equality,
ColumnPredicate::Range(column, &zero, &one).predicate_type());
ASSERT_EQ(PredicateType::None,
ColumnPredicate::Range(column, &zero, &zero).predicate_type());
ASSERT_EQ(PredicateType::None,
ColumnPredicate::Range(column, &one, &zero).predicate_type());
}
{
ColumnSchema column("c", STRING);
Slice zero("", 0);
Slice one("\0", 1);
Slice two("\0\0", 2);
ASSERT_EQ(PredicateType::Range,
ColumnPredicate::Range(column, &zero, &two).predicate_type());
ASSERT_EQ(PredicateType::Equality,
ColumnPredicate::Range(column, &zero, &one).predicate_type());
ASSERT_EQ(PredicateType::None,
ColumnPredicate::Range(column, &zero, &zero).predicate_type());
ASSERT_EQ(PredicateType::None,
ColumnPredicate::Range(column, &one, &zero).predicate_type());
}
}
// Test that the inclusive range constructor handles transforming to exclusive
// upper bound correctly.
TEST_F(TestColumnPredicate, TestInclusiveRange) {
Arena arena(1024, 1024 * 1024);
{
ColumnSchema column("c", INT32);
int32_t zero = 0;
int32_t two = 2;
int32_t three = 3;
int32_t max = INT32_MAX;
ASSERT_EQ(ColumnPredicate::Range(column, &zero, &three),
ColumnPredicate::InclusiveRange(column, &zero, &two, &arena));
ASSERT_EQ(ColumnPredicate::Range(column, &zero, nullptr),
ColumnPredicate::InclusiveRange(column, &zero, &max, &arena));
ASSERT_EQ(boost::none, ColumnPredicate::InclusiveRange(column, nullptr, &max, &arena));
}
{
ColumnSchema column("c", INT32, true);
int32_t zero = 0;
int32_t two = 2;
int32_t three = 3;
int32_t max = INT32_MAX;
ASSERT_EQ(ColumnPredicate::Range(column, &zero, &three),
ColumnPredicate::InclusiveRange(column, &zero, &two, &arena));
ASSERT_EQ(ColumnPredicate::Range(column, &zero, nullptr),
ColumnPredicate::InclusiveRange(column, &zero, &max, &arena));
ASSERT_EQ(ColumnPredicate::IsNotNull(column),
ColumnPredicate::InclusiveRange(column, nullptr, &max, &arena));
}
{
ColumnSchema column("c", STRING);
Slice zero("", 0);
Slice two("\0\0", 2);
Slice three("\0\0\0", 3);
ASSERT_EQ(ColumnPredicate::Range(column, &zero, &three),
ColumnPredicate::InclusiveRange(column, &zero, &two, &arena));
}
}
} // namespace kudu