blob: 746ac07901f5f88acd8b87768e333a2c2194226e [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 <cstddef>
#include <memory>
#include <string>
#include <vector>
#include "gtest/gtest_pred_impl.h"
#include "util/bitmap_value.h"
#include "vec/aggregate_functions/aggregate_function.h"
#include "vec/aggregate_functions/aggregate_function_simple_factory.h"
#include "vec/columns/column.h"
#include "vec/columns/column_complex.h"
#include "vec/core/field.h"
#include "vec/core/types.h"
#include "vec/data_types/data_type_bitmap.h"
#include "vec/data_types/data_type_decimal.h"
#include "vec/data_types/data_type_number.h"
#include "vec/data_types/data_type_string.h"
const int agg_test_batch_size = 10;
namespace doris::vectorized {
// declare function
void register_aggregate_function_bitmap(AggregateFunctionSimpleFactory& factory);
TEST(AggBitmapTest, bitmap_union_test) {
Arena arena;
std::string function_name = "bitmap_union";
auto data_type = std::make_shared<DataTypeBitMap>();
// Prepare test data.
auto column_bitmap = data_type->create_column();
for (int i = 0; i < agg_test_batch_size; i++) {
BitmapValue bitmap_value(i);
assert_cast<ColumnBitmap&>(*column_bitmap).insert_value(bitmap_value);
}
// Prepare test function and parameters.
AggregateFunctionSimpleFactory factory;
register_aggregate_function_bitmap(factory);
DataTypes data_types = {data_type};
auto agg_function = factory.get(function_name, data_types, nullptr, false, -1);
agg_function->set_version(3);
std::unique_ptr<char[]> memory(new char[agg_function->size_of_data()]);
AggregateDataPtr place = memory.get();
agg_function->create(place);
// Do aggregation.
const IColumn* column[1] = {column_bitmap.get()};
for (int i = 0; i < agg_test_batch_size; i++) {
agg_function->add(place, column, i, arena);
}
// Check result.
ColumnBitmap ans;
agg_function->insert_result_into(place, ans);
EXPECT_EQ(ans.size(), 1);
EXPECT_EQ(ans.get_element(0).cardinality(), agg_test_batch_size);
agg_function->destroy(place);
auto dst = agg_function->create_serialize_column();
agg_function->streaming_agg_serialize_to_column(column, dst, agg_test_batch_size, arena);
for (size_t i = 0; i != agg_test_batch_size; ++i) {
EXPECT_EQ(std::to_string(i), assert_cast<ColumnBitmap&>(*dst).get_element(i).to_string());
}
}
TEST(AggBitmapTest, group_bitmap_xor_test) {
Arena arena;
std::string function_name = "group_bitmap_xor";
auto data_type = std::make_shared<DataTypeBitMap>();
// Prepare test data.
auto column_bitmap = data_type->create_column();
// Insert first bitmap: {4, 7, 8}
std::vector<int> values_1 = {4, 7, 8};
BitmapValue bitmap_value_1;
for (int value : values_1) {
bitmap_value_1.add(value);
}
assert_cast<ColumnBitmap&>(*column_bitmap).insert_value(bitmap_value_1);
// Insert second bitmap: {1, 3, 6, 15}
std::vector<int> values_2 = {1, 3, 6, 15};
BitmapValue bitmap_value_2;
for (int value : values_2) {
bitmap_value_2.add(value);
}
assert_cast<ColumnBitmap&>(*column_bitmap).insert_value(bitmap_value_2);
// Insert third bitmap: {4, 7}
std::vector<int> values_3 = {4, 7};
BitmapValue bitmap_value_3;
for (int value : values_3) {
bitmap_value_3.add(value);
}
assert_cast<ColumnBitmap&>(*column_bitmap).insert_value(bitmap_value_3);
// Prepare test function and parameters.
AggregateFunctionSimpleFactory factory;
register_aggregate_function_bitmap(factory);
DataTypes data_types = {data_type};
auto agg_function = factory.get(function_name, data_types, nullptr, false, -1);
agg_function->set_version(3);
std::unique_ptr<char[]> memory(new char[agg_function->size_of_data()]);
AggregateDataPtr place = memory.get();
agg_function->create(place);
// Do aggregation.
const IColumn* column[1] = {column_bitmap.get()};
for (int i = 0; i < 3; i++) {
agg_function->add(place, column, i, arena);
}
// Check result.
ColumnBitmap ans;
agg_function->insert_result_into(place, ans);
EXPECT_EQ(ans.size(), 1);
EXPECT_EQ(ans.get_element(0).cardinality(), 5); // Expected intersection: {1, 3, 6, 8, 15}
agg_function->destroy(place);
auto dst = agg_function->create_serialize_column();
BitmapValue intersection_result = ans.get_element(0);
assert_cast<ColumnBitmap&>(*dst).insert_value(intersection_result);
std::vector<int> expected_values = {1, 3, 6, 8, 15};
BitmapValue expected_intersection;
for (int value : expected_values) {
expected_intersection.add(value);
}
EXPECT_EQ(expected_intersection.to_string(),
assert_cast<ColumnBitmap&>(*dst).get_element(0).to_string());
}
TEST(AggBitmapTest, bitmap_intersect_test) {
Arena arena;
std::string function_name = "bitmap_intersect";
auto data_type = std::make_shared<DataTypeBitMap>();
// Prepare test data.
auto column_bitmap = data_type->create_column();
// Insert first bitmap: {0, 1, 2, 3, 4, 5}
std::vector<int> values_1 = {0, 1, 2, 3, 4, 5};
BitmapValue bitmap_value_1;
for (int value : values_1) {
bitmap_value_1.add(value);
}
assert_cast<ColumnBitmap&>(*column_bitmap).insert_value(bitmap_value_1);
// Insert second bitmap: {0, 1, 2, 3, 100}
std::vector<int> values_2 = {0, 1, 2, 3, 100};
BitmapValue bitmap_value_2;
for (int value : values_2) {
bitmap_value_2.add(value);
}
assert_cast<ColumnBitmap&>(*column_bitmap).insert_value(bitmap_value_2);
// Prepare test function and parameters.
AggregateFunctionSimpleFactory factory;
register_aggregate_function_bitmap(factory);
DataTypes data_types = {data_type};
auto agg_function = factory.get(function_name, data_types, nullptr, false, -1);
agg_function->set_version(3);
std::unique_ptr<char[]> memory(new char[agg_function->size_of_data()]);
AggregateDataPtr place = memory.get();
agg_function->create(place);
// Do aggregation.
const IColumn* column[1] = {column_bitmap.get()};
for (int i = 0; i < 2; i++) {
agg_function->add(place, column, i, arena);
}
// Check result.
ColumnBitmap ans;
agg_function->insert_result_into(place, ans);
EXPECT_EQ(ans.size(), 1);
EXPECT_EQ(ans.get_element(0).cardinality(), 4); // Expected intersection: {0, 1, 2, 3}
agg_function->destroy(place);
auto dst = agg_function->create_serialize_column();
BitmapValue intersection_result = ans.get_element(0);
assert_cast<ColumnBitmap&>(*dst).insert_value(intersection_result);
BitmapValue expected_intersection;
for (int i = 0; i < 4; i++) {
expected_intersection.add(i);
}
EXPECT_EQ(expected_intersection.to_string(),
assert_cast<ColumnBitmap&>(*dst).get_element(0).to_string());
}
TEST(AggBitmapTest, bitmap_union_count_test) {
Arena arena;
std::string function_name = "bitmap_union_count";
auto data_type = std::make_shared<DataTypeBitMap>();
// Prepare test data.
auto column_bitmap = data_type->create_column();
std::vector<int> values = {1, 2, 3, 4, 5, 1, 2, 3, 100};
auto values_size = values.size();
for (int value : values) {
BitmapValue bitmap_value(value);
assert_cast<ColumnBitmap&>(*column_bitmap).insert_value(bitmap_value);
}
// Prepare test function and parameters.
AggregateFunctionSimpleFactory factory;
register_aggregate_function_bitmap(factory);
auto agg_function = factory.get(function_name, {data_type}, nullptr, false, -1);
agg_function->set_version(3);
std::unique_ptr<char[]> memory(new char[agg_function->size_of_data()]);
AggregateDataPtr place = memory.get();
agg_function->create(place);
// Do aggregation.
const IColumn* column[1] = {column_bitmap.get()};
for (int i = 0; i < values_size; i++) {
agg_function->add(place, column, i, arena);
}
// Check result.
ColumnInt64 ans;
agg_function->insert_result_into(place, ans);
EXPECT_EQ(ans.get_element(0), 6);
agg_function->destroy(place);
}
template <PrimitiveType T>
void validate_bitmap_union_int_test() {
Arena arena;
std::string function_name = "bitmap_union_int";
DataTypePtr data_type;
if constexpr (T == TYPE_TINYINT) {
data_type = std::make_shared<DataTypeInt8>();
} else if constexpr (T == TYPE_SMALLINT) {
data_type = std::make_shared<DataTypeInt16>();
} else if constexpr (T == TYPE_INT) {
data_type = std::make_shared<DataTypeInt32>();
} else if constexpr (T == TYPE_BIGINT) {
data_type = std::make_shared<DataTypeInt64>();
} else {
LOG(FATAL) << "unsupported type";
}
// Prepare test data.
auto column_int = data_type->create_column();
std::vector<typename PrimitiveTypeTraits<T>::ColumnItemType> values = {1, 2, 3, 4, 5,
1, 2, 3, 100};
auto values_size = values.size();
for (int value : values) {
(*column_int).insert(Field::create_field<T>(value));
}
// Prepare test function and parameters.
AggregateFunctionSimpleFactory factory;
register_aggregate_function_bitmap(factory);
auto agg_function = factory.get(function_name, {data_type}, nullptr, false, -1);
agg_function->set_version(3);
std::unique_ptr<char[]> memory(new char[agg_function->size_of_data()]);
AggregateDataPtr place = memory.get();
agg_function->create(place);
// Do aggregation.
const IColumn* column[1] = {column_int.get()};
for (int i = 0; i < values_size; i++) {
agg_function->add(place, column, i, arena);
}
// Check result.
ColumnInt64 ans;
agg_function->insert_result_into(place, ans);
EXPECT_EQ(ans.get_element(0), 6);
agg_function->destroy(place);
}
TEST(AggBitmapTest, bitmap_union_int_test) {
validate_bitmap_union_int_test<TYPE_TINYINT>();
validate_bitmap_union_int_test<TYPE_SMALLINT>();
validate_bitmap_union_int_test<TYPE_INT>();
validate_bitmap_union_int_test<TYPE_BIGINT>();
}
} // namespace doris::vectorized