You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@doris.apache.org by kx...@apache.org on 2024/09/02 02:00:06 UTC
(doris) branch master updated: [Refactor](inverted index) refactor inverted index compound predicates evaluate logic (#38908)
This is an automated email from the ASF dual-hosted git repository.
kxiao pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/doris.git
The following commit(s) were added to refs/heads/master by this push:
new bd08d1bcb2b [Refactor](inverted index) refactor inverted index compound predicates evaluate logic (#38908)
bd08d1bcb2b is described below
commit bd08d1bcb2b913bebfb5e2cc688482d25e7ce6ae
Author: airborne12 <ai...@gmail.com>
AuthorDate: Mon Sep 2 09:59:58 2024 +0800
[Refactor](inverted index) refactor inverted index compound predicates evaluate logic (#38908)
This PR addresses several key issues related to the compound condition
support in the inverted index, and optimization for index skipping
without returning to the table:
1. **Unified Handling of `expr` and `column predicate`**:
- Combined the processing of inverted index-related `column predicate`
and `expr`.
- Ensured that compound conditions involving both `column predicate` and
`expr` are processed uniformly to reduce complexity and improve
robustness.
2. **Optimized the Execution of Compound Conditions**:
- Removed the logic in `scan_operator` that normalized compound
predicates by pushing down logic to `_common_expr_ctxs_push_down` where
`expr` contexts are managed.
- Added `evaluate_inverted_index` support to the `vexpr` and function
layers, such as `function comparison` and `function collection_in`.
- Introduced new data structures in `VExprContext` to store results from
`evaluate_inverted_index`, thus facilitating quick lookup and
application of these results during execution.
---
.../rowset/segment_v2/inverted_index_reader.cpp | 6 +
.../olap/rowset/segment_v2/inverted_index_reader.h | 100 ++-
be/src/olap/rowset/segment_v2/segment_iterator.cpp | 786 ++++-----------------
be/src/olap/rowset/segment_v2/segment_iterator.h | 52 +-
be/src/pipeline/exec/scan_operator.cpp | 20 -
be/src/vec/exprs/vcompound_pred.h | 142 ++--
be/src/vec/exprs/vectorized_fn_call.cpp | 75 +-
be/src/vec/exprs/vectorized_fn_call.h | 11 +-
be/src/vec/exprs/vexpr.cpp | 184 +++--
be/src/vec/exprs/vexpr.h | 24 +-
be/src/vec/exprs/vexpr_context.cpp | 14 +-
be/src/vec/exprs/vexpr_context.h | 132 +++-
be/src/vec/exprs/vin_predicate.cpp | 27 +-
be/src/vec/exprs/vin_predicate.h | 2 +-
be/src/vec/exprs/vliteral.h | 1 +
be/src/vec/exprs/vmatch_predicate.cpp | 30 +-
be/src/vec/exprs/vmatch_predicate.h | 3 +-
be/src/vec/functions/array/function_array_index.h | 78 +-
be/src/vec/functions/function.h | 47 +-
be/src/vec/functions/function_multi_match.cpp | 119 +---
be/src/vec/functions/function_multi_match.h | 7 +-
be/src/vec/functions/functions_comparison.h | 68 ++
be/src/vec/functions/in.h | 58 ++
be/src/vec/functions/match.cpp | 178 +++--
be/src/vec/functions/match.h | 5 +
.../test_index_match_phrase_prefix.out | 22 +-
.../test_all_index_hit_fault_injection.groovy | 6 +-
.../test_index_inlist_fault_injection.groovy | 3 -
.../test_index_mow_fault_injection.groovy | 1 +
.../test_need_read_data_fault_injection.groovy | 1 +
.../test_topn_fault_injection.groovy | 1 +
.../char_filter/test_char_replace.groovy | 2 +-
.../test_index_compaction_dup_keys.groovy | 1 +
.../test_index_compaction_null.groovy | 1 +
.../test_index_compaction_unique_keys.groovy | 1 +
...dex_compaction_with_multi_index_segments.groovy | 1 +
...est_cumulative_compaction_with_format_v2.groovy | 1 +
.../test_drop_column_with_format_v2.groovy | 1 +
.../test_drop_index_with_format_v2.groovy | 1 +
.../test_mor_table_with_format_v2.groovy | 1 +
.../test_mow_table_with_format_v2.groovy | 1 +
.../test_rename_column_with_format_v2.groovy | 1 +
...single_replica_compaction_with_format_v2.groovy | 1 +
.../storage_format/test_storage_format_v1.groovy | 1 +
.../storage_format/test_storage_format_v2.groovy | 1 +
.../test_array_contains_with_inverted_index.groovy | 1 +
.../inverted_index_p0/test_array_index.groovy | 1 +
.../test_array_with_inverted_index_all_type.groovy | 1 +
.../inverted_index_p0/test_chinese_analyzer.groovy | 1 +
.../suites/inverted_index_p0/test_compound.groovy | 1 +
.../inverted_index_p0/test_compound_1.groovy | 1 +
.../inverted_index_p0/test_compound_inlist.groovy | 1 +
.../inverted_index_p0/test_count_on_index.groovy | 1 +
.../inverted_index_p0/test_count_on_index_2.groovy | 1 +
.../suites/inverted_index_p0/test_delete.groovy | 1 +
.../test_equal_on_fulltext.groovy | 1 +
.../test_index_chinese_column.groovy | 1 +
.../test_index_complex_match.groovy | 1 +
.../inverted_index_p0/test_index_delete.groovy | 1 +
.../test_index_empty_string.groovy | 2 +-
.../test_index_equal_select.groovy | 1 +
.../test_index_key_match_select.groovy | 1 +
.../test_index_lowercase_fault_injection.groovy | 1 +
.../test_index_match_phrase.groovy | 1 +
.../test_index_match_phrase_edge.groovy | 6 +-
.../test_index_match_phrase_ordered.groovy | 6 +-
.../test_index_match_phrase_prefix.groovy | 18 +-
.../test_index_match_phrase_prefix_1.groovy | 6 +-
.../test_index_match_phrase_slop.groovy | 6 +-
.../test_index_match_regexp.groovy | 6 +-
.../test_index_match_select.groovy | 1 +
.../test_index_multi_match.groovy | 2 +-
.../test_index_no_need_read_data.groovy | 1 +
.../inverted_index_p0/test_index_null.groovy | 2 +-
.../test_index_range_between_select.groovy | 1 +
...test_index_range_bigger_and_equal_select.groovy | 2 +-
.../test_index_range_bigger_select.groovy | 2 +-
.../test_index_range_in_select.groovy | 1 +
.../test_index_range_not_in_select.groovy | 1 +
...est_index_range_smaller_and_equal_select.groovy | 2 +-
.../test_index_range_smaller_select.groovy | 2 +-
.../inverted_index_p0/test_index_rqg_bug.groovy | 2 +-
.../inverted_index_p0/test_index_rqg_bug2.groovy | 2 +-
.../inverted_index_p0/test_index_rqg_bug3.groovy | 2 +-
.../inverted_index_p0/test_index_rqg_bug4.groovy | 1 +
.../test_index_skip_read_data.groovy | 2 +-
.../inverted_index_p0/test_inverted_index.groovy | 1 +
.../test_inverted_index_keyword.groovy | 2 +-
.../test_inverted_index_mor.groovy | 2 +-
.../test_inverted_index_null.groovy | 1 +
.../test_inverted_index_null_ram_dir.groovy | 1 +
.../test_inverted_index_v2_file_size.groovy | 1 +
.../suites/inverted_index_p0/test_lowercase.groovy | 1 +
.../test_match_query_without_index.groovy | 2 +-
.../test_match_without_index.groovy | 1 +
.../inverted_index_p0/test_need_read_data.groovy | 1 +
.../inverted_index_p0/test_no_index_match.groovy | 1 +
.../inverted_index_p0/test_null_index.groovy | 2 +-
.../inverted_index_p0/test_or_not_match.groovy | 1 +
.../test_pk_no_need_read_data.groovy | 1 +
.../suites/inverted_index_p0/test_stopwords.groovy | 1 +
.../inverted_index_p0/topn_clear_block.groovy | 1 +
.../test_mow_with_null_sequence.groovy | 1 +
.../unique_with_mow/test_pk_uk_case.groovy | 1 +
.../test_primary_key_simple_case.groovy | 1 +
.../test_unique_mow_sequence.groovy | 1 +
.../suites/variant_p0/with_index/load.groovy | 3 +-
.../suites/variant_p0/with_index/var_index.groovy | 1 +
108 files changed, 1127 insertions(+), 1213 deletions(-)
diff --git a/be/src/olap/rowset/segment_v2/inverted_index_reader.cpp b/be/src/olap/rowset/segment_v2/inverted_index_reader.cpp
index 609a41a5f99..6cf9de5df1a 100644
--- a/be/src/olap/rowset/segment_v2/inverted_index_reader.cpp
+++ b/be/src/olap/rowset/segment_v2/inverted_index_reader.cpp
@@ -156,6 +156,10 @@ std::unique_ptr<lucene::util::Reader> InvertedIndexReader::create_reader(
return reader;
}
+std::string InvertedIndexReader::get_index_file_path() {
+ return _inverted_index_file_reader->get_index_file_path(&_index_meta);
+}
+
void InvertedIndexReader::get_analyse_result(std::vector<std::string>& analyse_result,
lucene::util::Reader* reader,
lucene::analysis::Analyzer* analyzer,
@@ -231,6 +235,8 @@ Status InvertedIndexReader::read_null_bitmap(OlapReaderStatistics* stats,
null_bitmap->runOptimize();
cache->insert(cache_key, null_bitmap, cache_handle);
FINALIZE_INPUT(null_bitmap_in);
+ } else {
+ cache->insert(cache_key, null_bitmap, cache_handle);
}
if (owned_dir) {
FINALIZE_INPUT(dir);
diff --git a/be/src/olap/rowset/segment_v2/inverted_index_reader.h b/be/src/olap/rowset/segment_v2/inverted_index_reader.h
index 2377a91845f..e8395903d75 100644
--- a/be/src/olap/rowset/segment_v2/inverted_index_reader.h
+++ b/be/src/olap/rowset/segment_v2/inverted_index_reader.h
@@ -73,6 +73,104 @@ class InvertedIndexIterator;
class InvertedIndexQueryCacheHandle;
class InvertedIndexFileReader;
struct InvertedIndexQueryInfo;
+class InvertedIndexResultBitmap {
+private:
+ std::shared_ptr<roaring::Roaring> _data_bitmap = nullptr;
+ std::shared_ptr<roaring::Roaring> _null_bitmap = nullptr;
+
+public:
+ // Default constructor
+ InvertedIndexResultBitmap() = default;
+ ~InvertedIndexResultBitmap() = default;
+
+ // Constructor with arguments
+ InvertedIndexResultBitmap(std::shared_ptr<roaring::Roaring> data_bitmap,
+ std::shared_ptr<roaring::Roaring> null_bitmap)
+ : _data_bitmap(std::move(data_bitmap)), _null_bitmap(std::move(null_bitmap)) {}
+
+ // Copy constructor
+ InvertedIndexResultBitmap(const InvertedIndexResultBitmap& other)
+ : _data_bitmap(std::make_shared<roaring::Roaring>(*other._data_bitmap)),
+ _null_bitmap(std::make_shared<roaring::Roaring>(*other._null_bitmap)) {}
+
+ // Move constructor
+ InvertedIndexResultBitmap(InvertedIndexResultBitmap&& other) noexcept
+ : _data_bitmap(std::move(other._data_bitmap)),
+ _null_bitmap(std::move(other._null_bitmap)) {}
+
+ // Copy assignment operator
+ InvertedIndexResultBitmap& operator=(const InvertedIndexResultBitmap& other) {
+ if (this != &other) { // Prevent self-assignment
+ _data_bitmap = std::make_shared<roaring::Roaring>(*other._data_bitmap);
+ _null_bitmap = std::make_shared<roaring::Roaring>(*other._null_bitmap);
+ }
+ return *this;
+ }
+
+ // Move assignment operator
+ InvertedIndexResultBitmap& operator=(InvertedIndexResultBitmap&& other) noexcept {
+ if (this != &other) { // Prevent self-assignment
+ _data_bitmap = std::move(other._data_bitmap);
+ _null_bitmap = std::move(other._null_bitmap);
+ }
+ return *this;
+ }
+
+ // Operator &=
+ InvertedIndexResultBitmap& operator&=(const InvertedIndexResultBitmap& other) {
+ if (_data_bitmap && _null_bitmap && other._data_bitmap && other._null_bitmap) {
+ auto new_null_bitmap = (*_data_bitmap & *other._null_bitmap) |
+ (*_null_bitmap & *other._data_bitmap) |
+ (*_null_bitmap & *other._null_bitmap);
+ *_data_bitmap &= *other._data_bitmap;
+ *_null_bitmap = std::move(new_null_bitmap);
+ }
+ return *this;
+ }
+
+ // Operator |=
+ InvertedIndexResultBitmap& operator|=(const InvertedIndexResultBitmap& other) {
+ if (_data_bitmap && _null_bitmap && other._data_bitmap && other._null_bitmap) {
+ auto new_null_bitmap = (*_null_bitmap | *other._null_bitmap) - *_data_bitmap;
+ *_data_bitmap |= *other._data_bitmap;
+ *_null_bitmap = std::move(new_null_bitmap);
+ }
+ return *this;
+ }
+
+ // NOT operation
+ const InvertedIndexResultBitmap& op_not(const roaring::Roaring* universe) const {
+ if (_data_bitmap && _null_bitmap) {
+ *_data_bitmap = *universe - *_data_bitmap - *_null_bitmap;
+ // The _null_bitmap remains unchanged.
+ }
+ return *this;
+ }
+
+ // Operator -=
+ InvertedIndexResultBitmap& operator-=(const InvertedIndexResultBitmap& other) {
+ if (_data_bitmap && _null_bitmap && other._data_bitmap && other._null_bitmap) {
+ *_data_bitmap -= *other._data_bitmap;
+ *_data_bitmap -= *other._null_bitmap;
+ *_null_bitmap -= *other._null_bitmap;
+ }
+ return *this;
+ }
+
+ void mask_out_null() {
+ if (_data_bitmap && _null_bitmap) {
+ *_data_bitmap -= *_null_bitmap;
+ }
+ }
+
+ const std::shared_ptr<roaring::Roaring>& get_data_bitmap() const { return _data_bitmap; }
+
+ const std::shared_ptr<roaring::Roaring>& get_null_bitmap() const { return _null_bitmap; }
+
+ // Check if both bitmaps are empty
+ bool is_empty() const { return (_data_bitmap == nullptr && _null_bitmap == nullptr); }
+};
+
class InvertedIndexReader : public std::enable_shared_from_this<InvertedIndexReader> {
public:
explicit InvertedIndexReader(
@@ -136,7 +234,7 @@ public:
virtual Status handle_searcher_cache(InvertedIndexCacheHandle* inverted_index_cache_handle,
OlapReaderStatistics* stats);
-
+ std::string get_index_file_path();
static Status create_index_searcher(lucene::store::Directory* dir, IndexSearcherPtr* searcher,
MemTracker* mem_tracker,
InvertedIndexReaderType reader_type);
diff --git a/be/src/olap/rowset/segment_v2/segment_iterator.cpp b/be/src/olap/rowset/segment_v2/segment_iterator.cpp
index e4398abdb3d..af473bb5ecd 100644
--- a/be/src/olap/rowset/segment_v2/segment_iterator.cpp
+++ b/be/src/olap/rowset/segment_v2/segment_iterator.cpp
@@ -298,26 +298,18 @@ Status SegmentIterator::_init_impl(const StorageReadOptions& opts) {
_block_rowids.resize(_opts.block_row_max);
// compound predicates
- _col_preds_except_leafnode_of_andnode.clear();
+ //TODO: need to check can_apply_predicate_safely in expr
+ /*_col_preds_except_leafnode_of_andnode.clear();
for (const auto& predicate : opts.column_predicates_except_leafnode_of_andnode) {
if (!_segment->can_apply_predicate_safely(predicate->column_id(), predicate, *_schema,
_opts.io_ctx.reader_type)) {
continue;
}
_col_preds_except_leafnode_of_andnode.push_back(predicate);
- }
+ }*/
_remaining_conjunct_roots = opts.remaining_conjunct_roots;
- _common_expr_ctxs_push_down = opts.common_expr_ctxs_push_down;
- _enable_common_expr_pushdown = !_common_expr_ctxs_push_down.empty();
- _column_predicate_info.reset(new ColumnPredicateInfo());
-
- for (auto& expr : _remaining_conjunct_roots) {
- _calculate_pred_in_remaining_conjunct_root(expr);
- }
- _calculate_func_in_remaining_conjunct_root();
- _column_predicate_info.reset(new ColumnPredicateInfo());
if (_schema->rowid_col_idx() > 0) {
_record_rowids = true;
}
@@ -367,8 +359,9 @@ Status SegmentIterator::_init_impl(const StorageReadOptions& opts) {
}
}
+ RETURN_IF_ERROR(_construct_compound_expr_context());
+ _enable_common_expr_pushdown = !_common_expr_ctxs_push_down.empty();
_initialize_predicate_results();
-
return Status::OK();
}
@@ -376,33 +369,10 @@ void SegmentIterator::_initialize_predicate_results() {
// Initialize from _col_predicates
for (auto* pred : _col_predicates) {
int cid = pred->column_id();
- std::string pred_sign = _gen_predicate_result_sign(pred);
- _column_predicate_inverted_index_status[cid][pred_sign] = false;
- }
-
- // Initialize from _col_preds_except_leafnode_of_andnode
- for (auto* pred : _col_preds_except_leafnode_of_andnode) {
- int cid = pred->column_id();
- std::string pred_sign = _gen_predicate_result_sign(pred);
- _column_predicate_inverted_index_status[cid][pred_sign] = false;
- }
-
- // Initialize from _column_pred_in_remaining_vconjunct
- for (auto& preds_in_remaining_vconjuct : _column_pred_in_remaining_vconjunct) {
- for (auto& pred_info : preds_in_remaining_vconjuct.second) {
- int cid = _schema->column_id(pred_info.column_id);
- std::string pred_sign = _gen_predicate_result_sign(&pred_info);
- _column_predicate_inverted_index_status[cid][pred_sign] = false;
- }
+ _column_predicate_inverted_index_status[cid][pred] = false;
}
- // Initialize from _func_name_to_result_sign
- for (auto& iter : _func_name_to_result_sign) {
- for (auto& pred_sign : iter.second) {
- auto column_id = _opts.tablet_schema->field_index(iter.first);
- _column_predicate_inverted_index_status[column_id][pred_sign] = false;
- }
- }
+ _calculate_expr_in_remaining_conjunct_root();
}
Status SegmentIterator::init_iterators() {
@@ -421,12 +391,6 @@ Status SegmentIterator::_lazy_init() {
_segment->_tablet_schema->cluster_key_idxes().empty()) {
RETURN_IF_ERROR(_get_row_ranges_by_keys());
}
- // extract for index apply col id which is slot_ref
- if (_enable_common_expr_pushdown && !_remaining_conjunct_roots.empty()) {
- for (auto expr : _remaining_conjunct_roots) {
- RETURN_IF_ERROR(_extract_common_expr_columns_for_index(expr));
- }
- }
RETURN_IF_ERROR(_get_row_ranges_by_column_conditions());
RETURN_IF_ERROR(_vec_init_lazy_materialization());
// Remove rows that have been marked deleted
@@ -549,47 +513,34 @@ Status SegmentIterator::_get_row_ranges_by_column_conditions() {
return Status::OK();
}
- if (config::enable_index_apply_preds_except_leafnode_of_andnode) {
- size_t input_rows = _row_bitmap.cardinality();
- RETURN_IF_ERROR(_apply_index_except_leafnode_of_andnode());
- if (_can_filter_by_preds_except_leafnode_of_andnode()) {
- for (auto it = _remaining_conjunct_roots.begin();
- it != _remaining_conjunct_roots.end();) {
- _pred_except_leafnode_of_andnode_evaluate_result.clear();
- auto res = _execute_predicates_except_leafnode_of_andnode(*it);
- VLOG_DEBUG << "_execute_predicates_except_leafnode_of_andnode expr: "
- << (*it)->debug_string() << " res: " << res;
- if (res.ok() && _pred_except_leafnode_of_andnode_evaluate_result.size() == 1) {
- _row_bitmap &= _pred_except_leafnode_of_andnode_evaluate_result[0];
- // Delete expr after it obtains the final result.
- {
- std::erase_if(_common_expr_ctxs_push_down,
- [&it](const auto& iter) { return iter->root() == *it; });
- VLOG_DEBUG << "_remaining_conjunct_roots erase expr: "
- << (*it)->debug_string();
- it = _remaining_conjunct_roots.erase(it);
- }
- } else {
- ++it;
- }
- }
- _col_preds_except_leafnode_of_andnode.clear();
- compound_func_exprs.clear();
- // 1. if all conditions in the compound hit the inverted index and there are no other expr to handle.
- // 2. then there is no need to generate index_result_column.
- if (_enable_common_expr_pushdown && _remaining_conjunct_roots.empty()) {
- for (auto& iter : _rowid_result_for_index) {
- iter.second.first = false;
+ RETURN_IF_ERROR(_apply_bitmap_index());
+ RETURN_IF_ERROR(_apply_inverted_index());
+ RETURN_IF_ERROR(_apply_index_expr());
+ size_t input_rows = _row_bitmap.cardinality();
+ for (auto it = _common_expr_ctxs_push_down.begin(); it != _common_expr_ctxs_push_down.end();) {
+ if ((*it)->all_expr_inverted_index_evaluated()) {
+ const auto* result =
+ (*it)->get_inverted_index_context()->get_inverted_index_result_for_expr(
+ (*it)->root().get());
+ if (result != nullptr) {
+ _row_bitmap &= *result->get_data_bitmap();
+ auto root = (*it)->root();
+ auto iter_find = std::find(_remaining_conjunct_roots.begin(),
+ _remaining_conjunct_roots.end(), root);
+ if (iter_find != _remaining_conjunct_roots.end()) {
+ _remaining_conjunct_roots.erase(iter_find);
}
+ it = _common_expr_ctxs_push_down.erase(it);
}
+ } else {
+ ++it;
}
- _opts.stats->rows_inverted_index_filtered += (input_rows - _row_bitmap.cardinality());
}
- RETURN_IF_ERROR(_apply_bitmap_index());
- RETURN_IF_ERROR(_apply_inverted_index());
+ _opts.stats->rows_inverted_index_filtered += (input_rows - _row_bitmap.cardinality());
for (auto cid : _schema->column_ids()) {
- bool result_true = _check_all_predicates_passed_inverted_index_for_column(cid);
+ bool result_true = _check_all_conditions_passed_inverted_index_for_column(cid);
+
if (result_true) {
_need_read_data_indices[cid] = false;
}
@@ -794,133 +745,6 @@ Status SegmentIterator::_extract_common_expr_columns(const vectorized::VExprSPtr
return Status::OK();
}
-Status SegmentIterator::_extract_common_expr_columns_for_index(const vectorized::VExprSPtr& expr) {
- auto& children = expr->children();
- for (int i = 0; i < children.size(); ++i) {
- RETURN_IF_ERROR(_extract_common_expr_columns_for_index(children[i]));
- }
-
- auto node_type = expr->node_type();
- if (node_type == TExprNodeType::SLOT_REF) {
- auto slot_expr = std::dynamic_pointer_cast<doris::vectorized::VSlotRef>(expr);
- _common_expr_columns_for_index.insert(slot_expr->column_id());
- }
- return Status::OK();
-}
-
-Status SegmentIterator::_execute_predicates_except_leafnode_of_andnode(
- const vectorized::VExprSPtr& expr) {
- if (expr == nullptr) {
- return Status::OK();
- }
-
- auto& children = expr->children();
- for (int i = 0; i < children.size(); ++i) {
- RETURN_IF_ERROR(_execute_predicates_except_leafnode_of_andnode(children[i]));
- }
-
- auto node_type = expr->node_type();
- if (node_type == TExprNodeType::SLOT_REF) {
- auto slot_expr = std::dynamic_pointer_cast<doris::vectorized::VSlotRef>(expr);
- _column_predicate_info->column_name = expr->expr_name();
- _column_predicate_info->column_id = slot_expr->column_id();
- } else if (_is_literal_node(node_type)) {
- auto v_literal_expr = std::dynamic_pointer_cast<doris::vectorized::VLiteral>(expr);
- _column_predicate_info->query_values.insert(v_literal_expr->value());
- } else if (node_type == TExprNodeType::BINARY_PRED || node_type == TExprNodeType::MATCH_PRED ||
- node_type == TExprNodeType::IN_PRED || node_type == TExprNodeType::FUNCTION_CALL) {
- std::string result_sign;
- if (node_type == TExprNodeType::FUNCTION_CALL) {
- result_sign =
- BeConsts::BLOCK_TEMP_COLUMN_PREFIX + std::to_string(expr->index_unique_id());
- } else {
- if (node_type == TExprNodeType::MATCH_PRED) {
- _column_predicate_info->query_op = "match";
- } else if (node_type == TExprNodeType::IN_PRED) {
- if (expr->op() == TExprOpcode::type::FILTER_IN) {
- _column_predicate_info->query_op = "in";
- } else {
- _column_predicate_info->query_op = "not_in";
- }
- } else {
- _column_predicate_info->query_op = expr->fn().name.function_name;
- }
- result_sign = _gen_predicate_result_sign(_column_predicate_info.get());
- }
-
- // get child condition result in compound conditions
- _column_predicate_info.reset(new ColumnPredicateInfo());
- VLOG_DEBUG << "result_sign " << result_sign;
- if (_rowid_result_for_index.count(result_sign) > 0 &&
- _rowid_result_for_index[result_sign].first) {
- auto apply_result = _rowid_result_for_index[result_sign].second;
- _pred_except_leafnode_of_andnode_evaluate_result.push_back(apply_result);
- }
- } else if (node_type == TExprNodeType::COMPOUND_PRED) {
- auto function_name = expr->fn().name.function_name;
- // execute logic function
- RETURN_IF_ERROR(_execute_compound_fn(function_name));
- }
-
- return Status::OK();
-}
-
-Status SegmentIterator::_execute_compound_fn(const std::string& function_name) {
- auto size = _pred_except_leafnode_of_andnode_evaluate_result.size();
- if (function_name == "and") {
- if (size < 2) {
- return Status::InvalidArgument("_execute_compound_fn {} arg num {} < 2", function_name,
- size);
- }
- _pred_except_leafnode_of_andnode_evaluate_result.at(size - 2) &=
- _pred_except_leafnode_of_andnode_evaluate_result.at(size - 1);
- _pred_except_leafnode_of_andnode_evaluate_result.pop_back();
- } else if (function_name == "or") {
- if (size < 2) {
- return Status::InvalidArgument("_execute_compound_fn {} arg num {} < 2", function_name,
- size);
- }
- _pred_except_leafnode_of_andnode_evaluate_result.at(size - 2) |=
- _pred_except_leafnode_of_andnode_evaluate_result.at(size - 1);
- _pred_except_leafnode_of_andnode_evaluate_result.pop_back();
- } else if (function_name == "not") {
- if (size < 1) {
- return Status::InvalidArgument("_execute_compound_fn {} arg num {} < 1", function_name,
- size);
- }
- roaring::Roaring tmp = _row_bitmap;
- tmp -= _pred_except_leafnode_of_andnode_evaluate_result.at(size - 1);
- _pred_except_leafnode_of_andnode_evaluate_result.at(size - 1) = tmp;
- }
- return Status::OK();
-}
-
-bool SegmentIterator::_can_filter_by_preds_except_leafnode_of_andnode() {
- // no compound predicates push down, so no need to filter
- if (_col_preds_except_leafnode_of_andnode.empty() && compound_func_exprs.empty()) {
- return false;
- }
- for (auto pred : _col_preds_except_leafnode_of_andnode) {
- if (_not_apply_index_pred.count(pred->column_id()) ||
- (!_check_apply_by_inverted_index(pred, true))) {
- return false;
- }
- // all predicates are evaluated by index, then true, else false
- std::string pred_result_sign = _gen_predicate_result_sign(pred);
- if (_rowid_result_for_index.count(pred_result_sign) == 0) {
- return false;
- }
- }
- for (const auto& expr : compound_func_exprs) {
- std::string pred_result_sign =
- BeConsts::BLOCK_TEMP_COLUMN_PREFIX + std::to_string(expr->index_unique_id());
- if (!_rowid_result_for_index.contains(pred_result_sign)) {
- return false;
- }
- }
- return true;
-}
-
bool SegmentIterator::_check_apply_by_inverted_index(ColumnId col_id) {
if (_opts.runtime_state && !_opts.runtime_state->query_options().enable_inverted_index_query) {
return false;
@@ -989,74 +813,20 @@ bool SegmentIterator::_check_apply_by_inverted_index(ColumnPredicate* pred, bool
return true;
}
-Status SegmentIterator::_apply_inverted_index_except_leafnode_of_andnode(
- ColumnPredicate* pred, roaring::Roaring* output_result) {
- RETURN_IF_ERROR(pred->evaluate(_storage_name_and_type[pred->column_id()],
- _inverted_index_iterators[pred->column_id()].get(), num_rows(),
- output_result));
- return Status::OK();
-}
-
-Status SegmentIterator::_apply_index_except_leafnode_of_andnode() {
- for (auto* pred : _col_preds_except_leafnode_of_andnode) {
- auto column_id = pred->column_id();
- auto pred_type = pred->type();
- bool is_support = pred_type == PredicateType::EQ || pred_type == PredicateType::NE ||
- pred_type == PredicateType::LT || pred_type == PredicateType::LE ||
- pred_type == PredicateType::GT || pred_type == PredicateType::GE ||
- pred_type == PredicateType::MATCH ||
- pred_type == PredicateType::IN_LIST ||
- pred_type == PredicateType::NOT_IN_LIST;
- if (!is_support) {
- continue;
- }
-
- bool can_apply_by_inverted_index = _check_apply_by_inverted_index(pred, true);
- roaring::Roaring bitmap = _row_bitmap;
- Status res = Status::OK();
- if (can_apply_by_inverted_index) {
- res = _apply_inverted_index_except_leafnode_of_andnode(pred, &bitmap);
- } else {
- continue;
- }
-
- bool need_remaining_after_evaluate = _column_has_fulltext_index(column_id) &&
- PredicateTypeTraits::is_equal_or_list(pred_type);
- if (!res.ok()) {
- if (_downgrade_without_index(res, need_remaining_after_evaluate)) {
- // downgrade without index query
- _not_apply_index_pred.insert(column_id);
+Status SegmentIterator::_apply_index_expr() {
+ for (const auto& expr_ctx : _common_expr_ctxs_push_down) {
+ if (Status st = expr_ctx->evaluate_inverted_index(num_rows()); !st.ok()) {
+ if (_downgrade_without_index(st) || st.code() == ErrorCode::NOT_IMPLEMENTED_ERROR) {
continue;
- }
- LOG(WARNING) << "failed to evaluate index"
- << ", column predicate type: " << pred->pred_type_string(pred->type())
- << ", error msg: " << res.to_string();
- return res;
- }
-
- std::string pred_result_sign = _gen_predicate_result_sign(pred);
- _rowid_result_for_index.emplace(pred_result_sign, std::make_pair(true, std::move(bitmap)));
- if (!pred->predicate_params()->marked_by_runtime_filter) {
- _column_predicate_inverted_index_status[column_id][pred_result_sign] = true;
- }
- }
-
- for (const auto& expr : compound_func_exprs) {
- roaring::Roaring bitmap = _row_bitmap;
- auto result = std::make_shared<roaring::Roaring>();
- RETURN_IF_ERROR(execute_func_expr(expr, result));
- bitmap &= *result;
- std::string result_sign =
- BeConsts::BLOCK_TEMP_COLUMN_PREFIX + std::to_string(expr->index_unique_id());
- _rowid_result_for_index.emplace(result_sign, std::make_pair(true, std::move(bitmap)));
- for (const auto& child_expr : expr->children()) {
- if (child_expr->node_type() == TExprNodeType::type::SLOT_REF) {
- auto column_id = _opts.tablet_schema->field_index(child_expr->expr_name());
- _column_predicate_inverted_index_status[column_id][result_sign] = true;
+ } else {
+ // other code is not to be handled, we should just break
+ LOG(WARNING) << "failed to evaluate inverted index for expr_ctx: "
+ << expr_ctx->root()->debug_string()
+ << ", error msg: " << st.to_string();
+ return st;
}
}
}
-
return Status::OK();
}
@@ -1087,47 +857,6 @@ bool SegmentIterator::_downgrade_without_index(Status res, bool need_remaining)
return false;
}
-std::string SegmentIterator::_gen_predicate_result_sign(ColumnPredicate* predicate) {
- std::string pred_result_sign;
-
- auto column_desc = _schema->column(predicate->column_id());
- auto pred_type = predicate->type();
- auto predicate_params = predicate->predicate_params();
-
- std::string col_name = column_desc->name();
-
- if (column_desc->path() != nullptr && !_storage_name_and_type.empty()) {
- const static std::string pattern = "(CAST {}(Nullable(Variant)) TO {})";
- // indicate a subcolumn access for variant, using the expression pattern as pred result sign name
- col_name = fmt::format(pattern, col_name,
- _storage_name_and_type[predicate->column_id()].second->get_name());
- }
-
- pred_result_sign = BeConsts::BLOCK_TEMP_COLUMN_PREFIX + col_name + "_" +
- predicate->pred_type_string(pred_type) + "_" +
- join(predicate_params->values, ",");
- VLOG_DEBUG << "_gen_predicate_result_sign: " << pred_result_sign;
- return pred_result_sign;
-}
-
-std::string SegmentIterator::_gen_predicate_result_sign(ColumnPredicateInfo* predicate_info) {
- auto column_desc = _schema->column(_schema->column_id(predicate_info->column_id));
- std::string col_name = predicate_info->column_name;
- if (column_desc->path() != nullptr && !_storage_name_and_type.empty()) {
- const static std::string pattern = "(CAST {}(Nullable(Variant)) TO {})";
- // indicate a subcolumn access for variant, using the expression pattern as pred result sign name
- col_name = fmt::format(pattern, col_name,
- _storage_name_and_type[_schema->column_id(predicate_info->column_id)]
- .second->get_name());
- }
- std::string pred_result_sign;
- pred_result_sign = BeConsts::BLOCK_TEMP_COLUMN_PREFIX + col_name + "_" +
- predicate_info->query_op + "_" +
- boost::join(predicate_info->query_values, ",");
- VLOG_DEBUG << "_gen_predicate_result_sign: " << pred_result_sign;
- return pred_result_sign;
-}
-
bool SegmentIterator::_column_has_fulltext_index(int32_t cid) {
bool has_fulltext_index = _inverted_index_iterators[cid] != nullptr &&
_inverted_index_iterators[cid]->get_inverted_index_reader_type() ==
@@ -1140,10 +869,6 @@ inline bool SegmentIterator::_inverted_index_not_support_pred_type(const Predica
return type == PredicateType::BF || type == PredicateType::BITMAP_FILTER;
}
-#define all_predicates_are_range_predicate(predicate_set) \
- std::all_of(predicate_set.begin(), predicate_set.end(), \
- [](const ColumnPredicate* p) { return PredicateTypeTraits::is_range(p->type()); })
-
Status SegmentIterator::_apply_inverted_index_on_column_predicate(
ColumnPredicate* pred, std::vector<ColumnPredicate*>& remaining_predicates,
bool* continue_apply) {
@@ -1166,12 +891,6 @@ Status SegmentIterator::_apply_inverted_index_on_column_predicate(
return res;
}
- auto pred_type = pred->type();
- if (pred_type == PredicateType::MATCH || pred_type == PredicateType::IN_LIST) {
- std::string pred_result_sign = _gen_predicate_result_sign(pred);
- _rowid_result_for_index.emplace(pred_result_sign, std::make_pair(false, _row_bitmap));
- }
-
if (_row_bitmap.isEmpty()) {
// all rows have been pruned, no need to process further predicates
*continue_apply = false;
@@ -1182,52 +901,7 @@ Status SegmentIterator::_apply_inverted_index_on_column_predicate(
return Status::OK();
}
if (!pred->predicate_params()->marked_by_runtime_filter) {
- std::string pred_result_sign = _gen_predicate_result_sign(pred);
- _column_predicate_inverted_index_status[pred->column_id()][pred_result_sign] = true;
- }
- }
- return Status::OK();
-}
-
-Status SegmentIterator::_apply_inverted_index_on_block_column_predicate(
- ColumnId column_id, MutilColumnBlockPredicate* pred,
- std::set<const ColumnPredicate*>& no_need_to_pass_column_predicate_set,
- bool* continue_apply) {
- bool handle_by_fulltext = _column_has_fulltext_index(column_id);
- std::set<const ColumnPredicate*> predicate_set {};
-
- pred->get_all_column_predicate(predicate_set);
-
- //four requirements here.
- //1. Column has inverted index
- //2. There are multiple predicates for this column.
- //3. All the predicates are range predicate.
- //4. if it's under fulltext parser type, we need to skip inverted index evaluate.
- if (_inverted_index_iterators[column_id] != nullptr && predicate_set.size() > 1 &&
- all_predicates_are_range_predicate(predicate_set) && !handle_by_fulltext) {
- roaring::Roaring output_result = _row_bitmap;
-
- std::string column_name = _schema->column(column_id)->name();
-
- auto res = pred->evaluate(column_name, _inverted_index_iterators[column_id].get(),
- num_rows(), &_row_bitmap);
-
- if (res.ok()) {
- no_need_to_pass_column_predicate_set.insert(predicate_set.begin(), predicate_set.end());
- if (_row_bitmap.isEmpty()) {
- // all rows have been pruned, no need to process further predicates
- *continue_apply = false;
- }
- return res;
- } else {
- //TODO:mock until AndBlockColumnPredicate evaluate is ok.
- if (res.code() == ErrorCode::INVERTED_INDEX_NOT_IMPLEMENTED) {
- return Status::OK();
- }
- LOG(WARNING) << "failed to evaluate index"
- << ", column predicate type: range predicate"
- << ", error msg: " << res;
- return res;
+ _column_predicate_inverted_index_status[pred->column_id()][pred] = true;
}
}
return Status::OK();
@@ -1326,110 +1000,49 @@ Status SegmentIterator::_apply_inverted_index() {
}
}
- // delete from _common_expr_ctxs_push_down if a MATCH predicate will be removed from _col_predicates
- // since it's not necessary to eval it anymore to avoid index miss, which is added in _normalize_predicate
- for (auto pred : _col_predicates) {
- auto* match_pred = dynamic_cast<MatchPredicate*>(pred);
- if (!match_pred ||
- !_is_match_predicate_and_not_remaining(match_pred, remaining_predicates)) {
- continue;
- }
-
- for (auto it = _common_expr_ctxs_push_down.begin();
- it != _common_expr_ctxs_push_down.end();) {
- if (_is_target_expr_match_predicate((*it)->root(), match_pred, _schema.get())) {
- _delete_expr_from_conjunct_roots((*it)->root(), _remaining_conjunct_roots);
- it = _common_expr_ctxs_push_down.erase(it);
- VLOG_DEBUG << "delete expr from _remaining_conjunct_roots "
- << (*it)->root()->debug_string();
- } else {
- ++it;
- }
- }
- }
-
- for (const auto& expr : no_compound_func_exprs) {
- auto result = std::make_shared<roaring::Roaring>();
- RETURN_IF_ERROR(execute_func_expr(expr, result));
- _row_bitmap &= *result;
- for (auto it = _remaining_conjunct_roots.begin(); it != _remaining_conjunct_roots.end();) {
- if (*it == expr) {
- std::erase_if(_common_expr_ctxs_push_down,
- [&it](const auto& iter) { return iter->root() == *it; });
- it = _remaining_conjunct_roots.erase(it);
- } else {
- ++it;
- }
- }
- std::string result_sign =
- BeConsts::BLOCK_TEMP_COLUMN_PREFIX + std::to_string(expr->index_unique_id());
- for (const auto& child_expr : expr->children()) {
- if (child_expr->node_type() == TExprNodeType::type::SLOT_REF) {
- auto column_id = _opts.tablet_schema->field_index(child_expr->expr_name());
- _column_predicate_inverted_index_status[column_id][result_sign] = true;
- }
- }
- }
-
- // add a switch for inverted index filter
- if (_opts.runtime_state &&
- _opts.runtime_state->enable_common_expr_pushdown_for_inverted_index()) {
- // support expr to evaluate inverted index
- std::unordered_map<ColumnId,
- std::pair<vectorized::IndexFieldNameAndTypePair, InvertedIndexIterator*>>
- iter_map;
- for (auto col_id : _common_expr_columns_for_index) {
- auto tablet_col_id = _schema->column_id(col_id);
- if (_check_apply_by_inverted_index(tablet_col_id)) {
- iter_map[col_id] = std::make_pair(_storage_name_and_type[tablet_col_id],
- _inverted_index_iterators[tablet_col_id].get());
- }
- }
- for (auto expr_ctx : _common_expr_ctxs_push_down) {
- // _inverted_index_iterators has all column ids which has inverted index
- // _common_expr_columns has all column ids from _common_expr_ctxs_push_down
- // if current bitmap is already empty just return
- if (!(expr_ctx->root()->node_type() == TExprNodeType::FUNCTION_CALL &&
- expr_ctx->root()->fn().name.function_name ==
- vectorized::ArrayContainsAction::name)) {
- // now we only support ArrayContains function to evaluate inverted index
- continue;
- }
- if (_row_bitmap.isEmpty()) {
- break;
- }
- std::shared_ptr<roaring::Roaring> result_bitmap = std::make_shared<roaring::Roaring>();
- if (Status st =
- expr_ctx->eval_inverted_index(iter_map, num_rows(), result_bitmap.get());
- !st.ok()) {
- if (_downgrade_without_index(st) || st.code() == ErrorCode::NOT_IMPLEMENTED_ERROR) {
- continue;
- } else {
- // other code is not to be handled, we should just break
- LOG(WARNING) << "failed to evaluate inverted index for expr_ctx: "
- << expr_ctx->root()->debug_string()
- << ", error msg: " << st.to_string();
- return st;
- }
- } else {
- // every single result of expr_ctx must be `and` collection relationship
- _row_bitmap &= *result_bitmap;
- }
- }
- }
-
_col_predicates = std::move(remaining_predicates);
_opts.stats->rows_inverted_index_filtered += (input_rows - _row_bitmap.cardinality());
return Status::OK();
}
-bool SegmentIterator::_check_all_predicates_passed_inverted_index_for_column(ColumnId cid,
+/**
+ * @brief Checks if all conditions related to a specific column have passed in both
+ * `_column_predicate_inverted_index_status` and `_common_expr_inverted_index_status`.
+ *
+ * This function first checks the conditions in `_column_predicate_inverted_index_status`
+ * for the given `ColumnId`. If all conditions pass, it sets `default_return` to `true`.
+ * It then checks the conditions in `_common_expr_inverted_index_status` for the same column.
+ *
+ * The function returns `true` if all conditions in both maps pass. If any condition fails
+ * in either map, the function immediately returns `false`. If the column does not exist
+ * in one of the maps, the function returns `default_return`.
+ *
+ * @param cid The ColumnId of the column to check.
+ * @param default_return The default value to return if the column is not found in the status maps.
+ * @return true if all conditions in both status maps pass, or if the column is not found
+ * and `default_return` is true.
+ * @return false if any condition in either status map fails, or if the column is not found
+ * and `default_return` is false.
+ */
+bool SegmentIterator::_check_all_conditions_passed_inverted_index_for_column(ColumnId cid,
bool default_return) {
- auto it = _column_predicate_inverted_index_status.find(cid);
- if (it != _column_predicate_inverted_index_status.end()) {
- const auto& pred_map = it->second;
- return std::all_of(pred_map.begin(), pred_map.end(),
- [](const auto& pred_entry) { return pred_entry.second; });
+ auto pred_it = _column_predicate_inverted_index_status.find(cid);
+ if (pred_it != _column_predicate_inverted_index_status.end()) {
+ const auto& pred_map = pred_it->second;
+ bool pred_passed = std::all_of(pred_map.begin(), pred_map.end(),
+ [](const auto& pred_entry) { return pred_entry.second; });
+ if (!pred_passed) {
+ return false;
+ } else {
+ default_return = true;
+ }
+ }
+
+ auto expr_it = _common_expr_inverted_index_status.find(cid);
+ if (expr_it != _common_expr_inverted_index_status.end()) {
+ const auto& expr_map = expr_it->second;
+ return std::all_of(expr_map.begin(), expr_map.end(),
+ [](const auto& expr_entry) { return expr_entry.second; });
}
return default_return;
}
@@ -2103,15 +1716,16 @@ Status SegmentIterator::_read_columns_by_index(uint32_t nrows_read_limit, uint32
}
DBUG_EXECUTE_IF("segment_iterator._read_columns_by_index", {
+ auto col_name = _opts.tablet_schema->column(cid).name();
auto debug_col_name = DebugPoints::instance()->get_debug_param_or_default<std::string>(
"segment_iterator._read_columns_by_index", "column_name", "");
- if (debug_col_name.empty()) {
- return Status::Error<ErrorCode::INTERNAL_ERROR>("does not need to read data");
+ if (debug_col_name.empty() && col_name != "__DORIS_DELETE_SIGN__") {
+ return Status::Error<ErrorCode::INTERNAL_ERROR>("does not need to read data, {}",
+ col_name);
}
- auto col_name = _opts.tablet_schema->column(cid).name();
if (debug_col_name.find(col_name) != std::string::npos) {
return Status::Error<ErrorCode::INTERNAL_ERROR>("does not need to read data, {}",
- debug_col_name);
+ col_name);
}
})
@@ -2524,15 +2138,6 @@ Status SegmentIterator::_next_batch_internal(vectorized::Block* block) {
return Status::EndOfFile("no more data in segment");
}
- DBUG_EXECUTE_IF("segment_iterator._rowid_result_for_index", {
- for (auto& iter : _rowid_result_for_index) {
- if (iter.second.first) {
- return Status::Error<ErrorCode::INTERNAL_ERROR>(
- "_rowid_result_for_index exists true");
- }
- }
- })
-
if (!_is_need_vec_eval && !_is_need_short_eval && !_is_need_expr_eval) {
if (_non_predicate_columns.empty()) {
return Status::InternalError("_non_predicate_columns is empty");
@@ -2540,9 +2145,6 @@ Status SegmentIterator::_next_batch_internal(vectorized::Block* block) {
RETURN_IF_ERROR(_convert_to_expected_type(_first_read_column_ids));
RETURN_IF_ERROR(_convert_to_expected_type(_non_predicate_columns));
_output_non_pred_columns(block);
- if (!_enable_common_expr_pushdown || !_remaining_conjunct_roots.empty()) {
- _output_index_result_column(nullptr, 0, block);
- }
} else {
uint16_t selected_size = _current_batch_rows_read;
_sel_rowid_idx.resize(selected_size);
@@ -2599,13 +2201,15 @@ Status SegmentIterator::_next_batch_internal(vectorized::Block* block) {
auto col_const = vectorized::ColumnConst::create(std::move(res_column),
selected_size);
block->replace_by_position(0, std::move(col_const));
- _output_index_result_column(_sel_rowid_idx.data(), selected_size, block);
+ _output_index_result_column_for_expr(_sel_rowid_idx.data(), selected_size,
+ block);
block->shrink_char_type_column_suffix_zero(_char_type_idx_no_0);
RETURN_IF_ERROR(
_execute_common_expr(_sel_rowid_idx.data(), selected_size, block));
block->replace_by_position(0, std::move(col0));
} else {
- _output_index_result_column(_sel_rowid_idx.data(), selected_size, block);
+ _output_index_result_column_for_expr(_sel_rowid_idx.data(), selected_size,
+ block);
block->shrink_char_type_column_suffix_zero(_char_type_idx);
RETURN_IF_ERROR(
_execute_common_expr(_sel_rowid_idx.data(), selected_size, block));
@@ -2638,12 +2242,12 @@ Status SegmentIterator::_next_batch_internal(vectorized::Block* block) {
auto col_const =
vectorized::ColumnConst::create(std::move(res_column), selected_size);
block->replace_by_position(0, std::move(col_const));
- _output_index_result_column(_sel_rowid_idx.data(), selected_size, block);
+ _output_index_result_column_for_expr(_sel_rowid_idx.data(), selected_size, block);
block->shrink_char_type_column_suffix_zero(_char_type_idx_no_0);
RETURN_IF_ERROR(_execute_common_expr(_sel_rowid_idx.data(), selected_size, block));
block->replace_by_position(0, std::move(col0));
} else {
- _output_index_result_column(_sel_rowid_idx.data(), selected_size, block);
+ _output_index_result_column_for_expr(_sel_rowid_idx.data(), selected_size, block);
block->shrink_char_type_column_suffix_zero(_char_type_idx);
RETURN_IF_ERROR(_execute_common_expr(_sel_rowid_idx.data(), selected_size, block));
}
@@ -2674,10 +2278,6 @@ Status SegmentIterator::_next_batch_internal(vectorized::Block* block) {
RETURN_IF_ERROR(_convert_to_expected_type(_non_predicate_columns));
// step5: output columns
_output_non_pred_columns(block);
-
- if (!_is_need_expr_eval) {
- _output_index_result_column(_sel_rowid_idx.data(), selected_size, block);
- }
}
// shrink char_type suffix zero data
@@ -2754,53 +2354,42 @@ uint16_t SegmentIterator::_evaluate_common_expr_filter(uint16_t* sel_rowid_idx,
}
}
-void SegmentIterator::_output_index_result_column(uint16_t* sel_rowid_idx, uint16_t select_size,
- vectorized::Block* block) {
+void SegmentIterator::_output_index_result_column_for_expr(uint16_t* sel_rowid_idx,
+ uint16_t select_size,
+ vectorized::Block* block) {
SCOPED_RAW_TIMER(&_opts.stats->output_index_result_column_timer);
if (block->rows() == 0) {
return;
}
-
- for (auto& iter : _rowid_result_for_index) {
- _columns_to_filter.push_back(block->columns());
- block->insert({vectorized::ColumnUInt8::create(),
- std::make_shared<vectorized::DataTypeUInt8>(), iter.first});
- if (!iter.second.first) {
- // predicate not in compound query
- block->get_by_name(iter.first).column =
- vectorized::DataTypeUInt8().create_column_const(block->rows(), (uint8_t)1);
- continue;
- }
- _build_index_result_column(sel_rowid_idx, select_size, block, iter.first,
- iter.second.second);
- }
-}
-
-void SegmentIterator::_build_index_result_column(const uint16_t* sel_rowid_idx,
- uint16_t select_size, vectorized::Block* block,
- const std::string& pred_result_sign,
- const roaring::Roaring& index_result) {
- auto index_result_column = vectorized::ColumnUInt8::create();
- vectorized::ColumnUInt8::Container& vec_match_pred = index_result_column->get_data();
- vec_match_pred.resize(block->rows());
- size_t idx_in_selected = 0;
- roaring::BulkContext bulk_context;
-
- for (uint32_t i = 0; i < _current_batch_rows_read; i++) {
- auto rowid = _block_rowids[i];
- if (sel_rowid_idx == nullptr ||
- (idx_in_selected < select_size && i == sel_rowid_idx[idx_in_selected])) {
- if (index_result.containsBulk(bulk_context, rowid)) {
- vec_match_pred[idx_in_selected] = true;
- } else {
- vec_match_pred[idx_in_selected] = false;
+ for (auto& expr_ctx : _common_expr_ctxs_push_down) {
+ for (auto& inverted_index_result_bitmap_for_expr :
+ expr_ctx->get_inverted_index_context()->get_inverted_index_result_bitmap()) {
+ const auto* expr = inverted_index_result_bitmap_for_expr.first;
+ const auto& index_result_bitmap =
+ inverted_index_result_bitmap_for_expr.second.get_data_bitmap();
+ auto index_result_column = vectorized::ColumnUInt8::create();
+ vectorized::ColumnUInt8::Container& vec_match_pred = index_result_column->get_data();
+ vec_match_pred.resize(block->rows());
+ size_t idx_in_selected = 0;
+ roaring::BulkContext bulk_context;
+
+ for (uint32_t i = 0; i < _current_batch_rows_read; i++) {
+ auto rowid = _block_rowids[i];
+ if (sel_rowid_idx == nullptr ||
+ (idx_in_selected < select_size && i == sel_rowid_idx[idx_in_selected])) {
+ if (index_result_bitmap->containsBulk(bulk_context, rowid)) {
+ vec_match_pred[idx_in_selected] = true;
+ } else {
+ vec_match_pred[idx_in_selected] = false;
+ }
+ idx_in_selected++;
+ }
}
- idx_in_selected++;
+ DCHECK(block->rows() == vec_match_pred.size());
+ expr_ctx->get_inverted_index_context()->set_inverted_index_result_column_for_expr(
+ expr, std::move(index_result_column));
}
}
- DCHECK(block->rows() == vec_match_pred.size());
- auto index_result_position = block->get_position_by_name(pred_result_sign);
- block->replace_by_position(index_result_position, std::move(index_result_column));
}
void SegmentIterator::_convert_dict_code_for_predicate_if_necessary() {
@@ -2851,125 +2440,45 @@ Status SegmentIterator::current_block_row_locations(std::vector<RowLocation>* bl
return Status::OK();
}
-void SegmentIterator::_calculate_pred_in_remaining_conjunct_root(
- const vectorized::VExprSPtr& expr) {
- if (expr == nullptr) {
- return;
- }
-
- if (expr->fn().name.function_name == "multi_match") {
- return;
- }
-
- auto& children = expr->children();
- for (int i = 0; i < children.size(); ++i) {
- _calculate_pred_in_remaining_conjunct_root(children[i]);
- }
-
- auto node_type = expr->node_type();
- if (node_type == TExprNodeType::SLOT_REF) {
- auto slot_expr = std::dynamic_pointer_cast<doris::vectorized::VSlotRef>(expr);
- if (_column_predicate_info->column_name.empty()) {
- _column_predicate_info->column_name = expr->expr_name();
- _column_predicate_info->column_id = slot_expr->column_id();
- } else {
- // If column name already exists, create a new ColumnPredicateInfo
- // if expr is columnA > columnB, then column name will exist, in this situation, we need to add it to _column_pred_in_remaining_vconjunct
- auto new_column_pred_info = std::make_shared<ColumnPredicateInfo>();
- new_column_pred_info->column_name = expr->expr_name();
- new_column_pred_info->column_id = slot_expr->column_id();
- _column_pred_in_remaining_vconjunct[new_column_pred_info->column_name].push_back(
- *new_column_pred_info);
- }
- } else if (_is_literal_node(node_type)) {
- auto v_literal_expr = static_cast<const doris::vectorized::VLiteral*>(expr.get());
- _column_predicate_info->query_values.insert(v_literal_expr->value());
- } else if (node_type == TExprNodeType::NULL_LITERAL) {
- if (!_column_predicate_info->column_name.empty()) {
- auto v_literal_expr = static_cast<const doris::vectorized::VLiteral*>(expr.get());
- _column_predicate_info->query_values.insert(v_literal_expr->value());
- }
- } else {
- if (node_type == TExprNodeType::MATCH_PRED) {
- _column_predicate_info->query_op = "match";
- } else if (node_type == TExprNodeType::IN_PRED) {
- if (expr->op() == TExprOpcode::type::FILTER_IN) {
- _column_predicate_info->query_op = "in";
- } else {
- _column_predicate_info->query_op = "not_in";
- }
- } else if (node_type != TExprNodeType::COMPOUND_PRED) {
- _column_predicate_info->query_op = expr->fn().name.function_name;
- }
-
- if (!_column_predicate_info->is_empty()) {
- _column_pred_in_remaining_vconjunct[_column_predicate_info->column_name].push_back(
- *_column_predicate_info);
- _column_predicate_info.reset(new ColumnPredicateInfo());
- }
+Status SegmentIterator::_construct_compound_expr_context() {
+ auto inverted_index_context = std::make_shared<vectorized::InvertedIndexContext>(
+ _schema->column_ids(), _inverted_index_iterators, _storage_name_and_type,
+ _common_expr_inverted_index_status);
+ for (const auto& expr_ctx : _opts.common_expr_ctxs_push_down) {
+ vectorized::VExprContextSPtr context;
+ RETURN_IF_ERROR(expr_ctx->clone(_opts.runtime_state, context));
+ context->set_inverted_index_context(inverted_index_context);
+ _common_expr_ctxs_push_down.emplace_back(context);
}
+ return Status::OK();
}
-void SegmentIterator::_calculate_func_in_remaining_conjunct_root() {
- auto hash = [](const vectorized::VExprSPtr& expr) -> std::size_t {
- return std::hash<std::string>()(expr->expr_name());
- };
- auto equal = [](const vectorized::VExprSPtr& lhs, const vectorized::VExprSPtr& rhs) -> bool {
- return lhs->equals(*rhs);
- };
-
- uint32_t next_id = 0;
- std::unordered_map<vectorized::VExprSPtr, uint32_t, decltype(hash), decltype(equal)> unique_map(
- 0, hash, equal);
-
- auto gen_func_unique_id = [&unique_map, &next_id](const vectorized::VExprSPtr& expr) {
- auto it = unique_map.find(expr);
- if (it != unique_map.end()) {
- return it->second;
- } else {
- unique_map[expr] = ++next_id;
- return next_id;
- }
- };
-
+void SegmentIterator::_calculate_expr_in_remaining_conjunct_root() {
for (const auto& root_expr_ctx : _common_expr_ctxs_push_down) {
const auto& root_expr = root_expr_ctx->root();
if (root_expr == nullptr) {
continue;
}
- std::stack<std::pair<vectorized::VExprSPtr, bool>> stack;
- stack.emplace(root_expr, false);
+ std::stack<vectorized::VExprSPtr> stack;
+ stack.emplace(root_expr);
while (!stack.empty()) {
- const auto& [expr, has_compound_pred] = stack.top();
+ const auto& expr = stack.top();
stack.pop();
- bool current_has_compound_pred =
- has_compound_pred || (expr->node_type() == TExprNodeType::COMPOUND_PRED);
-
- if (expr->fn().name.function_name == "multi_match") {
- expr->set_index_unique_id(gen_func_unique_id(expr));
- if (current_has_compound_pred) {
- compound_func_exprs.emplace_back(expr);
- } else {
- no_compound_func_exprs.emplace_back(expr);
- }
-
- for (int32_t i = expr->get_num_children() - 1; i >= 0; i--) {
- auto child_expr = expr->get_child(i);
- if (child_expr->node_type() == TExprNodeType::type::SLOT_REF) {
- std::string result_sign = BeConsts::BLOCK_TEMP_COLUMN_PREFIX +
- std::to_string(expr->index_unique_id());
- _func_name_to_result_sign[child_expr->expr_name()].push_back(result_sign);
- }
+ for (const auto& child : expr->children()) {
+ if (child->is_slot_ref()) {
+ auto* column_slot_ref = assert_cast<vectorized::VSlotRef*>(child.get());
+ _common_expr_inverted_index_status[_schema->column_id(
+ column_slot_ref->column_id())][expr.get()] = false;
}
}
const auto& children = expr->children();
for (int32_t i = children.size() - 1; i >= 0; --i) {
if (!children[i]->children().empty()) {
- stack.emplace(children[i], current_has_compound_pred);
+ stack.emplace(children[i]);
}
}
}
@@ -3000,7 +2509,7 @@ bool SegmentIterator::_no_need_read_key_data(ColumnId cid, vectorized::MutableCo
return false;
}
- if (!_check_all_predicates_passed_inverted_index_for_column(cid, true)) {
+ if (!_check_all_conditions_passed_inverted_index_for_column(cid)) {
return false;
}
@@ -3034,7 +2543,7 @@ bool SegmentIterator::_can_opt_topn_reads() {
if (cid == _opts.tablet_schema->delete_sign_idx()) {
return true;
}
- if (_check_all_predicates_passed_inverted_index_for_column(cid, true)) {
+ if (_check_all_conditions_passed_inverted_index_for_column(cid, true)) {
return true;
}
return false;
@@ -3049,22 +2558,5 @@ bool SegmentIterator::_can_opt_topn_reads() {
return all_true;
}
-Status SegmentIterator::execute_func_expr(const vectorized::VExprSPtr& expr,
- std::shared_ptr<roaring::Roaring>& result) {
- const auto& expr0 = expr->get_child(0);
- if (!expr0 || expr0->node_type() != TExprNodeType::SLOT_REF) {
- return Status::RuntimeError("cannot perform index filtering");
- }
-
- FuncExprParams params;
- auto slot_expr = std::static_pointer_cast<vectorized::VSlotRef>(expr0);
- params._column_id = _schema->column_id(slot_expr->column_id());
- params._unique_id = _schema->unique_id(slot_expr->column_id());
- params._column_name = _opts.tablet_schema->column(params._column_id).name();
- params._segment_iterator = this;
-
- return expr->eval_inverted_index(params, result);
-}
-
} // namespace segment_v2
} // namespace doris
diff --git a/be/src/olap/rowset/segment_v2/segment_iterator.h b/be/src/olap/rowset/segment_v2/segment_iterator.h
index 4e065874e5c..6ffd1666f60 100644
--- a/be/src/olap/rowset/segment_v2/segment_iterator.h
+++ b/be/src/olap/rowset/segment_v2/segment_iterator.h
@@ -200,20 +200,10 @@ private:
[[nodiscard]] Status _apply_inverted_index_on_column_predicate(
ColumnPredicate* pred, std::vector<ColumnPredicate*>& remaining_predicates,
bool* continue_apply);
- [[nodiscard]] Status _apply_inverted_index_on_block_column_predicate(
- ColumnId column_id, MutilColumnBlockPredicate* pred,
- std::set<const ColumnPredicate*>& no_need_to_pass_column_predicate_set,
- bool* continue_apply);
- [[nodiscard]] Status _apply_index_except_leafnode_of_andnode();
- [[nodiscard]] Status _apply_inverted_index_except_leafnode_of_andnode(
- ColumnPredicate* pred, roaring::Roaring* output_result);
+ [[nodiscard]] Status _apply_index_expr();
bool _column_has_fulltext_index(int32_t cid);
bool _downgrade_without_index(Status res, bool need_remaining = false);
inline bool _inverted_index_not_support_pred_type(const PredicateType& type);
- bool _can_filter_by_preds_except_leafnode_of_andnode();
- [[nodiscard]] Status _execute_predicates_except_leafnode_of_andnode(
- const vectorized::VExprSPtr& expr);
- [[nodiscard]] Status _execute_compound_fn(const std::string& function_name);
bool _is_literal_node(const TExprNodeType::type& node_type);
Status _vec_init_lazy_materialization();
@@ -298,7 +288,6 @@ private:
[[nodiscard]] Status _extract_common_expr_columns(const vectorized::VExprSPtr& expr);
// same with _extract_common_expr_columns, but only extract columns that can be used for index
- [[nodiscard]] Status _extract_common_expr_columns_for_index(const vectorized::VExprSPtr& expr);
[[nodiscard]] Status _execute_common_expr(uint16_t* sel_rowid_idx, uint16_t& selected_size,
vectorized::Block* block);
uint16_t _evaluate_common_expr_filter(uint16_t* sel_rowid_idx, uint16_t selected_size,
@@ -312,24 +301,14 @@ private:
bool _check_apply_by_inverted_index(ColumnId col_id);
bool _check_apply_by_inverted_index(ColumnPredicate* pred, bool pred_in_compound = false);
- std::string _gen_predicate_result_sign(ColumnPredicate* predicate);
- std::string _gen_predicate_result_sign(ColumnPredicateInfo* predicate_info);
-
- void _build_index_result_column(const uint16_t* sel_rowid_idx, uint16_t select_size,
- vectorized::Block* block, const std::string& pred_result_sign,
- const roaring::Roaring& index_result);
- void _output_index_result_column(uint16_t* sel_rowid_idx, uint16_t select_size,
- vectorized::Block* block);
+ void _output_index_result_column_for_expr(uint16_t* sel_rowid_idx, uint16_t select_size,
+ vectorized::Block* block);
bool _need_read_data(ColumnId cid);
bool _prune_column(ColumnId cid, vectorized::MutableColumnPtr& column, bool fill_defaults,
size_t num_of_defaults);
- // return true means one column's predicates all pushed down
- bool _check_column_pred_all_push_down(const std::string& column_name, bool in_compound = false,
- bool is_match = false);
- void _calculate_pred_in_remaining_conjunct_root(const vectorized::VExprSPtr& expr);
- void _calculate_func_in_remaining_conjunct_root();
+ Status _construct_compound_expr_context();
// todo(wb) remove this method after RowCursor is removed
void _convert_rowcursor_to_short_key(const RowCursor& key, size_t num_keys) {
@@ -410,11 +389,10 @@ private:
bool _can_opt_topn_reads();
void _initialize_predicate_results();
- bool _check_all_predicates_passed_inverted_index_for_column(ColumnId cid,
+ bool _check_all_conditions_passed_inverted_index_for_column(ColumnId cid,
bool default_return = false);
- Status execute_func_expr(const vectorized::VExprSPtr& expr,
- std::shared_ptr<roaring::Roaring>& result);
+ void _calculate_expr_in_remaining_conjunct_root();
class BitmapRangeIterator;
class BackwardBitmapRangeIterator;
@@ -430,8 +408,6 @@ private:
std::vector<std::unique_ptr<InvertedIndexIterator>> _inverted_index_iterators;
// after init(), `_row_bitmap` contains all rowid to scan
roaring::Roaring _row_bitmap;
- // "column_name+operator+value-> <in_compound_query, rowid_result>
- std::unordered_map<std::string, std::pair<bool, roaring::Roaring>> _rowid_result_for_index;
// an iterator for `_row_bitmap` that can be used to extract row range to scan
std::unique_ptr<BitmapRangeIterator> _range_iter;
// the next rowid to read
@@ -443,7 +419,6 @@ private:
// columns to read after predicate evaluation and remaining expr execute
std::vector<ColumnId> _non_predicate_columns;
std::set<ColumnId> _common_expr_columns;
- std::set<ColumnId> _common_expr_columns_for_index;
// remember the rowids we've read for the current row block.
// could be a local variable of next_batch(), kept here to reuse vector memory
std::vector<rowid_t> _block_rowids;
@@ -481,19 +456,9 @@ private:
StorageReadOptions _opts;
// make a copy of `_opts.column_predicates` in order to make local changes
std::vector<ColumnPredicate*> _col_predicates;
- std::vector<ColumnPredicate*> _col_preds_except_leafnode_of_andnode;
-
- std::vector<vectorized::VExprSPtr> no_compound_func_exprs;
- std::vector<vectorized::VExprSPtr> compound_func_exprs;
-
vectorized::VExprContextSPtrs _common_expr_ctxs_push_down;
bool _enable_common_expr_pushdown = false;
std::vector<vectorized::VExprSPtr> _remaining_conjunct_roots;
- std::vector<roaring::Roaring> _pred_except_leafnode_of_andnode_evaluate_result;
- std::unique_ptr<ColumnPredicateInfo> _column_predicate_info;
- std::unordered_map<std::string, std::vector<ColumnPredicateInfo>>
- _column_pred_in_remaining_vconjunct;
- std::unordered_map<std::string, std::vector<std::string>> _func_name_to_result_sign;
std::set<ColumnId> _not_apply_index_pred;
// row schema of the key to seek
@@ -529,8 +494,11 @@ private:
std::vector<uint8_t> _ret_flags;
- std::unordered_map<int, std::unordered_map<std::string, bool>>
+ std::unordered_map<ColumnId, std::unordered_map<ColumnPredicate*, bool>>
_column_predicate_inverted_index_status;
+
+ std::unordered_map<ColumnId, std::unordered_map<const vectorized::VExpr*, bool>>
+ _common_expr_inverted_index_status;
};
} // namespace segment_v2
diff --git a/be/src/pipeline/exec/scan_operator.cpp b/be/src/pipeline/exec/scan_operator.cpp
index 5e1e04386e1..2c798ffcc51 100644
--- a/be/src/pipeline/exec/scan_operator.cpp
+++ b/be/src/pipeline/exec/scan_operator.cpp
@@ -302,9 +302,6 @@ Status ScanLocalState<Derived>::_normalize_predicate(
RETURN_IF_PUSH_DOWN(_normalize_noneq_binary_predicate(
cur_expr, context, slot, value_range, &pdt),
status);
- RETURN_IF_PUSH_DOWN(_normalize_match_predicate(cur_expr, context, slot,
- value_range, &pdt),
- status);
if (_is_key_column(slot->col_name())) {
RETURN_IF_PUSH_DOWN(
_normalize_bitmap_filter(cur_expr, context, slot, &pdt),
@@ -322,23 +319,6 @@ Status ScanLocalState<Derived>::_normalize_predicate(
*range);
RETURN_IF_ERROR(status);
}
-
- if (pdt == PushDownType::UNACCEPTABLE &&
- TExprNodeType::COMPOUND_PRED == cur_expr->node_type()) {
- _normalize_compound_predicate(cur_expr, context, &pdt, _is_runtime_filter_predicate,
- in_predicate_checker, eq_predicate_checker);
- output_expr = conjunct_expr_root; // remaining in conjunct tree
- return Status::OK();
- }
-
- if (pdt == PushDownType::ACCEPTABLE &&
- TExprNodeType::MATCH_PRED == cur_expr->node_type()) {
- // remaining it in the expr tree, in order to filter by function if the pushdown
- // match_predicate failed to apply inverted index in the storage layer
- output_expr = conjunct_expr_root; // remaining in conjunct tree
- return Status::OK();
- }
-
if (pdt == PushDownType::ACCEPTABLE && slotref != nullptr &&
slotref->type().is_variant_type()) {
// remaining it in the expr tree, in order to filter by function if the pushdown
diff --git a/be/src/vec/exprs/vcompound_pred.h b/be/src/vec/exprs/vcompound_pred.h
index 773ab04a48c..faed6788ba3 100644
--- a/be/src/vec/exprs/vcompound_pred.h
+++ b/be/src/vec/exprs/vcompound_pred.h
@@ -27,6 +27,7 @@
#include "vec/data_types/data_type_number.h"
#include "vec/exprs/vectorized_fn_call.h"
#include "vec/exprs/vexpr.h"
+#include "vec/exprs/vexpr_context.h"
namespace doris::vectorized {
@@ -53,76 +54,107 @@ public:
const std::string& expr_name() const override { return _expr_name; }
- // 1. when meet 'or' conjunct: a or b, if b can apply index, return all rows, so b should not be extracted
- // 2. when meet 'and' conjunct, function with column b can not apply inverted index
- // eg. a and hash(b)=1, if b can apply index, but hash(b)=1 is not for index, so b should not be extracted
- // but a and array_contains(b, 1), b can be applied inverted index, which b can be extracted
- Status eval_inverted_index(
- VExprContext* context,
- const std::unordered_map<ColumnId, std::pair<vectorized::IndexFieldNameAndTypePair,
- segment_v2::InvertedIndexIterator*>>&
- colid_to_inverted_index_iter,
- uint32_t num_rows, roaring::Roaring* bitmap) const override {
- std::shared_ptr<roaring::Roaring> res = std::make_shared<roaring::Roaring>();
- if (_op == TExprOpcode::COMPOUND_OR) {
- for (auto child : _children) {
- std::shared_ptr<roaring::Roaring> child_roaring =
- std::make_shared<roaring::Roaring>();
- Status st = child->eval_inverted_index(context, colid_to_inverted_index_iter,
- num_rows, child_roaring.get());
- if (!st.ok()) {
- bitmap->addRange(0, num_rows);
- return st;
+ Status evaluate_inverted_index(VExprContext* context, uint32_t segment_num_rows) override {
+ segment_v2::InvertedIndexResultBitmap res;
+ bool all_pass = true;
+
+ switch (_op) {
+ case TExprOpcode::COMPOUND_OR: {
+ for (const auto& child : _children) {
+ if (Status st = child->evaluate_inverted_index(context, segment_num_rows);
+ !st.ok()) {
+ LOG(ERROR) << "expr:" << child->expr_name()
+ << " evaluate_inverted_index error:" << st.to_string();
+ all_pass = false;
+ continue;
}
- if (child_roaring->cardinality() == 0) {
- // means inverted index filter do not reduce any rows
- // the left expr no need to be extracted by inverted index,
- // and cur roaring is all rows which means this inverted index is not useful,
- // do not need to calculate with res bitmap
- bitmap->addRange(0, num_rows);
- return Status::OK();
+ if (context->get_inverted_index_context()->has_inverted_index_result_for_expr(
+ child.get())) {
+ const auto* index_result =
+ context->get_inverted_index_context()
+ ->get_inverted_index_result_for_expr(child.get());
+ if (res.is_empty()) {
+ res = *index_result;
+ } else {
+ res |= *index_result;
+ }
+ if (res.get_data_bitmap()->cardinality() == segment_num_rows) {
+ break; // Early exit if result is full
+ }
+ } else {
+ all_pass = false;
}
- *res |= *child_roaring;
}
- *bitmap = *res;
- } else if (_op == TExprOpcode::COMPOUND_AND) {
- for (int i = 0; i < _children.size(); ++i) {
- std::shared_ptr<roaring::Roaring> child_roaring =
- std::make_shared<roaring::Roaring>();
- Status st = _children[0]->eval_inverted_index(context, colid_to_inverted_index_iter,
- num_rows, child_roaring.get());
- if (!st.ok()) {
+ break;
+ }
+ case TExprOpcode::COMPOUND_AND: {
+ for (const auto& child : _children) {
+ if (Status st = child->evaluate_inverted_index(context, segment_num_rows);
+ !st.ok()) {
+ LOG(ERROR) << "expr:" << child->expr_name()
+ << " evaluate_inverted_index error:" << st.to_string();
+ all_pass = false;
continue;
}
- if (i == 0) {
- *res = *child_roaring;
+ if (context->get_inverted_index_context()->has_inverted_index_result_for_expr(
+ child.get())) {
+ const auto* index_result =
+ context->get_inverted_index_context()
+ ->get_inverted_index_result_for_expr(child.get());
+ if (res.is_empty()) {
+ res = *index_result;
+ } else {
+ res &= *index_result;
+ }
+
+ if (res.get_data_bitmap()->isEmpty()) {
+ break; // Early exit if result is empty
+ }
} else {
- *res &= *child_roaring;
- }
- if (res->isEmpty()) {
- // the left expr no need to be extracted by inverted index, just return 0 rows
- // res bitmap will be zero
- return Status::OK();
+ all_pass = false;
}
}
- *bitmap = *res;
- } else if (_op == TExprOpcode::COMPOUND_NOT) {
- Status st = _children[0]->eval_inverted_index(context, colid_to_inverted_index_iter,
- num_rows, res.get());
+ break;
+ }
+ case TExprOpcode::COMPOUND_NOT: {
+ const auto& child = _children[0];
+ Status st = child->evaluate_inverted_index(context, segment_num_rows);
if (!st.ok()) {
+ LOG(ERROR) << "expr:" << child->expr_name()
+ << " evaluate_inverted_index error:" << st.to_string();
return st;
}
- std::shared_ptr<roaring::Roaring> all_rows = std::make_shared<roaring::Roaring>();
- all_rows->addRange(0, num_rows);
- *bitmap = *all_rows - *res;
- } else {
+
+ if (context->get_inverted_index_context()->has_inverted_index_result_for_expr(
+ child.get())) {
+ const auto* index_result =
+ context->get_inverted_index_context()->get_inverted_index_result_for_expr(
+ child.get());
+ roaring::Roaring full_result;
+ full_result.addRange(0, segment_num_rows);
+ res = index_result->op_not(&full_result);
+ } else {
+ all_pass = false;
+ }
+ break;
+ }
+ default:
return Status::NotSupported(
- "Compound operator must be AND or OR or Not can execute with inverted index.");
+ "Compound operator must be AND, OR, or NOT to execute with inverted index.");
+ }
+
+ if (all_pass && !res.is_empty()) {
+ // set fast_execute when expr evaluated by inverted index correctly
+ _can_fast_execute = true;
+ context->get_inverted_index_context()->set_inverted_index_result_for_expr(this, res);
}
return Status::OK();
}
Status execute(VExprContext* context, Block* block, int* result_column_id) override {
+ if (_can_fast_execute && fast_execute(context, block, result_column_id)) {
+ return Status::OK();
+ }
if (children().size() == 1 || !_all_child_is_compound_and_not_const()) {
return VectorizedFnCall::execute(context, block, result_column_id);
}
@@ -318,8 +350,8 @@ private:
}
std::pair<uint8*, uint8*> _get_raw_data_and_null_map(ColumnPtr column,
- bool nullable_column) const {
- if (nullable_column) {
+ bool has_nullable_column) const {
+ if (has_nullable_column) {
auto* nullable_column = assert_cast<ColumnNullable*>(column->assume_mutable().get());
auto* data_column =
assert_cast<ColumnUInt8*>(nullable_column->get_nested_column_ptr().get())
diff --git a/be/src/vec/exprs/vectorized_fn_call.cpp b/be/src/vec/exprs/vectorized_fn_call.cpp
index c8e56d423bc..3e58d8d7be0 100644
--- a/be/src/vec/exprs/vectorized_fn_call.cpp
+++ b/be/src/vec/exprs/vectorized_fn_call.cpp
@@ -22,7 +22,6 @@
#include <gen_cpp/Types_types.h>
#include <ostream>
-#include <string_view>
#include <utility>
#include "common/config.h"
@@ -30,11 +29,8 @@
#include "common/status.h"
#include "runtime/runtime_state.h"
#include "udf/udf.h"
-#include "vec/aggregate_functions/aggregate_function_simple_factory.h"
#include "vec/columns/column.h"
#include "vec/core/block.h"
-#include "vec/core/column_with_type_and_name.h"
-#include "vec/core/columns_with_type_and_name.h"
#include "vec/data_types/data_type.h"
#include "vec/data_types/data_type_agg_state.h"
#include "vec/exprs/vexpr_context.h"
@@ -119,7 +115,6 @@ Status VectorizedFnCall::prepare(RuntimeState* state, const RowDescriptor& desc,
}
VExpr::register_function_context(state, context);
_function_name = _fn.name.function_name;
- _can_fast_execute = can_fast_execute();
_prepare_finished = true;
return Status::OK();
}
@@ -143,38 +138,38 @@ void VectorizedFnCall::close(VExprContext* context, FunctionContext::FunctionSta
VExpr::close(context, scope);
}
-Status VectorizedFnCall::eval_inverted_index(
- VExprContext* context,
- const std::unordered_map<ColumnId, std::pair<vectorized::IndexFieldNameAndTypePair,
- segment_v2::InvertedIndexIterator*>>&
- colid_to_inverted_index_iter,
- uint32_t num_rows, roaring::Roaring* bitmap) const {
+Status VectorizedFnCall::evaluate_inverted_index(VExprContext* context, uint32_t segment_num_rows) {
DCHECK_GE(get_num_children(), 1);
- if (get_child(0)->is_slot_ref()) {
- auto* column_slot_ref = assert_cast<VSlotRef*>(get_child(0).get());
- if (auto iter = colid_to_inverted_index_iter.find(column_slot_ref->column_id());
- iter != colid_to_inverted_index_iter.end()) {
- const auto& pair = iter->second;
- return _function->eval_inverted_index(context->fn_context(_fn_context_index),
- pair.first, pair.second, num_rows, bitmap);
- } else {
- return Status::NotSupported("column id {} not found in colid_to_inverted_index_iter",
- column_slot_ref->column_id());
- }
- } else {
- return Status::NotSupported("we can only eval inverted index for slot ref expr, but got ",
- get_child(0)->expr_name());
- }
- return Status::OK();
+ return _evaluate_inverted_index(context, _function, segment_num_rows);
}
Status VectorizedFnCall::_do_execute(doris::vectorized::VExprContext* context,
doris::vectorized::Block* block, int* result_column_id,
std::vector<size_t>& args) {
- if (is_const_and_have_executed()) { // const have execute in open function
+ if (is_const_and_have_executed()) { // const have executed in open function
return get_result_from_const(block, _expr_name, result_column_id);
}
+ if (_can_fast_execute && fast_execute(context, block, result_column_id)) {
+ return Status::OK();
+ }
+ DBUG_EXECUTE_IF("VectorizedFnCall.must_in_slow_path", {
+ if (get_child(0)->is_slot_ref()) {
+ auto debug_col_name = DebugPoints::instance()->get_debug_param_or_default<std::string>(
+ "VectorizedFnCall.must_in_slow_path", "column_name", "");
+
+ std::vector<std::string> column_names;
+ boost::split(column_names, debug_col_name, boost::algorithm::is_any_of(","));
+ auto* column_slot_ref = assert_cast<VSlotRef*>(get_child(0).get());
+ std::string column_name = column_slot_ref->expr_name();
+ auto it = std::find(column_names.begin(), column_names.end(), column_name);
+ if (it == column_names.end()) {
+ return Status::Error<ErrorCode::INTERNAL_ERROR>(
+ "column {} should in slow path while VectorizedFnCall::execute.",
+ column_name);
+ }
+ }
+ })
DCHECK(_open_finished || _getting_const_col) << debug_string();
// TODO: not execute const expr again, but use the const column in function context
args.resize(_children.size());
@@ -189,14 +184,6 @@ Status VectorizedFnCall::_do_execute(doris::vectorized::VExprContext* context,
size_t num_columns_without_result = block->columns();
// prepare a column to save result
block->insert({nullptr, _data_type, _expr_name});
- if (_can_fast_execute) {
- auto can_fast_execute = fast_execute(*block, args, num_columns_without_result,
- block->rows(), _function->get_name());
- if (can_fast_execute) {
- *result_column_id = num_columns_without_result;
- return Status::OK();
- }
- }
RETURN_IF_ERROR(_function->execute(context->fn_context(_fn_context_index), *block, args,
num_columns_without_result, block->rows(), false));
*result_column_id = num_columns_without_result;
@@ -251,22 +238,6 @@ bool VectorizedFnCall::can_push_down_to_index() const {
return _function->can_push_down_to_index();
}
-bool VectorizedFnCall::can_fast_execute() const {
- auto function_name = _function->get_name();
- if (function_name == "eq" || function_name == "ne" || function_name == "lt" ||
- function_name == "gt" || function_name == "le" || function_name == "ge") {
- if (_children.size() == 2 && _children[0]->is_slot_ref() && _children[1]->is_literal()) {
- return true;
- }
- }
- return _function->can_push_down_to_index();
-}
-
-Status VectorizedFnCall::eval_inverted_index(segment_v2::FuncExprParams& params,
- std::shared_ptr<roaring::Roaring>& result) {
- return _function->eval_inverted_index(this, params, result);
-}
-
bool VectorizedFnCall::equals(const VExpr& other) {
const auto* other_ptr = dynamic_cast<const VectorizedFnCall*>(&other);
if (!other_ptr) {
diff --git a/be/src/vec/exprs/vectorized_fn_call.h b/be/src/vec/exprs/vectorized_fn_call.h
index e2708502369..bae996136dd 100644
--- a/be/src/vec/exprs/vectorized_fn_call.h
+++ b/be/src/vec/exprs/vectorized_fn_call.h
@@ -27,6 +27,7 @@
#include "udf/udf.h"
#include "vec/core/column_numbers.h"
#include "vec/exprs/vexpr.h"
+#include "vec/exprs/vliteral.h"
#include "vec/exprs/vslot_ref.h"
#include "vec/functions/function.h"
@@ -51,12 +52,7 @@ public:
Status execute_runtime_fitler(doris::vectorized::VExprContext* context,
doris::vectorized::Block* block, int* result_column_id,
std::vector<size_t>& args) override;
- Status eval_inverted_index(
- VExprContext* context,
- const std::unordered_map<ColumnId, std::pair<vectorized::IndexFieldNameAndTypePair,
- segment_v2::InvertedIndexIterator*>>&
- colid_to_inverted_index_iter,
- uint32_t num_rows, roaring::Roaring* bitmap) const override;
+ Status evaluate_inverted_index(VExprContext* context, uint32_t segment_num_rows) override;
Status prepare(RuntimeState* state, const RowDescriptor& desc, VExprContext* context) override;
Status open(RuntimeState* state, VExprContext* context,
FunctionContext::FunctionStateScope scope) override;
@@ -74,9 +70,6 @@ public:
static std::string debug_string(const std::vector<VectorizedFnCall*>& exprs);
bool can_push_down_to_index() const override;
- bool can_fast_execute() const override;
- Status eval_inverted_index(segment_v2::FuncExprParams& params,
- std::shared_ptr<roaring::Roaring>& result) override;
bool equals(const VExpr& other) override;
protected:
diff --git a/be/src/vec/exprs/vexpr.cpp b/be/src/vec/exprs/vexpr.cpp
index 8dc0fb49a1a..482a1a2e498 100644
--- a/be/src/vec/exprs/vexpr.cpp
+++ b/be/src/vec/exprs/vexpr.cpp
@@ -34,6 +34,7 @@
#include "runtime/define_primitive_type.h"
#include "vec/columns/column_vector.h"
#include "vec/columns/columns_number.h"
+#include "vec/data_types/data_type_array.h"
#include "vec/data_types/data_type_factory.hpp"
#include "vec/data_types/data_type_nullable.h"
#include "vec/data_types/data_type_number.h"
@@ -44,7 +45,6 @@
#include "vec/exprs/vcompound_pred.h"
#include "vec/exprs/vectorized_fn_call.h"
#include "vec/exprs/vexpr_context.h"
-#include "vec/exprs/vexpr_fwd.h"
#include "vec/exprs/vin_predicate.h"
#include "vec/exprs/vinfo_func.h"
#include "vec/exprs/vlambda_function_call_expr.h"
@@ -611,80 +611,134 @@ Status VExpr::get_result_from_const(vectorized::Block* block, const std::string&
return Status::OK();
}
-bool VExpr::fast_execute(Block& block, const ColumnNumbers& arguments, size_t result,
- size_t input_rows_count, const std::string& function_name) {
- if (!_enable_inverted_index_query) {
- return false;
+Status VExpr::_evaluate_inverted_index(VExprContext* context, const FunctionBasePtr& function,
+ uint32_t segment_num_rows) {
+ std::vector<segment_v2::InvertedIndexIterator*> iterators;
+ std::vector<vectorized::IndexFieldNameAndTypePair> data_type_with_names;
+ std::vector<int> column_ids;
+ vectorized::ColumnsWithTypeAndName arguments;
+ VExprSPtrs children_exprs;
+ for (auto child : children()) {
+ // if child is cast expr, we need to ensure target data type is the same with storage data type.
+ // or they are all string type
+ // and if data type is array, we need to get the nested data type to ensure that.
+ if (child->node_type() == TExprNodeType::CAST_EXPR) {
+ auto* cast_expr = assert_cast<VCastExpr*>(child.get());
+ DCHECK_EQ(cast_expr->children().size(), 1);
+ if (cast_expr->get_child(0)->is_slot_ref()) {
+ auto* column_slot_ref = assert_cast<VSlotRef*>(cast_expr->get_child(0).get());
+ auto column_id = column_slot_ref->column_id();
+ const auto* storage_name_type =
+ context->get_inverted_index_context()
+ ->get_storage_name_and_type_by_column_id(column_id);
+ auto storage_type = remove_nullable(storage_name_type->second);
+ auto target_type = cast_expr->get_target_type();
+ auto origin_primitive_type = storage_type->get_type_as_type_descriptor().type;
+ auto target_primitive_type = target_type->get_type_as_type_descriptor().type;
+ if (is_complex_type(storage_type)) {
+ if (is_array(storage_type) && is_array(target_type)) {
+ auto nested_storage_type =
+ (assert_cast<const DataTypeArray*>(storage_type.get()))
+ ->get_nested_type();
+ origin_primitive_type =
+ nested_storage_type->get_type_as_type_descriptor().type;
+ auto nested_target_type =
+ (assert_cast<const DataTypeArray*>(target_type.get()))
+ ->get_nested_type();
+ target_primitive_type =
+ nested_target_type->get_type_as_type_descriptor().type;
+ } else {
+ continue;
+ }
+ }
+ if (origin_primitive_type != TYPE_VARIANT &&
+ (origin_primitive_type == target_primitive_type ||
+ (is_string_type(target_primitive_type) &&
+ is_string_type(origin_primitive_type)))) {
+ children_exprs.emplace_back(expr_without_cast(child));
+ }
+ }
+ } else {
+ children_exprs.emplace_back(child);
+ }
}
- std::string result_column_name = gen_predicate_result_sign(block, arguments, function_name);
- if (!block.has(result_column_name)) {
- DBUG_EXECUTE_IF("segment_iterator.fast_execute", {
- auto debug_col_name = DebugPoints::instance()->get_debug_param_or_default<std::string>(
- "segment_iterator._read_columns_by_index", "column_name", "");
-
- std::vector<std::string> column_names;
- boost::split(column_names, debug_col_name, boost::algorithm::is_any_of(","));
-
- std::string column_name = block.get_by_position(arguments[0]).name;
- auto it = std::find(column_names.begin(), column_names.end(), column_name);
- if (it == column_names.end()) {
- return Status::Error<ErrorCode::INTERNAL_ERROR>("fast_execute failed: {}",
- result_column_name);
+ for (auto child : children_exprs) {
+ if (child->is_slot_ref()) {
+ auto* column_slot_ref = assert_cast<VSlotRef*>(child.get());
+ auto column_id = column_slot_ref->column_id();
+ auto* iter =
+ context->get_inverted_index_context()->get_inverted_index_iterator_by_column_id(
+ column_id);
+ //column does not have inverted index
+ if (iter == nullptr) {
+ continue;
}
- })
- return false;
+ const auto* storage_name_type =
+ context->get_inverted_index_context()->get_storage_name_and_type_by_column_id(
+ column_id);
+ if (storage_name_type == nullptr) {
+ auto err_msg = fmt::format(
+ "storage_name_type cannot be found for column {} while in {} "
+ "evaluate_inverted_index",
+ column_id, expr_name());
+ LOG(ERROR) << err_msg;
+ return Status::InternalError(err_msg);
+ }
+ iterators.emplace_back(iter);
+ data_type_with_names.emplace_back(*storage_name_type);
+ column_ids.emplace_back(column_id);
+ } else if (child->is_literal()) {
+ auto* column_literal = assert_cast<VLiteral*>(child.get());
+ arguments.emplace_back(column_literal->get_column_ptr(),
+ column_literal->get_data_type(), column_literal->expr_name());
+ }
}
-
- auto result_column =
- block.get_by_name(result_column_name).column->convert_to_full_column_if_const();
- auto& result_info = block.get_by_position(result);
- if (result_info.type->is_nullable()) {
- block.replace_by_position(result,
- ColumnNullable::create(std::move(result_column),
- ColumnUInt8::create(input_rows_count, 0)));
- } else {
- block.replace_by_position(result, std::move(result_column));
+ auto result_bitmap = segment_v2::InvertedIndexResultBitmap();
+ if (iterators.empty()) {
+ return Status::OK();
}
-
- return true;
+ // If arguments are empty, it means the left value in the expression is not a literal.
+ if (arguments.empty()) {
+ return Status::OK();
+ }
+ auto res = function->evaluate_inverted_index(arguments, data_type_with_names, iterators,
+ segment_num_rows, result_bitmap);
+ if (!res.ok()) {
+ return res;
+ }
+ if (!result_bitmap.is_empty()) {
+ context->get_inverted_index_context()->set_inverted_index_result_for_expr(this,
+ result_bitmap);
+ for (auto column_id : column_ids) {
+ context->get_inverted_index_context()->set_true_for_inverted_index_status(this,
+ column_id);
+ }
+ // set fast_execute when expr evaluated by inverted index correctly
+ _can_fast_execute = true;
+ }
+ return Status::OK();
}
-std::string VExpr::gen_predicate_result_sign(Block& block, const ColumnNumbers& arguments,
- const std::string& function_name) const {
- std::string pred_result_sign;
- if (this->fn().name.function_name == "multi_match") {
- pred_result_sign =
- BeConsts::BLOCK_TEMP_COLUMN_PREFIX + std::to_string(this->index_unique_id());
- } else {
- std::string column_name = block.get_by_position(arguments[0]).name;
- pred_result_sign +=
- BeConsts::BLOCK_TEMP_COLUMN_PREFIX + column_name + "_" + function_name + "_";
- if (function_name == "in" || function_name == "not_in") {
- if (arguments.size() - 1 > _in_list_value_count_threshold) {
- return pred_result_sign;
- }
- // Generating 'result_sign' from 'inlist' requires sorting the values.
- std::set<std::string> values;
- for (size_t i = 1; i < arguments.size(); i++) {
- const auto& entry = block.get_by_position(arguments[i]);
- if (!is_column_const(*entry.column)) {
- return pred_result_sign;
- }
- values.insert(entry.type->to_string(*entry.column, 0));
- }
- pred_result_sign += boost::join(values, ",");
- } else if (function_name == "collection_in" || function_name == "collection_not_in") {
- return pred_result_sign;
+bool VExpr::fast_execute(doris::vectorized::VExprContext* context, doris::vectorized::Block* block,
+ int* result_column_id) {
+ if (context->get_inverted_index_context() &&
+ context->get_inverted_index_context()->get_inverted_index_result_column().contains(this)) {
+ size_t num_columns_without_result = block->columns();
+ // prepare a column to save result
+ auto result_column =
+ context->get_inverted_index_context()->get_inverted_index_result_column()[this];
+ if (_data_type->is_nullable()) {
+ block->insert(
+ {ColumnNullable::create(result_column, ColumnUInt8::create(block->rows(), 0)),
+ _data_type, expr_name()});
} else {
- const auto& entry = block.get_by_position(arguments[1]);
- if (!is_column_const(*entry.column)) {
- return pred_result_sign;
- }
- pred_result_sign += entry.type->to_string(*entry.column, 0);
+ block->insert({result_column, _data_type, expr_name()});
}
+ *result_column_id = num_columns_without_result;
+ return true;
}
- return pred_result_sign;
+ return false;
}
bool VExpr::equals(const VExpr& other) {
diff --git a/be/src/vec/exprs/vexpr.h b/be/src/vec/exprs/vexpr.h
index 4720068a3aa..90048511c90 100644
--- a/be/src/vec/exprs/vexpr.h
+++ b/be/src/vec/exprs/vexpr.h
@@ -118,16 +118,14 @@ public:
virtual Status execute(VExprContext* context, Block* block, int* result_column_id) = 0;
- // execute current expr with inverted index to filter block. Given a roaringbitmap of match rows
- virtual Status eval_inverted_index(
- VExprContext* context,
- const std::unordered_map<ColumnId, std::pair<vectorized::IndexFieldNameAndTypePair,
- segment_v2::InvertedIndexIterator*>>&
- colid_to_inverted_index_iter,
- uint32_t num_rows, roaring::Roaring* bitmap) const {
+ // execute current expr with inverted index to filter block. Given a roaring bitmap of match rows
+ virtual Status evaluate_inverted_index(VExprContext* context, uint32_t segment_num_rows) {
return Status::NotSupported("Not supported execute_with_inverted_index");
}
+ Status _evaluate_inverted_index(VExprContext* context, const FunctionBasePtr& function,
+ uint32_t segment_num_rows);
+
// Only the 4th parameter is used in the runtime filter. In and MinMax need overwrite the
// interface
virtual Status execute_runtime_fitler(VExprContext* context, Block* block,
@@ -246,18 +244,10 @@ public:
}
// fast_execute can direct copy expr filter result which build by apply index in segment_iterator
- bool fast_execute(Block& block, const ColumnNumbers& arguments, size_t result,
- size_t input_rows_count, const std::string& function_name);
-
- std::string gen_predicate_result_sign(Block& block, const ColumnNumbers& arguments,
- const std::string& function_name) const;
+ bool fast_execute(doris::vectorized::VExprContext* context, doris::vectorized::Block* block,
+ int* result_column_id);
virtual bool can_push_down_to_index() const { return false; }
- virtual bool can_fast_execute() const { return false; }
- virtual Status eval_inverted_index(segment_v2::FuncExprParams& params,
- std::shared_ptr<roaring::Roaring>& result) {
- return Status::NotSupported("Not supported execute_with_inverted_index");
- }
virtual bool equals(const VExpr& other);
void set_index_unique_id(uint32_t index_unique_id) { _index_unique_id = index_unique_id; }
uint32_t index_unique_id() const { return _index_unique_id; }
diff --git a/be/src/vec/exprs/vexpr_context.cpp b/be/src/vec/exprs/vexpr_context.cpp
index a0ee4917976..bcfd7cda102 100644
--- a/be/src/vec/exprs/vexpr_context.cpp
+++ b/be/src/vec/exprs/vexpr_context.cpp
@@ -121,12 +121,14 @@ int VExprContext::register_function_context(RuntimeState* state, const TypeDescr
return _fn_contexts.size() - 1;
}
-Status VExprContext::eval_inverted_index(
- const std::unordered_map<ColumnId, std::pair<vectorized::IndexFieldNameAndTypePair,
- segment_v2::InvertedIndexIterator*>>&
- colid_to_inverted_index_iter,
- uint32_t num_rows, roaring::Roaring* bitmap) {
- return _root->eval_inverted_index(this, colid_to_inverted_index_iter, num_rows, bitmap);
+Status VExprContext::evaluate_inverted_index(uint32_t segment_num_rows) {
+ Status st;
+ RETURN_IF_CATCH_EXCEPTION({ st = _root->evaluate_inverted_index(this, segment_num_rows); });
+ return st;
+}
+
+bool VExprContext::all_expr_inverted_index_evaluated() {
+ return _inverted_index_context->has_inverted_index_result_for_expr(_root.get());
}
Status VExprContext::filter_block(VExprContext* vexpr_ctx, Block* block, int column_to_keep) {
diff --git a/be/src/vec/exprs/vexpr_context.h b/be/src/vec/exprs/vexpr_context.h
index d53fcfb2f47..d022cf6169e 100644
--- a/be/src/vec/exprs/vexpr_context.h
+++ b/be/src/vec/exprs/vexpr_context.h
@@ -38,6 +38,114 @@ class RuntimeState;
namespace doris::vectorized {
+class InvertedIndexContext {
+public:
+ InvertedIndexContext(
+ const std::vector<ColumnId>& col_ids,
+ const std::vector<std::unique_ptr<segment_v2::InvertedIndexIterator>>&
+ inverted_index_iterators,
+ const std::vector<vectorized::IndexFieldNameAndTypePair>& storage_name_and_type_vec,
+ std::unordered_map<ColumnId, std::unordered_map<const vectorized::VExpr*, bool>>&
+ common_expr_inverted_index_status)
+ : _col_ids(col_ids),
+ _inverted_index_iterators(inverted_index_iterators),
+ _storage_name_and_type(storage_name_and_type_vec),
+ _expr_inverted_index_status(common_expr_inverted_index_status) {}
+
+ segment_v2::InvertedIndexIterator* get_inverted_index_iterator_by_column_id(
+ int column_index) const {
+ if (column_index < 0 || column_index >= _col_ids.size()) {
+ return nullptr;
+ }
+ const auto& column_id = _col_ids[column_index];
+ if (column_id >= _inverted_index_iterators.size()) {
+ return nullptr;
+ }
+ if (!_inverted_index_iterators[column_id]) {
+ return nullptr;
+ }
+ return _inverted_index_iterators[column_id].get();
+ }
+
+ const vectorized::IndexFieldNameAndTypePair* get_storage_name_and_type_by_column_id(
+ int column_index) const {
+ if (column_index < 0 || column_index >= _col_ids.size()) {
+ return nullptr;
+ }
+ const auto& column_id = _col_ids[column_index];
+ if (column_id >= _storage_name_and_type.size()) {
+ return nullptr;
+ }
+ return &_storage_name_and_type[column_id];
+ }
+
+ bool has_inverted_index_result_for_expr(const vectorized::VExpr* expr) const {
+ return _inverted_index_result_bitmap.contains(expr);
+ }
+
+ void set_inverted_index_result_for_expr(const vectorized::VExpr* expr,
+ segment_v2::InvertedIndexResultBitmap bitmap) {
+ _inverted_index_result_bitmap[expr] = std::move(bitmap);
+ }
+
+ std::unordered_map<const vectorized::VExpr*, segment_v2::InvertedIndexResultBitmap>&
+ get_inverted_index_result_bitmap() {
+ return _inverted_index_result_bitmap;
+ }
+
+ std::unordered_map<const vectorized::VExpr*, ColumnPtr>& get_inverted_index_result_column() {
+ return _inverted_index_result_column;
+ }
+
+ const segment_v2::InvertedIndexResultBitmap* get_inverted_index_result_for_expr(
+ const vectorized::VExpr* expr) {
+ auto iter = _inverted_index_result_bitmap.find(expr);
+ if (iter == _inverted_index_result_bitmap.end()) {
+ return nullptr;
+ }
+ return &iter->second;
+ }
+
+ void set_inverted_index_result_column_for_expr(const vectorized::VExpr* expr,
+ ColumnPtr column) {
+ _inverted_index_result_column[expr] = std::move(column);
+ }
+
+ void set_true_for_inverted_index_status(const vectorized::VExpr* expr, int column_index) {
+ if (column_index < 0 || column_index >= _col_ids.size()) {
+ return;
+ }
+ const auto& column_id = _col_ids[column_index];
+ if (_expr_inverted_index_status.contains(column_id)) {
+ if (_expr_inverted_index_status[column_id].contains(expr)) {
+ _expr_inverted_index_status[column_id][expr] = true;
+ }
+ }
+ }
+
+private:
+ // A reference to a vector of column IDs for the current expression's output columns.
+ const std::vector<ColumnId>& _col_ids;
+
+ // A reference to a vector of unique pointers to inverted index iterators.
+ const std::vector<std::unique_ptr<segment_v2::InvertedIndexIterator>>&
+ _inverted_index_iterators;
+
+ // A reference to a vector of storage name and type pairs related to schema.
+ const std::vector<vectorized::IndexFieldNameAndTypePair>& _storage_name_and_type;
+
+ // A map of expressions to their corresponding inverted index result bitmaps.
+ std::unordered_map<const vectorized::VExpr*, segment_v2::InvertedIndexResultBitmap>
+ _inverted_index_result_bitmap;
+
+ // A map of expressions to their corresponding result columns.
+ std::unordered_map<const vectorized::VExpr*, ColumnPtr> _inverted_index_result_column;
+
+ // A reference to a map of common expressions to their inverted index evaluation status.
+ std::unordered_map<ColumnId, std::unordered_map<const vectorized::VExpr*, bool>>&
+ _expr_inverted_index_status;
+};
+
class VExprContext {
ENABLE_FACTORY_CREATOR(VExprContext);
@@ -51,6 +159,13 @@ public:
VExprSPtr root() { return _root; }
void set_root(const VExprSPtr& expr) { _root = expr; }
+ void set_inverted_index_context(std::shared_ptr<InvertedIndexContext> inverted_index_context) {
+ _inverted_index_context = std::move(inverted_index_context);
+ }
+
+ std::shared_ptr<InvertedIndexContext> get_inverted_index_context() const {
+ return _inverted_index_context;
+ }
/// Creates a FunctionContext, and returns the index that's passed to fn_context() to
/// retrieve the created context. Exprs that need a FunctionContext should call this in
@@ -73,17 +188,10 @@ public:
// execute expr with inverted index which column a, b has inverted indexes
// but some situation although column b has indexes, but apply index is not useful, we should
// skip this expr, just do not apply index anymore.
- /**
- * @param colid_to_inverted_index_iter contains all column id to inverted index iterator mapping from segmentIterator
- * @param num_rows number of rows in one segment.
- * @param bitmap roaring bitmap to store the result. 0 is present filed by index.
- * @return status not ok means execute failed.
- */
- [[nodiscard]] Status eval_inverted_index(
- const std::unordered_map<ColumnId, std::pair<vectorized::IndexFieldNameAndTypePair,
- segment_v2::InvertedIndexIterator*>>&
- colid_to_inverted_index_iter,
- uint32_t num_rows, roaring::Roaring* bitmap);
+
+ [[nodiscard]] Status evaluate_inverted_index(uint32_t segment_num_rows);
+
+ bool all_expr_inverted_index_evaluated();
[[nodiscard]] static Status filter_block(VExprContext* vexpr_ctx, Block* block,
int column_to_keep);
@@ -191,5 +299,7 @@ private:
// This flag only works on VSlotRef.
// Force to materialize even if the slot need_materialize is false, we just ignore need_materialize flag
bool _force_materialize_slot = false;
+
+ std::shared_ptr<InvertedIndexContext> _inverted_index_context;
};
} // namespace doris::vectorized
diff --git a/be/src/vec/exprs/vin_predicate.cpp b/be/src/vec/exprs/vin_predicate.cpp
index 4d518f9f923..361f55f038c 100644
--- a/be/src/vec/exprs/vin_predicate.cpp
+++ b/be/src/vec/exprs/vin_predicate.cpp
@@ -34,6 +34,8 @@
#include "vec/core/column_with_type_and_name.h"
#include "vec/core/columns_with_type_and_name.h"
#include "vec/exprs/vexpr_context.h"
+#include "vec/exprs/vliteral.h"
+#include "vec/exprs/vslot_ref.h"
#include "vec/functions/simple_function_factory.h"
namespace doris {
@@ -79,16 +81,14 @@ Status VInPredicate::prepare(RuntimeState* state, const RowDescriptor& desc,
VExpr::register_function_context(state, context);
_prepare_finished = true;
- _can_fast_execute = can_fast_execute();
- _in_list_value_count_threshold = state->query_options().in_list_value_count_threshold;
return Status::OK();
}
Status VInPredicate::open(RuntimeState* state, VExprContext* context,
FunctionContext::FunctionStateScope scope) {
DCHECK(_prepare_finished);
- for (int i = 0; i < _children.size(); ++i) {
- RETURN_IF_ERROR(_children[i]->open(state, context, scope));
+ for (auto& child : _children) {
+ RETURN_IF_ERROR(child->open(state, context, scope));
}
RETURN_IF_ERROR(VExpr::init_function_context(context, scope, _function));
if (scope == FunctionContext::FRAGMENT_LOCAL) {
@@ -103,10 +103,18 @@ void VInPredicate::close(VExprContext* context, FunctionContext::FunctionStateSc
VExpr::close(context, scope);
}
+Status VInPredicate::evaluate_inverted_index(VExprContext* context, uint32_t segment_num_rows) {
+ DCHECK_GE(get_num_children(), 2);
+ return _evaluate_inverted_index(context, _function, segment_num_rows);
+}
+
Status VInPredicate::execute(VExprContext* context, Block* block, int* result_column_id) {
if (is_const_and_have_executed()) { // const have execute in open function
return get_result_from_const(block, _expr_name, result_column_id);
}
+ if (_can_fast_execute && fast_execute(context, block, result_column_id)) {
+ return Status::OK();
+ }
DCHECK(_open_finished || _getting_const_col);
// TODO: not execute const expr again, but use the const column in function context
doris::vectorized::ColumnNumbers arguments(_children.size());
@@ -120,15 +128,6 @@ Status VInPredicate::execute(VExprContext* context, Block* block, int* result_co
// prepare a column to save result
block->insert({nullptr, _data_type, _expr_name});
- if (_can_fast_execute) {
- auto can_fast_execute = fast_execute(*block, arguments, num_columns_without_result,
- block->rows(), _function->get_name());
- if (can_fast_execute) {
- *result_column_id = num_columns_without_result;
- return Status::OK();
- }
- }
-
RETURN_IF_ERROR(_function->execute(context->fn_context(_fn_context_index), *block, arguments,
num_columns_without_result, block->rows(), false));
*result_column_id = num_columns_without_result;
@@ -152,4 +151,4 @@ std::string VInPredicate::debug_string() const {
return out.str();
}
-} // namespace doris::vectorized
\ No newline at end of file
+} // namespace doris::vectorized
diff --git a/be/src/vec/exprs/vin_predicate.h b/be/src/vec/exprs/vin_predicate.h
index 5f197f996e9..4d227510b91 100644
--- a/be/src/vec/exprs/vin_predicate.h
+++ b/be/src/vec/exprs/vin_predicate.h
@@ -54,7 +54,7 @@ public:
const FunctionBasePtr function() { return _function; }
bool is_not_in() const { return _is_not_in; };
- bool can_fast_execute() const override { return true; }
+ Status evaluate_inverted_index(VExprContext* context, uint32_t segment_num_rows) override;
private:
FunctionBasePtr _function;
diff --git a/be/src/vec/exprs/vliteral.h b/be/src/vec/exprs/vliteral.h
index 3e56757b313..3d9c948ec88 100644
--- a/be/src/vec/exprs/vliteral.h
+++ b/be/src/vec/exprs/vliteral.h
@@ -52,6 +52,7 @@ public:
std::string value() const;
const ColumnPtr& get_column_ptr() const { return _column_ptr; }
+ const DataTypePtr& get_data_type() const { return _data_type; }
bool is_literal() const override { return true; }
diff --git a/be/src/vec/exprs/vmatch_predicate.cpp b/be/src/vec/exprs/vmatch_predicate.cpp
index a9869bdc4ec..9dea7ca870c 100644
--- a/be/src/vec/exprs/vmatch_predicate.cpp
+++ b/be/src/vec/exprs/vmatch_predicate.cpp
@@ -43,6 +43,8 @@
#include "vec/core/column_with_type_and_name.h"
#include "vec/core/columns_with_type_and_name.h"
#include "vec/exprs/vexpr_context.h"
+#include "vec/exprs/vliteral.h"
+#include "vec/exprs/vslot_ref.h"
#include "vec/functions/simple_function_factory.h"
namespace doris {
@@ -130,9 +132,35 @@ void VMatchPredicate::close(VExprContext* context, FunctionContext::FunctionStat
VExpr::close(context, scope);
}
+Status VMatchPredicate::evaluate_inverted_index(VExprContext* context, uint32_t segment_num_rows) {
+ DCHECK_EQ(get_num_children(), 2);
+ return _evaluate_inverted_index(context, _function, segment_num_rows);
+}
+
Status VMatchPredicate::execute(VExprContext* context, Block* block, int* result_column_id) {
DCHECK(_open_finished || _getting_const_col);
- // TODO: not execute const expr again, but use the const column in function context
+ if (_can_fast_execute && fast_execute(context, block, result_column_id)) {
+ return Status::OK();
+ }
+ DBUG_EXECUTE_IF("VMatchPredicate.execute", {
+ return Status::Error<ErrorCode::INVERTED_INDEX_NOT_SUPPORTED>(
+ "{} not support slow path, hit debug point.", _expr_name);
+ });
+ DBUG_EXECUTE_IF("VMatchPredicate.must_in_slow_path", {
+ auto debug_col_name = DebugPoints::instance()->get_debug_param_or_default<std::string>(
+ "VMatchPredicate.must_in_slow_path", "column_name", "");
+
+ std::vector<std::string> column_names;
+ boost::split(column_names, debug_col_name, boost::algorithm::is_any_of(","));
+
+ auto* column_slot_ref = assert_cast<VSlotRef*>(get_child(0).get());
+ std::string column_name = column_slot_ref->expr_name();
+ auto it = std::find(column_names.begin(), column_names.end(), column_name);
+ if (it == column_names.end()) {
+ return Status::Error<ErrorCode::INTERNAL_ERROR>(
+ "column {} should in slow path while VMatchPredicate::execute.", column_name);
+ }
+ })
doris::vectorized::ColumnNumbers arguments(_children.size());
for (int i = 0; i < _children.size(); ++i) {
int column_id = -1;
diff --git a/be/src/vec/exprs/vmatch_predicate.h b/be/src/vec/exprs/vmatch_predicate.h
index af364b4fd54..aaa28658e8a 100644
--- a/be/src/vec/exprs/vmatch_predicate.h
+++ b/be/src/vec/exprs/vmatch_predicate.h
@@ -54,12 +54,13 @@ public:
Status open(RuntimeState* state, VExprContext* context,
FunctionContext::FunctionStateScope scope) override;
void close(VExprContext* context, FunctionContext::FunctionStateScope scope) override;
+ Status evaluate_inverted_index(VExprContext* context, uint32_t segment_num_rows) override;
const std::string& expr_name() const override;
const std::string& function_name() const;
std::string debug_string() const override;
- const FunctionBasePtr function() { return _function; }
+ FunctionBasePtr function() { return _function; }
private:
FunctionBasePtr _function;
diff --git a/be/src/vec/functions/array/function_array_index.h b/be/src/vec/functions/array/function_array_index.h
index 37598f26738..e4426e95ce3 100644
--- a/be/src/vec/functions/array/function_array_index.h
+++ b/be/src/vec/functions/array/function_array_index.h
@@ -115,19 +115,18 @@ public:
return Status::OK();
}
- /**
- * eval inverted index. we can filter array rows with inverted index iter
- */
- Status eval_inverted_index(FunctionContext* context,
- const vectorized::IndexFieldNameAndTypePair& data_type_with_name,
- segment_v2::InvertedIndexIterator* iter, uint32_t num_rows,
- roaring::Roaring* bitmap) const override {
- std::shared_ptr<roaring::Roaring> roaring = std::make_shared<roaring::Roaring>();
- auto* param_value = reinterpret_cast<ParamValue*>(
- context->get_function_state(FunctionContext::FRAGMENT_LOCAL));
- if (param_value == nullptr || param_value->value.is_null()) {
- return Status::Error<ErrorCode::INVERTED_INDEX_EVALUATE_SKIPPED>(
- "Inverted index evaluate skipped, param_value is nullptr or value is null");
+ Status evaluate_inverted_index(
+ const ColumnsWithTypeAndName& arguments,
+ const std::vector<vectorized::IndexFieldNameAndTypePair>& data_type_with_names,
+ std::vector<segment_v2::InvertedIndexIterator*> iterators, uint32_t num_rows,
+ segment_v2::InvertedIndexResultBitmap& bitmap_result) const override {
+ DCHECK(arguments.size() == 1);
+ DCHECK(data_type_with_names.size() == 1);
+ DCHECK(iterators.size() == 1);
+ auto* iter = iterators[0];
+ auto data_type_with_name = data_type_with_names[0];
+ if (iter == nullptr) {
+ return Status::OK();
}
if (iter->get_inverted_index_reader_type() ==
segment_v2::InvertedIndexReaderType::FULLTEXT) {
@@ -137,21 +136,35 @@ public:
// but query is also tokenized, and FULLTEXT reader will catch this row as matched,
// so array_index(array, 'tall:120cm, weight: 35kg') return this rowid,
// but we expect it to be filtered, because we want row is equal to 'tall:120cm, weight: 35kg'
- return Status::Error<ErrorCode::INVERTED_INDEX_EVALUATE_SKIPPED>(
- "Inverted index evaluate skipped, FULLTEXT reader can not support array_index");
+ return Status::OK();
+ }
+ Field param_value;
+ arguments[0].column->get(0, param_value);
+ auto param_type = arguments[0].type->get_type_as_type_descriptor().type;
+ // The current implementation for the inverted index of arrays cannot handle cases where the array contains null values,
+ // meaning an item in the array is null.
+ if (param_value.is_null()) {
+ return Status::OK();
+ }
+
+ std::shared_ptr<roaring::Roaring> roaring = std::make_shared<roaring::Roaring>();
+ std::shared_ptr<roaring::Roaring> null_bitmap = std::make_shared<roaring::Roaring>();
+ if (iter->has_null()) {
+ segment_v2::InvertedIndexQueryCacheHandle null_bitmap_cache_handle;
+ RETURN_IF_ERROR(iter->read_null_bitmap(&null_bitmap_cache_handle));
+ null_bitmap = null_bitmap_cache_handle.get_bitmap();
}
std::unique_ptr<InvertedIndexQueryParamFactory> query_param = nullptr;
- RETURN_IF_ERROR(InvertedIndexQueryParamFactory::create_query_value(
- param_value->type, ¶m_value->value, query_param));
- if (is_string_type(param_value->type)) {
+ RETURN_IF_ERROR(InvertedIndexQueryParamFactory::create_query_value(param_type, ¶m_value,
+ query_param));
+ if (is_string_type(param_type)) {
Status st = iter->read_from_inverted_index(
data_type_with_name.first, query_param->get_value(),
segment_v2::InvertedIndexQueryType::EQUAL_QUERY, num_rows, roaring);
if (st.code() == ErrorCode::INVERTED_INDEX_NO_TERMS) {
// if analyzed param with no term, we do not filter any rows
// return all rows with OK status
- bitmap->addRange(0, num_rows);
- return Status::OK();
+ roaring->addRange(0, num_rows);
} else if (st != Status::OK()) {
return st;
}
@@ -160,18 +173,6 @@ public:
data_type_with_name.first, query_param->get_value(),
segment_v2::InvertedIndexQueryType::EQUAL_QUERY, num_rows, roaring));
}
-
- // mask out null_bitmap, since NULL cmp VALUE will produce NULL
- // and be treated as false in WHERE
- // keep it after query, since query will try to read null_bitmap and put it to cache
- segment_v2::InvertedIndexQueryCacheHandle null_bitmap_cache_handle;
- RETURN_IF_ERROR(iter->read_null_bitmap(&null_bitmap_cache_handle));
- std::shared_ptr<roaring::Roaring> null_bitmap = null_bitmap_cache_handle.get_bitmap();
- if (null_bitmap) {
- *bitmap -= *null_bitmap;
- }
-
- *bitmap = *roaring;
// here debug for check array_contains function really filter rows by inverted index correctly
DBUG_EXECUTE_IF("array_func.array_contains", {
auto result_bitmap = DebugPoints::instance()->get_debug_param_or_default<int32_t>(
@@ -180,13 +181,22 @@ public:
return Status::Error<ErrorCode::INTERNAL_ERROR>(
"result_bitmap count cannot be negative");
}
- if (bitmap->cardinality() != result_bitmap) {
+ if (roaring->cardinality() != result_bitmap) {
return Status::Error<ErrorCode::INTERNAL_ERROR>(
"array_contains really filtered {} by inverted index not equal to expected "
"{}",
- bitmap->cardinality(), result_bitmap);
+ roaring->cardinality(), result_bitmap);
}
})
+ if (iter->has_null()) {
+ segment_v2::InvertedIndexQueryCacheHandle null_bitmap_cache_handle;
+ RETURN_IF_ERROR(iter->read_null_bitmap(&null_bitmap_cache_handle));
+ null_bitmap = null_bitmap_cache_handle.get_bitmap();
+ }
+ segment_v2::InvertedIndexResultBitmap result(roaring, null_bitmap);
+ bitmap_result = result;
+ bitmap_result.mask_out_null();
+
return Status::OK();
}
diff --git a/be/src/vec/functions/function.h b/be/src/vec/functions/function.h
index 43ab3aaba92..d53ad821dcf 100644
--- a/be/src/vec/functions/function.h
+++ b/be/src/vec/functions/function.h
@@ -190,12 +190,12 @@ public:
->execute(context, block, arguments, result, input_rows_count, dry_run);
}
- virtual Status eval_inverted_index(
- FunctionContext* context,
- const vectorized::IndexFieldNameAndTypePair& data_type_with_name,
- segment_v2::InvertedIndexIterator* iter, uint32_t num_rows,
- roaring::Roaring* bitmap) const {
- return Status::NotSupported("eval_inverted_index is not supported in function: ",
+ virtual Status evaluate_inverted_index(
+ const ColumnsWithTypeAndName& arguments,
+ const std::vector<vectorized::IndexFieldNameAndTypePair>& data_type_with_names,
+ std::vector<segment_v2::InvertedIndexIterator*> iterators, uint32_t num_rows,
+ segment_v2::InvertedIndexResultBitmap& bitmap_result) const {
+ return Status::NotSupported("evaluate_inverted_index is not supported in function: ",
get_name());
}
@@ -235,12 +235,6 @@ public:
}
virtual bool can_push_down_to_index() const { return false; }
-
- virtual Status eval_inverted_index(VExpr* context, segment_v2::FuncExprParams& params,
- std::shared_ptr<roaring::Roaring>& result) {
- return Status::NotSupported("eval_inverted_index is not supported in function: ",
- get_name());
- }
};
using FunctionBasePtr = std::shared_ptr<IFunctionBase>;
@@ -464,11 +458,13 @@ protected:
return function->execute_impl(context, block, arguments, result, input_rows_count);
}
- Status eval_inverted_index(FunctionContext* context,
- const vectorized::IndexFieldNameAndTypePair& data_type_with_name,
- segment_v2::InvertedIndexIterator* iter, uint32_t num_rows,
- roaring::Roaring* bitmap) const {
- return function->eval_inverted_index(context, data_type_with_name, iter, num_rows, bitmap);
+ Status evaluate_inverted_index(
+ const ColumnsWithTypeAndName& arguments,
+ const std::vector<vectorized::IndexFieldNameAndTypePair>& data_type_with_names,
+ std::vector<segment_v2::InvertedIndexIterator*> iterators, uint32_t num_rows,
+ segment_v2::InvertedIndexResultBitmap& bitmap_result) const {
+ return function->evaluate_inverted_index(arguments, data_type_with_names, iterators,
+ num_rows, bitmap_result);
}
Status execute_impl_dry_run(FunctionContext* context, Block& block,
@@ -528,11 +524,13 @@ public:
return function->close(context, scope);
}
- Status eval_inverted_index(FunctionContext* context,
- const vectorized::IndexFieldNameAndTypePair& data_type_with_name,
- segment_v2::InvertedIndexIterator* iter, uint32_t num_rows,
- roaring::Roaring* bitmap) const override {
- return function->eval_inverted_index(context, data_type_with_name, iter, num_rows, bitmap);
+ Status evaluate_inverted_index(
+ const ColumnsWithTypeAndName& args,
+ const std::vector<vectorized::IndexFieldNameAndTypePair>& data_type_with_names,
+ std::vector<segment_v2::InvertedIndexIterator*> iterators, uint32_t num_rows,
+ segment_v2::InvertedIndexResultBitmap& bitmap_result) const override {
+ return function->evaluate_inverted_index(args, data_type_with_names, iterators, num_rows,
+ bitmap_result);
}
IFunctionBase::Monotonicity get_monotonicity_for_range(const IDataType& type, const Field& left,
@@ -546,11 +544,6 @@ public:
bool can_push_down_to_index() const override { return function->can_push_down_to_index(); }
- Status eval_inverted_index(VExpr* expr, segment_v2::FuncExprParams& params,
- std::shared_ptr<roaring::Roaring>& result) override {
- return function->eval_inverted_index(expr, params, result);
- }
-
private:
std::shared_ptr<IFunction> function;
DataTypes arguments;
diff --git a/be/src/vec/functions/function_multi_match.cpp b/be/src/vec/functions/function_multi_match.cpp
index 342ecacf77e..e2c8a4a4a83 100644
--- a/be/src/vec/functions/function_multi_match.cpp
+++ b/be/src/vec/functions/function_multi_match.cpp
@@ -17,27 +17,17 @@
#include "vec/functions/function_multi_match.h"
-#include <gen_cpp/PaloBrokerService_types.h>
#include <glog/logging.h>
-#include <boost/algorithm/string.hpp>
-#include <boost/algorithm/string/classification.hpp>
-#include <cstddef>
-#include <cstdint>
#include <memory>
#include <roaring/roaring.hh>
#include <string>
#include <vector>
#include "io/fs/file_reader.h"
-#include "olap/olap_common.h"
#include "olap/rowset/segment_v2/inverted_index/query/phrase_prefix_query.h"
#include "olap/rowset/segment_v2/segment_iterator.h"
-#include "runtime/primitive_type.h"
#include "vec/columns/column.h"
-#include "vec/data_types/data_type.h"
-#include "vec/exprs/varray_literal.h"
-#include "vec/exprs/vexpr.h"
#include "vec/exprs/vslot_ref.h"
#include "vec/functions/simple_function_factory.h"
@@ -56,97 +46,42 @@ InvertedIndexQueryType get_query_type(const std::string& query_type) {
return InvertedIndexQueryType::UNKNOWN_QUERY;
}
-Status FunctionMultiMatch::eval_inverted_index(VExpr* expr, segment_v2::FuncExprParams& params,
- std::shared_ptr<roaring::Roaring>& result) {
- // fields
- std::vector<std::string> query_fileds;
- size_t i = 0;
- for (; i < expr->get_num_children(); i++) {
- auto child_expr = expr->get_child(i);
- if (child_expr->node_type() == TExprNodeType::type::SLOT_REF) {
- query_fileds.emplace_back(child_expr->expr_name());
- } else {
- break;
- }
- }
- if (i != expr->get_num_children() - 2) {
- return Status::RuntimeError("parameter type incorrect: slot = {}", i);
- }
-
+Status FunctionMultiMatch::evaluate_inverted_index(
+ const ColumnsWithTypeAndName& arguments,
+ const std::vector<vectorized::IndexFieldNameAndTypePair>& data_type_with_names,
+ std::vector<segment_v2::InvertedIndexIterator*> iterators, uint32_t num_rows,
+ segment_v2::InvertedIndexResultBitmap& bitmap_result) const {
+ DCHECK(arguments.size() == 2);
+ std::shared_ptr<roaring::Roaring> roaring = std::make_shared<roaring::Roaring>();
+ std::shared_ptr<roaring::Roaring> null_bitmap = std::make_shared<roaring::Roaring>();
// type
- std::string param1 = std::static_pointer_cast<VLiteral>(expr->get_child(i))->value();
- auto query_type = get_query_type(param1);
+ auto query_type_value = arguments[0].column->get_data_at(0);
+ auto query_type = get_query_type(query_type_value.to_string());
if (query_type == InvertedIndexQueryType::UNKNOWN_QUERY) {
- return Status::RuntimeError("parameter query type incorrect: query_type = {}", query_type);
+ return Status::RuntimeError(
+ "parameter query type incorrect for function multi_match: query_type = {}",
+ query_type);
}
// query
- std::string query_str = std::static_pointer_cast<VLiteral>(expr->get_child(i + 1))->value();
-
- auto& segment_iterator = params._segment_iterator;
- auto& segment = segment_iterator->segment();
- auto& opts = segment_iterator->storage_read_options();
- auto& tablet_schema = opts.tablet_schema;
- auto& idx_iterators = segment_iterator->inverted_index_iterators();
-
- // check
- std::vector<ColumnId> columns_ids;
- for (const auto& column_name : query_fileds) {
- auto cid = tablet_schema->field_index(column_name);
- if (cid < 0) {
- return Status::RuntimeError("column name is incorrect: {}", column_name);
- }
- if (idx_iterators[cid] == nullptr) {
- return Status::RuntimeError("column idx is incorrect: {}", column_name);
- }
- columns_ids.emplace_back(cid);
+ auto query_str = arguments[1].column->get_data_at(0);
+ auto param_type = arguments[1].type->get_type_as_type_descriptor().type;
+ if (!is_string_type(param_type)) {
+ return Status::Error<ErrorCode::INVERTED_INDEX_INVALID_PARAMETERS>(
+ "arguments for multi_match must be string");
}
-
- // cache key
- roaring::Roaring cids_str;
- cids_str.addMany(columns_ids.size(), columns_ids.data());
- cids_str.runOptimize();
- std::string column_name_binary(cids_str.getSizeInBytes(), 0);
- cids_str.write(column_name_binary.data());
-
- InvertedIndexQueryCache::CacheKey cache_key;
- io::Path index_path = segment.file_reader()->path();
- cache_key.index_path = index_path.parent_path() / index_path.stem();
- cache_key.column_name = column_name_binary;
- cache_key.query_type = query_type;
- cache_key.value = query_str;
-
- // query cache
- auto* cache = InvertedIndexQueryCache::instance();
- InvertedIndexQueryCacheHandle cache_handler;
- if (cache->lookup(cache_key, &cache_handler)) {
- result = cache_handler.get_bitmap();
- return Status::OK();
- }
-
// search
- for (const auto& column_name : query_fileds) {
- auto cid = tablet_schema->field_index(column_name);
- const auto& column = *DORIS_TRY(tablet_schema->column(column_name));
- const auto& index_reader = idx_iterators[cid]->reader();
-
+ for (int i = 0; i < data_type_with_names.size(); i++) {
+ auto column_name = data_type_with_names[i].first;
+ auto* iter = iterators[i];
auto single_result = std::make_shared<roaring::Roaring>();
- StringRef query_value(query_str.data());
- auto index_version = tablet_schema->get_inverted_index_storage_format();
- if (index_version == InvertedIndexStorageFormatPB::V1) {
- RETURN_IF_ERROR(index_reader->query(opts.stats, opts.runtime_state, column_name,
- &query_value, query_type, single_result));
- } else if (index_version == InvertedIndexStorageFormatPB::V2) {
- RETURN_IF_ERROR(index_reader->query(opts.stats, opts.runtime_state,
- std::to_string(column.unique_id()), &query_value,
- query_type, single_result));
- }
- (*result) |= (*single_result);
+ std::shared_ptr<roaring::Roaring> index = std::make_shared<roaring::Roaring>();
+ RETURN_IF_ERROR(iter->read_from_inverted_index(column_name, &query_str, query_type,
+ num_rows, index));
+ *roaring |= *index;
}
-
- result->runOptimize();
- cache->insert(cache_key, result, &cache_handler);
-
+ segment_v2::InvertedIndexResultBitmap result(roaring, null_bitmap);
+ bitmap_result = result;
return Status::OK();
}
diff --git a/be/src/vec/functions/function_multi_match.h b/be/src/vec/functions/function_multi_match.h
index 8e30b6e9f22..4aca75acc02 100644
--- a/be/src/vec/functions/function_multi_match.h
+++ b/be/src/vec/functions/function_multi_match.h
@@ -58,8 +58,11 @@ public:
bool can_push_down_to_index() const override { return true; }
- Status eval_inverted_index(VExpr* expr, segment_v2::FuncExprParams& params,
- std::shared_ptr<roaring::Roaring>& result) override;
+ Status evaluate_inverted_index(
+ const ColumnsWithTypeAndName& arguments,
+ const std::vector<vectorized::IndexFieldNameAndTypePair>& data_type_with_names,
+ std::vector<segment_v2::InvertedIndexIterator*> iterators, uint32_t num_rows,
+ segment_v2::InvertedIndexResultBitmap& bitmap_result) const override;
};
} // namespace doris::vectorized
diff --git a/be/src/vec/functions/functions_comparison.h b/be/src/vec/functions/functions_comparison.h
index 86380c37927..f6aa46fe1c4 100644
--- a/be/src/vec/functions/functions_comparison.h
+++ b/be/src/vec/functions/functions_comparison.h
@@ -39,6 +39,8 @@
#include "vec/functions/function_helpers.h"
#include "vec/functions/functions_logical.h"
#include "vec/runtime/vdatetime_value.h"
+//#include "olap/rowset/segment_v2/inverted_index_reader.h"
+
namespace doris::vectorized {
/** Comparison functions: ==, !=, <, >, <=, >=.
@@ -526,6 +528,72 @@ public:
return std::make_shared<DataTypeUInt8>();
}
+ Status evaluate_inverted_index(
+ const ColumnsWithTypeAndName& arguments,
+ const std::vector<vectorized::IndexFieldNameAndTypePair>& data_type_with_names,
+ std::vector<segment_v2::InvertedIndexIterator*> iterators, uint32_t num_rows,
+ segment_v2::InvertedIndexResultBitmap& bitmap_result) const override {
+ DCHECK(arguments.size() == 1);
+ DCHECK(data_type_with_names.size() == 1);
+ DCHECK(iterators.size() == 1);
+ auto* iter = iterators[0];
+ auto data_type_with_name = data_type_with_names[0];
+ if (iter == nullptr) {
+ return Status::OK();
+ }
+ if (iter->get_inverted_index_reader_type() ==
+ segment_v2::InvertedIndexReaderType::FULLTEXT) {
+ //NOT support comparison predicate when parser is FULLTEXT for expr inverted index evaluate.
+ return Status::OK();
+ }
+ std::string column_name = data_type_with_name.first;
+ Field param_value;
+ arguments[0].column->get(0, param_value);
+ auto param_type = arguments[0].type->get_type_as_type_descriptor().type;
+
+ std::unique_ptr<segment_v2::InvertedIndexQueryParamFactory> query_param = nullptr;
+ RETURN_IF_ERROR(segment_v2::InvertedIndexQueryParamFactory::create_query_value(
+ param_type, ¶m_value, query_param));
+ segment_v2::InvertedIndexQueryType query_type;
+ std::string_view name_view(name);
+ if (name_view == NameEquals::name || name_view == NameNotEquals::name) {
+ query_type = segment_v2::InvertedIndexQueryType::EQUAL_QUERY;
+ } else if (name_view == NameLess::name) {
+ query_type = segment_v2::InvertedIndexQueryType::LESS_THAN_QUERY;
+ } else if (name_view == NameLessOrEquals::name) {
+ query_type = segment_v2::InvertedIndexQueryType::LESS_EQUAL_QUERY;
+ } else if (name_view == NameGreater::name) {
+ query_type = segment_v2::InvertedIndexQueryType::GREATER_THAN_QUERY;
+ } else if (name_view == NameGreaterOrEquals::name) {
+ query_type = segment_v2::InvertedIndexQueryType::GREATER_EQUAL_QUERY;
+ } else {
+ return Status::InvalidArgument("invalid comparison op type {}", Name::name);
+ }
+
+ std::shared_ptr<roaring::Roaring> roaring = std::make_shared<roaring::Roaring>();
+ RETURN_IF_ERROR(segment_v2::InvertedIndexQueryParamFactory::create_query_value(
+ param_type, ¶m_value, query_param));
+ RETURN_IF_ERROR(iter->read_from_inverted_index(column_name, query_param->get_value(),
+ query_type, num_rows, roaring));
+ std::shared_ptr<roaring::Roaring> null_bitmap = std::make_shared<roaring::Roaring>();
+ if (iter->has_null()) {
+ segment_v2::InvertedIndexQueryCacheHandle null_bitmap_cache_handle;
+ RETURN_IF_ERROR(iter->read_null_bitmap(&null_bitmap_cache_handle));
+ null_bitmap = null_bitmap_cache_handle.get_bitmap();
+ }
+ segment_v2::InvertedIndexResultBitmap result(roaring, null_bitmap);
+ bitmap_result = result;
+ bitmap_result.mask_out_null();
+
+ if (name == "ne") {
+ roaring::Roaring full_result;
+ full_result.addRange(0, num_rows);
+ bitmap_result.op_not(&full_result);
+ }
+
+ return Status::OK();
+ }
+
Status execute_impl(FunctionContext* context, Block& block, const ColumnNumbers& arguments,
size_t result, size_t input_rows_count) const override {
const auto& col_with_type_and_name_left = block.get_by_position(arguments[0]);
diff --git a/be/src/vec/functions/in.h b/be/src/vec/functions/in.h
index 9b5c5bb023a..287e67d3b2c 100644
--- a/be/src/vec/functions/in.h
+++ b/be/src/vec/functions/in.h
@@ -135,6 +135,64 @@ public:
return Status::OK();
}
+ Status evaluate_inverted_index(
+ const ColumnsWithTypeAndName& arguments,
+ const std::vector<vectorized::IndexFieldNameAndTypePair>& data_type_with_names,
+ std::vector<segment_v2::InvertedIndexIterator*> iterators, uint32_t num_rows,
+ segment_v2::InvertedIndexResultBitmap& bitmap_result) const override {
+ DCHECK(data_type_with_names.size() == 1);
+ DCHECK(iterators.size() == 1);
+ auto* iter = iterators[0];
+ auto data_type_with_name = data_type_with_names[0];
+ std::shared_ptr<roaring::Roaring> roaring = std::make_shared<roaring::Roaring>();
+ std::shared_ptr<roaring::Roaring> null_bitmap = std::make_shared<roaring::Roaring>();
+
+ if (iter == nullptr) {
+ return Status::OK();
+ }
+ if (iter->get_inverted_index_reader_type() ==
+ segment_v2::InvertedIndexReaderType::FULLTEXT) {
+ //NOT support in list when parser is FULLTEXT for expr inverted index evaluate.
+ return Status::OK();
+ }
+ if (iter->has_null()) {
+ segment_v2::InvertedIndexQueryCacheHandle null_bitmap_cache_handle;
+ RETURN_IF_ERROR(iter->read_null_bitmap(&null_bitmap_cache_handle));
+ null_bitmap = null_bitmap_cache_handle.get_bitmap();
+ }
+ std::string column_name = data_type_with_name.first;
+ for (const auto& arg : arguments) {
+ Field param_value;
+ arg.column->get(0, param_value);
+ auto param_type = arg.type->get_type_as_type_descriptor().type;
+ if (param_value.is_null()) {
+ // predicate like column NOT IN (NULL, '') should not push down to index.
+ if (negative) {
+ return Status::OK();
+ }
+ *roaring |= *null_bitmap;
+ continue;
+ }
+ std::unique_ptr<InvertedIndexQueryParamFactory> query_param = nullptr;
+ RETURN_IF_ERROR(InvertedIndexQueryParamFactory::create_query_value(
+ param_type, ¶m_value, query_param));
+ InvertedIndexQueryType query_type = InvertedIndexQueryType::EQUAL_QUERY;
+ std::shared_ptr<roaring::Roaring> index = std::make_shared<roaring::Roaring>();
+ RETURN_IF_ERROR(iter->read_from_inverted_index(column_name, query_param->get_value(),
+ query_type, num_rows, index));
+ *roaring |= *index;
+ }
+ segment_v2::InvertedIndexResultBitmap result(roaring, null_bitmap);
+ bitmap_result = result;
+ bitmap_result.mask_out_null();
+ if constexpr (negative) {
+ roaring::Roaring full_result;
+ full_result.addRange(0, num_rows);
+ bitmap_result.op_not(&full_result);
+ }
+ return Status::OK();
+ }
+
Status execute_impl(FunctionContext* context, Block& block, const ColumnNumbers& arguments,
size_t result, size_t input_rows_count) const override {
auto* in_state = reinterpret_cast<InState*>(
diff --git a/be/src/vec/functions/match.cpp b/be/src/vec/functions/match.cpp
index a506dfac325..a9e1b6eba8e 100644
--- a/be/src/vec/functions/match.cpp
+++ b/be/src/vec/functions/match.cpp
@@ -24,7 +24,63 @@
#include "util/debug_points.h"
namespace doris::vectorized {
+Status FunctionMatchBase::evaluate_inverted_index(
+ const ColumnsWithTypeAndName& arguments,
+ const std::vector<vectorized::IndexFieldNameAndTypePair>& data_type_with_names,
+ std::vector<segment_v2::InvertedIndexIterator*> iterators, uint32_t num_rows,
+ segment_v2::InvertedIndexResultBitmap& bitmap_result) const {
+ DCHECK(arguments.size() == 1);
+ DCHECK(data_type_with_names.size() == 1);
+ DCHECK(iterators.size() == 1);
+ auto* iter = iterators[0];
+ auto data_type_with_name = data_type_with_names[0];
+ if (iter == nullptr) {
+ return Status::OK();
+ }
+ const std::string& function_name = get_name();
+
+ if (function_name == MATCH_PHRASE_FUNCTION || function_name == MATCH_PHRASE_PREFIX_FUNCTION ||
+ function_name == MATCH_PHRASE_EDGE_FUNCTION) {
+ if (iter->get_inverted_index_reader_type() == InvertedIndexReaderType::FULLTEXT &&
+ get_parser_phrase_support_string_from_properties(iter->get_index_properties()) ==
+ INVERTED_INDEX_PARSER_PHRASE_SUPPORT_NO) {
+ return Status::Error<ErrorCode::INVERTED_INDEX_INVALID_PARAMETERS>(
+ "phrase queries require setting support_phrase = true");
+ }
+ }
+ std::shared_ptr<roaring::Roaring> roaring = std::make_shared<roaring::Roaring>();
+ Field param_value;
+ arguments[0].column->get(0, param_value);
+ auto param_type = arguments[0].type->get_type_as_type_descriptor().type;
+ if (!is_string_type(param_type)) {
+ return Status::Error<ErrorCode::INVERTED_INDEX_INVALID_PARAMETERS>(
+ "arguments for match must be string");
+ }
+ std::unique_ptr<InvertedIndexQueryParamFactory> query_param = nullptr;
+ RETURN_IF_ERROR(InvertedIndexQueryParamFactory::create_query_value(param_type, ¶m_value,
+ query_param));
+ if (is_string_type(param_type)) {
+ auto inverted_index_query_type = get_query_type_from_fn_name();
+ RETURN_IF_ERROR(
+ iter->read_from_inverted_index(data_type_with_name.first, query_param->get_value(),
+ inverted_index_query_type, num_rows, roaring));
+ } else {
+ return Status::Error<ErrorCode::INVERTED_INDEX_INVALID_PARAMETERS>(
+ "invalid params type for FunctionMatchBase::evaluate_inverted_index {}",
+ param_type);
+ }
+ std::shared_ptr<roaring::Roaring> null_bitmap = std::make_shared<roaring::Roaring>();
+ if (iter->has_null()) {
+ segment_v2::InvertedIndexQueryCacheHandle null_bitmap_cache_handle;
+ RETURN_IF_ERROR(iter->read_null_bitmap(&null_bitmap_cache_handle));
+ null_bitmap = null_bitmap_cache_handle.get_bitmap();
+ }
+ segment_v2::InvertedIndexResultBitmap result(roaring, null_bitmap);
+ bitmap_result = result;
+ bitmap_result.mask_out_null();
+ return Status::OK();
+}
Status FunctionMatchBase::execute_impl(FunctionContext* context, Block& block,
const ColumnNumbers& arguments, size_t result,
size_t input_rows_count) const {
@@ -32,77 +88,69 @@ Status FunctionMatchBase::execute_impl(FunctionContext* context, Block& block,
DataTypePtr& type_ptr = block.get_by_position(arguments[1]).type;
auto match_query_str = type_ptr->to_string(*column_ptr, 0);
std::string column_name = block.get_by_position(arguments[0]).name;
- auto match_pred_column_name =
- BeConsts::BLOCK_TEMP_COLUMN_PREFIX + column_name + "_match_" + match_query_str;
- if (!block.has(match_pred_column_name)) {
- VLOG_DEBUG << "begin to execute match directly, column_name=" << column_name
- << ", match_query_str=" << match_query_str;
- InvertedIndexCtx* inverted_index_ctx = reinterpret_cast<InvertedIndexCtx*>(
- context->get_function_state(FunctionContext::THREAD_LOCAL));
- if (inverted_index_ctx == nullptr) {
- inverted_index_ctx = reinterpret_cast<InvertedIndexCtx*>(
- context->get_function_state(FunctionContext::FRAGMENT_LOCAL));
- }
+ VLOG_DEBUG << "begin to execute match directly, column_name=" << column_name
+ << ", match_query_str=" << match_query_str;
+ InvertedIndexCtx* inverted_index_ctx = reinterpret_cast<InvertedIndexCtx*>(
+ context->get_function_state(FunctionContext::THREAD_LOCAL));
+ if (inverted_index_ctx == nullptr) {
+ inverted_index_ctx = reinterpret_cast<InvertedIndexCtx*>(
+ context->get_function_state(FunctionContext::FRAGMENT_LOCAL));
+ }
- const ColumnPtr source_col =
- block.get_by_position(arguments[0]).column->convert_to_full_column_if_const();
- const auto* values = check_and_get_column<ColumnString>(source_col.get());
- const ColumnArray* array_col = nullptr;
- if (source_col->is_column_array()) {
- if (source_col->is_nullable()) {
- auto* nullable = check_and_get_column<ColumnNullable>(source_col.get());
- array_col = check_and_get_column<ColumnArray>(*nullable->get_nested_column_ptr());
- } else {
- array_col = check_and_get_column<ColumnArray>(source_col.get());
- }
- if (array_col && !array_col->get_data().is_column_string()) {
- return Status::NotSupported(
- fmt::format("unsupported nested array of type {} for function {}",
- is_column_nullable(array_col->get_data())
- ? array_col->get_data().get_name()
- : array_col->get_data().get_family_name(),
- get_name()));
- }
+ const ColumnPtr source_col =
+ block.get_by_position(arguments[0]).column->convert_to_full_column_if_const();
+ const auto* values = check_and_get_column<ColumnString>(source_col.get());
+ const ColumnArray* array_col = nullptr;
+ if (source_col->is_column_array()) {
+ if (source_col->is_nullable()) {
+ auto* nullable = check_and_get_column<ColumnNullable>(source_col.get());
+ array_col = check_and_get_column<ColumnArray>(*nullable->get_nested_column_ptr());
+ } else {
+ array_col = check_and_get_column<ColumnArray>(source_col.get());
+ }
+ if (array_col && !array_col->get_data().is_column_string()) {
+ return Status::NotSupported(
+ fmt::format("unsupported nested array of type {} for function {}",
+ is_column_nullable(array_col->get_data())
+ ? array_col->get_data().get_name()
+ : array_col->get_data().get_family_name(),
+ get_name()));
+ }
- if (is_column_nullable(array_col->get_data())) {
- const auto& array_nested_null_column =
- reinterpret_cast<const ColumnNullable&>(array_col->get_data());
- values = check_and_get_column<ColumnString>(
- *(array_nested_null_column.get_nested_column_ptr()));
- } else {
- // array column element is always set Nullable for now.
- values = check_and_get_column<ColumnString>(*(array_col->get_data_ptr()));
- }
- } else if (auto* nullable = check_and_get_column<ColumnNullable>(source_col.get())) {
- // match null
- if (type_ptr->is_nullable()) {
- if (column_ptr->only_null()) {
- block.get_by_position(result).column = nullable->get_null_map_column_ptr();
- return Status::OK();
- }
- } else {
- values = check_and_get_column<ColumnString>(*nullable->get_nested_column_ptr());
+ if (is_column_nullable(array_col->get_data())) {
+ const auto& array_nested_null_column =
+ reinterpret_cast<const ColumnNullable&>(array_col->get_data());
+ values = check_and_get_column<ColumnString>(
+ *(array_nested_null_column.get_nested_column_ptr()));
+ } else {
+ // array column element is always set Nullable for now.
+ values = check_and_get_column<ColumnString>(*(array_col->get_data_ptr()));
+ }
+ } else if (auto* nullable = check_and_get_column<ColumnNullable>(source_col.get())) {
+ // match null
+ if (type_ptr->is_nullable()) {
+ if (column_ptr->only_null()) {
+ block.get_by_position(result).column = nullable->get_null_map_column_ptr();
+ return Status::OK();
}
+ } else {
+ values = check_and_get_column<ColumnString>(*nullable->get_nested_column_ptr());
}
+ }
- if (!values) {
- LOG(WARNING) << "Illegal column " << source_col->get_name();
- return Status::InternalError("Not supported input column types");
- }
- // result column
- auto res = ColumnUInt8::create();
- ColumnUInt8::Container& vec_res = res->get_data();
- // set default value to 0, and match functions only need to set 1/true
- vec_res.resize_fill(input_rows_count);
- RETURN_IF_ERROR(execute_match(
- context, column_name, match_query_str, input_rows_count, values, inverted_index_ctx,
- (array_col ? &(array_col->get_offsets()) : nullptr), vec_res));
- block.replace_by_position(result, std::move(res));
- } else {
- auto match_pred_column =
- block.get_by_name(match_pred_column_name).column->convert_to_full_column_if_const();
- block.replace_by_position(result, std::move(match_pred_column));
+ if (!values) {
+ LOG(WARNING) << "Illegal column " << source_col->get_name();
+ return Status::InternalError("Not supported input column types");
}
+ // result column
+ auto res = ColumnUInt8::create();
+ ColumnUInt8::Container& vec_res = res->get_data();
+ // set default value to 0, and match functions only need to set 1/true
+ vec_res.resize_fill(input_rows_count);
+ RETURN_IF_ERROR(execute_match(context, column_name, match_query_str, input_rows_count, values,
+ inverted_index_ctx,
+ (array_col ? &(array_col->get_offsets()) : nullptr), vec_res));
+ block.replace_by_position(result, std::move(res));
return Status::OK();
}
diff --git a/be/src/vec/functions/match.h b/be/src/vec/functions/match.h
index 40a2fb7c1a6..3026e4a06cf 100644
--- a/be/src/vec/functions/match.h
+++ b/be/src/vec/functions/match.h
@@ -95,6 +95,11 @@ public:
int32_t& current_src_array_offset) const;
Status check(FunctionContext* context, const std::string& function_name) const;
+ Status evaluate_inverted_index(
+ const ColumnsWithTypeAndName& arguments,
+ const std::vector<vectorized::IndexFieldNameAndTypePair>& data_type_with_names,
+ std::vector<segment_v2::InvertedIndexIterator*> iterators, uint32_t num_rows,
+ segment_v2::InvertedIndexResultBitmap& bitmap_result) const override;
};
class FunctionMatchAny : public FunctionMatchBase {
diff --git a/regression-test/data/inverted_index_p0/test_index_match_phrase_prefix.out b/regression-test/data/inverted_index_p0/test_index_match_phrase_prefix.out
index 11af32e55e6..d5a81c28fe1 100644
--- a/regression-test/data/inverted_index_p0/test_index_match_phrase_prefix.out
+++ b/regression-test/data/inverted_index_p0/test_index_match_phrase_prefix.out
@@ -3,40 +3,40 @@
863
-- !sql --
-863
+235
-- !sql --
-863
+166
-- !sql --
-235
+56
-- !sql --
-235
+7
-- !sql --
-235
+863
-- !sql --
-166
+863
-- !sql --
-166
+235
-- !sql --
-166
+235
-- !sql --
-56
+166
-- !sql --
-56
+166
-- !sql --
56
-- !sql --
-7
+56
-- !sql --
7
diff --git a/regression-test/suites/fault_injection_p0/test_all_index_hit_fault_injection.groovy b/regression-test/suites/fault_injection_p0/test_all_index_hit_fault_injection.groovy
index 7adfe7702d5..eba1c5e93d2 100644
--- a/regression-test/suites/fault_injection_p0/test_all_index_hit_fault_injection.groovy
+++ b/regression-test/suites/fault_injection_p0/test_all_index_hit_fault_injection.groovy
@@ -96,10 +96,10 @@ suite("test_all_index_hit_fault_injection", "nonConcurrent") {
load_httplogs_data.call(indexTbName2, 'test_all_index_hit_fault_injection_2', 'true', 'json', 'documents-1000.json')
sql "sync"
-
+ sql """ set enable_common_expr_pushdown = true """
try {
GetDebugPoint().enableDebugPointForAllBEs("segment_iterator._read_columns_by_index", [column_name: "clientip,request"])
- GetDebugPoint().enableDebugPointForAllBEs("segment_iterator.fast_execute", [column_name: "status,size"])
+ GetDebugPoint().enableDebugPointForAllBEs("VectorizedFnCall.must_in_slow_path", [column_name: "status,size"])
qt_sql """ select count(`@timestamp`) from ${indexTbName1} where (request match_phrase 'hm'); """
qt_sql """ select count() from ${indexTbName1} where (request match_phrase 'hm'); """
@@ -125,7 +125,7 @@ suite("test_all_index_hit_fault_injection", "nonConcurrent") {
} finally {
GetDebugPoint().disableDebugPointForAllBEs("segment_iterator._read_columns_by_index")
- GetDebugPoint().disableDebugPointForAllBEs("segment_iterator.fast_execute")
+ GetDebugPoint().disableDebugPointForAllBEs("VectorizedFnCall.must_in_slow_path")
}
} finally {
}
diff --git a/regression-test/suites/fault_injection_p0/test_index_inlist_fault_injection.groovy b/regression-test/suites/fault_injection_p0/test_index_inlist_fault_injection.groovy
index a9b3d513521..54852394601 100644
--- a/regression-test/suites/fault_injection_p0/test_index_inlist_fault_injection.groovy
+++ b/regression-test/suites/fault_injection_p0/test_index_inlist_fault_injection.groovy
@@ -76,8 +76,6 @@ suite("test_index_inlist_fault_injection", "nonConcurrent") {
sql "sync"
try {
- GetDebugPoint().enableDebugPointForAllBEs("segment_iterator._rowid_result_for_index")
-
sql """ set enable_common_expr_pushdown = true; """
qt_sql """ select /*+ SET_VAR(inverted_index_skip_threshold = 0) */ count() from ${indexTbName} where clientip in ('40.135.0.0', '232.0.0.0', '26.1.0.0'); """
@@ -88,7 +86,6 @@ suite("test_index_inlist_fault_injection", "nonConcurrent") {
qt_sql """ select /*+ SET_VAR(inverted_index_skip_threshold = 0) */ count() from ${indexTbName} where (request match 'hm' and status in (1, 304, 200)); """
} finally {
- GetDebugPoint().disableDebugPointForAllBEs("segment_iterator._rowid_result_for_index")
}
try {
diff --git a/regression-test/suites/fault_injection_p0/test_index_mow_fault_injection.groovy b/regression-test/suites/fault_injection_p0/test_index_mow_fault_injection.groovy
index a1aa9a36f90..a0559119d2a 100644
--- a/regression-test/suites/fault_injection_p0/test_index_mow_fault_injection.groovy
+++ b/regression-test/suites/fault_injection_p0/test_index_mow_fault_injection.groovy
@@ -47,6 +47,7 @@ suite("test_index_mow_fault_injection", "nonConcurrent") {
try {
sql "DROP TABLE IF EXISTS ${testTable_unique}"
create_httplogs_unique_table.call(testTable_unique)
+ sql """ set enable_common_expr_pushdown = true """
sql """ INSERT INTO ${testTable_unique} VALUES (893964617, '40.135.0.0', 'GET /images/hm_bg.jpg HTTP/1.0', 200, 24736); """
sql """ INSERT INTO ${testTable_unique} VALUES (893964653, '232.0.0.0', 'GET /images/hm_bg.jpg HTTP/1.0', 200, 3781); """
diff --git a/regression-test/suites/fault_injection_p0/test_need_read_data_fault_injection.groovy b/regression-test/suites/fault_injection_p0/test_need_read_data_fault_injection.groovy
index 22e9e5eda3f..4e0b633ddb8 100644
--- a/regression-test/suites/fault_injection_p0/test_need_read_data_fault_injection.groovy
+++ b/regression-test/suites/fault_injection_p0/test_need_read_data_fault_injection.groovy
@@ -73,6 +73,7 @@ suite("test_need_read_data_fault_injection", "nonConcurrent") {
load_httplogs_data.call(indexTbName, 'test_need_read_data_fault_injection', 'true', 'json', 'documents-1000.json')
sql "sync"
+ sql """ set enable_common_expr_pushdown = true """
try {
GetDebugPoint().enableDebugPointForAllBEs("segment_iterator._read_columns_by_index")
diff --git a/regression-test/suites/fault_injection_p0/test_topn_fault_injection.groovy b/regression-test/suites/fault_injection_p0/test_topn_fault_injection.groovy
index d8eb8baf615..73b4bc808f1 100644
--- a/regression-test/suites/fault_injection_p0/test_topn_fault_injection.groovy
+++ b/regression-test/suites/fault_injection_p0/test_topn_fault_injection.groovy
@@ -96,6 +96,7 @@ suite("test_topn_fault_injection", "nonConcurrent") {
load_httplogs_data.call(indexTbName2, 'test_topn_fault_injection2', 'true', 'json', 'documents-1000.json')
sql "sync"
+ sql """ set enable_common_expr_pushdown = true """
try {
GetDebugPoint().enableDebugPointForAllBEs("segment_iterator.topn_opt_1")
diff --git a/regression-test/suites/inverted_index_p0/char_filter/test_char_replace.groovy b/regression-test/suites/inverted_index_p0/char_filter/test_char_replace.groovy
index 556a91c5df5..192c123aead 100644
--- a/regression-test/suites/inverted_index_p0/char_filter/test_char_replace.groovy
+++ b/regression-test/suites/inverted_index_p0/char_filter/test_char_replace.groovy
@@ -45,7 +45,7 @@ suite("test_char_replace") {
"replication_allocation" = "tag.location.default: 1"
);
"""
-
+ sql """ set enable_common_expr_pushdown = true """
def var_result = sql "show variables"
logger.info("show variales result: " + var_result )
diff --git a/regression-test/suites/inverted_index_p0/index_compaction/test_index_compaction_dup_keys.groovy b/regression-test/suites/inverted_index_p0/index_compaction/test_index_compaction_dup_keys.groovy
index 3e1cbc6b6e2..1de813a310b 100644
--- a/regression-test/suites/inverted_index_p0/index_compaction/test_index_compaction_dup_keys.groovy
+++ b/regression-test/suites/inverted_index_p0/index_compaction/test_index_compaction_dup_keys.groovy
@@ -156,6 +156,7 @@ suite("test_index_compaction_dup_keys", "nonConcurrent") {
sql """ INSERT INTO ${tableName} VALUES (2, "bason", "bason hate pear", 99); """
sql """ INSERT INTO ${tableName} VALUES (3, "andy", "andy love apple", 100); """
sql """ INSERT INTO ${tableName} VALUES (3, "bason", "bason hate pear", 99); """
+ sql """ set enable_common_expr_pushdown = true """
qt_sql """ select * from ${tableName} order by id, name, hobbies, score """
qt_sql """ select * from ${tableName} where name match "andy" order by id, name, hobbies, score """
diff --git a/regression-test/suites/inverted_index_p0/index_compaction/test_index_compaction_null.groovy b/regression-test/suites/inverted_index_p0/index_compaction/test_index_compaction_null.groovy
index 2a0647ecb63..8a77c2dbf7d 100644
--- a/regression-test/suites/inverted_index_p0/index_compaction/test_index_compaction_null.groovy
+++ b/regression-test/suites/inverted_index_p0/index_compaction/test_index_compaction_null.groovy
@@ -308,6 +308,7 @@ suite("test_index_compaction_null", "nonConcurrent") {
"inverted_index_storage_format" = "V1"
)
"""
+ sql """ set enable_common_expr_pushdown = true """
tablets = sql_return_maparray """ show tablets from ${tableName}; """
run_test.call(tablets)
diff --git a/regression-test/suites/inverted_index_p0/index_compaction/test_index_compaction_unique_keys.groovy b/regression-test/suites/inverted_index_p0/index_compaction/test_index_compaction_unique_keys.groovy
index 9d5f3b4cef6..5afd6bada19 100644
--- a/regression-test/suites/inverted_index_p0/index_compaction/test_index_compaction_unique_keys.groovy
+++ b/regression-test/suites/inverted_index_p0/index_compaction/test_index_compaction_unique_keys.groovy
@@ -154,6 +154,7 @@ suite("test_index_compaction_unique_keys", "nonConcurrent") {
"inverted_index_storage_format" = "V1"
);
"""
+ sql """ set enable_common_expr_pushdown = true """
sql """ INSERT INTO ${tableName} VALUES (1, "andy", "andy love apple", 100); """
sql """ INSERT INTO ${tableName} VALUES (1, "bason", "bason hate pear", 99); """
diff --git a/regression-test/suites/inverted_index_p0/index_compaction/test_index_compaction_with_multi_index_segments.groovy b/regression-test/suites/inverted_index_p0/index_compaction/test_index_compaction_with_multi_index_segments.groovy
index 55dfcbfb934..e9cc3300212 100644
--- a/regression-test/suites/inverted_index_p0/index_compaction/test_index_compaction_with_multi_index_segments.groovy
+++ b/regression-test/suites/inverted_index_p0/index_compaction/test_index_compaction_with_multi_index_segments.groovy
@@ -136,6 +136,7 @@ suite("test_index_compaction_with_multi_index_segments", "nonConcurrent") {
// check config
check_config.call("inverted_index_compaction_enable", "true")
check_config.call("inverted_index_max_buffered_docs", "5")
+ sql """ set enable_common_expr_pushdown = true """
/**
* test duplicated tables
diff --git a/regression-test/suites/inverted_index_p0/index_format_v2/test_cumulative_compaction_with_format_v2.groovy b/regression-test/suites/inverted_index_p0/index_format_v2/test_cumulative_compaction_with_format_v2.groovy
index 65270ebe597..003ac3c4c30 100644
--- a/regression-test/suites/inverted_index_p0/index_format_v2/test_cumulative_compaction_with_format_v2.groovy
+++ b/regression-test/suites/inverted_index_p0/index_format_v2/test_cumulative_compaction_with_format_v2.groovy
@@ -155,6 +155,7 @@ suite("test_cumulative_compaction_with_format_v2", "inverted_index_format_v2") {
"""
sql """ sync """
+ sql """ set enable_common_expr_pushdown = true """
qt_select_default """ SELECT * FROM ${tableName} t WHERE city MATCH 'Beijing' ORDER BY user_id,date,city,age,sex,last_visit_date,last_update_date,last_visit_date_not_null,cost,max_dwell_time,min_dwell_time; """
diff --git a/regression-test/suites/inverted_index_p0/index_format_v2/test_drop_column_with_format_v2.groovy b/regression-test/suites/inverted_index_p0/index_format_v2/test_drop_column_with_format_v2.groovy
index 1a75137e1e4..2de9c7fcbcb 100644
--- a/regression-test/suites/inverted_index_p0/index_format_v2/test_drop_column_with_format_v2.groovy
+++ b/regression-test/suites/inverted_index_p0/index_format_v2/test_drop_column_with_format_v2.groovy
@@ -95,6 +95,7 @@ suite("test_drop_column_with_format_v2", "inverted_index_format_v2"){
sql """ INSERT INTO ${tableName} VALUES (2, "bason", 99); """
sql """ INSERT INTO ${tableName} VALUES (3, "andy", 100); """
sql """ INSERT INTO ${tableName} VALUES (3, "bason", 99); """
+ sql """ set enable_common_expr_pushdown = true """
qt_sql "SELECT * FROM $tableName WHERE name match 'andy' order by id, name, score;"
diff --git a/regression-test/suites/inverted_index_p0/index_format_v2/test_drop_index_with_format_v2.groovy b/regression-test/suites/inverted_index_p0/index_format_v2/test_drop_index_with_format_v2.groovy
index 12877099f38..e572535109e 100644
--- a/regression-test/suites/inverted_index_p0/index_format_v2/test_drop_index_with_format_v2.groovy
+++ b/regression-test/suites/inverted_index_p0/index_format_v2/test_drop_index_with_format_v2.groovy
@@ -74,6 +74,7 @@ suite("test_drop_index_with_format_v2", "inverted_index_format_v2"){
sql """ INSERT INTO ${tableName} VALUES (2, "bason", 99); """
sql """ INSERT INTO ${tableName} VALUES (3, "andy", 100); """
sql """ INSERT INTO ${tableName} VALUES (3, "bason", 99); """
+ sql """ set enable_common_expr_pushdown = true """
qt_sql "SELECT * FROM $tableName WHERE name match 'andy' order by id, name, score;"
diff --git a/regression-test/suites/inverted_index_p0/index_format_v2/test_mor_table_with_format_v2.groovy b/regression-test/suites/inverted_index_p0/index_format_v2/test_mor_table_with_format_v2.groovy
index b20148e8bd5..ed19dd75d1f 100644
--- a/regression-test/suites/inverted_index_p0/index_format_v2/test_mor_table_with_format_v2.groovy
+++ b/regression-test/suites/inverted_index_p0/index_format_v2/test_mor_table_with_format_v2.groovy
@@ -155,6 +155,7 @@ suite("test_mor_table_with_format_v2", "inverted_index_format_v2") {
"""
sql """ sync """
+ sql """ set enable_common_expr_pushdown = true """
sql """ DELETE FROM ${tableName} WHERE user_id = 3 """
diff --git a/regression-test/suites/inverted_index_p0/index_format_v2/test_mow_table_with_format_v2.groovy b/regression-test/suites/inverted_index_p0/index_format_v2/test_mow_table_with_format_v2.groovy
index 568990c8b4d..750d5fd2e69 100644
--- a/regression-test/suites/inverted_index_p0/index_format_v2/test_mow_table_with_format_v2.groovy
+++ b/regression-test/suites/inverted_index_p0/index_format_v2/test_mow_table_with_format_v2.groovy
@@ -155,6 +155,7 @@ suite("test_mow_table_with_format_v2", "inverted_index_format_v2") {
"""
sql """ sync """
+ sql """ set enable_common_expr_pushdown = true """
qt_select_default """ SELECT * FROM ${tableName} t WHERE city MATCH 'Beijing' ORDER BY user_id,date,city,age,sex,last_visit_date,last_update_date,last_visit_date_not_null,cost,max_dwell_time,min_dwell_time; """
diff --git a/regression-test/suites/inverted_index_p0/index_format_v2/test_rename_column_with_format_v2.groovy b/regression-test/suites/inverted_index_p0/index_format_v2/test_rename_column_with_format_v2.groovy
index 38b03510a0c..baaff078520 100644
--- a/regression-test/suites/inverted_index_p0/index_format_v2/test_rename_column_with_format_v2.groovy
+++ b/regression-test/suites/inverted_index_p0/index_format_v2/test_rename_column_with_format_v2.groovy
@@ -67,6 +67,7 @@ suite("test_rename_column_with_format_v2", "inverted_index_format_v2"){
sql """ INSERT INTO ${tableName} VALUES (2, "bason", 99); """
sql """ INSERT INTO ${tableName} VALUES (3, "andy", 100); """
sql """ INSERT INTO ${tableName} VALUES (3, "bason", 99); """
+ sql """ set enable_common_expr_pushdown = true """
qt_sql "SELECT * FROM $tableName WHERE name match 'andy' order by id, name, score;"
diff --git a/regression-test/suites/inverted_index_p0/index_format_v2/test_single_replica_compaction_with_format_v2.groovy b/regression-test/suites/inverted_index_p0/index_format_v2/test_single_replica_compaction_with_format_v2.groovy
index 7826702fa7e..25924937a66 100644
--- a/regression-test/suites/inverted_index_p0/index_format_v2/test_single_replica_compaction_with_format_v2.groovy
+++ b/regression-test/suites/inverted_index_p0/index_format_v2/test_single_replica_compaction_with_format_v2.groovy
@@ -159,6 +159,7 @@ suite("test_single_replica_compaction_with_format_v2", "inverted_index_format_v2
"""
sql """ sync """
+ sql """ set enable_common_expr_pushdown = true """
qt_select_default """ SELECT * FROM ${tableName} t WHERE city MATCH 'Beijing' ORDER BY user_id,date,city,age,sex,last_visit_date,last_update_date,last_visit_date_not_null,cost,max_dwell_time,min_dwell_time; """
diff --git a/regression-test/suites/inverted_index_p0/storage_format/test_storage_format_v1.groovy b/regression-test/suites/inverted_index_p0/storage_format/test_storage_format_v1.groovy
index e30dddf54c3..02ebc1b5b12 100644
--- a/regression-test/suites/inverted_index_p0/storage_format/test_storage_format_v1.groovy
+++ b/regression-test/suites/inverted_index_p0/storage_format/test_storage_format_v1.groovy
@@ -98,6 +98,7 @@ suite("test_storage_format_v1", "p0") {
create_httplogs_dup_table.call(testTable_dup)
load_httplogs_data.call(testTable_dup, 'test_httplogs_load_count_on_index', 'true', 'json', 'documents-1000.json')
sql "sync"
+ sql """ set enable_common_expr_pushdown = true """
qt_sql(" select COUNT(*) from ${testTable_dup} where request match 'images' ")
diff --git a/regression-test/suites/inverted_index_p0/storage_format/test_storage_format_v2.groovy b/regression-test/suites/inverted_index_p0/storage_format/test_storage_format_v2.groovy
index 1b4d28e1033..639717d5689 100644
--- a/regression-test/suites/inverted_index_p0/storage_format/test_storage_format_v2.groovy
+++ b/regression-test/suites/inverted_index_p0/storage_format/test_storage_format_v2.groovy
@@ -82,6 +82,7 @@ suite("test_storage_format_v2", "p0, nonConcurrent") {
}
try {
+ sql """ set enable_common_expr_pushdown = true; """
sql "DROP TABLE IF EXISTS ${testTable}"
create_httplogs_dup_table.call(testTable)
diff --git a/regression-test/suites/inverted_index_p0/test_array_contains_with_inverted_index.groovy b/regression-test/suites/inverted_index_p0/test_array_contains_with_inverted_index.groovy
index 0ea18c784d6..3c182d9963d 100644
--- a/regression-test/suites/inverted_index_p0/test_array_contains_with_inverted_index.groovy
+++ b/regression-test/suites/inverted_index_p0/test_array_contains_with_inverted_index.groovy
@@ -63,6 +63,7 @@ suite("test_array_contains_with_inverted_index"){
sql """ INSERT INTO `${indexTblName}`(`apply_date`, `id`, `inventors`) VALUES ('2019-01-01', '0974e7a82e30d1af83205e474fadd0a2', '[\"w\"]'); """
sql """ INSERT INTO `${indexTblName}`(`apply_date`, `id`, `inventors`) VALUES ('2019-01-01', '26823b3995ee38bd145ddd910b2f6300', '[\"x\"]'); """
sql """ INSERT INTO `${indexTblName}`(`apply_date`, `id`, `inventors`) VALUES ('2019-01-01', 'ee27ee1da291e46403c408e220bed6e1', '[\"y\"]'); """
+ sql """ set enable_common_expr_pushdown = true """
qt_sql """ select count() from ${indexTblName}"""
order_qt_sql """ select * from tai where array_contains(inventors, 's') order by id; """
diff --git a/regression-test/suites/inverted_index_p0/test_array_index.groovy b/regression-test/suites/inverted_index_p0/test_array_index.groovy
index 7d10784b420..186738ce258 100644
--- a/regression-test/suites/inverted_index_p0/test_array_index.groovy
+++ b/regression-test/suites/inverted_index_p0/test_array_index.groovy
@@ -60,6 +60,7 @@ suite("test_array_index1"){
"enable_single_replica_compaction" = "false"
);
"""
+ sql """ set enable_common_expr_pushdown = true """
sql """ INSERT INTO `${indexTblName}`(`apply_date`, `id`, `inventors`) VALUES ('2017-01-01', '6afef581285b6608bf80d5a4e46cf839', '[\"a\", \"b\", \"c\"]'); """
sql """ INSERT INTO `${indexTblName}`(`apply_date`, `id`, `inventors`) VALUES ('2017-01-01', 'd93d942d985a8fb7547c72dada8d332d', '[\"d\", \"e\", \"f\", \"g\", \"h\", \"i\", \"j\", \"k\", \"l\"]'); """
diff --git a/regression-test/suites/inverted_index_p0/test_array_with_inverted_index_all_type.groovy b/regression-test/suites/inverted_index_p0/test_array_with_inverted_index_all_type.groovy
index da0df04540e..09663b5c10a 100644
--- a/regression-test/suites/inverted_index_p0/test_array_with_inverted_index_all_type.groovy
+++ b/regression-test/suites/inverted_index_p0/test_array_with_inverted_index_all_type.groovy
@@ -279,6 +279,7 @@ suite("test_array_with_inverted_index_all_type"){
}
// query test
+ sql """ set enable_common_expr_pushdown = true """
for (int i = 0; i < 6; i+=1) {
def indexTblName = indexTblNames[i]
diff --git a/regression-test/suites/inverted_index_p0/test_chinese_analyzer.groovy b/regression-test/suites/inverted_index_p0/test_chinese_analyzer.groovy
index 8278170cd4f..417c829ca80 100644
--- a/regression-test/suites/inverted_index_p0/test_chinese_analyzer.groovy
+++ b/regression-test/suites/inverted_index_p0/test_chinese_analyzer.groovy
@@ -98,6 +98,7 @@ suite("test_chinese_analyzer"){
"replication_allocation" = "tag.location.default: 1"
);
"""
+ sql """ set enable_common_expr_pushdown = true """
sql "INSERT INTO $indexTblName3 VALUES (1, '我来到北京清华大学'), (2, '我爱你中国'), (3, '人民可以得到更多实惠'), (4, '陕西省西安市高新区创业大厦A座,我的手机号码是12345678901,邮箱是12345678@qq.com,,ip是1.1.1.1,this information is created automatically.');"
qt_sql "SELECT * FROM $indexTblName3 WHERE c MATCH_PHRASE '我爱你' ORDER BY id;"
diff --git a/regression-test/suites/inverted_index_p0/test_compound.groovy b/regression-test/suites/inverted_index_p0/test_compound.groovy
index 9b1b8c7dde0..e1f8034114e 100644
--- a/regression-test/suites/inverted_index_p0/test_compound.groovy
+++ b/regression-test/suites/inverted_index_p0/test_compound.groovy
@@ -57,6 +57,7 @@ suite("test_compound", "p0"){
(9, '9', '9', '9'),
(10, '10', '10', '10');
"""
+ sql """ set enable_common_expr_pushdown = true """
qt_sql "SELECT count() FROM $indexTblName WHERE (id >= 2 AND id < 9) and (a match '2' or b match '5' and c match '5');"
qt_sql "SELECT count() FROM $indexTblName WHERE (id >= 2 AND id < 9) and (a match '2' or b match '5' or c match '6');"
diff --git a/regression-test/suites/inverted_index_p0/test_compound_1.groovy b/regression-test/suites/inverted_index_p0/test_compound_1.groovy
index 92dd2f78f0b..a8aca4b526b 100644
--- a/regression-test/suites/inverted_index_p0/test_compound_1.groovy
+++ b/regression-test/suites/inverted_index_p0/test_compound_1.groovy
@@ -80,6 +80,7 @@ suite("test_compound_1", "p0"){
load_httplogs_data.call(indexTbName, 'test_compound_1', 'true', 'json', 'documents-1000.json')
sql "sync"
+ sql """ set enable_common_expr_pushdown = true """
qt_sql """ select count() from ${indexTbName} where (request match_phrase 'english' and clientip match_phrase '4' or request match_phrase 'images'); """
qt_sql """ select count() from ${indexTbName} where (request match_phrase 'hm' and clientip match_phrase '3' or request match_phrase 'gif'); """
diff --git a/regression-test/suites/inverted_index_p0/test_compound_inlist.groovy b/regression-test/suites/inverted_index_p0/test_compound_inlist.groovy
index 855e2c0eec9..d49b1df03c3 100644
--- a/regression-test/suites/inverted_index_p0/test_compound_inlist.groovy
+++ b/regression-test/suites/inverted_index_p0/test_compound_inlist.groovy
@@ -103,6 +103,7 @@ suite("test_compound_inlist", "nonConcurrent"){
load_httplogs_data.call(indexTbName2, 'test_compound_list_2', 'true', 'json', 'documents-1000.json')
sql "sync"
+ sql """ set enable_common_expr_pushdown = true """
qt_sql """ select /*+ SET_VAR(inverted_index_skip_threshold = 0) */ count() from ${indexTbName1} where (((request match_phrase 'images' and clientip match_phrase '3') or (request match_phrase 'english' and clientip match_phrase '4')) and status in (1, 2, 304)); """
qt_sql """ select /*+ SET_VAR(inverted_index_skip_threshold = 0) */ count() from ${indexTbName2} where (((request match_phrase 'images' and clientip match_phrase '3') or (request match_phrase 'english' and clientip match_phrase '4')) and status in (1, 2, 304)); """
diff --git a/regression-test/suites/inverted_index_p0/test_count_on_index.groovy b/regression-test/suites/inverted_index_p0/test_count_on_index.groovy
index 77adae92c93..4197231089a 100644
--- a/regression-test/suites/inverted_index_p0/test_count_on_index.groovy
+++ b/regression-test/suites/inverted_index_p0/test_count_on_index.groovy
@@ -141,6 +141,7 @@ suite("test_count_on_index_httplogs", "p0") {
load_httplogs_data.call(testTable_unique, 'test_httplogs_load_count_on_index', 'true', 'json', 'documents-1000.json')
sql "sync"
+ sql """ set enable_common_expr_pushdown = true """
sql """set experimental_enable_nereids_planner=true;"""
sql """set enable_fallback_to_original_planner=false;"""
sql """analyze table ${testTable_dup} with sync""";
diff --git a/regression-test/suites/inverted_index_p0/test_count_on_index_2.groovy b/regression-test/suites/inverted_index_p0/test_count_on_index_2.groovy
index de94067e2f8..77e5de052b9 100644
--- a/regression-test/suites/inverted_index_p0/test_count_on_index_2.groovy
+++ b/regression-test/suites/inverted_index_p0/test_count_on_index_2.groovy
@@ -153,6 +153,7 @@ suite("test_count_on_index_2", "p0"){
load_httplogs_data.call(indexTbName2, indexTbName2, 'true', 'json', 'documents-1000.json')
sql "sync"
+ sql """ set enable_common_expr_pushdown = true """
qt_sql """ select count() from ${indexTbName1} where `@timestamp` >= 893964736 and `@timestamp` <= 893966453; """
qt_sql """ select count() from ${indexTbName2} where `@timestamp` >= 893964736 and `@timestamp` <= 893966453; """
diff --git a/regression-test/suites/inverted_index_p0/test_delete.groovy b/regression-test/suites/inverted_index_p0/test_delete.groovy
index 3d6100ca4fe..06cd51cc87a 100644
--- a/regression-test/suites/inverted_index_p0/test_delete.groovy
+++ b/regression-test/suites/inverted_index_p0/test_delete.groovy
@@ -47,6 +47,7 @@ suite("test_delete"){
"enable_single_replica_compaction" = "false"
);
"""
+ sql """ set enable_common_expr_pushdown = true """
sql """ INSERT INTO `${indexTblName}`(`a`, `b`, `c`) VALUES ('1', '6afef581285b6608bf80d5a4e46cf839', 'aaa'), ('2', '48a33ec3453a28bce84b8f96fe161956', 'bbb'),
('3', '021603e7dcfe65d44af0efd0e5aee154', 'ccc'), ('4', 'ee27ee1da291e46403c408e220bed6e1', 'ddd'),
diff --git a/regression-test/suites/inverted_index_p0/test_equal_on_fulltext.groovy b/regression-test/suites/inverted_index_p0/test_equal_on_fulltext.groovy
index 6d3a1bd06c8..debb5b07e35 100644
--- a/regression-test/suites/inverted_index_p0/test_equal_on_fulltext.groovy
+++ b/regression-test/suites/inverted_index_p0/test_equal_on_fulltext.groovy
@@ -45,6 +45,7 @@ suite("test_equal_on_fulltext", "p0"){
def var_result = sql "show variables"
logger.info("show variales result: " + var_result )
+ sql """ set enable_common_expr_pushdown = true """
sql "INSERT INTO $indexTblName VALUES (1, 'I am the person'), (2, 'I am a person'), (3, 'I am your person');"
qt_sql "SELECT * FROM $indexTblName WHERE c = 'I am a person' ORDER BY id;"
diff --git a/regression-test/suites/inverted_index_p0/test_index_chinese_column.groovy b/regression-test/suites/inverted_index_p0/test_index_chinese_column.groovy
index 21a94e1ffef..e0221fb67a8 100644
--- a/regression-test/suites/inverted_index_p0/test_index_chinese_column.groovy
+++ b/regression-test/suites/inverted_index_p0/test_index_chinese_column.groovy
@@ -38,6 +38,7 @@ suite("test_index_chinese_column", "inverted_index_select"){
def table_name_v2 = "test_index_chinese_column_v2"
sql "set enable_unicode_name_support=true"
+ sql """ set enable_common_expr_pushdown = true """
createAndInsertData(table_name_v1, "V1")
createAndInsertData(table_name_v2, "V2")
diff --git a/regression-test/suites/inverted_index_p0/test_index_complex_match.groovy b/regression-test/suites/inverted_index_p0/test_index_complex_match.groovy
index 191e147685d..0b77c4aec51 100644
--- a/regression-test/suites/inverted_index_p0/test_index_complex_match.groovy
+++ b/regression-test/suites/inverted_index_p0/test_index_complex_match.groovy
@@ -101,6 +101,7 @@ suite("test_index_complex_match", "p0"){
load_httplogs_data.call(indexTbName2, indexTbName2, 'true', 'json', 'documents-1000.json')
sql "sync"
+ sql """ set enable_common_expr_pushdown = true """
qt_sql """ select count() from ${indexTbName1} where clientip match_phrase '247.37.0.0'; """
qt_sql """ select count() from ${indexTbName1} where clientip match_phrase_prefix '247'; """
diff --git a/regression-test/suites/inverted_index_p0/test_index_delete.groovy b/regression-test/suites/inverted_index_p0/test_index_delete.groovy
index 51d9dd44303..8b9474d937b 100644
--- a/regression-test/suites/inverted_index_p0/test_index_delete.groovy
+++ b/regression-test/suites/inverted_index_p0/test_index_delete.groovy
@@ -49,6 +49,7 @@ suite("test_index_delete", "p0") {
try {
sql "sync"
+ sql """ set enable_common_expr_pushdown = true """
sql """ delete from ${indexTbName1} where a >= 9; """
sql "sync"
diff --git a/regression-test/suites/inverted_index_p0/test_index_empty_string.groovy b/regression-test/suites/inverted_index_p0/test_index_empty_string.groovy
index 2cf1d844d2b..05232ec6bc6 100644
--- a/regression-test/suites/inverted_index_p0/test_index_empty_string.groovy
+++ b/regression-test/suites/inverted_index_p0/test_index_empty_string.groovy
@@ -47,7 +47,7 @@ suite("test_index_empty_string", "p0"){
(1, '', '1'),
(2, '2', '');
"""
-
+ sql """ set enable_common_expr_pushdown = true """
qt_sql "SELECT count() FROM $indexTblName WHERE a match '';"
qt_sql "SELECT count() FROM $indexTblName WHERE b match '';"
}
diff --git a/regression-test/suites/inverted_index_p0/test_index_equal_select.groovy b/regression-test/suites/inverted_index_p0/test_index_equal_select.groovy
index 108e5615e42..de8991e72ec 100644
--- a/regression-test/suites/inverted_index_p0/test_index_equal_select.groovy
+++ b/regression-test/suites/inverted_index_p0/test_index_equal_select.groovy
@@ -54,6 +54,7 @@ suite("test_index_equal_select", "inverted_index_select"){
("san zhang", 10, "grade 5", "2017-10-01", "tall:100cm, weight: 30kg, hobbies:", "", "", "", "", ""),
("li sisi", 11, "grade 6", "2016-10-01", "tall:150cm, weight: 40kg, hobbies: sing, dancing, running", "good at handiwork and beaty", "", "li ba", "li liuliu", "")
"""
+ sql """ set enable_common_expr_pushdown = true """
// case1: test equal
// case1.0: test index coulume equal ‘’
diff --git a/regression-test/suites/inverted_index_p0/test_index_key_match_select.groovy b/regression-test/suites/inverted_index_p0/test_index_key_match_select.groovy
index 90c06155b87..4334a636f70 100644
--- a/regression-test/suites/inverted_index_p0/test_index_key_match_select.groovy
+++ b/regression-test/suites/inverted_index_p0/test_index_key_match_select.groovy
@@ -44,6 +44,7 @@ suite("test_index_key_match_select", "inverted_index_select"){
("u3", ["u1"]),
("u4", ["u3"])
"""
+ sql """ set enable_common_expr_pushdown = true """
qt_sql "SELECT * FROM ${indexTbName1} WHERE user MATCH_ANY 'u1, u2' ORDER BY user LIMIT 10;"
qt_sql "SELECT * FROM ${indexTbName1} WHERE user MATCH_ANY 'u1, u2, u3' ORDER BY user LIMIT 10;"
}
\ No newline at end of file
diff --git a/regression-test/suites/inverted_index_p0/test_index_lowercase_fault_injection.groovy b/regression-test/suites/inverted_index_p0/test_index_lowercase_fault_injection.groovy
index b384814e4b9..51f0eea5d88 100644
--- a/regression-test/suites/inverted_index_p0/test_index_lowercase_fault_injection.groovy
+++ b/regression-test/suites/inverted_index_p0/test_index_lowercase_fault_injection.groovy
@@ -63,6 +63,7 @@ suite("test_index_lowercase_fault_injection", "nonConcurrent") {
sql """ INSERT INTO ${testTable} VALUES (893964653, '232.0.0.0', 'GET /images/hm_bg.jpg HTTP/1.0', 200, 3781); """
sql 'sync'
+ sql """ set enable_common_expr_pushdown = true """
qt_sql """ select count() from ${testTable} where (request match 'HTTP'); """
qt_sql """ select count() from ${testTable} where (request match 'http'); """
diff --git a/regression-test/suites/inverted_index_p0/test_index_match_phrase.groovy b/regression-test/suites/inverted_index_p0/test_index_match_phrase.groovy
index 3cb93061bbb..1199e640848 100644
--- a/regression-test/suites/inverted_index_p0/test_index_match_phrase.groovy
+++ b/regression-test/suites/inverted_index_p0/test_index_match_phrase.groovy
@@ -155,6 +155,7 @@ suite("test_index_match_phrase_select", "inverted_index_select"){
wait_for_build_index_on_partition_finish(indexTbName1, timeout)
}
}
+ sql """ set enable_common_expr_pushdown = true; """
// case1: test match_phrase ""
try {
diff --git a/regression-test/suites/inverted_index_p0/test_index_match_phrase_edge.groovy b/regression-test/suites/inverted_index_p0/test_index_match_phrase_edge.groovy
index 8d4ab3d2320..b7fe5664556 100644
--- a/regression-test/suites/inverted_index_p0/test_index_match_phrase_edge.groovy
+++ b/regression-test/suites/inverted_index_p0/test_index_match_phrase_edge.groovy
@@ -16,7 +16,7 @@
// under the License.
-suite("test_index_match_phrase_edge", "p0"){
+suite("test_index_match_phrase_edge", "nonConcurrent"){
def indexTbName1 = "test_index_match_phrase_edge"
sql "DROP TABLE IF EXISTS ${indexTbName1}"
@@ -56,6 +56,8 @@ suite("test_index_match_phrase_edge", "p0"){
try {
sql "sync"
+ sql """ set enable_common_expr_pushdown = true; """
+ GetDebugPoint().enableDebugPointForAllBEs("VMatchPredicate.execute")
qt_sql """ select * from ${indexTbName1} where b match_phrase_edge 'x.h'; """
qt_sql """ select * from ${indexTbName1} where b match_phrase_edge 'v_i'; """
@@ -75,6 +77,6 @@ suite("test_index_match_phrase_edge", "p0"){
qt_sql """ select count() from ${indexTbName1} where c match_phrase_edge 'b'; """
} finally {
- //try_sql("DROP TABLE IF EXISTS ${testTable}")
+ GetDebugPoint().disableDebugPointForAllBEs("VMatchPredicate.execute")
}
}
\ No newline at end of file
diff --git a/regression-test/suites/inverted_index_p0/test_index_match_phrase_ordered.groovy b/regression-test/suites/inverted_index_p0/test_index_match_phrase_ordered.groovy
index 137bab70f05..a65811d4f65 100644
--- a/regression-test/suites/inverted_index_p0/test_index_match_phrase_ordered.groovy
+++ b/regression-test/suites/inverted_index_p0/test_index_match_phrase_ordered.groovy
@@ -16,7 +16,7 @@
// under the License.
-suite("test_index_match_phrase_ordered", "p0"){
+suite("test_index_match_phrase_ordered", "nonConcurrent"){
def indexTbName1 = "test_index_match_phrase_ordered"
sql "DROP TABLE IF EXISTS ${indexTbName1}"
@@ -49,6 +49,8 @@ suite("test_index_match_phrase_ordered", "p0"){
try {
sql "sync"
+ sql """ set enable_common_expr_pushdown = true; """
+ GetDebugPoint().enableDebugPointForAllBEs("VMatchPredicate.execute")
qt_sql """ select count() from ${indexTbName1} where b match_phrase 'the lazy'; """
qt_sql """ select count() from ${indexTbName1} where b match_phrase 'the lazy ~1'; """
@@ -82,6 +84,6 @@ suite("test_index_match_phrase_ordered", "p0"){
qt_sql """ select count() from ${indexTbName1} where b match_phrase 'the quick ~6'; """
qt_sql """ select count() from ${indexTbName1} where b match_phrase 'the quick ~6+'; """
} finally {
- //try_sql("DROP TABLE IF EXISTS ${testTable}")
+ GetDebugPoint().disableDebugPointForAllBEs("VMatchPredicate.execute")
}
}
\ No newline at end of file
diff --git a/regression-test/suites/inverted_index_p0/test_index_match_phrase_prefix.groovy b/regression-test/suites/inverted_index_p0/test_index_match_phrase_prefix.groovy
index 1f83d48a977..3906065e8d3 100644
--- a/regression-test/suites/inverted_index_p0/test_index_match_phrase_prefix.groovy
+++ b/regression-test/suites/inverted_index_p0/test_index_match_phrase_prefix.groovy
@@ -16,7 +16,7 @@
// under the License.
-suite("test_index_match_phrase_prefix", "p0"){
+suite("test_index_match_phrase_prefix", "nonConcurrent"){
def indexTbName1 = "test_index_match_phrase_prefix"
def indexTbName2 = "test_index_match_phrase_prefix2"
@@ -98,28 +98,32 @@ suite("test_index_match_phrase_prefix", "p0"){
load_httplogs_data.call(indexTbName2, indexTbName2, 'true', 'json', 'documents-1000.json')
sql "sync"
-
+ sql """ set enable_common_expr_pushdown = true; """
+ GetDebugPoint().enableDebugPointForAllBEs("VMatchPredicate.execute")
qt_sql """ select count() from ${indexTbName1} where request match_phrase_prefix 'ima'; """
+ qt_sql """ select count() from ${indexTbName1} where request match_phrase_prefix 'images/h'; """
+ qt_sql """ select count() from ${indexTbName1} where request match_phrase_prefix 'images/hm'; """
+ qt_sql """ select count() from ${indexTbName1} where request match_phrase_prefix '/french/images/n'; """
+ qt_sql """ select count() from ${indexTbName1} where request match_phrase_prefix '/french/tickets/images/ti'; """
+ GetDebugPoint().disableDebugPointForAllBEs("VMatchPredicate.execute")
+
qt_sql """ select count() from ${indexTbName2} where request match_phrase_prefix 'ima'; """
qt_sql """ select count() from ${indexTbName1} where request like '%ima%'; """
- qt_sql """ select count() from ${indexTbName1} where request match_phrase_prefix 'images/h'; """
qt_sql """ select count() from ${indexTbName2} where request match_phrase_prefix 'images/h'; """
qt_sql """ select count() from ${indexTbName1} where request like '%images/h%'; """
- qt_sql """ select count() from ${indexTbName1} where request match_phrase_prefix 'images/hm'; """
qt_sql """ select count() from ${indexTbName2} where request match_phrase_prefix 'images/hm'; """
qt_sql """ select count() from ${indexTbName1} where request like '%images/hm%'; """
- qt_sql """ select count() from ${indexTbName1} where request match_phrase_prefix '/french/images/n'; """
+
qt_sql """ select count() from ${indexTbName2} where request match_phrase_prefix '/french/images/n'; """
qt_sql """ select count() from ${indexTbName1} where request like '%/french/images/n%'; """
- qt_sql """ select count() from ${indexTbName1} where request match_phrase_prefix '/french/tickets/images/ti'; """
qt_sql """ select count() from ${indexTbName2} where request match_phrase_prefix '/french/tickets/images/ti'; """
qt_sql """ select count() from ${indexTbName1} where request like '%/french/tickets/images/ti%'; """
} finally {
- //try_sql("DROP TABLE IF EXISTS ${testTable}")
+ GetDebugPoint().disableDebugPointForAllBEs("VMatchPredicate.execute")
}
}
\ No newline at end of file
diff --git a/regression-test/suites/inverted_index_p0/test_index_match_phrase_prefix_1.groovy b/regression-test/suites/inverted_index_p0/test_index_match_phrase_prefix_1.groovy
index 1e2ac0d7900..f42462f12a6 100644
--- a/regression-test/suites/inverted_index_p0/test_index_match_phrase_prefix_1.groovy
+++ b/regression-test/suites/inverted_index_p0/test_index_match_phrase_prefix_1.groovy
@@ -16,7 +16,7 @@
// under the License.
-suite("test_index_match_phrase_prefix_1", "p0"){
+suite("test_index_match_phrase_prefix_1", "nonConcurrent"){
def indexTbName1 = "test_index_match_phrase_prefix_1"
sql "DROP TABLE IF EXISTS ${indexTbName1}"
@@ -49,6 +49,8 @@ suite("test_index_match_phrase_prefix_1", "p0"){
try {
sql "sync"
+ sql """ set enable_common_expr_pushdown = true; """
+ GetDebugPoint().enableDebugPointForAllBEs("VMatchPredicate.execute")
qt_sql """ select count() from ${indexTbName1} where c match_phrase_prefix 'O1704361998540E2Cemx9S'; """
qt_sql """ select count() from ${indexTbName1} where d match_phrase_prefix 'O1704361998540E2Cemx9S'; """
@@ -57,6 +59,6 @@ suite("test_index_match_phrase_prefix_1", "p0"){
qt_sql """ select count() from ${indexTbName1} where d match_phrase_prefix 'O1704361998540E2Cemx9S=123456789'; """
} finally {
- //try_sql("DROP TABLE IF EXISTS ${testTable}")
+ GetDebugPoint().disableDebugPointForAllBEs("VMatchPredicate.execute")
}
}
\ No newline at end of file
diff --git a/regression-test/suites/inverted_index_p0/test_index_match_phrase_slop.groovy b/regression-test/suites/inverted_index_p0/test_index_match_phrase_slop.groovy
index a8454878e61..5f772e0e7a4 100644
--- a/regression-test/suites/inverted_index_p0/test_index_match_phrase_slop.groovy
+++ b/regression-test/suites/inverted_index_p0/test_index_match_phrase_slop.groovy
@@ -16,7 +16,7 @@
// under the License.
-suite("test_index_match_phrase_slop", "p0"){
+suite("test_index_match_phrase_slop", "nonConcurrent"){
def indexTbName1 = "test_index_match_phrase_slop"
sql "DROP TABLE IF EXISTS ${indexTbName1}"
@@ -82,6 +82,8 @@ suite("test_index_match_phrase_slop", "p0"){
sql """ INSERT INTO ${indexTbName1} VALUES (1, "127.0.0.1", "I'm glad I kept my fingers crossed ~4", 1, 1); """
sql "sync"
+ sql """ set enable_common_expr_pushdown = true; """
+ GetDebugPoint().enableDebugPointForAllBEs("VMatchPredicate.execute")
qt_sql """ select count() from ${indexTbName1} where request match_phrase 'get jpg'; """
qt_sql """ select count() from ${indexTbName1} where request match_phrase 'get jpg ~2'; """
@@ -117,6 +119,6 @@ suite("test_index_match_phrase_slop", "p0"){
qt_sql """ select * from ${indexTbName1} where request match_phrase 'glad crossed \\~4'; """
} finally {
- //try_sql("DROP TABLE IF EXISTS ${testTable}")
+ GetDebugPoint().disableDebugPointForAllBEs("VMatchPredicate.execute")
}
}
\ No newline at end of file
diff --git a/regression-test/suites/inverted_index_p0/test_index_match_regexp.groovy b/regression-test/suites/inverted_index_p0/test_index_match_regexp.groovy
index 31863432707..49f0f563989 100644
--- a/regression-test/suites/inverted_index_p0/test_index_match_regexp.groovy
+++ b/regression-test/suites/inverted_index_p0/test_index_match_regexp.groovy
@@ -16,7 +16,7 @@
// under the License.
-suite("test_index_match_regexp", "p0"){
+suite("test_index_match_regexp", "nonConcurrent"){
def indexTbName1 = "test_index_match_regexp"
sql "DROP TABLE IF EXISTS ${indexTbName1}"
@@ -79,6 +79,8 @@ suite("test_index_match_regexp", "p0"){
load_httplogs_data.call(indexTbName1, 'test_index_match_regexp', 'true', 'json', 'documents-1000.json')
sql "sync"
+ sql """ set enable_common_expr_pushdown = true; """
+ GetDebugPoint().enableDebugPointForAllBEs("VMatchPredicate.execute")
qt_sql """ select count() from test_index_match_regexp where request match_regexp ''; """
qt_sql """ select count() from test_index_match_regexp where request match_regexp '^h'; """
@@ -89,6 +91,6 @@ suite("test_index_match_regexp", "p0"){
qt_sql """ select count() from test_index_match_regexp where request match_regexp 'nonexistence'; """
} finally {
- //try_sql("DROP TABLE IF EXISTS ${testTable}")
+ GetDebugPoint().disableDebugPointForAllBEs("VMatchPredicate.execute")
}
}
\ No newline at end of file
diff --git a/regression-test/suites/inverted_index_p0/test_index_match_select.groovy b/regression-test/suites/inverted_index_p0/test_index_match_select.groovy
index 42792bece60..c5cfa69fefe 100644
--- a/regression-test/suites/inverted_index_p0/test_index_match_select.groovy
+++ b/regression-test/suites/inverted_index_p0/test_index_match_select.groovy
@@ -154,6 +154,7 @@ suite("test_index_match_select", "inverted_index_select"){
wait_for_build_index_on_partition_finish(indexTbName1, timeout)
}
}
+ sql """ set enable_common_expr_pushdown = true; """
// case1: match term
// case1.0 test match ""
diff --git a/regression-test/suites/inverted_index_p0/test_index_multi_match.groovy b/regression-test/suites/inverted_index_p0/test_index_multi_match.groovy
index c926bc4d510..884fbaffa62 100644
--- a/regression-test/suites/inverted_index_p0/test_index_multi_match.groovy
+++ b/regression-test/suites/inverted_index_p0/test_index_multi_match.groovy
@@ -126,4 +126,4 @@ suite("test_index_multi_match", "p0"){
} finally {
//try_sql("DROP TABLE IF EXISTS ${testTable}")
}
-}
\ No newline at end of file
+}
diff --git a/regression-test/suites/inverted_index_p0/test_index_no_need_read_data.groovy b/regression-test/suites/inverted_index_p0/test_index_no_need_read_data.groovy
index fd871b0a000..924fffe54d7 100644
--- a/regression-test/suites/inverted_index_p0/test_index_no_need_read_data.groovy
+++ b/regression-test/suites/inverted_index_p0/test_index_no_need_read_data.groovy
@@ -54,6 +54,7 @@ suite("test_index_no_need_read_data", "inverted_index_select"){
// case1: enable nereids planner
sql "set enable_nereids_planner = true"
+ sql """ set enable_common_expr_pushdown = true; """
qt_select_nereids_0 "SELECT * FROM ${table1} ORDER BY id"
qt_select_nereids_1 "SELECT count() FROM ${table1} WHERE n > 100"
diff --git a/regression-test/suites/inverted_index_p0/test_index_null.groovy b/regression-test/suites/inverted_index_p0/test_index_null.groovy
index 9d237d0455d..82cf9a3f95f 100644
--- a/regression-test/suites/inverted_index_p0/test_index_null.groovy
+++ b/regression-test/suites/inverted_index_p0/test_index_null.groovy
@@ -42,7 +42,7 @@ suite("test__null_index", "inverted_index"){
"replication_allocation" = "tag.location.default: 1"
);
"""
-
+ sql """ set enable_common_expr_pushdown = true; """
sql "INSERT INTO $indexTblName VALUES (1, []), (2, []), (3, []);"
qt_sql "SELECT * FROM $indexTblName WHERE value match_all 'a';"
}
diff --git a/regression-test/suites/inverted_index_p0/test_index_range_between_select.groovy b/regression-test/suites/inverted_index_p0/test_index_range_between_select.groovy
index c93191973cf..5401c9e410a 100644
--- a/regression-test/suites/inverted_index_p0/test_index_range_between_select.groovy
+++ b/regression-test/suites/inverted_index_p0/test_index_range_between_select.groovy
@@ -117,6 +117,7 @@ suite("test_index_range_between_select", "inverted_index_select"){
"""
wait_for_latest_op_on_table_finish(indexTbName1, timeout)
}
+ sql """ set enable_common_expr_pushdown = true; """
// case1: test simple between case
// case1.0: test data index colume select in specific between condition
diff --git a/regression-test/suites/inverted_index_p0/test_index_range_bigger_and_equal_select.groovy b/regression-test/suites/inverted_index_p0/test_index_range_bigger_and_equal_select.groovy
index e0e3ee949d9..517caaea651 100644
--- a/regression-test/suites/inverted_index_p0/test_index_range_bigger_and_equal_select.groovy
+++ b/regression-test/suites/inverted_index_p0/test_index_range_bigger_and_equal_select.groovy
@@ -54,7 +54,7 @@ suite("test_index_range_bigger_and_equal_select", "inverted_index_select"){
("san zhang", 10, "grade 5", "2017-10-01", "tall:100cm, weight: 30kg, hobbies:", "", "", "", "", ""),
("li sisi", 11, "grade 6", "2016-10-01", "tall:150cm, weight: 40kg, hobbies: sing, dancing, running", "good at handiwork and beaty", "", "li ba", "li liuliu", "")
"""
-
+ sql """ set enable_common_expr_pushdown = true; """
// case1. test >=
// case1.0: test only >=
qt_sql "select * from ${indexTbName1} where name>='' order by name "
diff --git a/regression-test/suites/inverted_index_p0/test_index_range_bigger_select.groovy b/regression-test/suites/inverted_index_p0/test_index_range_bigger_select.groovy
index d1d29d2bd75..937d24ba2d1 100644
--- a/regression-test/suites/inverted_index_p0/test_index_range_bigger_select.groovy
+++ b/regression-test/suites/inverted_index_p0/test_index_range_bigger_select.groovy
@@ -54,7 +54,7 @@ suite("test_index_range_bigger_select", "inverted_index_select"){
("san zhang", 10, "grade 5", "2017-10-01", "tall:100cm, weight: 30kg, hobbies:", "", "", "", "", ""),
("li sisi", 11, "grade 6", "2016-10-01", "tall:150cm, weight: 40kg, hobbies: sing, dancing, running", "good at handiwork and beaty", "", "li ba", "li liuliu", "")
"""
-
+ sql """ set enable_common_expr_pushdown = true; """
// case1. test >
// case1.0: test only >
qt_sql "select * from ${indexTbName1} where name>'' order by name "
diff --git a/regression-test/suites/inverted_index_p0/test_index_range_in_select.groovy b/regression-test/suites/inverted_index_p0/test_index_range_in_select.groovy
index 8b5fb4cd392..432151a9a28 100644
--- a/regression-test/suites/inverted_index_p0/test_index_range_in_select.groovy
+++ b/regression-test/suites/inverted_index_p0/test_index_range_in_select.groovy
@@ -153,6 +153,7 @@ suite("test_index_range_in_select", "inverted_index_select"){
wait_for_build_index_on_partition_finish(indexTbName1, timeout)
}
}
+ sql """ set enable_common_expr_pushdown = true; """
// case1: select in
// case1.0: select in specific condition
diff --git a/regression-test/suites/inverted_index_p0/test_index_range_not_in_select.groovy b/regression-test/suites/inverted_index_p0/test_index_range_not_in_select.groovy
index 7e846733158..fd330c78b01 100644
--- a/regression-test/suites/inverted_index_p0/test_index_range_not_in_select.groovy
+++ b/regression-test/suites/inverted_index_p0/test_index_range_not_in_select.groovy
@@ -111,6 +111,7 @@ suite("test_index_range_not_in_select", "inverted_index_select"){
}
assertTrue(useTime <= OpTimeout, "wait_for_latest_build_index_on_partition_finish timeout")
}
+ sql """ set enable_common_expr_pushdown = true; """
for (int i = 0; i < 2; i++) {
logger.info("select table with index times " + i)
diff --git a/regression-test/suites/inverted_index_p0/test_index_range_smaller_and_equal_select.groovy b/regression-test/suites/inverted_index_p0/test_index_range_smaller_and_equal_select.groovy
index 0c5cd61ee69..4cc3ca1ab62 100644
--- a/regression-test/suites/inverted_index_p0/test_index_range_smaller_and_equal_select.groovy
+++ b/regression-test/suites/inverted_index_p0/test_index_range_smaller_and_equal_select.groovy
@@ -54,7 +54,7 @@ suite("test_index_range_smaller_and_equal_select", "inverted_index_select"){
("san zhang", 10, "grade 5", "2017-10-01", "tall:100cm, weight: 30kg, hobbies:", "", "", "", "", ""),
("li sisi", 11, "grade 6", "2016-10-01", "tall:150cm, weight: 40kg, hobbies: sing, dancing, running", "good at handiwork and beaty", "", "li ba", "li liuliu", "")
"""
-
+ sql """ set enable_common_expr_pushdown = true; """
// case1. test <=
// case1.0: test only <=
qt_sql "select * from ${indexTbName1} where name<='' order by name"
diff --git a/regression-test/suites/inverted_index_p0/test_index_range_smaller_select.groovy b/regression-test/suites/inverted_index_p0/test_index_range_smaller_select.groovy
index 83d2220c056..cf03e7c8caf 100644
--- a/regression-test/suites/inverted_index_p0/test_index_range_smaller_select.groovy
+++ b/regression-test/suites/inverted_index_p0/test_index_range_smaller_select.groovy
@@ -54,7 +54,7 @@ suite("test_index_range_smaller_select", "inverted_index_select"){
("san zhang", 10, "grade 5", "2017-10-01", "tall:100cm, weight: 30kg, hobbies:", "", "", "", "", ""),
("li sisi", 11, "grade 6", "2016-10-01", "tall:150cm, weight: 40kg, hobbies: sing, dancing, running", "good at handiwork and beaty", "", "li ba", "li liuliu", "")
"""
-
+ sql """ set enable_common_expr_pushdown = true; """
// case1. test <
// case1.0: test only <
sql "select * from ${indexTbName1} where name<'' order by name "
diff --git a/regression-test/suites/inverted_index_p0/test_index_rqg_bug.groovy b/regression-test/suites/inverted_index_p0/test_index_rqg_bug.groovy
index cc561782667..02762e57983 100644
--- a/regression-test/suites/inverted_index_p0/test_index_rqg_bug.groovy
+++ b/regression-test/suites/inverted_index_p0/test_index_rqg_bug.groovy
@@ -142,7 +142,7 @@ suite("test_index_rqg_bug", "test_index_rqg_bug"){
(48, -10, 7, 3, 4, -1290467110130692882, NULL, -5421887030808227301, 2147894047624029750, '2023-12-20', '2026-02-18', '2023-12-10', '2024-02-18', 'v', 'f', 'u', 'z', 'w', 'l', 'i', 'b'),
(49, 4, -10, -10, -4, 7177870619817484302, 2010854013707344984, 515636226818986547, -4617727694631456148, '2023-12-14', '2024-01-09', '2023-12-11', '2024-01-08', 'k', 'o', 'r', 'h', 'x', 'v', 'm', 'r');
"""
-
+ sql """ set enable_common_expr_pushdown = true; """
qt_select_bug_1 """
SELECT
MIN(DISTINCT table1.col_date_undef_signed_not_null) AS field1,
diff --git a/regression-test/suites/inverted_index_p0/test_index_rqg_bug2.groovy b/regression-test/suites/inverted_index_p0/test_index_rqg_bug2.groovy
index faede0bc3c1..e1411a70437 100644
--- a/regression-test/suites/inverted_index_p0/test_index_rqg_bug2.groovy
+++ b/regression-test/suites/inverted_index_p0/test_index_rqg_bug2.groovy
@@ -82,7 +82,7 @@ suite("test_index_rqg_bug2", "test_index_rqg_bug"){
sql """
INSERT INTO ${table1}(pk,col_int_undef_signed,col_int_undef_signed_index_inverted,col_int_undef_signed_not_null,col_int_undef_signed_not_null_index_inverted,col_bigint_undef_signed,col_bigint_undef_signed_index_inverted,col_bigint_undef_signed_not_null,col_bigint_undef_signed_not_null_index_inverted,col_date_undef_signed,col_date_undef_signed_index_inverted,col_date_undef_signed_not_null,col_date_undef_signed_not_null_index_inverted,col_varchar_10__undef_signed,col_varchar_10__undef_ [...]
"""
-
+ sql """ set enable_common_expr_pushdown = true; """
qt_select_bug_2 """
SELECT
table1.col_date_undef_signed_not_null_index_inverted,
diff --git a/regression-test/suites/inverted_index_p0/test_index_rqg_bug3.groovy b/regression-test/suites/inverted_index_p0/test_index_rqg_bug3.groovy
index eb49100effd..8fa4cdc4b80 100644
--- a/regression-test/suites/inverted_index_p0/test_index_rqg_bug3.groovy
+++ b/regression-test/suites/inverted_index_p0/test_index_rqg_bug3.groovy
@@ -63,7 +63,7 @@ suite("test_index_rqg_bug3", "test_index_rqg_bug3"){
sql """
insert into ${table1}(pk,col_int_undef_signed,col_int_undef_signed_index_inverted,col_int_undef_signed_not_null,col_int_undef_signed_not_null_index_inverted,col_bigint_undef_signed,col_bigint_undef_signed_index_inverted,col_bigint_undef_signed_not_null,col_bigint_undef_signed_not_null_index_inverted,col_date_undef_signed,col_date_undef_signed_index_inverted,col_date_undef_signed_not_null,col_date_undef_signed_not_null_index_inverted,col_varchar_10__undef_signed,col_varchar_10__undef_ [...]
"""
-
+ sql """ set enable_common_expr_pushdown = true; """
qt_select_bug_1 """
SELECT col_int_undef_signed_not_null, col_date_undef_signed_not_null
FROM ${table1} AS table1
diff --git a/regression-test/suites/inverted_index_p0/test_index_rqg_bug4.groovy b/regression-test/suites/inverted_index_p0/test_index_rqg_bug4.groovy
index 9353616f95f..b29532c12c3 100644
--- a/regression-test/suites/inverted_index_p0/test_index_rqg_bug4.groovy
+++ b/regression-test/suites/inverted_index_p0/test_index_rqg_bug4.groovy
@@ -126,6 +126,7 @@ suite("test_index_rqg_bug4", "test_index_rqg_bug"){
try {
sql "sync"
+ sql """ set enable_common_expr_pushdown = true; """
qt_sql """
select
diff --git a/regression-test/suites/inverted_index_p0/test_index_skip_read_data.groovy b/regression-test/suites/inverted_index_p0/test_index_skip_read_data.groovy
index 70213910934..cb3bbe65e2c 100644
--- a/regression-test/suites/inverted_index_p0/test_index_skip_read_data.groovy
+++ b/regression-test/suites/inverted_index_p0/test_index_skip_read_data.groovy
@@ -21,7 +21,7 @@ suite("test_index_skip_read_data", "p0"){
def indexTbName2 = "test_index_skip_read_data_mow"
def indexTbName3 = "test_index_skip_read_data_mor"
-
+ sql """ set enable_common_expr_pushdown = true; """
// dup
sql "DROP TABLE IF EXISTS ${indexTbName1}"
diff --git a/regression-test/suites/inverted_index_p0/test_inverted_index.groovy b/regression-test/suites/inverted_index_p0/test_inverted_index.groovy
index 280782f75c5..ff719eed032 100644
--- a/regression-test/suites/inverted_index_p0/test_inverted_index.groovy
+++ b/regression-test/suites/inverted_index_p0/test_inverted_index.groovy
@@ -21,6 +21,7 @@ suite("test_inverted_index", "inverted_index") {
def jobStateResult = sql """ SHOW ALTER TABLE COLUMN WHERE TableName='${tableName}' ORDER BY createtime DESC LIMIT 1 """
return jobStateResult[0][9]
}
+ sql """ set enable_common_expr_pushdown = true; """
sql "DROP TABLE IF EXISTS ${tbName1}"
sql """
CREATE TABLE IF NOT EXISTS ${tbName1} (
diff --git a/regression-test/suites/inverted_index_p0/test_inverted_index_keyword.groovy b/regression-test/suites/inverted_index_p0/test_inverted_index_keyword.groovy
index 1663de8e7c1..fbc584d7dd4 100644
--- a/regression-test/suites/inverted_index_p0/test_inverted_index_keyword.groovy
+++ b/regression-test/suites/inverted_index_p0/test_inverted_index_keyword.groovy
@@ -68,7 +68,7 @@ suite("test_inverted_index_keyword"){
(3, '我在北京市'),
(3, '我在西安市')
"""
-
+ sql """ set enable_common_expr_pushdown = true; """
qt_sql "SELECT * FROM ${indexTblName} where c match '330204195805121025'";
qt_sql "SELECT * FROM ${indexTblName} where c match '36'";
qt_sql "SELECT * FROM ${indexTblName} where c match '330225197806187713'";
diff --git a/regression-test/suites/inverted_index_p0/test_inverted_index_mor.groovy b/regression-test/suites/inverted_index_p0/test_inverted_index_mor.groovy
index 1905067d433..0f9ca2f31e8 100644
--- a/regression-test/suites/inverted_index_p0/test_inverted_index_mor.groovy
+++ b/regression-test/suites/inverted_index_p0/test_inverted_index_mor.groovy
@@ -48,7 +48,7 @@ suite("test_inverted_index_mor", "p0"){
sql """ INSERT INTO $indexTblName VALUES (1, 2, 12, 1.2, '1 2'), (3, 4, 34, 3.4, '3 4'); """
sql """ INSERT INTO $indexTblName VALUES (11, 12, 1112, 11.12, '11 22'), (13, 14, 1314, 13.14, '13 14'); """
-
+ sql """ set enable_common_expr_pushdown = true; """
// original data
qt_11 """ SELECT * FROM $indexTblName ORDER BY k1,k2 """
diff --git a/regression-test/suites/inverted_index_p0/test_inverted_index_null.groovy b/regression-test/suites/inverted_index_p0/test_inverted_index_null.groovy
index 43cf22d5720..6dac5d3e447 100644
--- a/regression-test/suites/inverted_index_p0/test_inverted_index_null.groovy
+++ b/regression-test/suites/inverted_index_p0/test_inverted_index_null.groovy
@@ -53,6 +53,7 @@ suite("test_inverted_index_null") {
(7,'tengxun','qie','addr gg','lj',null),
(8,'tengxun2','qie',null,'lj',800)
"""
+ sql """ set enable_common_expr_pushdown = true """
// select all data
qt_select_0 "SELECT * FROM ${table1} ORDER BY id"
diff --git a/regression-test/suites/inverted_index_p0/test_inverted_index_null_ram_dir.groovy b/regression-test/suites/inverted_index_p0/test_inverted_index_null_ram_dir.groovy
index 6059db20628..784c2316416 100644
--- a/regression-test/suites/inverted_index_p0/test_inverted_index_null_ram_dir.groovy
+++ b/regression-test/suites/inverted_index_p0/test_inverted_index_null_ram_dir.groovy
@@ -105,6 +105,7 @@ suite("test_inverted_index_null_ram_dir") {
(7,'tengxun','qie','addr gg','lj',null),
(8,'tengxun2','qie',null,'lj',800)
"""
+ sql """ set enable_common_expr_pushdown = true """
// select all data
qt_select_0 "SELECT * FROM ${tableName} ORDER BY id"
diff --git a/regression-test/suites/inverted_index_p0/test_inverted_index_v2_file_size.groovy b/regression-test/suites/inverted_index_p0/test_inverted_index_v2_file_size.groovy
index 1484b7284a3..5e22a7ae892 100644
--- a/regression-test/suites/inverted_index_p0/test_inverted_index_v2_file_size.groovy
+++ b/regression-test/suites/inverted_index_p0/test_inverted_index_v2_file_size.groovy
@@ -122,6 +122,7 @@ suite("test_index_index_V2_file_size", "nonConcurrent") {
//TabletId,ReplicaId,BackendId,SchemaHash,Version,LstSuccessVersion,LstFailedVersion,LstFailedTime,LocalDataSize,RemoteDataSize,RowCount,State,LstConsistencyCheckTime,CheckVersion,VersionCount,PathHash,MetaUrl,CompactionStatus
def tablets = sql_return_maparray """ show tablets from ${tableName}; """
+ sql """ set enable_common_expr_pushdown = true """
sql """ INSERT INTO ${tableName} VALUES (1, "andy", "andy love apple", 100); """
sql """ INSERT INTO ${tableName} VALUES (1, "bason", "bason hate pear", 99); """
diff --git a/regression-test/suites/inverted_index_p0/test_lowercase.groovy b/regression-test/suites/inverted_index_p0/test_lowercase.groovy
index 0670e05594a..3dacec72f4c 100644
--- a/regression-test/suites/inverted_index_p0/test_lowercase.groovy
+++ b/regression-test/suites/inverted_index_p0/test_lowercase.groovy
@@ -56,6 +56,7 @@ suite("test_lowercase"){
"replication_allocation" = "tag.location.default: 1"
);
"""
+ sql """ set enable_common_expr_pushdown = true """
sql "INSERT INTO $indexTblName2 VALUES (1, 'hello 我来到北京清华大学'), (2, 'HELLO 我爱你中国'), (3, 'Hello 人民可以得到更多实惠');"
qt_sql "SELECT * FROM $indexTblName2 WHERE c MATCH 'hello' ORDER BY id";
diff --git a/regression-test/suites/inverted_index_p0/test_match_query_without_index.groovy b/regression-test/suites/inverted_index_p0/test_match_query_without_index.groovy
index 3d255f2762e..61a564c51d8 100644
--- a/regression-test/suites/inverted_index_p0/test_match_query_without_index.groovy
+++ b/regression-test/suites/inverted_index_p0/test_match_query_without_index.groovy
@@ -59,7 +59,7 @@ suite("test_match_query_without_index", "inverted_index_select"){
("san zhang", "grade 5", "", "", "", 10, "2017-10-01", "tall:100cm, weight: 30kg, hobbies:", "", ""),
("li sisi", "grade 6", "li ba", "li liuliu", "", 11, "2016-10-01", "tall:150cm, weight: 40kg, hobbies: sing, dancing, running", "good at handiwork and beaty", "")
"""
-
+ sql """ set enable_common_expr_pushdown = true """
// case1: match any
try {
sql """ select * from ${indexTbName1} where ${varchar_colume1} match_any "" order by name; """
diff --git a/regression-test/suites/inverted_index_p0/test_match_without_index.groovy b/regression-test/suites/inverted_index_p0/test_match_without_index.groovy
index 94cee179ed2..a008cf703d8 100644
--- a/regression-test/suites/inverted_index_p0/test_match_without_index.groovy
+++ b/regression-test/suites/inverted_index_p0/test_match_without_index.groovy
@@ -39,6 +39,7 @@ suite("test_match_without_index", "p0") {
"replication_allocation" = "tag.location.default: 1"
);
"""
+ sql """ set enable_common_expr_pushdown = true """
sql """ INSERT INTO ${testTable} VALUES (123, '17.0.0.0', 'HTTP GET', '200', 20); """
sql """ INSERT INTO ${testTable} VALUES (123, '17.0.0.0', 'Life is like a box of chocolates, you never know what you are going to get.', '200', 20); """
diff --git a/regression-test/suites/inverted_index_p0/test_need_read_data.groovy b/regression-test/suites/inverted_index_p0/test_need_read_data.groovy
index 321c95fe32f..f66b92ae66c 100644
--- a/regression-test/suites/inverted_index_p0/test_need_read_data.groovy
+++ b/regression-test/suites/inverted_index_p0/test_need_read_data.groovy
@@ -73,6 +73,7 @@ suite("test_need_read_data", "p0"){
sql """ insert into ${indexTbName1}(pk,col_int_undef_signed,col_int_undef_signed_index_inverted,col_int_undef_signed_not_null,col_int_undef_signed_not_null_index_inverted,col_bigint_undef_signed,col_bigint_undef_signed_index_inverted,col_bigint_undef_signed_not_null,col_bigint_undef_signed_not_null_index_inverted,col_date_undef_signed,col_date_undef_signed_index_inverted,col_date_undef_signed_not_null,col_date_undef_signed_not_null_index_inverted,col_varchar_10__undef_signed,col_ [...]
sql "sync"
+ sql """ set enable_common_expr_pushdown = true """
qt_sql """ SELECT COUNT( *) AS field1, col_int_undef_signed AS field2 FROM ${indexTbName1} WHERE( col_date_undef_signed_not_null_index_inverted == '2024-01-01' OR day( col_date_undef_signed_not_null_index_inverted ) !=0 ) GROUP BY field2 ORDER BY field2; """
diff --git a/regression-test/suites/inverted_index_p0/test_no_index_match.groovy b/regression-test/suites/inverted_index_p0/test_no_index_match.groovy
index 7947844565c..7cace77da7e 100644
--- a/regression-test/suites/inverted_index_p0/test_no_index_match.groovy
+++ b/regression-test/suites/inverted_index_p0/test_no_index_match.groovy
@@ -84,6 +84,7 @@ suite("test_no_index_match", "p0") {
sql """ INSERT INTO ${testTable} VALUES (1, '1', '', 1, 1); """
sql 'sync'
+ sql """ set enable_common_expr_pushdown = true """
try {
qt_sql """ select count() from ${testTable} where (request match_any 'hm bg'); """
diff --git a/regression-test/suites/inverted_index_p0/test_null_index.groovy b/regression-test/suites/inverted_index_p0/test_null_index.groovy
index 797200ab010..61b613470ee 100644
--- a/regression-test/suites/inverted_index_p0/test_null_index.groovy
+++ b/regression-test/suites/inverted_index_p0/test_null_index.groovy
@@ -44,7 +44,7 @@ suite("test_null_index", "p0"){
"replication_allocation" = "tag.location.default: 1"
);
"""
-
+ sql """ set enable_common_expr_pushdown = true """
sql "INSERT INTO $indexTblName VALUES (1, 'a', null, [null], [1]), (2, 'b', 'b', ['b'], [2]), (3, 'c', 'c', ['c'], [3]);"
qt_sql "SELECT * FROM $indexTblName WHERE str match null order by id;"
qt_sql "SELECT * FROM $indexTblName WHERE str_null match null order by id;"
diff --git a/regression-test/suites/inverted_index_p0/test_or_not_match.groovy b/regression-test/suites/inverted_index_p0/test_or_not_match.groovy
index 95af26480c9..488639aae6e 100644
--- a/regression-test/suites/inverted_index_p0/test_or_not_match.groovy
+++ b/regression-test/suites/inverted_index_p0/test_or_not_match.groovy
@@ -64,6 +64,7 @@ suite("test_or_not_match", "p0") {
sql "set enable_nereids_planner = true"
sql "set enable_fallback_to_original_planner = false"
+ sql """ set enable_common_expr_pushdown = true """
qt_sql "select request from ${tableName} where request like '1.0' or not request MATCH 'GETA' order by request limit 2;"
}
diff --git a/regression-test/suites/inverted_index_p0/test_pk_no_need_read_data.groovy b/regression-test/suites/inverted_index_p0/test_pk_no_need_read_data.groovy
index 4aa969debda..b8cf3f4c0b5 100644
--- a/regression-test/suites/inverted_index_p0/test_pk_no_need_read_data.groovy
+++ b/regression-test/suites/inverted_index_p0/test_pk_no_need_read_data.groovy
@@ -54,6 +54,7 @@ suite("test_pk_no_need_read_data", "p0"){
// case1: enable count on index
sql "set enable_count_on_index_pushdown = true"
+ sql """ set enable_common_expr_pushdown = true """
qt_select_0 "SELECT COUNT() FROM ${table1} WHERE date='2017-10-01'"
qt_select_1 "SELECT COUNT() FROM ${table1} WHERE year(date)='2017'"
diff --git a/regression-test/suites/inverted_index_p0/test_stopwords.groovy b/regression-test/suites/inverted_index_p0/test_stopwords.groovy
index 4f7c577dc57..f9f8c8339a7 100644
--- a/regression-test/suites/inverted_index_p0/test_stopwords.groovy
+++ b/regression-test/suites/inverted_index_p0/test_stopwords.groovy
@@ -42,6 +42,7 @@ suite("test_stopwords", "p0"){
try {
sql "sync"
+ sql """ set enable_common_expr_pushdown = true """
qt_sql """ select * from ${indexTbName} where b match 'a'; """
qt_sql """ select * from ${indexTbName} where b match 'are'; """
diff --git a/regression-test/suites/inverted_index_p0/topn_clear_block.groovy b/regression-test/suites/inverted_index_p0/topn_clear_block.groovy
index 586173e0f3e..78d541bcb4a 100644
--- a/regression-test/suites/inverted_index_p0/topn_clear_block.groovy
+++ b/regression-test/suites/inverted_index_p0/topn_clear_block.groovy
@@ -40,6 +40,7 @@ suite("test_clear_block") {
}
sql """ set enable_match_without_inverted_index = false; """
+ sql """ set enable_common_expr_pushdown = true """
// sql """ set
def dupTableName = "dup_httplogs"
sql """ drop table if exists ${dupTableName} """
diff --git a/regression-test/suites/inverted_index_p0/unique_with_mow/test_mow_with_null_sequence.groovy b/regression-test/suites/inverted_index_p0/unique_with_mow/test_mow_with_null_sequence.groovy
index 92615e44d49..2da3509f1d5 100644
--- a/regression-test/suites/inverted_index_p0/unique_with_mow/test_mow_with_null_sequence.groovy
+++ b/regression-test/suites/inverted_index_p0/unique_with_mow/test_mow_with_null_sequence.groovy
@@ -38,6 +38,7 @@ suite("test_mow_with_null_sequence", "inverted_index") {
);
"""
+ sql """ set enable_common_expr_pushdown = true """
sql """ insert into $tableName values('a', 'zhang san', 'address1', NULL) """
sql """ insert into $tableName values('a', 'zhang si', 'address2', '2022-10-20') """
diff --git a/regression-test/suites/inverted_index_p0/unique_with_mow/test_pk_uk_case.groovy b/regression-test/suites/inverted_index_p0/unique_with_mow/test_pk_uk_case.groovy
index 309a458dd0d..e433ccaa06b 100644
--- a/regression-test/suites/inverted_index_p0/unique_with_mow/test_pk_uk_case.groovy
+++ b/regression-test/suites/inverted_index_p0/unique_with_mow/test_pk_uk_case.groovy
@@ -192,6 +192,7 @@ suite("test_pk_uk_case_unique_with_mow", "inverted_index") {
"""
sql "sync"
+ sql """ set enable_common_expr_pushdown = true """
// count(*)
def result0 = sql """ SELECT count(*) FROM ${tableNamePk}; """
diff --git a/regression-test/suites/inverted_index_p0/unique_with_mow/test_primary_key_simple_case.groovy b/regression-test/suites/inverted_index_p0/unique_with_mow/test_primary_key_simple_case.groovy
index b0ffda29754..8884ff837a6 100644
--- a/regression-test/suites/inverted_index_p0/unique_with_mow/test_primary_key_simple_case.groovy
+++ b/regression-test/suites/inverted_index_p0/unique_with_mow/test_primary_key_simple_case.groovy
@@ -66,6 +66,7 @@ suite("test_primary_key_simple_case", "inverted_index") {
sql """ INSERT INTO ${tableName} VALUES
(5, '2017-10-01', 'Beijing', 10, 1, NULL, NULL, '2020-01-05', 1, 34, 20)
"""
+ sql """ set enable_common_expr_pushdown = true """
result = sql """ SELECT * FROM ${tableName} t ORDER BY user_id; """
assertTrue(result.size() == 5)
diff --git a/regression-test/suites/inverted_index_p0/unique_with_mow/test_unique_mow_sequence.groovy b/regression-test/suites/inverted_index_p0/unique_with_mow/test_unique_mow_sequence.groovy
index 9c461f73714..c2a8b673f04 100644
--- a/regression-test/suites/inverted_index_p0/unique_with_mow/test_unique_mow_sequence.groovy
+++ b/regression-test/suites/inverted_index_p0/unique_with_mow/test_unique_mow_sequence.groovy
@@ -76,6 +76,7 @@ suite("test_unique_mow_sequence", "inverted_index") {
}
sql "sync"
+ sql """ set enable_common_expr_pushdown = true """
order_qt_sql "select * from $tableName where c_custkey < 6;"
diff --git a/regression-test/suites/variant_p0/with_index/load.groovy b/regression-test/suites/variant_p0/with_index/load.groovy
index ba46e7a9eee..4eeff1bfacb 100644
--- a/regression-test/suites/variant_p0/with_index/load.groovy
+++ b/regression-test/suites/variant_p0/with_index/load.groovy
@@ -61,7 +61,8 @@ suite("regression_test_variant_with_index", "nonConcurrent"){
properties("replication_num" = "1", "disable_auto_compaction" = "true");
"""
sql """insert into var_with_index values(1, '{"a" : 0, "b": 3}', 'hello world'), (2, '{"a" : 123}', 'world'),(3, '{"a" : 123}', 'hello world')"""
- sql """set enable_match_without_inverted_index = false"""
+ sql """set enable_match_without_inverted_index = false"""
+ sql """ set enable_common_expr_pushdown = true """
qt_sql_inv_1 """select v["a"] from var_with_index where inv match 'hello' order by k"""
qt_sql_inv_2 """select v["a"] from var_with_index where inv match 'hello' and cast(v['a'] as int) > 0 order by k"""
qt_sql_inv_3 """select * from var_with_index where inv match 'hello' and cast(v["a"] as int) > 0 order by k"""
diff --git a/regression-test/suites/variant_p0/with_index/var_index.groovy b/regression-test/suites/variant_p0/with_index/var_index.groovy
index a21d2429545..4d69bf0a6eb 100644
--- a/regression-test/suites/variant_p0/with_index/var_index.groovy
+++ b/regression-test/suites/variant_p0/with_index/var_index.groovy
@@ -33,6 +33,7 @@ suite("regression_test_variant_var_index", "p0"){
sql """insert into var_index values(2, '{"a" : 18811, "b" : "hello world", "c" : 1181111}')"""
sql """insert into var_index values(3, '{"a" : 18811, "b" : "hello wworld", "c" : 11111}')"""
sql """insert into var_index values(4, '{"a" : 1234, "b" : "hello xxx world", "c" : 8181111}')"""
+ sql """ set enable_common_expr_pushdown = true """
sql """set enable_match_without_inverted_index = false"""
qt_sql """select * from var_index where cast(v["a"] as smallint) > 123 and cast(v["b"] as string) match 'hello' and cast(v["c"] as int) > 1024 order by k"""
sql """set enable_match_without_inverted_index = true"""
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For additional commands, e-mail: commits-help@doris.apache.org