blob: e795fb58a61c5e89ae0b7f8e1ae63dfe967ad2d1 [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 "olap/rowset/segment_v2/zone_map_index.h"
#include <gtest/gtest.h>
#include <memory>
#include <string>
#include "env/env.h"
#include "olap/fs/block_manager.h"
#include "olap/fs/fs_util.h"
#include "olap/page_cache.h"
#include "olap/tablet_schema_helper.h"
#include "util/file_utils.h"
namespace doris {
namespace segment_v2 {
class ColumnZoneMapTest : public testing::Test {
public:
const std::string kTestDir = "./ut_dir/zone_map_index_test";
void SetUp() override {
if (FileUtils::check_exist(kTestDir)) {
ASSERT_TRUE(FileUtils::remove_all(kTestDir).ok());
}
ASSERT_TRUE(FileUtils::create_dir(kTestDir).ok());
}
void TearDown() override {
if (FileUtils::check_exist(kTestDir)) {
ASSERT_TRUE(FileUtils::remove_all(kTestDir).ok());
}
}
void test_string(std::string testname, Field* field) {
std::string filename = kTestDir + "/" + testname;
ZoneMapIndexWriter builder(field);
std::vector<std::string> values1 = {"aaaa", "bbbb", "cccc", "dddd", "eeee", "ffff"};
for (auto& value : values1) {
Slice slice(value);
builder.add_values((const uint8_t*)&slice, 1);
}
builder.flush();
std::vector<std::string> values2 = {"aaaaa", "bbbbb", "ccccc", "ddddd", "eeeee", "fffff"};
for (auto& value : values2) {
Slice slice(value);
builder.add_values((const uint8_t*)&slice, 1);
}
builder.add_nulls(1);
builder.flush();
for (int i = 0; i < 6; ++i) {
builder.add_nulls(1);
}
builder.flush();
// write out zone map index
ColumnIndexMetaPB index_meta;
{
std::unique_ptr<fs::WritableBlock> wblock;
fs::CreateBlockOptions opts({filename});
ASSERT_TRUE(fs::fs_util::block_manager()->create_block(opts, &wblock).ok());
ASSERT_TRUE(builder.finish(wblock.get(), &index_meta).ok());
ASSERT_EQ(ZONE_MAP_INDEX, index_meta.type());
ASSERT_TRUE(wblock->close().ok());
}
ZoneMapIndexReader column_zone_map(filename, &index_meta.zone_map_index());
Status status = column_zone_map.load(true, false);
ASSERT_TRUE(status.ok());
ASSERT_EQ(3, column_zone_map.num_pages());
const std::vector<ZoneMapPB>& zone_maps = column_zone_map.page_zone_maps();
ASSERT_EQ(3, zone_maps.size());
ASSERT_EQ("aaaa", zone_maps[0].min());
ASSERT_EQ("ffff", zone_maps[0].max());
ASSERT_EQ(false, zone_maps[0].has_null());
ASSERT_EQ(true, zone_maps[0].has_not_null());
ASSERT_EQ("aaaaa", zone_maps[1].min());
ASSERT_EQ("fffff", zone_maps[1].max());
ASSERT_EQ(true, zone_maps[1].has_null());
ASSERT_EQ(true, zone_maps[1].has_not_null());
ASSERT_EQ(true, zone_maps[2].has_null());
ASSERT_EQ(false, zone_maps[2].has_not_null());
}
};
// Test for int
TEST_F(ColumnZoneMapTest, NormalTestIntPage) {
std::string filename = kTestDir + "/NormalTestIntPage";
TabletColumn int_column = create_int_key(0);
Field* field = FieldFactory::create(int_column);
ZoneMapIndexWriter builder(field);
std::vector<int> values1 = {1, 10, 11, 20, 21, 22};
for (auto value : values1) {
builder.add_values((const uint8_t*)&value, 1);
}
builder.flush();
std::vector<int> values2 = {2, 12, 31, 23, 21, 22};
for (auto value : values2) {
builder.add_values((const uint8_t*)&value, 1);
}
builder.add_nulls(1);
builder.flush();
builder.add_nulls(6);
builder.flush();
// write out zone map index
ColumnIndexMetaPB index_meta;
{
std::unique_ptr<fs::WritableBlock> wblock;
fs::CreateBlockOptions opts({filename});
ASSERT_TRUE(fs::fs_util::block_manager()->create_block(opts, &wblock).ok());
ASSERT_TRUE(builder.finish(wblock.get(), &index_meta).ok());
ASSERT_EQ(ZONE_MAP_INDEX, index_meta.type());
ASSERT_TRUE(wblock->close().ok());
}
ZoneMapIndexReader column_zone_map(filename, &index_meta.zone_map_index());
Status status = column_zone_map.load(true, false);
ASSERT_TRUE(status.ok());
ASSERT_EQ(3, column_zone_map.num_pages());
const std::vector<ZoneMapPB>& zone_maps = column_zone_map.page_zone_maps();
ASSERT_EQ(3, zone_maps.size());
ASSERT_EQ(std::to_string(1), zone_maps[0].min());
ASSERT_EQ(std::to_string(22), zone_maps[0].max());
ASSERT_EQ(false, zone_maps[0].has_null());
ASSERT_EQ(true, zone_maps[0].has_not_null());
ASSERT_EQ(std::to_string(2), zone_maps[1].min());
ASSERT_EQ(std::to_string(31), zone_maps[1].max());
ASSERT_EQ(true, zone_maps[1].has_null());
ASSERT_EQ(true, zone_maps[1].has_not_null());
ASSERT_EQ(true, zone_maps[2].has_null());
ASSERT_EQ(false, zone_maps[2].has_not_null());
delete field;
}
// Test for string
TEST_F(ColumnZoneMapTest, NormalTestVarcharPage) {
TabletColumn varchar_column = create_varchar_key(0);
Field* field = FieldFactory::create(varchar_column);
test_string("NormalTestVarcharPage", field);
delete field;
}
// Test for string
TEST_F(ColumnZoneMapTest, NormalTestCharPage) {
TabletColumn char_column = create_char_key(0);
Field* field = FieldFactory::create(char_column);
test_string("NormalTestCharPage", field);
delete field;
}
} // namespace segment_v2
} // namespace doris
int main(int argc, char** argv) {
doris::StoragePageCache::create_global_cache(1 << 30, 0.1);
testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS();
}