/**
 * Copyright (c) 2021 OceanBase
 * OceanBase CE is licensed under Mulan PubL v2.
 * You can use this software according to the terms and conditions of the Mulan PubL v2.
 * You may obtain a copy of Mulan PubL v2 at:
 *          http://license.coscl.org.cn/MulanPubL-2.0
 * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
 * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
 * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
 * See the Mulan PubL v2 for more details.
 */

#include "observer/virtual_table/ob_gv_sql.h"
#include "observer/ob_req_time_service.h"

#include "common/object/ob_object.h"

#include "sql/plan_cache/ob_plan_cache_manager.h"
#include "sql/plan_cache/ob_plan_cache.h"
#include "sql/plan_cache/ob_plan_cache_callback.h"
#include "sql/plan_cache/ob_plan_cache_value.h"
#include "sql/plan_cache/ob_plan_cache_util.h"

#include "observer/ob_server_utils.h"
#include "observer/ob_server_struct.h"
#include "share/inner_table/ob_inner_table_schema.h"
#include "sql/plan_cache/ob_cache_object_factory.h"

#include "lib/thread_local/ob_tsi_factory.h"

using namespace oceanbase;
using namespace sql;
using namespace observer;
using namespace common;

ObGVSql::ObGVSql() : plan_id_array_(), plan_id_array_idx_(OB_INVALID_ID), plan_cache_(NULL)
{}

ObGVSql::~ObGVSql()
{}

void ObGVSql::reset()
{
  ObAllPlanCacheBase::reset();
  plan_id_array_.reset();
  plan_id_array_idx_ = OB_INVALID_ID;
  plan_cache_ = NULL;
}

int ObGVSql::inner_open()
{
  int ret = OB_SUCCESS;
  ObPlanCacheManager::ObGetAllCacheKeyOp op(&tenant_id_array_);
  if (OB_UNLIKELY(NULL == pcm_)) {
    ret = OB_NOT_INIT;
    SERVER_LOG(WARN, "pcm_ is NULL", K(ret));
  } else if (OB_FAIL(pcm_->get_plan_cache_map().foreach_refactored(op))) {
    SERVER_LOG(WARN, "fail to traverse pcm", K(ret));
  }
  return ret;
}

int ObGVSql::get_row_from_specified_tenant(uint64_t tenant_id, bool& is_end)
{
  int ret = OB_SUCCESS;
  ObReqTimeGuard req_timeinfo_guard;
  is_end = false;
  if (OB_INVALID_ID == static_cast<uint64_t>(plan_id_array_idx_)) {
    if (OB_UNLIKELY(NULL == pcm_)) {
      ret = OB_NOT_INIT;
      SERVER_LOG(WARN, "pcm_ is NULL", K(ret));
    } else if (OB_UNLIKELY(NULL != plan_cache_)) {
      ret = OB_ERR_UNEXPECTED;
      SERVER_LOG(WARN, "before get_plan_cache, the point of plan_cache must be NULL", K(ret));
    } else if (OB_UNLIKELY(NULL == (plan_cache_ = pcm_->get_plan_cache(tenant_id)))) {
      SERVER_LOG(WARN, "plan cache is null", K(ret));
    } else {
      NG_TRACE(trav_ps_map_start);
      ObPlanCache::PlanStatMap& plan_stats = plan_cache_->get_plan_stat_map();
      ObGetAllPlanIdOp plan_id_op(&plan_id_array_);
      if (OB_FAIL(plan_stats.foreach_refactored(plan_id_op))) {
        SERVER_LOG(WARN, "fail to traverse id2stat_map");
      } else {
        plan_id_array_idx_ = 0;
      }
      NG_TRACE(trav_ps_map_end);
    }
  }
  if (NULL == plan_cache_) {
    // do nothing
    is_end = true;
  } else if (OB_SUCC(ret)) {
    bool is_filled = false;
    while (OB_SUCC(ret) && false == is_filled && false == is_end) {
      if (plan_id_array_idx_ < 0) {
        ret = OB_ERR_UNEXPECTED;
        SERVER_LOG(WARN, "invalid plan_stat_array index", K(plan_id_array_idx_));
      } else if (plan_id_array_idx_ >= plan_id_array_.count()) {
        is_end = true;
        plan_id_array_idx_ = OB_INVALID_ID;
        plan_id_array_.reset();
        if (OB_UNLIKELY(NULL == plan_cache_)) {
          ret = OB_ERR_UNEXPECTED;
          SERVER_LOG(WARN, "plan cache is null", K(ret));
        } else {
          plan_cache_->dec_ref_count();
          plan_cache_ = NULL;
        }
      } else {
        is_end = false;
        uint64_t plan_id = plan_id_array_.at(plan_id_array_idx_);
        ObCacheObject* cache_obj = NULL;
        ++plan_id_array_idx_;
        // plan's reference count increase
        int tmp_ret = plan_cache_->ref_cache_obj(plan_id, GV_SQL_HANDLE, cache_obj);
        // if the plan coresponding to current plan id is expired, ignore it and get next plan.
        if (OB_HASH_NOT_EXIST == tmp_ret) {
          // do nothing;
        } else if (OB_SUCCESS != tmp_ret) {
          ret = tmp_ret;
        } else if (OB_FAIL(fill_cells(cache_obj, *plan_cache_))) {  // plan exist
          SERVER_LOG(WARN, "fail to fill cells", K(cache_obj), K(tenant_id));
        } else {
          is_filled = true;
        }
        if (NULL != cache_obj) {
          ObCacheObjectFactory::free(cache_obj, GV_SQL_HANDLE);
          cache_obj = NULL;
        }
      }
    }  // while end
  }
  SERVER_LOG(DEBUG, "add plan from a tenant", K(ret), K(tenant_id));
  return ret;
}

int ObGVSql::fill_cells(const ObCacheObject* cache_obj, const ObPlanCache& plan_cache)
{
  int ret = OB_SUCCESS;
  const int64_t col_count = output_column_ids_.count();
  ObObj* cells = cur_row_.cells_;
  ObString ipstr;
  ObString stmt;
  const ObPhysicalPlan* plan = NULL;
  if (OB_ISNULL(cache_obj) || OB_ISNULL(allocator_)) {
    ret = OB_INVALID_ARGUMENT;
    SERVER_LOG(WARN, "invalid argument", K(cache_obj), K(ret));
  } else if (cache_obj->is_sql_crsr()) {  // sql plan
    if (OB_ISNULL(plan = dynamic_cast<const ObPhysicalPlan*>(cache_obj))) {
      ret = OB_ERR_UNEXPECTED;
      SERVER_LOG(WARN, "unexpected null plan", K(ret), K(plan));
    }
  } else if (cache_obj->is_pkg() || cache_obj->is_anon() || cache_obj->is_sfc() ||
             cache_obj->is_prcr()) {  // pl package
    // do nothing
  } else {
    ret = OB_ERR_UNEXPECTED;
    SERVER_LOG(WARN, "unexpected cache object type", K(ret));
  }

  for (int64_t i = 0; OB_SUCC(ret) && i < col_count; ++i) {
    uint64_t col_id = output_column_ids_.at(i);
    switch (col_id) {
        // tenant id
      case share::ALL_VIRTUAL_PLAN_STAT_CDE::TENANT_ID: {
        cells[i].set_int(plan_cache.get_tenant_id());
        break;
      }
        // ip
      case share::ALL_VIRTUAL_PLAN_STAT_CDE::SVR_IP: {
        // ip
        ipstr.reset();
        if (OB_FAIL(ObServerUtils::get_server_ip(allocator_, ipstr))) {
          SERVER_LOG(ERROR, "get server ip failed", K(ret));
        } else {
          cells[i].set_varchar(ipstr);
          cells[i].set_collation_type(ObCharset::get_default_collation(ObCharset::get_default_charset()));
        }
        break;
      }
        // port
      case share::ALL_VIRTUAL_PLAN_STAT_CDE::SVR_PORT: {
        // svr_port
        cells[i].set_int(GCTX.self_addr_.get_port());
        break;
      }
      // plan id
      case share::ALL_VIRTUAL_PLAN_STAT_CDE::PLAN_ID: {
        cells[i].set_int(cache_obj->get_object_id());
        break;
      }
        // sql_id
      case share::ALL_VIRTUAL_PLAN_STAT_CDE::SQL_ID: {
        ObString sql_id;
        if (!cache_obj->is_sql_crsr()) {
          cells[i].set_null();
        } else if (OB_FAIL(ob_write_string(*allocator_, plan->stat_.sql_id_, sql_id))) {
          SERVER_LOG(ERROR, "copy sql_id failed", K(ret));
        } else {
          cells[i].set_varchar(sql_id);
          cells[i].set_collation_type(ObCharset::get_default_collation(ObCharset::get_default_charset()));
        }
        break;
      }
      case share::ALL_VIRTUAL_PLAN_STAT_CDE::TYPE: {
        if (cache_obj->is_sql_crsr()) {
          cells[i].set_int(plan->get_plan_type());
        } else {
          cells[i].set_int(cache_obj->get_type());
        }
        break;
      }
      case share::ALL_VIRTUAL_PLAN_STAT_CDE::IS_BIND_SENSITIVE: {
        if (cache_obj->is_sql_crsr()) {
          cells[i].set_int(plan->stat_.is_bind_sensitive_);
        } else {
          cells[i].set_int(0);
        }
        break;
      }
      case share::ALL_VIRTUAL_PLAN_STAT_CDE::IS_BIND_AWARE: {
        if (cache_obj->is_sql_crsr()) {
          cells[i].set_int(plan->stat_.is_bind_aware_);
        } else {
          cells[i].set_int(0);
        }
        break;
      }
      case share::ALL_VIRTUAL_PLAN_STAT_CDE::DB_ID: {
        if (cache_obj->is_sql_crsr()) {
          cells[i].set_uint64(plan->stat_.bl_info_.key_.db_id_);
        } else {
          cells[i].set_uint64(0);
        }
        break;
      }
      case share::ALL_VIRTUAL_PLAN_STAT_CDE::STATEMENT: {
        ObString statement;
        if (cache_obj->is_sql_crsr()) {
          if (OB_FAIL(ob_write_string(*allocator_, ObString(plan->stat_.stmt_len_, plan->stat_.stmt_), statement))) {
            SERVER_LOG(ERROR, "copy statement failed", K(ret));
          } else {
            cells[i].set_lob_value(ObLongTextType, statement.ptr(), static_cast<int32_t>(statement.length()));
            cells[i].set_collation_type(ObCharset::get_default_collation(ObCharset::get_default_charset()));
          }
        } else {
          cells[i].set_null();
        }
        break;
      }
      case share::ALL_VIRTUAL_PLAN_STAT_CDE::QUERY_SQL: {
        if (cache_obj->is_sql_crsr()) {
          ObString tmp_sql;
          tmp_sql = plan->stat_.raw_sql_;
          ObString raw_sql;
          if (OB_FAIL(ob_write_string(*allocator_, tmp_sql, raw_sql))) {
            SERVER_LOG(ERROR, "copy raw_sql failed", K(ret));
          } else {
            cells[i].set_lob_value(ObLongTextType, raw_sql.ptr(), static_cast<int32_t>(raw_sql.length()));
            cells[i].set_collation_type(ObCharset::get_default_collation(ObCharset::get_default_charset()));
          }
        } else {
          cells[i].set_null();
        }
        break;
      }
      case share::ALL_VIRTUAL_PLAN_STAT_CDE::SPECIAL_PARAMS: {
        if (cache_obj->is_sql_crsr()) {
          ObString sp_info_str;
          if (OB_FAIL(ob_write_string(*allocator_, plan->stat_.sp_info_str_, sp_info_str))) {
            SERVER_LOG(ERROR, "copy sp_info_str failed", K(ret));
          } else {
            cells[i].set_varchar(sp_info_str);
            cells[i].set_collation_type(ObCharset::get_default_collation(ObCharset::get_default_charset()));
          }
        } else {
          cells[i].set_null();
        }
        break;
      }
      case share::ALL_VIRTUAL_PLAN_STAT_CDE::PARAM_INFOS: {
        if (cache_obj->is_sql_crsr()) {
          cells[i].set_lob_value(
              ObLongTextType, plan->stat_.param_infos_.ptr(), static_cast<int32_t>(plan->stat_.param_infos_.length()));
          cells[i].set_collation_type(ObCharset::get_default_collation(ObCharset::get_default_charset()));
        } else {
          cells[i].set_null();
        }
        break;
      }
      case share::ALL_VIRTUAL_PLAN_STAT_CDE::SYS_VARS: {
        if (cache_obj->is_sql_crsr()) {
          ObString sys_vars_str;
          if (OB_FAIL(ob_write_string(*allocator_, plan->stat_.sys_vars_str_, sys_vars_str))) {
            SERVER_LOG(ERROR, "copy sys_vars_str failed", K(ret));
          } else {
            cells[i].set_varchar(sys_vars_str);
            cells[i].set_collation_type(ObCharset::get_default_collation(ObCharset::get_default_charset()));
          }
        } else {
          cells[i].set_null();
        }
        break;
      }
      case share::ALL_VIRTUAL_PLAN_STAT_CDE::PLAN_HASH: {
        if (cache_obj->is_sql_crsr()) {
          cells[i].set_uint64(plan->stat_.bl_info_.plan_hash_value_);
        } else {
          cells[i].set_uint64(0);
        }
        break;
      }
      case share::ALL_VIRTUAL_PLAN_STAT_CDE::FIRST_LOAD_TIME: {
        int64_t gen_time = 0;
        if (cache_obj->is_sql_crsr()) {
          gen_time = plan->stat_.gen_time_;
        }
        cells[i].set_timestamp(gen_time);
        break;
      }
      case share::ALL_VIRTUAL_PLAN_STAT_CDE::SCHEMA_VERSION: {
        if (cache_obj->is_sql_crsr()) {
          cells[i].set_int(plan->stat_.schema_version_);
        } else {
          cells[i].set_int(0);
        }
        break;
      }
      case share::ALL_VIRTUAL_PLAN_STAT_CDE::MERGED_VERSION: {
        if (cache_obj->is_sql_crsr()) {
          cells[i].set_int(plan->stat_.merged_version_);
        } else {
          cells[i].set_int(0);
        }
        break;
      }
      case share::ALL_VIRTUAL_PLAN_STAT_CDE::LAST_ACTIVE_TIME: {
        int64_t last_active_time = 0;
        if (cache_obj->is_sql_crsr()) {
          last_active_time = plan->stat_.last_active_time_;
        }
        cells[i].set_timestamp(last_active_time);
        break;
      }
      case share::ALL_VIRTUAL_PLAN_STAT_CDE::AVG_EXE_USEC: {
        if (cache_obj->is_sql_crsr()) {
          if (plan->stat_.execute_times_ != 0) {
            cells[i].set_int(plan->stat_.elapsed_time_ / plan->stat_.execute_times_);
          } else {
            cells[i].set_int(0);
          }
        } else {
          cells[i].set_int(0);
        }
        break;
      }
      case share::ALL_VIRTUAL_PLAN_STAT_CDE::SLOWEST_EXE_TIME: {
        if (cache_obj->is_sql_crsr()) {
          cells[i].set_timestamp(plan->stat_.slowest_exec_time_);
        } else {
          cells[i].set_timestamp(0);
        }
        break;
      }
      case share::ALL_VIRTUAL_PLAN_STAT_CDE::SLOWEST_EXE_USEC: {
        if (cache_obj->is_sql_crsr()) {
          cells[i].set_int(plan->stat_.slowest_exec_usec_);
        } else {
          cells[i].set_int(0);
        }
        break;
      }
      case share::ALL_VIRTUAL_PLAN_STAT_CDE::SLOW_COUNT: {
        if (cache_obj->is_sql_crsr()) {
          cells[i].set_int(plan->stat_.slow_count_);
        } else {
          cells[i].set_int(0);
        }
        break;
      }
      case share::ALL_VIRTUAL_PLAN_STAT_CDE::HIT_COUNT: {
        int64_t hit_count = 0;
        if (cache_obj->is_sql_crsr()) {
          hit_count = plan->stat_.hit_count_;
        }
        cells[i].set_int(hit_count);
        break;
      }
      case share::ALL_VIRTUAL_PLAN_STAT_CDE::PLAN_SIZE: {
        int64_t mem_used = 0;
        if (cache_obj->is_sql_crsr()) {
          mem_used = plan->stat_.mem_used_;
        } else {
          mem_used = cache_obj->get_mem_size();
        }
        cells[i].set_int(mem_used);
        break;
      }
      case share::ALL_VIRTUAL_PLAN_STAT_CDE::EXECUTIONS: {
        if (cache_obj->is_sql_crsr()) {
          cells[i].set_int(plan->stat_.execute_times_);
        } else {
          cells[i].set_int(0);
        }
        break;
      }
      case share::ALL_VIRTUAL_PLAN_STAT_CDE::DISK_READS: {
        if (cache_obj->is_sql_crsr()) {
          cells[i].set_int(plan->stat_.disk_reads_);
        } else {
          cells[i].set_int(0);
        }
        break;
      }
      case share::ALL_VIRTUAL_PLAN_STAT_CDE::DIRECT_WRITES: {
        if (cache_obj->is_sql_crsr()) {
          cells[i].set_int(plan->stat_.direct_writes_);
        } else {
          cells[i].set_int(0);
        }
        break;
      }
      case share::ALL_VIRTUAL_PLAN_STAT_CDE::BUFFER_GETS: {
        if (cache_obj->is_sql_crsr()) {
          cells[i].set_int(plan->stat_.buffer_gets_);
        } else {
          cells[i].set_int(0);
        }
        break;
      }
      case share::ALL_VIRTUAL_PLAN_STAT_CDE::APPLICATION_WAIT_TIME: {
        if (cache_obj->is_sql_crsr()) {
          cells[i].set_uint64(static_cast<uint64_t>(plan->stat_.application_wait_time_));
        } else {
          cells[i].set_uint64(0);
        }
        break;
      }
      case share::ALL_VIRTUAL_PLAN_STAT_CDE::CONCURRENCY_WAIT_TIME: {
        if (cache_obj->is_sql_crsr()) {
          cells[i].set_uint64(static_cast<uint64_t>(plan->stat_.concurrency_wait_time_));
        } else {
          cells[i].set_uint64(0);
        }
        break;
      }
      case share::ALL_VIRTUAL_PLAN_STAT_CDE::USER_IO_WAIT_TIME: {
        if (cache_obj->is_sql_crsr()) {
          cells[i].set_uint64(static_cast<uint64_t>(plan->stat_.user_io_wait_time_));
        } else {
          cells[i].set_uint64(0);
        }
        break;
      }
      case share::ALL_VIRTUAL_PLAN_STAT_CDE::ROWS_PROCESSED: {
        if (cache_obj->is_sql_crsr()) {
          cells[i].set_int(plan->stat_.rows_processed_);
        } else {
          cells[i].set_int(0);
        }
        break;
      }
      case share::ALL_VIRTUAL_PLAN_STAT_CDE::ELAPSED_TIME: {
        if (cache_obj->is_sql_crsr()) {
          cells[i].set_uint64(static_cast<uint64_t>(plan->stat_.elapsed_time_));
        } else {
          cells[i].set_uint64(0);
        }
        break;
      }
      case share::ALL_VIRTUAL_PLAN_STAT_CDE::CPU_TIME: {
        if (cache_obj->is_sql_crsr()) {
          cells[i].set_uint64(static_cast<uint64_t>(plan->stat_.cpu_time_));
        } else {
          cells[i].set_uint64(0);
        }
        break;
      }
      case share::ALL_VIRTUAL_PLAN_STAT_CDE::LARGE_QUERYS: {
        if (cache_obj->is_sql_crsr()) {
          cells[i].set_int(plan->stat_.large_querys_);
        } else {
          cells[i].set_int(0);
        }
        break;
      }
      case share::ALL_VIRTUAL_PLAN_STAT_CDE::DELAYED_LARGE_QUERYS: {
        if (cache_obj->is_sql_crsr()) {
          cells[i].set_int(plan->stat_.delayed_large_querys_);
        } else {
          cells[i].set_int(0);
        }
        break;
      }
      case share::ALL_VIRTUAL_PLAN_STAT_CDE::OUTLINE_VERSION: {
        if (cache_obj->is_sql_crsr()) {
          cells[i].set_int(plan->stat_.outline_version_);
        } else {
          cells[i].set_int(0);
        }
        break;
      }
      case share::ALL_VIRTUAL_PLAN_STAT_CDE::OUTLINE_ID: {
        if (cache_obj->is_sql_crsr()) {
          cells[i].set_int(plan->stat_.outline_id_);
        } else {
          cells[i].set_int(0);
        }
        break;
      }
      case share::ALL_VIRTUAL_PLAN_STAT_CDE::HINTS_INFO: {
        if (cache_obj->is_sql_crsr()) {
          ObString hints_info;
          if (OB_FAIL(ob_write_string(*allocator_, plan->stat_.bl_info_.hints_info_, hints_info))) {
            SERVER_LOG(ERROR, "copy hints_info failed", K(ret));
          } else {
            cells[i].set_lob_value(ObLongTextType, hints_info.ptr(), static_cast<int32_t>(hints_info.length()));
            cells[i].set_collation_type(ObCharset::get_default_collation(ObCharset::get_default_charset()));
          }
        } else {
          cells[i].set_null();
        }
        break;
      }
      case share::ALL_VIRTUAL_PLAN_STAT_CDE::OUTLINE_DATA: {
        if (cache_obj->is_sql_crsr()) {
          ObString outline_data;
          if (OB_FAIL(ob_write_string(*allocator_, plan->stat_.bl_info_.outline_data_, outline_data))) {
            SERVER_LOG(ERROR, "copy outline_data failed", K(ret));
          } else {
            cells[i].set_lob_value(ObLongTextType, outline_data.ptr(), static_cast<int32_t>(outline_data.length()));
            cells[i].set_collation_type(ObCharset::get_default_collation(ObCharset::get_default_charset()));
          }
        } else {
          cells[i].set_null();
        }
        break;
      }
      case share::ALL_VIRTUAL_PLAN_STAT_CDE::ACS_SEL_INFO: {
        if (cache_obj->is_sql_crsr()) {
          stmt.assign_ptr(plan->stat_.plan_sel_info_str_, plan->stat_.plan_sel_info_str_len_);
          cells[i].set_lob_value(ObLongTextType, stmt.ptr(), static_cast<int32_t>(stmt.length()));
          cells[i].set_collation_type(ObCharset::get_default_collation(ObCharset::get_default_charset()));
        } else {
          cells[i].set_null();
        }
        break;
      }
      case share::ALL_VIRTUAL_PLAN_STAT_CDE::TABLE_SCAN: {
        if (cache_obj->is_sql_crsr()) {
          cells[i].set_bool(plan->contain_table_scan());
        } else {
          cells[i].set_bool(false);
        }
        break;
      }
      case share::ALL_VIRTUAL_PLAN_STAT_CDE::EVOLUTION: {
        if (cache_obj->is_sql_crsr()) {
          cells[i].set_bool(plan->get_evolution());
        } else {
          cells[i].set_bool(false);
        }
        break;
      }
      case share::ALL_VIRTUAL_PLAN_STAT_CDE::HINTS_ALL_WORKED: {
        if (cache_obj->is_sql_crsr()) {
          cells[i].set_bool(plan->stat_.bl_info_.hints_all_worked_);
        } else {
          cells[i].set_bool(false);
        }
        break;
      }
      case share::ALL_VIRTUAL_PLAN_STAT_CDE::EVO_EXECUTIONS: {
        if (cache_obj->is_sql_crsr()) {
          cells[i].set_int(plan->stat_.bl_info_.executions_);
        } else {
          cells[i].set_int(0);
        }
        break;
      }
      case share::ALL_VIRTUAL_PLAN_STAT_CDE::EVO_CPU_TIME: {
        if (cache_obj->is_sql_crsr()) {
          cells[i].set_uint64(plan->stat_.bl_info_.cpu_time_);
        } else {
          cells[i].set_uint64(0);
        }
        break;
      }
      case share::ALL_VIRTUAL_PLAN_STAT_CDE::TIMEOUT_COUNT: {
        if (cache_obj->is_sql_crsr()) {
          cells[i].set_int(plan->stat_.timeout_count_);
        } else {
          cells[i].set_int(0);
        }
        break;
      }
      case share::ALL_VIRTUAL_PLAN_STAT_CDE::PS_STMT_ID: {
        if (cache_obj->is_sql_crsr()) {
          cells[i].set_int(plan->stat_.ps_stmt_id_);
        } else {
          cells[i].set_int(OB_INVALID_ID);
        }
        break;
      }
      case share::ALL_VIRTUAL_PLAN_STAT_CDE::DELAYED_PX_QUERYS: {
        if (cache_obj->is_sql_crsr()) {
          cells[i].set_int(plan->stat_.delayed_px_querys_);
        } else {
          cells[i].set_int(0);
        }
        break;
      }
      case share::ALL_VIRTUAL_PLAN_STAT_CDE::SESSID: {
        if (cache_obj->is_sql_crsr()) {
          cells[i].set_uint64(plan->stat_.sessid_);
        } else {
          cells[i].set_uint64(OB_INVALID_ID);
        }
        break;
      }
      case share::ALL_VIRTUAL_PLAN_STAT_CDE::TEMP_TABLES: {
        if (cache_obj->is_sql_crsr()) {
          stmt.assign_ptr(plan->stat_.plan_tmp_tbl_name_str_, plan->stat_.plan_tmp_tbl_name_str_len_);
          cells[i].set_lob_value(ObLongTextType, stmt.ptr(), static_cast<int32_t>(stmt.length()));
          cells[i].set_collation_type(ObCharset::get_default_collation(ObCharset::get_default_charset()));
        } else {
          cells[i].set_null();
        }
        break;
      }
      case share::ALL_VIRTUAL_PLAN_STAT_CDE::IS_USE_JIT: {
        if (cache_obj->is_sql_crsr()) {
          cells[i].set_bool(plan->stat_.is_use_jit_);
        } else {
          cells[i].set_bool(false);
        }
        break;
      }
      case share::ALL_VIRTUAL_PLAN_STAT_CDE::OBJECT_TYPE: {
        ObString type_name;
        if (OB_FAIL(ObCacheObject::type_to_name(cache_obj->get_type(), *allocator_, type_name))) {
          SERVER_LOG(ERROR, "failed to get type_name", K(ret));
        } else {
          // do nothing
        }
        cells[i].set_lob_value(ObLongTextType, type_name.ptr(), static_cast<int32_t>(type_name.length()));
        cells[i].set_collation_type(ObCharset::get_default_collation(ObCharset::get_default_charset()));
        break;
      }
      case share::ALL_VIRTUAL_PLAN_STAT_CDE::ENABLE_BF_CACHE: {
        if (cache_obj->is_sql_crsr()) {
          cells[i].set_bool(plan->stat_.enable_bf_cache_);
        } else {
          cells[i].set_bool(false);
        }
        break;
      }
      case share::ALL_VIRTUAL_PLAN_STAT_CDE::BF_FILTER_CNT: {
        if (cache_obj->is_sql_crsr()) {
          cells[i].set_int(plan->stat_.bf_filter_cnt_);
        } else {
          cells[i].set_int(0);
        }
        break;
      }
      case share::ALL_VIRTUAL_PLAN_STAT_CDE::BF_ACCESS_CNT: {
        if (cache_obj->is_sql_crsr()) {
          cells[i].set_int(plan->stat_.bf_access_cnt_);
        } else {
          cells[i].set_int(0);
        }
        break;
      }
      case share::ALL_VIRTUAL_PLAN_STAT_CDE::ENABLE_ROW_CACHE: {
        if (cache_obj->is_sql_crsr()) {
          cells[i].set_bool(plan->stat_.enable_fuse_row_cache_);
        } else {
          cells[i].set_bool(false);
        }
        break;
      }
      case share::ALL_VIRTUAL_PLAN_STAT_CDE::ROW_CACHE_HIT_CNT: {
        if (cache_obj->is_sql_crsr()) {
          cells[i].set_int(plan->stat_.row_cache_hit_cnt_);
        } else {
          cells[i].set_int(0);
        }
        break;
      }
      case share::ALL_VIRTUAL_PLAN_STAT_CDE::ROW_CACHE_MISS_CNT: {
        if (cache_obj->is_sql_crsr()) {
          cells[i].set_int(plan->stat_.row_cache_miss_cnt_);
        } else {
          cells[i].set_int(0);
        }
        break;
      }
      case share::ALL_VIRTUAL_PLAN_STAT_CDE::ENABLE_FUSE_ROW_CACHE: {
        if (cache_obj->is_sql_crsr()) {
          cells[i].set_bool(plan->stat_.enable_fuse_row_cache_);
        } else {
          cells[i].set_bool(false);
        }
        break;
      }
      case share::ALL_VIRTUAL_PLAN_STAT_CDE::FUSE_ROW_CACHE_HIT_CNT: {
        if (cache_obj->is_sql_crsr()) {
          cells[i].set_int(plan->stat_.fuse_row_cache_hit_cnt_);
        } else {
          cells[i].set_int(0);
        }
        break;
      }
      case share::ALL_VIRTUAL_PLAN_STAT_CDE::FUSE_ROW_CACHE_MISS_CNT: {
        if (cache_obj->is_sql_crsr()) {
          cells[i].set_int(plan->stat_.fuse_row_cache_miss_cnt_);
        } else {
          cells[i].set_int(0);
        }
        break;
      }
      case share::ALL_VIRTUAL_PLAN_STAT_CDE::PL_SCHEMA_ID: {
        break;
      }
      case share::ALL_VIRTUAL_PLAN_STAT_CDE::IS_BATCHED_MULTI_STMT: {
        if (cache_obj->is_sql_crsr()) {
          cells[i].set_bool(plan->get_is_batched_multi_stmt());
        } else {
          cells[i].set_bool(false);
        }
        break;
      }
      default: {
        ret = OB_ERR_UNEXPECTED;
        SERVER_LOG(WARN, "invalid column id", K(ret), K(i), K(output_column_ids_), K(col_id));
        break;
      }
    }
  }  // end for
  return ret;
}

int ObGVSql::get_row_from_tenants()
{
  int ret = OB_SUCCESS;
  bool is_sub_end = false;
  do {
    is_sub_end = false;
    if (tenant_id_array_idx_ < 0) {
      ret = OB_ERR_UNEXPECTED;
      SERVER_LOG(WARN, "invalid tenant_id_array idx", K(ret), K(tenant_id_array_idx_));
    } else if (tenant_id_array_idx_ >= tenant_id_array_.count()) {
      ret = OB_ITER_END;
      tenant_id_array_idx_ = 0;
    } else {
      if (OB_FAIL(get_row_from_specified_tenant(tenant_id_array_.at(tenant_id_array_idx_), is_sub_end))) {
        SERVER_LOG(WARN,
            "fail to insert plan by tenant id",
            K(ret),
            "tenant id",
            tenant_id_array_.at(tenant_id_array_idx_),
            K(tenant_id_array_idx_));
      } else {
        if (is_sub_end) {
          ++tenant_id_array_idx_;
        }
      }
    }
  } while (is_sub_end && OB_SUCCESS == ret);
  return ret;
}
