blob: fed5bd84322dc58d65e430d02e61af77f24f2023 [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 <stddef.h>
#include <algorithm>
#include <functional>
#include <memory>
#include <type_traits>
#include <utility>
#include <vector>
#include "common/status.h"
#include "util/bitmap_value.h"
#include "vec/aggregate_functions/aggregate_function.h"
#include "vec/columns/column.h"
#include "vec/columns/column_complex.h"
#include "vec/columns/column_nullable.h"
#include "vec/columns/column_vector.h"
#include "vec/common/assert_cast.h"
#include "vec/core/block.h"
#include "vec/core/column_numbers.h"
#include "vec/core/column_with_type_and_name.h"
#include "vec/core/types.h"
#include "vec/data_types/data_type.h"
#include "vec/data_types/data_type_bitmap.h"
#include "vec/data_types/data_type_nullable.h"
#include "vec/data_types/data_type_number.h"
#include "vec/functions/function.h"
#include "vec/functions/simple_function_factory.h"
namespace doris {
class FunctionContext;
} // namespace doris
namespace doris::vectorized {
// currently only bitmap_or and bitmap_or_count will call this function,
// other bitmap functions will use default implementation for nulls
#define BITMAP_OR_NULLABLE(nullable, input_rows_count, res, op) \
const auto& nested_col_ptr = nullable->get_nested_column_ptr(); \
const auto* __restrict null_map_data = nullable->get_null_map_data().data(); \
const auto& mid_data = assert_cast<const ColumnBitmap*>(nested_col_ptr.get())->get_data(); \
for (size_t row = 0; row < input_rows_count; ++row) { \
if (!null_map_data[row]) { \
res[row] op mid_data[row]; \
} \
}
#define BITMAP_FUNCTION_VARIADIC(CLASS, FUNCTION_NAME, OP) \
struct CLASS { \
static constexpr auto name = #FUNCTION_NAME; \
using ResultDataType = DataTypeBitMap; \
static Status vector_vector(ColumnPtr argument_columns[], size_t col_size, \
size_t input_rows_count, std::vector<BitmapValue>& res, \
IColumn* res_nulls) { \
std::vector<const ColumnUInt8::value_type*> null_map_datas(col_size); \
int nullable_cols_count = 0; \
ColumnUInt8::value_type* __restrict res_nulls_data = nullptr; \
if (res_nulls) { \
res_nulls_data = assert_cast<ColumnUInt8*>(res_nulls)->get_data().data(); \
} \
if (auto* nullable = check_and_get_column<ColumnNullable>(*argument_columns[0])) { \
null_map_datas[nullable_cols_count++] = nullable->get_null_map_data().data(); \
BITMAP_OR_NULLABLE(nullable, input_rows_count, res, =); \
} else { \
const auto& mid_data = \
assert_cast<const ColumnBitmap*>(argument_columns[0].get())->get_data(); \
for (size_t row = 0; row < input_rows_count; ++row) { \
res[row] = mid_data[row]; \
} \
} \
for (size_t col = 1; col < col_size; ++col) { \
if (auto* nullable = \
check_and_get_column<ColumnNullable>(*argument_columns[col])) { \
null_map_datas[nullable_cols_count++] = nullable->get_null_map_data().data(); \
BITMAP_OR_NULLABLE(nullable, input_rows_count, res, OP); \
} else { \
const auto& col_data = \
assert_cast<const ColumnBitmap*>(argument_columns[col].get()) \
->get_data(); \
for (size_t row = 0; row < input_rows_count; ++row) { \
res[row] OP col_data[row]; \
} \
} \
} \
if (res_nulls_data && nullable_cols_count == col_size) { \
const auto* null_map_data = null_map_datas[0]; \
for (size_t row = 0; row < input_rows_count; ++row) { \
res_nulls_data[row] = null_map_data[row]; \
} \
for (int i = 1; i < nullable_cols_count; ++i) { \
null_map_data = null_map_datas[i]; \
for (size_t row = 0; row < input_rows_count; ++row) { \
res_nulls_data[row] &= null_map_data[row]; \
} \
} \
} \
return Status::OK(); \
} \
}
#define BITMAP_FUNCTION_COUNT_VARIADIC(CLASS, FUNCTION_NAME, OP) \
struct CLASS { \
static constexpr auto name = #FUNCTION_NAME; \
using ResultDataType = DataTypeInt64; \
using TData = std::vector<BitmapValue>; \
using ResTData = typename ColumnInt64::Container; \
static Status vector_vector(ColumnPtr argument_columns[], size_t col_size, \
size_t input_rows_count, ResTData& res, IColumn* res_nulls) { \
TData vals; \
if (auto* nullable = check_and_get_column<ColumnNullable>(*argument_columns[0])) { \
vals.resize(input_rows_count); \
BITMAP_OR_NULLABLE(nullable, input_rows_count, vals, =); \
} else { \
vals = assert_cast<const ColumnBitmap*>(argument_columns[0].get())->get_data(); \
} \
for (size_t col = 1; col < col_size; ++col) { \
if (auto* nullable = \
check_and_get_column<ColumnNullable>(*argument_columns[col])) { \
BITMAP_OR_NULLABLE(nullable, input_rows_count, vals, OP); \
} else { \
const auto& col_data = \
assert_cast<const ColumnBitmap*>(argument_columns[col].get()) \
->get_data(); \
for (size_t row = 0; row < input_rows_count; ++row) { \
vals[row] OP col_data[row]; \
} \
} \
} \
for (size_t row = 0; row < input_rows_count; ++row) { \
res[row] = vals[row].cardinality(); \
} \
return Status::OK(); \
} \
}
BITMAP_FUNCTION_VARIADIC(BitmapOr, bitmap_or, |=);
BITMAP_FUNCTION_VARIADIC(BitmapAnd, bitmap_and, &=);
BITMAP_FUNCTION_VARIADIC(BitmapXor, bitmap_xor, ^=);
BITMAP_FUNCTION_COUNT_VARIADIC(BitmapOrCount, bitmap_or_count, |=);
BITMAP_FUNCTION_COUNT_VARIADIC(BitmapAndCount, bitmap_and_count, &=);
BITMAP_FUNCTION_COUNT_VARIADIC(BitmapXorCount, bitmap_xor_count, ^=);
Status execute_bitmap_op_count_null_to_zero(
FunctionContext* context, Block& block, const ColumnNumbers& arguments, uint32_t result,
size_t input_rows_count,
const std::function<Status(FunctionContext*, Block&, const ColumnNumbers&, size_t, size_t)>&
exec_impl_func);
template <typename Impl>
class FunctionBitMapVariadic : public IFunction {
public:
static constexpr auto name = Impl::name;
static FunctionPtr create() { return std::make_shared<FunctionBitMapVariadic>(); }
String get_name() const override { return name; }
size_t get_number_of_arguments() const override { return 0; }
bool is_variadic() const override { return true; }
DataTypePtr get_return_type_impl(const DataTypes& arguments) const override {
using ResultDataType = typename Impl::ResultDataType;
if (std::is_same_v<Impl, BitmapOr> || is_count()) {
bool return_nullable = false;
// result is nullable only when any columns is nullable for bitmap_or and bitmap_or_count
for (size_t i = 0; i < arguments.size(); ++i) {
if (arguments[i]->is_nullable()) {
return_nullable = true;
break;
}
}
auto result_type = std::make_shared<ResultDataType>();
return return_nullable ? make_nullable(result_type) : result_type;
} else {
return std::make_shared<ResultDataType>();
}
}
bool use_default_implementation_for_nulls() const override {
// result is null only when all columns is null for bitmap_or.
// for count functions, result is always not null, and if the bitmap op result is null,
// the count is 0
return !static_cast<bool>(std::is_same_v<Impl, BitmapOr> || is_count());
}
Status execute_impl(FunctionContext* context, Block& block, const ColumnNumbers& arguments,
uint32_t result, size_t input_rows_count) const override {
if (std::is_same_v<Impl, BitmapAndCount> || std::is_same_v<Impl, BitmapXorCount>) {
auto impl_func = [&](FunctionContext* context, Block& block,
const ColumnNumbers& arguments, uint32_t result,
size_t input_rows_count) {
return execute_impl_internal(context, block, arguments, result, input_rows_count);
};
return execute_bitmap_op_count_null_to_zero(context, block, arguments, result,
input_rows_count, impl_func);
} else {
return execute_impl_internal(context, block, arguments, result, input_rows_count);
}
}
Status execute_impl_internal(FunctionContext* context, Block& block,
const ColumnNumbers& arguments, uint32_t result,
size_t input_rows_count) const {
size_t argument_size = arguments.size();
std::vector<ColumnPtr> argument_columns(argument_size);
for (size_t i = 0; i < argument_size; ++i) {
argument_columns[i] =
block.get_by_position(arguments[i]).column->convert_to_full_column_if_const();
}
using ResultDataType = typename Impl::ResultDataType; //DataTypeBitMap or DataTypeInt64
using ColVecResult = std::conditional_t<is_complex_v<ResultDataType::PType>,
ColumnComplexType<ResultDataType::PType>,
ColumnVector<ResultDataType::PType>>;
typename ColVecResult::MutablePtr col_res = nullptr;
typename ColumnUInt8::MutablePtr col_res_nulls;
auto& result_info = block.get_by_position(result);
// special case for bitmap_or and bitmap_or_count
if (!use_default_implementation_for_nulls() && result_info.type->is_nullable()) {
col_res_nulls = ColumnUInt8::create(input_rows_count, 0);
}
col_res = ColVecResult::create();
auto& vec_res = col_res->get_data();
vec_res.resize(input_rows_count);
RETURN_IF_ERROR(Impl::vector_vector(argument_columns.data(), argument_size,
input_rows_count, vec_res, col_res_nulls.get()));
if (!use_default_implementation_for_nulls() && result_info.type->is_nullable()) {
block.replace_by_position(
result, ColumnNullable::create(std::move(col_res), std::move(col_res_nulls)));
} else {
block.replace_by_position(result, std::move(col_res));
}
return Status::OK();
}
private:
bool is_count() const {
return (std::is_same_v<Impl, BitmapOrCount> || std::is_same_v<Impl, BitmapAndCount> ||
std::is_same_v<Impl, BitmapXorCount>);
}
};
using FunctionBitmapOr = FunctionBitMapVariadic<BitmapOr>;
using FunctionBitmapXor = FunctionBitMapVariadic<BitmapXor>;
using FunctionBitmapAnd = FunctionBitMapVariadic<BitmapAnd>;
using FunctionBitmapOrCount = FunctionBitMapVariadic<BitmapOrCount>;
using FunctionBitmapAndCount = FunctionBitMapVariadic<BitmapAndCount>;
using FunctionBitmapXorCount = FunctionBitMapVariadic<BitmapXorCount>;
void register_function_bitmap_variadic(SimpleFunctionFactory& factory) {
factory.register_function<FunctionBitmapOr>();
factory.register_function<FunctionBitmapXor>();
factory.register_function<FunctionBitmapAnd>();
factory.register_function<FunctionBitmapOrCount>();
factory.register_function<FunctionBitmapAndCount>();
factory.register_function<FunctionBitmapXorCount>();
}
} // namespace doris::vectorized