blob: ec0f199e496829ec8e9c393d8c0bd063361e15ae [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.
#pragma once
#include <cstdint>
#include <memory>
#include "common/factory_creator.h"
#include "olap/column_predicate.h"
#include "olap/rowset/segment_v2/bloom_filter.h"
#include "olap/rowset/segment_v2/inverted_index_reader.h"
#include "olap/wrapper_field.h"
#include "vec/columns/column_dictionary.h"
namespace doris {
/**
* A wrapper predicate that delegate to nested predicate
* but pass (set/return true) for NULL value rows.
*
* At parent, it's used for topn runtime predicate.
* Eg: original input indexs is '1,2,3,7,8,9' and value of index9 is null, we get nested predicate output index is '1,2,3', but we finally output '1,2,3,9'
*/
class AcceptNullPredicate : public ColumnPredicate {
ENABLE_FACTORY_CREATOR(AcceptNullPredicate);
public:
AcceptNullPredicate(ColumnPredicate* nested)
: ColumnPredicate(nested->column_id(), nested->opposite()), _nested {nested} {}
PredicateType type() const override { return _nested->type(); }
Status evaluate(BitmapIndexIterator* iterator, uint32_t num_rows,
roaring::Roaring* roaring) const override {
return _nested->evaluate(iterator, num_rows, roaring);
}
Status evaluate(const vectorized::IndexFieldNameAndTypePair& name_with_type,
IndexIterator* iterator, uint32_t num_rows,
roaring::Roaring* bitmap) const override {
return _nested->evaluate(name_with_type, iterator, num_rows, bitmap);
}
void evaluate_and(const vectorized::IColumn& column, const uint16_t* sel, uint16_t size,
bool* flags) const override {
if (column.has_null()) {
std::vector<uint8_t> original_flags(size);
memcpy(original_flags.data(), flags, size);
const auto& nullable_col = assert_cast<const vectorized::ColumnNullable&>(column);
_nested->evaluate_and(nullable_col.get_nested_column(), sel, size, flags);
const auto& nullmap = nullable_col.get_null_map_data();
for (uint16_t i = 0; i < size; ++i) {
flags[i] |= (original_flags[i] && nullmap[sel[i]]);
}
} else {
_nested->evaluate_and(column, sel, size, flags);
}
}
void evaluate_or(const vectorized::IColumn& column, const uint16_t* sel, uint16_t size,
bool* flags) const override {
DCHECK(false) << "should not reach here";
}
bool evaluate_and(const std::pair<WrapperField*, WrapperField*>& statistic) const override {
// there is null in range, accept it
if (statistic.first->is_null() || statistic.second->is_null()) {
return true;
}
return _nested->evaluate_and(statistic);
}
bool evaluate_del(const std::pair<WrapperField*, WrapperField*>& statistic) const override {
return _nested->evaluate_del(statistic);
}
bool evaluate_and(const BloomFilter* bf) const override { return _nested->evaluate_and(bf); }
bool can_do_bloom_filter(bool ngram) const override {
return _nested->can_do_bloom_filter(ngram);
}
void evaluate_vec(const vectorized::IColumn& column, uint16_t size,
bool* flags) const override {
if (column.has_null()) {
const auto& nullable_col = assert_cast<const vectorized::ColumnNullable&>(column);
_nested->evaluate_vec(nullable_col.get_nested_column(), size, flags);
for (uint16_t i = 0; i < size; ++i) {
if (!flags[i] && nullable_col.is_null_at(i)) {
// set true for NULL rows
flags[i] = true;
}
}
} else {
_nested->evaluate_vec(column, size, flags);
}
}
void evaluate_and_vec(const vectorized::IColumn& column, uint16_t size,
bool* flags) const override {
if (column.has_null()) {
// copy original flags
std::vector<uint8_t> original_flags(size);
memcpy(original_flags.data(), flags, size);
const auto& nullable_col = assert_cast<const vectorized::ColumnNullable&>(column);
// call evaluate_and_vec and restore true for NULL rows
_nested->evaluate_and_vec(nullable_col.get_nested_column(), size, flags);
for (uint16_t i = 0; i < size; ++i) {
if (original_flags[i] && !flags[i] && nullable_col.is_null_at(i)) {
flags[i] = true;
}
}
} else {
_nested->evaluate_and_vec(column, size, flags);
}
}
std::string get_search_str() const override { return _nested->get_search_str(); }
private:
uint16_t _evaluate_inner(const vectorized::IColumn& column, uint16_t* sel,
uint16_t size) const override {
if (column.has_null()) {
if (size == 0) {
return 0;
}
// create selected_flags
uint16_t max_idx = sel[size - 1];
std::vector<uint16_t> old_sel(size);
memcpy(old_sel.data(), sel, sizeof(uint16_t) * size);
const auto& nullable_col = assert_cast<const vectorized::ColumnNullable&>(column);
// call nested predicate evaluate
uint16_t new_size = _nested->evaluate(nullable_col.get_nested_column(), sel, size);
// process NULL values
if (new_size < size) {
std::vector<uint8_t> selected(max_idx + 1, 0);
const auto* nullmap = nullable_col.get_null_map_data().data();
// add rows selected by _nested->evaluate
for (uint16_t i = 0; i < new_size; ++i) {
uint16_t row_idx = sel[i];
selected[row_idx] = true;
}
// reset null from original data
for (uint16_t i = 0; i < size; ++i) {
uint16_t row_idx = old_sel[i];
selected[row_idx] |= nullmap[row_idx];
}
// recaculate new_size and sel array
new_size = 0;
for (uint16_t row_idx = 0; row_idx < max_idx + 1; ++row_idx) {
if (selected[row_idx]) {
sel[new_size++] = row_idx;
}
}
}
return new_size;
}
return _nested->evaluate(column, sel, size);
}
std::string _debug_string() const override {
return "passnull predicate for " + _nested->debug_string();
}
std::unique_ptr<ColumnPredicate> _nested;
};
} //namespace doris