/** * Copyright (c) 2021 OceanBase * OceanBase CE is licensed under Mulan PubL v2. * You can use this software according to the terms and conditions of the Mulan PubL v2. * You may obtain a copy of Mulan PubL v2 at: * http://license.coscl.org.cn/MulanPubL-2.0 * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. * See the Mulan PubL v2 for more details. */ #define USING_LOG_PREFIX SQL_ENG #include "sql/engine/expr/ob_expr_frame_info.h" #include "sql/engine/expr/ob_expr.h" #include "sql/engine/ob_exec_context.h" #include "sql/engine/expr/ob_i_expr_extra_info.h" #include "sql/engine/expr/ob_expr_extra_info_factory.h" #include "sql/engine/expr/ob_expr_operator.h" #include "sql/engine/px/ob_px_util.h" #include "sql/engine/expr/ob_expr_lob_utils.h" namespace oceanbase { using namespace common; namespace sql { OB_SERIALIZE_MEMBER(ObFrameInfo, expr_cnt_, frame_idx_, frame_size_, zero_init_pos_, zero_init_size_); int ObExprFrameInfo::assign(const ObExprFrameInfo &other, common::ObIAllocator &allocator) { int ret = OB_SUCCESS; need_ctx_cnt_ = other.need_ctx_cnt_; if (OB_FAIL(rt_exprs_.assign(other.rt_exprs_))) { LOG_WARN("failed to copy rt exprs", K(ret)); } else if (OB_FAIL(const_frame_.assign(other.const_frame_))) { LOG_WARN("failed to copy const frame ptrs", K(ret)); } else if (OB_FAIL(param_frame_.assign(other.param_frame_))) { LOG_WARN("failed to copy param frames", K(ret)); } else if (OB_FAIL(dynamic_frame_.assign(other.dynamic_frame_))) { LOG_WARN("failed to copy dynamic frames", K(ret)); } else if (OB_FAIL(datum_frame_.assign(other.datum_frame_))) { LOG_WARN("failed to copy datum frame", K(ret)); } else if (const_frame_ptrs_.prepare_allocate(other.const_frame_ptrs_.count())) { LOG_WARN("failed to prepare allocate array", K(ret)); } else { char *frame_mem = NULL; for (int i = 0; OB_SUCC(ret) && i < other.const_frame_.count(); i++) { if (OB_ISNULL(frame_mem = (char *)allocator.alloc(other.const_frame_.at(i).frame_size_))) { ret = OB_ALLOCATE_MEMORY_FAILED; LOG_WARN("failed to allocate memory", K(ret)); } else { MEMCPY(frame_mem, other.const_frame_ptrs_.at(i), other.const_frame_.at(i).frame_size_); const_frame_ptrs_.at(i) = frame_mem; } // set datum ptr for (int j = 0; OB_SUCC(ret) && j < other.const_frame_.at(i).expr_cnt_; j++) { char *other_frame_mem = other.const_frame_ptrs_.at(i); int64_t other_frame_size = other.const_frame_.at(i).frame_size_; const int64_t datum_eval_info_size = sizeof(ObDatum) + sizeof(ObEvalInfo); ObDatum *other_expr_datum = reinterpret_cast (other_frame_mem + j * datum_eval_info_size); ObDatum *expr_datum = reinterpret_cast (frame_mem + j * datum_eval_info_size); // 在mysql模式下, 空串len为0, 且ptr = NULL, 当ptr为NULL时, copy时不需要再改变ptr值 if (NULL == other_expr_datum->ptr_) { // do nothing } else if ((other_expr_datum->ptr_ < other_frame_mem || other_expr_datum->ptr_ >= other_frame_mem + other_frame_size)) { // if datum's ptr_ does not locate in frame_mem, it must be deep copied separately void *extra_buf = NULL; if (0 == other_expr_datum->len_) { ret = OB_INVALID_ARGUMENT; LOG_WARN("length is null and ptr not null", K(ret), K(*other_expr_datum)); } else if (OB_ISNULL(extra_buf = allocator.alloc(other_expr_datum->len_))) { ret = OB_ALLOCATE_MEMORY_FAILED; LOG_WARN("failed to allocate memory", K(ret)); } else { MEMCPY(extra_buf, other_expr_datum->ptr_, other_expr_datum->len_); expr_datum->ptr_ = static_cast(extra_buf); } } else { expr_datum->ptr_ = frame_mem + (other_expr_datum->ptr_ - other.const_frame_ptrs_.at(i)); } } // end for } // for end if (OB_SUCC(ret)) { // deep copy extra info & inner function ptrs for (int i = 0; OB_SUCC(ret) && i < other.rt_exprs_.count(); i++) { if (ObExprExtraInfoFactory::is_registered(other.rt_exprs_.at(i).type_)) { if (OB_ISNULL(other.rt_exprs_.at(i).extra_info_)) { // do nothing } else if (OB_FAIL(other.rt_exprs_.at(i).extra_info_->deep_copy(allocator, other.rt_exprs_.at(i).type_, rt_exprs_.at(i).extra_info_))) { LOG_WARN("failed to deep copy extra info", K(ret)); } } // copy inner function ptrs if (other.rt_exprs_.at(i).inner_func_cnt_ > 0) { int64_t func_cnt = other.rt_exprs_.at(i).inner_func_cnt_; void *funcs_buf = NULL; if (OB_ISNULL(funcs_buf = allocator.alloc(sizeof(void *) * func_cnt))) { ret = OB_ALLOCATE_MEMORY_FAILED; LOG_WARN("failed to allocate memory", K(ret)); } else { MEMCPY(funcs_buf, other.rt_exprs_.at(i).inner_functions_, func_cnt * sizeof(void *)); rt_exprs_.at(i).inner_functions_ = (void **)funcs_buf; } } } // end for } } // allocate args memory for all rt exprs if (OB_SUCC(ret)) { for (int i = 0; OB_SUCC(ret) && i < rt_exprs_.count(); i++) { if (rt_exprs_.at(i).arg_cnt_ > 0) { ObExpr **arg_buf = NULL; int64_t buf_size = rt_exprs_.at(i).arg_cnt_ * sizeof(ObExpr *); if (OB_ISNULL(arg_buf = (ObExpr **)allocator.alloc(buf_size))) { ret = OB_ALLOCATE_MEMORY_FAILED; LOG_WARN("failed to allocate memory", K(ret)); } else { MEMSET(arg_buf, 0, buf_size); rt_exprs_.at(i).args_ = arg_buf; } } // allocate parents memory for all rt exprs if (rt_exprs_.at(i).parent_cnt_ > 0) { ObExpr **parent_buf = NULL; int64_t buf_size = rt_exprs_.at(i).parent_cnt_ * sizeof(ObExpr *); if (OB_ISNULL(parent_buf = (ObExpr **)allocator.alloc(buf_size))) { ret = OB_ALLOCATE_MEMORY_FAILED; LOG_WARN("failed to allocate memory", K(ret)); } else { MEMSET(parent_buf, 0, buf_size); rt_exprs_.at(i).parents_ = parent_buf; } } } // end for } // replace arg ptrs and parent ptrs for all rt exprs for (int i = 0; OB_SUCC(ret) && i < other.rt_exprs_.count(); i++) { if (other.rt_exprs_.at(i).arg_cnt_ > 0) { for (int j = 0; OB_SUCC(ret) && j < other.rt_exprs_.at(i).arg_cnt_; j++) { int64_t pos = other.rt_exprs_.at(i).args_[j] - &(other.rt_exprs_.at(0)); if (pos >= rt_exprs_.count() || pos < 0) { ret = OB_INVALID_ARGUMENT; LOG_WARN("rt expr pos is invalid", K(pos), KP(&other.rt_exprs_.at(0)), KP(other.rt_exprs_.at(i).args_[j])); } else { rt_exprs_.at(i).args_[j] = &rt_exprs_.at(pos); } } // end for } if (other.rt_exprs_.at(i).parent_cnt_ > 0) { for (int j = 0; OB_SUCC(ret) && j < other.rt_exprs_.at(i).parent_cnt_; j++) { int64_t pos = other.rt_exprs_.at(i).parents_[j] - &(other.rt_exprs_.at(0)); if (pos >= rt_exprs_.count() || pos < 0) { ret = OB_INVALID_ARGUMENT; LOG_WARN("rt expr pos is invalid", K(pos), KP(&other.rt_exprs_.at(0)), KP(other.rt_exprs_.at(i).args_[j])); } else { rt_exprs_.at(i).parents_[j] = &rt_exprs_.at(pos); } } // end for } } // end for if (OB_SUCC(ret)) { // deep copy extra info & inner function ptrs for (int i = 0; OB_SUCC(ret) && i < other.rt_exprs_.count(); i++) { if (ObExprExtraInfoFactory::is_registered(other.rt_exprs_.at(i).type_)) { if (OB_ISNULL(other.rt_exprs_.at(i).extra_info_)) { // do nothing } else if (OB_FAIL(other.rt_exprs_.at(i).extra_info_->deep_copy(allocator, other.rt_exprs_.at(i).type_, rt_exprs_.at(i).extra_info_))) { LOG_WARN("failed to deep copy extra info", K(ret)); } } // copy inner function ptrs if (OB_SUCC(ret) && other.rt_exprs_.at(i).inner_func_cnt_ > 0) { int64_t func_cnt = other.rt_exprs_.at(i).inner_func_cnt_; void *funcs_buf = NULL; if (OB_ISNULL(funcs_buf = allocator.alloc(sizeof(void *) * func_cnt))) { ret = OB_ALLOCATE_MEMORY_FAILED; LOG_WARN("failed to allocate memory", K(ret)); } else { MEMCPY(funcs_buf, other.rt_exprs_.at(i).inner_functions_, func_cnt * sizeof(void *)); rt_exprs_.at(i).inner_functions_ = (void **)funcs_buf; } } } // end for } return ret; } int ObExprFrameInfo::pre_alloc_exec_memory(ObExecContext &exec_ctx, ObIAllocator *allocator) const { int ret = OB_SUCCESS; uint64_t frame_cnt = 0; char **frames = NULL; ObPhysicalPlanCtx *phy_ctx = NULL; if (NULL == (phy_ctx = exec_ctx.get_physical_plan_ctx())) { ret = OB_INVALID_ARGUMENT; LOG_WARN("invalid argument", K(phy_ctx), K(ret)); } else if (OB_FAIL(alloc_frame(allocator != NULL ? *allocator : exec_ctx.get_allocator(), phy_ctx->get_param_frame_ptrs(), frame_cnt, frames))) { LOG_WARN("fail to alloc frame", K(ret)); } else { exec_ctx.set_frame_cnt(frame_cnt); exec_ctx.set_frames(frames); } return ret; } #define ALLOC_FRAME_MEM(frame_info_arr) \ for (int64_t i = 0; OB_SUCC(ret) && i < frame_info_arr.count(); i++) { \ const ObFrameInfo &frame_info = frame_info_arr.at(i); \ char *frame_mem = static_cast(exec_allocator.alloc(frame_info.frame_size_)); \ if (OB_ISNULL(frame_mem)) { \ ret = OB_ALLOCATE_MEMORY_FAILED; \ LOG_WARN("alloc memory failed", K(ret), K(frame_info.frame_size_)); \ } else if (frame_info.zero_init_size_ > 0) { \ MEMSET(frame_mem + frame_info.zero_init_pos_, 0, frame_info.zero_init_size_);\ } \ frames[frame_idx++] = frame_mem; \ } \ // 分配frame内存, 并将所有frame指针按每个frame idx的序存放到frames数组中 // 1. const frame内存来自plan中共享的内存, 直接将plan中存放的指针拿来使用 // 2. param frame内存来自编译期参数化后生成, 这里可直接获取 // 3. dynamic frame和datum frame内存在这里进行预分配 int ObExprFrameInfo::alloc_frame(ObIAllocator &exec_allocator, const ObIArray ¶m_frame_ptrs, uint64_t &frame_cnt, char **&frames) const { int ret = common::OB_SUCCESS; frame_cnt = const_frame_ptrs_.count() + param_frame_.count() + dynamic_frame_.count() + datum_frame_.count(); if (frame_cnt == 0) { // do nothing } else if (NULL == (frames = static_cast(exec_allocator.alloc( frame_cnt * sizeof(char *))))) { ret = OB_ALLOCATE_MEMORY_FAILED; LOG_WARN("alloc memory failed", K(ret), K(frame_cnt)); } else { int64_t frame_idx = 0; //frame idx OB_ASSERT(const_frame_ptrs_.count() == const_frame_.count()); // Param frame size maybe small than param frame ptrs, because the pre-calculated // exprs may be evaluate again in plan cache constraints check after param store extended. // After param_frame_ptrs from physical_plan_ctx is reset in ObPlanCacheValue::choose_plan, // can check OB_ASSERT(param_frame_.empty() || param_frame_ptrs.count() == param_frame_.count()); OB_ASSERT(param_frame_.empty() || param_frame_ptrs.count() >= param_frame_.count()); for (int64_t i = 0 ; i < const_frame_ptrs_.count(); i++) { frames[frame_idx++] = const_frame_ptrs_.at(i); } if (!param_frame_.empty()) { for (int64_t i = 0 ; i < param_frame_.count(); i++) { frames[frame_idx++] = param_frame_ptrs.at(i); } } int64_t begin_idx = frame_idx; const int64_t datum_eval_info_size = sizeof(ObDatum) + sizeof(ObEvalInfo); ALLOC_FRAME_MEM(dynamic_frame_); //for subquery core //提前将frame中的datum置为null for (int64_t i = 0; OB_SUCC(ret) && i < dynamic_frame_.count(); ++i) { char *cur_frame = frames[begin_idx + i]; for (int64_t j = 0; j < dynamic_frame_.at(i).expr_cnt_; ++j) { ObDatum *datum = reinterpret_cast(cur_frame + j * datum_eval_info_size); datum->set_null(); } } ALLOC_FRAME_MEM(datum_frame_); } return ret; } #undef ALLOC_FRAME_MEM OB_SERIALIZE_MEMBER(ObEmptyExpr); int ObExprFrameInfo::get_expr_idx_in_frame(ObExpr *expr, int64_t &expr_idx) const { int ret = OB_SUCCESS; if (OB_ISNULL(expr)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("frame info is null or expr is null", K(ret)); } else { const ObIArray *array = &rt_exprs_; int64_t idx = 0; if (OB_UNLIKELY(NULL == array || array->empty() || expr < &array->at(0) || (idx = expr - &array->at(0) + 1) > array->count())) { ret = OB_ERR_UNEXPECTED; SQL_LOG(WARN, "expr not in array", K(ret), KP(array), KP(idx), KP(expr)); } else { expr_idx = idx; } } return ret; } OB_DEF_SERIALIZE(ObExprFrameInfo) { int ret = OB_SUCCESS; LOG_TRACE("serialize expr frame info", KP(buf), K(buf_len), K(pos), K(*this)); OB_UNIS_ENCODE(need_ctx_cnt_); ObIArray *seri_arr_bak = ObExpr::get_serialize_array(); ObExpr::get_serialize_array() = const_cast *>(&rt_exprs_); if (OB_FAIL(ret)) { } else if (OB_FAIL(serialization::encode_i32(buf, buf_len, pos, rt_exprs_.count()))) { LOG_WARN("fail to encode op type", K(ret)); } else if (nullptr == ObExpr::get_serialize_array()) { ret = OB_ERR_UNEXPECTED; LOG_WARN("serialize array is null", K(ret), K(pos), K(rt_exprs_.count())); } else { LOG_TRACE("get serialize array", K(ObExpr::get_serialize_array()), K(rt_exprs_.count())); for (int64_t i = 0; i < rt_exprs_.count() && OB_SUCC(ret); ++i) { const ObExpr &expr = rt_exprs_.at(i); if (OB_FAIL(expr.serialize(buf, buf_len, pos))) { LOG_WARN("failed to serialize expr", K(ret), K(i), K(rt_exprs_.count())); } } } OB_UNIS_ENCODE(const_frame_ptrs_.count()); OZ(ObPxTreeSerializer::serialize_frame_info(buf, buf_len, pos, const_frame_, const_frame_ptrs_.get_data(), const_frame_ptrs_.count())); OB_UNIS_ENCODE(param_frame_); OB_UNIS_ENCODE(datum_frame_); OB_UNIS_ENCODE(dynamic_frame_); ObExpr::get_serialize_array() = seri_arr_bak; return ret; } OB_DEF_DESERIALIZE(ObExprFrameInfo) { int ret = OB_SUCCESS; int32_t expr_cnt = 0; OB_UNIS_DECODE(need_ctx_cnt_); ObIArray &exprs = const_cast &>(rt_exprs_); ObIArray *seri_arr_bak = ObExpr::get_serialize_array(); ObExpr::get_serialize_array() = &exprs; if (OB_FAIL(serialization::decode_i32(buf, data_len, pos, &expr_cnt))) { LOG_WARN("fail to encode op type", K(ret)); } else if (OB_FAIL(exprs.prepare_allocate(expr_cnt))) { LOG_WARN("failed to prepare allocator expr", K(ret)); } else { for (int64_t i = 0; i < expr_cnt && OB_SUCC(ret); ++i) { ObExpr &expr = exprs.at(i); if (OB_FAIL(expr.deserialize(buf, data_len, pos))) { LOG_WARN("failed to serialize expr", K(ret)); } } } int64_t const_frame_cnt = 0; char **frames = NULL; OB_UNIS_DECODE(const_frame_cnt); if (0 != const_frame_cnt) { CK(OB_NOT_NULL(frames = static_cast( allocator_.alloc(sizeof(char*) * const_frame_cnt)))); OX(MEMSET(frames, 0, sizeof(char*) * const_frame_cnt)); } OZ(ObPxTreeSerializer::deserialize_frame_info(buf, data_len, pos, allocator_, const_frame_, &const_frame_ptrs_, frames, const_frame_cnt)); OB_UNIS_DECODE(param_frame_); OB_UNIS_DECODE(datum_frame_); OB_UNIS_DECODE(dynamic_frame_); ObExpr::get_serialize_array() = seri_arr_bak; return ret; } OB_DEF_SERIALIZE_SIZE(ObExprFrameInfo) { int ret = OB_SUCCESS; int64_t len = 0; OB_UNIS_ADD_LEN(need_ctx_cnt_); ObIArray &exprs = const_cast &>(rt_exprs_); int32_t expr_cnt = exprs.count(); ObIArray *seri_arr_bak = ObExpr::get_serialize_array(); ObExpr::get_serialize_array() = &exprs; len += serialization::encoded_length_i32(expr_cnt); for (int64_t i = 0; i < exprs.count(); ++i) { ObExpr &expr = exprs.at(i); len += expr.get_serialize_size(); } OB_UNIS_ADD_LEN(const_frame_ptrs_.count()); len += ObPxTreeSerializer::get_serialize_frame_info_size( const_frame_, const_frame_ptrs_.get_data(), const_frame_ptrs_.count()); LOG_DEBUG("trace end get ser expr frame info size", K(ret), K(len)); OB_UNIS_ADD_LEN(param_frame_); OB_UNIS_ADD_LEN(datum_frame_); OB_UNIS_ADD_LEN(dynamic_frame_); ObExpr::get_serialize_array() = seri_arr_bak; return len; } int ObPreCalcExprFrameInfo::assign(const ObPreCalcExprFrameInfo &other, common::ObIAllocator &allocator) { int ret = OB_SUCCESS; if (OB_FAIL(ObExprFrameInfo::assign(other, allocator))) { LOG_WARN("fail to assign expr frame info", K(ret), K(other)); } else if (OB_FAIL(pre_calc_rt_exprs_.prepare_allocate(other.pre_calc_rt_exprs_.count()))) { LOG_WARN("failed to prepare allocate rt exprs", K(ret)); } for (int i = 0; OB_SUCC(ret) && i < other.pre_calc_rt_exprs_.count(); i++) { int64_t pos = other.pre_calc_rt_exprs_.at(i) - &(other.rt_exprs_.at(0)); if (pos >= rt_exprs_.count() || pos < 0) { ret = OB_INVALID_ARGUMENT; LOG_WARN("rt expr pos is invalid", K(pos), KP(&other.rt_exprs_.at(0)), KP(other.pre_calc_rt_exprs_.at(i))); } else { pre_calc_rt_exprs_.at(i) = &rt_exprs_.at(pos); } } // for end return ret; } int ObPreCalcExprFrameInfo::eval(ObExecContext &exec_ctx, ObIArray &res_datum_params) { int ret = OB_SUCCESS; res_datum_params.reuse(); if (pre_calc_rt_exprs_.empty()) { /* do nothing */ } else if (OB_FAIL(pre_alloc_exec_memory(exec_ctx))) { LOG_WARN("failed to pre alloc exec memory", K(ret)); } else if (OB_FAIL(exec_ctx.init_expr_op(need_ctx_cnt_))) { LOG_WARN("failed to init expr op ctx", K(ret)); } else if (OB_FAIL(do_normal_eval(exec_ctx, res_datum_params))) { LOG_WARN("do normal eval failed", K(ret)); } // reset expr op anyway exec_ctx.reset_expr_op(); return ret; } OB_INLINE int ObPreCalcExprFrameInfo::do_normal_eval(ObExecContext &exec_ctx, ObIArray &res_datum_params) { int ret = OB_SUCCESS; ObEvalCtx eval_ctx(exec_ctx); ObDatum *res_datum = NULL; ObDatumObjParam datum_param; ObExpr *rt_expr = NULL; for (int64_t i = 0; OB_SUCC(ret) && i < pre_calc_rt_exprs_.count(); ++i) { if (OB_ISNULL(rt_expr = pre_calc_rt_exprs_.at(i))) { ret = OB_ERR_UNEXPECTED; LOG_WARN("unexpected null rt exprs", K(ret)); } else if (OB_FAIL(rt_expr->eval(eval_ctx, res_datum))) { LOG_WARN("failed to eval", K(ret)); } else { datum_param.set_datum(*res_datum); datum_param.set_meta(rt_expr->datum_meta_); if (rt_expr->obj_meta_.has_lob_header()) { datum_param.set_result_flag(HAS_LOB_HEADER_FLAG); } if (OB_FAIL(res_datum_params.push_back(datum_param))) { LOG_WARN("failed to push back obj param", K(ret)); } } // else end } // for end return ret; } OB_NOINLINE int ObPreCalcExprFrameInfo::do_batch_stmt_eval(ObExecContext &exec_ctx, ObIArray &res_datum_params) { int ret = OB_SUCCESS; ObEvalCtx eval_ctx(exec_ctx); ObDatum *res_datum = NULL; ObDatumObjParam datum_param; int64_t group_cnt = exec_ctx.get_sql_ctx()->multi_stmt_item_.get_batched_stmt_cnt(); ObSqlDatumArray *datum_array = nullptr; //construct sql array obj for (int64_t i = 0; OB_SUCC(ret) && i < pre_calc_rt_exprs_.count(); ++i) { ObExpr *rt_expr = NULL; if (OB_ISNULL(rt_expr = pre_calc_rt_exprs_.at(i))) { ret = OB_ERR_UNEXPECTED; LOG_WARN("unexpected null rt exprs", K(ret)); } else if (OB_ISNULL(datum_array = ObSqlDatumArray::alloc(exec_ctx.get_allocator(), group_cnt))) { ret = OB_ALLOCATE_MEMORY_FAILED; LOG_WARN("allocate array buffer failed", K(ret), K(group_cnt)); } else { datum_array->element_.set_obj_type(rt_expr->datum_meta_.type_); datum_array->element_.set_collation_type(rt_expr->datum_meta_.cs_type_); datum_array->element_.set_scale(rt_expr->datum_meta_.scale_); const ObObjTypeClass &dst_tc = ob_obj_type_class(rt_expr->datum_meta_.type_); if (ObStringTC == dst_tc || ObTextTC == dst_tc) { datum_array->element_.set_length_semantics(rt_expr->datum_meta_.length_semantics_); } else { datum_array->element_.set_precision(rt_expr->datum_meta_.precision_); } } if (OB_SUCC(ret)) { datum_param.meta_.type_ = ObExtendType; datum_param.meta_.scale_ = T_EXT_SQL_ARRAY; if (OB_FAIL(datum_param.alloc_datum_reserved_buff(datum_param.meta_, exec_ctx.get_allocator()))) { LOG_WARN("alloc datum reserved buffer failed", K(ret)); } else if (FALSE_IT(datum_param.set_sql_array_datum(datum_array))) { //always false, do nothing } else if (OB_FAIL(res_datum_params.push_back(datum_param))) { LOG_WARN("failed to push back obj param", K(ret)); } } // else end } // for end //replace array param to the real param and eval the pre calc expr for (int64_t group_id = 0; OB_SUCC(ret) && group_id < group_cnt; ++group_id) { if (OB_FAIL(exec_ctx.get_physical_plan_ctx()->replace_batch_param_datum(group_id))) { LOG_WARN("replace batch param frame failed", K(ret)); } //params of each group need to clear the datum evaluted flags before calc the pre_calc_expr //otherwise, the result of pre_calc_expr will be the result of the last group param clear_datum_evaluted_flags(exec_ctx.get_frames()); for (int64_t i = 0; OB_SUCC(ret) && i < pre_calc_rt_exprs_.count(); ++i) { ObExpr *rt_expr = pre_calc_rt_exprs_.at(i); datum_array = res_datum_params.at(i).get_sql_datum_array(); if (OB_FAIL(rt_expr->eval(eval_ctx, res_datum))) { LOG_WARN("failed to eval", K(ret)); } else if (OB_FAIL(datum_array->data_[group_id].deep_copy(*res_datum, exec_ctx.get_allocator()))) { LOG_WARN("deep copy datum failed", K(ret)); } else { LOG_DEBUG("do batch stmt eval", K(datum_array->data_[group_id]), KPC(res_datum), KPC(rt_expr)); } } } return ret; } void ObPreCalcExprFrameInfo::clear_datum_evaluted_flags(char **frames) { int64_t datum_frame_idx = const_frame_ptrs_.count() + param_frame_.count() + dynamic_frame_.count(); const int64_t datum_eval_info_size = sizeof(ObDatum) + sizeof(ObEvalInfo); for (int64_t i = 0; i < datum_frame_.count(); ++i) { char *cur_frame = frames[datum_frame_idx + i]; for (int64_t j = 0; j < datum_frame_.at(i).expr_cnt_; ++j) { char *datum_ptr = cur_frame + j * datum_eval_info_size; ObEvalInfo *eval_info = reinterpret_cast(datum_ptr + sizeof(ObDatum)); eval_info->clear_evaluated_flag(); } } } int ObPreCalcExprFrameInfo::eval_expect_err(ObExecContext &exec_ctx, bool &all_eval_err) { int ret = OB_SUCCESS; all_eval_err = true; if (pre_calc_rt_exprs_.empty()) { /* do nothing */ } else if (OB_FAIL(pre_alloc_exec_memory(exec_ctx))) { LOG_WARN("failed to pre alloc exec memory", K(ret)); } else if (OB_FAIL(exec_ctx.init_expr_op(need_ctx_cnt_))) { LOG_WARN("failed to init expr op ctx", K(ret)); } else { ObEvalCtx eval_ctx(exec_ctx); ObDatum *res_datum = NULL; for (int64_t i = 0; OB_SUCC(ret) && all_eval_err && i < pre_calc_rt_exprs_.count(); ++i) { if (OB_ISNULL(pre_calc_rt_exprs_.at(i))) { ret = OB_ERR_UNEXPECTED; LOG_WARN("unexpected null rt exprs", K(ret)); } else if (OB_LIKELY(OB_SUCCESS != pre_calc_rt_exprs_.at(i)->eval(eval_ctx, res_datum))) { // eval error is expected } else { all_eval_err = false; }// else end } // for end // reset expr op anyway exec_ctx.reset_expr_op(); } return ret; } ObTempExprCtx::~ObTempExprCtx() { if (expr_op_ctx_store_ != NULL) { ObExprOperatorCtx **it = expr_op_ctx_store_; ObExprOperatorCtx **it_end = &expr_op_ctx_store_[expr_op_size_]; for (; it != it_end; ++it) { if (NULL != (*it)) { (*it)->~ObExprOperatorCtx(); } } expr_op_ctx_store_ = NULL; expr_op_size_ = 0; frame_cnt_ = 0; } } int ObTempExpr::eval(ObExecContext &exec_ctx, const ObNewRow &row, ObObj &result) const { int ret = OB_SUCCESS; ObDatum *res_datum = NULL; char **frames = NULL; ObTempExprCtx *temp_expr_ctx = NULL; OZ(exec_ctx.get_temp_expr_eval_ctx(*this, temp_expr_ctx)); CK(OB_NOT_NULL(temp_expr_ctx)); OX(ObSQLUtils::clear_expr_eval_flags(rt_exprs_.at(expr_idx_), *temp_expr_ctx)); OZ(row_to_frame(row, *temp_expr_ctx)); if (OB_SUCC(ret)) { ObTempExprCtxReplaceGuard exec_ctx_backup_guard(exec_ctx, *temp_expr_ctx); OZ(rt_exprs_.at(expr_idx_).eval(*temp_expr_ctx, res_datum)); OZ(res_datum->to_obj(result, rt_exprs_.at(expr_idx_).obj_meta_)); LOG_TRACE("temp expr result", K(result), K(row), K(rt_exprs_)); } return ret; } int ObTempExpr::row_to_frame(const ObNewRow &row, ObTempExprCtx &temp_expr_ctx) const { int ret = OB_SUCCESS; for (int64_t i = 0; OB_SUCC(ret) && i < idx_col_arr_.count(); i++) { const RowIdxColumnPair &idx_col = idx_col_arr_.at(i); ObObj &v = row.cells_[idx_col.idx_]; ObExpr &expr = rt_exprs_.at(idx_col.expr_pos_); ObDatum &expr_datum = expr.locate_datum_for_write(temp_expr_ctx); if (v.get_type() != expr.datum_meta_.type_ && !v.is_null()) { ret = OB_ERR_UNEXPECTED; LOG_WARN("obj type miss match", K(ret), K(v), K(idx_col), K(row)); } else if (OB_FAIL(expr_datum.from_obj(v, expr.obj_datum_map_))) { LOG_WARN("fail to from obj", K(v), K(idx_col), K(row), K(ret)); } else if (is_lob_storage(v.get_type()) && OB_FAIL(ob_adjust_lob_datum(v, expr.obj_meta_, expr.obj_datum_map_, temp_expr_ctx.exec_ctx_.get_allocator(), expr_datum))) { LOG_WARN("adjust lob datum failed", K(ret), K(v.get_meta()), K(expr.obj_meta_)); } } return ret; } int ObTempExpr::deep_copy(ObIAllocator &allocator, ObTempExpr *&dst) const { int ret = OB_SUCCESS; char *buf = static_cast(allocator.alloc(sizeof(ObTempExpr))); CK(OB_NOT_NULL(buf)); OX(dst = new(buf)ObTempExpr(allocator)); OZ(dst->assign(*this, allocator)); OX(dst->expr_idx_ = expr_idx_); OZ(dst->idx_col_arr_.assign(this->idx_col_arr_)); return ret; } OB_SERIALIZE_MEMBER(RowIdxColumnPair, idx_, expr_pos_); OB_SERIALIZE_MEMBER((ObTempExpr, ObExprFrameInfo), expr_idx_, idx_col_arr_); } }