From 8a519477bbfad3af7ea11764fbb01bb412a0ab76 Mon Sep 17 00:00:00 2001 From: ls0 Date: Thu, 29 Jul 2021 21:09:13 +0800 Subject: [PATCH] fix merge group by overwrite T_QUESTIONMARK leads div core --- src/sql/engine/basic/ob_chunk_datum_store.h | 31 +++++++++++++++++++-- src/sql/engine/join/ob_hash_join_op.cpp | 12 ++++---- src/sql/engine/join/ob_hash_join_op.h | 6 ++-- src/sql/optimizer/ob_logical_operator.cpp | 2 +- 4 files changed, 38 insertions(+), 13 deletions(-) diff --git a/src/sql/engine/basic/ob_chunk_datum_store.h b/src/sql/engine/basic/ob_chunk_datum_store.h index e74058df34..0224de3b84 100644 --- a/src/sql/engine/basic/ob_chunk_datum_store.h +++ b/src/sql/engine/basic/ob_chunk_datum_store.h @@ -120,7 +120,13 @@ public: template class LastStoredRow { public: - LastStoredRow(ObIAllocator& alloc) : store_row_(nullptr), alloc_(alloc), max_size_(0), reuse_(false) + LastStoredRow(ObIAllocator& alloc) + : store_row_(nullptr), + alloc_(alloc), + max_size_(0), + reuse_(false), + pre_alloc_row1_(nullptr), + pre_alloc_row2_(nullptr) {} ~LastStoredRow() {} @@ -141,17 +147,31 @@ public: int64_t head_size = sizeof(T); reuse = OB_ISNULL(store_row_) ? false : reuse && (max_size_ >= row_size + head_size + extra_size); if (reuse && OB_NOT_NULL(store_row_)) { + // switch buffer for write + store_row_ = (store_row_ == pre_alloc_row1_ ? pre_alloc_row2_ : pre_alloc_row1_); buf = reinterpret_cast(store_row_); new_row = store_row_; buffer_len = max_size_; } else { + // alloc 2 buffer with same length buffer_len = (!reuse_ ? row_size : row_size * 2) + head_size + extra_size; - if (OB_ISNULL(buf = reinterpret_cast(alloc_.alloc(buffer_len)))) { + char* buf1 = nullptr; + char* buf2 = nullptr; + if (OB_ISNULL(buf1 = reinterpret_cast(alloc_.alloc(buffer_len)))) { ret = OB_ALLOCATE_MEMORY_FAILED; SQL_ENG_LOG(ERROR, "alloc buf failed", K(ret)); - } else if (OB_ISNULL(new_row = new (buf) T())) { + } else if (OB_ISNULL(buf2 = reinterpret_cast(alloc_.alloc(buffer_len)))) { + ret = OB_ALLOCATE_MEMORY_FAILED; + SQL_ENG_LOG(ERROR, "alloc buf failed", K(ret)); + } else if (OB_ISNULL(pre_alloc_row1_ = new (buf1) T())) { + ret = OB_ALLOCATE_MEMORY_FAILED; + SQL_ENG_LOG(ERROR, "failed to new row", K(ret)); + } else if (OB_ISNULL(pre_alloc_row2_ = new (buf2) T())) { ret = OB_ALLOCATE_MEMORY_FAILED; SQL_ENG_LOG(ERROR, "failed to new row", K(ret)); + } else { + buf = buf1; + new_row = pre_alloc_row1_; } } if (OB_SUCC(ret)) { @@ -221,6 +241,11 @@ public: ObIAllocator& alloc_; int64_t max_size_; bool reuse_; + + private: + // To avoid writing memory overwrite, alloc 2 row for alternate writing + T* pre_alloc_row1_; + T* pre_alloc_row2_; }; template diff --git a/src/sql/engine/join/ob_hash_join_op.cpp b/src/sql/engine/join/ob_hash_join_op.cpp index d0b5d6683b..7f2e6386a3 100644 --- a/src/sql/engine/join/ob_hash_join_op.cpp +++ b/src/sql/engine/join/ob_hash_join_op.cpp @@ -1561,15 +1561,13 @@ void ObHashJoinOp::calc_cache_aware_partition_count() int64_t tmp_partition_cnt_per_level = max_partition_count_per_level_; if (total_partition_cnt > tmp_partition_cnt_per_level) { level1_part_count_ = part_count_; - OB_ASSERT(0 != level1_part_count_); - level1_bit_ = __builtin_ctz(level1_part_count_); + level1_bit_ = (0 == level1_part_count_) ? 0 : __builtin_ctz(level1_part_count_); level2_part_count_ = total_partition_cnt / level1_part_count_; level2_part_count_ = level2_part_count_ > tmp_partition_cnt_per_level ? tmp_partition_cnt_per_level : level2_part_count_; } else { level1_part_count_ = total_partition_cnt > part_count_ ? total_partition_cnt : part_count_; - OB_ASSERT(0 != level1_part_count_); - level1_bit_ = __builtin_ctz(level1_part_count_); + level1_bit_ = (0 == level1_part_count_) ? 0 : __builtin_ctz(level1_part_count_); } LOG_TRACE("partition count", K(total_partition_cnt), @@ -2758,7 +2756,11 @@ int ObHashJoinOp::get_next_probe_partition() } else { // two level OB_ASSERT(0 != level2_part_count_); - int64_t level1_part_idx = (cur_full_right_partition_ >> (__builtin_ctz(level2_part_count_))); + int64_t leading_zero = 0; + if (0 != level2_part_count_) { + leading_zero = __builtin_ctz(level2_part_count_); + } + int64_t level1_part_idx = (cur_full_right_partition_ >> (leading_zero)); if (level1_part_idx < dump_part_count) { cur_left_hist_ = &part_histograms_[cur_full_right_partition_]; break; diff --git a/src/sql/engine/join/ob_hash_join_op.h b/src/sql/engine/join/ob_hash_join_op.h index b6eef411f9..35a1d3060b 100644 --- a/src/sql/engine/join/ob_hash_join_op.h +++ b/src/sql/engine/join/ob_hash_join_op.h @@ -307,13 +307,11 @@ private: void set_part_count(int64_t part_shift, int64_t level1_part_count, int64_t level2_part_count) { - OB_ASSERT(0 != level1_part_count); - OB_ASSERT(0 != level2_part_count); part_shift_ = part_shift; level_one_part_count_ = level1_part_count; level_two_part_count_ = level2_part_count; - level1_bit_ = __builtin_ctz(level1_part_count); - level2_bit_ = __builtin_ctz(level2_part_count); + level1_bit_ = (0 == level1_part_count) ? 0 : __builtin_ctz(level1_part_count); + level2_bit_ = (0 == level2_part_count) ? 0 : __builtin_ctz(level2_part_count); } bool is_valid() { diff --git a/src/sql/optimizer/ob_logical_operator.cpp b/src/sql/optimizer/ob_logical_operator.cpp index ce19ad0dd6..7c9ce87143 100644 --- a/src/sql/optimizer/ob_logical_operator.cpp +++ b/src/sql/optimizer/ob_logical_operator.cpp @@ -1507,7 +1507,7 @@ int ObLogicalOperator::do_pre_traverse_operation(const TraverseOp& op, void* ctx // select /*+NO_REWRITE*/ count(*) from t1 group by 1 + (select 1 > all (select 0)); // if ((*e)->has_const_or_const_expr_flag() && !(*e)->has_flag(CNT_VOLATILE_CONST) && - !(*e)->has_flag(IS_EXEC_PARAM)) { + !(*e)->has_flag(CNT_EXEC_PARAM)) { ObRawExpr* remove_const_expr = NULL; OZ(ObRawExprUtils::build_remove_const_expr( get_plan()->get_optimizer_context().get_expr_factory(), *session, *e, remove_const_expr)); -- GitLab