blob: e1db67b232172195749f044e518cef4644ab2ff1 [file] [log] [blame]
// Licensed to the Apache Software Foundation (ASF) under one
// 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 <gtest/gtest.h>
#include "kudu/common/scan_predicate.h"
#include "kudu/common/rowblock.h"
#include "kudu/util/memory/overwrite.h"
#include "kudu/util/test_util.h"
namespace kudu {
class TestPredicate : public KuduTest {
public:
TestPredicate() :
arena_(1024, 4096),
n_rows_(100),
schema_({ ColumnSchema("col0", UINT32),
ColumnSchema("col1", UINT32),
ColumnSchema("col2", STRING) },
1),
row_block_(schema_, n_rows_, &arena_)
{}
// Set up a block of data with two columns:
// col0 col1
// ---- ------
// 0 0
// 1 10
// ... ...
// N N * 10
//
// The third STRING column is left unset.
void SetUp() OVERRIDE {
KuduTest::SetUp();
ColumnBlock col0 = row_block_.column_block(0, n_rows_);
ColumnBlock col1 = row_block_.column_block(1, n_rows_);
for (uint32_t i = 0; i < n_rows_; i++) {
uint32_t i1 = i * 10;
col0.SetCellValue(i, &i);
col1.SetCellValue(i, &i1);
}
}
protected:
Arena arena_;
const size_t n_rows_;
Schema schema_;
RowBlock row_block_;
};
TEST_F(TestPredicate, TestSelectionVector) {
SelectionVector selvec(10);
selvec.SetAllTrue();
ASSERT_TRUE(selvec.IsRowSelected(0));
ASSERT_TRUE(selvec.IsRowSelected(9));
ASSERT_EQ(10, selvec.CountSelected());
ASSERT_TRUE(selvec.AnySelected());
for (int i = 0; i < 10; i++) {
BitmapClear(selvec.mutable_bitmap(), i);
}
ASSERT_FALSE(selvec.AnySelected());
// Test Resize()
selvec.SetAllTrue();
for (int i = 10; i > 0; --i) {
selvec.Resize(i);
ASSERT_EQ(selvec.CountSelected(), i);
ASSERT_TRUE(selvec.AnySelected());
}
selvec.Resize(0);
ASSERT_EQ(selvec.CountSelected(), 0);
ASSERT_FALSE(selvec.AnySelected());
}
TEST_F(TestPredicate, TestColumnRange) {
SelectionVector selvec(n_rows_);
selvec.SetAllTrue();
ASSERT_EQ(100, selvec.CountSelected());
// Apply predicate 20 <= col0 <= 29
uint32_t col0_lower = 20;
uint32_t col0_upper = 29;
ColumnRangePredicate pred1(schema_.column(0), &col0_lower, &col0_upper);
ASSERT_EQ("(`col0` BETWEEN 20 AND 29)", pred1.ToString());
pred1.Evaluate(&row_block_, &selvec);
ASSERT_EQ(10, selvec.CountSelected()) << "Only 10 rows should be left (20-29)";
// Apply predicate col1 >= 250
uint32_t col1_lower = 250;
ColumnRangePredicate pred2(schema_.column(1), &col1_lower, nullptr);
ASSERT_EQ("(`col1` >= 250)", pred2.ToString());
pred2.Evaluate(&row_block_, &selvec);
ASSERT_EQ(5, selvec.CountSelected()) << "Only 5 rows should be left (25-29)";
}
// Regression test for KUDU-54: should not try to access rows for which the
// selection vector is 0.
TEST_F(TestPredicate, TestDontEvalauteOnUnselectedRows) {
SelectionVector selvec(n_rows_);
selvec.SetAllFalse();
// Fill the STRING column with garbage data.
OverwriteWithPattern(reinterpret_cast<char*>(row_block_.column_block(2).data()),
row_block_.column_block(2).stride() * row_block_.nrows(),
"JUNKDATA");
Slice lower("lower");
ColumnRangePredicate p(schema_.column(2), &lower, nullptr);
p.Evaluate(&row_block_, &selvec);
ASSERT_EQ(0, selvec.CountSelected());
}
} // namespace kudu