diff --git a/src/observer/mysql/ob_async_plan_driver.cpp b/src/observer/mysql/ob_async_plan_driver.cpp index a2821665c2b2337e70cf241e05a266d0ac6f26d2..3e38fb119fb01b610515b749e1ee24ce82c79b8a 100644 --- a/src/observer/mysql/ob_async_plan_driver.cpp +++ b/src/observer/mysql/ob_async_plan_driver.cpp @@ -93,7 +93,7 @@ int ObAsyncPlanDriver::response_result(ObMySQLResultSet& result) if (!OB_SUCC(ret) && !async_resp_used && !retry_ctrl_.need_retry()) { int sret = OB_SUCCESS; - bool is_partition_hit = session_.partition_hit().get_bool(); + bool is_partition_hit = session_.get_err_final_partition_hit(ret); if (OB_SUCCESS != (sret = sender_.send_error_packet(ret, NULL, is_partition_hit))) { LOG_WARN("send error packet fail", K(sret), K(ret)); } diff --git a/src/observer/mysql/ob_sync_plan_driver.cpp b/src/observer/mysql/ob_sync_plan_driver.cpp index 81bf887b8adcee0c4d9a3ffe6b427ad87c5b2f67..34dc27892c84fd28b971754c5bd9329422b734bd 100644 --- a/src/observer/mysql/ob_sync_plan_driver.cpp +++ b/src/observer/mysql/ob_sync_plan_driver.cpp @@ -191,7 +191,7 @@ int ObSyncPlanDriver::response_result(ObMySQLResultSet& result) OB_BATCHED_MULTI_STMT_ROLLBACK != ret) { // if OB_BATCHED_MULTI_STMT_ROLLBACK is err ret of batch stmt rollback,not return to client, retry int sret = OB_SUCCESS; - bool is_partition_hit = session_.partition_hit().get_bool(); + bool is_partition_hit = session_.get_err_final_partition_hit(ret); if (OB_SUCCESS != (sret = sender_.send_error_packet(ret, NULL, is_partition_hit))) { LOG_WARN("send error packet fail", K(sret), K(ret)); } @@ -433,7 +433,7 @@ int ObRemotePlanDriver::response_result(ObMySQLResultSet& result) if (!retry_ctrl_.need_retry()) { if (OB_FAIL(ret) && !process_ok) { int sret = OB_SUCCESS; - bool is_partition_hit = session_.partition_hit().get_bool(); + bool is_partition_hit = session_.get_err_final_partition_hit(ret); if (OB_SUCCESS != (sret = sender_.send_error_packet(ret, NULL, is_partition_hit))) { LOG_WARN("send error packet fail", K(sret), K(ret)); } diff --git a/src/observer/mysql/obmp_query.cpp b/src/observer/mysql/obmp_query.cpp index 9c608c044737e7aa30df14e799782a6dba879a99..37d3e8d1ba31ce9aba2f98e66a92046ba039f6a8 100644 --- a/src/observer/mysql/obmp_query.cpp +++ b/src/observer/mysql/obmp_query.cpp @@ -739,9 +739,13 @@ OB_INLINE int ObMPQuery::do_process( } else { LOG_WARN("query failed", K(ret), K(retry_ctrl_.need_retry())); } - bool is_partition_hit = session.partition_hit().get_bool(); - int err = send_error_packet(ret, NULL, is_partition_hit, (void*)&ctx_.reroute_info_); - if (OB_SUCCESS != err) { + // 当need_retry=false时,可能给客户端回过包了,可能还没有回过任何包。 + // 不过,可以确定:这个请求出错了,还没处理完。如果不是已经交给异步EndTrans收尾, + // 则需要在下面回复一个error_packet作为收尾。否则后面没人帮忙发错误包给客户端了, + // 可能会导致客户端挂起等回包。 + bool is_partition_hit = session.get_err_final_partition_hit(ret); + int err = send_error_packet(ret, NULL, is_partition_hit, (void *)&ctx_.reroute_info_); + if (OB_SUCCESS != err) { // 发送error包 LOG_WARN("send error packet failed", K(ret), K(err)); } } diff --git a/src/observer/mysql/obmp_stmt_execute.cpp b/src/observer/mysql/obmp_stmt_execute.cpp index 357da1f1adc4fb5cb06b93df70d9a25c831910c7..da2afef249bed67fd12cd279b4e135a2ef593b80 100644 --- a/src/observer/mysql/obmp_stmt_execute.cpp +++ b/src/observer/mysql/obmp_stmt_execute.cpp @@ -716,9 +716,13 @@ int ObMPStmtExecute::do_process( && !THIS_WORKER.need_retry() && !retry_ctrl_.need_retry()) { LOG_WARN("query failed", K(ret), K(retry_ctrl_.need_retry()), K_(stmt_id)); - bool is_partition_hit = session.partition_hit().get_bool(); - int err = send_error_packet(ret, NULL, is_partition_hit, (void*)(&ctx_.reroute_info_)); - if (OB_SUCCESS != err) { + // 当need_retry=false时,可能给客户端回过包了,可能还没有回过任何包。 + // 不过,可以确定:这个请求出错了,还没处理完。如果不是已经交给异步EndTrans收尾, + // 则需要在下面回复一个error_packet作为收尾。否则后面没人帮忙发错误包给客户端了, + // 可能会导致客户端挂起等回包。 + bool is_partition_hit = session.get_err_final_partition_hit(ret); + int err = send_error_packet(ret, NULL, is_partition_hit, (void *)(&ctx_.reroute_info_)); + if (OB_SUCCESS != err) { // 发送error包 LOG_WARN("send error packet failed", K(ret), K(err)); } } diff --git a/src/observer/mysql/obmp_stmt_prepare.cpp b/src/observer/mysql/obmp_stmt_prepare.cpp index d900f76fbbce3649f04f4a9cdca324dad4191253..0a951247057b8eaeaf5342612778c92fe800cfbc 100644 --- a/src/observer/mysql/obmp_stmt_prepare.cpp +++ b/src/observer/mysql/obmp_stmt_prepare.cpp @@ -445,7 +445,11 @@ int ObMPStmtPrepare::do_process( if (!OB_SUCC(ret) && !async_resp_used && need_response_error && conn_valid_ && !THIS_WORKER.need_retry()) { LOG_WARN("query failed", K(ret), K(retry_ctrl_.need_retry()), K_(sql)); - bool is_partition_hit = session.partition_hit().get_bool(); + // 当need_retry=false时,可能给客户端回过包了,可能还没有回过任何包。 + // 不过,可以确定:这个请求出错了,还没处理完。如果不是已经交给异步EndTrans收尾, + // 则需要在下面回复一个error_packet作为收尾。否则后面没人帮忙发错误包给客户端了, + // 可能会导致客户端挂起等回包。 + bool is_partition_hit = session.get_err_final_partition_hit(ret); int err = send_error_packet(ret, NULL, is_partition_hit); if (OB_SUCCESS != err) { LOG_WARN("send error packet failed", K(ret), K(err)); diff --git a/src/sql/engine/expr/ob_expr_trim.cpp b/src/sql/engine/expr/ob_expr_trim.cpp index 61729f54278ccd03fd9d3a11633c715a632b79ae..366bfb659f2345ec727ba7685dfbdd10dbbe5042 100644 --- a/src/sql/engine/expr/ob_expr_trim.cpp +++ b/src/sql/engine/expr/ob_expr_trim.cpp @@ -370,10 +370,15 @@ inline int ObExprTrim::deduce_result_type( if (lib::is_oracle_mode() && type_ctx.get_session()->use_static_typing_engine()) { auto str_params = make_const_carray(str_type); LOG_DEBUG("str_type is", K(str_type)); - OZ(aggregate_string_type_and_charset_oracle(*type_ctx.get_session(), str_params, type, true)); // prefer varchar - OZ(deduce_string_param_calc_type_and_charset(*type_ctx.get_session(), type, str_params)); - if (NULL != pattern_type) { - pattern_type->set_calc_meta(type); + if (str_type->is_null()) { + type.set_meta(*str_type); + } else { + OZ(aggregate_string_type_and_charset_oracle(*type_ctx.get_session(), str_params, + type, true)); // prefer varchar + OZ(deduce_string_param_calc_type_and_charset(*type_ctx.get_session(), type, str_params)); + if (OB_SUCC(ret) && NULL != pattern_type) { + pattern_type->set_calc_meta(type); + } } } else { if (str_type->is_lob()) { @@ -389,6 +394,8 @@ inline int ObExprTrim::deduce_result_type( if (NULL != pattern_type) { pattern_type->set_calc_type(ObVarcharType); } + } else if (str_type->is_null()) { + type.set_meta(*str_type); } else { const common::ObLengthSemantics default_length_semantics = (OB_NOT_NULL(type_ctx.get_session()) ? type_ctx.get_session()->get_actual_nls_length_semantics() diff --git a/src/sql/engine/join/ob_basic_nested_loop_join.cpp b/src/sql/engine/join/ob_basic_nested_loop_join.cpp index 477ec9c0d1df5cc5a22855533fc54165a47facba..b115713e501f81b83112047db9a044009a59f021 100644 --- a/src/sql/engine/join/ob_basic_nested_loop_join.cpp +++ b/src/sql/engine/join/ob_basic_nested_loop_join.cpp @@ -51,33 +51,41 @@ int ObBasicNestedLoopJoin::prepare_rescan_params(ObBasicNestedLoopJoinCtx& join_ { int ret = OB_SUCCESS; ObObjParam res_obj; - ObPhysicalPlanCtx* plan_ctx = join_ctx.exec_ctx_.get_physical_plan_ctx(); - if (OB_ISNULL(plan_ctx) || OB_ISNULL(join_ctx.left_row_)) { + ObPhysicalPlanCtx *plan_ctx = join_ctx.exec_ctx_.get_physical_plan_ctx(); + ObPhyOperator *left_child = get_child(FIRST_CHILD); + ObPhyOperatorCtx *left_child_ctx = NULL; + if (OB_ISNULL(plan_ctx) || OB_ISNULL(join_ctx.left_row_) || + OB_ISNULL(left_child)) { ret = OB_BAD_NULL_ERROR; LOG_WARN("plan ctx or left row is null", K(ret)); + } else if (NULL == + (left_child_ctx = static_cast( + join_ctx.exec_ctx_.get_phy_op_ctx(left_child->get_id())))) { + LOG_WARN("fail to get phy operator ctx", K(ret)); } else { int64_t param_cnt = rescan_params_.count(); - const ObSqlExpression* expr = NULL; + const ObSqlExpression *expr = NULL; + // rescan param need deep copy, because memory of expr result from calc_buf + // in ObPhyOperator, when get next row next time, will free memory in + // calc_buf; here we use left child calc_buf, because when left child need + // get next row, rescan param will not used; for (int64_t i = 0; OB_SUCC(ret) && i < param_cnt; ++i) { + int64_t idx = rescan_params_.at(i).param_idx_; if (OB_ISNULL(expr = rescan_params_.at(i).expr_)) { ret = OB_BAD_NULL_ERROR; LOG_WARN("rescan param expr is null", K(ret), K(i)); } else if (OB_FAIL(expr->calc(join_ctx.expr_ctx_, *join_ctx.left_row_, res_obj))) { LOG_WARN("failed to calc expr for rescan param", K(ret), K(i)); } else { - int64_t idx = rescan_params_.at(i).param_idx_; res_obj.set_param_meta(); - plan_ctx->get_param_store_for_update().at(idx) = res_obj; - LOG_DEBUG("prepare_rescan_params", - K(ret), - K(i), - K(res_obj), - K(idx), - K(expr), - K(plan_ctx), - K(*join_ctx.left_row_), - K(*expr), - K(join_ctx.expr_ctx_.phy_plan_ctx_)); + if (OB_FAIL(deep_copy_obj( + left_child_ctx->get_calc_buf(), res_obj, + plan_ctx->get_param_store_for_update().at(idx)))) { + LOG_WARN("fail to deep copy ", K(ret)); + } + LOG_DEBUG("prepare_rescan_params", K(ret), K(i), K(res_obj), K(idx), + K(expr), K(plan_ctx), K(*join_ctx.left_row_), K(*expr), + K(join_ctx.expr_ctx_.phy_plan_ctx_)); } } } diff --git a/src/sql/engine/join/ob_nested_loop_join.cpp b/src/sql/engine/join/ob_nested_loop_join.cpp index 0730c0228d12f4cc70779b9985b72960e2e13db2..5ab3395d39df01d3b1e0e32ab3ec1863cf21ece8 100644 --- a/src/sql/engine/join/ob_nested_loop_join.cpp +++ b/src/sql/engine/join/ob_nested_loop_join.cpp @@ -122,23 +122,35 @@ int ObNestedLoopJoin::switch_iterator(ObExecContext& ctx) const return ret; } -int ObNestedLoopJoin::rescan(ObExecContext& exec_ctx) const -{ +int ObNestedLoopJoin::reset_rescan_params(ObExecContext &ctx) const { int ret = OB_SUCCESS; - ObNestedLoopJoinCtx* join_ctx = GET_PHY_OPERATOR_CTX(ObNestedLoopJoinCtx, exec_ctx, get_id()); - ObPhysicalPlanCtx* plan_ctx = exec_ctx.get_physical_plan_ctx(); - if (OB_ISNULL(join_ctx) || OB_ISNULL(plan_ctx)) { - ret = OB_BAD_NULL_ERROR; - LOG_WARN("join ctx is null", K(ret)); + ObPhysicalPlanCtx *plan_ctx = NULL; + if (OB_ISNULL(plan_ctx = GET_PHY_PLAN_CTX(ctx))) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("physical plan context is null", K(ret)); } else { - join_ctx->reset(); - int64_t param_cnt = rescan_params_.count(); - for (int64_t i = 0; OB_SUCC(ret) && i < param_cnt; ++i) { + for (int64_t i = 0; i < rescan_params_.count(); ++i) { int64_t idx = rescan_params_.at(i).param_idx_; plan_ctx->get_param_store_for_update().at(idx).set_null(); - LOG_DEBUG("prepare_rescan_params", K(ret), K(i), K(idx)); + LOG_TRACE("prepare_rescan_params", K(ret), K(i), K(idx)); } - if (OB_FAIL(ObBasicNestedLoopJoin::rescan(exec_ctx))) { + } + + return ret; +} + +int ObNestedLoopJoin::rescan(ObExecContext &exec_ctx) const { + int ret = OB_SUCCESS; + ObNestedLoopJoinCtx *join_ctx = + GET_PHY_OPERATOR_CTX(ObNestedLoopJoinCtx, exec_ctx, get_id()); + if (OB_ISNULL(join_ctx)) { + ret = OB_BAD_NULL_ERROR; + LOG_WARN("join ctx is null", K(ret)); + } else { + join_ctx->reset(); + if (OB_FAIL(reset_rescan_params(exec_ctx))) { + LOG_WARN("fail to reset rescan params", K(ret)); + } else if (OB_FAIL(ObBasicNestedLoopJoin::rescan(exec_ctx))) { LOG_WARN("failed to rescan", K(ret)); } } @@ -204,9 +216,16 @@ int ObNestedLoopJoin::inner_get_next_row(ObExecContext& exec_ctx, const ObNewRow LOG_WARN("copy current row failed", K(ret)); } } + if (OB_ITER_END == ret) { + if (OB_FAIL(reset_rescan_params(exec_ctx))) { + LOG_WARN("fail to reset rescan params", K(ret)); + } else { + ret = OB_ITER_END; + } + } if (OB_SUCC(ret)) { - LOG_DEBUG("get next row from nested loop join", K(*row)); + LOG_TRACE("get next row from nested loop join", K(*row)); } return ret; } diff --git a/src/sql/engine/join/ob_nested_loop_join.h b/src/sql/engine/join/ob_nested_loop_join.h index 9016c0673d26c92b591be59fccdee1cb5240fc61..9fab9dde7d67890bb12d7316e7dca7a40d8b5241 100644 --- a/src/sql/engine/join/ob_nested_loop_join.h +++ b/src/sql/engine/join/ob_nested_loop_join.h @@ -124,7 +124,9 @@ private: state_operation_func_type state_operation_func_[JS_STATE_COUNT]; state_function_func_type state_function_func_[JS_STATE_COUNT][FT_TYPE_COUNT]; // nested loop join with index seek, batch - int batch_index_join_get_next(ObExecContext& exec_ctx, const common::ObNewRow*& row) const; + int batch_index_join_get_next(ObExecContext &exec_ctx, + const common::ObNewRow *&row) const; + int reset_rescan_params(ObExecContext &ctx) const; private: int bij_fill_left_rows(ObExecContext& exec_ctx) const; diff --git a/src/sql/engine/join/ob_nested_loop_join_op.cpp b/src/sql/engine/join/ob_nested_loop_join_op.cpp index 4a7052d4e19122c7795e2843359a0cf70423f15f..132f2139a59585dd99f0acd7204ec684b34b16f6 100644 --- a/src/sql/engine/join/ob_nested_loop_join_op.cpp +++ b/src/sql/engine/join/ob_nested_loop_join_op.cpp @@ -73,12 +73,25 @@ int ObNestedLoopJoinOp::switch_iterator() return ret; } -int ObNestedLoopJoinOp::rescan() -{ +int ObNestedLoopJoinOp::set_param_null() { + int ret = OB_SUCCESS; + ObDatum null_datum; + null_datum.set_null(); + for (int64_t i = 0; OB_SUCC(ret) && i < MY_SPEC.rescan_params_.count(); ++i) { + OZ(MY_SPEC.rescan_params_.at(i).update_dynamic_param(eval_ctx_, + null_datum)); + LOG_DEBUG("prepare_rescan_params", K(ret), K(i)); + } + return ret; +} + +int ObNestedLoopJoinOp::rescan() { int ret = OB_SUCCESS; reset_buf_state(); - ObPhysicalPlanCtx* plan_ctx = GET_PHY_PLAN_CTX(ctx_); - if (OB_FAIL(ObBasicNestedLoopJoinOp::rescan())) { + ObPhysicalPlanCtx *plan_ctx = GET_PHY_PLAN_CTX(ctx_); + if (OB_FAIL(set_param_null())) { + LOG_WARN("failed to set param null", K(ret)); + } else if (OB_FAIL(ObBasicNestedLoopJoinOp::rescan())) { LOG_WARN("failed to rescan", K(ret)); } @@ -117,6 +130,13 @@ int ObNestedLoopJoinOp::inner_get_next_row() } } // while end } + if (OB_ITER_END == ret) { + if (OB_FAIL(set_param_null())) { + LOG_WARN("failed to set param null", K(ret)); + } else { + ret = OB_ITER_END; + } + } return ret; } diff --git a/src/sql/engine/join/ob_nested_loop_join_op.h b/src/sql/engine/join/ob_nested_loop_join_op.h index b48aaf6ac630fb3b90c51e839060c36564e30e83..cd02a8a51e0a980a2ca418cf45223ad552ca02f3 100644 --- a/src/sql/engine/join/ob_nested_loop_join_op.h +++ b/src/sql/engine/join/ob_nested_loop_join_op.h @@ -93,6 +93,7 @@ private: bool is_full() const; // used for rescan and switch iter virtual void reset_buf_state(); + int set_param_null(); public: ObJoinState state_; diff --git a/src/sql/engine/subquery/ob_subplan_filter.cpp b/src/sql/engine/subquery/ob_subplan_filter.cpp index 5b372858aacc77c79491b06e0b52672ca457cc21..1700e1230fd028a0f91e6c8e2ac943b6f5a597d2 100644 --- a/src/sql/engine/subquery/ob_subplan_filter.cpp +++ b/src/sql/engine/subquery/ob_subplan_filter.cpp @@ -204,25 +204,34 @@ void ObSubPlanFilter::reuse() ObMultiChildrenPhyOperator::reuse(); } -int ObSubPlanFilter::rescan(ObExecContext& ctx) const -{ +int ObSubPlanFilter::reset_rescan_params(ObExecContext &ctx) const { int ret = OB_SUCCESS; - ObPhyOperator* child_op = NULL; - ObSubPlanFilterCtx* subplan_ctx = NULL; - ObPhysicalPlanCtx* plan_ctx = NULL; - if (OB_ISNULL(subplan_ctx = GET_PHY_OPERATOR_CTX(ObSubPlanFilterCtx, ctx, get_id())) || - OB_ISNULL(plan_ctx = ctx.get_physical_plan_ctx())) { + ObPhysicalPlanCtx *plan_ctx = NULL; + if (OB_ISNULL(plan_ctx = GET_PHY_PLAN_CTX(ctx))) { ret = OB_ERR_UNEXPECTED; - LOG_WARN("get physical operator context failed", K(ret)); - } else { /*do nothing*/ + LOG_WARN("physical plan context is null", K(ret)); + } else { + for (int64_t i = 0; i < rescan_params_.count(); ++i) { + int64_t idx = rescan_params_.at(i).second; + plan_ctx->get_param_store_for_update().at(idx).set_null(); + LOG_TRACE("prepare_rescan_params", K(ret), K(i), K(idx)); + } } - for (int64_t i = 0; OB_SUCC(ret) && i < rescan_params_.count(); ++i) { - int64_t idx = rescan_params_.at(i).second; - plan_ctx->get_param_store_for_update().at(idx).set_null(); - LOG_DEBUG("prepare_rescan_params", K(ret), K(i), K(idx)); - } + return ret; +} +int ObSubPlanFilter::rescan(ObExecContext &ctx) const { + int ret = OB_SUCCESS; + ObPhyOperator *child_op = NULL; + ObSubPlanFilterCtx *subplan_ctx = NULL; + if (OB_ISNULL(subplan_ctx = + GET_PHY_OPERATOR_CTX(ObSubPlanFilterCtx, ctx, get_id()))) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("get physical operator context failed", K(ret)); + } else if (OB_FAIL(reset_rescan_params(ctx))) { + LOG_WARN("fail to reset rescan params", K(ret)); + } for (int32_t i = 1; OB_SUCC(ret) && i < get_child_num(); ++i) { if (OB_ISNULL(child_op = get_child(i))) { ret = OB_ERR_UNEXPECTED; @@ -620,6 +629,13 @@ int ObSubPlanFilter::inner_get_next_row(ObExecContext& ctx, const ObNewRow*& row OZ(copy_cur_row(*subplan_ctx, row)); } } + if (OB_ITER_END == ret) { + if (OB_FAIL(reset_rescan_params(ctx))) { + LOG_WARN("fail to reset rescan params", K(ret)); + } else { + ret = OB_ITER_END; + } + } return ret; } diff --git a/src/sql/engine/subquery/ob_subplan_filter.h b/src/sql/engine/subquery/ob_subplan_filter.h index c1811ae6c072dc49555563646b427e9e4df60733..195669654ed48709fd39791c93c37f3238e7db0f 100644 --- a/src/sql/engine/subquery/ob_subplan_filter.h +++ b/src/sql/engine/subquery/ob_subplan_filter.h @@ -104,6 +104,7 @@ private: virtual int64_t to_string_kv(char* buf, const int64_t buf_len) const; int handle_update_set(ObSubPlanFilterCtx* subplan_ctx, const common::ObNewRow*& row) const; int construct_array_params(ObExecContext& ctx) const; + int reset_rescan_params(ObExecContext &ctx) const; private: DISALLOW_COPY_AND_ASSIGN(ObSubPlanFilter); diff --git a/src/sql/engine/subquery/ob_subplan_filter_op.cpp b/src/sql/engine/subquery/ob_subplan_filter_op.cpp index 98845854d35139b468474b6ca01b58b7ba5b268a..d28a2e1d8a069c96381bf671a62eab4c64c3dd02 100644 --- a/src/sql/engine/subquery/ob_subplan_filter_op.cpp +++ b/src/sql/engine/subquery/ob_subplan_filter_op.cpp @@ -325,6 +325,13 @@ int ObSubPlanFilterOp::inner_get_next_row() OZ(handle_update_set()); } } + if (OB_ITER_END == ret) { + if (OB_FAIL(set_param_null())) { + LOG_WARN("failed to set param null", K(ret)); + } else { + ret = OB_ITER_END; + } + } return ret; } diff --git a/src/sql/plan_cache/ob_plan_cache_util.h b/src/sql/plan_cache/ob_plan_cache_util.h index 8e5e54efbc17fed907359b73584b4976f5edc186..6bf76dcb317a90f7ba758b76820756be705d7af9 100644 --- a/src/sql/plan_cache/ob_plan_cache_util.h +++ b/src/sql/plan_cache/ob_plan_cache_util.h @@ -470,7 +470,7 @@ struct ObPlanCacheCtx { must_be_positive_index_(), multi_stmt_fp_results_(allocator), handle_id_(MAX_HANDLE), - is_remote_executor_(false) + is_remote_executor_(false) { bl_key_.tenant_id_ = tenant_id; fp_result_.pc_key_.is_ps_mode_ = is_ps_mode_; diff --git a/src/sql/plan_cache/ob_prepare_stmt_struct.cpp b/src/sql/plan_cache/ob_prepare_stmt_struct.cpp index 828dac6081d8f941c14d2f0252a1d7810d1545b1..6ce347d7030fa5bb5a621b113b89c884d03c870c 100644 --- a/src/sql/plan_cache/ob_prepare_stmt_struct.cpp +++ b/src/sql/plan_cache/ob_prepare_stmt_struct.cpp @@ -264,6 +264,7 @@ ObPsStmtInfo::ObPsStmtInfo(ObIAllocator* inner_allocator) dep_objs_(NULL), dep_objs_cnt_(0), ps_item_(NULL), + is_expired_evicted_(false), allocator_(inner_allocator), external_allocator_(NULL) @@ -286,6 +287,7 @@ ObPsStmtInfo::ObPsStmtInfo(ObIAllocator* inner_allocator, ObIAllocator* external ps_item_(NULL), tenant_version_(OB_INVALID_VERSION), is_expired_(false), + is_expired_evicted_(false), allocator_(inner_allocator), external_allocator_(external_allocator) {} @@ -312,6 +314,7 @@ int ObPsStmtInfo::deep_copy(const ObPsStmtInfo& other) ps_item_ = other.ps_item_; tenant_version_ = other.tenant_version_; is_expired_ = other.is_expired_; + is_expired_evicted_ = other.is_expired_evicted_; if (other.get_dep_objs_cnt() > 0) { dep_objs_cnt_ = other.get_dep_objs_cnt(); if (NULL == (dep_objs_ = reinterpret_cast( diff --git a/src/sql/plan_cache/ob_prepare_stmt_struct.h b/src/sql/plan_cache/ob_prepare_stmt_struct.h index 89af0417cb13efde17f572716196378db93b50aa..2d2386d7aaec2a8def1393c148d880e79eeb5ff9 100644 --- a/src/sql/plan_cache/ob_prepare_stmt_struct.h +++ b/src/sql/plan_cache/ob_prepare_stmt_struct.h @@ -321,14 +321,9 @@ public: { tenant_version_ = tenant_version; } - void set_is_expired() - { - ATOMIC_STORE(&is_expired_, true); - } - int64_t is_expired() - { - return ATOMIC_LOAD(&is_expired_); - } + void set_is_expired() { ATOMIC_STORE(&is_expired_, true); } + bool is_expired() { return ATOMIC_LOAD(&is_expired_); } + bool *get_is_expired_evicted_ptr() { return &is_expired_evicted_; } DECLARE_VIRTUAL_TO_STRING; @@ -351,6 +346,8 @@ private: ObPsStmtItem* ps_item_; int64_t tenant_version_; bool is_expired_; + // check whether has dec ref count for ps info expired + bool is_expired_evicted_; // ObDataBuffer is used to use the internal memory of ObPsStmtItem, // The memory essentially comes from inner_allocator_ in ObPsPlancache diff --git a/src/sql/plan_cache/ob_ps_cache.cpp b/src/sql/plan_cache/ob_ps_cache.cpp index 26f447689a28814cf3ddf986869a513a6ea614df..36d04ce7a4ebd62113196edc26d8d9ff67bc3b96 100644 --- a/src/sql/plan_cache/ob_ps_cache.cpp +++ b/src/sql/plan_cache/ob_ps_cache.cpp @@ -46,19 +46,10 @@ ObPsCache::ObPsCache() ObPsCache::~ObPsCache() { int ret = OB_SUCCESS; - ObSEArray all_stmt_id; - ObGetAllStmtIdOp op(&all_stmt_id); - if (OB_FAIL(stmt_info_map_.foreach_refactored(op))) { - LOG_WARN("traverse stmt_info_map_ failed", K(ret)); - } else if (OB_FAIL(op.get_callback_ret())) { - LOG_WARN("traverse stmt_info_map_ failed", K(ret)); - } else { - for (int64_t i = 0; i < all_stmt_id.count(); ++i) { // ignore ret - if (OB_FAIL(deref_ps_stmt(all_stmt_id.at(i), true /*erase_info*/))) { - LOG_WARN("deref_ps_stmt faield when destroy ObPsCache", K(ret), K(all_stmt_id.at(i)), K(all_stmt_id.count())); - } - } - } + // ps_stmt_id和ps_stmt_info创建时,会给其增加引用计数 + // 现在PsCache要析构了,对所有内部对象减去1,如果引用计数到0,会显式free内存 + cache_evict_all_ps(); + if (NULL != mem_context_) { DESTROY_CONTEXT(mem_context_); mem_context_ = NULL; diff --git a/src/sql/plan_cache/ob_ps_cache_callback.h b/src/sql/plan_cache/ob_ps_cache_callback.h index b46103861961f52690bcc1e10a3f7b65c038b986..39a49e6de70b78b877734e3003c3185b8c67e561 100644 --- a/src/sql/plan_cache/ob_ps_cache_callback.h +++ b/src/sql/plan_cache/ob_ps_cache_callback.h @@ -43,8 +43,14 @@ public: id_time.first = entry.first; id_time.second = entry.second->get_last_closed_timestamp(); if (entry.second->is_expired()) { - if (OB_SUCCESS != (callback_ret_ = expired_ps_->push_back(id_time))) { - SQL_PC_LOG(WARN, "fail to push back key", K_(callback_ret)); + // for expired ps info, only evicted once; + // use cas, because auto cache evict and flush ps cache may concurrent + // processing + if (ATOMIC_BCAS(entry.second->get_is_expired_evicted_ptr(), false, + true)) { + if (OB_SUCCESS != (callback_ret_ = expired_ps_->push_back(id_time))) { + SQL_PC_LOG(WARN, "fail to push back key", K_(callback_ret)); + } } } else { if (OB_SUCCESS != (callback_ret_ = closed_ps_->push_back(id_time))) { diff --git a/src/sql/resolver/dml/ob_column_namespace_checker.cpp b/src/sql/resolver/dml/ob_column_namespace_checker.cpp index c60ed75a954e19551ccf3d0bda69658613c05d02..7360534fc2152d99f44a5f21ead05079d0f4ae37 100644 --- a/src/sql/resolver/dml/ob_column_namespace_checker.cpp +++ b/src/sql/resolver/dml/ob_column_namespace_checker.cpp @@ -295,6 +295,7 @@ int ObColumnNamespaceChecker::find_column_in_single_table( // if databasename or table name is not specified, // we must check the uniqueness of column in the table with the same name bool is_match = true; + LOG_TRACE("column info", K(q_name), K(table_item)); if (!q_name.database_name_.empty()) { if (OB_FAIL(ObResolverUtils::name_case_cmp( params_.session_info_, q_name.database_name_, table_item.database_name_, OB_TABLE_NAME_CLASS, is_match))) { @@ -314,11 +315,6 @@ int ObColumnNamespaceChecker::find_column_in_single_table( params_.session_info_, q_name.tbl_name_, table_item.get_object_name(), OB_TABLE_NAME_CLASS, is_match))) { LOG_WARN("database name case compare failed", K(ret)); } - if (OB_SUCC(ret) && !is_match && !table_item.synonym_name_.empty() && - OB_FAIL(ObResolverUtils::name_case_cmp( - params_.session_info_, q_name.tbl_name_, table_item.synonym_name_, OB_TABLE_NAME_CLASS, is_match))) { - LOG_WARN("database name case compare failed", K(ret)); - } } if (OB_SUCC(ret) && is_match) { if (OB_FAIL(check_column_exists(table_item, q_name.col_name_, is_match))) { diff --git a/src/sql/resolver/dml/ob_dml_resolver.cpp b/src/sql/resolver/dml/ob_dml_resolver.cpp index 7aa540c2e60f1898156135a762f04e222b828cdb..2765afcc34d9e5f966e92e90c9e29ac8849aab93 100644 --- a/src/sql/resolver/dml/ob_dml_resolver.cpp +++ b/src/sql/resolver/dml/ob_dml_resolver.cpp @@ -567,6 +567,7 @@ int ObDMLResolver::resolve_basic_column_item(const TableItem& table_item, const col_expr->set_synonym_db_name(table_item.synonym_db_name_); col_expr->set_synonym_name(table_item.synonym_name_); col_expr->set_column_attr(table_item.get_table_name(), col_schema->get_column_name_str()); + col_expr->set_from_alias_table(!table_item.alias_name_.empty()); col_expr->set_database_name(table_item.database_name_); // column maybe from alias table, so must reset ref id by table id from table_item col_expr->set_ref_id(table_item.table_id_, col_schema->get_column_id()); diff --git a/src/sql/resolver/expr/ob_raw_expr.h b/src/sql/resolver/expr/ob_raw_expr.h index 7f0495e7e6f94b238aacc59229eddec9eaea8dde..637e2a7c64d9b0357a542dc2016e0479e6b526d2 100644 --- a/src/sql/resolver/expr/ob_raw_expr.h +++ b/src/sql/resolver/expr/ob_raw_expr.h @@ -1989,6 +1989,7 @@ public: is_lob_column_(false), is_unpivot_mocked_column_(false), is_hidden_(false), + from_alias_table_(false), real_expr_(nullptr) { set_expr_class(ObExpr::EXPR_COLUMN_REF); @@ -2010,6 +2011,7 @@ public: is_lob_column_(false), is_unpivot_mocked_column_(false), is_hidden_(false), + from_alias_table_(false), real_expr_(nullptr) { set_expr_class(ObExpr::EXPR_COLUMN_REF); @@ -2031,6 +2033,7 @@ public: is_lob_column_(false), is_unpivot_mocked_column_(false), is_hidden_(false), + from_alias_table_(false), real_expr_(nullptr) { set_expr_class(ObExpr::EXPR_COLUMN_REF); @@ -2119,6 +2122,9 @@ public: virtual int do_visit(ObRawExprVisitor& visitor) override; virtual uint64_t hash_internal(uint64_t seed) const; + + bool is_from_alias_table() const { return from_alias_table_; } + void set_from_alias_table(bool value) { from_alias_table_ = value; } inline bool is_generated_column() const { return share::schema::ObSchemaUtils::is_generated_column(column_flags_); @@ -2226,6 +2232,7 @@ private: bool is_lob_column_; // TODO add lob column bool is_unpivot_mocked_column_; // used for unpivot bool is_hidden_; // used for print hidden column + bool from_alias_table_; ObRawExpr* real_expr_; // for oracle virtual table that is mapping a real table }; diff --git a/src/sql/resolver/expr/ob_raw_expr_printer.cpp b/src/sql/resolver/expr/ob_raw_expr_printer.cpp index 2daf06483a53d327b7f8aa37a71b6fb6980a53f9..9336ecfbe0e37c00ea6963f383c095a514860ae7 100644 --- a/src/sql/resolver/expr/ob_raw_expr_printer.cpp +++ b/src/sql/resolver/expr/ob_raw_expr_printer.cpp @@ -280,6 +280,9 @@ int ObRawExprPrinter::print(ObColumnRefRawExpr* expr) is_oracle_mode ? "\"%.*s\".\"%.*s\"" : "`%.*s`.`%.*s`", LEN_AND_PTR(table_name), LEN_AND_PTR(col_name)); } else if (OB_UNLIKELY(only_column_namespace_)) { DATA_PRINTF(is_oracle_mode ? "\"%.*s\"" : "`%.*s`", LEN_AND_PTR(col_name)); + } else if (expr->is_from_alias_table()) { + DATA_PRINTF(is_oracle_mode ? "\"%.*s\".\"%.*s\"" : "`%.*s`.`%.*s`", + LEN_AND_PTR(expr->get_table_name()), LEN_AND_PTR(col_name)); } else { if (!expr->get_synonym_name().empty() && !expr->get_synonym_db_name().empty()) { ObString synonyn_db_name = expr->get_synonym_db_name(); diff --git a/src/sql/session/ob_basic_session_info.h b/src/sql/session/ob_basic_session_info.h index ae02637eaa0ea1a949ad870338986ecc4143a8bf..d2d655c0ae74b7a24d7da5f0858fc4fdf3c77dfd 100644 --- a/src/sql/session/ob_basic_session_info.h +++ b/src/sql/session/ob_basic_session_info.h @@ -1259,48 +1259,31 @@ public: int get_max_allowed_packet(int64_t& max_allowed_pkt) const; int get_net_buffer_length(int64_t& net_buffer_len) const; /// @} - int64_t get_session_info_mem_size() const - { - return block_allocator_.get_total_mem_size(); - } - int64_t get_sys_var_mem_size() const - { - return base_sys_var_alloc_.total(); - } - // for improving cache miss of proxy, nothing to do with the set_partition_hit() above. - ObPartitionHitInfo& partition_hit() - { - return partition_hit_; - } - void set_shadow(bool is_shadow) - { - ATOMIC_STORE(&thread_data_.is_shadow_, is_shadow); - } - bool is_shadow() - { - return ATOMIC_LOAD(&thread_data_.is_shadow_); - } - uint32_t get_version() const - { - return version_; - } - uint32_t get_magic_num() - { - return magic_num_; - } - int64_t get_current_execution_id() const - { - return current_execution_id_; - } - const common::ObCurTraceId::TraceId& get_last_trace_id() const - { - return last_trace_id_; - } - void set_current_execution_id(int64_t execution_id) - { - current_execution_id_ = execution_id; - } - void set_last_trace_id(common::ObCurTraceId::TraceId* trace_id) + int64_t get_session_info_mem_size() const { return block_allocator_.get_total_mem_size(); } + int64_t get_sys_var_mem_size() const { return base_sys_var_alloc_.total(); } + ObPartitionHitInfo &partition_hit() { return partition_hit_; } // 和上面的set_partition_hit没有任何关系 + bool get_err_final_partition_hit(int err_ret) + { + bool is_partition_hit = partition_hit().get_bool(); + if (is_proxy_refresh_location_ret(err_ret)) { + is_partition_hit = false; + } else if (get_is_in_retry() + && is_proxy_refresh_location_ret(retry_info_.get_last_query_retry_err())) { + is_partition_hit = false; + } + return is_partition_hit; + }; + bool is_proxy_refresh_location_ret(int err_ret) { + return common::OB_NOT_MASTER == err_ret; + } + void set_shadow(bool is_shadow) { ATOMIC_STORE(&thread_data_.is_shadow_, is_shadow); } + bool is_shadow() { return ATOMIC_LOAD(&thread_data_.is_shadow_); } + uint32_t get_version() const {return version_;} + uint32_t get_magic_num() {return magic_num_;} + int64_t get_current_execution_id() const { return current_execution_id_; } + const common::ObCurTraceId::TraceId &get_last_trace_id() const { return last_trace_id_; } + void set_current_execution_id(int64_t execution_id) { current_execution_id_ = execution_id; } + void set_last_trace_id(common::ObCurTraceId::TraceId *trace_id) { if (OB_ISNULL(trace_id)) { } else { diff --git a/src/sql/session/ob_sql_session_info.cpp b/src/sql/session/ob_sql_session_info.cpp index f5c1f286a9b12f24b4acb43eb4f9b371eec7c4a3..1cb3093f534e84652811077830fc7e3b6dcde5f6 100644 --- a/src/sql/session/ob_sql_session_info.cpp +++ b/src/sql/session/ob_sql_session_info.cpp @@ -803,7 +803,9 @@ int ObSQLSessionInfo::get_ps_session_info(const ObPsStmtId stmt_id, ObPsSessionI int ObSQLSessionInfo::remove_ps_session_info(const ObPsStmtId stmt_id) { int ret = OB_SUCCESS; - ObPsSessionInfo* session_info = NULL; + ObPsSessionInfo *session_info = NULL; + LOG_TRACE("remove ps session info", K(ret), K(stmt_id), K(get_sessid()), + K(lbt())); if (OB_FAIL(ps_session_info_map_.erase_refactored(stmt_id, &session_info))) { LOG_WARN("ps session info not exist", K(stmt_id)); } else if (OB_ISNULL(session_info)) { diff --git a/unittest/sql/rewrite/result/test_transformer_stmt_after_together.result b/unittest/sql/rewrite/result/test_transformer_stmt_after_together.result index e0ac0027128e4f6747ca104c909aa7fcf93c2397..033ef669077d6c01327ccff6bccb3a619c1980ff 100644 --- a/unittest/sql/rewrite/result/test_transformer_stmt_after_together.result +++ b/unittest/sql/rewrite/result/test_transformer_stmt_after_together.result @@ -65110,8 +65110,8 @@ SQL: select * from vv1; ] }, "is_alias":false, - "alias_name":"(`opt`.`t1`.`c1` + 2)", - "expr_name":"(`opt`.`t1`.`c1` + 2)", + "alias_name":"(`t1`.`c1` + 2)", + "expr_name":"(`t1`.`c1` + 2)", "default": { "NULL":"NULL" }, @@ -65355,7 +65355,7 @@ SQL: select * from vv1; }, "is_alias":false, "alias_name":"c1", - "expr_name":"`opt`.`t1`.`c1`", + "expr_name":"`t1`.`c1`", "default": { "NULL":"NULL" },