Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions be/src/core/value/bitmap_value.h
Original file line number Diff line number Diff line change
Expand Up @@ -1796,8 +1796,8 @@ class BitmapValue {
}
case SET: {
uint64_t cardinality = _set.size();
for (auto v : _set) {
if (!rhs._set.contains(v)) {
for (auto v : rhs._set) {
if (!_set.contains(v)) {
++cardinality;
}
}
Expand Down
1 change: 1 addition & 0 deletions be/src/exprs/function/function.h
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ namespace doris {

struct FunctionAttr {
bool new_version_unix_timestamp {false};
bool new_version_bitmap_op_count {false};
};

#define RETURN_REAL_TYPE_FOR_DATEV2_FUNCTION(TYPE) \
Expand Down
101 changes: 24 additions & 77 deletions be/src/exprs/function/function_bitmap.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -577,52 +577,6 @@ struct BitmapNot {
}
};

struct NameBitmapAndNot {
static constexpr auto name = "bitmap_and_not";
};

template <typename LeftDataType, typename RightDataType>
struct BitmapAndNot {
using ResultDataType = DataTypeBitMap;
using T0 = typename LeftDataType::FieldType;
using T1 = typename RightDataType::FieldType;
using TData = std::vector<BitmapValue>;

static void vector_vector(const TData& lvec, const TData& rvec, TData& res) {
size_t size = lvec.size();
BitmapValue mid_data;
for (size_t i = 0; i < size; ++i) {
mid_data = lvec[i];
mid_data &= rvec[i];
res[i] = lvec[i];
res[i] -= mid_data;
mid_data.reset();
}
}
static void vector_scalar(const TData& lvec, const BitmapValue& rval, TData& res) {
size_t size = lvec.size();
BitmapValue mid_data;
for (size_t i = 0; i < size; ++i) {
mid_data = lvec[i];
mid_data &= rval;
res[i] = lvec[i];
res[i] -= mid_data;
mid_data.reset();
}
}
static void scalar_vector(const BitmapValue& lval, const TData& rvec, TData& res) {
size_t size = rvec.size();
BitmapValue mid_data;
for (size_t i = 0; i < size; ++i) {
mid_data = lval;
mid_data &= rvec[i];
res[i] = lval;
res[i] -= mid_data;
mid_data.reset();
}
}
};

struct NameBitmapAndNotCount {
static constexpr auto name = "bitmap_and_not_count";
};
Expand All @@ -637,32 +591,20 @@ struct BitmapAndNotCount {

static void vector_vector(const TData& lvec, const TData& rvec, ResTData* res) {
size_t size = lvec.size();
BitmapValue mid_data;
for (size_t i = 0; i < size; ++i) {
mid_data = lvec[i];
mid_data &= rvec[i];
res[i] = lvec[i].andnot_cardinality(mid_data);
mid_data.reset();
res[i] = lvec[i].andnot_cardinality(rvec[i]);
}
}
static void scalar_vector(const BitmapValue& lval, const TData& rvec, ResTData* res) {
size_t size = rvec.size();
BitmapValue mid_data;
for (size_t i = 0; i < size; ++i) {
mid_data = lval;
mid_data &= rvec[i];
res[i] = lval.andnot_cardinality(mid_data);
mid_data.reset();
res[i] = lval.andnot_cardinality(rvec[i]);
}
}
static void vector_scalar(const TData& lvec, const BitmapValue& rval, ResTData* res) {
size_t size = lvec.size();
BitmapValue mid_data;
for (size_t i = 0; i < size; ++i) {
mid_data = lvec[i];
mid_data &= rval;
res[i] = lvec[i].andnot_cardinality(mid_data);
mid_data.reset();
res[i] = lvec[i].andnot_cardinality(rval);
}
}
};
Expand All @@ -682,8 +624,10 @@ ColumnPtr handle_bitmap_op_count_null_value(ColumnPtr& src, const Block& block,
const ColumnNumbers& args, uint32_t result,
size_t input_rows_count) {
MutableColumnPtr mutable_src = IColumn::mutate(std::move(src));
auto* nullable = assert_cast<ColumnNullable*>(mutable_src.get());
auto* src_not_nullable_mutable = &nullable->get_nested_column();
auto* src_not_nullable_mutable = mutable_src.get();
if (auto* nullable = check_and_get_column<ColumnNullable>(*mutable_src)) {
src_not_nullable_mutable = &nullable->get_nested_column();
}
auto* __restrict count_data =
assert_cast<ColumnInt64*>(src_not_nullable_mutable)->get_data().data();

Expand Down Expand Up @@ -734,28 +678,32 @@ Status execute_bitmap_op_count_null_to_zero(
return Status::OK();
}

template <typename FunctionName>
template <typename FunctionName, bool NewVersion = false>
class FunctionBitmapAndNotCount : public IFunction {
public:
using LeftDataType = DataTypeBitMap;
using RightDataType = DataTypeBitMap;
using ResultDataType = typename BitmapAndNotCount<LeftDataType, RightDataType>::ResultDataType;

static constexpr auto name = FunctionName::name;
static constexpr auto name = NewVersion ? "bitmap_and_not_count_v2" : FunctionName::name;
static FunctionPtr create() { return std::make_shared<FunctionBitmapAndNotCount>(); }
String get_name() const override { return name; }
size_t get_number_of_arguments() const override { return 2; }
DataTypePtr get_return_type_impl(const DataTypes& arguments) const override {
bool return_nullable = false;
// result is nullable only when any columns is nullable for bitmap_and_not_count
for (size_t i = 0; i < arguments.size(); ++i) {
if (arguments[i]->is_nullable()) {
return_nullable = true;
break;
if constexpr (NewVersion) {
return std::make_shared<ResultDataType>();
} else {
bool return_nullable = false;
// result is nullable only when any columns is nullable for bitmap_and_not_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;
}
auto result_type = std::make_shared<ResultDataType>();
return return_nullable ? make_nullable(result_type) : result_type;
}

bool use_default_implementation_for_nulls() const override {
Expand Down Expand Up @@ -1264,8 +1212,6 @@ using FunctionBitmapToBase64 = FunctionUnaryToType<BitmapToBase64, NameBitmapToB
using FunctionBitmapFromBase64 = FunctionBitmapAlwaysNull<BitmapFromBase64>;
using FunctionBitmapNot =
FunctionBinaryToType<DataTypeBitMap, DataTypeBitMap, BitmapNot, NameBitmapNot>;
using FunctionBitmapAndNot =
FunctionBinaryToType<DataTypeBitMap, DataTypeBitMap, BitmapAndNot, NameBitmapAndNot>;
using FunctionBitmapContains =
FunctionBinaryToType<DataTypeBitMap, DataTypeInt64, BitmapContains, NameBitmapContains>;
using FunctionBitmapRemove =
Expand Down Expand Up @@ -1294,9 +1240,10 @@ void register_function_bitmap(SimpleFunctionFactory& factory) {
factory.register_function<FunctionBitmapMax>();
factory.register_function<FunctionBitmapToString>();
factory.register_function<FunctionBitmapNot>();
factory.register_function<FunctionBitmapAndNot>();
factory.register_alias(NameBitmapAndNot::name, "bitmap_andnot");
factory.register_alias(NameBitmapNot::name, "bitmap_and_not");
factory.register_alias(NameBitmapNot::name, "bitmap_andnot");
factory.register_function<FunctionBitmapAndNotCount<NameBitmapAndNotCount>>();
factory.register_function<FunctionBitmapAndNotCount<NameBitmapAndNotCount, true>>();
factory.register_alias(NameBitmapAndNotCount::name, "bitmap_andnot_count");
factory.register_function<FunctionBitmapContains>();
factory.register_function<FunctionBitmapRemove>();
Expand Down
153 changes: 140 additions & 13 deletions be/src/exprs/function/function_bitmap_variadic.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -162,12 +162,30 @@ Status execute_bitmap_op_count_null_to_zero(
const std::function<Status(FunctionContext*, Block&, const ColumnNumbers&, size_t, size_t)>&
exec_impl_func);

template <typename Impl>
template <typename Impl, bool NewVersion = false>
class FunctionBitMapVariadic : public IFunction {
static_assert(!NewVersion || (NewVersion && (std::is_same_v<Impl, BitmapOrCount> ||
std::is_same_v<Impl, BitmapAndCount> ||
std::is_same_v<Impl, BitmapXorCount>)));

public:
static constexpr auto name = Impl::name;
static constexpr auto name = []() constexpr {
if constexpr (!NewVersion) {
return Impl::name;
} else if constexpr (std::is_same_v<Impl, BitmapOrCount>) {
return "bitmap_or_count_v2";
} else if constexpr (std::is_same_v<Impl, BitmapAndCount>) {
return "bitmap_and_count_v2";
} else if constexpr (std::is_same_v<Impl, BitmapXorCount>) {
return "bitmap_xor_count_v2";
} else {
return Impl::name;
}
}();

static FunctionPtr create() { return std::make_shared<FunctionBitMapVariadic>(); }
static FunctionPtr create() {
return std::make_shared<FunctionBitMapVariadic<Impl, NewVersion>>();
}

String get_name() const override { return name; }

Expand All @@ -177,6 +195,9 @@ class FunctionBitMapVariadic : public IFunction {

DataTypePtr get_return_type_impl(const DataTypes& arguments) const override {
using ResultDataType = typename Impl::ResultDataType;
if constexpr (NewVersion) {
return std::make_shared<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
Expand All @@ -202,7 +223,8 @@ class FunctionBitMapVariadic : public IFunction {

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>) {
if constexpr (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) {
Expand All @@ -219,12 +241,6 @@ class FunctionBitMapVariadic : public IFunction {
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>,
Expand All @@ -244,8 +260,26 @@ class FunctionBitMapVariadic : public IFunction {
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()));
bool used_binary_count_path = false;
if constexpr (std::is_same_v<Impl, BitmapOrCount> || std::is_same_v<Impl, BitmapAndCount> ||
std::is_same_v<Impl, BitmapXorCount>) {
if (argument_size == 2) {
RETURN_IF_ERROR(execute_binary_bitmap_count<Impl>(
block.get_by_position(arguments[0]).column,
block.get_by_position(arguments[1]).column, input_rows_count, vec_res));
used_binary_count_path = true;
}
}
if (!used_binary_count_path) {
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();
}
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)));
Expand All @@ -260,6 +294,93 @@ class FunctionBitMapVariadic : public IFunction {
return (std::is_same_v<Impl, BitmapOrCount> || std::is_same_v<Impl, BitmapAndCount> ||
std::is_same_v<Impl, BitmapXorCount>);
}

template <typename CountImpl>
Status execute_binary_bitmap_count(const ColumnPtr& lhs_column, const ColumnPtr& rhs_column,
size_t input_rows_count, ColumnInt64::Container& res) const {
static_assert(std::is_same_v<CountImpl, BitmapOrCount> ||
std::is_same_v<CountImpl, BitmapAndCount> ||
std::is_same_v<CountImpl, BitmapXorCount>);

struct BitmapColumnAccessor {
const std::vector<BitmapValue>* values = nullptr;
const BitmapValue* const_value = nullptr;
const ColumnUInt8::value_type* null_map_data = nullptr;
bool is_const = false;
bool is_const_null = false;

bool is_null_at(size_t row) const {
return is_const ? is_const_null : (null_map_data && null_map_data[row]);
}

const BitmapValue& get_value(size_t row) const {
return is_const ? *const_value : (*values)[row];
}
};

auto make_accessor = [](const ColumnPtr& column) {
BitmapColumnAccessor accessor;
const auto& [data_column_ptr, is_const] = unpack_if_const(column);
accessor.is_const = is_const;
const IColumn* data_column = data_column_ptr.get();

if (const auto* nullable = check_and_get_column<ColumnNullable>(*data_column)) {
if (accessor.is_const) {
accessor.is_const_null = nullable->is_null_at(0);
} else {
accessor.null_map_data = nullable->get_null_map_data().data();
}
data_column = nullable->get_nested_column_ptr().get();
}

const auto* bitmap_column = assert_cast<const ColumnBitmap*>(data_column);
if (accessor.is_const) {
accessor.const_value = &bitmap_column->get_data()[0];
} else {
accessor.values = &bitmap_column->get_data();
}

return accessor;
};

const auto lhs = make_accessor(lhs_column);
const auto rhs = make_accessor(rhs_column);

for (size_t row = 0; row < input_rows_count; ++row) {
const bool lhs_is_null = lhs.is_null_at(row);
const bool rhs_is_null = rhs.is_null_at(row);

if (lhs_is_null && rhs_is_null) {
res[row] = 0;
continue;
}

if constexpr (std::is_same_v<CountImpl, BitmapOrCount>) {
if (lhs_is_null) {
res[row] = rhs.get_value(row).cardinality();
} else if (rhs_is_null) {
res[row] = lhs.get_value(row).cardinality();
} else {
res[row] = lhs.get_value(row).or_cardinality(rhs.get_value(row));
}
} else if constexpr (std::is_same_v<CountImpl, BitmapAndCount>) {
res[row] = (lhs_is_null || rhs_is_null)
? 0
: lhs.get_value(row).and_cardinality(rhs.get_value(row));
} else {
if (lhs_is_null || rhs_is_null) {
res[row] = 0;
} else {
const auto& lhs_value = lhs.get_value(row);
const auto& rhs_value = rhs.get_value(row);
uint64_t inter = lhs_value.and_cardinality(rhs_value);
res[row] = lhs_value.cardinality() + rhs_value.cardinality() - 2 * inter;
}
}
}

return Status::OK();
}
};

using FunctionBitmapOr = FunctionBitMapVariadic<BitmapOr>;
Expand All @@ -268,6 +389,9 @@ using FunctionBitmapAnd = FunctionBitMapVariadic<BitmapAnd>;
using FunctionBitmapOrCount = FunctionBitMapVariadic<BitmapOrCount>;
using FunctionBitmapAndCount = FunctionBitMapVariadic<BitmapAndCount>;
using FunctionBitmapXorCount = FunctionBitMapVariadic<BitmapXorCount>;
using FunctionBitmapOrCountV2 = FunctionBitMapVariadic<BitmapOrCount, true>;
using FunctionBitmapAndCountV2 = FunctionBitMapVariadic<BitmapAndCount, true>;
using FunctionBitmapXorCountV2 = FunctionBitMapVariadic<BitmapXorCount, true>;

void register_function_bitmap_variadic(SimpleFunctionFactory& factory) {
factory.register_function<FunctionBitmapOr>();
Expand All @@ -276,5 +400,8 @@ void register_function_bitmap_variadic(SimpleFunctionFactory& factory) {
factory.register_function<FunctionBitmapOrCount>();
factory.register_function<FunctionBitmapAndCount>();
factory.register_function<FunctionBitmapXorCount>();
factory.register_function<FunctionBitmapOrCountV2>();
factory.register_function<FunctionBitmapAndCountV2>();
factory.register_function<FunctionBitmapXorCountV2>();
}
} // namespace doris
} // namespace doris
Loading
Loading