diff --git a/src/observer/mysql/obmp_base.cpp b/src/observer/mysql/obmp_base.cpp index a49d289baf..46a3cc4968 100644 --- a/src/observer/mysql/obmp_base.cpp +++ b/src/observer/mysql/obmp_base.cpp @@ -407,6 +407,7 @@ int ObMPBase::do_after_process(sql::ObSQLSessionInfo &session, } // clear tsi warning buffer ob_setup_tsi_warning_buffer(NULL); + session.reset_plsql_exec_time(); return ret; } diff --git a/src/observer/mysql/obmp_query.cpp b/src/observer/mysql/obmp_query.cpp index 2f5ff68497..a2bd81abfc 100644 --- a/src/observer/mysql/obmp_query.cpp +++ b/src/observer/mysql/obmp_query.cpp @@ -712,6 +712,7 @@ OB_INLINE int ObMPQuery::do_process(ObSQLSessionInfo &session, LOG_ERROR("invalid sql engine", K(ret), K(gctx_)); } else { session.set_current_execution_id(GCTX.sql_engine_->get_execution_id()); + session.reset_plsql_exec_time(); result.get_exec_context().set_need_disconnect(true); ctx_.schema_guard_ = schema_guard; retry_ctrl_.set_tenant_local_schema_version(tenant_version); @@ -749,6 +750,7 @@ OB_INLINE int ObMPQuery::do_process(ObSQLSessionInfo &session, LOG_WARN("fail to set session active", K(ret)); } else if (OB_FAIL(gctx_.sql_engine_->stmt_query(sql, ctx_, result))) { exec_start_timestamp_ = ObTimeUtility::current_time(); + session.reset_plsql_exec_time(); if (!THIS_WORKER.need_retry()) { int cli_ret = OB_SUCCESS; retry_ctrl_.test_and_save_retry_state(gctx_, ctx_, result, ret, cli_ret); @@ -780,6 +782,7 @@ OB_INLINE int ObMPQuery::do_process(ObSQLSessionInfo &session, } else { //监控项统计开始 exec_start_timestamp_ = ObTimeUtility::current_time(); + session.reset_plsql_exec_time(); result.get_exec_context().set_plan_start_time(exec_start_timestamp_); // 本分支内如果出错,全部会在response_result内部处理妥当 // 无需再额外处理回复错误包 @@ -942,6 +945,10 @@ OB_INLINE int ObMPQuery::do_process(ObSQLSessionInfo &session, audit_record.params_value_ = params_value_; audit_record.params_value_len_ = params_value_len_; audit_record.is_perf_event_closed_ = !lib::is_diagnose_info_enabled(); + audit_record.plsql_exec_time_ = session.get_plsql_exec_time(); + if (result.is_pl_stmt(result.get_stmt_type()) && OB_NOT_NULL(ObCurTraceId::get_trace_id())) { + audit_record.pl_trace_id_ = *ObCurTraceId::get_trace_id(); + } ObPhysicalPlanCtx *plan_ctx = result.get_exec_context().get_physical_plan_ctx(); if (OB_ISNULL(plan_ctx)) { diff --git a/src/observer/mysql/obmp_stmt_execute.cpp b/src/observer/mysql/obmp_stmt_execute.cpp index ff3bfd27ce..c470ba0735 100644 --- a/src/observer/mysql/obmp_stmt_execute.cpp +++ b/src/observer/mysql/obmp_stmt_execute.cpp @@ -1091,6 +1091,7 @@ int ObMPStmtExecute::execute_response(ObSQLSessionInfo &session, OZ (gctx_.sql_engine_->init_result_set(ctx_, result)); if (OB_SUCCESS != ret || enable_perf_event) { exec_start_timestamp_ = ObTimeUtility::current_time(); + session.reset_plsql_exec_time(); } if (OB_SUCC(ret)) { ObPLExecCtx pl_ctx(cursor->get_allocator(), &result.get_exec_context(), NULL/*params*/, @@ -1156,6 +1157,7 @@ int ObMPStmtExecute::execute_response(ObSQLSessionInfo &session, //监控项统计开始 exec_start_timestamp_ = ObTimeUtility::current_time(); result.get_exec_context().set_plan_start_time(exec_start_timestamp_); + session.reset_plsql_exec_time(); // 本分支内如果出错,全部会在response_result内部处理妥当 // 无需再额外处理回复错误包 @@ -1232,6 +1234,7 @@ int ObMPStmtExecute::do_process(ObSQLSessionInfo &session, task_ctx->set_min_cluster_version(GET_MIN_CLUSTER_VERSION()); ctx_.retry_times_ = retry_ctrl_.get_retry_times(); + session.reset_plsql_exec_time(); if (OB_ISNULL(ctx_.schema_guard_)) { ret = OB_INVALID_ARGUMENT; LOG_WARN("newest schema is NULL", K(ret)); @@ -1359,6 +1362,10 @@ int ObMPStmtExecute::do_process(ObSQLSessionInfo &session, audit_record.params_value_ = params_value_; audit_record.params_value_len_ = params_value_len_; audit_record.is_perf_event_closed_ = !lib::is_diagnose_info_enabled(); + audit_record.plsql_exec_time_ = session.get_plsql_exec_time(); + if (result.is_pl_stmt(result.get_stmt_type()) && OB_NOT_NULL(ObCurTraceId::get_trace_id())) { + audit_record.pl_trace_id_ = *ObCurTraceId::get_trace_id(); + } ObPhysicalPlanCtx *plan_ctx = result.get_exec_context().get_physical_plan_ctx(); if (OB_NOT_NULL(plan_ctx)) { diff --git a/src/observer/mysql/obsm_utils.cpp b/src/observer/mysql/obsm_utils.cpp index 87f0a9b263..756d5a5037 100644 --- a/src/observer/mysql/obsm_utils.cpp +++ b/src/observer/mysql/obsm_utils.cpp @@ -220,7 +220,7 @@ int ObSMUtils::cell_str( if (OB_ISNULL(field) || OB_ISNULL(schema_guard)) { ret = OB_ERR_UNEXPECTED; OB_LOG(WARN, "complex type need field and schema guard not null", K(ret)); - } else if (field->type_.get_type() != ObExtendType) { + } else if (BINARY == type && field->type_.get_type() != ObExtendType) { ret = OB_ERR_UNEXPECTED; OB_LOG(WARN, "field type is not ObExtended", K(ret)); } else if (field->type_owner_.empty() || field->type_name_.empty()) { @@ -245,28 +245,40 @@ int ObSMUtils::cell_str( K(ret)); } else { /*do nothing*/ } #ifdef OB_BUILD_ORACLE_PL - } else if (obj.is_pl_extend() - && PL_NESTED_TABLE_TYPE == obj.get_meta().get_extend_type()) { - // anonymous collection - ObPLCollection *coll = reinterpret_cast(obj.get_ext()); - ObNestedTableType *nested_type = NULL; - ObPLDataType element_type; - if (OB_ISNULL(nested_type = - reinterpret_cast(allocator.alloc(sizeof(ObNestedTableType))))) { - ret = OB_ALLOCATE_MEMORY_FAILED; - OB_LOG(WARN, "failed to alloc memory for ObNestedTableType", K(ret)); - } else if (OB_ISNULL(coll)) { - ret = OB_ERR_UNEXPECTED; - OB_LOG(WARN, "coll is null", K(ret)); - } else if (FALSE_IT(new (nested_type) ObNestedTableType())) { - } else if (FALSE_IT(element_type.reset())) { - } else if (FALSE_IT(element_type.set_data_type(coll->get_element_type()))) { - } else if (FALSE_IT(nested_type->set_element_type(element_type))) { - } else if (OB_FAIL(nested_type->serialize( - *schema_guard, dtc_params.tz_info_, type, src, buf, len, pos))) { - OB_LOG(WARN, "failed to serialize anonymous collection", K(ret)); + } else if (obj.is_pl_extend()) { + if (TEXT == type && (PL_VARRAY_TYPE == obj.get_meta().get_extend_type() + || PL_NESTED_TABLE_TYPE == obj.get_meta().get_extend_type() + || PL_ASSOCIATIVE_ARRAY_TYPE == obj.get_meta().get_extend_type() + || PL_RECORD_TYPE == obj.get_meta().get_extend_type())) { + if (OB_FAIL(extend_cell_str(buf, len, src, type, pos, + dtc_params, field, schema_guard, tenant_id))) { + OB_LOG(WARN, "extend type cell string fail.", K(ret)); + } + } else if (BINARY == type && PL_NESTED_TABLE_TYPE == obj.get_meta().get_extend_type()) { + // anonymous collection + ObPLCollection *coll = reinterpret_cast(obj.get_ext()); + ObNestedTableType *nested_type = NULL; + ObPLDataType element_type; + if (OB_ISNULL(nested_type = + reinterpret_cast(allocator.alloc(sizeof(ObNestedTableType))))) { + ret = OB_ALLOCATE_MEMORY_FAILED; + OB_LOG(WARN, "failed to alloc memory for ObNestedTableType", K(ret)); + } else if (OB_ISNULL(coll)) { + ret = OB_ERR_UNEXPECTED; + OB_LOG(WARN, "coll is null", K(ret)); + } else if (FALSE_IT(new (nested_type) ObNestedTableType())) { + } else if (FALSE_IT(element_type.reset())) { + } else if (FALSE_IT(element_type.set_data_type(coll->get_element_type()))) { + } else if (FALSE_IT(nested_type->set_element_type(element_type))) { + } else if (OB_FAIL(nested_type->serialize( + *schema_guard, dtc_params.tz_info_, type, src, buf, len, pos))) { + OB_LOG(WARN, "failed to serialize anonymous collection", K(ret)); + } else { + OB_LOG(DEBUG, "success to serialize anonymous collection", K(ret)); + } } else { - OB_LOG(DEBUG, "success to serialize anonymous collection", K(ret)); + ret = OB_NOT_SUPPORTED; + OB_LOG(WARN, "this extend type is not support", KPC(field), K(type), K(obj.get_meta().get_extend_type()), K(ret)); } #endif } else { @@ -553,3 +565,62 @@ int ObSMUtils::get_ob_type(ObObjType &ob_type, EMySQLFieldType mysql_type, const } return ret; } + +int ObSMUtils::extend_cell_str(char *buf, const int64_t len, + char *src, + MYSQL_PROTOCOL_TYPE type, int64_t &pos, + const ObDataTypeCastParams &dtc_params, + const ObField *field, + ObSchemaGetterGuard *schema_guard, + uint64_t tenant_id) +{ + int ret = OB_SUCCESS; + common::ObArenaAllocator allocator; + const pl::ObUserDefinedType *user_type = NULL; + const ObUDTTypeInfo *udt_info = NULL; + const int64_t type_id = field->accuracy_.get_accuracy(); + if (OB_FAIL(schema_guard->get_udt_info(tenant_id, type_id, udt_info))) { + OB_LOG(WARN, "get user type fail.", K(type_id), K(ret)); + } else if (NULL == udt_info) { + ret = OB_ERR_UNEXPECTED; + OB_LOG(WARN, "faild to get udt info.", K(ret)); + } else if (OB_FAIL(udt_info->transform_to_pl_type(allocator, user_type))) { + OB_LOG(WARN, "faild to transform to pl type", K(ret)); + } else if (NULL == user_type) { + ret = OB_ERR_UNEXPECTED; + OB_LOG(WARN, "faild to get user type.", K(ret)); + } else if (len - pos < user_type->get_name().length() + 12) { + // 12 is the length of string length and '(' and ')' + // string length is reserve a const value of 10 + ret = OB_SIZE_OVERFLOW; + OB_LOG(WARN, "size over flow.", K(ret), K(len), K(user_type->get_name())); + } else { + ObArenaAllocator alloc; + char* tmp_buf = static_cast(alloc.alloc(len - pos - 12)); + int64_t tmp_pos = 0; + MEMCPY(tmp_buf + tmp_pos, user_type->get_name().ptr(), user_type->get_name().length()); + tmp_pos += user_type->get_name().length(); + MEMCPY(tmp_buf + tmp_pos, "(", 1); + tmp_pos += 1; + const_cast(user_type)->set_charset(static_cast(field->charsetnr_)); + if (OB_FAIL(user_type->serialize(*schema_guard, dtc_params.tz_info_, type, src, tmp_buf, len, tmp_pos))) { + OB_LOG(WARN, "failed to serialize", K(ret)); + } else if (len - pos > tmp_pos + 1) { + MEMCPY(tmp_buf + tmp_pos, ")", 1); + tmp_pos += 1; + } else { + ret = OB_ERR_UNEXPECTED; + OB_LOG(WARN, "tmp_buf length is not enough.", K(ret), K(pos), K(len), K(tmp_pos)); + } + if (OB_FAIL(ret)) { + // do nothing + } else if (OB_FAIL(ObMySQLUtil::store_length(buf, len, tmp_pos, pos))) { + OB_LOG(WARN, "store length fail.", K(ret), K(pos), K(len), K(tmp_pos)); + } else { + MEMCPY(buf + pos, tmp_buf, tmp_pos); + pos += tmp_pos; + } + const_cast(user_type)->reset_charset(); + } + return ret; +} diff --git a/src/observer/mysql/obsm_utils.h b/src/observer/mysql/obsm_utils.h index d812aae622..94cab23290 100644 --- a/src/observer/mysql/obsm_utils.h +++ b/src/observer/mysql/obsm_utils.h @@ -68,6 +68,10 @@ public: static int get_ob_type(ObObjType &ob_type, obmysql::EMySQLFieldType mysql_type, const bool is_unsigned = false); + + static int extend_cell_str(char *buf, const int64_t len, char *src, obmysql::MYSQL_PROTOCOL_TYPE type, int64_t &pos, + const ObDataTypeCastParams &dtc_params, const ObField *field, + share::schema::ObSchemaGetterGuard *schema_guard, uint64_t tenant_id); }; } // end of namespace common diff --git a/src/observer/ob_inner_sql_connection.cpp b/src/observer/ob_inner_sql_connection.cpp index d20ef1ec3a..89a19885a1 100644 --- a/src/observer/ob_inner_sql_connection.cpp +++ b/src/observer/ob_inner_sql_connection.cpp @@ -531,6 +531,13 @@ int ObInnerSQLConnection::process_record(sql::ObResultSet &result_set, ObExecStatUtils::record_exec_timestamp(time_record, first_record, exec_timestamp); audit_record.exec_timestamp_ = exec_timestamp; audit_record.exec_timestamp_.update_stage_time(); + audit_record.plsql_exec_time_ = session.get_plsql_exec_time(); + if (audit_record.pl_trace_id_.is_invalid() && + result_set.is_pl_stmt(result_set.get_stmt_type()) && + OB_NOT_NULL(ObCurTraceId::get_trace_id())) { + audit_record.pl_trace_id_ = *ObCurTraceId::get_trace_id(); + } + session.update_pure_sql_exec_time(audit_record.exec_timestamp_.elapsed_t_); if (enable_perf_event) { record_stat(session, result_set.get_stmt_type(), is_from_pl); diff --git a/src/observer/virtual_table/ob_gv_sql.cpp b/src/observer/virtual_table/ob_gv_sql.cpp index 1ecbd2484b..0f06dc97d5 100644 --- a/src/observer/virtual_table/ob_gv_sql.cpp +++ b/src/observer/virtual_table/ob_gv_sql.cpp @@ -147,9 +147,8 @@ int ObGVSql::fill_cells(const ObILibCacheObject *cache_obj, const ObPlanCache &p ObString ipstr; ObString stmt; const ObPhysicalPlan *plan = NULL; - const pl::ObPLFunction *pl_func = NULL; - const pl::ObPLPackage *pl_pkg = NULL; bool cache_stat_updated = false; + const pl::ObPLCacheObject *pl_object = NULL; if (OB_ISNULL(cache_obj) || OB_ISNULL(allocator_)) { ret = OB_INVALID_ARGUMENT; SERVER_LOG(WARN, "invalid argument", K(cache_obj), K(ret)); @@ -160,17 +159,13 @@ int ObGVSql::fill_cells(const ObILibCacheObject *cache_obj, const ObPlanCache &p } else { cache_stat_updated = plan->stat_.is_updated(); } - } else if (cache_obj->is_pkg()) { // pl package - if (OB_ISNULL(pl_pkg = dynamic_cast(cache_obj))) { + } else if ((cache_obj->get_ns() >= ObLibCacheNameSpace::NS_PRCR && cache_obj->get_ns() <= ObLibCacheNameSpace::NS_PKG) || + cache_obj->get_ns() == ObLibCacheNameSpace::NS_CALLSTMT) { + if (OB_ISNULL(pl_object = dynamic_cast(cache_obj))) { ret = OB_ERR_UNEXPECTED; SERVER_LOG(WARN, "unexpected null pl pkg", K(ret)); - } - } else if (cache_obj->is_anon() || cache_obj->is_sfc() || cache_obj->is_prcr()) { // pl function - if (OB_ISNULL(pl_func = dynamic_cast(cache_obj))) { - ret = OB_ERR_UNEXPECTED; - SERVER_LOG(WARN, "unexpected null pl function", K(ret)); } else { - cache_stat_updated = pl_func->get_stat().is_updated(); + cache_stat_updated = pl_object->get_stat().is_updated(); } } else { ret = OB_ERR_UNEXPECTED; @@ -212,9 +207,9 @@ int ObGVSql::fill_cells(const ObILibCacheObject *cache_obj, const ObPlanCache &p case share::ALL_VIRTUAL_PLAN_STAT_CDE::SQL_ID: { if (cache_stat_updated) { ObString sql_id; - if (OB_NOT_NULL(pl_func)) { + if (OB_NOT_NULL(pl_object)) { if (OB_FAIL(ob_write_string(*allocator_, - pl_func->get_stat().sql_id_, + pl_object->get_stat().sql_id_, sql_id))) { SERVER_LOG(ERROR, "copy sql_id failed", K(ret)); } else { @@ -241,8 +236,10 @@ int ObGVSql::fill_cells(const ObILibCacheObject *cache_obj, const ObPlanCache &p case share::ALL_VIRTUAL_PLAN_STAT_CDE::TYPE: { if (cache_obj->is_sql_crsr()) { cells[i].set_int(plan->get_plan_type()); + } else if (NULL != pl_object) { + cells[i].set_int(pl_object->get_stat().type_); } else { - cells[i].set_int(cache_obj->get_ns()); + cells[i].set_int(0); } break; } @@ -301,10 +298,24 @@ int ObGVSql::fill_cells(const ObILibCacheObject *cache_obj, const ObPlanCache &p cells[i].set_collation_type(ObCharset::get_default_collation( ObCharset::get_default_charset())); } - } else if (cache_obj->is_anon()) { - if (OB_FAIL(ObCharset::charset_convert(row_calc_buf_, - pl_func->get_stat().raw_sql_, - pl_func->get_stat().sql_cs_type_, + } else if (cache_obj->is_anon() || ObLibCacheNameSpace::NS_CALLSTMT == cache_obj->get_ns()) { + if (OB_FAIL(ObCharset::charset_convert(*allocator_, + pl_object->get_stat().raw_sql_, + pl_object->get_stat().sql_cs_type_, + ObCharset::get_system_collation(), + statement, + ObCharset::COPY_STRING_ON_SAME_CHARSET | ObCharset::REPLACE_UNKNOWN_CHARACTER))) { + SERVER_LOG(WARN, "convert raw_sql failed", K(ret)); + } else { + cells[i].set_lob_value(ObLongTextType, statement.ptr(), + static_cast(statement.length())); + cells[i].set_collation_type(ObCharset::get_default_collation( + ObCharset::get_default_charset())); + } + } else if (NULL != pl_object) { + if (OB_FAIL(ObCharset::charset_convert(*allocator_, + pl_object->get_stat().name_, + pl_object->get_stat().sql_cs_type_, ObCharset::get_system_collation(), statement, ObCharset::COPY_STRING_ON_SAME_CHARSET | ObCharset::REPLACE_UNKNOWN_CHARACTER))) { @@ -327,8 +338,8 @@ int ObGVSql::fill_cells(const ObILibCacheObject *cache_obj, const ObPlanCache &p ObString tmp_sql; ObCollationType tmp_sql_cs_type; if (cache_obj->is_anon()) { - tmp_sql = pl_func->get_stat().raw_sql_; - tmp_sql_cs_type = pl_func->get_stat().sql_cs_type_; + tmp_sql = pl_object->get_stat().raw_sql_; + tmp_sql_cs_type = pl_object->get_stat().sql_cs_type_; } else { tmp_sql = plan->stat_.raw_sql_; tmp_sql_cs_type = plan->stat_.sql_cs_type_; @@ -448,8 +459,8 @@ int ObGVSql::fill_cells(const ObILibCacheObject *cache_obj, const ObPlanCache &p cells[i].set_null(); } else if (cache_obj->is_sql_crsr()) { gen_time = plan->stat_.gen_time_; - } else if (NULL != pl_func) { - gen_time = pl_func->get_stat().gen_time_; + } else if (NULL != pl_object) { + gen_time = pl_object->get_stat().gen_time_; } cells[i].set_timestamp(gen_time); break; @@ -459,6 +470,8 @@ int ObGVSql::fill_cells(const ObILibCacheObject *cache_obj, const ObPlanCache &p cells[i].set_null(); } else if (cache_obj->is_sql_crsr()) { cells[i].set_int(plan->stat_.schema_version_); + } else if (NULL != pl_object) { + cells[i].set_int(pl_object->get_stat().schema_version_); } else { cells[i].set_int(0); } @@ -470,8 +483,8 @@ int ObGVSql::fill_cells(const ObILibCacheObject *cache_obj, const ObPlanCache &p cells[i].set_null(); } else if (cache_obj->is_sql_crsr()) { last_active_time = plan->stat_.last_active_time_; - } else if (NULL != pl_func) { - last_active_time = pl_func->get_stat().last_active_time_; + } else if (NULL != pl_object) { + last_active_time = pl_object->get_stat().last_active_time_; } cells[i].set_timestamp(last_active_time); break; @@ -485,6 +498,12 @@ int ObGVSql::fill_cells(const ObILibCacheObject *cache_obj, const ObPlanCache &p } else { cells[i].set_int(0); } + } else if (NULL != pl_object) { + if (pl_object->get_stat().execute_times_ != 0) { + cells[i].set_int(pl_object->get_stat().elapsed_time_ / pl_object->get_stat().execute_times_); + } else { + cells[i].set_int(0); + } } else { cells[i].set_int(0); } @@ -495,6 +514,8 @@ int ObGVSql::fill_cells(const ObILibCacheObject *cache_obj, const ObPlanCache &p cells[i].set_null(); } else if (cache_obj->is_sql_crsr()) { cells[i].set_timestamp(plan->stat_.slowest_exec_time_); + } else if (NULL != pl_object) { + cells[i].set_timestamp(pl_object->get_stat().slowest_exec_time_); } else { cells[i].set_timestamp(0); } @@ -505,6 +526,8 @@ int ObGVSql::fill_cells(const ObILibCacheObject *cache_obj, const ObPlanCache &p cells[i].set_null(); } else if (cache_obj->is_sql_crsr()) { cells[i].set_int(plan->stat_.slowest_exec_usec_); + } else if (NULL != pl_object) { + cells[i].set_int(pl_object->get_stat().slowest_exec_usec_); } else { cells[i].set_int(0); } @@ -526,8 +549,8 @@ int ObGVSql::fill_cells(const ObILibCacheObject *cache_obj, const ObPlanCache &p cells[i].set_null(); } else if (cache_obj->is_sql_crsr()) { hit_count = plan->stat_.hit_count_; - } else if (NULL != pl_func) { - hit_count = pl_func->get_stat().hit_count_; + } else if (NULL != pl_object) { + hit_count = pl_object->get_stat().hit_count_; } cells[i].set_int(hit_count); break; @@ -549,6 +572,8 @@ int ObGVSql::fill_cells(const ObILibCacheObject *cache_obj, const ObPlanCache &p cells[i].set_null(); } else if (cache_obj->is_sql_crsr()) { cells[i].set_int(plan->stat_.execute_times_); + } else if (NULL != pl_object) { + cells[i].set_int(pl_object->get_stat().execute_times_); } else { cells[i].set_int(0); } @@ -629,6 +654,8 @@ int ObGVSql::fill_cells(const ObILibCacheObject *cache_obj, const ObPlanCache &p cells[i].set_null(); } else if (cache_obj->is_sql_crsr()) { cells[i].set_uint64(static_cast(plan->stat_.elapsed_time_)); + } else if (NULL != pl_object) { + cells[i].set_uint64(static_cast(pl_object->get_stat().elapsed_time_)); } else { cells[i].set_uint64(0); } @@ -806,8 +833,8 @@ int ObGVSql::fill_cells(const ObILibCacheObject *cache_obj, const ObPlanCache &p cells[i].set_null(); } else if (cache_obj->is_sql_crsr()) { cells[i].set_int(plan->stat_.ps_stmt_id_); - } else if (cache_obj->is_anon()) { - cells[i].set_int(pl_func->get_stat().pl_schema_id_); + } else if (NULL != pl_object) { + cells[i].set_int(pl_object->get_stat().ps_stmt_id_); } else { cells[i].set_int(OB_INVALID_ID); } @@ -865,7 +892,32 @@ int ObGVSql::fill_cells(const ObILibCacheObject *cache_obj, const ObPlanCache &p } case share::ALL_VIRTUAL_PLAN_STAT_CDE::OBJECT_TYPE: { ObString type_name; - if (OB_FAIL(ObPlanCacheObject::type_to_name(cache_obj->get_ns(), *allocator_, type_name))) { + if (NS_PKG == cache_obj->get_ns()) { + uint64_t package_id = pl_object->get_stat().pl_schema_id_; + if (package_id != common::OB_INVALID_ID && (package_id & common::OB_MOCK_TRIGGER_PACKAGE_ID_MASK) != 0) { // trigger + char *buf = NULL; + int32_t str_len = (int32_t)std::strlen("TRIGGER"); + if (OB_ISNULL(buf = static_cast(allocator_->alloc(str_len)))) { + ret = OB_ALLOCATE_MEMORY_FAILED; + SERVER_LOG(ERROR, "failed to allocate memory", K(ret), K(str_len)); + } else { + MEMCPY(buf, "TRIGGER", str_len); + type_name.assign(buf, str_len); + } + } else if (package_id != common::OB_INVALID_ID && (package_id & common::OB_MOCK_OBJECT_PACAKGE_ID_MASK) != 0) { // udt + char *buf = NULL; + int32_t str_len = (int32_t)std::strlen("TYPE"); + if (OB_ISNULL(buf = static_cast(allocator_->alloc(str_len)))) { + ret = OB_ALLOCATE_MEMORY_FAILED; + SERVER_LOG(ERROR, "failed to allocate memory", K(ret), K(str_len)); + } else { + MEMCPY(buf, "TYPE", str_len); + type_name.assign(buf, str_len); + } + } else if (OB_FAIL(ObPlanCacheObject::type_to_name(cache_obj->get_ns(), *allocator_, type_name))) { + SERVER_LOG(ERROR, "failed to get type_name", K(ret)); + } + } else if (OB_FAIL(ObPlanCacheObject::type_to_name(cache_obj->get_ns(), *allocator_, type_name))) { SERVER_LOG(ERROR, "failed to get type_name", K(ret)); } else { // do nothing @@ -967,10 +1019,11 @@ int ObGVSql::fill_cells(const ObILibCacheObject *cache_obj, const ObPlanCache &p } case share::ALL_VIRTUAL_PLAN_STAT_CDE::PL_SCHEMA_ID: { uint64_t pl_schema_id = 0; - if (cache_obj->is_anon() || cache_obj->is_sfc() || cache_obj->is_prcr()) { - pl_schema_id = pl_func->get_stat().pl_schema_id_; - } else if (cache_obj->is_pkg()) { - pl_schema_id = pl_pkg->get_id(); + if (cache_obj->is_anon() || + cache_obj->is_sfc() || + cache_obj->is_prcr() || + cache_obj->is_pkg()) { + pl_schema_id = pl_object->get_stat().pl_schema_id_; } cells[i].set_uint64(pl_schema_id); break; @@ -1018,6 +1071,9 @@ int ObGVSql::fill_cells(const ObILibCacheObject *cache_obj, const ObPlanCache &p } case share::ALL_VIRTUAL_PLAN_STAT_CDE::COMPILE_TIME: { uint64_t compile_time = 0; + if (NULL != pl_object) { + compile_time = static_cast(pl_object->get_stat().compile_time_); + } cells[i].set_uint64(compile_time); break; } diff --git a/src/observer/virtual_table/ob_gv_sql_audit.cpp b/src/observer/virtual_table/ob_gv_sql_audit.cpp index 02cd1413ff..051358624c 100644 --- a/src/observer/virtual_table/ob_gv_sql_audit.cpp +++ b/src/observer/virtual_table/ob_gv_sql_audit.cpp @@ -1049,10 +1049,18 @@ int ObGvSqlAudit::fill_cells(obmysql::ObMySQLRequestRecord &record) } break; case PL_TRACE_ID: { - cells[cell_idx].set_null(); + const ObCurTraceId::TraceId &pl_trace_id = record.data_.pl_trace_id_; + if (pl_trace_id.is_invalid()) { + cells[cell_idx].set_null(); + } else { + int64_t len = pl_trace_id.to_string(pl_trace_id_, sizeof(pl_trace_id_)); + cells[cell_idx].set_varchar(pl_trace_id_, len); + cells[cell_idx].set_collation_type(ObCharset::get_default_collation( + ObCharset::get_default_charset())); + } } break; case PLSQL_EXEC_TIME: { - cells[cell_idx].set_int(0); + cells[cell_idx].set_int(record.data_.plsql_exec_time_); } break; case NETWORK_WAIT_TIME: { cells[cell_idx].set_null(); diff --git a/src/observer/virtual_table/ob_gv_sql_audit.h b/src/observer/virtual_table/ob_gv_sql_audit.h index 6b44e636d6..7fe48490ff 100644 --- a/src/observer/virtual_table/ob_gv_sql_audit.h +++ b/src/observer/virtual_table/ob_gv_sql_audit.h @@ -203,6 +203,7 @@ private: char client_ip_[common::MAX_IP_ADDR_LENGTH + 2]; char user_client_ip_[common::MAX_IP_ADDR_LENGTH + 2]; char trace_id_[128]; + char pl_trace_id_[128]; //max wait event columns bool is_first_get_; diff --git a/src/pl/ob_pl.cpp b/src/pl/ob_pl.cpp index 21d59203ab..79d2475a12 100644 --- a/src/pl/ob_pl.cpp +++ b/src/pl/ob_pl.cpp @@ -609,6 +609,9 @@ int ObPLContext::init(ObSQLSessionInfo &session_info, OX (is_autonomous_ = routine->is_autonomous()); OX (is_function_or_trigger_ = is_function_or_trigger); } + if (OB_SUCC(ret) && OB_NOT_NULL(ObCurTraceId::get_trace_id())) { + trace_id_.set(*ObCurTraceId::get_trace_id()); + } OZ (session_info.get_pl_block_timeout(pl_block_timeout)); OX (pl_block_timeout = std::min(pl_block_timeout, OB_MAX_USER_SPECIFIED_TIMEOUT)); @@ -1504,14 +1507,22 @@ int ObPL::execute(ObExecContext &ctx, OX (*result = local_result); } + //当前层 pl 执行时间 int64_t execute_end = ObTimeUtility::current_time(); + pl.add_pl_exec_time(execute_end - execute_start - pl.get_pure_sql_exec_time(), is_called_from_sql); + #ifndef NDEBUG LOG_INFO(">>>>>>>>>Execute Time: ", K(ret), - K(routine.get_package_id()), K(routine.get_routine_id()), K(routine.get_package_name()), K(routine.get_function_name()), K(execute_end - execute_start)); + K(routine.get_package_id()), K(routine.get_routine_id()), K(routine.get_package_name()), K(routine.get_function_name()), K(execute_end - execute_start), + K(is_top_stack), K(execute_end - execute_start - pl.get_pure_sql_exec_time()), K(pl.get_pure_sql_exec_time()), + K(pl.get_plsql_exec_time()), K(pl.get_sub_plsql_exec_time())); #else LOG_DEBUG(">>>>>>>>Execute Time: ", K(ret), - K(routine.get_package_id()), K(routine.get_routine_id()), K(routine.get_package_name()), K(routine.get_function_name()), K(execute_end - execute_start)); + K(routine.get_package_id()), K(routine.get_routine_id()), K(routine.get_package_name()), K(routine.get_function_name()), K(execute_end - execute_start), + K(is_top_stack), K(execute_end - execute_start - pl.get_pure_sql_exec_time()), K(pl.get_pure_sql_exec_time()), K(pl.get_plsql_exec_time()), + K(pl.get_sub_plsql_exec_time())); #endif + OX (routine.update_execute_time(execute_end - execute_start)); return ret; } @@ -1726,6 +1737,40 @@ int ObPL::parameter_anonymous_block(ObExecContext &ctx, return ret; } +struct ObPLExecTraceIdGuard { + ObPLExecTraceIdGuard(const ObCurTraceId::TraceId &trace_id, + uint64_t package_id, uint64_t routine_id) + : package_id_(package_id), routine_id_(routine_id) { + int ret = OB_SUCCESS; + if (trace_id.is_valid() + && OB_NOT_NULL(ObCurTraceId::get_trace_id()) + && !(trace_id == *ObCurTraceId::get_trace_id())) { + origin_trace_id_.set(*ObCurTraceId::get_trace_id()); + + // log with SQL trace_id + LOG_TRACE("executing pl, restore trace_id to pl trace_id", + K(package_id_), K(routine_id_), + "from", origin_trace_id_, "to", trace_id); + + ObCurTraceId::get_trace_id()->set(trace_id); + } + } + + ~ObPLExecTraceIdGuard() { + int ret = OB_SUCCESS; + if (origin_trace_id_.is_valid() && OB_NOT_NULL(ObCurTraceId::get_trace_id())) { + ObCurTraceId::TraceId curr_trace_id = *ObCurTraceId::get_trace_id(); + ObCurTraceId::get_trace_id()->set(origin_trace_id_); + LOG_TRACE("pl execution finished, trace id restored from pl trace_id to sql trace_id", + K(package_id_), K(routine_id_), + "from", curr_trace_id, "to", origin_trace_id_); + } + } + ObCurTraceId::TraceId origin_trace_id_; + uint64_t package_id_; + uint64_t routine_id_; +}; + // for execute anonymous int ObPL::execute(ObExecContext &ctx, ParamStore ¶ms, const ObStmtNodeTree *block) { @@ -1812,6 +1857,13 @@ int ObPL::execute(ObExecContext &ctx, ParamStore ¶ms, const ObStmtNodeTree * // prepare it. if (OB_SUCC(ret)) { SMART_VAR(ObPLContext, stack_ctx) { + ObCurTraceId::TraceId parent_trace_id; + if (nullptr != ctx.get_my_session()->get_pl_context()) { + ObPLContext *curr = ctx.get_my_session()->get_pl_context()->get_top_stack_ctx(); + parent_trace_id.set(curr->get_trace_id()); + } + ObPLExecTraceIdGuard trace_guard(parent_trace_id, OB_INVALID_ID, OB_INVALID_ID); + LinkPLStackGuard link_stack_guard(ctx, stack_ctx); OZ (stack_ctx.init(*(ctx.get_my_session()), ctx, routine, false)); @@ -1917,6 +1969,13 @@ int ObPL::execute(ObExecContext &ctx, // prepare it... if (OB_SUCC(ret)) { SMART_VAR(ObPLContext, stack_ctx) { + ObCurTraceId::TraceId parent_trace_id; + if (nullptr != ctx.get_my_session()->get_pl_context()) { + ObPLContext *curr = ctx.get_my_session()->get_pl_context()->get_top_stack_ctx(); + parent_trace_id.set(curr->get_trace_id()); + } + ObPLExecTraceIdGuard trace_guard(parent_trace_id, OB_INVALID_ID, stmt_id); + LinkPLStackGuard link_stack_guard(ctx, stack_ctx); OZ (stack_ctx.init(*(ctx.get_my_session()), ctx, routine, false)); @@ -1975,24 +2034,30 @@ int ObPL::execute(ObExecContext &ctx, ObPLFunction *local_routine = NULL; ObCacheObjGuard cacheobj_guard(PL_ROUTINE_HANDLE); int64_t old_worker_timeout_ts = 0; + ObCurTraceId::TraceId parent_trace_id; /* !!! * PL,req_timeinfo_guard一定要在执行前定义 * !!! */ - if (OB_ISNULL(ctx.get_my_session()->get_pl_context())) { - // set work timeout for compile it only top level store routine - int64_t pl_block_timeout = 0; - int64_t query_start_time = ctx.get_my_session()->get_query_start_time(); - old_worker_timeout_ts = THIS_WORKER.get_timeout_ts(); - OZ (ctx.get_my_session()->get_pl_block_timeout(pl_block_timeout)); - if (OB_SUCC(ret) && pl_block_timeout > OB_MAX_USER_SPECIFIED_TIMEOUT) { - pl_block_timeout = OB_MAX_USER_SPECIFIED_TIMEOUT; - } - OX (THIS_WORKER.set_timeout_ts(query_start_time + pl_block_timeout)); - } - - observer::ObReqTimeGuard req_timeinfo_guard; SMART_VAR(ObPLContext, stack_ctx) { + if (OB_ISNULL(ctx.get_my_session()->get_pl_context())) { + // set work timeout for compile it only top level store routine + int64_t pl_block_timeout = 0; + int64_t query_start_time = ctx.get_my_session()->get_query_start_time(); + old_worker_timeout_ts = THIS_WORKER.get_timeout_ts(); + OZ (ctx.get_my_session()->get_pl_block_timeout(pl_block_timeout)); + if (OB_SUCC(ret) && pl_block_timeout > OB_MAX_USER_SPECIFIED_TIMEOUT) { + pl_block_timeout = OB_MAX_USER_SPECIFIED_TIMEOUT; + } + OX (THIS_WORKER.set_timeout_ts(query_start_time + pl_block_timeout)); + } else { + ObPLContext *curr = ctx.get_my_session()->get_pl_context()->get_top_stack_ctx(); + parent_trace_id.set(curr->get_trace_id()); + } + ObPLExecTraceIdGuard trace_guard(parent_trace_id, package_id, routine_id); + + observer::ObReqTimeGuard req_timeinfo_guard; + LinkPLStackGuard link_stack_guard(ctx, stack_ctx); CHECK_COMPATIBILITY_MODE(ctx.get_my_session()); @@ -2233,6 +2298,8 @@ int ObPL::get_pl_function(ObExecContext &ctx, OX (routine = static_cast(cacheobj_guard.get_cache_obj())); CK (OB_NOT_NULL(routine)); if (OB_SUCC(ret) && routine->get_can_cached()) { + routine->get_stat_for_update().name_ = pc_ctx.raw_sql_; + routine->get_stat_for_update().type_ = ObPLCacheObjectType::ANONYMOUS_BLOCK_TYPE; OZ (add_pl_lib_cache(routine, pc_ctx)); // add sql key to plan cache //OX (pc_ctx.key_.name_ = sql); @@ -2347,6 +2414,8 @@ int ObPL::get_pl_function(ObExecContext &ctx, CK (OB_NOT_NULL(routine)); if (OB_SUCC(ret) && routine->get_can_cached()) { + routine->get_stat_for_update().name_ = routine->get_function_name(); + routine->get_stat_for_update().type_ = ObPLCacheObjectType::STANDALONE_ROUTINE_TYPE; OZ (add_pl_lib_cache(routine, pc_ctx)); } OX (need_update_schema = true); @@ -2676,6 +2745,30 @@ int ObPLExecState::deep_copy_result_if_need() return ret; } +int ObPLExecState::add_pl_exec_time(int64_t pl_exec_time, bool is_called_from_sql) +{ + int ret = OB_SUCCESS; + if (OB_ISNULL(top_context_)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("top context is null. ", K(ret)); + } else if (top_context_->get_exec_stack().count() > 0) { + // get_exec_stack is already pop in final(ret) + ObPLExecState *parent = top_context_->get_exec_stack().at(top_context_->get_exec_stack().count() - 1); + CK (OB_NOT_NULL(parent)); + CK (parent != this); + OX (parent->add_sub_plsql_exec_time(pl_exec_time)); + if (!is_called_from_sql) { + OX (parent->add_pure_sql_exec_time(get_pure_sql_exec_time())); + } + } else { + CK (OB_NOT_NULL(ctx_.exec_ctx_)); + CK (OB_NOT_NULL(ctx_.exec_ctx_->get_my_session())); + // top pl exec time , need add to session + OX ((ctx_.exec_ctx_->get_my_session()->add_plsql_exec_time(pl_exec_time))); + } + return ret; +} + bool ObPLExecCtx::valid() { return OB_NOT_NULL(allocator_) @@ -4214,35 +4307,6 @@ bool ObPLFunction::should_init_as_session_cursor() return b_ret; } -int ObPLFunction::update_cache_obj_stat(ObILibCacheCtx &ctx) -{ - int ret = OB_SUCCESS; - ObPLCacheCtx &pc_ctx = static_cast(ctx); - - PLCacheObjStat &stat = get_stat_for_update(); - stat.pl_schema_id_ = pc_ctx.key_.key_id_; - stat.gen_time_ = ObTimeUtility::current_time(); - stat.hit_count_ = 0; - MEMCPY(stat.sql_id_, pc_ctx.sql_id_, (int32_t)sizeof(pc_ctx.sql_id_)); - - if (ObLibCacheNameSpace::NS_ANON == get_ns()) { - ObTruncatedString trunc_raw_sql(pc_ctx.raw_sql_, OB_MAX_SQL_LENGTH); - if (OB_FAIL(ob_write_string(get_allocator(), - trunc_raw_sql.string(), - stat.raw_sql_))) { - LOG_WARN("failed to write sql", K(ret)); - } else { - stat.sql_cs_type_ = pc_ctx.session_info_->get_local_collation_connection(); - } - } - if (OB_SUCC(ret)) { - // Update last_active_time_ last, because last_active_time_ is used to - // indicate whether the cache stat has been updated. - stat.last_active_time_ = ObTimeUtility::current_time(); - } - return ret; -} - int ObPLFunction::is_special_pkg_invoke_right(ObSchemaGetterGuard &guard, bool &flag) { typedef const char *(*name_pair_ptr)[2]; diff --git a/src/pl/ob_pl.h b/src/pl/ob_pl.h index afd059399c..46d66d53b7 100644 --- a/src/pl/ob_pl.h +++ b/src/pl/ob_pl.h @@ -71,50 +71,6 @@ enum ObPLObjectType PACKAGE_SPEC }; - -struct PLCacheObjStat -{ - char sql_id_[common::OB_MAX_SQL_ID_LENGTH + 1]; - int64_t pl_schema_id_; - common::ObString raw_sql_; - common::ObCollationType sql_cs_type_; - int64_t gen_time_; - int64_t last_active_time_; - uint64_t hit_count_; - - PLCacheObjStat() - : pl_schema_id_(OB_INVALID_ID), - sql_cs_type_(common::CS_TYPE_INVALID), - gen_time_(0), - last_active_time_(0), - hit_count_(0) - { - sql_id_[0] = '\0'; - } - - inline bool is_updated() const - { - return last_active_time_ != 0; - } - - void reset() - { - sql_id_[0] = '\0'; - pl_schema_id_ = OB_INVALID_ID; - sql_cs_type_ = common::CS_TYPE_INVALID; - raw_sql_.reset(); - gen_time_ = 0; - last_active_time_ = 0; - hit_count_ = 0; - } - - TO_STRING_KV(K_(pl_schema_id), - K_(gen_time), - K_(last_active_time), - K_(hit_count), - K_(raw_sql)); -}; - class ObPLINS { public: @@ -500,9 +456,6 @@ public: inline bool get_has_parallel_affect_factor() const { return has_parallel_affect_factor_; } inline void set_has_parallel_affect_factor(bool value) { has_parallel_affect_factor_ = value; } - inline const PLCacheObjStat get_stat() const { return stat_; } - inline PLCacheObjStat &get_stat_for_update() { return stat_; } - int get_subprogram(const ObIArray &path, ObPLFunction *&routine) const; inline const common::ObString &get_function_name() const { return function_name_; } @@ -544,7 +497,6 @@ public: * test -> oceanbase, we see oceanbase in interface but can't see test. */ int is_special_pkg_invoke_right(ObSchemaGetterGuard &guard, bool &flag); - virtual int update_cache_obj_stat(ObILibCacheCtx &ctx); common::ObFixedArray& get_sql_infos() { @@ -579,8 +531,6 @@ private: bool is_invoker_right_; bool is_pipelined_; ObPLNameDebugInfo name_debuginfo_; - // stat info - PLCacheObjStat stat_; common::ObString function_name_; common::ObString package_name_; @@ -767,7 +717,10 @@ public: current_line_(OB_INVALID_INDEX), loc_(loc), is_called_from_sql_(is_called_from_sql), - dwarf_helper_(NULL) {} + dwarf_helper_(NULL), + pure_sql_exec_time_(0), + pure_plsql_exec_time_(0), + pure_sub_plsql_exec_time_(0) {} virtual ~ObPLExecState(); int init(const ParamStore *params = NULL, bool is_anonymous = false); @@ -819,11 +772,31 @@ public: } inline jit::ObDWARFHelper* get_dwarf_helper() { return dwarf_helper_; } + inline void add_pure_sql_exec_time(int64_t sql_exec_time) + { + pure_sql_exec_time_ += sql_exec_time; + } + inline void reset_pure_sql_exec_time() { pure_sql_exec_time_ = 0; } + + int64_t get_pure_sql_exec_time() { return pure_sql_exec_time_; } + + int add_pl_exec_time(int64_t pl_exec_time, bool is_called_from_sql); + + void reset_plsql_exec_time() { pure_plsql_exec_time_ = 0; } + void add_plsql_exec_time(int64_t plsql_exec_time) { pure_plsql_exec_time_ = plsql_exec_time; } + int64_t get_plsql_exec_time() { return pure_plsql_exec_time_; } + void add_sub_plsql_exec_time(int64_t sub_plsql_exec_time) { pure_sub_plsql_exec_time_ += sub_plsql_exec_time; } + int64_t get_sub_plsql_exec_time() { return pure_sub_plsql_exec_time_; } + void reset_sub_plsql_exec_time() { pure_sub_plsql_exec_time_ = 0; } + TO_STRING_KV(K_(inner_call), K_(top_call), K_(need_reset_physical_plan), K_(loc), - K_(is_called_from_sql)); + K_(is_called_from_sql), + K_(pure_sql_exec_time), + K_(pure_plsql_exec_time), + K_(pure_sub_plsql_exec_time)); private: private: ObPLFunction &func_; @@ -843,6 +816,9 @@ private: uint64_t loc_; // combine of line and column number bool is_called_from_sql_; jit::ObDWARFHelper *dwarf_helper_; // for decode dwarf debuginfo + int64_t pure_sql_exec_time_; + int64_t pure_plsql_exec_time_; + int64_t pure_sub_plsql_exec_time_; }; class ObPLContext @@ -884,6 +860,7 @@ public: cur_query_.reset(); is_function_or_trigger_ = false; last_insert_id_ = 0; + trace_id_.reset(); } int is_inited() { return session_info_ != NULL; } @@ -998,6 +975,7 @@ public: pl::ObPLContext *get_parent_stack_ctx() { return parent_stack_ctx_; } pl::ObPLContext *get_top_stack_ctx() { return top_stack_ctx_; } sql::ObExecContext *get_my_exec_ctx() { return my_exec_ctx_; } + ObCurTraceId::TraceId get_trace_id() const { return trace_id_; } private: ObPLContext* get_stack_pl_ctx(); @@ -1054,6 +1032,7 @@ private: sql::ObExecContext *my_exec_ctx_; //my exec context bool is_function_or_trigger_; uint64_t last_insert_id_; + ObCurTraceId::TraceId trace_id_; }; struct PlTransformTreeCtx diff --git a/src/pl/ob_pl_compile.cpp b/src/pl/ob_pl_compile.cpp index 19696a04b1..e16ca4b27e 100644 --- a/src/pl/ob_pl_compile.cpp +++ b/src/pl/ob_pl_compile.cpp @@ -176,6 +176,7 @@ int ObPLCompiler::compile( int ret = OB_SUCCESS; FLTSpanGuard(pl_compile); bool use_jitted_expr = false; + int64_t compile_start = ObTimeUtility::current_time(); //Step 1:构造匿名块的ObPLFunctionAST HEAP_VAR(ObPLFunctionAST, func_ast, allocator_) { @@ -281,6 +282,8 @@ int ObPLCompiler::compile( } // end of HEAP_VAR } } + int64_t compile_end = ObTimeUtility::current_time(); + OX (func.get_stat_for_update().compile_time_ = compile_end - compile_start); return ret; } @@ -529,6 +532,7 @@ int ObPLCompiler::compile(const uint64_t id, ObPLFunction &func) } int64_t final_end = ObTimeUtility::current_time(); LOG_INFO(">>>>>>>>Final Time: ", K(id), K(final_end - cg_end)); + OX (func.get_stat_for_update().compile_time_ = final_end - init_start); } return ret; } @@ -761,6 +765,7 @@ int ObPLCompiler::compile_package(const ObPackageInfo &package_info, bool saved_trigger_flag = session_info_.is_for_trigger_package(); ObString source; bool use_jitted_expr = false; + int64_t compile_start = ObTimeUtility::current_time(); ObPLCompilerEnvGuard guard(package_info, session_info_, schema_guard_, ret); session_info_.set_for_trigger_package(package_info.is_for_trigger()); @@ -841,6 +846,9 @@ int ObPLCompiler::compile_package(const ObPackageInfo &package_info, } } } + int64_t compile_end = ObTimeUtility::current_time(); + OX (package.get_stat_for_update().compile_time_ = compile_end - compile_start); + OX (package.get_stat_for_update().type_ = ObPLCacheObjectType::PACKAGE_ROUTINE_TYPE); return ret; } diff --git a/src/pl/ob_pl_package_manager.cpp b/src/pl/ob_pl_package_manager.cpp index 7a3c83d9d1..f00f76a07e 100644 --- a/src/pl/ob_pl_package_manager.cpp +++ b/src/pl/ob_pl_package_manager.cpp @@ -1374,16 +1374,15 @@ int ObPLPackageManager::add_package_to_plan_cache(const ObPLResolveCtx &resolve_ //HEAP_VAR(ObExecContext, exec_ctx, allocator) { + ObPLCacheCtx pc_ctx; uint64_t database_id = OB_INVALID_ID; resolve_ctx.session_info_.get_database_id(database_id); - ObPLCacheCtx pc_ctx; pc_ctx.session_info_ = &resolve_ctx.session_info_; pc_ctx.schema_guard_ = &resolve_ctx.schema_guard_; (void)ObSQLUtils::md5(sql,pc_ctx.sql_id_, (int32_t)sizeof(pc_ctx.sql_id_)); int64_t sys_schema_version = OB_INVALID_VERSION; int64_t tenant_schema_version = OB_INVALID_VERSION; - pc_ctx.key_.namespace_ = ObLibCacheNameSpace::NS_PKG; pc_ctx.key_.db_id_ = database_id; pc_ctx.key_.key_id_ = package_id; @@ -1398,6 +1397,7 @@ int ObPLPackageManager::add_package_to_plan_cache(const ObPLResolveCtx &resolve_ } else { package->set_tenant_schema_version(tenant_schema_version); package->set_sys_schema_version(sys_schema_version); + package->get_stat_for_update().name_ = package->get_name(); } if (OB_FAIL(ret)) { // do nothing diff --git a/src/pl/ob_pl_package_manager.h b/src/pl/ob_pl_package_manager.h index fcdf45632a..06f1464afc 100644 --- a/src/pl/ob_pl_package_manager.h +++ b/src/pl/ob_pl_package_manager.h @@ -57,6 +57,7 @@ struct ObPackageStateVersion; class ObPLPackageState; class ObPLCondition; class ObPLCursor; +class ObPLCacheCtx; struct ObSysPackageFile { const char *package_name; diff --git a/src/pl/ob_pl_resolver.cpp b/src/pl/ob_pl_resolver.cpp index ada32f4226..1f7e939e7f 100644 --- a/src/pl/ob_pl_resolver.cpp +++ b/src/pl/ob_pl_resolver.cpp @@ -2449,54 +2449,71 @@ int ObPLResolver::fill_record_type( return ret; } +#define RESOLVE_SELECT_VIEW_STMT \ + ObSelectStmt *select_stmt = NULL; \ + ObSelectStmt *real_stmt = NULL; \ + ObArenaAllocator alloc; \ + ObStmtFactory stmt_factory(alloc); \ + ObRawExprFactory expr_factory(alloc); \ + const ObDatabaseSchema *db_schema = NULL; \ + ObSqlString select_sql; \ + ParseResult parse_result; \ + ObParser parser(alloc, ctx.session_info_.get_sql_mode(), \ + ctx.session_info_.get_charsets4parser()); \ + ObSchemaChecker schema_checker; \ + ObResolverParams resolver_ctx; \ + ParseNode *select_stmt_node = NULL; \ + \ + OZ (ctx.schema_guard_.get_database_schema(view_schema->get_tenant_id(), \ + view_schema->get_database_id(), db_schema)); \ + CK (OB_NOT_NULL(db_schema)); \ + if (lib::is_oracle_mode()) { \ + OZ (select_sql.append_fmt( \ + "select * from \"%.*s\".\"%.*s\"", \ + db_schema->get_database_name_str().length(), db_schema->get_database_name_str().ptr(), \ + view_schema->get_table_name_str().length(), view_schema->get_table_name_str().ptr())); \ + } else { \ + OZ (select_sql.append_fmt( \ + "select * from `%.*s`.`%.*s`", \ + db_schema->get_database_name_str().length(), db_schema->get_database_name_str().ptr(), \ + view_schema->get_table_name_str().length(), view_schema->get_table_name_str().ptr())); \ + } \ + OZ (parser.parse(select_sql.string(), parse_result)); \ + OZ (schema_checker.init(ctx.schema_guard_, ctx.session_info_.get_sessid())); \ + \ + OX (resolver_ctx.allocator_ = &(alloc)); \ + OX (resolver_ctx.schema_checker_ = &schema_checker); \ + OX (resolver_ctx.session_info_ = &(ctx.session_info_)); \ + OX (resolver_ctx.expr_factory_ = &expr_factory); \ + OX (resolver_ctx.stmt_factory_ = &stmt_factory); \ + OX (resolver_ctx.sql_proxy_ = &(ctx.sql_proxy_)); \ + CK (OB_NOT_NULL(resolver_ctx.query_ctx_ = stmt_factory.get_query_ctx())); \ + OX (resolver_ctx.query_ctx_->question_marks_count_ \ + = static_cast(parse_result.question_mark_ctx_.count_)); \ + \ + CK (OB_NOT_NULL(select_stmt_node = parse_result.result_tree_->children_[0]));\ + CK (T_SELECT == select_stmt_node->type_); \ + ObSelectResolver select_resolver(resolver_ctx); \ + OZ (SMART_CALL(select_resolver.resolve(*select_stmt_node))); \ + CK (OB_NOT_NULL(select_stmt = static_cast(select_resolver.get_basic_stmt()))); \ + CK (OB_NOT_NULL(real_stmt = select_stmt->get_real_stmt())); + int ObPLResolver::build_record_type_by_view_schema(const ObPLResolveCtx &ctx, const ObTableSchema* view_schema, - ObRecordType *&record_type) + ObRecordType *&record_type, + ObIArray *dependency_objects) { int ret = OB_SUCCESS; - ObSelectStmt *select_stmt = NULL; - ObSelectStmt *real_stmt = NULL; - ObArenaAllocator alloc; - ObStmtFactory stmt_factory(alloc); - ObRawExprFactory expr_factory(alloc); - const ObDatabaseSchema *db_schema = NULL; - ObSqlString select_sql; - ParseResult parse_result; - ObParser parser(alloc, ctx.session_info_.get_sql_mode(), - ctx.session_info_.get_charsets4parser()); - ObSchemaChecker schema_checker; - ObResolverParams resolver_ctx; - ParseNode *select_stmt_node = NULL; - OZ (ctx.schema_guard_.get_database_schema(view_schema->get_tenant_id(), - view_schema->get_database_id(), db_schema)); - CK (OB_NOT_NULL(db_schema)); - OZ (select_sql.append_fmt( - "select * from \"%.*s\".\"%.*s\"", - db_schema->get_database_name_str().length(), db_schema->get_database_name_str().ptr(), - view_schema->get_table_name_str().length(), view_schema->get_table_name_str().ptr())); - OZ (parser.parse(select_sql.string(), parse_result)); - OZ (schema_checker.init(ctx.schema_guard_, ctx.session_info_.get_sessid())); + RESOLVE_SELECT_VIEW_STMT; - OX (resolver_ctx.allocator_ = &(alloc)); - OX (resolver_ctx.schema_checker_ = &schema_checker); - OX (resolver_ctx.session_info_ = &(ctx.session_info_)); - OX (resolver_ctx.expr_factory_ = &expr_factory); - OX (resolver_ctx.stmt_factory_ = &stmt_factory); - OX (resolver_ctx.sql_proxy_ = &(ctx.sql_proxy_)); - CK (OB_NOT_NULL(resolver_ctx.query_ctx_ = stmt_factory.get_query_ctx())); - OX (resolver_ctx.query_ctx_->question_marks_count_ - = static_cast(parse_result.question_mark_ctx_.count_)); - - CK (OB_NOT_NULL(select_stmt_node = parse_result.result_tree_->children_[0])); - CK (T_SELECT == select_stmt_node->type_); - - ObSelectResolver select_resolver(resolver_ctx); - OZ (SMART_CALL(select_resolver.resolve(*select_stmt_node))); - CK (OB_NOT_NULL(select_stmt = static_cast(select_resolver.get_basic_stmt()))); - // OZ (get_view_select_stmt(resolve_ctx, view_schema, select_stmt)); - CK (OB_NOT_NULL(real_stmt = select_stmt->get_real_stmt())); CK (OB_NOT_NULL(record_type)); + if (OB_NOT_NULL(dependency_objects)) { + CK (OB_NOT_NULL(real_stmt->get_global_dependency_table())); + for (int64_t i = 0; OB_SUCC(ret) && i < real_stmt->get_global_dependency_table()->count(); ++i) { + OZ (dependency_objects->push_back(real_stmt->get_global_dependency_table()->at(i))); + } + } OZ (fill_record_type(ctx.schema_guard_, ctx.allocator_, real_stmt, record_type)); return ret; } @@ -2580,9 +2597,42 @@ int ObPLResolver::build_record_type_by_table_schema(ObSchemaGetterGuard &schema_ return ret; } +int ObPLResolver::collect_dep_info_by_view_schema(const ObPLResolveCtx &ctx, + const ObTableSchema* view_schema, + ObIArray &dependency_objects) +{ + int ret = OB_SUCCESS; + + RESOLVE_SELECT_VIEW_STMT; + CK (OB_NOT_NULL(real_stmt->get_global_dependency_table())); + for (int64_t i = 0; OB_SUCC(ret) && i < real_stmt->get_global_dependency_table()->count(); ++i) { + OZ (dependency_objects.push_back(real_stmt->get_global_dependency_table()->at(i))); + } + return ret; +} + +int ObPLResolver::collect_dep_info_by_schema(const ObPLResolveCtx &ctx, + const ObTableSchema* table_schema, + ObIArray &dependency_objects) +{ + int ret = OB_SUCCESS; + CK (OB_NOT_NULL(table_schema)); + + if (OB_SUCC(ret)) { + if (table_schema->is_view_table() && !table_schema->is_materialized_view()) { + OZ (collect_dep_info_by_view_schema(ctx, table_schema, dependency_objects)); + } else { + OZ(dependency_objects.push_back(ObSchemaObjVersion(table_schema->get_table_id(), + table_schema->get_schema_version(), + ObDependencyTableType::DEPENDENCY_TABLE))); + } + } + return ret; +} + int ObPLResolver::build_record_type_by_schema( const ObPLResolveCtx &resolve_ctx, const ObTableSchema* table_schema, - ObRecordType *&record_type, bool with_rowid) + ObRecordType *&record_type, bool with_rowid, ObIArray *dependency_objects) { int ret = OB_SUCCESS; CK (OB_NOT_NULL(table_schema)); @@ -2606,10 +2656,15 @@ int ObPLResolver::build_record_type_by_schema( if (OB_SUCC(ret)) { if (table_schema->is_view_table() && !table_schema->is_materialized_view()) { OZ (build_record_type_by_view_schema( - resolve_ctx, table_schema, record_type)); + resolve_ctx, table_schema, record_type, dependency_objects)); } else { OZ (build_record_type_by_table_schema( resolve_ctx.schema_guard_, resolve_ctx.allocator_, table_schema, record_type, with_rowid)); + if (OB_NOT_NULL(dependency_objects)) { + OZ(dependency_objects->push_back(ObSchemaObjVersion(table_schema->get_table_id(), + table_schema->get_schema_version(), + ObDependencyTableType::DEPENDENCY_TABLE))); + } } } return ret; @@ -3000,6 +3055,16 @@ int ObPLResolver::resolve_sp_row_type(const ParseNode *sp_data_type_node, OX (pl_type.set_type_from_orgin(pl_type.get_type_from())); OX (pl_type.set_type_from(PL_TYPE_ATTR_TYPE)); OZ (resolve_extern_type_info(resolve_ctx_.schema_guard_, access_idxs, extern_type_info)); + if (OB_SUCC(ret) && ObObjAccessIdx::is_table_column(access_idxs)) { + ObSEArray dep_schemas; + const ObTableSchema* table_schema = NULL; + const uint64_t tenant_id = resolve_ctx_.session_info_.get_effective_tenant_id(); + CK (idx_cnt > 1); + OZ (resolve_ctx_.schema_guard_.get_table_schema(tenant_id, access_idxs.at(idx_cnt - 2).var_index_, table_schema)); + CK (OB_NOT_NULL(table_schema)); + OZ (collect_dep_info_by_schema(resolve_ctx_, table_schema, dep_schemas)); + OZ (func.add_dependency_objects(dep_schemas)); + } } else { ret = OB_ERR_TYPE_DECL_ILLEGAL; LOG_WARN("PLS-00206: %TYPE must be applied to a variable, column, field or attribute", @@ -3012,6 +3077,7 @@ int ObPLResolver::resolve_sp_row_type(const ParseNode *sp_data_type_node, uint64_t db_id = OB_INVALID_ID; const ObTableSchema* table_schema = NULL; ObRecordType *record_type = NULL; + ObSEArray dep_schemas; ObSEArray types; const uint64_t tenant_id = session_info.get_effective_tenant_id(); OZ (session_info.get_database_id(db_id)); @@ -3054,11 +3120,11 @@ int ObPLResolver::resolve_sp_row_type(const ParseNode *sp_data_type_node, record_type = static_cast(const_cast(dup_type)); OV (OB_NOT_NULL(record_type)); OX (pl_type.set_user_type_id(record_type->get_type(), record_type->get_user_type_id())); - OZ (func.add_dependency_object(ObSchemaObjVersion(table_schema->get_table_id(), - table_schema->get_schema_version(), ObDependencyTableType::DEPENDENCY_TABLE))); + OZ (collect_dep_info_by_schema(resolve_ctx_, table_schema, dep_schemas)); + OZ (func.add_dependency_objects(dep_schemas)); } } else { - OZ (build_record_type_by_schema(resolve_ctx_, table_schema, record_type, with_rowid)); + OZ (build_record_type_by_schema(resolve_ctx_, table_schema, record_type, with_rowid, &dep_schemas)); CK (OB_NOT_NULL(record_type)); OX (record_type->set_name(record_name_str)); OZ (pre_ns->expand_data_type(record_type, types)); @@ -3066,14 +3132,13 @@ int ObPLResolver::resolve_sp_row_type(const ParseNode *sp_data_type_node, OX (record_type->set_type_from(PL_TYPE_PACKAGE)); OX (pl_type.set_user_type_id(record_type->get_type(), record_type->get_user_type_id())); OZ (pl_type.get_all_depended_user_type(resolve_ctx_, *pre_ns)); - OZ (func.add_dependency_object(ObSchemaObjVersion(table_schema->get_table_id(), - table_schema->get_schema_version(), ObDependencyTableType::DEPENDENCY_TABLE))); + OZ (func.add_dependency_objects(dep_schemas)); } } OX (pl_type.set_type_from(PL_TYPE_PACKAGE)); OX (pl_type.set_type_from_orgin(PL_TYPE_PACKAGE)); } else { - OZ (build_record_type_by_schema(resolve_ctx_, table_schema, record_type, with_rowid)); + OZ (build_record_type_by_schema(resolve_ctx_, table_schema, record_type, with_rowid, &dep_schemas)); CK (OB_NOT_NULL(record_type)); CK (OB_NOT_NULL(current_block_)); CK (OB_NOT_NULL(current_block_->get_namespace().get_type_table())); @@ -3084,8 +3149,7 @@ int ObPLResolver::resolve_sp_row_type(const ParseNode *sp_data_type_node, OX (pl_type.set_type_from(PL_TYPE_ATTR_ROWTYPE)); OZ (pl_type.get_all_depended_user_type(resolve_ctx_, current_block_->get_namespace())); OZ (resolve_extern_type_info(resolve_ctx_.schema_guard_, access_idxs, extern_type_info)); - OZ (func.add_dependency_object(ObSchemaObjVersion(table_schema->get_table_id(), - table_schema->get_schema_version(), ObDependencyTableType::DEPENDENCY_TABLE))); + OZ (func.add_dependency_objects(dep_schemas)); } } else if (ObObjAccessIdx::is_local_cursor_variable(access_idxs) || ObObjAccessIdx::is_local_refcursor_variable(access_idxs) @@ -5716,10 +5780,14 @@ int ObPLResolver::resolve_static_sql(const ObStmtNodeTree *parse_tree, ObPLSql & } if (OB_SUCC(ret)) { - if (OB_FAIL(func.add_dependency_objects(prepare_result.ref_objects_))) { - LOG_WARN("add dependency tables failed", K(ret)); - } else if (OB_FAIL(static_sql.set_ref_objects(prepare_result.ref_objects_))) { - LOG_WARN("set ref objects failed", K(ret)); + if (lib::is_mysql_mode()) { + for (int64_t i = 0; OB_SUCC(ret) && i < prepare_result.ref_objects_.count(); ++i) { + if (DEPENDENCY_TABLE == prepare_result.ref_objects_.at(i).object_type_) { + // do nothing, no need collect table schema in mysql mode + } else if (OB_FAIL(func.add_dependency_object(prepare_result.ref_objects_.at(i)))) { + LOG_WARN("add dependency object failed", K(ret)); + } + } } else { // sql contain package var or package udf for (int64_t i = 0; OB_SUCC(ret) && i < prepare_result.ref_objects_.count(); ++i) { @@ -5729,8 +5797,11 @@ int ObPLResolver::resolve_static_sql(const ObStmtNodeTree *parse_tree, ObPLSql & func.set_external_state(); } } - static_sql.set_row_desc(record_type); + OZ (func.add_dependency_objects(prepare_result.ref_objects_)); + OX (static_sql.set_row_desc(record_type)); } + // used for generate route sql + OZ (static_sql.set_ref_objects(prepare_result.ref_objects_)); } } } @@ -7514,17 +7585,24 @@ int ObPLResolver::resolve_cursor_def(const ObString &cursor_name, } } if (OB_SUCC(ret)) { - if (OB_FAIL(func.add_dependency_objects(prepare_result.ref_objects_))) { - LOG_WARN("failed to set ref object", K(prepare_result.ref_objects_), K(ret)); - } else { - // sql contain package var or package udf + if (lib::is_mysql_mode()) { for (int64_t i = 0; OB_SUCC(ret) && i < prepare_result.ref_objects_.count(); ++i) { - if (DEPENDENCY_PACKAGE == prepare_result.ref_objects_.at(i).object_type_ || - DEPENDENCY_PACKAGE_BODY == prepare_result.ref_objects_.at(i).object_type_ || - DEPENDENCY_FUNCTION == prepare_result.ref_objects_.at(i).object_type_) { - func.set_external_state(); + if (DEPENDENCY_TABLE == prepare_result.ref_objects_.at(i).object_type_) { + // do nothing, no need collect table schema in mysql mode + } else if (OB_FAIL(func.add_dependency_object(prepare_result.ref_objects_.at(i)))) { + LOG_WARN("add dependency object failed", K(ret)); } } + } else if (OB_FAIL(func.add_dependency_objects(prepare_result.ref_objects_))) { + LOG_WARN("add dependency tables failed", K(ret)); + } + // sql contain package var or package udf + for (int64_t i = 0; OB_SUCC(ret) && i < prepare_result.ref_objects_.count(); ++i) { + if (DEPENDENCY_PACKAGE == prepare_result.ref_objects_.at(i).object_type_ || + DEPENDENCY_PACKAGE_BODY == prepare_result.ref_objects_.at(i).object_type_ || + DEPENDENCY_FUNCTION == prepare_result.ref_objects_.at(i).object_type_) { + func.set_external_state(); + } } } } diff --git a/src/pl/ob_pl_resolver.h b/src/pl/ob_pl_resolver.h index 5958fd0a31..99e88867d5 100644 --- a/src/pl/ob_pl_resolver.h +++ b/src/pl/ob_pl_resolver.h @@ -401,17 +401,25 @@ public: static int build_record_type_by_view_schema(const ObPLResolveCtx &resolve_ctx, const share::schema::ObTableSchema* view_schema, - ObRecordType *&record_type); + ObRecordType *&record_type, + ObIArray *dependency_objects = NULL); static int build_record_type_by_table_schema(share::schema::ObSchemaGetterGuard &schema_guard, common::ObIAllocator &allocator, const share::schema::ObTableSchema* table_schema, ObRecordType *&record_type, bool with_rowid = false); + static int collect_dep_info_by_view_schema(const ObPLResolveCtx &ctx, + const ObTableSchema* view_schema, + ObIArray &dependency_objects); + static int collect_dep_info_by_schema(const ObPLResolveCtx &ctx, + const ObTableSchema* table_schema, + ObIArray &dependency_objects); static int build_record_type_by_schema(const ObPLResolveCtx &resolve_ctx, const share::schema::ObTableSchema* table_schema, - ObRecordType *&record_type, bool with_rowid = false); + ObRecordType *&record_type, bool with_rowid = false, + ObIArray *dependency_objects = NULL); static int resolve_extern_type_info(bool is_row_type, diff --git a/src/pl/ob_pl_stmt.cpp b/src/pl/ob_pl_stmt.cpp index 2b28600fe2..76ef232eba 100644 --- a/src/pl/ob_pl_stmt.cpp +++ b/src/pl/ob_pl_stmt.cpp @@ -1724,6 +1724,12 @@ int ObPLExternalNS::resolve_external_symbol(const common::ObString &name, tenant_id, db_id, name, object_db_id, object_name, exist, OB_INVALID_INDEX == parent_id)); if (exist) { OZ (resolve_synonym(object_db_id, object_name, type, parent_id, var_idx, name, db_id)); + if (synonym_checker.has_synonym() && OB_NOT_NULL(get_dependency_table())) { + OZ (ObResolverUtils::add_dependency_synonym_object(&resolve_ctx_.schema_guard_, + &resolve_ctx_.session_info_, + synonym_checker, + *get_dependency_table())); + } } } } @@ -2185,6 +2191,7 @@ int ObPLExternalNS::resolve_external_routine(const ObString &db_name, } } if (OB_SUCC(ret) && routine_infos.empty()) { + ObSynonymChecker synonym_checker; const ObRoutineInfo *schema_routine_info = NULL; ObRoutineType schema_routine_type = is_procedure(routine_type) ? ROUTINE_PROCEDURE_TYPE : ROUTINE_FUNCTION_TYPE; @@ -2196,7 +2203,8 @@ int ObPLExternalNS::resolve_external_routine(const ObString &db_name, routine_name, schema_routine_type, expr_params, - schema_routine_info))) { + schema_routine_info, + &synonym_checker))) { LOG_WARN("failed to get routine info", K(ret), K(db_name), K(package_name), K(routine_name)); } else { @@ -2207,9 +2215,15 @@ int ObPLExternalNS::resolve_external_routine(const ObString &db_name, obj_version.version_ = schema_routine_info->get_schema_version(); if (OB_FAIL(add_dependency_object(obj_version))) { LOG_WARN("add dependency object failed", "package_id", schema_routine_info->get_package_id(), K(ret)); - } else { - OZ (routine_infos.push_back(schema_routine_info)); + } else if (synonym_checker.has_synonym()) { + if (OB_FAIL(ObResolverUtils::add_dependency_synonym_object(&resolve_ctx_.schema_guard_, + &resolve_ctx_.session_info_, + synonym_checker, + *get_dependency_table()))) { + LOG_WARN("add dependency synonym failed", K(ret)); + } } + OZ (routine_infos.push_back(schema_routine_info)); } } return ret; diff --git a/src/pl/ob_pl_type.cpp b/src/pl/ob_pl_type.cpp index a6eaa50e70..0d8fb78a3b 100644 --- a/src/pl/ob_pl_type.cpp +++ b/src/pl/ob_pl_type.cpp @@ -1087,11 +1087,14 @@ int ObPLDataType::serialize(share::schema::ObSchemaGetterGuard &schema_guard, uint16_t flags; ObScale num_decimals; ObObj obj; + ObField field; if (OB_FAIL(ObSMUtils::get_mysql_type(get_obj_type(), mysql_type, flags, num_decimals))) { LOG_WARN("get mysql type failed", K(ret), K(get_obj_type())); } else { obj = *(reinterpret_cast(src)); src += sizeof(ObObj); + field.accuracy_ = get_data_type()->get_accuracy(); + field.flags_ = get_data_type()->is_zero_fill() ? ZEROFILL_FLAG : 0; } if (OB_SUCC(ret) && !obj.is_invalid_type() // deleted element not serialize. @@ -1100,7 +1103,7 @@ int ObPLDataType::serialize(share::schema::ObSchemaGetterGuard &schema_guard, ret = OB_ERR_UNEXPECTED; LOG_WARN("failed to serialize pl data type, data type inconsistent with pl type", K(get_obj_type()), K(obj.get_type()), K(obj), K(*this), K(ret)); - } else if (OB_FAIL(ObSMUtils::cell_str(dst, dst_len, obj, type, dst_pos, OB_INVALID_ID, NULL, tz_info, NULL, NULL))) { + } else if (OB_FAIL(ObSMUtils::cell_str(dst, dst_len, obj, type, dst_pos, OB_INVALID_ID, NULL, tz_info, &field, NULL))) { LOG_WARN("failed to cell str", K(ret), K(obj), K(dst_len), K(dst_pos)); } else { LOG_DEBUG("success serialize pl data type", K(*this), K(obj), @@ -2060,6 +2063,7 @@ int ObPLCursorInfo::deep_copy(ObPLCursorInfo &src, common::ObIAllocator *allocat snapshot_ = src.snapshot_; is_need_check_snapshot_ = src.is_need_check_snapshot_; last_execute_time_ = src.last_execute_time_; + sql_trace_id_ = src.sql_trace_id_; //these should not be copied .. // lib::MemoryContext entity_; // ObIAllocator *allocator_; diff --git a/src/pl/ob_pl_type.h b/src/pl/ob_pl_type.h index d9a1e45624..f28b278c5c 100644 --- a/src/pl/ob_pl_type.h +++ b/src/pl/ob_pl_type.h @@ -244,7 +244,8 @@ public: user_type_id_(common::OB_INVALID_ID), not_null_(false), pls_type_(ObPLIntegerType::PL_INTEGER_INVALID), - type_info_() + type_info_(), + charsetnr_(CS_TYPE_UTF8MB4_GENERAL_CI) { type_info_.set_tenant_id(MTL_ID()); } @@ -256,7 +257,8 @@ public: user_type_id_(common::OB_INVALID_ID), not_null_(false), pls_type_(ObPLIntegerType::PL_INTEGER_INVALID), - type_info_() + type_info_(), + charsetnr_(CS_TYPE_UTF8MB4_GENERAL_CI) { type_info_.set_tenant_id(MTL_ID()); } @@ -268,7 +270,8 @@ public: user_type_id_(common::OB_INVALID_ID), not_null_(false), pls_type_(ObPLIntegerType::PL_INTEGER_INVALID), - type_info_() + type_info_(), + charsetnr_(CS_TYPE_UTF8MB4_GENERAL_CI) { common::ObDataType data_type; data_type.set_obj_type(type); @@ -282,7 +285,8 @@ public: obj_type_(other.obj_type_), user_type_id_(other.user_type_id_), not_null_(other.not_null_), - pls_type_(other.pls_type_) + pls_type_(other.pls_type_), + charsetnr_(other.charsetnr_) { type_info_.set_tenant_id(MTL_ID()); type_info_ = other.type_info_; @@ -300,6 +304,7 @@ public: not_null_ = false; pls_type_ = ObPLIntegerType::PL_INTEGER_INVALID; type_info_.reset(); + charsetnr_ = CS_TYPE_UTF8MB4_GENERAL_CI; } bool operator==(const ObPLDataType &other) const; @@ -346,6 +351,10 @@ public: inline bool get_not_null() const { return not_null_; } inline void set_not_null(bool not_null) { not_null_ = not_null; } + void set_charset(const ObCollationType charset) { charsetnr_ = charset; } + void reset_charset() { charsetnr_ = CS_TYPE_UTF8MB4_GENERAL_CI; } + ObCollationType get_charset() const { return charsetnr_; } + const common::ObIArray& get_type_info() const { return type_info_; } int set_type_info(const common::ObIArray &type_info); int set_type_info(const common::ObIArray *type_info); @@ -614,6 +623,7 @@ protected: ObPLGenericType generic_type_; }; common::ObArray type_info_; + ObCollationType charsetnr_; }; inline void ObPLDataType::set_pl_integer_type(ObPLIntegerType integer_type, const common::ObDataType &obj_type) @@ -873,6 +883,7 @@ public: first_row_.reset(); last_row_.reset(); is_need_check_snapshot_ = false; + sql_trace_id_.reset(); is_packed_ = false; } @@ -1018,6 +1029,8 @@ public: uint64_t tenant_id, uint64_t mem_limit, bool is_local_for_update = false); + ObCurTraceId::TraceId *get_sql_trace_id() { return &sql_trace_id_; } + inline void set_packed(bool is_packed) { is_packed_ = is_packed; } inline bool is_packed() { return is_packed_; } @@ -1047,6 +1060,7 @@ public: K_(snapshot), K_(is_need_check_snapshot), K_(last_execute_time), + K_(sql_trace_id), K_(is_packed)); protected: @@ -1079,6 +1093,7 @@ protected: bool is_need_check_snapshot_; int64_t last_execute_time_; // 记录上一次cursor操作的时间点 bool last_stream_cursor_; // cursor复用场景下,记录上一次是否是流式cursor + ObCurTraceId::TraceId sql_trace_id_; // trace id of cursor sql statement bool is_packed_; }; diff --git a/src/pl/ob_pl_user_type.cpp b/src/pl/ob_pl_user_type.cpp index 36f1559770..94d2f8e0a5 100644 --- a/src/pl/ob_pl_user_type.cpp +++ b/src/pl/ob_pl_user_type.cpp @@ -25,6 +25,7 @@ #include "sql/resolver/expr/ob_raw_expr_util.h" #include "pl/ob_pl_allocator.h" #include "share/ob_lob_access_utils.h" +#include "observer/mysql/ob_query_driver.h" namespace oceanbase { @@ -635,7 +636,184 @@ int64_t ObUserDefinedType::get_serialize_obj_size(const ObObj &obj) return size; } +int ObUserDefinedType::text_protocol_prefix_info_for_each_item(share::schema::ObSchemaGetterGuard &schema_guard, + const ObPLDataType &type, + char *buf, + const int64_t len, + int64_t &pos) const +{ + int ret = OB_SUCCESS; + if (type.is_collection_type() || type.is_record_type()) { + const ObUserDefinedType *user_type = NULL; + const ObUDTTypeInfo *udt_info = NULL; + ObArenaAllocator local_allocator; + const uint64_t tenant_id = get_tenant_id_by_object_id(type.get_user_type_id()); + const_cast(type).set_charset(get_charset()); + + if (!is_udt_type()) { + ret = OB_NOT_SUPPORTED; + LOG_WARN("not support other type except udt type", K(ret), K(get_type_from())); + LOG_USER_ERROR(OB_NOT_SUPPORTED, "non-schema user defined type deserialize"); + } else if (OB_FAIL(schema_guard.get_udt_info(tenant_id, type.get_user_type_id(), udt_info))) { + LOG_WARN("failed to get udt info", K(ret), K(tenant_id), K(type.get_user_type_id())); + } else if (OB_ISNULL(udt_info)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("udt info is null", K(ret), K(type.get_user_type_id())); + } else { + if (len - pos < udt_info->get_type_name().length() + 1) { + ret = OB_SIZE_OVERFLOW; + LOG_WARN("buffer length is not enough. ", K(udt_info->get_type_name()), K(udt_info->get_type_name().length()), K(len)); + } else { + MEMCPY(buf + pos, udt_info->get_type_name().ptr(), udt_info->get_type_name().length()); + pos += udt_info->get_type_name().length(); + MEMCPY(buf + pos, "(", 1); + pos += 1; + } + } + } else if (NULL != type.get_meta_type() && (type.get_meta_type()->is_string_or_lob_locator_type() + || type.get_meta_type()->is_oracle_temporal_type() + || type.get_meta_type()->is_raw())) { + if (len - pos < 1) { + ret = OB_SIZE_OVERFLOW; + LOG_WARN("buffer length is not enough. ", K(type_name_), K(type_name_.length()), K(len)); + } else { + MEMCPY(buf + pos, "'", 1); + pos += 1; + } + } + + return ret; +} + +int ObUserDefinedType::text_protocol_suffix_info_for_each_item(const ObPLDataType &type, + char *buf, + const int64_t len, + int64_t &pos, + const bool is_last_item, + const bool is_null) const +{ + int ret = OB_SUCCESS; + if (type.is_collection_type() || type.is_record_type()) { + // reset charset + const_cast(type).reset_charset(); + + if (len - pos < 3) { + ret = OB_SIZE_OVERFLOW; + LOG_WARN("buffer length is not enough. ", K(type_name_), K(type_name_.length()), K(len)); + } else if (is_last_item) { + MEMCPY(buf + pos, ")", 1); + pos += 1; + } else { + MEMCPY(buf + pos, "), ", 3); + pos += 3; + } + } else if (!is_null && NULL != type.get_meta_type() && (type.get_meta_type()->is_string_or_lob_locator_type() + || type.get_meta_type()->is_oracle_temporal_type() + || type.get_meta_type()->is_raw())) { + if (len - pos < 3) { + ret = OB_SIZE_OVERFLOW; + LOG_WARN("buffer length is not enough. ", K(type_name_), K(type_name_.length()), K(len)); + } else { + MEMCPY(buf + pos, "'", 1); + pos += 1; + if (!is_last_item) { + MEMCPY(buf + pos, ", ", 2); + pos += 2; + } + } + } else if (!is_last_item) { + if (len - pos < 2) { + ret = OB_SIZE_OVERFLOW; + LOG_WARN("buffer length is not enough. ", K(type_name_), K(type_name_.length()), K(len)); + } else { + MEMCPY(buf + pos, ", ", 2); + pos += 2; + } + } + + return ret; +} + +int ObUserDefinedType::text_protocol_base_type_convert(const ObPLDataType &type, char *buf, int64_t &pos, int64_t len) const +{ + int ret = OB_SUCCESS; + /* 1. base type is use cell string to convert to string type + * string type store as [length + value] + * we should remove length in buffer + * 2. nchar/nvarchar need convert string with charset + */ + uint64_t orign_str_length = 0; // the string length + uint64_t inc_len = 0; // the length of [string length] in buffer + const char *start = buf + pos; // all string begin + uint32_t convert_length = 0; + if (OB_FAIL(ObMySQLUtil::get_length(start, orign_str_length, inc_len))) { + LOG_WARN("get length fail.", K(ret)); + } else { + ObArenaAllocator alloc; + char* tmp_buf = static_cast(alloc.alloc(orign_str_length)); + MEMCPY(tmp_buf, buf + pos + inc_len, orign_str_length); + if (type.is_obj_type() && (OB_NOT_NULL(type.get_data_type())) + && (type.get_data_type()->get_meta_type().is_string_or_lob_locator_type())) { + // need do convert first + if (OB_FAIL(observer::ObQueryDriver::convert_string_charset(ObString(orign_str_length, tmp_buf), + type.get_data_type()->get_collation_type(), + get_charset(), + buf + pos, + len - pos, + convert_length))) { + LOG_WARN("convert string charset failed", K(ret)); + } else { + pos += convert_length; + } + } else { + // only remove length info in buf when type is not nchar/nvarchar + MEMCPY(buf + pos, tmp_buf, orign_str_length); + pos += orign_str_length; + } + } + return ret; +} + +int ObUserDefinedType::base_type_serialize_for_text(ObObj* obj, + const ObTimeZoneInfo *tz_info, + char *dst, + const int64_t dst_len, + int64_t &dst_pos, + bool &has_serialized) const +{ + int ret = OB_SUCCESS; + has_serialized = true; + if (NULL == obj) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("obj is null.", K(ret)); + } else if (ObOTimestampTC == obj->get_type_class()) { + OZ (ObMySQLUtil::otimestamp_cell_str2(dst, dst_len, obj->get_otimestamp_value(), TEXT, dst_pos, tz_info, + ObAccuracy::DML_DEFAULT_ACCURACY[obj->get_type()].get_scale(), obj->get_type())); + } else if (obj->is_raw() || obj->is_hex_string()) { + OZ (ObMySQLUtil::store_length(dst, dst_len, obj->get_string_len() * 2 + 1, dst_pos)); + OZ (to_hex_cstr(obj->get_string_ptr(), obj->get_string_len(), dst + dst_pos, dst_len - dst_pos)); + OX (dst_pos += obj->get_string_len() * 2 + 1); + } else if (obj->is_lob() && NULL != obj->get_string_ptr()) { + ObString lob_string; + OZ (obj->get_string(lob_string)); + if (obj->is_blob()) { + OZ (ObMySQLUtil::store_length(dst, dst_len, lob_string.length() * 2 + 1, dst_pos)); + OZ (to_hex_cstr(lob_string.ptr(), lob_string.length(), dst + dst_pos, dst_len - dst_pos)); + OX (dst_pos += (lob_string.length() * 2 + 1)); + } else { + CK (obj->is_clob()); + OZ (ObMySQLUtil::store_length(dst, dst_len, lob_string.length(), dst_pos)); + OX (MEMCPY(dst + dst_pos, lob_string.ptr(), lob_string.length())); + OX (dst_pos += lob_string.length()); + } + } else { + has_serialized = false; + } + return ret; +} + #ifdef OB_BUILD_ORACLE_PL + //---------- for ObUserDefinedSubType ---------- int ObUserDefinedSubType::deep_copy(common::ObIAllocator &alloc, const ObUserDefinedSubType &other) @@ -1679,7 +1857,7 @@ int ObRecordType::serialize(share::schema::ObSchemaGetterGuard &schema_guard, ret = OB_SIZE_OVERFLOW; LOG_WARN("size overflow", K(ret), K(dst_len), K(dst_pos), K(bitmap_bytes), K(record_members_.count())); - } else { + } else if (BINARY == protocl_type) { bitmap = dst + dst_pos; MEMSET(dst + dst_pos, 0, bitmap_bytes); dst_pos += bitmap_bytes; @@ -1696,9 +1874,26 @@ int ObRecordType::serialize(share::schema::ObSchemaGetterGuard &schema_guard, CK (OB_NOT_NULL(type)); CK (OB_NOT_NULL(obj)); if (OB_FAIL(ret)) { - } else if (obj->is_null()) { - ObMySQLUtil::update_null_bitmap(bitmap, i); - new_src += sizeof(ObObj); + } else if (ObPLComposite::obj_is_null(obj)) { + if (BINARY == protocl_type) { + ObMySQLUtil::update_null_bitmap(bitmap, i); + new_src += sizeof(ObObj); + } else { + if (dst_len - dst_pos < 4) { + ret = OB_SIZE_OVERFLOW; + LOG_WARN("size overflow", K(ret), K(dst_len), K(dst_pos)); + } else { + MEMCPY(dst + dst_pos, "NULL", 4); + dst_pos += 4; + new_src += sizeof(ObObj); + } + } + } else if (TEXT == protocl_type && OB_FAIL(text_protocol_prefix_info_for_each_item(schema_guard, + *type, + dst, + dst_len - dst_pos, + dst_pos))) { + LOG_WARN("set text protocol prefix info fail.", K(ret), K(get_name())); } else if (type->is_collection_type()) { #ifdef OB_BUILD_ORACLE_PL char *coll_src = reinterpret_cast(obj->get_ext()); @@ -1707,15 +1902,33 @@ int ObRecordType::serialize(share::schema::ObSchemaGetterGuard &schema_guard, CK (OB_NOT_NULL(coll_table)); CK (OB_NOT_NULL(coll_src)); if (OB_FAIL(ret)) { - } else if (!coll_table->is_inited()) { + } else if (BINARY == protocl_type && !coll_table->is_inited()) { ObMySQLUtil::update_null_bitmap(bitmap, i); } else { OZ (type->serialize(schema_guard, tz_info, protocl_type, new_src, dst, dst_len, dst_pos)); } #endif } else { - OZ (type->serialize(schema_guard, tz_info, protocl_type, new_src, dst, dst_len, dst_pos), - K(i), KPC(this)); + int64_t offset_dst_pos = dst_pos; + bool has_serialized = false; + if (TEXT == protocl_type && OB_FAIL(base_type_serialize_for_text(obj, tz_info, dst, dst_len, dst_pos, has_serialized))) { + LOG_WARN("serialize for text fail.", K(ret), K(has_serialized)); + } else if (false == has_serialized) { + OZ (type->serialize(schema_guard, tz_info, protocl_type, new_src, dst, dst_len, dst_pos), + K(i), KPC(this)); + } + if (TEXT == protocl_type && !type->is_record_type()) { + OZ (text_protocol_base_type_convert(*type, dst, offset_dst_pos, dst_len)); + OX (dst_pos = offset_dst_pos); + } + } + if (TEXT == protocl_type && !obj->is_invalid_type()) { + OZ (text_protocol_suffix_info_for_each_item(*type, + dst, + dst_len - dst_pos, + dst_pos, + i < record_members_.count() - 1 ? false : true, + ObPLComposite::obj_is_null(obj))); } LOG_DEBUG("serialize element finished!", K(ret), K(*this), K(i), K(src), K(dst), K(dst_len), K(dst_pos)); } @@ -2545,19 +2758,23 @@ int ObCollectionType::serialize(share::schema::ObSchemaGetterGuard &schema_guard LOG_WARN("table is null", K(ret), KPC(table), KPC(this)); } else if (!table->is_inited()) { // table未初始化应该序列化为null, 空在空值位图中标识, 上层已经处理过空值位图, 这里什么都不做 - } else if (OB_FAIL(ObMySQLUtil::store_length(dst, dst_len, table->get_actual_count(), dst_pos))) { + } else if (BINARY == type && OB_FAIL(ObMySQLUtil::store_length(dst, dst_len, table->get_actual_count(), dst_pos))) { LOG_WARN("failed to stroe_length for table count", K(ret), KPC(this), KPC(table), K(table->get_count())); } else { - int64_t bitmap_bytes = (table->get_actual_count() + 7 + 2) / 8; char* bitmap = NULL; - // 计算空值位图位置 - if ((dst_len - dst_pos) < bitmap_bytes) { - ret = OB_SIZE_OVERFLOW; - LOG_WARN("size overflow", K(ret), KPC(this), KPC(table), K(dst_len), K(dst_pos), K(bitmap_bytes)); + int64_t bitmap_bytes = (table->get_actual_count() + 7 + 2) / 8; + if (BINARY == type) { + // 计算空值位图位置 + if ((dst_len - dst_pos) < bitmap_bytes) { + ret = OB_SIZE_OVERFLOW; + LOG_WARN("size overflow", K(ret), KPC(this), KPC(table), K(dst_len), K(dst_pos), K(bitmap_bytes)); + } else { + bitmap = dst + dst_pos; + MEMSET(dst + dst_pos, 0, bitmap_bytes); + dst_pos += bitmap_bytes; + } } else { - bitmap = dst + dst_pos; - MEMSET(dst + dst_pos, 0, bitmap_bytes); - dst_pos += bitmap_bytes; + // do nothing } // 序列化值并更新空值位图 for (int64_t i = 0; OB_SUCC(ret) && i < table->get_count(); ++i) { @@ -2567,8 +2784,24 @@ int ObCollectionType::serialize(share::schema::ObSchemaGetterGuard &schema_guard if (OB_FAIL(ret)) { } else if (obj->is_invalid_type()) { // deleted element, do nothing... - } else if (obj->is_null()) { - ObMySQLUtil::update_null_bitmap(bitmap, i); + } else if (ObPLComposite::obj_is_null(obj)) { + if (BINARY == type) { + ObMySQLUtil::update_null_bitmap(bitmap, i); + } else { + if (dst_len - dst_pos < 4) { + ret = OB_SIZE_OVERFLOW; + LOG_WARN("size overflow", K(ret), K(dst_len), K(dst_pos)); + } else { + MEMCPY(dst + dst_pos, "NULL", 4); + dst_pos += 4; + } + } + } else if (TEXT == type && OB_FAIL(text_protocol_prefix_info_for_each_item(schema_guard, + element_type_, + dst, + dst_len - dst_pos, + dst_pos))) { + LOG_WARN("set text protocol prefix info fail.", K(ret), K(get_name())); } else if (element_type_.is_collection_type()) { char *coll_src = reinterpret_cast(obj->get_ext()); ObPLNestedTable *coll_table = reinterpret_cast(coll_src); @@ -2576,13 +2809,31 @@ int ObCollectionType::serialize(share::schema::ObSchemaGetterGuard &schema_guard CK (OB_NOT_NULL(coll_src)); CK (OB_NOT_NULL(coll_table)); if (OB_FAIL(ret)) { - } else if (!coll_table->is_inited()) { + } else if (BINARY == type && !coll_table->is_inited()) { ObMySQLUtil::update_null_bitmap(bitmap, i); } else { OZ (element_type_.serialize(schema_guard, tz_info, type, data, dst, dst_len, dst_pos), KPC(this), K(i)); } } else { - OZ (element_type_.serialize(schema_guard, tz_info, type, data, dst, dst_len, dst_pos), KPC(this), K(i)); + int64_t offset_dst_pos = dst_pos; + bool has_serialized = false; + if (TEXT == type && OB_FAIL(base_type_serialize_for_text(obj, tz_info, dst, dst_len, dst_pos, has_serialized))) { + LOG_WARN("serialize for text fail.", K(ret), K(has_serialized)); + } else if (false == has_serialized) { + OZ (element_type_.serialize(schema_guard, tz_info, type, data, dst, dst_len, dst_pos), KPC(this), K(i)); + } + if (TEXT == type && !element_type_.is_record_type()) { + OZ (text_protocol_base_type_convert(element_type_, dst, offset_dst_pos, dst_len)); + OX (dst_pos = offset_dst_pos); + } + } + if (TEXT == type && !obj->is_invalid_type()) { + OZ (text_protocol_suffix_info_for_each_item(element_type_, + dst, + dst_len - dst_pos, + dst_pos, + i < table->get_count() - 1 ? false : true, + ObPLComposite::obj_is_null(obj))); } } LOG_DEBUG("serialize length", K(ret), KPC(table), KPC(this), K(reinterpret_cast(dst)), K(dst_len), K(dst_pos)); @@ -3518,6 +3769,31 @@ void ObPLComposite::print() const } } +bool ObPLComposite::obj_is_null(ObObj* obj) { + int ret = OB_SUCCESS; + bool is_null = true; + if (OB_ISNULL(obj)) { + } else if (obj->is_null()) { + } else if (obj->is_ext()) { + if (0 == obj->get_ext()) { + is_null = true; + } else if (PL_RECORD_TYPE == obj->get_meta().get_extend_type()) { + ObPLRecord *record = reinterpret_cast(obj->get_ext()); + is_null = (record->is_null() || !record->is_inited()) ? true : false; + } else if (PL_VARRAY_TYPE == obj->get_meta().get_extend_type() + || PL_NESTED_TABLE_TYPE == obj->get_meta().get_extend_type() + || PL_ASSOCIATIVE_ARRAY_TYPE == obj->get_meta().get_extend_type()) { + ObPLCollection *coll = reinterpret_cast(obj->get_ext()); + is_null = (coll->is_null() || !coll->is_inited()) ? true : false; + } else { + is_null = false; + } + } else { + is_null = false; + } + return is_null; +} + int ObPLRecord::get_not_null(int64_t i, bool ¬_null) { int ret = OB_SUCCESS; diff --git a/src/pl/ob_pl_user_type.h b/src/pl/ob_pl_user_type.h index a853afdb1e..cfd0b75754 100644 --- a/src/pl/ob_pl_user_type.h +++ b/src/pl/ob_pl_user_type.h @@ -151,6 +151,25 @@ public: static int deserialize_obj(ObObj &obj, const char* buf, const int64_t len, int64_t& pos); static int64_t get_serialize_obj_size(const ObObj &obj); + int text_protocol_prefix_info_for_each_item(share::schema::ObSchemaGetterGuard &schema_guard, + const ObPLDataType &type, + char *buf, + const int64_t len, + int64_t &pos) const; + int text_protocol_suffix_info_for_each_item(const ObPLDataType &type, + char *buf, + const int64_t len, + int64_t &pos, + const bool is_last_item, + const bool is_null) const; + int text_protocol_base_type_convert(const ObPLDataType &type, char *buf, int64_t &pos, int64_t len) const; + int base_type_serialize_for_text(ObObj* obj, + const ObTimeZoneInfo *tz_info, + char *dst, + const int64_t dst_len, + int64_t &dst_pos, + bool &has_serialized) const; + VIRTUAL_TO_STRING_KV(K_(type), K_(user_type_id), K_(type_name)); protected: common::ObString type_name_; @@ -827,6 +846,7 @@ public: int serialize(char *buf, int64_t len, int64_t &pos) const; int deserialize(const char* buf, const int64_t len, int64_t &pos); void print() const; + static bool obj_is_null(ObObj* obj); TO_STRING_KV(K_(type), K_(id), K_(is_null)); diff --git a/src/pl/pl_cache/ob_pl_cache.cpp b/src/pl/pl_cache/ob_pl_cache.cpp index 18fdabe440..feff01be9c 100644 --- a/src/pl/pl_cache/ob_pl_cache.cpp +++ b/src/pl/pl_cache/ob_pl_cache.cpp @@ -20,6 +20,109 @@ namespace oceanbase namespace pl { +void ObPLTableColumnInfo::reset() +{ + column_id_ = common::OB_INVALID_ID; + meta_type_.reset(); + accuracy_.reset(); + charset_type_ = CHARSET_INVALID; + if (inner_alloc_ != nullptr) { + if (column_name_.ptr() != nullptr) { + inner_alloc_->free(column_name_.ptr()); + column_name_.reset(); + } + for (int64_t i = 0; i < type_info_.count(); i++) { + ObString &str = type_info_.at(i); + if (str.ptr() != nullptr) { + inner_alloc_->free(str.ptr()); + str.reset(); + } + } + inner_alloc_ = nullptr; + } +} + +int ObPLTableColumnInfo::deep_copy_type_info(const common::ObIArray& type_info) +{ + int ret = OB_SUCCESS; + CK (OB_NOT_NULL(inner_alloc_)); + CK (0 == type_info_.count()); + for (int64_t i = 0; OB_SUCC(ret) && i < type_info.count(); ++i) { + const ObString &info = type_info.at(i); + if (OB_UNLIKELY(0 == info.length())) { + if (OB_FAIL(type_info_.push_back(ObString(0, NULL)))) { + LOG_WARN("fail to push back info", K(i), K(info), K(ret)); + } + } else { + char *buf = NULL; + if (OB_ISNULL(buf = static_cast(inner_alloc_->alloc(info.length())))) { + ret = OB_ALLOCATE_MEMORY_FAILED; + LOG_WARN("fail to allocate memory", K(i), K(info), K(ret)); + } else if (FALSE_IT(MEMCPY(buf, info.ptr(), info.length()))) { + } else if (OB_FAIL(type_info_.push_back(ObString(info.length(), buf)))) { + LOG_WARN("fail to push back info", K(i), K(info), K(ret)); + } + } + } + + return ret; +} + +int PCVPlSchemaObj::deep_copy_column_infos(const ObTableSchema *schema) +{ + int ret = OB_SUCCESS; + + if (OB_ISNULL(schema) || OB_ISNULL(inner_alloc_)) { + ret = OB_INVALID_ARGUMENT; + LOG_WARN("unexpected null argument", K(ret), K(schema), K(inner_alloc_)); + } else { + void *obj_buf = nullptr; + ObPLTableColumnInfo *column_info = nullptr; + column_cnt_ = schema->get_column_count(); + column_infos_.set_allocator(inner_alloc_); + if (OB_FAIL(column_infos_.init(column_cnt_))) { + LOG_WARN("failed to init column_infos", K(ret)); + } else { + ObTableSchema::const_column_iterator cs_iter = schema->column_begin(); + ObTableSchema::const_column_iterator cs_iter_end = schema->column_end(); + for (; OB_SUCC(ret) && cs_iter != cs_iter_end; cs_iter++) { + const ObColumnSchemaV2 &column_schema = **cs_iter; + if (nullptr == (obj_buf = inner_alloc_->alloc(sizeof(ObPLTableColumnInfo)))) { + ret = OB_ALLOCATE_MEMORY_FAILED; + LOG_WARN("failed to allocate memory", K(ret)); + } else if (FALSE_IT(column_info = new(obj_buf)ObPLTableColumnInfo(inner_alloc_))) { + // do nothing + } else { + column_info->column_id_ = column_schema.get_column_id(); + column_info->meta_type_ = column_schema.get_meta_type(); + column_info->charset_type_ = column_schema.get_charset_type(); + column_info->accuracy_ = column_schema.get_accuracy(); + OZ (column_info->deep_copy_type_info(column_schema.get_extended_type_info())); + + if (OB_SUCC(ret)) { + char *name_buf = NULL; + const ObString &column_name = column_schema.get_column_name_str(); + if (OB_ISNULL(name_buf = + static_cast(inner_alloc_->alloc(column_name.length() + 1)))) { + ret = OB_ALLOCATE_MEMORY_FAILED; + LOG_WARN("failed to alloc column name buf", K(ret), K(column_name)); + } else { + MEMCPY(name_buf, column_name.ptr(), column_name.length()); + ObString deep_copy_name(column_name.length(), name_buf); + column_info->column_name_ = deep_copy_name; + OZ (column_infos_.push_back(column_info)); + } + } + } + } + CK (column_cnt_ == column_infos_.count()); + } + } + + return ret; +} + + int PCVPlSchemaObj::init(const ObTableSchema *schema) { int ret = OB_SUCCESS; @@ -45,10 +148,26 @@ int PCVPlSchemaObj::init(const ObTableSchema *schema) MEMCPY(buf, tname.ptr(), tname.length()); table_name_.assign_ptr(buf, tname.length()); } + OZ (deep_copy_column_infos(schema)); } return ret; } +bool PCVPlSchemaObj::match_columns(ObIArray &column_infos) const +{ + bool is_match = true; + if (column_cnt_ != column_infos.count()) { + is_match = false; + } else { + for (int64_t i = 0; is_match && i < column_infos_.count(); ++i) { + if (*column_infos_.at(i) != column_infos.at(i)) { + is_match = false; + } + } + } + return is_match; +} + bool PCVPlSchemaObj::operator==(const PCVPlSchemaObj &other) const { bool ret = true; @@ -106,9 +225,20 @@ void PCVPlSchemaObj::reset() schema_version_ = 0; table_type_ = MAX_TABLE_TYPE; is_tmp_table_ = false; - if (inner_alloc_ != nullptr && table_name_.ptr() != nullptr) { - inner_alloc_->free(table_name_.ptr()); - table_name_.reset(); + column_cnt_ = 0; + if (inner_alloc_ != nullptr) { + if (table_name_.ptr() != nullptr) { + inner_alloc_->free(table_name_.ptr()); + table_name_.reset(); + } + for (int64_t i = 0; i < column_infos_.count(); i++) { + if (OB_ISNULL(column_infos_.at(i))) { + // do nothing + } else { + column_infos_.at(i)->reset(); + inner_alloc_->free(column_infos_.at(i)); + } + } inner_alloc_ = nullptr; } } @@ -236,6 +366,41 @@ int ObPLObjectValue::lift_tenant_schema_version(int64_t new_schema_version) return ret; } +int ObPLObjectValue::obtain_new_column_infos(share::schema::ObSchemaGetterGuard &schema_guard, + const PCVPlSchemaObj &schema_obj, + ObIArray &column_infos) +{ + int ret = OB_SUCCESS; + const ObTableSchema *table_schema = nullptr; + if (OB_FAIL(schema_guard.get_table_schema( + MTL_ID(), + schema_obj.schema_id_, + table_schema))) { // now deal with table schema + LOG_WARN("failed to get table schema", K(ret), K(schema_obj), K(table_schema)); + } else if (nullptr == table_schema) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("get an unexpected null schema", K(ret), K(table_schema)); + } else if (table_schema->is_index_table()) { + // do nothing + } else { + ObPLTableColumnInfo column_info; + ObTableSchema::const_column_iterator cs_iter = table_schema->column_begin(); + ObTableSchema::const_column_iterator cs_iter_end = table_schema->column_end(); + for (; OB_SUCC(ret) && cs_iter != cs_iter_end; cs_iter++) { + const ObColumnSchemaV2 &column_schema = **cs_iter; + column_info.column_id_ = column_schema.get_column_id(); + column_info.meta_type_ = column_schema.get_meta_type(); + column_info.charset_type_ = column_schema.get_charset_type(); + column_info.accuracy_ = column_schema.get_accuracy(); + OZ (column_info.type_info_.assign(column_schema.get_extended_type_info())); + OX (column_info.column_name_ = column_schema.get_column_name_str()); + OZ (column_infos.push_back(column_info)); + } + } + + return ret; +} + int ObPLObjectValue::check_value_version(share::schema::ObSchemaGetterGuard *schema_guard, bool need_check_schema, const ObIArray &schema_array, @@ -264,6 +429,12 @@ int ObPLObjectValue::check_value_version(share::schema::ObSchemaGetterGuard *sch } else if (*schema_obj1 == schema_obj2) { // schema do match LOG_DEBUG("matched schema objs", K(*schema_obj1), K(schema_obj2), K(i)); // do nothing + } else if (schema_obj1->schema_type_ == schema_obj2.schema_type_ && + TABLE_SCHEMA == schema_obj1->schema_type_ && + schema_obj1->schema_id_ == schema_obj2.schema_id_) { + ObSEArray column_infos; + OZ (obtain_new_column_infos(*schema_guard, schema_obj2, column_infos)); + OX (is_old_version = !schema_obj1->match_columns(column_infos)); } else { LOG_WARN("mismatched schema objs", K(*schema_obj1), K(schema_obj2), K(i)); is_old_version = true; @@ -344,6 +515,54 @@ int ObPLObjectValue::get_all_dep_schema(ObSchemaGetterGuard &schema_guard, return ret; } +int ObPLObjectValue::get_synonym_schema_version(ObPLCacheCtx &pc_ctx, + uint64_t tenant_id, + const PCVPlSchemaObj &pcv_schema, + int64_t &new_version) +{ + int ret = OB_SUCCESS; + if (OB_ISNULL(pc_ctx.schema_guard_) || OB_ISNULL(pc_ctx.session_info_)) { + ret = OB_INVALID_ARGUMENT; + LOG_WARN("invalid argument", K(ret)); + } else { + const ObSimpleSynonymSchema *synonym_info = NULL; + ObSchemaGetterGuard &schema_guard = *pc_ctx.schema_guard_; + ObSQLSessionInfo *session_info = pc_ctx.session_info_; + CK (SYNONYM_SCHEMA == pcv_schema.schema_type_); + OZ (schema_guard.get_simple_synonym_info(tenant_id, pcv_schema.schema_id_, synonym_info)); + if (OB_SUCC(ret) && OB_NOT_NULL(synonym_info)) { + if (OB_PUBLIC_SCHEMA_ID == synonym_info->get_database_id()) { + // in same db, no need check for objects with the same name if synonym name is same as linked object name + if (pc_ctx.session_info_->get_database_id() == synonym_info->get_object_database_id() && + synonym_info->get_synonym_name() == synonym_info->get_object_name()) { + new_version = synonym_info->get_schema_version(); + } else { + bool exist = false; + bool is_private_syn = false; + ObSchemaChecker schema_checker; + int tmp = schema_checker.init(schema_guard); + if (OB_SUCCESS == tmp) { + tmp = schema_checker.check_exist_same_name_object_with_synonym(synonym_info->get_tenant_id(), + session_info->get_database_id(), + synonym_info->get_synonym_name(), + exist, + is_private_syn); + if (exist) { + ret = OB_OLD_SCHEMA_VERSION; + LOG_WARN("exist object which name as current synonym", K(ret), KPC(synonym_info)); + } else { + new_version = synonym_info->get_schema_version(); + } + } + } + } else { + new_version = synonym_info->get_schema_version(); + } + } + } + return ret; +} + int ObPLObjectValue::get_all_dep_schema(ObPLCacheCtx &pc_ctx, const uint64_t database_id, int64_t &new_schema_version, @@ -376,18 +595,24 @@ int ObPLObjectValue::get_all_dep_schema(ObPLCacheCtx &pc_ctx, } else if (TABLE_SCHEMA != pcv_schema->schema_type_) { // if no table schema, get schema version is enough int64_t new_version = 0; - if (PACKAGE_SCHEMA == stored_schema_objs_.at(i)->schema_type_ - || UDT_SCHEMA == stored_schema_objs_.at(i)->schema_type_ - || ROUTINE_SCHEMA == stored_schema_objs_.at(i)->schema_type_) { - tenant_id = pl::get_tenant_id_by_object_id(stored_schema_objs_.at(i)->schema_id_); + if (PACKAGE_SCHEMA == pcv_schema->schema_type_ + || UDT_SCHEMA == pcv_schema->schema_type_ + || ROUTINE_SCHEMA == pcv_schema->schema_type_) { + tenant_id = pl::get_tenant_id_by_object_id(pcv_schema->schema_id_); } - if (OB_FAIL(schema_guard.get_schema_version(pcv_schema->schema_type_, - tenant_id, - pcv_schema->schema_id_, - new_version))) { + if (SYNONYM_SCHEMA == pcv_schema->schema_type_) { + if (OB_FAIL(get_synonym_schema_version(pc_ctx, tenant_id, *pcv_schema, new_version))) { + LOG_WARN("failed to get schema version", + K(ret), K(tenant_id), K(pcv_schema->schema_type_), K(pcv_schema->schema_id_)); + } + } else if (OB_FAIL(schema_guard.get_schema_version(pcv_schema->schema_type_, + tenant_id, + pcv_schema->schema_id_, + new_version))) { LOG_WARN("failed to get schema version", K(ret), K(tenant_id), K(pcv_schema->schema_type_), K(pcv_schema->schema_id_)); - } else { + } + if (OB_SUCC(ret)) { tmp_schema_obj.schema_id_ = pcv_schema->schema_id_; tmp_schema_obj.schema_type_ = pcv_schema->schema_type_; tmp_schema_obj.schema_version_ = new_version; @@ -474,17 +699,13 @@ int ObPLObjectValue::match_dep_schema(const ObPLCacheCtx &pc_ctx, } else if (schema_array.count() != stored_schema_objs_.count()) { is_same = false; } else { + // oracle模式临时表实际上就是实表, 只需比较schema信息即可; + // mysql模式临时表不能用于trigger, sql语句的表依赖信息也不会加到存储过程依赖列表中 + // 因此, 移除临时表比较sessid相关逻辑 for (int64_t i = 0; OB_SUCC(ret) && is_same && i < schema_array.count(); i++) { if (OB_ISNULL(stored_schema_objs_.at(i))) { ret = OB_INVALID_ARGUMENT; LOG_WARN("invalid null table schema", K(ret), K(i)); - } else if (schema_array.at(i).is_tmp_table_) { // check for tmp table - is_same = ((session_info->get_sessid_for_table() == sessid_) && - (session_info->get_sess_create_time() == sess_create_time_)); - if (!is_same) { - LOG_WARN("tmp table not match", K(ret), K(sessid_), K(session_info->get_sessid_for_table()), - K(sess_create_time_), K(session_info->get_sess_create_time())); - } } else if (lib::is_oracle_mode() && TABLE_SCHEMA == stored_schema_objs_.at(i)->schema_type_ && !stored_schema_objs_.at(i)->match_compare(schema_array.at(i))) { diff --git a/src/pl/pl_cache/ob_pl_cache.h b/src/pl/pl_cache/ob_pl_cache.h index 3164b63fea..965fd6abf0 100644 --- a/src/pl/pl_cache/ob_pl_cache.h +++ b/src/pl/pl_cache/ob_pl_cache.h @@ -34,6 +34,74 @@ struct ObPLCacheCtx; class ObPLObjectSet; class ObPLCacheMgr; +struct ObPLTableColumnInfo +{ + common::ObIAllocator *inner_alloc_; + uint64_t column_id_; + common::ObObjMeta meta_type_; + common::ObAccuracy accuracy_; + common::ObCharsetType charset_type_; + common::ObString column_name_; + common::ObArray type_info_;//used for enum and set + + ObPLTableColumnInfo(): + inner_alloc_(nullptr), + column_id_(common::OB_INVALID_ID), + meta_type_(), + accuracy_(), + charset_type_(CHARSET_INVALID), + column_name_(), + type_info_() + {} + + explicit ObPLTableColumnInfo(ObIAllocator *alloc): + inner_alloc_(alloc), + column_id_(common::OB_INVALID_ID), + meta_type_(), + accuracy_(), + charset_type_(CHARSET_INVALID), + column_name_(), + type_info_() + {} + + bool operator==(const ObPLTableColumnInfo &other) const + { + bool is_same = true; + if (type_info_.count() != other.type_info_.count()) { + is_same = false; + } else { + for (int64_t i = 0; is_same && i < type_info_.count(); ++i) { + is_same = type_info_.at(i) == other.type_info_.at(i); + } + is_same = is_same && + column_id_ == other.column_id_ && + meta_type_ == other.meta_type_ && + accuracy_ == other.accuracy_ && + charset_type_ == other.charset_type_ && + column_name_ == other.column_name_; + } + return is_same; + } + + bool operator!=(const ObPLTableColumnInfo &other) const + { + return !operator==(other); + } + + void reset(); + int deep_copy_type_info(const common::ObIArray& type_info); + ~ObPLTableColumnInfo() + { + reset(); + } + + TO_STRING_KV(K_(column_id), + K_(meta_type), + K_(accuracy), + K_(charset_type), + K_(column_name)); +}; + //todo:when PCVSchemaObj has been moved to appropriate header file, use PCVSchemaObj to instead of PCVPlSchemaObj struct PCVPlSchemaObj { @@ -47,6 +115,8 @@ struct PCVPlSchemaObj bool is_tmp_table_; bool is_explicit_db_name_; common::ObIAllocator *inner_alloc_; + int64_t column_cnt_; + common::ObFixedArray column_infos_; PCVPlSchemaObj(): tenant_id_(common::OB_INVALID_ID), @@ -58,7 +128,9 @@ struct PCVPlSchemaObj table_name_(), is_tmp_table_(false), is_explicit_db_name_(false), - inner_alloc_(nullptr) {} + inner_alloc_(nullptr), + column_cnt_(0), + column_infos_(inner_alloc_) {} explicit PCVPlSchemaObj(ObIAllocator *alloc): tenant_id_(common::OB_INVALID_ID), @@ -70,7 +142,9 @@ struct PCVPlSchemaObj table_name_(), is_tmp_table_(false), is_explicit_db_name_(false), - inner_alloc_(alloc) {} + inner_alloc_(alloc), + column_cnt_(0), + column_infos_(inner_alloc_) {} int init(const share::schema::ObTableSchema *schema); int init_with_version_obj(const share::schema::ObSchemaObjVersion &schema_obj_version); @@ -79,6 +153,7 @@ struct PCVPlSchemaObj { inner_alloc_ = alloc; } + int deep_copy_column_infos(const ObTableSchema *schema); bool compare_schema(const share::schema::ObTableSchema &schema) const { @@ -100,6 +175,8 @@ struct PCVPlSchemaObj return ret; } + bool match_columns(ObIArray &column_infos) const; + bool operator==(const PCVPlSchemaObj &other) const; bool operator!=(const PCVPlSchemaObj &other) const @@ -176,6 +253,9 @@ public: int set_stored_schema_objs(const DependenyTableStore &dep_table_store, share::schema::ObSchemaGetterGuard *schema_guard); int lift_tenant_schema_version(int64_t new_schema_version); + int obtain_new_column_infos(share::schema::ObSchemaGetterGuard &schema_guard, + const PCVPlSchemaObj &schema_obj, + ObIArray &column_infos); int check_value_version(share::schema::ObSchemaGetterGuard *schema_guard, bool need_check_schema, const ObIArray &schema_array, @@ -183,6 +263,10 @@ public: int need_check_schema_version(ObPLCacheCtx &pc_ctx, int64_t &new_schema_version, bool &need_check); + int get_synonym_schema_version(ObPLCacheCtx &pc_ctx, + uint64_t tenant_id, + const PCVPlSchemaObj &pcv_schema, + int64_t &new_version); int get_all_dep_schema(ObPLCacheCtx &pc_ctx, const uint64_t database_id, int64_t &new_schema_version, @@ -260,7 +344,8 @@ struct ObPLCacheCtx : public ObILibCacheCtx schema_guard_(NULL), need_add_obj_stat_(true), cache_params_(NULL), - raw_sql_() + raw_sql_(), + compile_time_(0) { sql_id_[0] = '\0'; sql_id_[common::OB_MAX_SQL_ID_LENGTH] = '\0'; @@ -274,6 +359,7 @@ struct ObPLCacheCtx : public ObILibCacheCtx bool need_add_obj_stat_; ParamStore *cache_params_; ObString raw_sql_; + int64_t compile_time_; // pl object cost time of compile }; diff --git a/src/pl/pl_cache/ob_pl_cache_mgr.cpp b/src/pl/pl_cache/ob_pl_cache_mgr.cpp index 5d19674a27..e6677fd7f7 100644 --- a/src/pl/pl_cache/ob_pl_cache_mgr.cpp +++ b/src/pl/pl_cache/ob_pl_cache_mgr.cpp @@ -90,17 +90,10 @@ int ObPLCacheMgr::get_pl_cache(ObPlanCache *lib_cache, ObCacheObjGuard& guard, O // update pl func/package stat pl::PLCacheObjStat *stat = NULL; int64_t current_time = ObTimeUtility::current_time(); - if (ObLibCacheNameSpace::NS_PKG != guard.get_cache_obj()->get_ns() && - ObLibCacheNameSpace::NS_CALLSTMT != guard.get_cache_obj()->get_ns()) { - pl::ObPLFunction* pl_func = static_cast(guard.get_cache_obj()); - stat = &pl_func->get_stat_for_update(); - ATOMIC_INC(&(stat->hit_count_)); - ATOMIC_STORE(&(stat->last_active_time_), current_time); - } else { - //todo:support package - //pl::ObPLPackage* pl_pkg = static_cast(guard.get_cache_obj()); - //stat = &pl_pkg->get_stat_for_update(); - } + pl::ObPLCacheObject* pl_object = static_cast(guard.get_cache_obj()); + stat = &pl_object->get_stat_for_update(); + ATOMIC_INC(&(stat->hit_count_)); + ATOMIC_STORE(&(stat->last_active_time_), current_time); } return ret; } diff --git a/src/pl/pl_cache/ob_pl_cache_object.cpp b/src/pl/pl_cache/ob_pl_cache_object.cpp index ccf3a85a4e..a7b057f08c 100644 --- a/src/pl/pl_cache/ob_pl_cache_object.cpp +++ b/src/pl/pl_cache/ob_pl_cache_object.cpp @@ -13,6 +13,8 @@ #define USING_LOG_PREFIX PL_CACHE #include "ob_pl_cache_object.h" #include "lib/oblog/ob_log_module.h" +#include "pl/pl_cache/ob_pl_cache.h" +#include "src/share/ob_truncated_string.h" namespace oceanbase { @@ -113,5 +115,65 @@ int ObPLCacheObject::set_params_info(const ParamStore ¶ms, bool is_anonymous return ret; } +int ObPLCacheObject::update_cache_obj_stat(sql::ObILibCacheCtx &ctx) +{ + int ret = OB_SUCCESS; + ObPLCacheCtx &pc_ctx = static_cast(ctx); + PLCacheObjStat &stat = get_stat_for_update(); + + stat.pl_schema_id_ = pc_ctx.key_.key_id_; + stat.gen_time_ = ObTimeUtility::current_time(); + stat.last_active_time_ = ObTimeUtility::current_time(); + stat.hit_count_ = 0; + stat.schema_version_ = get_tenant_schema_version(); + MEMCPY(stat.sql_id_, pc_ctx.sql_id_, (int32_t)sizeof(pc_ctx.sql_id_)); + + if (OB_SUCC(ret)) { + ObTruncatedString trunc_name_sql(stat.name_, OB_MAX_SQL_LENGTH); + if (OB_FAIL(ob_write_string(get_allocator(), + trunc_name_sql.string(), + stat.name_))) { + LOG_WARN("failed to write sql", K(ret)); + } else { + stat.sql_cs_type_ = pc_ctx.session_info_->get_local_collation_connection(); + } + } + if (OB_SUCC(ret)) { + if (ObLibCacheNameSpace::NS_ANON == get_ns() || + ObLibCacheNameSpace::NS_CALLSTMT == get_ns()) { + ObTruncatedString trunc_raw_sql(pc_ctx.raw_sql_, OB_MAX_SQL_LENGTH); + if (OB_FAIL(ob_write_string(get_allocator(), + trunc_raw_sql.string(), + stat.raw_sql_))) { + LOG_WARN("failed to write sql", K(ret)); + } + } + } + if (OB_SUCC(ret)) { + if (ObLibCacheNameSpace::NS_ANON == get_ns() && OB_INVALID_ID != pc_ctx.key_.key_id_) { + stat.ps_stmt_id_ = pc_ctx.key_.key_id_; + } + } + if (OB_SUCC(ret)) { + // Update last_active_time_ last, because last_active_time_ is used to + // indicate whether the cache stat has been updated. + stat.last_active_time_ = ObTimeUtility::current_time(); + } + return ret; +} + +int ObPLCacheObject::update_execute_time(int64_t exec_time) +{ + int ret = OB_SUCCESS; + ATOMIC_STORE(&(stat_.elapsed_time_), exec_time); + ATOMIC_INC(&(stat_.execute_times_)); + int64_t slowest_usec = ATOMIC_LOAD(&stat_.slowest_exec_usec_); + if (slowest_usec < exec_time) { + ATOMIC_STORE(&(stat_.slowest_exec_usec_), exec_time); + ATOMIC_STORE(&(stat_.slowest_exec_time_), ObClockGenerator::getClock()); + } + return ret; +} + } } \ No newline at end of file diff --git a/src/pl/pl_cache/ob_pl_cache_object.h b/src/pl/pl_cache/ob_pl_cache_object.h index 5c3db9843d..3d29cff518 100644 --- a/src/pl/pl_cache/ob_pl_cache_object.h +++ b/src/pl/pl_cache/ob_pl_cache_object.h @@ -59,6 +59,91 @@ struct ObPlParamInfo : public sql::ObParamInfo OB_UNIS_VERSION_V(1); }; +enum ObPLCacheObjectType +{ + INVALID_PL_OBJECT_TYPE = 5, // start with OB_PHY_PLAN_UNCERTAIN, distict ObPhyPlanType + STANDALONE_ROUTINE_TYPE, + PACKAGE_ROUTINE_TYPE, + UDT_ROUTINE_TYPE, + ANONYMOUS_BLOCK_TYPE, + CALL_STMT_TYPE, + MAX_TYPE_NUM +}; + +struct PLCacheObjStat +{ + char sql_id_[common::OB_MAX_SQL_ID_LENGTH + 1]; + int64_t pl_schema_id_; + common::ObString raw_sql_; // sql txt for anonymous block + common::ObString name_; + common::ObCollationType sql_cs_type_; + int64_t gen_time_; + int64_t last_active_time_; + int64_t compile_time_; // pl object cost time of compile + uint64_t hit_count_; + ObPLCacheObjectType type_; + int64_t elapsed_time_; //执行时间rt + int64_t execute_times_; //SUCC下执行次数 + int64_t slowest_exec_time_; // execution slowest time + uint64_t slowest_exec_usec_; // execution slowest usec + int64_t schema_version_; + int64_t ps_stmt_id_;//prepare stmt id + + PLCacheObjStat() + : pl_schema_id_(OB_INVALID_ID), + raw_sql_(), + name_(), + sql_cs_type_(common::CS_TYPE_INVALID), + gen_time_(0), + last_active_time_(0), + compile_time_(0), + hit_count_(0), + type_(ObPLCacheObjectType::INVALID_PL_OBJECT_TYPE), + elapsed_time_(0), + execute_times_(0), + slowest_exec_time_(0), + slowest_exec_usec_(0), + schema_version_(OB_INVALID_ID), + ps_stmt_id_(OB_INVALID_ID) + { + sql_id_[0] = '\0'; + } + + inline bool is_updated() const + { + return last_active_time_ != 0; + } + + void reset() + { + sql_id_[0] = '\0'; + pl_schema_id_ = OB_INVALID_ID; + sql_cs_type_ = common::CS_TYPE_INVALID; + raw_sql_.reset(); + name_.reset(); + gen_time_ = 0; + last_active_time_ = 0; + hit_count_ = 0; + type_ = ObPLCacheObjectType::INVALID_PL_OBJECT_TYPE; + elapsed_time_ = 0; + execute_times_ = 0; + slowest_exec_time_ = 0; + slowest_exec_usec_ = 0; + schema_version_ = OB_INVALID_ID; + ps_stmt_id_ = OB_INVALID_ID; + } + + TO_STRING_KV(K_(pl_schema_id), + K_(gen_time), + K_(last_active_time), + K_(hit_count), + K_(raw_sql), + K_(name), + K_(compile_time), + K_(type), + K_(schema_version)); +}; + class ObPLCacheObject : public sql::ObILibCacheObject { public: @@ -73,7 +158,8 @@ public: expr_operator_factory_(allocator_), expressions_(allocator_), expr_op_size_(0), - frame_info_(allocator_) + frame_info_(allocator_), + stat_() {} virtual ~ObPLCacheObject() {} @@ -104,6 +190,12 @@ public: inline void set_expr_op_size(int64_t size) { expr_op_size_ = size; } inline sql::ObExprFrameInfo &get_frame_info() { return frame_info_; } + inline const PLCacheObjStat get_stat() const { return stat_; } + inline PLCacheObjStat &get_stat_for_update() { return stat_; } + + virtual int update_cache_obj_stat(sql::ObILibCacheCtx &ctx); + int update_execute_time(int64_t exec_time); + TO_STRING_KV(K_(expr_op_size), K_(tenant_schema_version), K_(sys_schema_version), @@ -123,6 +215,8 @@ protected: common::ObFixedArray expressions_; int64_t expr_op_size_; sql::ObExprFrameInfo frame_info_; + // stat info + PLCacheObjStat stat_; }; } // namespace pl end diff --git a/src/share/inner_table/ob_inner_table_schema.21451_21500.cpp b/src/share/inner_table/ob_inner_table_schema.21451_21500.cpp index 858617c68a..4f97cd8663 100644 --- a/src/share/inner_table/ob_inner_table_schema.21451_21500.cpp +++ b/src/share/inner_table/ob_inner_table_schema.21451_21500.cpp @@ -25,6 +25,106 @@ using namespace common; namespace share { +int ObInnerTableSchema::gv_ob_pl_cache_object_schema(ObTableSchema &table_schema) +{ + int ret = OB_SUCCESS; + uint64_t column_id = OB_APP_MIN_COLUMN_ID - 1; + + //generated fields: + table_schema.set_tenant_id(OB_SYS_TENANT_ID); + table_schema.set_tablegroup_id(OB_INVALID_ID); + table_schema.set_database_id(OB_SYS_DATABASE_ID); + table_schema.set_table_id(OB_GV_OB_PL_CACHE_OBJECT_TID); + table_schema.set_rowkey_split_pos(0); + table_schema.set_is_use_bloomfilter(false); + table_schema.set_progressive_merge_num(0); + table_schema.set_rowkey_column_num(0); + table_schema.set_load_type(TABLE_LOAD_TYPE_IN_DISK); + table_schema.set_table_type(SYSTEM_VIEW); + table_schema.set_index_type(INDEX_TYPE_IS_NOT); + table_schema.set_def_type(TABLE_DEF_TYPE_INTERNAL); + + if (OB_SUCC(ret)) { + if (OB_FAIL(table_schema.set_table_name(OB_GV_OB_PL_CACHE_OBJECT_TNAME))) { + LOG_ERROR("fail to set table_name", K(ret)); + } + } + + if (OB_SUCC(ret)) { + if (OB_FAIL(table_schema.set_compress_func_name(OB_DEFAULT_COMPRESS_FUNC_NAME))) { + LOG_ERROR("fail to set compress_func_name", K(ret)); + } + } + table_schema.set_part_level(PARTITION_LEVEL_ZERO); + table_schema.set_charset_type(ObCharset::get_default_charset()); + table_schema.set_collation_type(ObCharset::get_default_collation(ObCharset::get_default_charset())); + + if (OB_SUCC(ret)) { + if (OB_FAIL(table_schema.set_view_definition(R"__( SELECT TENANT_ID, SVR_IP, SVR_PORT, PLAN_ID AS CACHE_OBJECT_ID, STATEMENT AS PARAMETERIZE_TEXT, QUERY_SQL AS OBJECT_TEXT, FIRST_LOAD_TIME, LAST_ACTIVE_TIME, AVG_EXE_USEC, SLOWEST_EXE_TIME, SLOWEST_EXE_USEC, HIT_COUNT, PLAN_SIZE AS CACHE_OBJ_SIZE, EXECUTIONS, ELAPSED_TIME, OBJECT_TYPE, PL_SCHEMA_ID AS OBJECT_ID, COMPILE_TIME, SCHEMA_VERSION, PS_STMT_ID FROM oceanbase.__all_virtual_plan_stat WHERE OBJECT_STATUS = 0 AND TYPE > 5 AND TYPE < 11 AND is_in_pc=true )__"))) { + LOG_ERROR("fail to set view_definition", K(ret)); + } + } + table_schema.set_index_using_type(USING_BTREE); + table_schema.set_row_store_type(ENCODING_ROW_STORE); + table_schema.set_store_format(OB_STORE_FORMAT_DYNAMIC_MYSQL); + table_schema.set_progressive_merge_round(1); + table_schema.set_storage_format_version(3); + table_schema.set_tablet_id(0); + + table_schema.set_max_used_column_id(column_id); + return ret; +} + +int ObInnerTableSchema::v_ob_pl_cache_object_schema(ObTableSchema &table_schema) +{ + int ret = OB_SUCCESS; + uint64_t column_id = OB_APP_MIN_COLUMN_ID - 1; + + //generated fields: + table_schema.set_tenant_id(OB_SYS_TENANT_ID); + table_schema.set_tablegroup_id(OB_INVALID_ID); + table_schema.set_database_id(OB_SYS_DATABASE_ID); + table_schema.set_table_id(OB_V_OB_PL_CACHE_OBJECT_TID); + table_schema.set_rowkey_split_pos(0); + table_schema.set_is_use_bloomfilter(false); + table_schema.set_progressive_merge_num(0); + table_schema.set_rowkey_column_num(0); + table_schema.set_load_type(TABLE_LOAD_TYPE_IN_DISK); + table_schema.set_table_type(SYSTEM_VIEW); + table_schema.set_index_type(INDEX_TYPE_IS_NOT); + table_schema.set_def_type(TABLE_DEF_TYPE_INTERNAL); + + if (OB_SUCC(ret)) { + if (OB_FAIL(table_schema.set_table_name(OB_V_OB_PL_CACHE_OBJECT_TNAME))) { + LOG_ERROR("fail to set table_name", K(ret)); + } + } + + if (OB_SUCC(ret)) { + if (OB_FAIL(table_schema.set_compress_func_name(OB_DEFAULT_COMPRESS_FUNC_NAME))) { + LOG_ERROR("fail to set compress_func_name", K(ret)); + } + } + table_schema.set_part_level(PARTITION_LEVEL_ZERO); + table_schema.set_charset_type(ObCharset::get_default_charset()); + table_schema.set_collation_type(ObCharset::get_default_collation(ObCharset::get_default_charset())); + + if (OB_SUCC(ret)) { + if (OB_FAIL(table_schema.set_view_definition(R"__( SELECT TENANT_ID, SVR_IP, SVR_PORT, CACHE_OBJECT_ID, PARAMETERIZE_TEXT, OBJECT_TEXT, FIRST_LOAD_TIME, LAST_ACTIVE_TIME, AVG_EXE_USEC, SLOWEST_EXE_TIME, SLOWEST_EXE_USEC, HIT_COUNT, CACHE_OBJ_SIZE, EXECUTIONS, ELAPSED_TIME, OBJECT_TYPE, OBJECT_ID, COMPILE_TIME, SCHEMA_VERSION, PS_STMT_ID FROM oceanbase.GV$OB_PL_CACHE_OBJECT WHERE SVR_IP =HOST_IP() AND SVR_PORT = RPC_PORT() )__"))) { + LOG_ERROR("fail to set view_definition", K(ret)); + } + } + table_schema.set_index_using_type(USING_BTREE); + table_schema.set_row_store_type(ENCODING_ROW_STORE); + table_schema.set_store_format(OB_STORE_FORMAT_DYNAMIC_MYSQL); + table_schema.set_progressive_merge_round(1); + table_schema.set_storage_format_version(3); + table_schema.set_tablet_id(0); + + table_schema.set_max_used_column_id(column_id); + return ret; +} + int ObInnerTableSchema::cdb_ob_recover_table_jobs_schema(ObTableSchema &table_schema) { int ret = OB_SUCCESS; diff --git a/src/share/inner_table/ob_inner_table_schema.28151_28200.cpp b/src/share/inner_table/ob_inner_table_schema.28151_28200.cpp index 540802b590..8bece71d57 100644 --- a/src/share/inner_table/ob_inner_table_schema.28151_28200.cpp +++ b/src/share/inner_table/ob_inner_table_schema.28151_28200.cpp @@ -1525,6 +1525,106 @@ int ObInnerTableSchema::gv_ob_flt_trace_config_ora_schema(ObTableSchema &table_s return ret; } +int ObInnerTableSchema::gv_ob_pl_cache_object_ora_schema(ObTableSchema &table_schema) +{ + int ret = OB_SUCCESS; + uint64_t column_id = OB_APP_MIN_COLUMN_ID - 1; + + //generated fields: + table_schema.set_tenant_id(OB_SYS_TENANT_ID); + table_schema.set_tablegroup_id(OB_INVALID_ID); + table_schema.set_database_id(OB_ORA_SYS_DATABASE_ID); + table_schema.set_table_id(OB_GV_OB_PL_CACHE_OBJECT_ORA_TID); + table_schema.set_rowkey_split_pos(0); + table_schema.set_is_use_bloomfilter(false); + table_schema.set_progressive_merge_num(0); + table_schema.set_rowkey_column_num(0); + table_schema.set_load_type(TABLE_LOAD_TYPE_IN_DISK); + table_schema.set_table_type(SYSTEM_VIEW); + table_schema.set_index_type(INDEX_TYPE_IS_NOT); + table_schema.set_def_type(TABLE_DEF_TYPE_INTERNAL); + + if (OB_SUCC(ret)) { + if (OB_FAIL(table_schema.set_table_name(OB_GV_OB_PL_CACHE_OBJECT_ORA_TNAME))) { + LOG_ERROR("fail to set table_name", K(ret)); + } + } + + if (OB_SUCC(ret)) { + if (OB_FAIL(table_schema.set_compress_func_name(OB_DEFAULT_COMPRESS_FUNC_NAME))) { + LOG_ERROR("fail to set compress_func_name", K(ret)); + } + } + table_schema.set_part_level(PARTITION_LEVEL_ZERO); + table_schema.set_charset_type(ObCharset::get_default_charset()); + table_schema.set_collation_type(ObCharset::get_default_collation(ObCharset::get_default_charset())); + + if (OB_SUCC(ret)) { + if (OB_FAIL(table_schema.set_view_definition(R"__( SELECT TENANT_ID AS TENANT_ID, SVR_IP AS SVR_IP, SVR_PORT AS SVR_PORT, PLAN_ID AS CACHE_OBJECT_ID, STATEMENT AS PARAMETERIZE_TEXT, QUERY_SQL AS OBJECT_TEXT, FIRST_LOAD_TIME AS FIRST_LOAD_TIME, LAST_ACTIVE_TIME AS LAST_ACTIVE_TIME, AVG_EXE_USEC AS AVG_EXE_USEC, SLOWEST_EXE_TIME AS SLOWEST_EXE_TIME, SLOWEST_EXE_USEC AS SLOWEST_EXE_USEC, HIT_COUNT AS HIT_COUNT, PLAN_SIZE AS CACHE_OBJ_SIZE, EXECUTIONS AS EXECUTIONS, ELAPSED_TIME AS ELAPSED_TIME, OBJECT_TYPE AS OBJECT_TYPE, PL_SCHEMA_ID AS OBJECT_ID, COMPILE_TIME AS COMPILE_TIME, SCHEMA_VERSION AS SCHEMA_VERSION, PS_STMT_ID AS PS_STMT_ID FROM SYS.ALL_VIRTUAL_PLAN_STAT WHERE OBJECT_STATUS = 0 AND TYPE > 5 AND TYPE < 11 AND is_in_pc='1' )__"))) { + LOG_ERROR("fail to set view_definition", K(ret)); + } + } + table_schema.set_index_using_type(USING_BTREE); + table_schema.set_row_store_type(ENCODING_ROW_STORE); + table_schema.set_store_format(OB_STORE_FORMAT_DYNAMIC_MYSQL); + table_schema.set_progressive_merge_round(1); + table_schema.set_storage_format_version(3); + table_schema.set_tablet_id(0); + + table_schema.set_max_used_column_id(column_id); + return ret; +} + +int ObInnerTableSchema::v_ob_pl_cache_object_ora_schema(ObTableSchema &table_schema) +{ + int ret = OB_SUCCESS; + uint64_t column_id = OB_APP_MIN_COLUMN_ID - 1; + + //generated fields: + table_schema.set_tenant_id(OB_SYS_TENANT_ID); + table_schema.set_tablegroup_id(OB_INVALID_ID); + table_schema.set_database_id(OB_ORA_SYS_DATABASE_ID); + table_schema.set_table_id(OB_V_OB_PL_CACHE_OBJECT_ORA_TID); + table_schema.set_rowkey_split_pos(0); + table_schema.set_is_use_bloomfilter(false); + table_schema.set_progressive_merge_num(0); + table_schema.set_rowkey_column_num(0); + table_schema.set_load_type(TABLE_LOAD_TYPE_IN_DISK); + table_schema.set_table_type(SYSTEM_VIEW); + table_schema.set_index_type(INDEX_TYPE_IS_NOT); + table_schema.set_def_type(TABLE_DEF_TYPE_INTERNAL); + + if (OB_SUCC(ret)) { + if (OB_FAIL(table_schema.set_table_name(OB_V_OB_PL_CACHE_OBJECT_ORA_TNAME))) { + LOG_ERROR("fail to set table_name", K(ret)); + } + } + + if (OB_SUCC(ret)) { + if (OB_FAIL(table_schema.set_compress_func_name(OB_DEFAULT_COMPRESS_FUNC_NAME))) { + LOG_ERROR("fail to set compress_func_name", K(ret)); + } + } + table_schema.set_part_level(PARTITION_LEVEL_ZERO); + table_schema.set_charset_type(ObCharset::get_default_charset()); + table_schema.set_collation_type(ObCharset::get_default_collation(ObCharset::get_default_charset())); + + if (OB_SUCC(ret)) { + if (OB_FAIL(table_schema.set_view_definition(R"__( SELECT TENANT_ID AS TENANT_ID, SVR_IP AS SVR_IP, SVR_PORT AS SVR_PORT, CACHE_OBJECT_ID AS CACHE_OBJECT_ID, PARAMETERIZE_TEXT AS PARAMETERIZE_TEXT, OBJECT_TEXT AS OBJECT_TEXT, FIRST_LOAD_TIME AS FIRST_LOAD_TIME, LAST_ACTIVE_TIME AS LAST_ACTIVE_TIME, AVG_EXE_USEC AS AVG_EXE_USEC, SLOWEST_EXE_TIME AS SLOWEST_EXE_TIME, SLOWEST_EXE_USEC AS SLOWEST_EXE_USEC, HIT_COUNT AS HIT_COUNT, CACHE_OBJ_SIZE AS CACHE_OBJ_SIZE, EXECUTIONS AS EXECUTIONS, ELAPSED_TIME AS ELAPSED_TIME, OBJECT_TYPE AS OBJECT_TYPE, OBJECT_ID AS OBJECT_ID, COMPILE_TIME AS COMPILE_TIME, SCHEMA_VERSION AS SCHEMA_VERSION, PS_STMT_ID AS PS_STMT_ID FROM SYS.GV$OB_PL_CACHE_OBJECT WHERE SVR_IP =HOST_IP() AND SVR_PORT = RPC_PORT() )__"))) { + LOG_ERROR("fail to set view_definition", K(ret)); + } + } + table_schema.set_index_using_type(USING_BTREE); + table_schema.set_row_store_type(ENCODING_ROW_STORE); + table_schema.set_store_format(OB_STORE_FORMAT_DYNAMIC_MYSQL); + table_schema.set_progressive_merge_round(1); + table_schema.set_storage_format_version(3); + table_schema.set_tablet_id(0); + + table_schema.set_max_used_column_id(column_id); + return ret; +} + } // end namespace share } // end namespace oceanbase diff --git a/src/share/inner_table/ob_inner_table_schema.h b/src/share/inner_table/ob_inner_table_schema.h index d069861195..0d47ceb6b9 100644 --- a/src/share/inner_table/ob_inner_table_schema.h +++ b/src/share/inner_table/ob_inner_table_schema.h @@ -1624,6 +1624,8 @@ public: static int dba_ob_tenant_event_history_schema(share::schema::ObTableSchema &table_schema); static int cdb_ob_tenant_event_history_schema(share::schema::ObTableSchema &table_schema); static int gv_ob_flt_trace_config_schema(share::schema::ObTableSchema &table_schema); + static int gv_ob_pl_cache_object_schema(share::schema::ObTableSchema &table_schema); + static int v_ob_pl_cache_object_schema(share::schema::ObTableSchema &table_schema); static int cdb_ob_recover_table_jobs_schema(share::schema::ObTableSchema &table_schema); static int dba_ob_recover_table_jobs_schema(share::schema::ObTableSchema &table_schema); static int cdb_ob_recover_table_job_history_schema(share::schema::ObTableSchema &table_schema); @@ -2113,6 +2115,8 @@ public: static int v_ob_timestamp_service_ora_schema(share::schema::ObTableSchema &table_schema); static int v_ob_ls_log_restore_status_ora_schema(share::schema::ObTableSchema &table_schema); static int gv_ob_flt_trace_config_ora_schema(share::schema::ObTableSchema &table_schema); + static int gv_ob_pl_cache_object_ora_schema(share::schema::ObTableSchema &table_schema); + static int v_ob_pl_cache_object_ora_schema(share::schema::ObTableSchema &table_schema); static int gv_ob_cgroup_config_ora_schema(share::schema::ObTableSchema &table_schema); static int v_ob_cgroup_config_ora_schema(share::schema::ObTableSchema &table_schema); static int dba_ob_aux_statistics_ora_schema(share::schema::ObTableSchema &table_schema); @@ -4327,6 +4331,8 @@ const schema_create_func sys_view_schema_creators [] = { ObInnerTableSchema::dba_ob_tenant_event_history_schema, ObInnerTableSchema::cdb_ob_tenant_event_history_schema, ObInnerTableSchema::gv_ob_flt_trace_config_schema, + ObInnerTableSchema::gv_ob_pl_cache_object_schema, + ObInnerTableSchema::v_ob_pl_cache_object_schema, ObInnerTableSchema::cdb_ob_recover_table_jobs_schema, ObInnerTableSchema::dba_ob_recover_table_jobs_schema, ObInnerTableSchema::cdb_ob_recover_table_job_history_schema, @@ -4816,6 +4822,8 @@ const schema_create_func sys_view_schema_creators [] = { ObInnerTableSchema::v_ob_timestamp_service_ora_schema, ObInnerTableSchema::v_ob_ls_log_restore_status_ora_schema, ObInnerTableSchema::gv_ob_flt_trace_config_ora_schema, + ObInnerTableSchema::gv_ob_pl_cache_object_ora_schema, + ObInnerTableSchema::v_ob_pl_cache_object_ora_schema, ObInnerTableSchema::gv_ob_cgroup_config_ora_schema, ObInnerTableSchema::v_ob_cgroup_config_ora_schema, ObInnerTableSchema::dba_ob_aux_statistics_ora_schema, @@ -5956,6 +5964,8 @@ const uint64_t tenant_space_tables [] = { OB_DBA_OB_LS_HISTORY_TID, OB_DBA_OB_TENANT_EVENT_HISTORY_TID, OB_GV_OB_FLT_TRACE_CONFIG_TID, + OB_GV_OB_PL_CACHE_OBJECT_TID, + OB_V_OB_PL_CACHE_OBJECT_TID, OB_DBA_OB_RECOVER_TABLE_JOBS_TID, OB_DBA_OB_RECOVER_TABLE_JOB_HISTORY_TID, OB_DBA_OB_IMPORT_TABLE_JOBS_TID, @@ -6422,6 +6432,8 @@ const uint64_t tenant_space_tables [] = { OB_V_OB_TIMESTAMP_SERVICE_ORA_TID, OB_V_OB_LS_LOG_RESTORE_STATUS_ORA_TID, OB_GV_OB_FLT_TRACE_CONFIG_ORA_TID, + OB_GV_OB_PL_CACHE_OBJECT_ORA_TID, + OB_V_OB_PL_CACHE_OBJECT_ORA_TID, OB_GV_OB_CGROUP_CONFIG_ORA_TID, OB_V_OB_CGROUP_CONFIG_ORA_TID, OB_DBA_OB_AUX_STATISTICS_ORA_TID, @@ -8434,6 +8446,8 @@ const char* const tenant_space_table_names [] = { OB_DBA_OB_LS_HISTORY_TNAME, OB_DBA_OB_TENANT_EVENT_HISTORY_TNAME, OB_GV_OB_FLT_TRACE_CONFIG_TNAME, + OB_GV_OB_PL_CACHE_OBJECT_TNAME, + OB_V_OB_PL_CACHE_OBJECT_TNAME, OB_DBA_OB_RECOVER_TABLE_JOBS_TNAME, OB_DBA_OB_RECOVER_TABLE_JOB_HISTORY_TNAME, OB_DBA_OB_IMPORT_TABLE_JOBS_TNAME, @@ -8900,6 +8914,8 @@ const char* const tenant_space_table_names [] = { OB_V_OB_TIMESTAMP_SERVICE_ORA_TNAME, OB_V_OB_LS_LOG_RESTORE_STATUS_ORA_TNAME, OB_GV_OB_FLT_TRACE_CONFIG_ORA_TNAME, + OB_GV_OB_PL_CACHE_OBJECT_ORA_TNAME, + OB_V_OB_PL_CACHE_OBJECT_ORA_TNAME, OB_GV_OB_CGROUP_CONFIG_ORA_TNAME, OB_V_OB_CGROUP_CONFIG_ORA_TNAME, OB_DBA_OB_AUX_STATISTICS_ORA_TNAME, @@ -12403,10 +12419,10 @@ static inline int get_sys_table_lob_aux_schema(const uint64_t tid, const int64_t OB_CORE_TABLE_COUNT = 4; const int64_t OB_SYS_TABLE_COUNT = 281; const int64_t OB_VIRTUAL_TABLE_COUNT = 786; -const int64_t OB_SYS_VIEW_COUNT = 850; -const int64_t OB_SYS_TENANT_TABLE_COUNT = 1922; +const int64_t OB_SYS_VIEW_COUNT = 854; +const int64_t OB_SYS_TENANT_TABLE_COUNT = 1926; const int64_t OB_CORE_SCHEMA_VERSION = 1; -const int64_t OB_BOOTSTRAP_SCHEMA_VERSION = 1925; +const int64_t OB_BOOTSTRAP_SCHEMA_VERSION = 1929; } // end namespace share } // end namespace oceanbase diff --git a/src/share/inner_table/ob_inner_table_schema_constants.h b/src/share/inner_table/ob_inner_table_schema_constants.h index d6fd7f66e5..2431a110f5 100644 --- a/src/share/inner_table/ob_inner_table_schema_constants.h +++ b/src/share/inner_table/ob_inner_table_schema_constants.h @@ -1360,6 +1360,8 @@ const uint64_t OB_CDB_OB_LS_HISTORY_TID = 21446; // "CDB_OB_LS_HISTORY" const uint64_t OB_DBA_OB_TENANT_EVENT_HISTORY_TID = 21447; // "DBA_OB_TENANT_EVENT_HISTORY" const uint64_t OB_CDB_OB_TENANT_EVENT_HISTORY_TID = 21448; // "CDB_OB_TENANT_EVENT_HISTORY" const uint64_t OB_GV_OB_FLT_TRACE_CONFIG_TID = 21449; // "GV$OB_FLT_TRACE_CONFIG" +const uint64_t OB_GV_OB_PL_CACHE_OBJECT_TID = 21461; // "GV$OB_PL_CACHE_OBJECT" +const uint64_t OB_V_OB_PL_CACHE_OBJECT_TID = 21462; // "V$OB_PL_CACHE_OBJECT" const uint64_t OB_CDB_OB_RECOVER_TABLE_JOBS_TID = 21463; // "CDB_OB_RECOVER_TABLE_JOBS" const uint64_t OB_DBA_OB_RECOVER_TABLE_JOBS_TID = 21464; // "DBA_OB_RECOVER_TABLE_JOBS" const uint64_t OB_CDB_OB_RECOVER_TABLE_JOB_HISTORY_TID = 21465; // "CDB_OB_RECOVER_TABLE_JOB_HISTORY" @@ -1849,6 +1851,8 @@ const uint64_t OB_V_OB_ARBITRATION_SERVICE_STATUS_ORA_TID = 28192; // "V$OB_ARBI const uint64_t OB_V_OB_TIMESTAMP_SERVICE_ORA_TID = 28193; // "V$OB_TIMESTAMP_SERVICE_ORA" const uint64_t OB_V_OB_LS_LOG_RESTORE_STATUS_ORA_TID = 28194; // "V$OB_LS_LOG_RESTORE_STATUS_ORA" const uint64_t OB_GV_OB_FLT_TRACE_CONFIG_ORA_TID = 28195; // "GV$OB_FLT_TRACE_CONFIG_ORA" +const uint64_t OB_GV_OB_PL_CACHE_OBJECT_ORA_TID = 28198; // "GV$OB_PL_CACHE_OBJECT_ORA" +const uint64_t OB_V_OB_PL_CACHE_OBJECT_ORA_TID = 28199; // "V$OB_PL_CACHE_OBJECT_ORA" const uint64_t OB_GV_OB_CGROUP_CONFIG_ORA_TID = 28200; // "GV$OB_CGROUP_CONFIG_ORA" const uint64_t OB_V_OB_CGROUP_CONFIG_ORA_TID = 28201; // "V$OB_CGROUP_CONFIG_ORA" const uint64_t OB_DBA_OB_AUX_STATISTICS_ORA_TID = 28210; // "DBA_OB_AUX_STATISTICS_ORA" @@ -3953,6 +3957,8 @@ const char *const OB_CDB_OB_LS_HISTORY_TNAME = "CDB_OB_LS_HISTORY"; const char *const OB_DBA_OB_TENANT_EVENT_HISTORY_TNAME = "DBA_OB_TENANT_EVENT_HISTORY"; const char *const OB_CDB_OB_TENANT_EVENT_HISTORY_TNAME = "CDB_OB_TENANT_EVENT_HISTORY"; const char *const OB_GV_OB_FLT_TRACE_CONFIG_TNAME = "GV$OB_FLT_TRACE_CONFIG"; +const char *const OB_GV_OB_PL_CACHE_OBJECT_TNAME = "GV$OB_PL_CACHE_OBJECT"; +const char *const OB_V_OB_PL_CACHE_OBJECT_TNAME = "V$OB_PL_CACHE_OBJECT"; const char *const OB_CDB_OB_RECOVER_TABLE_JOBS_TNAME = "CDB_OB_RECOVER_TABLE_JOBS"; const char *const OB_DBA_OB_RECOVER_TABLE_JOBS_TNAME = "DBA_OB_RECOVER_TABLE_JOBS"; const char *const OB_CDB_OB_RECOVER_TABLE_JOB_HISTORY_TNAME = "CDB_OB_RECOVER_TABLE_JOB_HISTORY"; @@ -4442,6 +4448,8 @@ const char *const OB_V_OB_ARBITRATION_SERVICE_STATUS_ORA_TNAME = "V$OB_ARBITRATI const char *const OB_V_OB_TIMESTAMP_SERVICE_ORA_TNAME = "V$OB_TIMESTAMP_SERVICE"; const char *const OB_V_OB_LS_LOG_RESTORE_STATUS_ORA_TNAME = "V$OB_LS_LOG_RESTORE_STATUS"; const char *const OB_GV_OB_FLT_TRACE_CONFIG_ORA_TNAME = "GV$OB_FLT_TRACE_CONFIG"; +const char *const OB_GV_OB_PL_CACHE_OBJECT_ORA_TNAME = "GV$OB_PL_CACHE_OBJECT"; +const char *const OB_V_OB_PL_CACHE_OBJECT_ORA_TNAME = "V$OB_PL_CACHE_OBJECT"; const char *const OB_GV_OB_CGROUP_CONFIG_ORA_TNAME = "GV$OB_CGROUP_CONFIG"; const char *const OB_V_OB_CGROUP_CONFIG_ORA_TNAME = "V$OB_CGROUP_CONFIG"; const char *const OB_DBA_OB_AUX_STATISTICS_ORA_TNAME = "DBA_OB_AUX_STATISTICS"; diff --git a/src/share/inner_table/ob_inner_table_schema_def.py b/src/share/inner_table/ob_inner_table_schema_def.py index 4780ecf51f..a6a3243ab8 100644 --- a/src/share/inner_table/ob_inner_table_schema_def.py +++ b/src/share/inner_table/ob_inner_table_schema_def.py @@ -13957,6 +13957,7 @@ def_table_schema( # * # 100001: __all_table ################################################################################ + ################################################################################ # Oracle Virtual Table(15000,20000] ################################################################################ @@ -31221,8 +31222,78 @@ def_table_schema( ) # 21459:GV$OB_SESSION # 21460:V$OB_SESSION -# 21461: GV$OB_PL_CACHE_OBJECT -# 21462: V$OB_PL_CACHE_OBJECT + +def_table_schema( + owner = 'hr351303', + table_name = 'GV$OB_PL_CACHE_OBJECT', + table_id = '21461', + table_type = 'SYSTEM_VIEW', + gm_columns = [], + in_tenant_space = True, + rowkey_columns = [], + view_definition = """ + SELECT TENANT_ID, + SVR_IP, + SVR_PORT, + PLAN_ID AS CACHE_OBJECT_ID, + STATEMENT AS PARAMETERIZE_TEXT, + QUERY_SQL AS OBJECT_TEXT, + FIRST_LOAD_TIME, + LAST_ACTIVE_TIME, + AVG_EXE_USEC, + SLOWEST_EXE_TIME, + SLOWEST_EXE_USEC, + HIT_COUNT, + PLAN_SIZE AS CACHE_OBJ_SIZE, + EXECUTIONS, + ELAPSED_TIME, + OBJECT_TYPE, + PL_SCHEMA_ID AS OBJECT_ID, + COMPILE_TIME, + SCHEMA_VERSION, + PS_STMT_ID + FROM oceanbase.__all_virtual_plan_stat WHERE OBJECT_STATUS = 0 AND TYPE > 5 AND TYPE < 11 AND is_in_pc=true +""".replace("\n", " "), + normal_columns = [ + ], +) + +def_table_schema( + owner = 'hr351303', + table_name = 'V$OB_PL_CACHE_OBJECT', + table_id = '21462', + table_type = 'SYSTEM_VIEW', + gm_columns = [], + in_tenant_space = True, + rowkey_columns = [], + view_definition = """ + SELECT TENANT_ID, + SVR_IP, + SVR_PORT, + CACHE_OBJECT_ID, + PARAMETERIZE_TEXT, + OBJECT_TEXT, + FIRST_LOAD_TIME, + LAST_ACTIVE_TIME, + AVG_EXE_USEC, + SLOWEST_EXE_TIME, + SLOWEST_EXE_USEC, + HIT_COUNT, + CACHE_OBJ_SIZE, + EXECUTIONS, + ELAPSED_TIME, + OBJECT_TYPE, + OBJECT_ID, + COMPILE_TIME, + SCHEMA_VERSION, + PS_STMT_ID + FROM oceanbase.GV$OB_PL_CACHE_OBJECT WHERE SVR_IP =HOST_IP() AND SVR_PORT = RPC_PORT() +""".replace("\n", " "), + + + normal_columns = [ + ], +) def_table_schema( owner = 'chongrong.th', @@ -60106,8 +60177,80 @@ def_table_schema( ) # 28196: GV$OB_SESSION # 28197: V$OB_SESSION -# 28198: GV$OB_PL_CACHE_OBJECT -# 28199: V$OB_PL_CACHE_OBJECT + +def_table_schema( + owner = 'hr351303', + table_name = 'GV$OB_PL_CACHE_OBJECT', + name_postfix = '_ORA', + database_id = 'OB_ORA_SYS_DATABASE_ID', + table_id = '28198', + table_type = 'SYSTEM_VIEW', + gm_columns = [], + in_tenant_space = True, + rowkey_columns = [], + view_definition = """ + SELECT TENANT_ID AS TENANT_ID, + SVR_IP AS SVR_IP, + SVR_PORT AS SVR_PORT, + PLAN_ID AS CACHE_OBJECT_ID, + STATEMENT AS PARAMETERIZE_TEXT, + QUERY_SQL AS OBJECT_TEXT, + FIRST_LOAD_TIME AS FIRST_LOAD_TIME, + LAST_ACTIVE_TIME AS LAST_ACTIVE_TIME, + AVG_EXE_USEC AS AVG_EXE_USEC, + SLOWEST_EXE_TIME AS SLOWEST_EXE_TIME, + SLOWEST_EXE_USEC AS SLOWEST_EXE_USEC, + HIT_COUNT AS HIT_COUNT, + PLAN_SIZE AS CACHE_OBJ_SIZE, + EXECUTIONS AS EXECUTIONS, + ELAPSED_TIME AS ELAPSED_TIME, + OBJECT_TYPE AS OBJECT_TYPE, + PL_SCHEMA_ID AS OBJECT_ID, + COMPILE_TIME AS COMPILE_TIME, + SCHEMA_VERSION AS SCHEMA_VERSION, + PS_STMT_ID AS PS_STMT_ID + FROM SYS.ALL_VIRTUAL_PLAN_STAT WHERE OBJECT_STATUS = 0 AND TYPE > 5 AND TYPE < 11 AND is_in_pc='1' +""".replace("\n", " "), + normal_columns = [ + ], +) +def_table_schema( + owner = 'hr351303', + table_name = 'V$OB_PL_CACHE_OBJECT', + name_postfix = '_ORA', + database_id = 'OB_ORA_SYS_DATABASE_ID', + table_id = '28199', + table_type = 'SYSTEM_VIEW', + gm_columns = [], + in_tenant_space = True, + rowkey_columns = [], + view_definition = """ + SELECT TENANT_ID AS TENANT_ID, + SVR_IP AS SVR_IP, + SVR_PORT AS SVR_PORT, + CACHE_OBJECT_ID AS CACHE_OBJECT_ID, + PARAMETERIZE_TEXT AS PARAMETERIZE_TEXT, + OBJECT_TEXT AS OBJECT_TEXT, + FIRST_LOAD_TIME AS FIRST_LOAD_TIME, + LAST_ACTIVE_TIME AS LAST_ACTIVE_TIME, + AVG_EXE_USEC AS AVG_EXE_USEC, + SLOWEST_EXE_TIME AS SLOWEST_EXE_TIME, + SLOWEST_EXE_USEC AS SLOWEST_EXE_USEC, + HIT_COUNT AS HIT_COUNT, + CACHE_OBJ_SIZE AS CACHE_OBJ_SIZE, + EXECUTIONS AS EXECUTIONS, + ELAPSED_TIME AS ELAPSED_TIME, + OBJECT_TYPE AS OBJECT_TYPE, + OBJECT_ID AS OBJECT_ID, + COMPILE_TIME AS COMPILE_TIME, + SCHEMA_VERSION AS SCHEMA_VERSION, + PS_STMT_ID AS PS_STMT_ID + FROM SYS.GV$OB_PL_CACHE_OBJECT WHERE SVR_IP =HOST_IP() AND SVR_PORT = RPC_PORT() +""".replace("\n", " "), + normal_columns = [ + ], +) + def_table_schema( owner = 'huangrenhaung.hrh', table_name = 'GV$OB_CGROUP_CONFIG', diff --git a/src/share/inner_table/table_id_to_name b/src/share/inner_table/table_id_to_name index fe75b5db35..e6b0bd89a4 100644 --- a/src/share/inner_table/table_id_to_name +++ b/src/share/inner_table/table_id_to_name @@ -2008,6 +2008,8 @@ # 21447: DBA_OB_TENANT_EVENT_HISTORY # 21448: CDB_OB_TENANT_EVENT_HISTORY # 21449: GV$OB_FLT_TRACE_CONFIG +# 21461: GV$OB_PL_CACHE_OBJECT +# 21462: V$OB_PL_CACHE_OBJECT # 21463: CDB_OB_RECOVER_TABLE_JOBS # 21464: DBA_OB_RECOVER_TABLE_JOBS # 21465: CDB_OB_RECOVER_TABLE_JOB_HISTORY @@ -2497,6 +2499,8 @@ # 28193: V$OB_TIMESTAMP_SERVICE # 28194: V$OB_LS_LOG_RESTORE_STATUS # 28195: GV$OB_FLT_TRACE_CONFIG +# 28198: GV$OB_PL_CACHE_OBJECT +# 28199: V$OB_PL_CACHE_OBJECT # 28200: GV$OB_CGROUP_CONFIG # 28201: V$OB_CGROUP_CONFIG # 28210: DBA_OB_AUX_STATISTICS diff --git a/src/sql/engine/prepare/ob_execute_executor.cpp b/src/sql/engine/prepare/ob_execute_executor.cpp index b97c86f71c..0a62978f2a 100644 --- a/src/sql/engine/prepare/ob_execute_executor.cpp +++ b/src/sql/engine/prepare/ob_execute_executor.cpp @@ -18,6 +18,9 @@ #include "observer/ob_server_struct.h" #include "observer/virtual_table/ob_virtual_table_iterator_factory.h" #include "sql/resolver/ob_schema_checker.h" +#include "observer/mysql/ob_sync_cmd_driver.h" +#include "sql/engine/cmd/ob_variable_set_executor.h" +#include "sql/resolver/cmd/ob_call_procedure_stmt.h" namespace oceanbase { @@ -31,6 +34,9 @@ int ObExecuteExecutor::execute(ObExecContext &ctx, ObExecuteStmt &stmt) if (OB_ISNULL(ctx.get_sql_ctx()) || OB_ISNULL(ctx.get_my_session())) { ret = OB_ERR_UNEXPECTED; LOG_WARN("sql ctx or session is NULL", K(ctx.get_sql_ctx()), K(ctx.get_my_session()), K(ret)); + } else if (stmt::T_CALL_PROCEDURE != stmt.get_prepare_type()) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("it must be call procedure stmt", K(ret), K(stmt)); } else { ObObjParam result; ParamStore params_array( (ObWrapperAllocator(ctx.get_allocator())) ); @@ -98,20 +104,58 @@ int ObExecuteExecutor::execute(ObExecContext &ctx, ObExecuteStmt &stmt) LOG_WARN("result set open failed", K(result_set.get_statement_id()), K(ret)); } if (OB_SUCC(ret)) { - if (result_set.is_with_rows()) { - while (OB_SUCC(ret)) { - const common::ObNewRow *row = NULL; - if (OB_FAIL(result_set.get_next_row(row))) { - if (OB_ITER_END == ret) { - ret = OB_SUCCESS; - } else { - LOG_WARN("get next row error", K(ret)); + ObCallProcedureInfo *call_proc_info = NULL; + ObCallProcedureStmt *call_stmt = static_cast(result_set.get_cmd()); + if (OB_ISNULL(call_proc_info = call_stmt->get_call_proc_info())) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("call procedure info is null", K(ret)); + } else { + for (int64_t i = 0; OB_SUCC(ret) && i < call_proc_info->get_expressions().count(); ++i) { + if (call_proc_info->is_out_param(i)) { + const ObSqlExpression *call_param_expr = call_proc_info->get_expressions().at(i); + ObItemType expr_type = call_param_expr->get_expr_items().at(0).get_item_type(); + if (OB_LIKELY(IS_CONST_TYPE(expr_type))) { + if (T_QUESTIONMARK == expr_type) { + const ObObj &value = call_param_expr->get_expr_items().at(0).get_obj(); + int64_t idx = value.get_unknown(); + CK (idx < params_array.count()); + if (OB_SUCC(ret)) { + const ObRawExpr *expr = stmt.get_params().at(idx); + if (OB_ISNULL(expr)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("expr is null", K(ret), K(stmt)); + } else if (T_OP_GET_USER_VAR != expr->get_expr_type()) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("it must be user var", K(ret), K(stmt)); + } else { + ObExprCtx expr_ctx; + if (OB_ISNULL(expr->get_param_expr(0))) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("sys var is NULL", K(*expr), K(ret)); + } else if (OB_UNLIKELY(!expr->get_param_expr(0)->is_const_raw_expr() + || !static_cast(expr->get_param_expr(0))->get_value().is_varchar())) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("invalid user var", K(*expr->get_param_expr(0)), K(ret)); + } else if (OB_FAIL(ObSQLUtils::wrap_expr_ctx(stmt::T_CALL_PROCEDURE, ctx, ctx.get_allocator(), expr_ctx))) { + LOG_WARN("Failed to wrap expr ctx", K(ret)); + } else { + const ObString var_name = static_cast(expr->get_param_expr(0))->get_value().get_varchar(); + if (OB_FAIL(ObVariableSetExecutor::set_user_variable(result_set.get_exec_context().get_physical_plan_ctx()->get_param_store_for_update().at(idx), + var_name, expr_ctx))) { + LOG_WARN("set user variable failed", K(ret)); + } + } + } + } + } else { + /* do nothing */ + } } - break; } - } + } // for end } } + int tmp_ret = OB_SUCCESS; if ((tmp_ret = result_set.close()) != OB_SUCCESS) { LOG_WARN("result set open failed", K(result_set.get_statement_id()), K(ret)); diff --git a/src/sql/executor/ob_cmd_executor.cpp b/src/sql/executor/ob_cmd_executor.cpp index b82af4377e..24a4951196 100644 --- a/src/sql/executor/ob_cmd_executor.cpp +++ b/src/sql/executor/ob_cmd_executor.cpp @@ -511,10 +511,15 @@ int ObCmdExecutor::execute(ObExecContext &ctx, ObICmd &cmd) break; } case stmt::T_EXECUTE: { - // ps文本模式应该要返回结果,不能定义为cmd - ret = OB_ERR_UNEXPECTED; - LOG_WARN("ps text shoudle be handled as normal query, not cmd", K(ret)); - // DEFINE_EXECUTE_CMD(ObExecuteStmt, ObExecuteExecutor); + // only call procedure run this logic, text ps mode execute call procedure, + // if procedure has out param, it should return result to argument + ObExecuteStmt &stmt = *(static_cast(&cmd)); + if (stmt::T_CALL_PROCEDURE != stmt.get_prepare_type()) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("ps text shoudle be handled as normal query, not cmd", K(ret)); + } else { + DEFINE_EXECUTE_CMD(ObExecuteStmt, ObExecuteExecutor); + } break; } case stmt::T_DEALLOCATE: { diff --git a/src/sql/monitor/ob_exec_stat.h b/src/sql/monitor/ob_exec_stat.h index ed0bfa0af2..d2f37e5e70 100644 --- a/src/sql/monitor/ob_exec_stat.h +++ b/src/sql/monitor/ob_exec_stat.h @@ -290,6 +290,7 @@ struct ObAuditRecordData { params_value_len_ = 0; partition_hit_ = true; is_perf_event_closed_ = false; + pl_trace_id_.reset(); } int64_t get_elapsed_time() const @@ -414,6 +415,8 @@ struct ObAuditRecordData { char snapshot_source_[OB_MAX_SNAPSHOT_SOURCE_LENGTH + 1]; uint64_t total_memstore_read_row_count_; uint64_t total_ssstore_read_row_count_; + ObCurTraceId::TraceId pl_trace_id_; + int64_t plsql_exec_time_; }; } //namespace sql diff --git a/src/sql/ob_spi.cpp b/src/sql/ob_spi.cpp index bde1c96cc1..5df5a9c1dc 100644 --- a/src/sql/ob_spi.cpp +++ b/src/sql/ob_spi.cpp @@ -1548,6 +1548,49 @@ public: }; +struct ObPLSPITraceIdGuard { + ObPLSPITraceIdGuard(const ObString &sql, const ObString &ps_sql, ObCurTraceId::TraceId *reused_trace_id = nullptr) + : sql_(sql), ps_sql_(ps_sql) { + int ret = OB_SUCCESS; + if (OB_NOT_NULL(ObCurTraceId::get_trace_id())) { + origin_trace_id_.set(*ObCurTraceId::get_trace_id()); + + if (reused_trace_id != nullptr && reused_trace_id->is_valid()) { + // do not log when fetching from cursor + ObCurTraceId::get_trace_id()->set(*reused_trace_id); + } else { + ObCurTraceId::TraceId new_trace_id; + new_trace_id.init(origin_trace_id_.get_addr()); + + // log with PL trace_id + LOG_TRACE("executing sql, trace id changed", + K(sql_), K(ps_sql_), + "from", origin_trace_id_, + "to", new_trace_id); + + ObCurTraceId::get_trace_id()->set(new_trace_id); + } + } + } + + ~ObPLSPITraceIdGuard() { + int ret = OB_SUCCESS; + ObCurTraceId::TraceId curr_trace_id; + if (OB_NOT_NULL(ObCurTraceId::get_trace_id())) { + curr_trace_id.set(*ObCurTraceId::get_trace_id()); + ObCurTraceId::get_trace_id()->set(origin_trace_id_); + + LOG_TRACE("sql execution finished, trace id restored", + K(sql_), K(ps_sql_), + "from", curr_trace_id, + "to", origin_trace_id_); + } + } + ObCurTraceId::TraceId origin_trace_id_; + const ObString &sql_; + const ObString &ps_sql_; +}; + //todo:@hr351303 确认sql 和 ps sql是否可以合一 int ObSPIService::spi_inner_execute(ObPLExecCtx *ctx, const char *sql, @@ -1570,6 +1613,7 @@ int ObSPIService::spi_inner_execute(ObPLExecCtx *ctx, ObWarningBuffer* wb = NULL; FLTSpanGuard(pl_spi_query); CK (OB_NOT_NULL(ctx)); + ObPLSPITraceIdGuard trace_id_guard(sql, ps_sql); CK (OB_NOT_NULL(ctx->allocator_)); CK (OB_NOT_NULL(ctx->exec_ctx_)); CK (OB_NOT_NULL(ctx->exec_ctx_->get_my_session())); @@ -1583,6 +1627,7 @@ int ObSPIService::spi_inner_execute(ObPLExecCtx *ctx, exec_timestamp.exec_type_ = sql::PLSql; ObSQLSessionInfo *session = ctx->exec_ctx_->get_my_session(); + ObPLSubPLSqlTimeGuard guard(ctx); if (OB_SUCC(ret) && is_forall && !session->is_enable_batched_multi_statement()) { /* forall need rollback to for loop */ ret = OB_BATCHED_MULTI_STMT_ROLLBACK; @@ -1722,6 +1767,7 @@ int ObSPIService::spi_inner_execute(ObPLExecCtx *ctx, int64_t try_cnt = session_info->get_raw_audit_record().try_cnt_; ObExecRecord record_bk = session_info->get_raw_audit_record().exec_record_; session_info->get_raw_audit_record().try_cnt_ = retry_ctrl.get_retry_times(); + session_info->get_raw_audit_record().pl_trace_id_.set(trace_id_guard.origin_trace_id_); ObInnerSQLConnection::process_record(*spi_result.get_result_set(), spi_result.get_sql_ctx(), *session_info, @@ -1739,6 +1785,7 @@ int ObSPIService::spi_inner_execute(ObPLExecCtx *ctx, spi_result.get_exec_params_str_ptr()); session_info->get_raw_audit_record().exec_record_ = record_bk; session_info->get_raw_audit_record().try_cnt_ = try_cnt; + session_info->get_raw_audit_record().pl_trace_id_.reset(); } else { LOG_DEBUG("result set is not inited, do not process record", K(ret), K(ps_sql), K(sql), K(type)); @@ -2658,6 +2705,7 @@ int ObSPIService::spi_execute_immediate(ObPLExecCtx *ctx, ObMySQLProxy *sql_proxy = NULL; ObSqlString sql_str; ObArenaAllocator allocator(GET_PL_MOD_STRING(PL_MOD_IDX::OB_PL_DYNAMIC_SQL_EXEC), OB_MALLOC_NORMAL_BLOCK_SIZE, MTL_ID()); + ObPLSubPLSqlTimeGuard guard(ctx); HEAP_VAR(ObSPIResultSet, spi_result) { stmt::StmtType stmt_type = stmt::T_NONE; ObString ps_sql; @@ -2784,6 +2832,7 @@ int ObSPIService::spi_execute_immediate(ObPLExecCtx *ctx, OZ (spi_result.start_nested_stmt_if_need(ctx, sql_str.string(), stmt_type, for_update)); // Step2: execute dynamic SQL now! + ObPLSPITraceIdGuard trace_id_guard(sql_str.string(), ps_sql); if (OB_FAIL(ret)) { } else if (need_execute_sql) { ObExecRecord exec_record; @@ -2932,6 +2981,7 @@ int ObSPIService::spi_execute_immediate(ObPLExecCtx *ctx, int64_t try_cnt = session->get_raw_audit_record().try_cnt_; ObExecRecord record_bk = session->get_raw_audit_record().exec_record_; session->get_raw_audit_record().try_cnt_ = retry_ctrl.get_retry_times(); + session->get_raw_audit_record().pl_trace_id_ = trace_id_guard.origin_trace_id_; ObInnerSQLConnection::process_record(*spi_result.get_result_set(), spi_result.get_sql_ctx(), *session, @@ -2949,6 +2999,7 @@ int ObSPIService::spi_execute_immediate(ObPLExecCtx *ctx, spi_result.get_exec_params_str_ptr()); session->get_raw_audit_record().exec_record_ = record_bk; session->get_raw_audit_record().try_cnt_ = try_cnt; + session->get_raw_audit_record().pl_trace_id_.reset(); } else { LOG_DEBUG("result set is not inited, do not process record", K(ret), K(ps_sql), K(sql_str), K(stmt_type)); @@ -3531,6 +3582,7 @@ int ObSPIService::spi_cursor_open(ObPLExecCtx *ctx, } else { ParamStore current_params(ObWrapperAllocator(ctx->allocator_)); ObIAllocator *allocator = cursor->get_allocator(); + ObPLSubPLSqlTimeGuard guard(ctx); if (OB_ISNULL(allocator)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("Argument in pl context is NULL", K(allocator), K(ret)); @@ -3673,6 +3725,7 @@ int ObSPIService::spi_cursor_open(ObPLExecCtx *ctx, } cursor->set_last_execute_time(ObTimeUtility::current_time()); } else { //MySQL Cursor/Updated Cursor/Server Cursor(REF_CURSOR, PACKAGE CURSOR) + ObPLSPITraceIdGuard trace_id_guard(sql, ps_sql); HEAP_VAR(ObSPIResultSet, spi_result) { ObString sqlstr(sql); OZ (spi_result.init(*session_info)); @@ -3682,86 +3735,134 @@ int ObSPIService::spi_cursor_open(ObPLExecCtx *ctx, int64_t new_query_start_time = ObTimeUtility::current_time(); session_info->set_query_start_time(new_query_start_time); if (OB_SUCC(ret)) { + ObExecRecord exec_record; + ObExecTimestamp exec_timestamp; + ObSPITimeRecord time_record; + exec_timestamp.exec_type_ = sql::PLSql; ObQueryRetryCtrl retry_ctrl; int64_t tenant_version = 0; int64_t sys_version = 0; bool is_retry = false; do { - ret = OB_SUCCESS; - if (is_retry) { - spi_result.get_out_params().reset(); - spi_result.reset_member_for_retry(*session_info); - } - retry_ctrl.clear_state_before_each_retry(session_info->get_retry_info_for_update()); - OZ ((GCTX.schema_service_->get_tenant_schema_guard(session_info->get_effective_tenant_id(), spi_result.get_scheme_guard()))); - OX (spi_result.get_sql_ctx().schema_guard_ = &spi_result.get_scheme_guard()); - OZ (spi_result.get_scheme_guard().get_schema_version(session_info->get_effective_tenant_id(), tenant_version)); - OZ (spi_result.get_scheme_guard().get_schema_version(OB_SYS_TENANT_ID, sys_version)); - OX (retry_ctrl.set_tenant_local_schema_version(tenant_version)); - OX (retry_ctrl.set_sys_local_schema_version(sys_version)); + // SQL_AUDIT_START + ObWaitEventDesc max_wait_desc; + ObWaitEventStat total_wait_desc; + const bool enable_perf_event = lib::is_diagnose_info_enabled(); + const bool enable_sql_audit = + GCONF.enable_sql_audit && ctx->exec_ctx_->get_my_session()->get_local_ob_enable_sql_audit(); + { + ObMaxWaitGuard max_wait_guard(enable_perf_event ? &max_wait_desc : NULL); + ObTotalWaitGuard total_wait_guard(enable_perf_event ? &total_wait_desc : NULL); + if (enable_perf_event) { + exec_record.record_start(); + } + //监控项统计开始 + time_record.set_send_timestamp(ObTimeUtility::current_time()); + ret = OB_SUCCESS; + if (is_retry) { + spi_result.get_out_params().reset(); + spi_result.reset_member_for_retry(*session_info); + } + OX (retry_ctrl.clear_state_before_each_retry(session_info->get_retry_info_for_update())); + OZ ((GCTX.schema_service_->get_tenant_schema_guard(session_info->get_effective_tenant_id(), spi_result.get_scheme_guard()))); + OX (spi_result.get_sql_ctx().schema_guard_ = &spi_result.get_scheme_guard()); + OZ (spi_result.get_scheme_guard().get_schema_version(session_info->get_effective_tenant_id(), tenant_version)); + OZ (spi_result.get_scheme_guard().get_schema_version(OB_SYS_TENANT_ID, sys_version)); + OX (retry_ctrl.set_tenant_local_schema_version(tenant_version)); + OX (retry_ctrl.set_sys_local_schema_version(sys_version)); - OZ (inner_open(ctx, - spi_result.get_allocaor(), - sql, - ps_sql, - type, - sql_param_exprs, - sql_param_count, - NULL, - 0, - spi_result, - spi_result.get_out_params(), - &retry_ctrl)); + OZ (inner_open(ctx, + spi_result.get_allocaor(), + sql, + ps_sql, + type, + sql_param_exprs, + sql_param_count, + NULL, + 0, + spi_result, + spi_result.get_out_params(), + &retry_ctrl)); + if (OB_SUCC(ret)) { + ObSPICursor* spi_cursor = cursor->get_spi_cursor(); + uint64_t size = 0; + OZ (session_info->get_tmp_table_size(size)); + OZ (cursor->prepare_spi_cursor(spi_cursor, + session_info->get_effective_tenant_id(), + size, + for_update && !is_server_cursor), K(size)); + //if (is_server_cursor) { + // not only server cursor need field set + // normal cursor maybe convert to session cursor by to_cursor_number + // so all kind of cursor need do the copy + CK (OB_NOT_NULL(cursor->get_allocator())); + CK (OB_NOT_NULL(spi_result.get_result_set())); + OZ (ObDbmsInfo::deep_copy_field_columns( + *cursor->get_allocator(), + spi_result.get_result_set()->get_field_columns(), + spi_cursor->fields_)); + //} + OZ (fill_cursor(*spi_result.get_result_set(), spi_cursor, new_query_start_time)); + if (OB_FAIL(ret) && OB_NOT_NULL(spi_result.get_result_set())) { + int cli_ret = OB_SUCCESS; + retry_ctrl.test_and_save_retry_state(GCTX, + spi_result.get_sql_ctx(), + *spi_result.get_result_set(), + ret, + cli_ret, + true, + true, + true); + LOG_WARN("failed to do fill_cursor, check if need retry", K(ret), K(cli_ret), K(retry_ctrl.need_retry()), K(sql), K(ps_sql)); + ret = cli_ret; + spi_result.get_sql_ctx().clear(); + ctx->exec_ctx_->get_my_session()->set_session_in_retry(retry_ctrl.need_retry()); + } + OX (spi_cursor->row_store_.finish_add_row()) + OX (cursor->open(spi_cursor)); + if (OB_FAIL(ret)) { + spi_cursor->~ObSPICursor(); + } + } + OX (for_update ? cursor->set_for_update() : (void)NULL); + OX (for_update ? cursor->set_trans_id(session_info->get_tx_id()) : (void)NULL); + OX (has_hidden_rowid ? cursor->set_hidden_rowid() : (void)NULL); + + CK (OB_NOT_NULL(spi_result.get_result_set())); + if (OB_SUCC(ret) && lib::is_oracle_mode()) { + transaction::ObTxReadSnapshot &snapshot = + spi_result.get_result_set()->get_exec_context().get_das_ctx().get_snapshot(); + OZ (cursor->set_and_register_snapshot(snapshot)); + } + } + //监控项统计结束 + time_record.set_exec_end_timestamp(ObTimeUtility::current_time()); if (OB_SUCC(ret)) { - ObSPICursor* spi_cursor = cursor->get_spi_cursor(); - uint64_t size = 0; - OZ (session_info->get_tmp_table_size(size)); - OZ (cursor->prepare_spi_cursor(spi_cursor, - session_info->get_effective_tenant_id(), - size, - for_update && !is_server_cursor), K(size)); - //if (is_server_cursor) { - // not only server cursor need field set - // normal cursor maybe convert to session cursor by to_cursor_number - // so all kind of cursor need do the copy - CK (OB_NOT_NULL(cursor->get_allocator())); - CK (OB_NOT_NULL(spi_result.get_result_set())); - OZ (ObDbmsInfo::deep_copy_field_columns( - *cursor->get_allocator(), - spi_result.get_result_set()->get_field_columns(), - spi_cursor->fields_)); - //} - OZ (fill_cursor(*spi_result.get_result_set(), spi_cursor, new_query_start_time)); - if (OB_FAIL(ret) && OB_NOT_NULL(spi_result.get_result_set())) { - int cli_ret = OB_SUCCESS; - retry_ctrl.test_and_save_retry_state(GCTX, - spi_result.get_sql_ctx(), - *spi_result.get_result_set(), - ret, - cli_ret, - true, - true, - true); - LOG_WARN("failed to do fill_cursor, check if need retry", K(ret), K(cli_ret), K(retry_ctrl.need_retry()), K(sql), K(ps_sql)); - ret = cli_ret; - spi_result.get_sql_ctx().clear(); - ctx->exec_ctx_->get_my_session()->set_session_in_retry(retry_ctrl.need_retry()); + LOG_DEBUG("start process record", K(ret), K(ps_sql), K(sql), K(type), K(enable_sql_audit)); + if (spi_result.get_result_set()->is_inited()) { + ObSQLSessionInfo *session_info = ctx->exec_ctx_->get_my_session(); + int64_t try_cnt = session_info->get_raw_audit_record().try_cnt_; + ObExecRecord record_bk = session_info->get_raw_audit_record().exec_record_; + session_info->get_raw_audit_record().try_cnt_ = retry_ctrl.get_retry_times(); + session_info->get_raw_audit_record().pl_trace_id_.set(trace_id_guard.origin_trace_id_); + ObInnerSQLConnection::process_record(*spi_result.get_result_set(), + spi_result.get_sql_ctx(), + *session_info, + time_record, + ret, + session_info->get_current_execution_id(), // sql execute id + OB_INVALID_ID, + max_wait_desc, + total_wait_desc, + exec_record, + exec_timestamp, + true, + sql != NULL ? sql : ps_sql, + true); + session_info->get_raw_audit_record().exec_record_ = record_bk; + session_info->get_raw_audit_record().try_cnt_ = try_cnt; + session_info->get_raw_audit_record().pl_trace_id_.reset(); } - OX (spi_cursor->row_store_.finish_add_row()) - OX (cursor->open(spi_cursor)); - if (OB_FAIL(ret) && OB_NOT_NULL(spi_cursor)) { - spi_cursor->~ObSPICursor(); - } - } - OX (for_update ? cursor->set_for_update() : (void)NULL); - OX (for_update ? cursor->set_trans_id(session_info->get_tx_id()) : (void)NULL); - OX (has_hidden_rowid ? cursor->set_hidden_rowid() : (void)NULL); - - CK (OB_NOT_NULL(spi_result.get_result_set())); - if (OB_SUCC(ret) && lib::is_oracle_mode()) { - transaction::ObTxReadSnapshot &snapshot = - spi_result.get_result_set()->get_exec_context().get_das_ctx().get_snapshot(); - OZ (cursor->set_and_register_snapshot(snapshot)); } int close_ret = spi_result.close_result_set(); @@ -3818,6 +3919,7 @@ int ObSPIService::dbms_cursor_open(ObPLExecCtx *ctx, const bool enable_perf_event = lib::is_diagnose_info_enabled(); const bool enable_sql_audit = GCONF.enable_sql_audit && ctx->exec_ctx_->get_my_session()->get_local_ob_enable_sql_audit(); + ObPLSubPLSqlTimeGuard guard(ctx); OV (OB_NOT_NULL(ctx) && OB_NOT_NULL(ctx->exec_ctx_) && OB_NOT_NULL(ctx->allocator_) && @@ -3989,6 +4091,7 @@ int ObSPIService::dbms_cursor_open(ObPLExecCtx *ctx, int64_t tenant_version = 0; int64_t sys_version = 0; int64_t retry_cnt = 0; + ObPLSPITraceIdGuard trace_id_guard(sql_stmt,ps_sql); int64_t old_query_start_time = session->get_query_start_time(); int64_t new_query_start_time = ObTimeUtility::current_time(); if (!cursor.is_ps_cursor()) { @@ -4063,6 +4166,7 @@ int ObSPIService::dbms_cursor_open(ObPLExecCtx *ctx, int64_t try_cnt = session_info->get_raw_audit_record().try_cnt_; ObExecRecord record_bk = session_info->get_raw_audit_record().exec_record_; session_info->get_raw_audit_record().try_cnt_ = retry_ctrl.get_retry_times(); + session_info->get_raw_audit_record().pl_trace_id_.set(trace_id_guard.origin_trace_id_); // 会在inner_open的时候被改成了 inner ,所以这个地方需要重新设置一下 exec_timestamp.exec_type_ = cursor.is_ps_cursor() ? sql::PSCursor : sql::DbmsCursor; ObInnerSQLConnection::process_record(*result_set, @@ -4082,6 +4186,7 @@ int ObSPIService::dbms_cursor_open(ObPLExecCtx *ctx, &exec_param_str); session_info->get_raw_audit_record().exec_record_ = record_bk; session_info->get_raw_audit_record().try_cnt_ = retry_cnt; + session_info->get_raw_audit_record().pl_trace_id_.reset(); } int close_ret = spi_result.close_result_set(); if (OB_SUCCESS != close_ret) { @@ -4148,6 +4253,7 @@ int ObSPIService::do_cursor_fetch(ObPLExecCtx *ctx, CK (OB_NOT_NULL(ctx->exec_ctx_)); CK (OB_NOT_NULL(session = ctx->exec_ctx_->get_my_session())); CK (OB_NOT_NULL(cursor)); + ObPLSubPLSqlTimeGuard guard(ctx); if (OB_FAIL(ret)) { } else if (cursor->is_need_check_snapshot()) { /* case: select * from dual, snapshot do not initilize, so it's invalid */ @@ -4232,6 +4338,7 @@ int ObSPIService::do_cursor_fetch(ObPLExecCtx *ctx, } } if (OB_SUCC(ret)) { + ObCurTraceId::TraceId pl_trace_id; int64_t row_count = 0; #define GET_RESULT \ @@ -4262,6 +4369,19 @@ int ObSPIService::do_cursor_fetch(ObPLExecCtx *ctx, return_type_count, \ is_type_record); \ } else { \ + ObString sql; \ + ObString ps_sql; \ + if (spi_result->get_sql_ctx().is_prepare_protocol_) { \ + ps_sql = spi_result->get_sql_ctx().cur_sql_; \ + } else { \ + sql = spi_result->get_sql_ctx().cur_sql_; \ + } \ + ObPLSPITraceIdGuard trace_id_guard(sql, ps_sql, cursor->get_sql_trace_id()); \ + if (cursor->get_sql_trace_id()->is_invalid() \ + && OB_NOT_NULL(ObCurTraceId::get_trace_id())) { \ + cursor->get_sql_trace_id()->set(*ObCurTraceId::get_trace_id()); \ + } \ + pl_trace_id = trace_id_guard.origin_trace_id_; \ ret = inner_fetch_with_retry(ctx, \ *cursor->get_cursor_handler(), \ into_exprs, \ @@ -4296,9 +4416,13 @@ int ObSPIService::do_cursor_fetch(ObPLExecCtx *ctx, #undef GET_RESULT if (cursor->is_streaming()) { + ObPLSPITraceIdGuard trace_id_guard(nullptr, nullptr, cursor->get_sql_trace_id()); if (OB_ISNULL(spi_result)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("spi result must be not null in oracle mode", K(ret), K(spi_result)); + } else if (pl_trace_id.is_invalid() || OB_ISNULL(cursor->get_sql_trace_id()) || cursor->get_sql_trace_id()->is_invalid()) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("unexpected invalid trace_id", K(ret), K(pl_trace_id), K(trace_id_guard.origin_trace_id_)); } else { LOG_DEBUG("start process record", K(ret), K(cursor->get_id()), K(enable_sql_audit)); //监控项统计结束 @@ -4311,6 +4435,7 @@ int ObSPIService::do_cursor_fetch(ObPLExecCtx *ctx, ObSQLSessionInfo *session_info = ctx->exec_ctx_->get_my_session(); int64_t try_cnt = session_info->get_raw_audit_record().try_cnt_; ObExecRecord record_bk = session_info->get_raw_audit_record().exec_record_; + session_info->get_raw_audit_record().pl_trace_id_.set(pl_trace_id); ObInnerSQLConnection::process_record(*(result_set), spi_result->get_sql_ctx(), *session_info, @@ -4328,6 +4453,7 @@ int ObSPIService::do_cursor_fetch(ObPLExecCtx *ctx, spi_result->get_exec_params_str_ptr()); session_info->get_raw_audit_record().exec_record_ = record_bk; session_info->get_raw_audit_record().try_cnt_ = try_cnt; + session_info->get_raw_audit_record().pl_trace_id_.reset(); } spi_result->end_cursor_stmt(ctx, ret); cursor->set_last_execute_time(ObTimeUtility::current_time()); @@ -8926,5 +9052,44 @@ int ObSPIService::spi_after_execute_dblink(ObSQLSessionInfo *session, #endif +ObPLSubPLSqlTimeGuard::ObPLSubPLSqlTimeGuard(pl::ObPLExecCtx *ctx) : + old_sub_plsql_exec_time_(-1), + execute_start_(ObTimeUtility::current_time()), + state_(NULL) +{ + if (OB_NOT_NULL(ctx) + && OB_NOT_NULL(ctx->pl_ctx_) + && ctx->pl_ctx_->get_exec_stack().count() > 0) { + // hold old time and reset sub time + ObIArray &stack = ctx->pl_ctx_->get_exec_stack(); + state_ = stack.at(stack.count()-1); + old_sub_plsql_exec_time_ = state_->get_sub_plsql_exec_time(); + old_pure_sql_exec_time_ = state_->get_pure_sql_exec_time(); + state_->reset_sub_plsql_exec_time(); + state_->reset_pure_sql_exec_time(); + } +} + +ObPLSubPLSqlTimeGuard::~ObPLSubPLSqlTimeGuard() +{ + int ret = OB_SUCCESS; + int64_t sql_exec_time = ObTimeUtility::current_time() - execute_start_; + if (OB_NOT_NULL(state_)) { + if (state_->get_sub_plsql_exec_time() > 0) { + //此时纯SQL时间已经在 add_pl_exec_time 被加到了上层 + LOG_DEBUG("<<< sql exec time ", K(sql_exec_time), K(state_->get_sub_plsql_exec_time()), + K(sql_exec_time-state_->get_sub_plsql_exec_time()), K(state_->get_pure_sql_exec_time()), + K(old_sub_plsql_exec_time_), K(old_pure_sql_exec_time_)); + } + // update sub plsql exec time + if (-1 != old_sub_plsql_exec_time_) { + state_->add_sub_plsql_exec_time(old_sub_plsql_exec_time_); + } + if (-1 != old_pure_sql_exec_time_) { + state_->add_pure_sql_exec_time(old_pure_sql_exec_time_); + } + } +} + } } diff --git a/src/sql/ob_spi.h b/src/sql/ob_spi.h index cb0db4bb02..915a19b26c 100644 --- a/src/sql/ob_spi.h +++ b/src/sql/ob_spi.h @@ -1100,6 +1100,16 @@ private: int64_t cursor_param_count); }; +struct ObPLSubPLSqlTimeGuard +{ + ObPLSubPLSqlTimeGuard(pl::ObPLExecCtx *ctx); + ~ObPLSubPLSqlTimeGuard(); + int64_t old_sub_plsql_exec_time_; + int64_t execute_start_; + pl::ObPLExecState *state_; + int64_t old_pure_sql_exec_time_; +}; + } } diff --git a/src/sql/ob_sql.cpp b/src/sql/ob_sql.cpp index 8eb270897b..18a6a27ec8 100644 --- a/src/sql/ob_sql.cpp +++ b/src/sql/ob_sql.cpp @@ -636,6 +636,58 @@ int ObSql::fill_result_set(ObResultSet &result_set, return ret; } +int ObSql::get_composite_type_field_name(ObSchemaGetterGuard &schema_guard, + int64_t type_id, + ObSqlString &composite_field_name) +{ + int ret = OB_SUCCESS; + const pl::ObUserDefinedType *user_type = NULL; + const ObUDTTypeInfo *udt_info = NULL; + ObArenaAllocator allocator; + const uint64_t tenant_id = pl::get_tenant_id_by_object_id(type_id); + if (OB_FAIL(schema_guard.get_udt_info(tenant_id, type_id, udt_info))) { + OB_LOG(WARN, "get user type fail.", K(type_id), K(ret)); + } else if (NULL == udt_info) { + ret = OB_ERR_UNEXPECTED; + OB_LOG(WARN, "udt info is null.", K(type_id), K(ret)); + } else if (OB_FAIL(udt_info->transform_to_pl_type(allocator, user_type))) { + OB_LOG(WARN, "faild to transform to pl type", K(ret)); + } else if (NULL == user_type) { + ret = OB_ERR_UNEXPECTED; + OB_LOG(WARN, "user type is null.", K(type_id), K(ret)); + } else { + if (user_type->is_record_type()) { + const pl::ObRecordType *rec_type = static_cast(user_type); + OZ (composite_field_name.append("(")); + for (int64_t i = 0; OB_SUCC(ret) && i < rec_type->get_member_count(); ++i) { + pl::ObRecordMember *member = const_cast(rec_type->get_record_member(i)); + CK (OB_NOT_NULL(member)); + OZ (composite_field_name.append(member->member_name_)); + if (OB_FAIL(ret)) { + // do nothing + } else if (member->member_type_.is_record_type() || member->member_type_.is_collection_type()) { + OZ (get_composite_type_field_name(schema_guard, + member->member_type_.get_user_type_id(), + composite_field_name)); + } + if (i < rec_type->get_member_count() - 1) { + OZ (composite_field_name.append(", ")); + } + } + OZ (composite_field_name.append(")")); + } else if (user_type->is_collection_type()) { + const pl::ObCollectionType *coll_type = static_cast(user_type); + if (coll_type->get_element_type().is_record_type() + || coll_type->get_element_type().is_collection_type()) { + OZ (get_composite_type_field_name(schema_guard, + coll_type->get_element_type().get_user_type_id(), + composite_field_name)); + } + } + } + return ret; +} + int ObSql::fill_select_result_set(ObResultSet &result_set, ObSqlCtx *context, const PlanCacheMode mode, ObCollationType collation_type, const ObString &type_name, ObStmt &basic_stmt, ObField &field) @@ -656,6 +708,8 @@ int ObSql::fill_select_result_set(ObResultSet &result_set, ObSqlCtx *context, co const SelectItem &select_item = select_stmt->get_select_item(i); LOG_DEBUG("select item info", K(select_item)); ObRawExpr *expr = select_item.expr_; + bool is_ext_field = false; + ObSqlString composite_field_name; if (OB_UNLIKELY(NULL == expr)) { ret = OB_ERR_ILLEGAL_ID; LOG_WARN("fail to get expr", K(ret), K(i), K(size)); @@ -670,7 +724,15 @@ int ObSql::fill_select_result_set(ObResultSet &result_set, ObSqlCtx *context, co } if (OB_SUCC(ret) && expr->get_result_type().is_ext()) { - if ((expr->is_query_ref_expr() && static_cast(expr)->is_cursor()) +#ifdef OB_BUILD_ORACLE_PL + // error code compiltable with oracle + if (pl::ObPlJsonUtil::is_pl_jsontype(expr->get_result_type().get_udt_id())) { + ret = OB_ERR_PL_JSONTYPE_USAGE; + } +#endif + if (OB_FAIL(ret)) { + // do nothing + } else if ((expr->is_query_ref_expr() && static_cast(expr)->is_cursor()) || (expr->is_udf_expr() && static_cast(expr)->get_is_return_sys_cursor())) { if (OB_FAIL(ob_write_string(alloc, "SYS_REFCURSOR", field.type_name_))) { LOG_WARN("fail to alloc string", K(i), K(field), K(ret)); @@ -680,14 +742,21 @@ int ObSql::fill_select_result_set(ObResultSet &result_set, ObSqlCtx *context, co // xmltype is supported, do nothing } else if (NULL == context->secondary_namespace_ // pl resolve && NULL == context->session_info_->get_pl_context()) { // pl execute - ret = OB_NOT_SUPPORTED; -#ifdef OB_BUILD_ORACLE_PL - // error code compiltable with oracle - if (pl::ObPlJsonUtil::is_pl_jsontype(expr->get_result_type().get_udt_id())) { - ret = OB_ERR_PL_JSONTYPE_USAGE; + is_ext_field = true; + field.type_.set_collation_type(CS_TYPE_BINARY); + field.type_.set_collation_level(CS_LEVEL_IMPLICIT); + field.length_ = OB_MAX_LONGTEXT_LENGTH; + if (CS_TYPE_BINARY != expr->get_collation_type() + && ObCharset::is_valid_collation(collation_type)) { + field.charsetnr_ = static_cast(collation_type); + } else { + field.charsetnr_ = static_cast(expr->get_collation_type()); + } + if (OB_FAIL(get_composite_type_field_name(*context->schema_guard_, + expr->get_result_type().get_udt_id(), + composite_field_name))) { + LOG_WARN("get record member name fail.", K(ret), K(composite_field_name)); } -#endif - LOG_WARN("composite type use in pure sql context not supported!"); } } @@ -704,7 +773,7 @@ int ObSql::fill_select_result_set(ObResultSet &result_set, ObSqlCtx *context, co field.type_.set_collation_level(expr->get_collation_level()); } // Setup Scale - if (ObVarcharType == field.type_.get_type()) { + if (ObVarcharType == field.type_.get_type() || is_ext_field) { field.type_.set_varchar(type_name); } else if (ObNumberType == field.type_.get_type()) { field.type_.set_number(number); @@ -738,8 +807,20 @@ int ObSql::fill_select_result_set(ObResultSet &result_set, ObSqlCtx *context, co ObCollationType field_names_collation = ObCharset::is_valid_collation(collation_type) ? collation_type : CS_TYPE_UTF8MB4_BIN; if (OB_SUCC(ret)) { - if (OB_FAIL(ObSQLUtils::copy_and_convert_string_charset(alloc, select_item.alias_name_, field.cname_, - CS_TYPE_UTF8MB4_BIN, field_names_collation))) { + ObSqlString field_name; + if (composite_field_name.length() > 0) { + // need record member name + if (OB_FAIL(field_name.append(select_item.alias_name_))) { + LOG_WARN("append field name fail.", K(ret), K(select_item.alias_name_), K(composite_field_name)); + } else if (OB_FAIL(field_name.append(composite_field_name.string()))) { + LOG_WARN("get field name fail.", K(ret), K(select_item.alias_name_), K(composite_field_name)); + } + } + if (OB_FAIL(ret)) { + // do nothing + } else if (OB_FAIL(ObSQLUtils::copy_and_convert_string_charset(alloc, + field_name.length() > 0 ? field_name.string() : select_item.alias_name_, + field.cname_, CS_TYPE_UTF8MB4_BIN, field_names_collation))) { LOG_WARN("fail to alloc string", K(select_item.alias_name_), K(ret)); } else { field.is_hidden_rowid_ = select_item.is_hidden_rowid_; @@ -842,9 +923,23 @@ int ObSql::fill_select_result_set(ObResultSet &result_set, ObSqlCtx *context, co ret = OB_ALLOCATE_MEMORY_FAILED; LOG_WARN("failed to allocate memory", K(ret)); } else { + ObSqlString paramed_field_name; field.paramed_ctx_ = new(buf) ObParamedSelectItemCtx(); - if (OB_FAIL(ob_write_string(alloc, select_item.paramed_alias_name_, - field.paramed_ctx_->paramed_cname_))) { + if (composite_field_name.length() > 0) { + // need record member name + if (OB_FAIL(paramed_field_name.append(select_item.paramed_alias_name_))) { + LOG_WARN("append paramed field fail.", K(ret), K(select_item.paramed_alias_name_), K(composite_field_name)); + } else if (OB_FAIL(paramed_field_name.append(composite_field_name.string()))) { + LOG_WARN("get field name fail.", K(ret), K(select_item.paramed_alias_name_), K(composite_field_name)); + } + } + if (OB_FAIL(ret)) { + // do nothing + } else if (OB_FAIL(ob_write_string(alloc, + paramed_field_name.length() > 0 + ? paramed_field_name.string() + : select_item.paramed_alias_name_, + field.paramed_ctx_->paramed_cname_))) { LOG_WARN("failed to copy paramed cname", K(ret)); } else if (OB_FAIL(field.paramed_ctx_->param_str_offsets_.assign( select_item.questions_pos_))) { @@ -3003,7 +3098,8 @@ int ObSql::generate_physical_plan(ParseResult &parse_result, stmt_ora_need_privs))) { LOG_WARN("failed to generate plan", K(ret)); } - } else if (stmt::T_EXECUTE == basic_stmt->get_stmt_type()) { + } else if (stmt::T_EXECUTE == basic_stmt->get_stmt_type() && + stmt::T_CALL_PROCEDURE != static_cast(basic_stmt)->get_prepare_type()) { if (OB_FAIL(handle_text_execute(basic_stmt, sql_ctx, result))) { LOG_WARN("handle_text_execute failed", K(ret)); } diff --git a/src/sql/ob_sql.h b/src/sql/ob_sql.h index d60ea90327..69ae2f5381 100644 --- a/src/sql/ob_sql.h +++ b/src/sql/ob_sql.h @@ -274,6 +274,9 @@ private: int fill_select_result_set(ObResultSet &result_set, ObSqlCtx *context, const PlanCacheMode mode, ObCollationType collation_type, const ObString &type_name, ObStmt &basic_stmt, ObField &field); + static int get_composite_type_field_name(share::schema::ObSchemaGetterGuard &schema_guard, + int64_t type_id, + ObSqlString &name_string); int pc_add_udr_plan(const ObUDRItemMgr::UDRItemRefGuard &item_guard, ObPlanCacheCtx &pc_ctx, ObResultSet &result, diff --git a/src/sql/ob_sql_define.h b/src/sql/ob_sql_define.h index b36290680a..ef27455462 100644 --- a/src/sql/ob_sql_define.h +++ b/src/sql/ob_sql_define.h @@ -278,6 +278,8 @@ enum ObRepartitionScope OB_REPARTITION_BOTH_SIDE, }; +// enum ObPLCacheObjectType start wich OB_PHY_PLAN_UNCERTAIN value. +// if it need add enum value to ObPhyPlanType, need skip ObPLCacheObjectType max value. enum ObPhyPlanType { OB_PHY_PLAN_UNINITIALIZED = 0, diff --git a/src/sql/optimizer/ob_optimizer_util.cpp b/src/sql/optimizer/ob_optimizer_util.cpp index d3febcd3d0..08c3cdb450 100644 --- a/src/sql/optimizer/ob_optimizer_util.cpp +++ b/src/sql/optimizer/ob_optimizer_util.cpp @@ -6619,6 +6619,12 @@ int ObOptimizerUtil::try_add_cast_to_set_child_list(ObIAllocator *allocator, } else if (ObMaxType == res_type.get_type()) { ret = OB_ERR_INVALID_TYPE_FOR_OP; LOG_WARN("column type incompatible", K(left_type), K(right_type)); + } else if ((left_type.is_ext() && !right_type.is_ext()) + || (!left_type.is_ext() && right_type.is_ext()) + || (left_type.is_ext() && right_type.is_ext() + && left_type.get_udt_id() != right_type.get_udt_id())) { + ret = OB_ERR_EXP_NEED_SAME_DATATYPE; + LOG_WARN("expression must have same datatype as corresponding expression", K(ret), K(left_type), K(right_type)); } else if (left_type != res_type && OB_FAIL(add_cast_to_set_list(session_info, expr_factory, left_stmts, res_type, i))) { LOG_WARN("failed to add add cast to set list", K(ret)); diff --git a/src/sql/plan_cache/ob_cache_object.cpp b/src/sql/plan_cache/ob_cache_object.cpp index 1aacede89c..8964b35ec5 100644 --- a/src/sql/plan_cache/ob_cache_object.cpp +++ b/src/sql/plan_cache/ob_cache_object.cpp @@ -434,7 +434,7 @@ int ObPlanCacheObject::type_to_name(const ObLibCacheNameSpace ns, common::ObString &type_name) { int ret = OB_SUCCESS; - const char* type_strs[] = {"NS_INVALID", "SQL_PLAN", "PROCEDURE", "FUNCTION", "ANONYMOUS", "TRIGGER", "PACKAGE", "NS_MAX"}; + const char* type_strs[] = {"NS_INVALID", "SQL_PLAN", "PROCEDURE", "FUNCTION", "ANONYMOUS", "TRIGGER", "PACKAGE", "TABLEAPI", "CALLSTMT", "NS_MAX"}; char *buf = NULL; if (ns <= NS_INVALID || ns >= NS_MAX) { ret = OB_INVALID_ARGUMENT; diff --git a/src/sql/printer/ob_raw_expr_printer.cpp b/src/sql/printer/ob_raw_expr_printer.cpp index 7261dbf088..42bc492880 100644 --- a/src/sql/printer/ob_raw_expr_printer.cpp +++ b/src/sql/printer/ob_raw_expr_printer.cpp @@ -3338,6 +3338,7 @@ do { \ const share::schema::OBJECT *object_info = NULL; \ ObSchemaChecker checker; \ bool exist = false; \ + bool is_private_syn = false; \ if (OB_SYS_TENANT_ID == tenant_id) { \ } else if (OB_FAIL(schema_guard_->get_object_info_func(tenant_id, object_id, object_info))) { \ LOG_WARN("failed to get udt info", K(ret), KPC(expr), K(tenant_id)); \ @@ -3352,7 +3353,8 @@ do { \ } else if (OB_FAIL(checker.check_exist_same_name_object_with_synonym(tenant_id, \ database_schema->get_database_id(), \ database_schema->get_database_name_str(), \ - exist))) { \ + exist, \ + is_private_syn))) { \ LOG_WARN("failed to check exist same name object with database name", K(ret), KPC(database_schema)); \ } else if (!exist) { \ PRINT_IDENT_WITH_QUOT(database_schema->get_database_name_str()); \ diff --git a/src/sql/resolver/cmd/ob_call_procedure_resolver.cpp b/src/sql/resolver/cmd/ob_call_procedure_resolver.cpp index 3a2661e2ab..065f7064e1 100644 --- a/src/sql/resolver/cmd/ob_call_procedure_resolver.cpp +++ b/src/sql/resolver/cmd/ob_call_procedure_resolver.cpp @@ -347,6 +347,7 @@ int ObCallProcedureResolver::resolve(const ParseNode &parse_tree) CK (OB_NOT_NULL(package_guard)); OX (params_.package_guard_ = package_guard); } + int64_t compile_start = ObTimeUtility::current_time(); OZ (ObCacheObjectFactory::alloc(stmt->get_cacheobj_guard(), ObLibCacheNameSpace::NS_CALLSTMT, session_info_->get_effective_tenant_id())); @@ -390,6 +391,7 @@ int ObCallProcedureResolver::resolve(const ParseNode &parse_tree) ObSEArray expr_params; // 获取routine schem info if (OB_SUCC(ret)) { + ObSynonymChecker synonym_checker; if (OB_NOT_NULL(params_node) && OB_FAIL(resolve_param_exprs(params_node, expr_params))) { LOG_WARN("failed to resolve param exprs", K(ret)); @@ -404,7 +406,8 @@ int ObCallProcedureResolver::resolve(const ParseNode &parse_tree) expr_params, proc_info, dblink_name, - &(call_proc_info->get_allocator())))) { + &(call_proc_info->get_allocator()), + &synonym_checker))) { LOG_WARN("failed to get routine info", K(ret), K(db_name), K(package_name), K(sp_name)); } else if (OB_ISNULL(proc_info)) { ret = OB_ERR_UNEXPECTED; @@ -425,7 +428,7 @@ int ObCallProcedureResolver::resolve(const ParseNode &parse_tree) if (OB_SUCC(ret)) { ObSchemaObjVersion obj_version; obj_version.object_id_ = proc_info->get_routine_id(); - obj_version.object_type_ = proc_info->is_procedure() ? DEPENDENCY_PROCEDURE : DEPENDENCY_FUNCTION; + obj_version.object_type_ = DEPENDENCY_PROCEDURE; obj_version.version_ = proc_info->get_schema_version(); int64_t tenant_id = session_info_->get_effective_tenant_id(); int64_t tenant_schema_version = OB_INVALID_VERSION; @@ -435,8 +438,14 @@ int ObCallProcedureResolver::resolve(const ParseNode &parse_tree) OZ (schema_checker_->get_schema_mgr()->get_schema_version(OB_SYS_TENANT_ID, sys_schema_version)); OX (call_proc_info->set_tenant_schema_version(tenant_schema_version)); OX (call_proc_info->set_sys_schema_version(sys_schema_version)); - OZ (call_proc_info->init_dependency_table_store(1)); + OZ (call_proc_info->init_dependency_table_store(1 + (synonym_checker.has_synonym() ? synonym_checker.get_synonym_ids().count() : 0))); OZ (call_proc_info->get_dependency_table().push_back(obj_version)); + if (synonym_checker.has_synonym()) { + OZ (ObResolverUtils::add_dependency_synonym_object(schema_checker_->get_schema_mgr(), + session_info_, + synonym_checker, + call_proc_info->get_dependency_table())); + } } } ObSEArray params; @@ -479,7 +488,7 @@ int ObCallProcedureResolver::resolve(const ParseNode &parse_tree) if (lib::is_mysql_mode() && param->get_expr_type() != T_OP_GET_USER_VAR && param->get_expr_type() != T_OP_GET_SYS_VAR - && param->get_expr_type() != T_QUESTIONMARK) { + && !(param->get_expr_type() == T_QUESTIONMARK && params_.is_prepare_protocol_)) { ret = OB_ER_SP_NOT_VAR_ARG; LOG_USER_ERROR(OB_ER_SP_NOT_VAR_ARG, static_cast(i), static_cast(sp_name.length()), sp_name.ptr()); LOG_WARN("OUT or INOUT argument for routine is not a variable", K(param->get_expr_type()), K(ret)); @@ -558,16 +567,20 @@ int ObCallProcedureResolver::resolve(const ParseNode &parse_tree) OZ (call_proc_info->prepare_expression(params)); OZ (call_proc_info->final_expression(params, session_info_, schema_checker_->get_schema_mgr())); OX (stmt->set_call_proc_info(call_proc_info)); + int64_t compile_end = ObTimeUtility::current_time(); if (params_.is_execute_call_stmt_ && 0 != params_.cur_sql_.length() && NULL == stmt->get_dblink_routine_info()) { if (NULL != params_.param_list_) { OZ (call_proc_info->set_params_info(*params_.param_list_)); } + OX (call_proc_info->get_stat_for_update().type_ = pl::ObPLCacheObjectType::CALL_STMT_TYPE); + OX (call_proc_info->get_stat_for_update().compile_time_ = compile_end - compile_start); OZ (add_call_proc_info(call_proc_info)); } - CK (1 == call_proc_info->get_dependency_table().count()); - OZ (stmt->add_global_dependency_table(call_proc_info->get_dependency_table().at(0))); + for (int64_t i = 0; OB_SUCC(ret) && i < call_proc_info->get_dependency_table().count(); ++i) { + OZ (stmt->add_global_dependency_table(call_proc_info->get_dependency_table().at(i))); + } } return ret; diff --git a/src/sql/resolver/dml/ob_dml_resolver.cpp b/src/sql/resolver/dml/ob_dml_resolver.cpp index 752492f4ff..3216db5afd 100755 --- a/src/sql/resolver/dml/ob_dml_resolver.cpp +++ b/src/sql/resolver/dml/ob_dml_resolver.cpp @@ -2675,10 +2675,10 @@ int ObDMLResolver::resolve_qualified_identifier(ObQualifiedName &q_name, } else if (T_FUN_PL_COLLECTION_CONSTRUCT == real_ref_expr->get_expr_type()) { if (!params_.is_resolve_table_function_expr_) { //such as insert into tbl values(1,3, coll('a', 1)); - if ((NULL == params_.secondary_namespace_ && NULL == session_info_->get_pl_context()) || - (current_scope_ != T_FIELD_LIST_SCOPE && current_scope_ != T_INTO_SCOPE)) { + if ((!stmt_->is_select_stmt() && params_.secondary_namespace_ == NULL && session_info_->get_pl_context() == NULL) + || (current_scope_ != T_FIELD_LIST_SCOPE && current_scope_ != T_INTO_SCOPE)) { ret = OB_NOT_SUPPORTED; - LOG_WARN("dml with collection or record construction function is not supported", K(ret)); + LOG_WARN("dml with collection or record construction function is not supported", K(ret), K(current_scope_)); LOG_USER_ERROR(OB_NOT_SUPPORTED, "dml with collection or record construction function is"); } else { is_external = false; @@ -11289,7 +11289,7 @@ int ObDMLResolver::generate_check_constraint_exprs(const TableItem *table_item, return ret; } -int ObDMLResolver::collect_schema_version(ObRawExpr *expr) +int ObDMLResolver::check_disable_parallel_state(ObRawExpr *expr) { int ret = OB_SUCCESS; ObDMLStmt *stmt = get_stmt(); @@ -11297,135 +11297,55 @@ int ObDMLResolver::collect_schema_version(ObRawExpr *expr) CK (OB_NOT_NULL(stmt)); if (OB_FAIL(ret)) { - } else if (T_OP_GET_PACKAGE_VAR == expr->get_expr_type()) { - uint64_t package_id = OB_INVALID_ID; - const ObPackageInfo *spec_info = NULL; - const ObPackageInfo *body_info = NULL; - uint64_t dep_obj_id = view_ref_id_; - ObSchemaObjVersion ver; - CK (expr->get_param_count() >= 3); - OX (package_id = static_cast(expr->get_param_expr(0))->get_value().get_uint64()); - if (package_id != OB_INVALID_ID) { - OZ (pl::ObPLPackageManager::get_package_schema_info(*schema_checker_->get_schema_guard(), package_id, spec_info, body_info)); - } - if (OB_NOT_NULL(spec_info)) { - OX (ver.object_id_ = spec_info->get_package_id()); - OX (ver.version_ = spec_info->get_schema_version()); - OX (ver.object_type_ = DEPENDENCY_PACKAGE); - OZ (stmt->add_global_dependency_table(ver)); - OZ (stmt->add_ref_obj_version(dep_obj_id, spec_info->get_database_id(), ObObjectType::VIEW, ver, *allocator_)); - } - if (OB_NOT_NULL(body_info)) { - OX (ver.object_id_ = body_info->get_package_id()); - OX (ver.version_ = body_info->get_schema_version()); - OX (ver.object_type_ = DEPENDENCY_PACKAGE_BODY); - OZ (stmt->add_global_dependency_table(ver)); - OZ (stmt->add_ref_obj_version(dep_obj_id, body_info->get_database_id(), ObObjectType::VIEW, ver, *allocator_)); - } } else if (T_FUN_UDF == expr->get_expr_type()) { - ObUDFRawExpr *udf_expr = static_cast(expr); - ObSchemaObjVersion udf_version; - share::schema::ObSchemaGetterGuard *schema_guard = NULL; uint64_t database_id = OB_INVALID_ID; + ObUDFRawExpr *udf_expr = static_cast(expr); + ObSEArray return_value_version; CK (OB_NOT_NULL(udf_expr)); - if (OB_FAIL(ret)) { - } else if (OB_ISNULL(schema_guard = params_.schema_checker_->get_schema_guard())) { - ret = OB_ERR_UNEXPECTED; - LOG_WARN("table schema is null", K(ret), K(schema_guard)); - } else if (OB_FAIL(schema_guard->get_database_id(session_info_->get_effective_tenant_id(), - udf_expr->get_database_name().empty() ? session_info_->get_database_name() : udf_expr->get_database_name(), - database_id))) { - LOG_WARN("failed to get database id", K(ret)); - } else { - bool exist = false; - uint64_t object_db_id = OB_INVALID_ID; - ObSynonymChecker synonym_checker; - ObString object_name; - OZ (ObResolverUtils::resolve_synonym_object_recursively(*params_.schema_checker_, - synonym_checker, - session_info_->get_effective_tenant_id(), - database_id, - udf_expr->get_func_name(), - object_db_id, object_name, exist)); - if (OB_SUCC(ret) && exist) { - for (int64_t i = 0; OB_SUCC(ret) && i < synonym_checker.get_synonym_ids().count(); ++i) { - int64_t schema_version = OB_INVALID_VERSION; - uint64_t obj_id = synonym_checker.get_synonym_ids().at(i); - uint64_t dep_db_id = synonym_checker.get_database_ids().at(i); - ObSchemaObjVersion syn_version; - OZ (schema_guard->get_schema_version(SYNONYM_SCHEMA, - session_info_->get_effective_tenant_id(), - obj_id, - schema_version)); - OX (syn_version.object_id_ = obj_id); - OX (syn_version.version_ = schema_version); - OX (syn_version.object_type_ = DEPENDENCY_SYNONYM); - OZ (stmt->add_global_dependency_table(syn_version)); - OZ (stmt->add_ref_obj_version(obj_id, dep_db_id, ObObjectType::SYNONYM, syn_version, *allocator_)); + OZ (ObResolverUtils::set_parallel_info(*params_.session_info_, + *params_.schema_checker_->get_schema_guard(), + *expr, + *stmt->get_query_ctx(), + return_value_version)); + OX (stmt->get_query_ctx()->disable_udf_parallel_ |= !udf_expr->is_parallel_enable()); + OX (stmt_->get_query_ctx()->disable_udf_parallel_ |= is_valid_id(udf_expr->get_dblink_id())); + OX (stmt_->get_query_ctx()->has_dblink_udf_ |= is_valid_id(udf_expr->get_dblink_id())); + OX (stmt_->get_query_ctx()->set_has_dblink( + stmt_->get_query_ctx()->has_dblink() || is_valid_id(udf_expr->get_dblink_id()))); + OX (stmt_->get_query_ctx()->has_pl_udf_ = true); + if (OB_SUCC(ret) && + T_FIELD_LIST_SCOPE == current_scope_ && + udf_expr->get_result_type().is_ext() && + (pl::PL_RECORD_TYPE == udf_expr->get_result_type().get_extend_type() || + pl::PL_NESTED_TABLE_TYPE == udf_expr->get_result_type().get_extend_type() || + pl::PL_VARRAY_TYPE == udf_expr->get_result_type().get_extend_type())) { + OX (stmt->get_query_ctx()->disable_udf_parallel_ |= true); + } + if (OB_SUCC(ret) && return_value_version.count()) { + uint64_t database_id = OB_INVALID_ID; + OZ (params_.schema_checker_->get_schema_guard()->get_database_id(params_.session_info_->get_effective_tenant_id(), + udf_expr->get_database_name().empty() + ? params_.session_info_->get_database_name() + : udf_expr->get_database_name(), + database_id)); + for (int64_t i = 0; OB_SUCC(ret) && i < return_value_version.count(); ++i) { + if (return_value_version.at(i).is_valid()) { + OZ (stmt->add_global_dependency_table(return_value_version.at(i))); + OZ (stmt->add_ref_obj_version(view_ref_id_, database_id, ObObjectType::VIEW, return_value_version.at(i), *allocator_)); } } - if (OB_SUCC(ret) && udf_expr->need_add_dependency()) { - uint64_t dep_obj_id = view_ref_id_; - uint64_t dep_db_id = database_id; - ObArray vers; - OZ (udf_expr->get_schema_object_version(*schema_guard, vers)); - for (int64_t i = 0; OB_SUCC(ret) && i < vers.count(); ++i) { - OZ (stmt->add_global_dependency_table(vers.at(i))); - OZ (stmt->add_ref_obj_version(dep_obj_id, dep_db_id, ObObjectType::VIEW, vers.at(i), *allocator_)); - } - //for udf without params, we just set called_in_sql = true, - //if this expr go through pl :: build_raw_expr later, - //the flag will change to false; - OX (expr->set_is_called_in_sql(true)); - } - OZ (ObResolverUtils::set_parallel_info(*params_.session_info_, - *params_.schema_checker_->get_schema_guard(), - *expr, - *stmt_->get_query_ctx())); - OX (stmt_->get_query_ctx()->disable_udf_parallel_ |= !udf_expr->is_parallel_enable()); - OX (stmt_->get_query_ctx()->disable_udf_parallel_ |= is_valid_id(udf_expr->get_dblink_id())); - OX (stmt_->get_query_ctx()->has_dblink_udf_ |= is_valid_id(udf_expr->get_dblink_id())); - OX (stmt_->get_query_ctx()->set_has_dblink( - stmt_->get_query_ctx()->has_dblink() || is_valid_id(udf_expr->get_dblink_id()))); - OX (stmt_->get_query_ctx()->has_pl_udf_ = true); - if (OB_SUCC(ret) && - T_FIELD_LIST_SCOPE == current_scope_ && - udf_expr->get_result_type().is_ext() && - (pl::PL_RECORD_TYPE == udf_expr->get_result_type().get_extend_type() || - pl::PL_NESTED_TABLE_TYPE == udf_expr->get_result_type().get_extend_type() || - pl::PL_VARRAY_TYPE == udf_expr->get_result_type().get_extend_type())) { - OX (stmt_->get_query_ctx()->disable_udf_parallel_ |= true); - } } } else if (T_FUN_PL_OBJECT_CONSTRUCT == expr->get_expr_type()) { - ObObjectConstructRawExpr *object_expr = static_cast(expr); - CK (OB_NOT_NULL(object_expr)); if (T_FIELD_LIST_SCOPE == current_scope_) { OX (stmt_->get_query_ctx()->disable_udf_parallel_ |= true); } - if (OB_SUCC(ret) && object_expr->need_add_dependency()) { - uint64_t dep_obj_id = view_ref_id_; - ObSchemaObjVersion coll_schema_version; - OZ (object_expr->get_schema_object_version(coll_schema_version)); - OZ (stmt->add_global_dependency_table(coll_schema_version)); - OZ (stmt->add_ref_obj_version(dep_obj_id, object_expr->get_database_id(), ObObjectType::VIEW, coll_schema_version, *allocator_)); - } } else if (T_FUN_PL_COLLECTION_CONSTRUCT == expr->get_expr_type()) { - ObCollectionConstructRawExpr *coll_expr = static_cast(expr); - CK (OB_NOT_NULL(coll_expr)); if (T_FIELD_LIST_SCOPE == current_scope_) { OX (stmt_->get_query_ctx()->disable_udf_parallel_ |= true); } - if (OB_SUCC(ret) && coll_expr->need_add_dependency()) { - uint64_t dep_obj_id = view_ref_id_; - ObSchemaObjVersion coll_schema_version; - OZ (coll_expr->get_schema_object_version(coll_schema_version)); - OZ (stmt->add_global_dependency_table(coll_schema_version)); - OZ (stmt->add_ref_obj_version(dep_obj_id, coll_expr->get_database_id(), ObObjectType::VIEW, coll_schema_version, *allocator_)); - } } else if (T_OBJ_ACCESS_REF == expr->get_expr_type()) { for (int64_t i = 0; OB_SUCC(ret) && i < expr->get_param_count(); ++i) { - OZ (collect_schema_version(expr->get_param_expr(i))); + OZ (check_disable_parallel_state(expr->get_param_expr(i))); } } @@ -11473,7 +11393,24 @@ int ObDMLResolver::resolve_external_name(ObQualifiedName &q_name, ret = OB_ERR_UNEXPECTED; LOG_WARN("Invalid expr", K(expr), K(ret)); } - OZ (collect_schema_version(expr)); + if (OB_SUCC(ret)) { + ObArray dependency_objects; + ObArray dep_db_array; + OZ (ObResolverUtils::collect_schema_version(*params_.schema_checker_->get_schema_guard(), + params_.session_info_, + expr, + dependency_objects, + true, + &dep_db_array)); + for (int64_t i = 0; OB_SUCC(ret) && i < dependency_objects.count(); ++i) { + OZ (stmt_->add_global_dependency_table(dependency_objects.at(i))); + } + CK (dependency_objects.count() >= dep_db_array.count()); + for (int64_t i = 0; OB_SUCC(ret) && i < dep_db_array.count(); ++i) { + OZ (stmt_->add_ref_obj_version(view_ref_id_, dep_db_array.at(i), ObObjectType::VIEW, dependency_objects.at(i), *allocator_)); + } + } + OZ (check_disable_parallel_state(expr)); } if (OB_ERR_SP_UNDECLARED_VAR == ret) { ret = OB_ERR_BAD_FIELD_ERROR; diff --git a/src/sql/resolver/dml/ob_dml_resolver.h b/src/sql/resolver/dml/ob_dml_resolver.h index 1f4c099464..0caa8b2fdc 100644 --- a/src/sql/resolver/dml/ob_dml_resolver.h +++ b/src/sql/resolver/dml/ob_dml_resolver.h @@ -625,11 +625,11 @@ protected: int resolve_generated_column_expr_temp(TableItem *table_item); int find_generated_column_expr(ObRawExpr *&expr, bool &is_found); int deduce_generated_exprs(common::ObIArray &exprs); - int collect_schema_version(ObRawExpr *expr); int resolve_external_name(ObQualifiedName &q_name, ObIArray &columns, ObIArray &real_exprs, ObRawExpr *&expr); + int check_disable_parallel_state(ObRawExpr *expr); int resolve_geo_mbr_column(); int build_prefix_index_compare_expr(ObRawExpr &column_expr, ObRawExpr *prefix_expr, diff --git a/src/sql/resolver/ob_resolver_utils.cpp b/src/sql/resolver/ob_resolver_utils.cpp index 317909bbf9..6954dbd87c 100644 --- a/src/sql/resolver/ob_resolver_utils.cpp +++ b/src/sql/resolver/ob_resolver_utils.cpp @@ -209,6 +209,191 @@ int ObResolverUtils::check_json_table_column_exists(const TableItem &table_item, return ret; } +int ObResolverUtils::collect_schema_version(share::schema::ObSchemaGetterGuard &schema_guard, + const ObSQLSessionInfo *session_info, + ObRawExpr *expr, + ObIArray &dependency_objects, + bool is_called_in_sql, + ObIArray *dep_db_array) +{ + int ret = OB_SUCCESS; + CK (OB_NOT_NULL(session_info)); + CK (OB_NOT_NULL(expr)); + + if (OB_FAIL(ret)) { + } else if (T_OP_GET_PACKAGE_VAR == expr->get_expr_type()) { + uint64_t package_id = OB_INVALID_ID; + const ObPackageInfo *spec_info = NULL; + const ObPackageInfo *body_info = NULL; + ObSchemaObjVersion ver; + CK (expr->get_param_count() >= 3); + OX (package_id = static_cast(expr->get_param_expr(0))->get_value().get_uint64()); + if (package_id != OB_INVALID_ID) { + OZ (pl::ObPLPackageManager::get_package_schema_info(schema_guard, package_id, spec_info, body_info)); + } + if (OB_NOT_NULL(spec_info)) { + OX (ver.object_id_ = spec_info->get_package_id()); + OX (ver.version_ = spec_info->get_schema_version()); + OX (ver.object_type_ = DEPENDENCY_PACKAGE); + OZ (dependency_objects.push_back(ver)); + if (OB_NOT_NULL(dep_db_array)) { + OZ (dep_db_array->push_back(spec_info->get_database_id())); + } + } + if (OB_NOT_NULL(body_info)) { + OX (ver.object_id_ = body_info->get_package_id()); + OX (ver.version_ = body_info->get_schema_version()); + OX (ver.object_type_ = DEPENDENCY_PACKAGE_BODY); + OZ (dependency_objects.push_back(ver)); + if (OB_NOT_NULL(dep_db_array)) { + OZ (dep_db_array->push_back(body_info->get_database_id())); + } + } + } else if (T_FUN_UDF == expr->get_expr_type()) { + ObUDFRawExpr *udf_expr = static_cast(expr); + ObSchemaObjVersion ver; + uint64_t database_id = OB_INVALID_ID; + CK (OB_NOT_NULL(udf_expr)); + if (OB_SUCC(ret) && udf_expr->need_add_dependency()) { + OZ (schema_guard.get_database_id(session_info->get_effective_tenant_id(), + udf_expr->get_database_name().empty() ? session_info->get_database_name() : udf_expr->get_database_name(), + database_id)); + if (OB_SUCC(ret)) { + bool exist = false; + uint64_t object_db_id = OB_INVALID_ID; + ObSchemaChecker schema_checker; + ObSynonymChecker synonym_checker; + ObString object_name; + OZ (schema_checker.init(schema_guard, session_info->get_sessid())); + OZ (ObResolverUtils::resolve_synonym_object_recursively(schema_checker, + synonym_checker, + session_info->get_effective_tenant_id(), + database_id, + udf_expr->get_func_name(), + object_db_id, object_name, exist)); + if (OB_SUCC(ret) && exist) { + for (int64_t i = 0; OB_SUCC(ret) && i < synonym_checker.get_synonym_ids().count(); ++i) { + int64_t schema_version = OB_INVALID_VERSION; + uint64_t obj_id = synonym_checker.get_synonym_ids().at(i); + uint64_t dep_db_id = synonym_checker.get_database_ids().at(i); + ObSchemaObjVersion syn_version; + OZ (schema_guard.get_schema_version(SYNONYM_SCHEMA, + session_info->get_effective_tenant_id(), + obj_id, + schema_version)); + OX (syn_version.object_id_ = obj_id); + OX (syn_version.version_ = schema_version); + OX (syn_version.object_type_ = DEPENDENCY_SYNONYM); + OZ (dependency_objects.push_back(syn_version)); + if (OB_NOT_NULL(dep_db_array)) { + OZ (dep_db_array->push_back(dep_db_id)); + } + } + } + } + ObArray vers; + OZ (udf_expr->get_schema_object_version(schema_guard, vers)); + for (int64_t i = 0; OB_SUCC(ret) && i < vers.count(); ++i) { + OZ (dependency_objects.push_back(vers.at(i))); + if (OB_NOT_NULL(dep_db_array)) { + OZ (dep_db_array->push_back(database_id)); + } + } + } + OX (expr->set_is_called_in_sql(is_called_in_sql)); + } else if (T_FUN_PL_OBJECT_CONSTRUCT == expr->get_expr_type()) { + ObObjectConstructRawExpr *object_expr = static_cast(expr); + ObSchemaObjVersion ver; + CK (OB_NOT_NULL(object_expr)); + if (OB_SUCC(ret) && object_expr->need_add_dependency()) { + OZ (object_expr->get_schema_object_version(ver)); + OZ (dependency_objects.push_back(ver)); + if (OB_NOT_NULL(dep_db_array)) { + OZ (dep_db_array->push_back(object_expr->get_database_id())); + } + } + } else if (T_FUN_PL_COLLECTION_CONSTRUCT == expr->get_expr_type()) { + ObCollectionConstructRawExpr *coll_expr = static_cast(expr); + ObSchemaObjVersion ver; + CK (OB_NOT_NULL(coll_expr)); + if (OB_SUCC(ret) && coll_expr->need_add_dependency()) { + OZ (coll_expr->get_schema_object_version(ver)); + OZ (dependency_objects.push_back(ver)); + if (OB_NOT_NULL(dep_db_array)) { + OZ (dep_db_array->push_back(coll_expr->get_database_id())); + } + } + } else if (T_OBJ_ACCESS_REF == expr->get_expr_type()) { + for (int64_t i = 0; OB_SUCC(ret) && i < expr->get_param_count(); ++i) { + OZ (collect_schema_version(schema_guard, + session_info, + expr->get_param_expr(i), + dependency_objects, + is_called_in_sql, + dep_db_array)); + } + } + + return ret; +} + +int ObResolverUtils::add_dependency_synonym_object(share::schema::ObSchemaGetterGuard *schema_guard, + const ObSQLSessionInfo *session_info, + const ObSynonymChecker &synonym_checker, + DependenyTableStore &dep_table) +{ + int ret = OB_SUCCESS; + + CK (OB_NOT_NULL(schema_guard)); + CK (OB_NOT_NULL(session_info)); + for (int64_t i = 0; OB_SUCC(ret) && i < synonym_checker.get_synonym_ids().count(); ++i) { + int64_t schema_version = OB_INVALID_VERSION; + uint64_t obj_id = synonym_checker.get_synonym_ids().at(i); + if (OB_FAIL(schema_guard->get_schema_version(SYNONYM_SCHEMA, + session_info->get_effective_tenant_id(), + obj_id, + schema_version))) { + LOG_WARN("get schema version failed", K(session_info->get_effective_tenant_id()), + K(obj_id), K(ret)); + } else { + if (OB_FAIL(dep_table.push_back(ObSchemaObjVersion(obj_id, schema_version, DEPENDENCY_SYNONYM)))) { + LOG_WARN("add dependency object failed", K(obj_id), K(ret)); + } + } + } + + return ret; +} + +int ObResolverUtils::add_dependency_synonym_object(share::schema::ObSchemaGetterGuard *schema_guard, + const ObSQLSessionInfo *session_info, + const ObSynonymChecker &synonym_checker, + const pl::ObPLDependencyTable &dep_table) +{ + int ret = OB_SUCCESS; + + CK (OB_NOT_NULL(schema_guard)); + CK (OB_NOT_NULL(session_info)); + for (int64_t i = 0; OB_SUCC(ret) && i < synonym_checker.get_synonym_ids().count(); ++i) { + int64_t schema_version = OB_INVALID_VERSION; + uint64_t obj_id = synonym_checker.get_synonym_ids().at(i); + if (OB_FAIL(schema_guard->get_schema_version(SYNONYM_SCHEMA, + session_info->get_effective_tenant_id(), + obj_id, + schema_version))) { + LOG_WARN("get schema version failed", K(session_info->get_effective_tenant_id()), + K(obj_id), K(ret)); + } else { + ObSchemaObjVersion ver(obj_id, schema_version, DEPENDENCY_SYNONYM); + if (OB_FAIL(ObPLCompileUnitAST::add_dependency_object_impl(dep_table, ver))) { + LOG_WARN("add dependency object failed", K(obj_id), K(ret)); + } + } + } + + return ret; +} + int ObResolverUtils::resolve_extended_type_info(const ParseNode &str_list_node, ObIArray& type_info_array) { int ret = OB_SUCCESS; @@ -403,7 +588,8 @@ int ObResolverUtils::get_candidate_routines(ObSchemaChecker &schema_checker, const ObString &package_name, const ObString &routine_name, const share::schema::ObRoutineType routine_type, common::ObIArray &routines, - uint64_t udt_id, const pl::ObPLResolveCtx *resolve_ctx) + uint64_t udt_id, const pl::ObPLResolveCtx *resolve_ctx, + ObSynonymChecker *outer_synonym_checker) { int ret = OB_SUCCESS; @@ -451,7 +637,7 @@ if ((OB_FAIL(ret) || 0 == routines.count()) \ bool exist = false; \ ObSynonymChecker synonym_checker; \ OZ (resolve_synonym_object_recursively( \ - schema_checker, synonym_checker, \ + schema_checker, (outer_synonym_checker != NULL) ? *outer_synonym_checker : synonym_checker, \ tenant_id, database_id, synonym_name, \ object_db_id, object_name, exist)); \ if (OB_SUCC(ret) && exist) { \ @@ -1293,7 +1479,8 @@ int ObResolverUtils::get_routine(pl::ObPLPackageGuard &package_guard, const common::ObIArray &expr_params, const ObRoutineInfo *&routine, const ObString &dblink_name, - ObIAllocator *allocator) + ObIAllocator *allocator, + ObSynonymChecker *outer_synonym_checker) { int ret = OB_SUCCESS; #define COPY_DBLINK_ROUTINE(dblink_routine) \ @@ -1332,7 +1519,8 @@ int ObResolverUtils::get_routine(pl::ObPLPackageGuard &package_guard, routine_name, routine_type, expr_params, - tmp_routine_info)); + tmp_routine_info, + outer_synonym_checker)); if (OB_SUCC(ret)) { if (OB_INVALID_ID == tmp_routine_info->get_dblink_id()) { routine = tmp_routine_info; @@ -1433,7 +1621,8 @@ int ObResolverUtils::get_routine(const pl::ObPLResolveCtx &resolve_ctx, const ObString &routine_name, const share::schema::ObRoutineType routine_type, const common::ObIArray &expr_params, - const ObRoutineInfo *&routine) + const ObRoutineInfo *&routine, + ObSynonymChecker *synonym_checker) { int ret = OB_SUCCESS; common::ObSEArray candidate_routine_infos; @@ -1451,7 +1640,8 @@ int ObResolverUtils::get_routine(const pl::ObPLResolveCtx &resolve_ctx, routine_type, candidate_routine_infos, udt_id, - &resolve_ctx))) { + &resolve_ctx, + synonym_checker))) { LOG_WARN("failed to get candidate routine infos", K(db_name), K(package_name), K(routine_name), K(ret)); } else { @@ -1559,6 +1749,7 @@ int ObResolverUtils::resolve_synonym_object_recursively(ObSchemaChecker &schema_ uint64_t synonym_id = OB_INVALID_ID; bool exist_with_synonym = false; bool exist_non_syn_object = false; + bool is_private_syn = false; if (OB_FAIL(schema_checker.get_synonym_schema( tenant_id, database_id, synonym_name, object_database_id, synonym_id, object_name, exist_with_synonym, search_public_schema))) { @@ -1576,7 +1767,10 @@ int ObResolverUtils::resolve_synonym_object_recursively(ObSchemaChecker &schema_ } else if (OB_FAIL(schema_checker.check_exist_same_name_object_with_synonym(tenant_id, object_database_id, object_name, - exist_non_syn_object)) || !exist_non_syn_object) { + exist_non_syn_object, + is_private_syn)) || + !exist_non_syn_object || + is_private_syn) { OZ (SMART_CALL(resolve_synonym_object_recursively( schema_checker, synonym_checker, tenant_id, object_database_id, object_name, object_database_id, object_name, exist_with_synonym, @@ -6904,7 +7098,8 @@ int ObResolverUtils::resolve_string(const ParseNode *node, ObString &string) int ObResolverUtils::set_parallel_info(sql::ObSQLSessionInfo &session_info, share::schema::ObSchemaGetterGuard &schema_guard, ObRawExpr &expr, - ObQueryCtx &ctx) + ObQueryCtx &ctx, + ObIArray &return_value_version) { int ret = OB_SUCCESS; const ObRoutineInfo *routine_info = NULL; @@ -6963,6 +7158,23 @@ int ObResolverUtils::set_parallel_info(sql::ObSQLSessionInfo &session_info, } OX (udf_raw_expr.set_parallel_enable(enable_parallel)); } + if (OB_SUCC(ret) && OB_NOT_NULL(routine_info)) { + ObArenaAllocator alloc; + ObPLDataType param_type; + ObRoutineParam *param = nullptr; + common::ObMySQLProxy *sql_proxy = GCTX.sql_proxy_; + ObArray version; + CK (routine_info->get_routine_params().count() > 0); + OX (param = routine_info->get_routine_params().at(0)); + CK (OB_NOT_NULL(sql_proxy)); + OZ (pl::ObPLDataType::transform_from_iparam(param, + schema_guard, + session_info, + alloc, + *sql_proxy, + param_type, + &return_value_version)); + } } return ret; } diff --git a/src/sql/resolver/ob_resolver_utils.h b/src/sql/resolver/ob_resolver_utils.h index 29a856cefe..cf4d4e9d07 100644 --- a/src/sql/resolver/ob_resolver_utils.h +++ b/src/sql/resolver/ob_resolver_utils.h @@ -23,6 +23,7 @@ #include "sql/parser/parse_node.h" #include "sql/session/ob_sql_session_info.h" #include "pl/ob_pl.h" +#include "pl/ob_pl_stmt.h" #define LOG_WARN_IGNORE_COL_NOTFOUND(ret, fmt, args...) \ do {\ @@ -137,6 +138,23 @@ public: const ObString &column_name, bool& exists); + static int collect_schema_version(share::schema::ObSchemaGetterGuard &schema_guard, + const ObSQLSessionInfo *session_info, + ObRawExpr *expr, + ObIArray &dependency_objects, + bool is_called_in_sql = false, + ObIArray *dep_db_array = NULL); + + static int add_dependency_synonym_object(share::schema::ObSchemaGetterGuard *schema_guard, + const ObSQLSessionInfo *session_info, + const ObSynonymChecker &synonym_checker, + DependenyTableStore &dep_table); + + static int add_dependency_synonym_object(share::schema::ObSchemaGetterGuard *schema_guard, + const ObSQLSessionInfo *session_info, + const ObSynonymChecker &synonym_checker, + const pl::ObPLDependencyTable &dep_table); + static int resolve_extended_type_info(const ParseNode &str_list_node, ObIArray& type_info_array); // type_infos is %ori_cs_type, need convert to %cs_type first @@ -166,7 +184,8 @@ public: const share::schema::ObRoutineType routine_type, common::ObIArray &routines, uint64_t udt_id = OB_INVALID_ID, - const pl::ObPLResolveCtx *resolve_ctx = NULL); + const pl::ObPLResolveCtx *resolve_ctx = NULL, + ObSynonymChecker *synonym_checker = NULL); static int check_routine_exists(const ObSQLSessionInfo *session_info, ObSchemaChecker *schema_checker, pl::ObPLBlockNS *secondary_namespace, @@ -239,7 +258,8 @@ public: const common::ObIArray &expr_params, const share::schema::ObRoutineInfo *&routine, const ObString &dblink_name = ObString(""), - ObIAllocator *allocator = NULL); + ObIAllocator *allocator = NULL, + ObSynonymChecker *synonym_checker = NULL); static int get_routine(const pl::ObPLResolveCtx &resolve_ctx, uint64_t tenant_id, const ObString ¤t_database, @@ -248,7 +268,8 @@ public: const ObString &routine_name, const share::schema::ObRoutineType routine_type, const common::ObIArray &expr_params, - const share::schema::ObRoutineInfo *&routine); + const share::schema::ObRoutineInfo *&routine, + ObSynonymChecker *synonym_checker = NULL); static int resolve_sp_access_name(ObSchemaChecker &schema_checker, ObIAllocator &allocator, uint64_t tenant_id, @@ -289,7 +310,8 @@ public: static int set_parallel_info(sql::ObSQLSessionInfo &session_info, share::schema::ObSchemaGetterGuard &schema_guard, ObRawExpr &expr, - ObQueryCtx &ctx); + ObQueryCtx &ctx, + ObIArray &return_value_version); static int resolve_external_symbol(common::ObIAllocator &allocator, sql::ObRawExprFactory &expr_factory, diff --git a/src/sql/resolver/ob_schema_checker.cpp b/src/sql/resolver/ob_schema_checker.cpp index aa4c587211..efaa4417a9 100644 --- a/src/sql/resolver/ob_schema_checker.cpp +++ b/src/sql/resolver/ob_schema_checker.cpp @@ -2398,10 +2398,12 @@ int ObSchemaChecker::get_object_type_with_view_info(ObIAllocator* allocator, int ObSchemaChecker::check_exist_same_name_object_with_synonym(const uint64_t tenant_id, uint64_t database_id, const common::ObString &object_name, - bool &exist) + bool &exist, + bool &is_private_syn) { int ret = OB_SUCCESS; exist = false; + is_private_syn = false; common::ObString database_name; const ObDatabaseSchema *db_schema = NULL; const share::schema::ObTableSchema *table_schema = NULL; @@ -2483,6 +2485,20 @@ int ObSchemaChecker::check_exist_same_name_object_with_synonym(const uint64_t te exist = true; } } + //check synonym + if (OB_TABLE_NOT_EXIST == ret) { + ObString obj_db_name; + ObString obj_name; + uint64_t synonym_id = OB_INVALID_ID; + uint64_t database_id = OB_INVALID_ID; + ret = OB_SUCCESS; + if (OB_FAIL(get_syn_info(tenant_id, database_name, object_name, obj_db_name, + obj_name, synonym_id, database_id, exist))) { + ret = OB_TABLE_NOT_EXIST; + } else { + is_private_syn = true; + } + } } if (OB_TABLE_NOT_EXIST == ret) { ret = OB_SUCCESS; diff --git a/src/sql/resolver/ob_schema_checker.h b/src/sql/resolver/ob_schema_checker.h index 0508e4f067..371c9d7e67 100644 --- a/src/sql/resolver/ob_schema_checker.h +++ b/src/sql/resolver/ob_schema_checker.h @@ -424,7 +424,8 @@ public: int check_exist_same_name_object_with_synonym(const uint64_t tenant_id, uint64_t database_id, const common::ObString &object_name, - bool &exist); + bool &exist, + bool &is_private_syn); int get_object_type(const uint64_t tenant_id, const common::ObString &database_name, const common::ObString &table_name, diff --git a/src/sql/session/ob_sql_session_info.cpp b/src/sql/session/ob_sql_session_info.cpp index 0781f2a06a..b4d92cc3aa 100644 --- a/src/sql/session/ob_sql_session_info.cpp +++ b/src/sql/session/ob_sql_session_info.cpp @@ -151,6 +151,7 @@ ObSQLSessionInfo::ObSQLSessionInfo(const uint64_t tenant_id) : curr_session_context_size_(0), pl_context_(NULL), pl_can_retry_(true), + plsql_exec_time_(0), #ifdef OB_BUILD_ORACLE_PL pl_debugger_(NULL), #endif @@ -324,6 +325,7 @@ void ObSQLSessionInfo::reset(bool skip_sys_var) curr_session_context_size_ = 0; pl_context_ = NULL; pl_can_retry_ = true; + plsql_exec_time_ = 0; #ifdef OB_BUILD_ORACLE_PL pl_debugger_ = NULL; #endif @@ -1638,6 +1640,25 @@ int ObSQLSessionInfo::make_dbms_cursor(pl::ObDbmsCursorInfo *&cursor, return ret; } +int64_t ObSQLSessionInfo::get_plsql_exec_time() +{ + return (NULL == pl_context_ || 0 == pl_context_->get_exec_stack().count() + || NULL == pl_context_->get_exec_stack().at(pl_context_->get_exec_stack().count()-1)) + ? plsql_exec_time_ + : pl_context_->get_exec_stack().at(pl_context_->get_exec_stack().count()-1)->get_sub_plsql_exec_time(); +} + +void ObSQLSessionInfo::update_pure_sql_exec_time(int64_t elapsed_time) +{ + if (OB_NOT_NULL(pl_context_) + && pl_context_->get_exec_stack().count() > 0 + && OB_NOT_NULL(pl_context_->get_exec_stack().at(pl_context_->get_exec_stack().count()-1))) { + int64_t pos = pl_context_->get_exec_stack().count()-1; + pl::ObPLExecState *state = pl_context_->get_exec_stack().at(pos); + state->add_pure_sql_exec_time(elapsed_time - state->get_sub_plsql_exec_time() - state->get_pure_sql_exec_time()); + } +} + int ObSQLSessionInfo::check_read_only_privilege(const bool read_only, const ObSqlTraits &sql_traits) { @@ -1884,7 +1905,10 @@ const ObAuditRecordData &ObSQLSessionInfo::get_final_audit_record( || EXECUTE_PS_SEND_PIECE == mode || EXECUTE_PS_GET_PIECE == mode || EXECUTE_PS_SEND_LONG_DATA == mode - || EXECUTE_PS_FETCH == mode) { + || EXECUTE_PS_FETCH == mode + || (EXECUTE_PL_EXECUTE == mode && audit_record_.sql_len_ > 0)) { + // spi_cursor_open may not use process_record to set audit_record_.sql_ + // so only EXECUTE_PL_EXECUTE == mode && audit_record_.sql_len_ > 0 do not set sql //ps模式对应的sql在协议层中设置, session的current_query_中没值 // do nothing } else { diff --git a/src/sql/session/ob_sql_session_info.h b/src/sql/session/ob_sql_session_info.h index 03f6ee586e..b17b8d9be8 100644 --- a/src/sql/session/ob_sql_session_info.h +++ b/src/sql/session/ob_sql_session_info.h @@ -966,6 +966,9 @@ public: inline bool get_pl_can_retry() { return pl_can_retry_; } inline void set_pl_can_retry(bool can_retry) { pl_can_retry_ = can_retry; } + void reset_plsql_exec_time() { plsql_exec_time_ = 0; } + void add_plsql_exec_time(int64_t plsql_exec_time) { plsql_exec_time_ += plsql_exec_time; } + CursorCache &get_cursor_cache() { return pl_cursor_cache_; } pl::ObPLCursorInfo *get_cursor(int64_t cursor_id); pl::ObDbmsCursorInfo *get_dbms_cursor(int64_t cursor_id); @@ -1343,6 +1346,8 @@ public: int on_user_disconnect(); virtual void reset_tx_variable(bool reset_next_scope = true); ObOptimizerTraceImpl& get_optimizer_tracer() { return optimizer_tracer_; } + int64_t get_plsql_exec_time(); + void update_pure_sql_exec_time(int64_t elapsed_time); public: bool has_tx_level_temp_table() const { return tx_desc_ && tx_desc_->with_temporary_table(); } void set_affected_rows_is_changed(int64_t affected_rows); @@ -1443,6 +1448,7 @@ private: // otherwise the PL block can be retried in all. // if false == pl_can_retry_, we can only retry query in PL blocks locally bool pl_can_retry_; //标记当前执行的PL是否可以整体重试 + int64_t plsql_exec_time_; #ifdef OB_BUILD_ORACLE_PL pl::debugger::ObPLDebugger *pl_debugger_; // 如果开启了debug, 该字段不为null diff --git a/tools/deploy/mysql_test/r/mysql/information_schema.result b/tools/deploy/mysql_test/r/mysql/information_schema.result index d623d4d4c8..2fa23223cc 100644 --- a/tools/deploy/mysql_test/r/mysql/information_schema.result +++ b/tools/deploy/mysql_test/r/mysql/information_schema.result @@ -374,6 +374,7 @@ select * from information_schema.tables where table_schema in ('oceanbase', 'mys | def | oceanbase | GV$OB_PLAN_CACHE_PLAN_STAT | SYSTEM VIEW | MEMORY | NULL | DYNAMIC | NULL | NULL | NULL | NULL | NULL | NULL | NULL | NULL | NULL | NULL | utf8mb4_general_ci | NULL | NULL | | | def | oceanbase | GV$OB_PLAN_CACHE_REFERENCE_INFO | SYSTEM VIEW | MEMORY | NULL | DYNAMIC | NULL | NULL | NULL | NULL | NULL | NULL | NULL | NULL | NULL | NULL | utf8mb4_general_ci | NULL | NULL | | | def | oceanbase | GV$OB_PLAN_CACHE_STAT | SYSTEM VIEW | MEMORY | NULL | DYNAMIC | NULL | NULL | NULL | NULL | NULL | NULL | NULL | NULL | NULL | NULL | utf8mb4_general_ci | NULL | NULL | | +| def | oceanbase | GV$OB_PL_CACHE_OBJECT | SYSTEM VIEW | MEMORY | NULL | DYNAMIC | NULL | NULL | NULL | NULL | NULL | NULL | NULL | NULL | NULL | NULL | utf8mb4_general_ci | NULL | NULL | | | def | oceanbase | GV$OB_PROCESSLIST | SYSTEM VIEW | MEMORY | NULL | DYNAMIC | NULL | NULL | NULL | NULL | NULL | NULL | NULL | NULL | NULL | NULL | utf8mb4_general_ci | NULL | NULL | | | def | oceanbase | GV$OB_PS_ITEM_INFO | SYSTEM VIEW | MEMORY | NULL | DYNAMIC | NULL | NULL | NULL | NULL | NULL | NULL | NULL | NULL | NULL | NULL | utf8mb4_general_ci | NULL | NULL | | | def | oceanbase | GV$OB_PS_STAT | SYSTEM VIEW | MEMORY | NULL | DYNAMIC | NULL | NULL | NULL | NULL | NULL | NULL | NULL | NULL | NULL | NULL | utf8mb4_general_ci | NULL | NULL | | @@ -439,6 +440,7 @@ select * from information_schema.tables where table_schema in ('oceanbase', 'mys | def | oceanbase | V$OB_PLAN_CACHE_PLAN_STAT | SYSTEM VIEW | MEMORY | NULL | DYNAMIC | NULL | NULL | NULL | NULL | NULL | NULL | NULL | NULL | NULL | NULL | utf8mb4_general_ci | NULL | NULL | | | def | oceanbase | V$OB_PLAN_CACHE_REFERENCE_INFO | SYSTEM VIEW | MEMORY | NULL | DYNAMIC | NULL | NULL | NULL | NULL | NULL | NULL | NULL | NULL | NULL | NULL | utf8mb4_general_ci | NULL | NULL | | | def | oceanbase | V$OB_PLAN_CACHE_STAT | SYSTEM VIEW | MEMORY | NULL | DYNAMIC | NULL | NULL | NULL | NULL | NULL | NULL | NULL | NULL | NULL | NULL | utf8mb4_general_ci | NULL | NULL | | +| def | oceanbase | V$OB_PL_CACHE_OBJECT | SYSTEM VIEW | MEMORY | NULL | DYNAMIC | NULL | NULL | NULL | NULL | NULL | NULL | NULL | NULL | NULL | NULL | utf8mb4_general_ci | NULL | NULL | | | def | oceanbase | V$OB_PROCESSLIST | SYSTEM VIEW | MEMORY | NULL | DYNAMIC | NULL | NULL | NULL | NULL | NULL | NULL | NULL | NULL | NULL | NULL | utf8mb4_general_ci | NULL | NULL | | | def | oceanbase | V$OB_PS_ITEM_INFO | SYSTEM VIEW | MEMORY | NULL | DYNAMIC | NULL | NULL | NULL | NULL | NULL | NULL | NULL | NULL | NULL | NULL | utf8mb4_general_ci | NULL | NULL | | | def | oceanbase | V$OB_PS_STAT | SYSTEM VIEW | MEMORY | NULL | DYNAMIC | NULL | NULL | NULL | NULL | NULL | NULL | NULL | NULL | NULL | NULL | utf8mb4_general_ci | NULL | NULL | | @@ -1745,6 +1747,7 @@ select * from information_schema.tables where table_schema in ('oceanbase', 'mys | def | oceanbase | GV$OB_PLAN_CACHE_PLAN_STAT | SYSTEM VIEW | MEMORY | NULL | DYNAMIC | NULL | NULL | NULL | NULL | NULL | NULL | NULL | NULL | NULL | NULL | utf8mb4_general_ci | NULL | NULL | | | def | oceanbase | GV$OB_PLAN_CACHE_REFERENCE_INFO | SYSTEM VIEW | MEMORY | NULL | DYNAMIC | NULL | NULL | NULL | NULL | NULL | NULL | NULL | NULL | NULL | NULL | utf8mb4_general_ci | NULL | NULL | | | def | oceanbase | GV$OB_PLAN_CACHE_STAT | SYSTEM VIEW | MEMORY | NULL | DYNAMIC | NULL | NULL | NULL | NULL | NULL | NULL | NULL | NULL | NULL | NULL | utf8mb4_general_ci | NULL | NULL | | +| def | oceanbase | GV$OB_PL_CACHE_OBJECT | SYSTEM VIEW | MEMORY | NULL | DYNAMIC | NULL | NULL | NULL | NULL | NULL | NULL | NULL | NULL | NULL | NULL | utf8mb4_general_ci | NULL | NULL | | | def | oceanbase | GV$OB_PROCESSLIST | SYSTEM VIEW | MEMORY | NULL | DYNAMIC | NULL | NULL | NULL | NULL | NULL | NULL | NULL | NULL | NULL | NULL | utf8mb4_general_ci | NULL | NULL | | | def | oceanbase | GV$OB_PS_ITEM_INFO | SYSTEM VIEW | MEMORY | NULL | DYNAMIC | NULL | NULL | NULL | NULL | NULL | NULL | NULL | NULL | NULL | NULL | utf8mb4_general_ci | NULL | NULL | | | def | oceanbase | GV$OB_PS_STAT | SYSTEM VIEW | MEMORY | NULL | DYNAMIC | NULL | NULL | NULL | NULL | NULL | NULL | NULL | NULL | NULL | NULL | utf8mb4_general_ci | NULL | NULL | | @@ -1810,6 +1813,7 @@ select * from information_schema.tables where table_schema in ('oceanbase', 'mys | def | oceanbase | V$OB_PLAN_CACHE_PLAN_STAT | SYSTEM VIEW | MEMORY | NULL | DYNAMIC | NULL | NULL | NULL | NULL | NULL | NULL | NULL | NULL | NULL | NULL | utf8mb4_general_ci | NULL | NULL | | | def | oceanbase | V$OB_PLAN_CACHE_REFERENCE_INFO | SYSTEM VIEW | MEMORY | NULL | DYNAMIC | NULL | NULL | NULL | NULL | NULL | NULL | NULL | NULL | NULL | NULL | utf8mb4_general_ci | NULL | NULL | | | def | oceanbase | V$OB_PLAN_CACHE_STAT | SYSTEM VIEW | MEMORY | NULL | DYNAMIC | NULL | NULL | NULL | NULL | NULL | NULL | NULL | NULL | NULL | NULL | utf8mb4_general_ci | NULL | NULL | | +| def | oceanbase | V$OB_PL_CACHE_OBJECT | SYSTEM VIEW | MEMORY | NULL | DYNAMIC | NULL | NULL | NULL | NULL | NULL | NULL | NULL | NULL | NULL | NULL | utf8mb4_general_ci | NULL | NULL | | | def | oceanbase | V$OB_PROCESSLIST | SYSTEM VIEW | MEMORY | NULL | DYNAMIC | NULL | NULL | NULL | NULL | NULL | NULL | NULL | NULL | NULL | NULL | utf8mb4_general_ci | NULL | NULL | | | def | oceanbase | V$OB_PS_ITEM_INFO | SYSTEM VIEW | MEMORY | NULL | DYNAMIC | NULL | NULL | NULL | NULL | NULL | NULL | NULL | NULL | NULL | NULL | utf8mb4_general_ci | NULL | NULL | | | def | oceanbase | V$OB_PS_STAT | SYSTEM VIEW | MEMORY | NULL | DYNAMIC | NULL | NULL | NULL | NULL | NULL | NULL | NULL | NULL | NULL | NULL | utf8mb4_general_ci | NULL | NULL | | diff --git a/tools/deploy/mysql_test/test_suite/inner_table/r/mysql/desc_sys_views_in_mysql.result b/tools/deploy/mysql_test/test_suite/inner_table/r/mysql/desc_sys_views_in_mysql.result index 13fdc37a1c..27dcf8ba4f 100644 --- a/tools/deploy/mysql_test/test_suite/inner_table/r/mysql/desc_sys_views_in_mysql.result +++ b/tools/deploy/mysql_test/test_suite/inner_table/r/mysql/desc_sys_views_in_mysql.result @@ -5448,6 +5448,56 @@ RECORD_POLICY varchar(32) NO NULL select /*+QUERY_TIMEOUT(60000000)*/ count(*) as cnt from (select * from oceanbase.GV$OB_FLT_TRACE_CONFIG limit 1); cnt 1 +desc oceanbase.GV$OB_PL_CACHE_OBJECT; +Field Type Null Key Default Extra +TENANT_ID bigint(20) NO NULL +SVR_IP varchar(46) NO NULL +SVR_PORT bigint(20) NO NULL +CACHE_OBJECT_ID bigint(20) NO NULL +PARAMETERIZE_TEXT longtext NO NULL +OBJECT_TEXT longtext NO NULL +FIRST_LOAD_TIME timestamp(6) NO NULL +LAST_ACTIVE_TIME timestamp(6) NO NULL +AVG_EXE_USEC bigint(20) NO NULL +SLOWEST_EXE_TIME timestamp(6) NO NULL +SLOWEST_EXE_USEC bigint(20) NO NULL +HIT_COUNT bigint(20) NO NULL +CACHE_OBJ_SIZE bigint(20) NO NULL +EXECUTIONS bigint(20) NO NULL +ELAPSED_TIME bigint(20) unsigned NO NULL +OBJECT_TYPE longtext NO NULL +OBJECT_ID bigint(20) unsigned NO NULL +COMPILE_TIME bigint(20) unsigned NO NULL +SCHEMA_VERSION bigint(20) NO NULL +PS_STMT_ID bigint(20) NO NULL +select /*+QUERY_TIMEOUT(60000000)*/ count(*) as cnt from (select * from oceanbase.GV$OB_PL_CACHE_OBJECT limit 1); +cnt +1 +desc oceanbase.V$OB_PL_CACHE_OBJECT; +Field Type Null Key Default Extra +TENANT_ID bigint(20) NO +SVR_IP varchar(46) NO +SVR_PORT bigint(20) NO +CACHE_OBJECT_ID bigint(20) NO +PARAMETERIZE_TEXT longtext NO +OBJECT_TEXT longtext NO +FIRST_LOAD_TIME timestamp(6) NO +LAST_ACTIVE_TIME timestamp(6) NO +AVG_EXE_USEC bigint(20) NO +SLOWEST_EXE_TIME timestamp(6) NO +SLOWEST_EXE_USEC bigint(20) NO +HIT_COUNT bigint(20) NO +CACHE_OBJ_SIZE bigint(20) NO +EXECUTIONS bigint(20) NO +ELAPSED_TIME bigint(20) unsigned NO +OBJECT_TYPE longtext NO +OBJECT_ID bigint(20) unsigned NO +COMPILE_TIME bigint(20) unsigned NO +SCHEMA_VERSION bigint(20) NO +PS_STMT_ID bigint(20) NO +select /*+QUERY_TIMEOUT(60000000)*/ count(*) as cnt from (select * from oceanbase.V$OB_PL_CACHE_OBJECT limit 1); +cnt +1 desc oceanbase.DBA_OB_RECOVER_TABLE_JOBS; Field Type Null Key Default Extra JOB_ID bigint(20) NO NULL diff --git a/tools/deploy/mysql_test/test_suite/inner_table/r/mysql/desc_sys_views_in_sys.result b/tools/deploy/mysql_test/test_suite/inner_table/r/mysql/desc_sys_views_in_sys.result index 66fa5e2dd5..5f21e3e416 100644 --- a/tools/deploy/mysql_test/test_suite/inner_table/r/mysql/desc_sys_views_in_sys.result +++ b/tools/deploy/mysql_test/test_suite/inner_table/r/mysql/desc_sys_views_in_sys.result @@ -7636,6 +7636,56 @@ RECORD_POLICY varchar(32) NO NULL select /*+QUERY_TIMEOUT(60000000)*/ count(*) as cnt from (select * from oceanbase.GV$OB_FLT_TRACE_CONFIG limit 1); cnt 1 +desc oceanbase.GV$OB_PL_CACHE_OBJECT; +Field Type Null Key Default Extra +TENANT_ID bigint(20) NO NULL +SVR_IP varchar(46) NO NULL +SVR_PORT bigint(20) NO NULL +CACHE_OBJECT_ID bigint(20) NO NULL +PARAMETERIZE_TEXT longtext NO NULL +OBJECT_TEXT longtext NO NULL +FIRST_LOAD_TIME timestamp(6) NO NULL +LAST_ACTIVE_TIME timestamp(6) NO NULL +AVG_EXE_USEC bigint(20) NO NULL +SLOWEST_EXE_TIME timestamp(6) NO NULL +SLOWEST_EXE_USEC bigint(20) NO NULL +HIT_COUNT bigint(20) NO NULL +CACHE_OBJ_SIZE bigint(20) NO NULL +EXECUTIONS bigint(20) NO NULL +ELAPSED_TIME bigint(20) unsigned NO NULL +OBJECT_TYPE longtext NO NULL +OBJECT_ID bigint(20) unsigned NO NULL +COMPILE_TIME bigint(20) unsigned NO NULL +SCHEMA_VERSION bigint(20) NO NULL +PS_STMT_ID bigint(20) NO NULL +select /*+QUERY_TIMEOUT(60000000)*/ count(*) as cnt from (select * from oceanbase.GV$OB_PL_CACHE_OBJECT limit 1); +cnt +1 +desc oceanbase.V$OB_PL_CACHE_OBJECT; +Field Type Null Key Default Extra +TENANT_ID bigint(20) NO +SVR_IP varchar(46) NO +SVR_PORT bigint(20) NO +CACHE_OBJECT_ID bigint(20) NO +PARAMETERIZE_TEXT longtext NO +OBJECT_TEXT longtext NO +FIRST_LOAD_TIME timestamp(6) NO +LAST_ACTIVE_TIME timestamp(6) NO +AVG_EXE_USEC bigint(20) NO +SLOWEST_EXE_TIME timestamp(6) NO +SLOWEST_EXE_USEC bigint(20) NO +HIT_COUNT bigint(20) NO +CACHE_OBJ_SIZE bigint(20) NO +EXECUTIONS bigint(20) NO +ELAPSED_TIME bigint(20) unsigned NO +OBJECT_TYPE longtext NO +OBJECT_ID bigint(20) unsigned NO +COMPILE_TIME bigint(20) unsigned NO +SCHEMA_VERSION bigint(20) NO +PS_STMT_ID bigint(20) NO +select /*+QUERY_TIMEOUT(60000000)*/ count(*) as cnt from (select * from oceanbase.V$OB_PL_CACHE_OBJECT limit 1); +cnt +1 desc oceanbase.CDB_OB_RECOVER_TABLE_JOBS; Field Type Null Key Default Extra TENANT_ID bigint(20) NO NULL diff --git a/tools/deploy/mysql_test/test_suite/inner_table/r/mysql/inner_table_overall.result b/tools/deploy/mysql_test/test_suite/inner_table/r/mysql/inner_table_overall.result index 7668ff675b..5d968a4388 100644 --- a/tools/deploy/mysql_test/test_suite/inner_table/r/mysql/inner_table_overall.result +++ b/tools/deploy/mysql_test/test_suite/inner_table/r/mysql/inner_table_overall.result @@ -1069,6 +1069,8 @@ select 0xffffffffff & table_id, table_name, table_type, database_id, part_num fr 21447 DBA_OB_TENANT_EVENT_HISTORY 1 201001 1 21448 CDB_OB_TENANT_EVENT_HISTORY 1 201001 1 21449 GV$OB_FLT_TRACE_CONFIG 1 201001 1 +21461 GV$OB_PL_CACHE_OBJECT 1 201001 1 +21462 V$OB_PL_CACHE_OBJECT 1 201001 1 21463 CDB_OB_RECOVER_TABLE_JOBS 1 201001 1 21464 DBA_OB_RECOVER_TABLE_JOBS 1 201001 1 21465 CDB_OB_RECOVER_TABLE_JOB_HISTORY 1 201001 1