blob: d52e036f22997a1b20fe6835f99564e10ee49520 [file]
// 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 "storage/index/index_reader_helper.h"
#include <gtest/gtest.h>
#include <map>
#include <memory>
#include <string>
#include "common/be_mock_util.h"
#include "storage/index/index_reader.h"
#include "storage/index/inverted/inverted_index_parser.h"
#include "storage/index/inverted/inverted_index_query_type.h"
#include "storage/index/inverted/inverted_index_reader.h"
#include "storage/tablet/tablet_schema.h"
using namespace doris;
using namespace doris::segment_v2;
class MockIndexReader : public segment_v2::IndexReader {
public:
MockIndexReader(IndexType type, uint64_t id) : _type(type), _id(id) {}
MOCK_FUNCTION IndexType index_type() override { return _type; }
MOCK_FUNCTION uint64_t get_index_id() const override { return _id; }
MOCK_FUNCTION Status new_iterator(std::unique_ptr<IndexIterator>* iterator) override {
return Status::OK();
}
private:
IndexType _type;
uint64_t _id;
};
class MockInvertedIndexReader : public InvertedIndexReader {
public:
MockInvertedIndexReader(InvertedIndexReaderType reader_type,
const std::map<std::string, std::string>& properties)
: InvertedIndexReader(get_static_tablet_index(), nullptr),
_reader_type(reader_type),
_properties(properties) {}
MOCK_FUNCTION InvertedIndexReaderType type() override { return _reader_type; }
MOCK_FUNCTION const std::map<std::string, std::string>& get_index_properties() const override {
return _properties;
}
MOCK_FUNCTION Status query(const IndexQueryContextPtr& context, const std::string& column_name,
const Field& query_value, InvertedIndexQueryType query_type,
std::shared_ptr<roaring::Roaring>& bit_map,
const InvertedIndexAnalyzerCtx* analyzer_ctx = nullptr) override {
return Status::OK();
}
MOCK_FUNCTION Status try_query(const IndexQueryContextPtr& context,
const std::string& column_name, const Field& query_value,
InvertedIndexQueryType query_type, size_t* count) override {
return Status::OK();
}
MOCK_FUNCTION Status new_iterator(std::unique_ptr<IndexIterator>* iterator) override {
return Status::OK();
}
private:
static const TabletIndex* get_static_tablet_index() {
static TabletIndex idx_meta;
auto index_meta_pb = std::make_unique<TabletIndexPB>();
index_meta_pb->set_index_type(IndexType::INVERTED);
index_meta_pb->set_index_id(1);
index_meta_pb->set_index_name("test_mock_cache");
index_meta_pb->add_col_unique_id(1);
idx_meta.init_from_pb(*index_meta_pb);
return &idx_meta;
}
InvertedIndexReaderType _reader_type;
std::map<std::string, std::string> _properties;
};
class IndexReaderHelperTest : public ::testing::Test {
protected:
void SetUp() override {}
void TearDown() override {}
};
TEST_F(IndexReaderHelperTest, IsFulltextIndexWithNonInvertedIndexTest) {
// auto ann_reader = std::make_shared<MockIndexReader>(IndexType::ANN, 1);
auto bitmap_reader = std::make_shared<MockIndexReader>(IndexType::BITMAP, 2);
auto bloomfilter_reader = std::make_shared<MockIndexReader>(IndexType::BLOOMFILTER, 3);
auto ngram_reader = std::make_shared<MockIndexReader>(IndexType::NGRAM_BF, 4);
// EXPECT_FALSE(IndexReaderHelper::is_fulltext_index(ann_reader));
EXPECT_FALSE(IndexReaderHelper::is_fulltext_index(bitmap_reader));
EXPECT_FALSE(IndexReaderHelper::is_fulltext_index(bloomfilter_reader));
EXPECT_FALSE(IndexReaderHelper::is_fulltext_index(ngram_reader));
}
TEST_F(IndexReaderHelperTest, IsFulltextIndexWithInvertedIndexTest) {
std::map<std::string, std::string> properties;
auto fulltext_reader = std::make_shared<MockInvertedIndexReader>(
InvertedIndexReaderType::FULLTEXT, properties);
auto string_reader = std::make_shared<MockInvertedIndexReader>(
InvertedIndexReaderType::STRING_TYPE, properties);
auto bkd_reader =
std::make_shared<MockInvertedIndexReader>(InvertedIndexReaderType::BKD, properties);
auto unknown_reader =
std::make_shared<MockInvertedIndexReader>(InvertedIndexReaderType::UNKNOWN, properties);
EXPECT_TRUE(IndexReaderHelper::is_fulltext_index(fulltext_reader));
EXPECT_FALSE(IndexReaderHelper::is_fulltext_index(string_reader));
EXPECT_FALSE(IndexReaderHelper::is_fulltext_index(bkd_reader));
EXPECT_FALSE(IndexReaderHelper::is_fulltext_index(unknown_reader));
}
TEST_F(IndexReaderHelperTest, IsStringIndexWithNonInvertedIndexTest) {
// auto ann_reader = std::make_shared<MockIndexReader>(IndexType::ANN, 1);
auto bitmap_reader = std::make_shared<MockIndexReader>(IndexType::BITMAP, 2);
// EXPECT_FALSE(IndexReaderHelper::is_string_index(ann_reader));
EXPECT_FALSE(IndexReaderHelper::is_string_index(bitmap_reader));
}
TEST_F(IndexReaderHelperTest, IsStringIndexWithInvertedIndexTest) {
std::map<std::string, std::string> properties;
auto fulltext_reader = std::make_shared<MockInvertedIndexReader>(
InvertedIndexReaderType::FULLTEXT, properties);
auto string_reader = std::make_shared<MockInvertedIndexReader>(
InvertedIndexReaderType::STRING_TYPE, properties);
auto bkd_reader =
std::make_shared<MockInvertedIndexReader>(InvertedIndexReaderType::BKD, properties);
auto unknown_reader =
std::make_shared<MockInvertedIndexReader>(InvertedIndexReaderType::UNKNOWN, properties);
EXPECT_FALSE(IndexReaderHelper::is_string_index(fulltext_reader));
EXPECT_TRUE(IndexReaderHelper::is_string_index(string_reader));
EXPECT_FALSE(IndexReaderHelper::is_string_index(bkd_reader));
EXPECT_FALSE(IndexReaderHelper::is_string_index(unknown_reader));
}
TEST_F(IndexReaderHelperTest, IsBkdIndexWithNonInvertedIndexTest) {
// auto ann_reader = std::make_shared<MockIndexReader>(IndexType::ANN, 1);
auto bitmap_reader = std::make_shared<MockIndexReader>(IndexType::BITMAP, 2);
auto bloomfilter_reader = std::make_shared<MockIndexReader>(IndexType::BLOOMFILTER, 3);
// EXPECT_FALSE(IndexReaderHelper::is_bkd_index(ann_reader));
EXPECT_FALSE(IndexReaderHelper::is_bkd_index(bitmap_reader));
EXPECT_FALSE(IndexReaderHelper::is_bkd_index(bloomfilter_reader));
}
TEST_F(IndexReaderHelperTest, IsBkdIndexWithInvertedIndexTest) {
std::map<std::string, std::string> properties;
auto fulltext_reader = std::make_shared<MockInvertedIndexReader>(
InvertedIndexReaderType::FULLTEXT, properties);
auto string_reader = std::make_shared<MockInvertedIndexReader>(
InvertedIndexReaderType::STRING_TYPE, properties);
auto bkd_reader =
std::make_shared<MockInvertedIndexReader>(InvertedIndexReaderType::BKD, properties);
auto unknown_reader =
std::make_shared<MockInvertedIndexReader>(InvertedIndexReaderType::UNKNOWN, properties);
EXPECT_FALSE(IndexReaderHelper::is_bkd_index(fulltext_reader));
EXPECT_FALSE(IndexReaderHelper::is_bkd_index(string_reader));
EXPECT_TRUE(IndexReaderHelper::is_bkd_index(bkd_reader));
EXPECT_FALSE(IndexReaderHelper::is_bkd_index(unknown_reader));
}
TEST_F(IndexReaderHelperTest, IsSupportPhraseWithNonInvertedIndexTest) {
// auto ann_reader = std::make_shared<MockIndexReader>(IndexType::ANN, 1);
auto bitmap_reader = std::make_shared<MockIndexReader>(IndexType::BITMAP, 2);
auto bloomfilter_reader = std::make_shared<MockIndexReader>(IndexType::BLOOMFILTER, 3);
auto ngram_reader = std::make_shared<MockIndexReader>(IndexType::NGRAM_BF, 4);
// EXPECT_FALSE(IndexReaderHelper::is_support_phrase(ann_reader));
EXPECT_FALSE(IndexReaderHelper::is_support_phrase(bitmap_reader));
EXPECT_FALSE(IndexReaderHelper::is_support_phrase(bloomfilter_reader));
EXPECT_FALSE(IndexReaderHelper::is_support_phrase(ngram_reader));
}
TEST_F(IndexReaderHelperTest, IsSupportPhraseWithPhraseSupportYesTest) {
std::map<std::string, std::string> properties;
properties[INVERTED_INDEX_PARSER_PHRASE_SUPPORT_KEY] = INVERTED_INDEX_PARSER_PHRASE_SUPPORT_YES;
auto fulltext_reader = std::make_shared<MockInvertedIndexReader>(
InvertedIndexReaderType::FULLTEXT, properties);
auto string_reader = std::make_shared<MockInvertedIndexReader>(
InvertedIndexReaderType::STRING_TYPE, properties);
auto bkd_reader =
std::make_shared<MockInvertedIndexReader>(InvertedIndexReaderType::BKD, properties);
EXPECT_TRUE(IndexReaderHelper::is_support_phrase(fulltext_reader));
EXPECT_TRUE(IndexReaderHelper::is_support_phrase(string_reader));
EXPECT_TRUE(IndexReaderHelper::is_support_phrase(bkd_reader));
}
TEST_F(IndexReaderHelperTest, IsSupportPhraseWithPhraseSupportNoTest) {
std::map<std::string, std::string> properties;
properties[INVERTED_INDEX_PARSER_PHRASE_SUPPORT_KEY] = INVERTED_INDEX_PARSER_PHRASE_SUPPORT_NO;
auto fulltext_reader = std::make_shared<MockInvertedIndexReader>(
InvertedIndexReaderType::FULLTEXT, properties);
auto string_reader = std::make_shared<MockInvertedIndexReader>(
InvertedIndexReaderType::STRING_TYPE, properties);
auto bkd_reader =
std::make_shared<MockInvertedIndexReader>(InvertedIndexReaderType::BKD, properties);
EXPECT_FALSE(IndexReaderHelper::is_support_phrase(fulltext_reader));
EXPECT_FALSE(IndexReaderHelper::is_support_phrase(string_reader));
EXPECT_FALSE(IndexReaderHelper::is_support_phrase(bkd_reader));
}
TEST_F(IndexReaderHelperTest, IsSupportPhraseWithEmptyPropertiesTest) {
std::map<std::string, std::string> properties;
auto fulltext_reader = std::make_shared<MockInvertedIndexReader>(
InvertedIndexReaderType::FULLTEXT, properties);
auto string_reader = std::make_shared<MockInvertedIndexReader>(
InvertedIndexReaderType::STRING_TYPE, properties);
auto bkd_reader =
std::make_shared<MockInvertedIndexReader>(InvertedIndexReaderType::BKD, properties);
EXPECT_FALSE(IndexReaderHelper::is_support_phrase(fulltext_reader));
EXPECT_FALSE(IndexReaderHelper::is_support_phrase(string_reader));
EXPECT_FALSE(IndexReaderHelper::is_support_phrase(bkd_reader));
}
TEST_F(IndexReaderHelperTest, IsSupportPhraseWithInvalidValueTest) {
std::map<std::string, std::string> properties;
properties[INVERTED_INDEX_PARSER_PHRASE_SUPPORT_KEY] = "invalid_value";
auto fulltext_reader = std::make_shared<MockInvertedIndexReader>(
InvertedIndexReaderType::FULLTEXT, properties);
auto string_reader = std::make_shared<MockInvertedIndexReader>(
InvertedIndexReaderType::STRING_TYPE, properties);
EXPECT_FALSE(IndexReaderHelper::is_support_phrase(fulltext_reader));
EXPECT_FALSE(IndexReaderHelper::is_support_phrase(string_reader));
}
TEST_F(IndexReaderHelperTest, IsSupportPhraseWithMixedPropertiesTest) {
std::map<std::string, std::string> properties;
properties[INVERTED_INDEX_PARSER_KEY] = INVERTED_INDEX_PARSER_ENGLISH;
properties[INVERTED_INDEX_PARSER_PHRASE_SUPPORT_KEY] = INVERTED_INDEX_PARSER_PHRASE_SUPPORT_YES;
properties[INVERTED_INDEX_PARSER_LOWERCASE_KEY] = INVERTED_INDEX_PARSER_TRUE;
auto fulltext_reader = std::make_shared<MockInvertedIndexReader>(
InvertedIndexReaderType::FULLTEXT, properties);
EXPECT_TRUE(IndexReaderHelper::is_support_phrase(fulltext_reader));
}
TEST_F(IndexReaderHelperTest, AllMethodsWithNullPointerTest) {
IndexReaderPtr null_reader = nullptr;
EXPECT_FALSE(IndexReaderHelper::is_fulltext_index(null_reader));
EXPECT_FALSE(IndexReaderHelper::is_string_index(null_reader));
EXPECT_FALSE(IndexReaderHelper::is_bkd_index(null_reader));
EXPECT_FALSE(IndexReaderHelper::is_support_phrase(null_reader));
}
TEST_F(IndexReaderHelperTest, EdgeCaseWithUnknownReaderTypeTest) {
std::map<std::string, std::string> properties;
properties[INVERTED_INDEX_PARSER_PHRASE_SUPPORT_KEY] = INVERTED_INDEX_PARSER_PHRASE_SUPPORT_YES;
auto unknown_reader =
std::make_shared<MockInvertedIndexReader>(InvertedIndexReaderType::UNKNOWN, properties);
EXPECT_FALSE(IndexReaderHelper::is_fulltext_index(unknown_reader));
EXPECT_FALSE(IndexReaderHelper::is_string_index(unknown_reader));
EXPECT_FALSE(IndexReaderHelper::is_bkd_index(unknown_reader));
EXPECT_TRUE(IndexReaderHelper::is_support_phrase(unknown_reader));
}
TEST_F(IndexReaderHelperTest, CombinedMethodsConsistencyTest) {
std::map<std::string, std::string> properties;
properties[INVERTED_INDEX_PARSER_PHRASE_SUPPORT_KEY] = INVERTED_INDEX_PARSER_PHRASE_SUPPORT_YES;
auto fulltext_reader = std::make_shared<MockInvertedIndexReader>(
InvertedIndexReaderType::FULLTEXT, properties);
auto string_reader = std::make_shared<MockInvertedIndexReader>(
InvertedIndexReaderType::STRING_TYPE, properties);
auto bkd_reader =
std::make_shared<MockInvertedIndexReader>(InvertedIndexReaderType::BKD, properties);
EXPECT_TRUE(IndexReaderHelper::is_fulltext_index(fulltext_reader));
EXPECT_FALSE(IndexReaderHelper::is_string_index(fulltext_reader));
EXPECT_FALSE(IndexReaderHelper::is_bkd_index(fulltext_reader));
EXPECT_TRUE(IndexReaderHelper::is_support_phrase(fulltext_reader));
EXPECT_FALSE(IndexReaderHelper::is_fulltext_index(string_reader));
EXPECT_TRUE(IndexReaderHelper::is_string_index(string_reader));
EXPECT_FALSE(IndexReaderHelper::is_bkd_index(string_reader));
EXPECT_TRUE(IndexReaderHelper::is_support_phrase(string_reader));
EXPECT_FALSE(IndexReaderHelper::is_fulltext_index(bkd_reader));
EXPECT_FALSE(IndexReaderHelper::is_string_index(bkd_reader));
EXPECT_TRUE(IndexReaderHelper::is_bkd_index(bkd_reader));
EXPECT_TRUE(IndexReaderHelper::is_support_phrase(bkd_reader));
}
TEST_F(IndexReaderHelperTest, MultipleInvertedIndexTypesTest) {
std::map<std::string, std::string> properties;
auto readers = {
std::make_shared<MockInvertedIndexReader>(InvertedIndexReaderType::FULLTEXT,
properties),
std::make_shared<MockInvertedIndexReader>(InvertedIndexReaderType::STRING_TYPE,
properties),
std::make_shared<MockInvertedIndexReader>(InvertedIndexReaderType::BKD, properties),
std::make_shared<MockInvertedIndexReader>(InvertedIndexReaderType::UNKNOWN,
properties)};
std::vector<bool> expected_fulltext = {true, false, false, false};
std::vector<bool> expected_string = {false, true, false, false};
std::vector<bool> expected_bkd = {false, false, true, false};
int i = 0;
for (const auto& reader : readers) {
EXPECT_EQ(IndexReaderHelper::is_fulltext_index(reader), expected_fulltext[i]);
EXPECT_EQ(IndexReaderHelper::is_string_index(reader), expected_string[i]);
EXPECT_EQ(IndexReaderHelper::is_bkd_index(reader), expected_bkd[i]);
i++;
}
}
TEST_F(IndexReaderHelperTest, PropertiesVariationsTest) {
std::map<std::string, std::string> props1;
props1[INVERTED_INDEX_PARSER_PHRASE_SUPPORT_KEY] = "TRUE";
std::map<std::string, std::string> props2;
props2[INVERTED_INDEX_PARSER_PHRASE_SUPPORT_KEY] = "True";
std::map<std::string, std::string> props3;
props3[INVERTED_INDEX_PARSER_PHRASE_SUPPORT_KEY] = "false";
std::map<std::string, std::string> props4;
props4[INVERTED_INDEX_PARSER_PHRASE_SUPPORT_KEY] = "FALSE";
auto reader1 =
std::make_shared<MockInvertedIndexReader>(InvertedIndexReaderType::FULLTEXT, props1);
auto reader2 =
std::make_shared<MockInvertedIndexReader>(InvertedIndexReaderType::FULLTEXT, props2);
auto reader3 =
std::make_shared<MockInvertedIndexReader>(InvertedIndexReaderType::FULLTEXT, props3);
auto reader4 =
std::make_shared<MockInvertedIndexReader>(InvertedIndexReaderType::FULLTEXT, props4);
EXPECT_FALSE(IndexReaderHelper::is_support_phrase(reader1));
EXPECT_FALSE(IndexReaderHelper::is_support_phrase(reader2));
EXPECT_FALSE(IndexReaderHelper::is_support_phrase(reader3));
EXPECT_FALSE(IndexReaderHelper::is_support_phrase(reader4));
}
TEST_F(IndexReaderHelperTest, IsNeedSimilarityScoreWithInvertedIndexQueryTypeTest) {
TabletIndex index_meta;
auto index_meta_pb = std::make_unique<TabletIndexPB>();
index_meta_pb->set_index_type(IndexType::INVERTED);
index_meta_pb->set_index_id(1);
index_meta_pb->set_index_name("test_index");
index_meta_pb->add_col_unique_id(1);
auto* properties = index_meta_pb->mutable_properties();
(*properties)[INVERTED_INDEX_PARSER_PHRASE_SUPPORT_KEY] =
INVERTED_INDEX_PARSER_PHRASE_SUPPORT_YES;
index_meta.init_from_pb(*index_meta_pb);
EXPECT_TRUE(IndexReaderHelper::is_need_similarity_score(InvertedIndexQueryType::MATCH_ANY_QUERY,
&index_meta));
EXPECT_TRUE(IndexReaderHelper::is_need_similarity_score(
InvertedIndexQueryType::MATCH_PHRASE_QUERY, &index_meta));
EXPECT_FALSE(IndexReaderHelper::is_need_similarity_score(InvertedIndexQueryType::EQUAL_QUERY,
&index_meta));
EXPECT_FALSE(IndexReaderHelper::is_need_similarity_score(
InvertedIndexQueryType::LESS_THAN_QUERY, &index_meta));
}
TEST_F(IndexReaderHelperTest, IsNeedSimilarityScoreWithTExprOpcodeTest) {
TabletIndex index_meta;
auto index_meta_pb = std::make_unique<TabletIndexPB>();
index_meta_pb->set_index_type(IndexType::INVERTED);
index_meta_pb->set_index_id(1);
index_meta_pb->set_index_name("test_index");
index_meta_pb->add_col_unique_id(1);
auto* properties = index_meta_pb->mutable_properties();
(*properties)[INVERTED_INDEX_PARSER_PHRASE_SUPPORT_KEY] =
INVERTED_INDEX_PARSER_PHRASE_SUPPORT_YES;
index_meta.init_from_pb(*index_meta_pb);
EXPECT_TRUE(IndexReaderHelper::is_need_similarity_score(TExprOpcode::MATCH_ANY, &index_meta));
EXPECT_TRUE(
IndexReaderHelper::is_need_similarity_score(TExprOpcode::MATCH_PHRASE, &index_meta));
EXPECT_FALSE(IndexReaderHelper::is_need_similarity_score(TExprOpcode::EQ, &index_meta));
EXPECT_FALSE(IndexReaderHelper::is_need_similarity_score(TExprOpcode::LT, &index_meta));
}