1765 lines
		
	
	
		
			65 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			1765 lines
		
	
	
		
			65 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
/**
 | 
						|
 * Copyright (c) 2021 OceanBase
 | 
						|
 * OceanBase CE is licensed under Mulan PubL v2.
 | 
						|
 * You can use this software according to the terms and conditions of the Mulan PubL v2.
 | 
						|
 * You may obtain a copy of Mulan PubL v2 at:
 | 
						|
 *          http://license.coscl.org.cn/MulanPubL-2.0
 | 
						|
 * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
 | 
						|
 * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
 | 
						|
 * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
 | 
						|
 * See the Mulan PubL v2 for more details.
 | 
						|
 */
 | 
						|
 | 
						|
#define USING_LOG_PREFIX SERVER
 | 
						|
 | 
						|
#include "ob_inner_sql_connection.h"
 | 
						|
#include "share/ob_worker.h"
 | 
						|
#include "lib/stat/ob_diagnose_info.h"
 | 
						|
#include "lib/profile/ob_trace_id.h"
 | 
						|
#include "common/ob_timeout_ctx.h"
 | 
						|
#include "common/ob_smart_call.h"
 | 
						|
#include "share/ob_debug_sync.h"
 | 
						|
#include "share/ob_time_utility2.h"
 | 
						|
#include "share/schema/ob_multi_version_schema_service.h"
 | 
						|
#include "share/schema/ob_schema_getter_guard.h"
 | 
						|
#include "share/config/ob_server_config.h"
 | 
						|
#include "sql/ob_sql.h"
 | 
						|
#include "sql/ob_sql_partition_location_cache.h"
 | 
						|
#include "sql/ob_sql_trans_util.h"
 | 
						|
#include "sql/resolver/ddl/ob_ddl_stmt.h"
 | 
						|
#include "observer/ob_server.h"
 | 
						|
#include "observer/mysql/ob_mysql_request_manager.h"
 | 
						|
#include "observer/ob_server_struct.h"
 | 
						|
#include "observer/virtual_table/ob_virtual_table_iterator_factory.h"
 | 
						|
#include "observer/ob_req_time_service.h"
 | 
						|
#include "ob_inner_sql_connection_pool.h"
 | 
						|
#include "ob_inner_sql_read_context.h"
 | 
						|
#include "ob_inner_sql_result.h"
 | 
						|
#include "storage/transaction/ob_trans_define.h"  // ObTransIsolation
 | 
						|
#include "sql/resolver/ob_schema_checker.h"
 | 
						|
 | 
						|
namespace oceanbase {
 | 
						|
using namespace common;
 | 
						|
using namespace sql;
 | 
						|
using namespace share;
 | 
						|
using namespace share::schema;
 | 
						|
 | 
						|
namespace observer {
 | 
						|
 | 
						|
constexpr const char ObInnerSQLConnection::LABEL[];
 | 
						|
 | 
						|
class ObInnerSQLConnection::ObSqlQueryExecutor : public sqlclient::ObIExecutor {
 | 
						|
public:
 | 
						|
  explicit ObSqlQueryExecutor(const ObString& sql) : sql_(sql)
 | 
						|
  {}
 | 
						|
  explicit ObSqlQueryExecutor(const char* sql) : sql_(ObString::make_string(sql))
 | 
						|
  {}
 | 
						|
 | 
						|
  virtual ~ObSqlQueryExecutor()
 | 
						|
  {}
 | 
						|
 | 
						|
  virtual int execute(sql::ObSql& engine, sql::ObSqlCtx& ctx, sql::ObResultSet& res) override
 | 
						|
  {
 | 
						|
    observer::ObReqTimeGuard req_timeinfo_guard;
 | 
						|
    int ret = OB_SUCCESS;
 | 
						|
    // Deep copy sql, because sql may be destroyed before result iteration.
 | 
						|
    const int64_t alloc_size = sizeof(ObString) + sql_.length() + 1;  // 1 for C terminate char
 | 
						|
    void *mem = res.get_mem_pool().alloc(alloc_size);
 | 
						|
    if (NULL == mem) {
 | 
						|
      ret = OB_ALLOCATE_MEMORY_FAILED;
 | 
						|
      LOG_WARN("allocate memory failed", K(ret));
 | 
						|
    } else {
 | 
						|
      ObString *dup_sql = new (mem) ObString(sql_.length(), sql_.length(), static_cast<char *>(mem) + sizeof(ObString));
 | 
						|
      MEMCPY(dup_sql->ptr(), sql_.ptr(), sql_.length());
 | 
						|
      dup_sql->ptr()[sql_.length()] = '\0';
 | 
						|
      res.get_session().store_query_string(*dup_sql);
 | 
						|
      ret = engine.stmt_query(*dup_sql, ctx, res);
 | 
						|
    }
 | 
						|
    return ret;
 | 
						|
  }
 | 
						|
 | 
						|
  // process result after result open
 | 
						|
  virtual int process_result(sql::ObResultSet&) override
 | 
						|
  {
 | 
						|
    return OB_SUCCESS;
 | 
						|
  }
 | 
						|
 | 
						|
  INHERIT_TO_STRING_KV("ObIExecutor", ObIExecutor, K_(sql));
 | 
						|
 | 
						|
private:
 | 
						|
  ObString sql_;
 | 
						|
};
 | 
						|
 | 
						|
ObInnerSQLConnection::TimeoutGuard::TimeoutGuard(ObInnerSQLConnection& conn) : conn_(conn)
 | 
						|
{
 | 
						|
  int ret = OB_SUCCESS;
 | 
						|
  worker_timeout_ = THIS_WORKER.get_timeout_ts();
 | 
						|
  if (OB_FAIL(conn_.get_session().get_query_timeout(query_timeout_)) ||
 | 
						|
      OB_FAIL(conn_.get_session().get_tx_timeout(trx_timeout_))) {
 | 
						|
    LOG_ERROR("get timeout failed", K(ret));
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
ObInnerSQLConnection::TimeoutGuard::~TimeoutGuard()
 | 
						|
{
 | 
						|
  int ret = OB_SUCCESS;
 | 
						|
  if (THIS_WORKER.get_timeout_ts() != worker_timeout_) {
 | 
						|
    THIS_WORKER.set_timeout_ts(worker_timeout_);
 | 
						|
  }
 | 
						|
 | 
						|
  int64_t query_timeout = 0;
 | 
						|
  int64_t trx_timeout = 0;
 | 
						|
  if (OB_FAIL(conn_.get_session().get_query_timeout(query_timeout)) ||
 | 
						|
      OB_FAIL(conn_.get_session().get_tx_timeout(trx_timeout))) {
 | 
						|
    LOG_ERROR("get timeout failed", K(ret));
 | 
						|
  } else {
 | 
						|
    if (query_timeout != query_timeout_ || trx_timeout != trx_timeout_) {
 | 
						|
      if (OB_FAIL(conn_.set_session_timeout(query_timeout_, trx_timeout_))) {
 | 
						|
        LOG_ERROR("set session timeout failed", K(ret));
 | 
						|
      }
 | 
						|
    }
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
ObInnerSQLConnection::ObInnerSQLConnection()
 | 
						|
    : inited_(false),
 | 
						|
      inner_session_(),
 | 
						|
      extern_session_(NULL),
 | 
						|
      is_spi_conn_(false),
 | 
						|
      ref_cnt_(0),
 | 
						|
      pool_(NULL),
 | 
						|
      schema_service_(NULL),
 | 
						|
      ob_sql_(NULL),
 | 
						|
      vt_iter_creator_(NULL),
 | 
						|
      ref_ctx_(NULL),
 | 
						|
      partition_table_operator_(NULL),
 | 
						|
      sql_modifier_(NULL),
 | 
						|
      init_timestamp_(0),
 | 
						|
      tid_(-1),
 | 
						|
      bt_size_(0),
 | 
						|
      bt_addrs_(),
 | 
						|
      execute_start_timestamp_(0),
 | 
						|
      execute_end_timestamp_(0),
 | 
						|
      config_(NULL),
 | 
						|
      associated_client_(NULL),
 | 
						|
      primary_schema_versions_()
 | 
						|
{}
 | 
						|
 | 
						|
ObInnerSQLConnection::~ObInnerSQLConnection()
 | 
						|
{
 | 
						|
  if (0 < ref_cnt_) {
 | 
						|
    LOG_ERROR("connection be referenced while destruct", K_(ref_cnt));
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
int ObInnerSQLConnection::init(ObInnerSQLConnectionPool* pool, ObMultiVersionSchemaService* schema_service,
 | 
						|
    ObSql* ob_sql, ObVTIterCreator* vt_iter_creator, const share::ObPartitionTableOperator* partition_table_operator,
 | 
						|
    common::ObServerConfig* config, sql::ObSQLSessionInfo* extern_session, /* = NULL */
 | 
						|
    ObISQLClient* client_addr,                                             /* = NULL */
 | 
						|
    ObRestoreSQLModifier* sql_modifier /* = NULL */)
 | 
						|
{
 | 
						|
  int ret = OB_SUCCESS;
 | 
						|
  if (inited_) {
 | 
						|
    ret = OB_INIT_TWICE;
 | 
						|
    LOG_WARN("connection init twice", K(ret));
 | 
						|
  } else if ((NULL == pool && NULL == sql_modifier) || NULL == schema_service || NULL == ob_sql ||
 | 
						|
             NULL == vt_iter_creator || NULL == partition_table_operator) {
 | 
						|
    ret = OB_INVALID_ARGUMENT;
 | 
						|
    LOG_WARN("schema service should not be NULL",
 | 
						|
        K(ret),
 | 
						|
        KP(sql_modifier),
 | 
						|
        KP(pool),
 | 
						|
        KP(schema_service),
 | 
						|
        KP(ob_sql),
 | 
						|
        KP(vt_iter_creator),
 | 
						|
        KP(partition_table_operator));
 | 
						|
  } else {
 | 
						|
    pool_ = pool;
 | 
						|
    schema_service_ = schema_service;
 | 
						|
    ob_sql_ = ob_sql;
 | 
						|
    vt_iter_creator_ = vt_iter_creator;
 | 
						|
    partition_table_operator_ = partition_table_operator;
 | 
						|
    sql_modifier_ = sql_modifier;
 | 
						|
    init_timestamp_ = ObTimeUtility::current_time();
 | 
						|
    tid_ = GETTID();
 | 
						|
    if (NULL == extern_session) {
 | 
						|
      // Only backtrace internal used connection to avoid performance problems.
 | 
						|
      bt_size_ = backtrace(bt_addrs_, MAX_BT_SIZE);
 | 
						|
    }
 | 
						|
    config_ = config;
 | 
						|
    associated_client_ = client_addr;
 | 
						|
    primary_schema_versions_.reset();
 | 
						|
    if (NULL != client_addr) {
 | 
						|
      oracle_mode_ = client_addr->is_oracle_mode();
 | 
						|
    } else if (NULL != extern_session) {
 | 
						|
      oracle_mode_ = ORACLE_MODE == extern_session->get_compatibility_mode();
 | 
						|
    }
 | 
						|
    if (OB_FAIL(init_session(extern_session))) {
 | 
						|
      LOG_WARN("init session failed", K(ret));
 | 
						|
    } else {
 | 
						|
      inited_ = true;
 | 
						|
    }
 | 
						|
  }
 | 
						|
  return ret;
 | 
						|
}
 | 
						|
 | 
						|
int ObInnerSQLConnection::destroy()
 | 
						|
{
 | 
						|
  int ret = OB_SUCCESS;
 | 
						|
  // uninited connection can be destroy too
 | 
						|
  if (inited_) {
 | 
						|
    if (0 < ref_cnt_) {
 | 
						|
      ret = OB_REF_NUM_NOT_ZERO;
 | 
						|
      LOG_ERROR("connection be referenced while destroy", K(ret), K_(ref_cnt));
 | 
						|
    }
 | 
						|
 | 
						|
    // continue execute while error happen.
 | 
						|
    inited_ = false;
 | 
						|
    ref_cnt_ = 0;
 | 
						|
    pool_ = NULL;
 | 
						|
    schema_service_ = NULL;
 | 
						|
    inner_session_.destroy();
 | 
						|
    extern_session_ = NULL;
 | 
						|
    config_ = NULL;
 | 
						|
    associated_client_ = NULL;
 | 
						|
    primary_schema_versions_.reset();
 | 
						|
    ref_ctx_ = NULL;
 | 
						|
  }
 | 
						|
  return ret;
 | 
						|
}
 | 
						|
 | 
						|
void ObInnerSQLConnection::ref()
 | 
						|
{
 | 
						|
  if (!inited_) {
 | 
						|
    LOG_WARN("not init");
 | 
						|
  } else {
 | 
						|
    ref_cnt_++;
 | 
						|
    if (ref_cnt_ > TOO_MANY_REF_ALERT) {
 | 
						|
      LOG_WARN("connection be referenced too many times, this should be rare", K_(ref_cnt));
 | 
						|
    }
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
void ObInnerSQLConnection::unref()
 | 
						|
{
 | 
						|
  int ret = OB_SUCCESS;
 | 
						|
  if (!inited_) {
 | 
						|
    ret = OB_NOT_INIT;
 | 
						|
    LOG_WARN("not init", K(ret), K(lbt()));
 | 
						|
  } else if (OB_ISNULL(pool_)) {
 | 
						|
    LOG_ERROR("not init conn pool");
 | 
						|
  } else {
 | 
						|
    if (0 == --ref_cnt_) {
 | 
						|
      if (OB_FAIL(pool_->revert(this))) {
 | 
						|
        LOG_WARN("revert connection failed", K(ret));
 | 
						|
      }
 | 
						|
    } else {
 | 
						|
      // extern_session_ = NULL;
 | 
						|
    }
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
int ObInnerSQLConnection::init_session(sql::ObSQLSessionInfo* extern_session)
 | 
						|
{
 | 
						|
  int ret = OB_SUCCESS;
 | 
						|
  if (NULL == extern_session) {
 | 
						|
    // called in init(), can not check inited_ flag.
 | 
						|
    ObArenaAllocator* allocator = NULL;
 | 
						|
    const bool print_info_log = false;
 | 
						|
    const bool is_sys_tenant = true;
 | 
						|
    ObPCMemPctConf pc_mem_conf;
 | 
						|
    inner_session_.set_inner_session();
 | 
						|
    ObObj mysql_mode;
 | 
						|
    ObObj oracle_mode;
 | 
						|
    mysql_mode.set_int(0);
 | 
						|
    oracle_mode.set_int(1);
 | 
						|
    ObObj mysql_sql_mode;
 | 
						|
    ObObj oracle_sql_mode;
 | 
						|
    mysql_sql_mode.set_uint(ObUInt64Type, DEFAULT_MYSQL_MODE);
 | 
						|
    oracle_sql_mode.set_uint(ObUInt64Type, DEFAULT_ORACLE_MODE);
 | 
						|
    if (OB_FAIL(inner_session_.init(INNER_SQL_SESS_VERSION, INNER_SQL_SESS_ID, INNER_SQL_PROXY_SESS_ID, allocator))) {
 | 
						|
      LOG_WARN("init session failed", K(ret));
 | 
						|
    } else if (OB_FAIL(inner_session_.load_default_sys_variable(print_info_log, is_sys_tenant))) {
 | 
						|
      LOG_WARN("session load default system variable failed", K(ret));
 | 
						|
    } else if (OB_FAIL(inner_session_.update_max_packet_size())) {
 | 
						|
      LOG_WARN("fail to update max packet size", K(ret));
 | 
						|
    } else if (OB_FAIL(inner_session_.init_tenant(OB_SYS_TENANT_NAME, OB_SYS_TENANT_ID))) {
 | 
						|
      LOG_WARN("fail to init tenant", K(ret));
 | 
						|
    } else if (OB_FAIL(switch_tenant(OB_SYS_TENANT_ID))) {
 | 
						|
      LOG_WARN("set system tenant id failed", K(ret));
 | 
						|
    } else if (OB_FAIL(inner_session_.update_sys_variable(
 | 
						|
                   SYS_VAR_SQL_MODE, oracle_mode_ ? oracle_sql_mode : mysql_sql_mode))) {
 | 
						|
      LOG_WARN("update sys variables failed", K(ret));
 | 
						|
    } else if (OB_FAIL(inner_session_.update_sys_variable(
 | 
						|
                   SYS_VAR_OB_COMPATIBILITY_MODE, oracle_mode_ ? oracle_mode : mysql_mode))) {
 | 
						|
      LOG_WARN("update sys variables failed", K(ret));
 | 
						|
    } else if (OB_FAIL(inner_session_.update_sys_variable(
 | 
						|
                   SYS_VAR_NLS_DATE_FORMAT, ObTimeConverter::COMPAT_OLD_NLS_DATE_FORMAT))) {
 | 
						|
      LOG_WARN("update sys variables failed", K(ret));
 | 
						|
    } else if (OB_FAIL(inner_session_.update_sys_variable(
 | 
						|
                   SYS_VAR_NLS_TIMESTAMP_FORMAT, ObTimeConverter::COMPAT_OLD_NLS_TIMESTAMP_FORMAT))) {
 | 
						|
      LOG_WARN("update sys variables failed", K(ret));
 | 
						|
    } else if (OB_FAIL(inner_session_.update_sys_variable(
 | 
						|
                   SYS_VAR_NLS_TIMESTAMP_TZ_FORMAT, ObTimeConverter::COMPAT_OLD_NLS_TIMESTAMP_TZ_FORMAT))) {
 | 
						|
      LOG_WARN("update sys variables failed", K(ret));
 | 
						|
    } else {
 | 
						|
      ObString database_name(OB_SYS_DATABASE_NAME);
 | 
						|
      if (OB_FAIL(inner_session_.set_default_database(database_name))) {
 | 
						|
        LOG_WARN("fail to set default database", K(ret), K(database_name));
 | 
						|
      } else if (OB_FAIL(inner_session_.get_pc_mem_conf(pc_mem_conf))) {
 | 
						|
        LOG_WARN("fail to get pc mem conf", K(ret));
 | 
						|
      } else {
 | 
						|
        inner_session_.set_plan_cache_manager(ob_sql_->get_plan_cache_manager());
 | 
						|
        inner_session_.set_database_id(combine_id(OB_SYS_TENANT_ID, OB_SYS_DATABASE_ID));
 | 
						|
        inner_session_.set_use_static_typing_engine(false);
 | 
						|
      }
 | 
						|
    }
 | 
						|
  } else {
 | 
						|
    extern_session_ = extern_session;
 | 
						|
  }
 | 
						|
  return ret;
 | 
						|
}
 | 
						|
 | 
						|
int ObInnerSQLConnection::init_result(ObInnerSQLResult& res, ObVirtualTableIteratorFactory* vt_iter_factory,
 | 
						|
    int64_t retry_cnt, ObSchemaGetterGuard& schema_guard, bool is_prepare_protocol, bool is_prepare_stage,
 | 
						|
    bool is_from_pl, bool is_dynamic_sql, bool is_dbms_sql, bool is_cursor)
 | 
						|
{
 | 
						|
  int ret = OB_SUCCESS;
 | 
						|
  sql::ObResultSet& result_set = res.result_set();
 | 
						|
  const ObGlobalContext& gctx = ObServer::get_instance().get_gctx();
 | 
						|
  result_set.init_partition_location_cache(gctx.location_cache_, gctx.self_addr_, &schema_guard);
 | 
						|
  result_set.get_exec_context().get_task_exec_ctx().set_min_cluster_version(GET_MIN_CLUSTER_VERSION());
 | 
						|
  result_set.get_exec_context().get_task_exec_ctx().schema_service_ = gctx.schema_service_;
 | 
						|
  res.sql_ctx().retry_times_ = retry_cnt;
 | 
						|
  res.sql_ctx().merged_version_ = *(gctx.merged_version_);
 | 
						|
  res.sql_ctx().vt_iter_factory_ = vt_iter_factory;
 | 
						|
  res.sql_ctx().session_info_ = &get_session();
 | 
						|
  res.sql_ctx().sql_proxy_ = gctx.sql_proxy_;
 | 
						|
  res.sql_ctx().use_plan_cache_ = true;
 | 
						|
  res.sql_ctx().disable_privilege_check_ = is_from_pl ? PRIV_CHECK_FLAG_IN_PL : PRIV_CHECK_FLAG_DISABLE;
 | 
						|
  res.sql_ctx().partition_table_operator_ = partition_table_operator_;
 | 
						|
  res.sql_ctx().partition_location_cache_ = &(result_set.get_partition_location_cache());
 | 
						|
  res.sql_ctx().part_mgr_ = gctx.part_mgr_;
 | 
						|
  res.sql_ctx().is_prepare_protocol_ = is_prepare_protocol;
 | 
						|
  res.sql_ctx().is_prepare_stage_ = is_prepare_stage;
 | 
						|
  res.sql_ctx().is_dynamic_sql_ = is_dynamic_sql;
 | 
						|
  res.sql_ctx().is_dbms_sql_ = is_dbms_sql;
 | 
						|
  res.sql_ctx().is_cursor_ = is_cursor;
 | 
						|
  if (FALSE_IT(res.sql_ctx().schema_guard_ = &schema_guard)) {
 | 
						|
    // do-nothing
 | 
						|
  } else if (NULL == res.sql_ctx().partition_table_operator_) {
 | 
						|
    ret = OB_ERR_UNEXPECTED;
 | 
						|
    LOG_WARN("partition table operator is NULL!", K(ret));
 | 
						|
  } else if (OB_FAIL(res.result_set().init())) {
 | 
						|
    LOG_WARN("result set init failed", K(ret));
 | 
						|
  } else if (is_prepare_protocol && !is_dynamic_sql) {
 | 
						|
    result_set.set_simple_ps_protocol();
 | 
						|
  } else { /*do nothing*/
 | 
						|
  }
 | 
						|
  return ret;
 | 
						|
}
 | 
						|
 | 
						|
int ObInnerSQLConnection::process_retry(
 | 
						|
    ObInnerSQLResult& res, int& last_ret, int64_t abs_timeout_us, bool& need_retry, int64_t retry_cnt, bool is_from_pl)
 | 
						|
{
 | 
						|
  int ret = last_ret;
 | 
						|
  sql::ObResultSet& result_set = res.result_set();
 | 
						|
  bool is_direct_local_plan_retry = result_set.get_exec_context().get_direct_local_plan() &&
 | 
						|
                                    (OB_NOT_MASTER == last_ret || OB_PARTITION_NOT_EXIST == last_ret);
 | 
						|
  ObQueryRetryInfo& retry_info = inner_session_.get_retry_info_for_update();
 | 
						|
  const bool non_blocking_refresh = false;
 | 
						|
  bool repeatable_stmt =
 | 
						|
      (ObStmt::is_dml_stmt(result_set.get_stmt_type()) ||
 | 
						|
          ObStmt::is_ddl_stmt(result_set.get_stmt_type(), result_set.has_global_variable()) ||
 | 
						|
          ObStmt::is_dcl_stmt(result_set.get_stmt_type()) || ObStmt::is_execute_stmt(result_set.get_stmt_type()));
 | 
						|
  int64_t now = ObTimeUtility::current_time();
 | 
						|
  if (now >= abs_timeout_us) {
 | 
						|
    ret = OB_TIMEOUT;
 | 
						|
    LOG_WARN("timeout, do not need retry", K(ret), K(last_ret), K(abs_timeout_us), K(now));
 | 
						|
    if (retry_info.is_rpc_timeout() || is_transaction_rpc_timeout_err(last_ret)) {
 | 
						|
      int err1 = result_set.refresh_location_cache(true);
 | 
						|
      if (OB_SUCCESS != err1) {
 | 
						|
        LOG_WARN("fail to nonblock refresh location cache", K(ret), K(last_ret), K(err1));
 | 
						|
      }
 | 
						|
      LOG_WARN("sql rpc timeout, or trans rpc timeout, maybe location is changed, "
 | 
						|
               "refresh location cache non blockly",
 | 
						|
          K(ret),
 | 
						|
          K(last_ret),
 | 
						|
          K(retry_info.is_rpc_timeout()));
 | 
						|
    }
 | 
						|
  } else if (repeatable_stmt && did_no_retry_on_rpc_error_ &&
 | 
						|
             (retry_info.is_rpc_timeout() || is_transaction_rpc_timeout_err(last_ret) ||
 | 
						|
                 is_server_down_error(last_ret) || is_master_changed_error(last_ret))) {
 | 
						|
    ret = OB_TIMEOUT;
 | 
						|
    LOG_INFO("YZFDEBUG no retry for rpc error",
 | 
						|
        K(ret),
 | 
						|
        K(abs_timeout_us),
 | 
						|
        K(now),
 | 
						|
        K(retry_cnt),
 | 
						|
        K(last_ret),
 | 
						|
        K(is_direct_local_plan_retry));
 | 
						|
    if (!is_direct_local_plan_retry) {
 | 
						|
      int err1 = result_set.refresh_location_cache(true);
 | 
						|
      if (OB_SUCCESS != err1) {
 | 
						|
        LOG_WARN("fail to nonblock refresh location cache", K(ret), K(last_ret), K(err1));
 | 
						|
      }
 | 
						|
    }
 | 
						|
  } else if (repeatable_stmt && is_try_lock_row_err(last_ret) && is_from_pl) {
 | 
						|
    if (retry_cnt <= 0 || !get_session().get_pl_can_retry()) {
 | 
						|
      need_retry = true;
 | 
						|
    } else {
 | 
						|
      need_retry = false;
 | 
						|
      ret = last_ret;
 | 
						|
    }
 | 
						|
  } else if (is_schema_error(last_ret) && result_set.is_user_sql()) {
 | 
						|
    if ((OB_ERR_WAIT_REMOTE_SCHEMA_REFRESH == last_ret) || (OB_SCHEMA_NOT_UPTODATE == last_ret) ||
 | 
						|
        (OB_SCHEMA_ERROR == last_ret) || (OB_SCHEMA_EAGAIN == last_ret)) {
 | 
						|
      need_retry = true;
 | 
						|
      LOG_WARN("schema err, need to retry", K(last_ret));
 | 
						|
    } else {
 | 
						|
      LOG_WARN("schema err, but not need to retry", K(last_ret));
 | 
						|
    }
 | 
						|
  } else if (repeatable_stmt &&
 | 
						|
             (is_master_changed_error(last_ret) || is_partition_change_error(last_ret) ||
 | 
						|
                 is_server_down_error(last_ret) || is_process_timeout_error(last_ret) ||
 | 
						|
                 is_get_location_timeout_error(last_ret) || is_try_lock_row_err(last_ret) ||
 | 
						|
                 is_has_no_readable_replica_err(last_ret) || is_select_dup_follow_replic_err(last_ret) ||
 | 
						|
                 is_trans_stmt_need_retry_error(last_ret) || is_transaction_set_violation_err(last_ret) ||
 | 
						|
                 is_snapshot_discarded_err(last_ret))) {
 | 
						|
    need_retry = true;
 | 
						|
    const uint64_t* trace_id = ObCurTraceId::get();
 | 
						|
    bool sql_trigger_by_user_req = (NULL != trace_id && 0 != trace_id[0] && 0 != trace_id[1]);
 | 
						|
    if (is_location_leader_not_exist_error(last_ret) || is_has_no_readable_replica_err(last_ret)) {
 | 
						|
      // retry_info.reset();
 | 
						|
      retry_info.clear();
 | 
						|
    }
 | 
						|
    if (!is_try_lock_row_err(last_ret)) {
 | 
						|
      LOG_INFO("sql execute need retry", K(ret), K(last_ret), K(retry_cnt), K(is_direct_local_plan_retry));
 | 
						|
      if (!is_direct_local_plan_retry && OB_FAIL(result_set.refresh_location_cache(non_blocking_refresh))) {
 | 
						|
        LOG_WARN("refresh location cache failed", K(ret), K(last_ret));
 | 
						|
      }
 | 
						|
    }
 | 
						|
    if (sql_trigger_by_user_req) {
 | 
						|
      const int64_t step = 1000 * 10;  // 10ms
 | 
						|
      const int64_t max = 100;         // cost constant time after max retry_cnt
 | 
						|
      const int64_t sleep_time_us = (retry_cnt < max ? retry_cnt : max) * step;
 | 
						|
      LOG_INFO("sql execute need retry", K(ret), K(last_ret), K(retry_cnt), K(sleep_time_us));
 | 
						|
      THIS_WORKER.sched_wait();
 | 
						|
      usleep(static_cast<unsigned int>(sleep_time_us));
 | 
						|
      THIS_WORKER.sched_run();
 | 
						|
    }
 | 
						|
  } else if (repeatable_stmt && is_data_not_readable_err(last_ret)) {
 | 
						|
    need_retry = true;
 | 
						|
    const int64_t step = 1000 * 10;  // 10ms
 | 
						|
    const int64_t max = 10;          // cost constant time after max retry_cnt, so max sleep time is 100ms
 | 
						|
    const int64_t sleep_time_us = (retry_cnt < max ? retry_cnt : max) * step;
 | 
						|
    usleep(static_cast<unsigned int>(sleep_time_us));
 | 
						|
 | 
						|
    LOG_WARN("has read not readable data, retry in local thread",
 | 
						|
        K(need_retry),
 | 
						|
        K(ret),
 | 
						|
        K(last_ret),
 | 
						|
        K(retry_cnt),
 | 
						|
        K(sleep_time_us));
 | 
						|
  } else if (repeatable_stmt && is_gts_not_ready_err(last_ret)) {
 | 
						|
    const int64_t sleep_time_us = 10 * 1000;  // 10ms
 | 
						|
    need_retry = true;
 | 
						|
    LOG_WARN("gts is not ready, need retry", K(ret), K(last_ret), K(retry_cnt));
 | 
						|
    THIS_WORKER.sched_wait();
 | 
						|
    usleep(static_cast<unsigned int>(sleep_time_us));
 | 
						|
    THIS_WORKER.sched_run();
 | 
						|
  } else if (repeatable_stmt && OB_AUTOINC_SERVICE_BUSY == last_ret) {
 | 
						|
    const int64_t sleep_time_us = 10 * 1000;  // 10ms
 | 
						|
    need_retry = true;
 | 
						|
    LOG_WARN("conncurrent update autoinc cache, need retry", K(ret), K(last_ret), K(retry_cnt));
 | 
						|
    THIS_WORKER.sched_wait();
 | 
						|
    usleep(static_cast<unsigned int>(sleep_time_us));
 | 
						|
    THIS_WORKER.sched_run();
 | 
						|
  } else if (repeatable_stmt && is_scheduler_thread_not_enough_err(last_ret)) {
 | 
						|
    const int64_t sleep_time_us = 10 * 1000; // 10ms
 | 
						|
    need_retry = true;
 | 
						|
    LOG_WARN("scheduler thread not enough, need retry", K(ret), K(last_ret), K(retry_cnt));
 | 
						|
    THIS_WORKER.sched_wait();
 | 
						|
    usleep(static_cast<unsigned int>(sleep_time_us));
 | 
						|
    THIS_WORKER.sched_run();
 | 
						|
  }
 | 
						|
  if (get_session().is_nested_session()) {
 | 
						|
    /**
 | 
						|
     * right now, top session will retry, bug we can do something here like refresh XXX cache.
 | 
						|
     * in future, nested session can retry if nested transaction is supported.
 | 
						|
     */
 | 
						|
    need_retry = false;
 | 
						|
    ret = last_ret;
 | 
						|
  }
 | 
						|
  if (need_retry) {
 | 
						|
    LOG_WARN("need retry, set ret to OB_SUCCESS", K(ret), K(last_ret), K(retry_cnt));
 | 
						|
    retry_info.set_last_query_retry_err(last_ret);
 | 
						|
    if (OB_ISNULL(extern_session_)) {
 | 
						|
    } else {
 | 
						|
      extern_session_->get_retry_info_for_update().set_last_query_retry_err(last_ret);
 | 
						|
    }
 | 
						|
    ret = OB_SUCCESS;
 | 
						|
  }
 | 
						|
  return ret;
 | 
						|
}
 | 
						|
 | 
						|
class ObInnerSQLTimeRecord : public ObITimeRecord {
 | 
						|
public:
 | 
						|
  ObInnerSQLTimeRecord(sql::ObSQLSessionInfo& session)
 | 
						|
      : session_(session), execute_start_timestamp_(0), execute_end_timestamp_(0)
 | 
						|
  {}
 | 
						|
 | 
						|
  int64_t get_send_timestamp() const
 | 
						|
  {
 | 
						|
    return session_.get_query_start_time();
 | 
						|
  }
 | 
						|
  int64_t get_receive_timestamp() const
 | 
						|
  {
 | 
						|
    return session_.get_query_start_time();
 | 
						|
  }
 | 
						|
  int64_t get_enqueue_timestamp() const
 | 
						|
  {
 | 
						|
    return session_.get_query_start_time();
 | 
						|
  }
 | 
						|
  int64_t get_run_timestamp() const
 | 
						|
  {
 | 
						|
    return session_.get_query_start_time();
 | 
						|
  }
 | 
						|
  int64_t get_process_timestamp() const
 | 
						|
  {
 | 
						|
    return session_.get_query_start_time();
 | 
						|
  }
 | 
						|
  int64_t get_single_process_timestamp() const
 | 
						|
  {
 | 
						|
    return session_.get_query_start_time();
 | 
						|
  }
 | 
						|
  int64_t get_exec_start_timestamp() const
 | 
						|
  {
 | 
						|
    return execute_start_timestamp_;
 | 
						|
  }
 | 
						|
  int64_t get_exec_end_timestamp() const
 | 
						|
  {
 | 
						|
    return execute_end_timestamp_;
 | 
						|
  }
 | 
						|
 | 
						|
  void set_execute_start_timestamp(int64_t v)
 | 
						|
  {
 | 
						|
    execute_start_timestamp_ = v;
 | 
						|
  }
 | 
						|
  void set_execute_end_timestamp(int64_t v)
 | 
						|
  {
 | 
						|
    execute_end_timestamp_ = v;
 | 
						|
  }
 | 
						|
 | 
						|
private:
 | 
						|
  sql::ObSQLSessionInfo& session_;
 | 
						|
  int64_t execute_start_timestamp_;
 | 
						|
  int64_t execute_end_timestamp_;
 | 
						|
};
 | 
						|
 | 
						|
int ObInnerSQLConnection::process_record(ObInnerSQLResult& res, sql::ObSQLSessionInfo& session,
 | 
						|
    ObITimeRecord& time_record, int last_ret, int64_t execution_id, int64_t ps_stmt_id, int64_t routine_id,
 | 
						|
    ObWaitEventDesc& max_wait_desc, ObWaitEventStat& total_wait_desc, ObExecRecord& exec_record,
 | 
						|
    ObExecTimestamp& exec_timestamp, bool is_from_pl)
 | 
						|
{
 | 
						|
  int ret = OB_SUCCESS;
 | 
						|
 | 
						|
  UNUSED(routine_id);
 | 
						|
  sql::ObResultSet& result_set = res.result_set();
 | 
						|
  ObAuditRecordData& audit_record = session.get_audit_record();
 | 
						|
  ObPhysicalPlan* plan = res.result_set().get_physical_plan();
 | 
						|
  audit_record.seq_ = 0;  // don't use now
 | 
						|
  audit_record.status_ = (0 == last_ret || OB_ITER_END == last_ret) ? obmysql::REQUEST_SUCC : last_ret;
 | 
						|
 | 
						|
  audit_record.client_addr_ = session.get_peer_addr();
 | 
						|
  audit_record.user_client_addr_ = session.get_user_client_addr();
 | 
						|
  audit_record.user_group_ = THIS_WORKER.get_group_id();
 | 
						|
  audit_record.execution_id_ = execution_id;
 | 
						|
  audit_record.ps_stmt_id_ = ps_stmt_id;
 | 
						|
  MEMCPY(audit_record.sql_id_, res.sql_ctx().sql_id_, (int32_t)sizeof(audit_record.sql_id_));
 | 
						|
  audit_record.affected_rows_ = res.result_set().get_affected_rows();
 | 
						|
  audit_record.return_rows_ = res.result_set().get_return_rows();
 | 
						|
  if (NULL != res.result_set().get_exec_context().get_task_executor_ctx()) {
 | 
						|
    audit_record.partition_cnt_ = res.result_set().get_exec_context().get_task_executor_ctx()->get_related_part_cnt();
 | 
						|
  }
 | 
						|
 | 
						|
  exec_record.max_wait_event_ = max_wait_desc;
 | 
						|
  exec_record.wait_time_end_ = total_wait_desc.time_waited_;
 | 
						|
  exec_record.wait_count_end_ = total_wait_desc.total_waits_;
 | 
						|
 | 
						|
  if (NULL != res.result_set().get_physical_plan()) {
 | 
						|
    audit_record.plan_type_ = res.result_set().get_physical_plan()->get_plan_type();
 | 
						|
    audit_record.table_scan_ = res.result_set().get_physical_plan()->contain_table_scan();
 | 
						|
    audit_record.plan_id_ = res.result_set().get_physical_plan()->get_plan_id();
 | 
						|
    audit_record.plan_hash_ = res.result_set().get_physical_plan()->get_plan_hash_value();
 | 
						|
  }
 | 
						|
 | 
						|
  audit_record.is_executor_rpc_ = false;
 | 
						|
  audit_record.is_inner_sql_ = true;
 | 
						|
  audit_record.is_hit_plan_cache_ = res.result_set().get_is_from_plan_cache();
 | 
						|
  audit_record.is_multi_stmt_ = false;  // if multi sql
 | 
						|
  audit_record.trans_hash_ = session.get_trans_desc().get_trans_id().hash();
 | 
						|
 | 
						|
  bool first_record = (0 == audit_record.try_cnt_);
 | 
						|
  ObExecStatUtils::record_exec_timestamp(time_record, first_record, exec_timestamp);
 | 
						|
  audit_record.exec_timestamp_ = exec_timestamp;
 | 
						|
  audit_record.exec_record_ = exec_record;
 | 
						|
 | 
						|
  ObIArray<ObTableRowCount>* table_row_count_list = NULL;
 | 
						|
  ObPhysicalPlanCtx* plan_ctx = GET_PHY_PLAN_CTX(res.result_set().get_exec_context());
 | 
						|
  if (NULL != plan_ctx) {
 | 
						|
    audit_record.consistency_level_ = plan_ctx->get_consistency_level();
 | 
						|
    audit_record.table_scan_stat_ = plan_ctx->get_table_scan_stat();
 | 
						|
    table_row_count_list = &(plan_ctx->get_table_row_count_list());
 | 
						|
  }
 | 
						|
 | 
						|
  audit_record.tenant_id_ = session.get_effective_tenant_id();
 | 
						|
  audit_record.update_stage_stat();
 | 
						|
 | 
						|
  // update v$sql statistics
 | 
						|
  if (OB_SUCC(last_ret) && session.get_local_ob_enable_plan_cache()) {
 | 
						|
    if (NULL != plan) {
 | 
						|
      if (!(res.sql_ctx().self_add_plan_) && res.sql_ctx().plan_cache_hit_) {
 | 
						|
        plan->update_plan_stat(audit_record,
 | 
						|
            false,  // false mean not first update plan stat
 | 
						|
            res.result_set().get_exec_context().get_is_evolution(),
 | 
						|
            table_row_count_list);
 | 
						|
      } else if (res.sql_ctx().self_add_plan_ && !res.sql_ctx().plan_cache_hit_) {
 | 
						|
        plan->update_plan_stat(
 | 
						|
            audit_record, true, res.result_set().get_exec_context().get_is_evolution(), table_row_count_list);
 | 
						|
      }
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  record_stat(session, result_set.get_stmt_type(), is_from_pl);
 | 
						|
  ObSQLUtils::handle_audit_record(false, EXECUTE_INNER, session, res.result_set().get_exec_context());
 | 
						|
  return ret;
 | 
						|
}
 | 
						|
 | 
						|
template <typename T>
 | 
						|
int ObInnerSQLConnection::process_final(const T& sql, ObInnerSQLResult& res, int last_ret)
 | 
						|
{
 | 
						|
  int ret = OB_SUCCESS;
 | 
						|
  UNUSED(res);
 | 
						|
  if (lib::is_diagnose_info_enabled()) {
 | 
						|
    int64_t process_time = ObTimeUtility::current_time() - get_session().get_query_start_time();
 | 
						|
    if (OB_SUCC(last_ret)) {
 | 
						|
      const int64_t now = ObTimeUtility::current_time();
 | 
						|
      EVENT_INC(INNER_SQL_CONNECTION_EXECUTE_COUNT);
 | 
						|
      EVENT_ADD(INNER_SQL_CONNECTION_EXECUTE_TIME, now - get_session().get_query_start_time());
 | 
						|
    }
 | 
						|
 | 
						|
    if (process_time > 1L * 1000 * 1000) {
 | 
						|
      LOG_INFO("slow inner sql", K(last_ret), K(sql), K(process_time));
 | 
						|
    }
 | 
						|
  }
 | 
						|
  return ret;
 | 
						|
}
 | 
						|
 | 
						|
int ObInnerSQLConnection::do_query(sqlclient::ObIExecutor& executor, ObInnerSQLResult& res)
 | 
						|
{
 | 
						|
  int ret = OB_SUCCESS;
 | 
						|
  WITH_CONTEXT(res.mem_context_)
 | 
						|
  {
 | 
						|
    bool is_restore = NULL != sql_modifier_;
 | 
						|
    res.sql_ctx().is_restore_ = is_restore;
 | 
						|
    res.sql_ctx().is_ddl_from_primary_ = is_ddl_from_primary();
 | 
						|
    if (!inited_) {
 | 
						|
      ret = OB_NOT_INIT;
 | 
						|
      LOG_WARN("not init", K(ret));
 | 
						|
    } else if (OB_ISNULL(ob_sql_)) {
 | 
						|
      ret = OB_ERR_UNEXPECTED;
 | 
						|
      LOG_ERROR("ob_sql_ is NULL", K(ret));
 | 
						|
    } else if (OB_FAIL(executor.execute(*ob_sql_, res.sql_ctx(), res.result_set()))) {
 | 
						|
      LOG_WARN("executor execute failed", K(ret));
 | 
						|
    } else {
 | 
						|
      ObSQLSessionInfo& session = res.result_set().get_session();
 | 
						|
      if (OB_ISNULL(res.sql_ctx().schema_guard_)) {
 | 
						|
        ret = OB_ERR_UNEXPECTED;
 | 
						|
        LOG_WARN("schema guard is null");
 | 
						|
      } else if (OB_FAIL(session.update_query_sensitive_system_variable(*(res.sql_ctx().schema_guard_)))) {
 | 
						|
        LOG_WARN("update query affacted system variable failed", K(ret));
 | 
						|
      } else if (OB_UNLIKELY(is_restore) && OB_FAIL(sql_modifier_->modify(res.result_set()))) {
 | 
						|
        LOG_WARN("fail modify sql", K(res.result_set().get_statement_name()), K(ret));
 | 
						|
      } else if (0 < primary_schema_versions_.count() && OB_FAIL(process_schema_version(res.result_set()))) {
 | 
						|
        LOG_WARN("failed to procsee schema version", K(ret), K(primary_schema_versions_));
 | 
						|
      } else if (OB_FAIL(res.open())) {
 | 
						|
        LOG_WARN("result set open failed", K(ret), K(executor));
 | 
						|
      }
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  return ret;
 | 
						|
}
 | 
						|
 | 
						|
int ObInnerSQLConnection::process_schema_version(sql::ObResultSet& result_set)
 | 
						|
{
 | 
						|
  int ret = OB_SUCCESS;
 | 
						|
  if (!inited_) {
 | 
						|
    ret = OB_NOT_INIT;
 | 
						|
    LOG_WARN("not init", K(ret));
 | 
						|
  } else if (0 >= primary_schema_versions_.count()) {
 | 
						|
    ret = OB_INVALID_ARGUMENT;
 | 
						|
    LOG_WARN("schema version is invalid", K(ret), K(primary_schema_versions_));
 | 
						|
  } else {
 | 
						|
    ObICmd* cmd = const_cast<ObICmd*>(result_set.get_cmd());
 | 
						|
    if (OB_ISNULL(cmd)) {
 | 
						|
      ret = OB_ERR_UNEXPECTED;
 | 
						|
      LOG_WARN("cmd is null", K(ret), K(result_set));
 | 
						|
    } else {
 | 
						|
      sql::ObDDLStmt* ddl_stmt = static_cast<sql::ObDDLStmt*>(cmd);
 | 
						|
      if (OB_ISNULL(ddl_stmt)) {
 | 
						|
        ret = OB_ERR_UNEXPECTED;
 | 
						|
        LOG_WARN("type error", K(ret), K(cmd));
 | 
						|
      } else if (OB_FAIL(ddl_stmt->get_ddl_arg().primary_schema_versions_.assign(primary_schema_versions_))) {
 | 
						|
        LOG_WARN("failed to assign ddl_stmt", K(ret), K(primary_schema_versions_), K(ddl_stmt));
 | 
						|
      }
 | 
						|
    }
 | 
						|
  }
 | 
						|
  return ret;
 | 
						|
}
 | 
						|
 | 
						|
int ObInnerSQLConnection::query(sqlclient::ObIExecutor& executor, ObInnerSQLResult& res,
 | 
						|
    ObVirtualTableIteratorFactory* vt_iter_factory, bool is_from_pl)
 | 
						|
{
 | 
						|
  int ret = OB_SUCCESS;
 | 
						|
  share::CompatModeGuard g(get_compat_mode());
 | 
						|
  ObExecRecord exec_record;
 | 
						|
  ObExecTimestamp exec_timestamp;
 | 
						|
 | 
						|
  exec_timestamp.exec_type_ = sql::InnerSql;
 | 
						|
  const ObGlobalContext& gctx = ObServer::get_instance().get_gctx();
 | 
						|
  int64_t start_time = ObTimeUtility::current_time();
 | 
						|
  if (!is_from_pl) {
 | 
						|
    get_session().set_query_start_time(start_time);
 | 
						|
  }
 | 
						|
  get_session().set_trans_type(transaction::ObTransType::TRANS_SYSTEM);
 | 
						|
  int64_t abs_timeout_us = 0;
 | 
						|
  int64_t execution_id = 0;
 | 
						|
  bool is_trace_id_init = true;
 | 
						|
  ObQueryRetryInfo& retry_info = inner_session_.get_retry_info_for_update();
 | 
						|
  ObAddr host_addr = ObCurTraceId::get_addr();
 | 
						|
  if (!host_addr.is_valid()) {
 | 
						|
    is_trace_id_init = false;
 | 
						|
    common::ObCurTraceId::init(observer::ObServer::get_instance().get_self());
 | 
						|
  }
 | 
						|
 | 
						|
  // backup && restore worker/session timeout.
 | 
						|
  TimeoutGuard timeout_guard(*this);
 | 
						|
 | 
						|
  if (!inited_) {
 | 
						|
    ret = OB_NOT_INIT;
 | 
						|
    LOG_WARN("not init", K(ret));
 | 
						|
  } else if (NULL != ref_ctx_) {
 | 
						|
    ret = OB_REF_NUM_NOT_ZERO;
 | 
						|
    LOG_ERROR("connection still be referred by previous sql result, can not execute sql now", K(ret), K(executor));
 | 
						|
  } else if (OB_FAIL(set_timeout(abs_timeout_us, is_from_pl))) {
 | 
						|
    LOG_WARN("set timeout failed", K(ret));
 | 
						|
  } else if (OB_ISNULL(ob_sql_)) {
 | 
						|
    ret = OB_ERR_UNEXPECTED;
 | 
						|
    LOG_WARN("invalid sql engine", K(ret), K(ob_sql_));
 | 
						|
  } else if (OB_UNLIKELY(retry_info.is_inited())) {
 | 
						|
    if (is_inner_session()) {
 | 
						|
      ret = OB_ERR_UNEXPECTED;
 | 
						|
      LOG_ERROR("retry info is inited", K(ret), K(retry_info), K(executor));
 | 
						|
    }
 | 
						|
  } else if (OB_FAIL(retry_info.init())) {
 | 
						|
    LOG_WARN("fail to init retry info", K(ret), K(retry_info), K(executor));
 | 
						|
  }
 | 
						|
  if (OB_SUCC(ret)) {
 | 
						|
    execution_id = ob_sql_->get_execution_id();
 | 
						|
    bool need_retry = true;
 | 
						|
    for (int64_t retry_cnt = 0; need_retry; ++retry_cnt) {
 | 
						|
      need_retry = false;
 | 
						|
      retry_info.clear_state_before_each_retry();
 | 
						|
      if (retry_cnt > 0) {  // reset result set
 | 
						|
        bool is_user_sql = res.result_set().is_user_sql();
 | 
						|
        res.~ObInnerSQLResult();
 | 
						|
        new (&res) ObInnerSQLResult(get_session());
 | 
						|
        if (OB_FAIL(res.init())) {
 | 
						|
          LOG_WARN("fail to init result set", K(ret));
 | 
						|
        } else {
 | 
						|
          res.result_set().set_user_sql(is_user_sql);
 | 
						|
        }
 | 
						|
      }
 | 
						|
 | 
						|
      int64_t local_tenant_schema_version = -1;
 | 
						|
      int64_t local_sys_schema_version = -1;
 | 
						|
      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 && get_session().get_local_ob_enable_sql_audit() && !is_from_pl;
 | 
						|
      {
 | 
						|
        ObMaxWaitGuard max_wait_guard(enable_perf_event ? &max_wait_desc : NULL);
 | 
						|
        ObTotalWaitGuard total_wait_guard(enable_perf_event ? &total_wait_desc : NULL);
 | 
						|
 | 
						|
        if (enable_sql_audit) {
 | 
						|
          exec_record.record_start();
 | 
						|
        }
 | 
						|
 | 
						|
        const uint64_t tenant_id = get_session().get_effective_tenant_id();
 | 
						|
        if (OB_FAIL(ret)) {
 | 
						|
          // do nothing
 | 
						|
        } else if (OB_FAIL(gctx.schema_service_->get_tenant_schema_guard(tenant_id, res.schema_guard_))) {
 | 
						|
          LOG_WARN("get schema guard failed", K(ret));
 | 
						|
        } else if (OB_FAIL(init_result(res, vt_iter_factory, retry_cnt, res.schema_guard_, false, false, is_from_pl))) {
 | 
						|
          LOG_WARN("failed to init result", K(ret));
 | 
						|
        } else if (OB_FAIL(res.schema_guard_.get_schema_version(tenant_id, local_tenant_schema_version))) {
 | 
						|
          LOG_WARN("get tenant schema version failed", K(ret), K(ob_sql_));
 | 
						|
        } else if (OB_FAIL(res.schema_guard_.get_schema_version(OB_SYS_TENANT_ID, local_sys_schema_version))) {
 | 
						|
          LOG_WARN("get sys tenant schema version failed", K(ret), K(ob_sql_));
 | 
						|
        } else if (OB_UNLIKELY(is_extern_session())) {
 | 
						|
          res.result_set().get_exec_context().get_task_exec_ctx().set_query_tenant_begin_schema_version(
 | 
						|
              local_tenant_schema_version);
 | 
						|
          res.result_set().get_exec_context().get_task_exec_ctx().set_query_sys_begin_schema_version(
 | 
						|
              local_sys_schema_version);
 | 
						|
        }
 | 
						|
 | 
						|
        int ret_code = OB_SUCCESS;
 | 
						|
        if (OB_FAIL(ret)) {
 | 
						|
          // do nothing
 | 
						|
        } else if (OB_FAIL(SMART_CALL(do_query(executor, res)))) {
 | 
						|
          ret_code = ret;
 | 
						|
          LOG_WARN("execute failed", K(ret), K(executor), K(retry_cnt));
 | 
						|
          int tmp_ret = process_retry(res, ret, abs_timeout_us, need_retry, retry_cnt, is_from_pl);
 | 
						|
          if (OB_SUCCESS != tmp_ret) {
 | 
						|
            LOG_WARN("failed to process retry", K(tmp_ret), K(ret), K(executor), K(retry_cnt));
 | 
						|
          }
 | 
						|
          ret = tmp_ret;
 | 
						|
          // moved here from ObInnerSQLConnection::do_query() -> ObInnerSQLResult::open().
 | 
						|
          int close_ret = res.force_close(need_retry);
 | 
						|
          if (OB_SUCCESS != close_ret) {
 | 
						|
            LOG_WARN("failed to close result", K(close_ret), K(ret));
 | 
						|
          }
 | 
						|
        }
 | 
						|
        get_session().set_session_in_retry(need_retry, ret_code);
 | 
						|
        execute_start_timestamp_ = res.get_execute_start_ts();
 | 
						|
        execute_end_timestamp_ = res.get_execute_end_ts();
 | 
						|
 | 
						|
        if (enable_sql_audit) {
 | 
						|
          exec_record.record_end();
 | 
						|
        }
 | 
						|
      }
 | 
						|
 | 
						|
      if (enable_sql_audit && res.is_inited()) {
 | 
						|
        ObInnerSQLTimeRecord time_record(get_session());
 | 
						|
        time_record.set_execute_start_timestamp(execute_start_timestamp_);
 | 
						|
        time_record.set_execute_end_timestamp(execute_end_timestamp_);
 | 
						|
        int record_ret = process_record(res,
 | 
						|
            get_session(),
 | 
						|
            time_record,
 | 
						|
            ret,
 | 
						|
            execution_id,
 | 
						|
            OB_INVALID_ID,
 | 
						|
            OB_INVALID_ID,
 | 
						|
            max_wait_desc,
 | 
						|
            total_wait_desc,
 | 
						|
            exec_record,
 | 
						|
            exec_timestamp);
 | 
						|
        if (OB_SUCCESS != record_ret) {
 | 
						|
          LOG_WARN("failed to process record", K(executor), K(record_ret), K(ret));
 | 
						|
        }
 | 
						|
      }
 | 
						|
 | 
						|
      if (res.is_inited()) {
 | 
						|
        if (get_session().get_in_transaction()) {
 | 
						|
          if (ObStmt::is_dml_write_stmt(res.result_set().get_stmt_type())) {
 | 
						|
            get_session().set_has_inner_dml_write(true);
 | 
						|
          }
 | 
						|
        }
 | 
						|
      }
 | 
						|
    }
 | 
						|
  }
 | 
						|
  if (res.is_inited()) {
 | 
						|
    int aret = process_final(executor, res, ret);
 | 
						|
    if (OB_SUCCESS != aret) {
 | 
						|
      LOG_WARN("failed to process final", K(executor), K(aret), K(ret));
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  if (false == is_trace_id_init) {
 | 
						|
    common::ObCurTraceId::reset();
 | 
						|
  }
 | 
						|
 | 
						|
  retry_info.reset();
 | 
						|
  return ret;
 | 
						|
}
 | 
						|
 | 
						|
int ObInnerSQLConnection::do_prepare(const common::ObString& sql, ObInnerSQLResult& res)
 | 
						|
{
 | 
						|
  int ret = OB_SUCCESS;
 | 
						|
  WITH_CONTEXT(res.mem_context_)
 | 
						|
  {
 | 
						|
    if (!inited_) {
 | 
						|
      ret = OB_NOT_INIT;
 | 
						|
      LOG_WARN("not init", K(ret));
 | 
						|
    } else if (sql.empty()) {
 | 
						|
      ret = OB_INVALID_ARGUMENT;
 | 
						|
      LOG_WARN("invalid argument", K(ret), K(sql));
 | 
						|
    } else if (OB_FAIL(ob_sql_->stmt_prepare(sql, res.sql_ctx(), res.result_set()))) {
 | 
						|
      LOG_WARN("sql execute failed", K(ret), K(sql));
 | 
						|
    }
 | 
						|
  }
 | 
						|
  return ret;
 | 
						|
}
 | 
						|
 | 
						|
int ObInnerSQLConnection::prepare(const ObString& sql, bool is_dynamic_sql, bool is_dbms_sql, bool is_cursor,
 | 
						|
    ObInnerSQLResult& res, ObVirtualTableIteratorFactory* vt_iter_factory)
 | 
						|
{
 | 
						|
  int ret = OB_SUCCESS;
 | 
						|
  ObExecRecord exec_record;
 | 
						|
  ObExecTimestamp exec_timestamp;
 | 
						|
  int64_t execution_id = 0;
 | 
						|
  exec_timestamp.exec_type_ = sql::InnerSql;
 | 
						|
  const ObGlobalContext& gctx = ObServer::get_instance().get_gctx();
 | 
						|
  int64_t old_query_start_time = get_session().get_query_start_time();
 | 
						|
  get_session().set_query_start_time(ObTimeUtility::current_time());
 | 
						|
  get_session().set_trans_type(transaction::ObTransType::TRANS_SYSTEM);
 | 
						|
  // get_session().store_query_string(sql);
 | 
						|
  int64_t abs_timeout_us = 0;
 | 
						|
  const uint64_t* trace_id_val = ObCurTraceId::get();
 | 
						|
  bool is_trace_id_init = true;
 | 
						|
  ObQueryRetryInfo& retry_info = inner_session_.get_retry_info_for_update();
 | 
						|
  if (0 == trace_id_val[0]) {
 | 
						|
    is_trace_id_init = false;
 | 
						|
    common::ObCurTraceId::init(observer::ObServer::get_instance().get_self());
 | 
						|
  }
 | 
						|
 | 
						|
  // backup && restore worker/session timeout.
 | 
						|
  TimeoutGuard timeout_guard(*this);
 | 
						|
 | 
						|
  // %vt_iter_factory may be NULL
 | 
						|
  if (!inited_) {
 | 
						|
    ret = OB_NOT_INIT;
 | 
						|
    LOG_WARN("not init", K(ret));
 | 
						|
  } else if (sql.empty()) {
 | 
						|
    ret = OB_INVALID_ARGUMENT;
 | 
						|
    LOG_WARN("invalid argument", K(ret), K(sql));
 | 
						|
  } else if (NULL != ref_ctx_) {
 | 
						|
    ret = OB_REF_NUM_NOT_ZERO;
 | 
						|
    LOG_ERROR("connection still be referred by previous sql result, can not execute sql now", K(ret), K(sql));
 | 
						|
  } else if (OB_FAIL(set_timeout(abs_timeout_us, true))) {
 | 
						|
    LOG_WARN("set timeout failed", K(ret));
 | 
						|
  } else if (OB_ISNULL(ob_sql_)) {
 | 
						|
    ret = OB_ERR_UNEXPECTED;
 | 
						|
    LOG_WARN("invalid sql engine", K(ret), K(ob_sql_));
 | 
						|
  } else if (OB_UNLIKELY(retry_info.is_inited())) {
 | 
						|
    ret = OB_ERR_UNEXPECTED;
 | 
						|
    LOG_ERROR("retry info is inited", K(ret), K(retry_info), K(sql));
 | 
						|
  } else if (OB_FAIL(retry_info.init())) {
 | 
						|
    LOG_WARN("fail to init retry info", K(ret), K(retry_info), K(sql));
 | 
						|
  } else {
 | 
						|
    execution_id = ob_sql_->get_execution_id();
 | 
						|
  }
 | 
						|
  if (OB_SUCC(ret)) {
 | 
						|
    bool need_retry = true;
 | 
						|
    for (int64_t retry_cnt = 0; need_retry; ++retry_cnt) {
 | 
						|
      need_retry = false;
 | 
						|
      retry_info.clear_state_before_each_retry();
 | 
						|
      if (retry_cnt > 0) {  // reset result set
 | 
						|
        res.~ObInnerSQLResult();
 | 
						|
        new (&res) ObInnerSQLResult(get_session());
 | 
						|
        ret = res.init();
 | 
						|
      }
 | 
						|
      const uint64_t tenant_id = get_session().get_effective_tenant_id();
 | 
						|
      if (OB_FAIL(gctx.schema_service_->get_tenant_schema_guard(tenant_id, res.schema_guard_))) {
 | 
						|
        LOG_WARN("get schema guard failed", K(ret));
 | 
						|
      } else if (OB_FAIL(init_result(res,
 | 
						|
                     vt_iter_factory,
 | 
						|
                     retry_cnt,
 | 
						|
                     res.schema_guard_,
 | 
						|
                     true,
 | 
						|
                     true,
 | 
						|
                     true,
 | 
						|
                     is_dynamic_sql,
 | 
						|
                     is_dbms_sql,
 | 
						|
                     is_cursor))) {
 | 
						|
        LOG_WARN("failed to init result", K(ret));
 | 
						|
      } else if (OB_FAIL(do_prepare(sql, res))) {
 | 
						|
        LOG_WARN("execute sql failed", K(ret), K(sql), K(retry_cnt));
 | 
						|
        int tmp_ret = process_retry(res, ret, abs_timeout_us, need_retry, retry_cnt, true);
 | 
						|
        if (OB_SUCCESS != tmp_ret) {
 | 
						|
          LOG_WARN("failed to process retry", K(tmp_ret), K(ret), K(sql), K(retry_cnt));
 | 
						|
        }
 | 
						|
        ret = tmp_ret;
 | 
						|
      }
 | 
						|
    }
 | 
						|
  }
 | 
						|
  if (res.is_inited()) {
 | 
						|
    int aret = process_final(sql, res, ret);
 | 
						|
    if (OB_SUCCESS != aret) {
 | 
						|
      LOG_WARN("failed to process final", K(sql), K(aret), K(ret));
 | 
						|
    }
 | 
						|
  }
 | 
						|
  if (false == is_trace_id_init) {
 | 
						|
    common::ObCurTraceId::reset();
 | 
						|
  }
 | 
						|
  retry_info.reset();
 | 
						|
  get_session().set_query_start_time(old_query_start_time);
 | 
						|
  return ret;
 | 
						|
}
 | 
						|
 | 
						|
int ObInnerSQLConnection::do_execute(const ParamStore& params, ObInnerSQLResult& res)
 | 
						|
{
 | 
						|
  int ret = OB_SUCCESS;
 | 
						|
  WITH_CONTEXT(res.mem_context_)
 | 
						|
  {
 | 
						|
    if (!inited_) {
 | 
						|
      ret = OB_NOT_INIT;
 | 
						|
      LOG_WARN("not init", K(ret));
 | 
						|
    } else if (OB_ISNULL(ob_sql_)) {
 | 
						|
      ret = OB_ERR_UNEXPECTED;
 | 
						|
      LOG_ERROR("ob_sql_ is NULL", K(ret));
 | 
						|
    } else if (OB_FAIL(ob_sql_->stmt_execute(res.result_set().get_statement_id(),
 | 
						|
                   res.result_set().get_stmt_type(),
 | 
						|
                   params,
 | 
						|
                   res.sql_ctx(),
 | 
						|
                   res.result_set(),
 | 
						|
                   true /* is_inner_sql */))) {
 | 
						|
      LOG_WARN("sql execute failed", K(res.result_set().get_statement_id()), K(ret));
 | 
						|
    } else {
 | 
						|
      ObSQLSessionInfo& session = res.result_set().get_session();
 | 
						|
      if (OB_ISNULL(res.sql_ctx().schema_guard_)) {
 | 
						|
        ret = OB_ERR_UNEXPECTED;
 | 
						|
        LOG_WARN("schema guard is null");
 | 
						|
      } else if (OB_FAIL(session.update_query_sensitive_system_variable(*(res.sql_ctx().schema_guard_)))) {
 | 
						|
        LOG_WARN("update query affacted system variable failed", K(ret));
 | 
						|
      } else if (OB_UNLIKELY(NULL != sql_modifier_) && OB_FAIL(sql_modifier_->modify(res.result_set()))) {
 | 
						|
        LOG_WARN("fail modify sql", K(res.result_set().get_statement_name()), K(ret));
 | 
						|
      } else if (OB_FAIL(res.open())) {
 | 
						|
        LOG_WARN("result set open failed", K(res.result_set().get_statement_id()), K(ret));
 | 
						|
      } else { /*do nothing*/
 | 
						|
      }
 | 
						|
    }
 | 
						|
  }
 | 
						|
  return ret;
 | 
						|
}
 | 
						|
 | 
						|
int ObInnerSQLConnection::execute(ParamStore& params, ObInnerSQLResult& res,
 | 
						|
    ObVirtualTableIteratorFactory* vt_iter_factory, bool is_from_pl, bool is_dynamic)
 | 
						|
{
 | 
						|
  int ret = OB_SUCCESS;
 | 
						|
  ObExecRecord exec_record;
 | 
						|
  ObExecTimestamp exec_timestamp;
 | 
						|
  exec_timestamp.exec_type_ = sql::InnerSql;
 | 
						|
  const ObGlobalContext& gctx = ObServer::get_instance().get_gctx();
 | 
						|
  const ObString& sql = res.result_set().get_statement_name();
 | 
						|
  int64_t start_time = ObTimeUtility::current_time();
 | 
						|
  if (!is_from_pl) {
 | 
						|
    get_session().set_query_start_time(start_time);
 | 
						|
  }
 | 
						|
  get_session().set_trans_type(transaction::ObTransType::TRANS_SYSTEM);
 | 
						|
  int64_t abs_timeout_us = 0;
 | 
						|
  int64_t execution_id = 0;
 | 
						|
  uint64_t stmt_id = res.result_set().get_statement_id();
 | 
						|
  sql::stmt::StmtType stmt_type = res.result_set().get_stmt_type();
 | 
						|
  const uint64_t* trace_id_val = ObCurTraceId::get();
 | 
						|
  bool is_trace_id_init = true;
 | 
						|
  ObQueryRetryInfo& retry_info = inner_session_.get_retry_info_for_update();
 | 
						|
  if (0 == trace_id_val[0]) {
 | 
						|
    is_trace_id_init = false;
 | 
						|
    common::ObCurTraceId::init(observer::ObServer::get_instance().get_self());
 | 
						|
  }
 | 
						|
 | 
						|
  // backup && restore worker/session timeout.
 | 
						|
  TimeoutGuard timeout_guard(*this);
 | 
						|
 | 
						|
  // %vt_iter_factory may be NULL
 | 
						|
  if (!inited_) {
 | 
						|
    ret = OB_NOT_INIT;
 | 
						|
    LOG_WARN("not init", K(ret));
 | 
						|
  } else if (NULL != ref_ctx_) {
 | 
						|
    ret = OB_REF_NUM_NOT_ZERO;
 | 
						|
    LOG_ERROR("connection still be referred by previous sql result, can not execute sql now", K(ret), K(sql));
 | 
						|
  } else if (OB_FAIL(set_timeout(abs_timeout_us, is_from_pl))) {
 | 
						|
    LOG_WARN("set timeout failed", K(ret));
 | 
						|
  } else if (OB_ISNULL(ob_sql_)) {
 | 
						|
    ret = OB_ERR_UNEXPECTED;
 | 
						|
    LOG_WARN("invalid sql engine", K(ret), K(ob_sql_));
 | 
						|
  } else if (OB_UNLIKELY(retry_info.is_inited())) {
 | 
						|
    ret = OB_ERR_UNEXPECTED;
 | 
						|
    LOG_ERROR("retry info is inited", K(ret), K(retry_info), K(sql));
 | 
						|
  } else if (OB_FAIL(retry_info.init())) {
 | 
						|
    LOG_WARN("fail to init retry info", K(ret), K(retry_info), K(sql));
 | 
						|
  } else {
 | 
						|
    execution_id = ob_sql_->get_execution_id();
 | 
						|
    bool need_retry = true;
 | 
						|
    for (int64_t retry_cnt = 0; need_retry; ++retry_cnt) {
 | 
						|
      need_retry = false;
 | 
						|
      retry_info.clear_state_before_each_retry();
 | 
						|
      if (retry_cnt > 0) {  // reset result set
 | 
						|
        res.~ObInnerSQLResult();
 | 
						|
        new (&res) ObInnerSQLResult(get_session());
 | 
						|
        ret = res.init();
 | 
						|
        if (OB_SUCC(ret)) {
 | 
						|
          res.result_set().set_ps_protocol();
 | 
						|
          res.result_set().set_statement_id(stmt_id);
 | 
						|
          res.result_set().set_stmt_type(stmt_type);
 | 
						|
        }
 | 
						|
      }
 | 
						|
 | 
						|
      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 && get_session().get_local_ob_enable_sql_audit() && !is_from_pl;
 | 
						|
      {
 | 
						|
        ObMaxWaitGuard max_wait_guard(enable_perf_event ? &max_wait_desc : NULL);
 | 
						|
        ObTotalWaitGuard total_wait_guard(enable_perf_event ? &total_wait_desc : NULL);
 | 
						|
 | 
						|
        if (enable_sql_audit) {
 | 
						|
          exec_record.record_start();
 | 
						|
        }
 | 
						|
 | 
						|
        const uint64_t tenant_id = get_session().get_effective_tenant_id();
 | 
						|
        int ret_code = OB_SUCCESS;
 | 
						|
        if (OB_FAIL(gctx.schema_service_->get_tenant_schema_guard(tenant_id, res.schema_guard_))) {
 | 
						|
          LOG_WARN("get schema guard failed", K(ret));
 | 
						|
        } else if (OB_FAIL(init_result(
 | 
						|
                       res, vt_iter_factory, retry_cnt, res.schema_guard_, false, false, is_from_pl, is_dynamic))) {
 | 
						|
          LOG_WARN("failed to init result", K(ret));
 | 
						|
        } else if (OB_FAIL(do_execute(params, res))) {
 | 
						|
          LOG_WARN("execute sql failed", K(ret), K(sql), K(retry_cnt));
 | 
						|
          ret_code = ret;
 | 
						|
          int tmp_ret = process_retry(res, ret, abs_timeout_us, need_retry, retry_cnt, is_from_pl);
 | 
						|
          if (OB_SUCCESS != tmp_ret) {
 | 
						|
            LOG_WARN("failed to process retry", K(tmp_ret), K(ret), K(sql), K(retry_cnt));
 | 
						|
          }
 | 
						|
          ret = tmp_ret;
 | 
						|
          // moved here from ObInnerSQLConnection::do_execute() -> ObInnerSQLResult::open().
 | 
						|
          int close_ret = res.force_close(need_retry);
 | 
						|
          if (OB_SUCCESS != close_ret) {
 | 
						|
            LOG_WARN("failed to close result", K(close_ret), K(ret), K(sql));
 | 
						|
          }
 | 
						|
        }
 | 
						|
        ObSQLSessionInfo& session = res.result_set().get_session();
 | 
						|
        session.set_session_in_retry(need_retry, ret_code);
 | 
						|
        LOG_DEBUG("after process_retry",
 | 
						|
            K(retry_cnt),
 | 
						|
            K(ret),
 | 
						|
            K(need_retry),
 | 
						|
            K(inner_session_),
 | 
						|
            KP(&inner_session_),
 | 
						|
            K(inner_session_.get_is_in_retry()),
 | 
						|
            K(session.get_is_in_retry_for_dup_tbl()),
 | 
						|
            K(session),
 | 
						|
            K(&session),
 | 
						|
            K(session.get_is_in_retry()));
 | 
						|
 | 
						|
        execute_start_timestamp_ = res.get_execute_start_ts();
 | 
						|
        execute_end_timestamp_ = res.get_execute_end_ts();
 | 
						|
        if (enable_sql_audit) {
 | 
						|
          exec_record.record_end();
 | 
						|
        }
 | 
						|
      }
 | 
						|
 | 
						|
      if (enable_sql_audit && res.is_inited()) {
 | 
						|
        ObInnerSQLTimeRecord time_record(get_session());
 | 
						|
        time_record.set_execute_start_timestamp(execute_start_timestamp_);
 | 
						|
        time_record.set_execute_end_timestamp(execute_end_timestamp_);
 | 
						|
        int record_ret = process_record(res,
 | 
						|
            get_session(),
 | 
						|
            time_record,
 | 
						|
            ret,
 | 
						|
            execution_id,
 | 
						|
            OB_INVALID_ID,
 | 
						|
            OB_INVALID_ID,
 | 
						|
            max_wait_desc,
 | 
						|
            total_wait_desc,
 | 
						|
            exec_record,
 | 
						|
            exec_timestamp);
 | 
						|
        if (OB_SUCCESS != record_ret) {
 | 
						|
          LOG_WARN("failed to process record", K(sql), K(record_ret), K(ret));
 | 
						|
        }
 | 
						|
      }
 | 
						|
 | 
						|
      if (get_session().get_in_transaction()) {
 | 
						|
        if (ObStmt::is_dml_write_stmt(stmt_type)) {
 | 
						|
          get_session().set_has_inner_dml_write(true);
 | 
						|
        }
 | 
						|
      }
 | 
						|
    }
 | 
						|
  }
 | 
						|
  if (res.is_inited()) {
 | 
						|
    int aret = process_final(sql, res, ret);
 | 
						|
    if (OB_SUCCESS != aret) {
 | 
						|
      LOG_WARN("failed to process final", K(sql), K(aret), K(ret));
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  if (false == is_trace_id_init) {
 | 
						|
    common::ObCurTraceId::reset();
 | 
						|
  }
 | 
						|
 | 
						|
  retry_info.reset();
 | 
						|
 | 
						|
  return ret;
 | 
						|
}
 | 
						|
 | 
						|
int ObInnerSQLConnection::start_transaction(bool with_snap_shot /* = false */)
 | 
						|
{
 | 
						|
  int ret = OB_SUCCESS;
 | 
						|
  ObString sql;
 | 
						|
  observer::ObReqTimeGuard req_timeinfo_guard;
 | 
						|
  if (with_snap_shot) {
 | 
						|
    sql = ObString::make_string("START TRANSACTION WITH CONSISTENT SNAPSHOT");
 | 
						|
  } else {
 | 
						|
    sql = ObString::make_string("START TRANSACTION");
 | 
						|
  }
 | 
						|
  ObSqlQueryExecutor executor(sql);
 | 
						|
  SMART_VAR(ObInnerSQLResult, res, get_session())
 | 
						|
  {
 | 
						|
    if (OB_FAIL(res.init())) {
 | 
						|
      LOG_WARN("init result set", K(ret));
 | 
						|
    } else if (!inited_) {
 | 
						|
      ret = OB_NOT_INIT;
 | 
						|
      LOG_WARN("connection not inited", K(ret));
 | 
						|
    } else if (OB_FAIL(query(executor, res))) {
 | 
						|
      LOG_WARN("start transaction failed", K(ret), K(with_snap_shot));
 | 
						|
    } else if (OB_FAIL(res.close())) {
 | 
						|
      LOG_WARN("close result set failed", K(ret));
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  return ret;
 | 
						|
}
 | 
						|
 | 
						|
int ObInnerSQLConnection::rollback()
 | 
						|
{
 | 
						|
  int ret = OB_SUCCESS;
 | 
						|
  observer::ObReqTimeGuard req_timeinfo_guard;
 | 
						|
  ObSqlQueryExecutor executor("ROLLBACK");
 | 
						|
  SMART_VAR(ObInnerSQLResult, res, get_session())
 | 
						|
  {
 | 
						|
    if (OB_FAIL(res.init())) {
 | 
						|
      LOG_WARN("init result set", K(ret));
 | 
						|
    } else if (!inited_) {
 | 
						|
      ret = OB_NOT_INIT;
 | 
						|
      LOG_WARN("connection not inited", K(ret));
 | 
						|
    } else if (OB_FAIL(query(executor, res))) {
 | 
						|
      LOG_WARN("rollback failed", K(ret));
 | 
						|
    } else if (OB_FAIL(res.close())) {
 | 
						|
      LOG_WARN("close result set failed", K(ret));
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  return ret;
 | 
						|
}
 | 
						|
 | 
						|
int ObInnerSQLConnection::commit()
 | 
						|
{
 | 
						|
  int ret = OB_SUCCESS;
 | 
						|
  DEBUG_SYNC(BEFORE_INNER_SQL_COMMIT);
 | 
						|
  observer::ObReqTimeGuard req_timeinfo_guard;
 | 
						|
  ObSqlQueryExecutor executor("COMMIT");
 | 
						|
  SMART_VAR(ObInnerSQLResult, res, get_session())
 | 
						|
  {
 | 
						|
    if (OB_FAIL(res.init())) {
 | 
						|
      LOG_WARN("init result set", K(ret));
 | 
						|
    } else if (!inited_) {
 | 
						|
      ret = OB_NOT_INIT;
 | 
						|
      LOG_WARN("connection not inited", K(ret));
 | 
						|
    } else if (OB_FAIL(query(executor, res))) {
 | 
						|
      LOG_WARN("commit failed", K(ret));
 | 
						|
    } else if (OB_FAIL(res.close())) {
 | 
						|
      LOG_WARN("close result set failed", K(ret));
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  return ret;
 | 
						|
}
 | 
						|
 | 
						|
int ObInnerSQLConnection::execute_write(
 | 
						|
    const uint64_t tenant_id, const char* sql, int64_t& affected_rows, bool is_user_sql)
 | 
						|
{
 | 
						|
  int ret = OB_SUCCESS;
 | 
						|
  observer::ObReqTimeGuard req_timeinfo_guard;
 | 
						|
  ObSqlQueryExecutor executor(sql);
 | 
						|
  SMART_VAR(ObInnerSQLResult, res, get_session())
 | 
						|
  {
 | 
						|
    if (OB_FAIL(res.init())) {
 | 
						|
      LOG_WARN("init result set", K(ret));
 | 
						|
    } else if (!inited_) {
 | 
						|
      ret = OB_NOT_INIT;
 | 
						|
      LOG_WARN("connection not inited", K(ret));
 | 
						|
    } else if (NULL == sql || '\0' == *sql || OB_INVALID_ID == tenant_id) {
 | 
						|
      ret = OB_INVALID_ARGUMENT;
 | 
						|
      LOG_WARN("invalid argument", K(ret), K(sql), K(tenant_id));
 | 
						|
    } else if (OB_FAIL(switch_tenant(tenant_id))) {
 | 
						|
      LOG_WARN("switch tenant_id failed", K(ret), K(tenant_id));
 | 
						|
    } else if (FALSE_IT(res.result_set().set_user_sql(is_user_sql))) {
 | 
						|
    } else if (OB_FAIL(query(executor, res))) {
 | 
						|
      LOG_WARN("execute sql failed", K(ret), K(tenant_id), K(sql));
 | 
						|
    } else if (FALSE_IT(affected_rows = res.result_set().get_affected_rows())) {
 | 
						|
    } else if (OB_FAIL(res.close())) {
 | 
						|
      LOG_WARN("close result set failed", K(ret), K(tenant_id), K(sql));
 | 
						|
    }
 | 
						|
    primary_schema_versions_.reset();
 | 
						|
    if (tenant_id < OB_MAX_RESERVED_TENANT_ID) {  // only print log for sys table
 | 
						|
      LOG_INFO("execute write sql", K(ret), K(tenant_id), K(affected_rows), K(sql));
 | 
						|
    }
 | 
						|
  }
 | 
						|
  return ret;
 | 
						|
}
 | 
						|
 | 
						|
int ObInnerSQLConnection::execute_read(
 | 
						|
    const uint64_t tenant_id, const char* sql, ObISQLClient::ReadResult& res, bool is_user_sql, bool is_from_pl)
 | 
						|
{
 | 
						|
  int ret = OB_SUCCESS;
 | 
						|
  ObInnerSQLReadContext* read_ctx = NULL;
 | 
						|
  observer::ObReqTimeGuard req_timeinfo_guard;
 | 
						|
  const static int64_t ctx_size = sizeof(ObInnerSQLReadContext);
 | 
						|
  static_assert(ctx_size <= ObISQLClient::ReadResult::BUF_SIZE, "buffer not enough");
 | 
						|
  ObSqlQueryExecutor executor(sql);
 | 
						|
  if (!inited_) {
 | 
						|
    ret = OB_NOT_INIT;
 | 
						|
    LOG_WARN("connection not inited", K(ret));
 | 
						|
  } else if (NULL == sql || '\0' == *sql || OB_INVALID_ID == tenant_id) {
 | 
						|
    ret = OB_INVALID_ARGUMENT;
 | 
						|
    LOG_WARN("invalid argument", K(ret), K(sql), K(tenant_id));
 | 
						|
  } else if (OB_FAIL(switch_tenant(tenant_id))) {
 | 
						|
    LOG_WARN("switch tenant_id failed", K(ret), K(tenant_id));
 | 
						|
  } else if (OB_FAIL(res.create_handler(read_ctx, *this))) {
 | 
						|
    LOG_WARN("create result handler failed", K(ret));
 | 
						|
  } else if (OB_FAIL(read_ctx->get_result().init())) {
 | 
						|
    LOG_WARN("init result set", K(ret));
 | 
						|
  } else if (FALSE_IT(read_ctx->get_result().result_set().set_user_sql(is_user_sql))) {
 | 
						|
    // nothing.
 | 
						|
  } else if (OB_FAIL(query(executor, read_ctx->get_result(), &read_ctx->get_vt_iter_factory(), is_from_pl))) {
 | 
						|
    LOG_WARN("execute sql failed", K(ret), K(tenant_id), K(sql));
 | 
						|
  }
 | 
						|
  if (OB_SUCC(ret)) {
 | 
						|
    ref_ctx_ = read_ctx;
 | 
						|
  }
 | 
						|
  return ret;
 | 
						|
}
 | 
						|
 | 
						|
int ObInnerSQLConnection::execute(const uint64_t tenant_id, sqlclient::ObIExecutor& executor)
 | 
						|
{
 | 
						|
  int ret = OB_SUCCESS;
 | 
						|
  observer::ObReqTimeGuard req_timeinfo_guard;
 | 
						|
  SMART_VAR(ObInnerSQLResult, res, get_session())
 | 
						|
  {
 | 
						|
    if (OB_FAIL(res.init())) {
 | 
						|
      LOG_WARN("init result set", K(ret));
 | 
						|
    } else if (!inited_) {
 | 
						|
      ret = OB_NOT_INIT;
 | 
						|
      LOG_WARN("connection not inited", K(ret));
 | 
						|
    } else if (OB_INVALID_ID == tenant_id) {
 | 
						|
      ret = OB_INVALID_ARGUMENT;
 | 
						|
      LOG_WARN("invalid argument", K(ret), K(tenant_id), K(executor));
 | 
						|
    } else if (OB_FAIL(switch_tenant(tenant_id))) {
 | 
						|
      LOG_WARN("switch tenant_id failed", K(ret), K(tenant_id));
 | 
						|
    } else if (OB_FAIL(query(executor, res))) {
 | 
						|
      LOG_WARN("executor execute failed", K(ret), K(tenant_id), K(executor));
 | 
						|
    } else {
 | 
						|
      share::CompatModeGuard g(get_compat_mode());
 | 
						|
      WITH_CONTEXT(res.mem_context_)
 | 
						|
      {
 | 
						|
        if (OB_FAIL(executor.process_result(res.result_set()))) {
 | 
						|
          LOG_WARN("process result failed", K(ret));
 | 
						|
        } else {
 | 
						|
          if (OB_FAIL(res.close())) {
 | 
						|
            LOG_WARN("close result set failed", K(ret), K(tenant_id), K(executor));
 | 
						|
          }
 | 
						|
        }
 | 
						|
      }
 | 
						|
    }
 | 
						|
    LOG_INFO("execute executor", K(ret), K(tenant_id), K(executor));
 | 
						|
  }
 | 
						|
  return ret;
 | 
						|
}
 | 
						|
 | 
						|
int ObInnerSQLConnection::prepare(const uint64_t tenant_id, const ObString& sql, bool is_dynamic_sql, bool is_dbms_sql,
 | 
						|
    bool is_cursor, ObISQLClient::ReadResult& res)
 | 
						|
{
 | 
						|
  int ret = OB_SUCCESS;
 | 
						|
  ObInnerSQLReadContext* read_ctx = NULL;
 | 
						|
  if (!inited_) {
 | 
						|
    ret = OB_NOT_INIT;
 | 
						|
    LOG_WARN("connection not inited", K(ret));
 | 
						|
  } else if (NULL == sql || '\0' == *sql || OB_INVALID_ID == tenant_id) {
 | 
						|
    ret = OB_INVALID_ARGUMENT;
 | 
						|
    LOG_WARN("invalid argument", K(ret), K(sql), K(tenant_id));
 | 
						|
  } else if (OB_FAIL(switch_tenant(tenant_id))) {
 | 
						|
    LOG_WARN("switch tenant_id failed", K(ret), K(tenant_id));
 | 
						|
  } else if (OB_FAIL(res.create_handler(read_ctx, *this))) {
 | 
						|
    LOG_WARN("create result handler failed", K(ret));
 | 
						|
  } else if (OB_FAIL(read_ctx->get_result().init())) {
 | 
						|
    LOG_WARN("init result set", K(ret));
 | 
						|
  } else if (OB_FAIL(prepare(sql,
 | 
						|
                 is_dynamic_sql,
 | 
						|
                 is_dbms_sql,
 | 
						|
                 is_cursor,
 | 
						|
                 read_ctx->get_result(),
 | 
						|
                 &read_ctx->get_vt_iter_factory()))) {
 | 
						|
    LOG_WARN("execute sql failed", K(ret), K(tenant_id), K(sql));
 | 
						|
  }
 | 
						|
  if (OB_SUCC(ret)) {
 | 
						|
    ref_ctx_ = read_ctx;
 | 
						|
  }
 | 
						|
  return ret;
 | 
						|
}
 | 
						|
 | 
						|
int ObInnerSQLConnection::execute(const uint64_t tenant_id, const ObPsStmtId stmt_id, const stmt::StmtType stmt_type,
 | 
						|
    ParamStore& params, ObISQLClient::ReadResult& res, bool is_from_pl, bool is_dynamic)
 | 
						|
{
 | 
						|
  int ret = OB_SUCCESS;
 | 
						|
  ObInnerSQLReadContext* read_ctx = NULL;
 | 
						|
  observer::ObReqTimeGuard req_timeinfo_guard;
 | 
						|
  ObPsStmtInfoGuard ps_guard;
 | 
						|
  ObPsStmtInfo* ps_info = NULL;
 | 
						|
  ObPsCache* ps_cache = get_session().get_ps_cache();
 | 
						|
  if (!inited_) {
 | 
						|
    ret = OB_NOT_INIT;
 | 
						|
    LOG_WARN("connection not inited", K(ret));
 | 
						|
  } else if (OB_INVALID_ID == tenant_id) {
 | 
						|
    ret = OB_INVALID_ARGUMENT;
 | 
						|
    LOG_WARN("invalid argument", K(ret), K(stmt_id), K(tenant_id));
 | 
						|
  } else if (OB_FAIL(switch_tenant(tenant_id))) {
 | 
						|
    LOG_WARN("switch tenant_id failed", K(ret), K(tenant_id));
 | 
						|
  } else if (OB_FAIL(res.create_handler(read_ctx, *this))) {
 | 
						|
    LOG_WARN("create result handler failed", K(ret));
 | 
						|
  } else if (OB_FAIL(read_ctx->get_result().init())) {
 | 
						|
    LOG_WARN("init result set", K(ret));
 | 
						|
  } else if (OB_ISNULL(ps_cache)) {
 | 
						|
    ret = OB_ERR_UNEXPECTED;
 | 
						|
    LOG_WARN("ps cache is null", K(ret), K(ps_cache));
 | 
						|
  } else if (OB_FAIL(ps_cache->get_stmt_info_guard(stmt_id, ps_guard))) {
 | 
						|
    LOG_WARN("get stmt info guard failed", K(ret), K(stmt_id));
 | 
						|
  } else if (OB_ISNULL(ps_info = ps_guard.get_stmt_info())) {
 | 
						|
    ret = OB_ERR_UNEXPECTED;
 | 
						|
    LOG_WARN("get stmt info is null", K(ret), K(ps_info), K(stmt_id));
 | 
						|
  } else {
 | 
						|
    read_ctx->get_result().result_set().set_ps_protocol();
 | 
						|
    read_ctx->get_result().result_set().set_statement_id(stmt_id);
 | 
						|
    read_ctx->get_result().result_set().set_stmt_type(stmt_type);
 | 
						|
    get_session().store_query_string(ps_info->get_ps_sql());
 | 
						|
 | 
						|
    if (OB_FAIL(execute(params, read_ctx->get_result(), &read_ctx->get_vt_iter_factory(), is_from_pl, is_dynamic))) {
 | 
						|
      LOG_WARN("execute sql failed", K(ret), K(tenant_id), K(stmt_id));
 | 
						|
    }
 | 
						|
  }
 | 
						|
  if (OB_SUCC(ret)) {
 | 
						|
    ref_ctx_ = read_ctx;
 | 
						|
  }
 | 
						|
  return ret;
 | 
						|
}
 | 
						|
 | 
						|
int ObInnerSQLConnection::switch_tenant(const uint64_t tenant_id)
 | 
						|
{
 | 
						|
  int ret = OB_SUCCESS;
 | 
						|
  // called in init(), can not check inited_ flag.
 | 
						|
  if (OB_INVALID_ID == tenant_id) {
 | 
						|
    LOG_WARN("invalid argument", K(ret), K(tenant_id));
 | 
						|
  } else if (is_inner_session()) {
 | 
						|
    if (OB_FAIL(get_session().switch_tenant(tenant_id))) {
 | 
						|
      LOG_WARN("Init sys tenant in session error", K(ret));
 | 
						|
    } else if (OB_FAIL(
 | 
						|
                   get_session().set_user(OB_SYS_USER_NAME, OB_SYS_HOST_NAME, combine_id(tenant_id, OB_SYS_USER_ID)))) {
 | 
						|
      LOG_WARN("Set sys user in session error", K(ret));
 | 
						|
    } else {
 | 
						|
      get_session().set_user_priv_set(OB_PRIV_ALL | OB_PRIV_GRANT);
 | 
						|
      get_session().set_database_id(combine_id(tenant_id, OB_SYS_DATABASE_ID));
 | 
						|
    }
 | 
						|
  } else { /*do nothing*/
 | 
						|
  }
 | 
						|
  return ret;
 | 
						|
}
 | 
						|
 | 
						|
int ObInnerSQLConnection::set_timeout(int64_t& abs_timeout_us, bool is_from_pl)
 | 
						|
{
 | 
						|
  int ret = OB_SUCCESS;
 | 
						|
  const ObTimeoutCtx& ctx = ObTimeoutCtx::get_ctx();
 | 
						|
  const int64_t now = ObTimeUtility::current_time();
 | 
						|
  int64_t timeout = 0;
 | 
						|
  int64_t trx_timeout = 0;
 | 
						|
  abs_timeout_us = 0;
 | 
						|
  if (!inited_) {
 | 
						|
    ret = OB_NOT_INIT;
 | 
						|
    LOG_WARN("not init", K(ret));
 | 
						|
  }
 | 
						|
 | 
						|
  if (OB_SUCC(ret)) {
 | 
						|
    if (THIS_WORKER.is_timeout()) {
 | 
						|
      ret = OB_TIMEOUT;
 | 
						|
      LOG_WARN("already timeout", K(ret), K(abs_timeout_us), K(THIS_WORKER.get_timeout_ts()));
 | 
						|
    } else {
 | 
						|
      if (THIS_WORKER.get_timeout_remain() < OB_MAX_USER_SPECIFIED_TIMEOUT) {
 | 
						|
        timeout = THIS_WORKER.get_timeout_remain();
 | 
						|
        abs_timeout_us = THIS_WORKER.get_timeout_ts();
 | 
						|
        LOG_DEBUG("set timeout by worker", K(timeout), K(abs_timeout_us));
 | 
						|
        trx_timeout = timeout;
 | 
						|
        LOG_DEBUG("set timeout according to THIS_WORKER", K(timeout), K(trx_timeout), K(abs_timeout_us));
 | 
						|
      }
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  if (OB_SUCC(ret)) {
 | 
						|
    if (ctx.is_timeout_set()) {
 | 
						|
      if (ctx.get_abs_timeout() < abs_timeout_us || 0 == abs_timeout_us) {
 | 
						|
        abs_timeout_us = ctx.get_abs_timeout();
 | 
						|
        timeout = ctx.get_timeout();
 | 
						|
        trx_timeout = timeout;
 | 
						|
      }
 | 
						|
      if (ctx.is_trx_timeout_set()) {
 | 
						|
        trx_timeout = ctx.get_trx_timeout_us();
 | 
						|
      }
 | 
						|
      if (timeout <= 0) {
 | 
						|
        ret = OB_TIMEOUT;
 | 
						|
        LOG_WARN("already timeout", K(ret), K(ctx), K(abs_timeout_us));
 | 
						|
      }
 | 
						|
    }
 | 
						|
#if !defined(NDEBUG)
 | 
						|
    LOG_DEBUG("set timeout according to time_ctx", K(timeout), K(trx_timeout), K(abs_timeout_us));
 | 
						|
#endif
 | 
						|
  }
 | 
						|
 | 
						|
  if (OB_SUCC(ret)) {
 | 
						|
    if (0 == abs_timeout_us) {
 | 
						|
      timeout = GCONF.internal_sql_execute_timeout;
 | 
						|
      trx_timeout = timeout;
 | 
						|
      abs_timeout_us = now + timeout;
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  // no need to set session timeout for outer session if no timeout ctx
 | 
						|
  if (OB_SUCC(ret) && (is_inner_session() || ctx.is_timeout_set() || ctx.is_trx_timeout_set() || is_from_pl)) {
 | 
						|
    if (!is_from_pl) {
 | 
						|
      if (OB_FAIL(set_session_timeout(timeout, trx_timeout))) {
 | 
						|
        LOG_WARN("set session timeout failed", K(timeout), K(trx_timeout), K(ret));
 | 
						|
      } else {
 | 
						|
        THIS_WORKER.set_timeout_ts(get_session().get_query_start_time() + timeout);
 | 
						|
      }
 | 
						|
    } else {
 | 
						|
      int64_t query_timeout;
 | 
						|
      OZ(get_session().get_query_timeout(query_timeout));
 | 
						|
      OX(abs_timeout_us = get_session().get_query_start_time() > 0
 | 
						|
                              ? get_session().get_query_start_time() + query_timeout
 | 
						|
                              : ObTimeUtility::current_time() + query_timeout);
 | 
						|
      if (OB_SUCC(ret) && THIS_WORKER.get_timeout_ts() > abs_timeout_us) {
 | 
						|
        OX(THIS_WORKER.set_timeout_ts(abs_timeout_us));
 | 
						|
      }
 | 
						|
    }
 | 
						|
  }
 | 
						|
  return ret;
 | 
						|
}
 | 
						|
 | 
						|
int ObInnerSQLConnection::set_session_timeout(int64_t query_timeout, int64_t trx_timeout)
 | 
						|
{
 | 
						|
  int ret = OB_SUCCESS;
 | 
						|
  if (OB_SUCC(ret)) {
 | 
						|
    LOG_DEBUG("set query timeout", K(query_timeout));
 | 
						|
    ObObj val;
 | 
						|
    val.set_int(query_timeout);
 | 
						|
    if (OB_FAIL(get_session().update_sys_variable(SYS_VAR_OB_QUERY_TIMEOUT, val))) {
 | 
						|
      LOG_WARN("set sys variable failed", K(ret), K(OB_SV_QUERY_TIMEOUT), K(val));
 | 
						|
    }
 | 
						|
  }
 | 
						|
  if (OB_SUCC(ret)) {
 | 
						|
    LOG_DEBUG("set trx timeout", K(trx_timeout));
 | 
						|
    ObObj val;
 | 
						|
    val.set_int(trx_timeout);
 | 
						|
    if (OB_FAIL(get_session().update_sys_variable(SYS_VAR_OB_TRX_TIMEOUT, val))) {
 | 
						|
      LOG_WARN("set sys variable failed", K(ret), K(OB_SV_TRX_TIMEOUT), K(val));
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  return ret;
 | 
						|
}
 | 
						|
 | 
						|
void ObInnerSQLConnection::dump_conn_bt_info()
 | 
						|
{
 | 
						|
  const int64_t BUF_SIZE = (1LL << 10);
 | 
						|
  char buf_bt[BUF_SIZE];
 | 
						|
  buf_bt[0] = '\0';
 | 
						|
  char buf_time[OB_MAX_TIMESTAMP_LENGTH];
 | 
						|
  int64_t pos = 0;
 | 
						|
  (void)ObTimeUtility2::usec_to_str(init_timestamp_, buf_time, OB_MAX_TIMESTAMP_LENGTH, pos);
 | 
						|
  pos = 0;
 | 
						|
  for (int i = 0; i < bt_size_; ++i) {
 | 
						|
    if (OB_UNLIKELY(pos + 1 > BUF_SIZE)) {
 | 
						|
      LOG_WARN("buf is not large enough", K(pos), K(BUF_SIZE));
 | 
						|
    } else {
 | 
						|
      (void)databuff_printf(buf_bt, BUF_SIZE, pos, "%p ", bt_addrs_[i]);
 | 
						|
    }
 | 
						|
  }
 | 
						|
  LOG_WARN("dump inner sql connection backtrace", "tid", tid_, "init time", buf_time, "backtrace", buf_bt);
 | 
						|
}
 | 
						|
 | 
						|
void ObInnerSQLConnection::record_stat(sql::ObSQLSessionInfo& session, const stmt::StmtType type, bool is_from_pl)
 | 
						|
{
 | 
						|
#define ADD_STMT_STAT(type)                        \
 | 
						|
  if (is_from_pl) {                                \
 | 
						|
    EVENT_INC(SQL_##type##_COUNT);                 \
 | 
						|
    EVENT_ADD(SQL_##type##_TIME, time_cost);       \
 | 
						|
  } else {                                         \
 | 
						|
    EVENT_INC(SQL_INNER_##type##_COUNT);           \
 | 
						|
    EVENT_ADD(SQL_INNER_##type##_TIME, time_cost); \
 | 
						|
  }
 | 
						|
 | 
						|
#define ADD_CASE(type)   \
 | 
						|
  case stmt::T_##type:   \
 | 
						|
    ADD_STMT_STAT(type); \
 | 
						|
    break
 | 
						|
 | 
						|
  if (lib::is_diagnose_info_enabled()) {
 | 
						|
    const int64_t now = ObTimeUtility::current_time();
 | 
						|
    const int64_t time_cost = now - session.get_query_start_time();
 | 
						|
    switch (type) {
 | 
						|
      ADD_CASE(SELECT);
 | 
						|
      ADD_CASE(INSERT);
 | 
						|
      ADD_CASE(REPLACE);
 | 
						|
      ADD_CASE(UPDATE);
 | 
						|
      ADD_CASE(DELETE);
 | 
						|
      default: {
 | 
						|
        ADD_STMT_STAT(OTHER);
 | 
						|
      }
 | 
						|
    }
 | 
						|
  }
 | 
						|
#undef ADD_STMT_STAT
 | 
						|
#undef ADD_CASE
 | 
						|
}
 | 
						|
 | 
						|
int ObInnerSQLConnection::get_session_variable(const ObString& name, int64_t& val)
 | 
						|
{
 | 
						|
  int ret = OB_SUCCESS;
 | 
						|
  if (!inited_) {
 | 
						|
    ret = OB_NOT_INIT;
 | 
						|
    LOG_WARN("not init", K(ret));
 | 
						|
  } else if (0 == name.case_compare("ob_read_snapshot_version")) {  // fake system variable
 | 
						|
    val = get_session().get_read_snapshot_version();
 | 
						|
  } else if (0 == name.case_compare("tx_isolation")) {
 | 
						|
    ObObj obj;
 | 
						|
    if (OB_FAIL(get_session().get_sys_variable_by_name(name, obj))) {
 | 
						|
      LOG_WARN("get tx_isolation system variable value fail", K(ret), K(name));
 | 
						|
    } else {
 | 
						|
      val = transaction::ObTransIsolation::get_level(obj.get_string());
 | 
						|
    }
 | 
						|
  } else {
 | 
						|
    ret = get_session().get_sys_variable_by_name(name, val);
 | 
						|
  }
 | 
						|
  return ret;
 | 
						|
}
 | 
						|
 | 
						|
int ObInnerSQLConnection::set_session_variable(const ObString& name, int64_t val)
 | 
						|
{
 | 
						|
  int ret = OB_SUCCESS;
 | 
						|
  if (!inited_) {
 | 
						|
    ret = OB_NOT_INIT;
 | 
						|
    LOG_WARN("not init", K(ret));
 | 
						|
  } else if (0 == name.case_compare("ob_read_snapshot_version")) {  // fake system variable
 | 
						|
    if (val > 0) {
 | 
						|
      LOG_INFO("inner sql with read snapshot version", K(name), K(val));
 | 
						|
    }
 | 
						|
    (void)get_session().set_read_snapshot_version(val);
 | 
						|
  } else if (0 == name.case_compare("ob_check_sys_variable")) {  // fake system variable
 | 
						|
    if (0 == val) {
 | 
						|
      LOG_INFO("disable inner sql check sys variable");
 | 
						|
    }
 | 
						|
    (void)get_session().set_check_sys_variable(0 != val);
 | 
						|
  } else if (0 == name.case_compare("tx_isolation")) {
 | 
						|
    ObObj obj;
 | 
						|
    obj.set_varchar(transaction::ObTransIsolation::get_name(val));
 | 
						|
    if (OB_FAIL(get_session().update_sys_variable_by_name(name, obj))) {
 | 
						|
      LOG_WARN("update sys variable by name fail", K(ret), K(name), K(obj), K(name), K(val));
 | 
						|
    }
 | 
						|
  } else if (OB_FAIL(get_session().update_sys_variable_by_name(name, val))) {
 | 
						|
    LOG_WARN("failed to update sys variable", K(ret), K(name), K(val));
 | 
						|
  } else if (0 == name.case_compare("ob_read_consistency")) {
 | 
						|
    LOG_INFO("YZFDEBUG inner session use weak consitency", K(val), "inner_connection_p", this);
 | 
						|
  }
 | 
						|
  return ret;
 | 
						|
}
 | 
						|
 | 
						|
ObWorker::CompatMode ObInnerSQLConnection::get_compat_mode() const
 | 
						|
{
 | 
						|
  ObWorker::CompatMode mode;
 | 
						|
  if (is_oracle_compat_mode()) {
 | 
						|
    mode = ObWorker::CompatMode::ORACLE;
 | 
						|
  } else {
 | 
						|
    mode = ObWorker::CompatMode::MYSQL;
 | 
						|
  }
 | 
						|
  return mode;
 | 
						|
}
 | 
						|
 | 
						|
// nested session and sql execute for foreign key.
 | 
						|
 | 
						|
int ObInnerSQLConnection::begin_nested_session(
 | 
						|
    ObSQLSessionInfo::StmtSavedValue& saved_session, SavedValue& saved_conn, bool skip_cur_stmt_tables)
 | 
						|
{
 | 
						|
  int ret = OB_SUCCESS;
 | 
						|
  if (!is_extern_session()) {
 | 
						|
    ret = OB_ERR_UNEXPECTED;
 | 
						|
    LOG_WARN("connection is not extern session", K(ret));
 | 
						|
  } else if (OB_FAIL(extern_session_->begin_nested_session(saved_session, skip_cur_stmt_tables))) {
 | 
						|
    LOG_WARN("failed to begin nested session", K(ret));
 | 
						|
  } else {
 | 
						|
    saved_conn.ref_ctx_ = ref_ctx_;
 | 
						|
    saved_conn.execute_start_timestamp_ = execute_start_timestamp_;
 | 
						|
    saved_conn.execute_end_timestamp_ = execute_end_timestamp_;
 | 
						|
  }
 | 
						|
  return ret;
 | 
						|
}
 | 
						|
 | 
						|
int ObInnerSQLConnection::end_nested_session(ObSQLSessionInfo::StmtSavedValue& saved_session, SavedValue& saved_conn)
 | 
						|
{
 | 
						|
  int ret = OB_SUCCESS;
 | 
						|
  if (!is_extern_session()) {
 | 
						|
    ret = OB_ERR_UNEXPECTED;
 | 
						|
    LOG_WARN("connection is not extern session", K(ret));
 | 
						|
  } else if (OB_FAIL(extern_session_->end_nested_session(saved_session))) {
 | 
						|
    LOG_WARN("failed to end nested session", K(ret));
 | 
						|
  } else {
 | 
						|
    ref_ctx_ = saved_conn.ref_ctx_;
 | 
						|
    execute_start_timestamp_ = saved_conn.execute_start_timestamp_;
 | 
						|
    execute_end_timestamp_ = saved_conn.execute_end_timestamp_;
 | 
						|
    saved_conn.reset();
 | 
						|
  }
 | 
						|
  return ret;
 | 
						|
}
 | 
						|
 | 
						|
int ObInnerSQLConnection::set_foreign_key_cascade(bool is_cascade)
 | 
						|
{
 | 
						|
  int ret = OB_SUCCESS;
 | 
						|
  OV(is_extern_session());
 | 
						|
  OX(extern_session_->set_foreign_key_casecade(is_cascade));
 | 
						|
  return ret;
 | 
						|
}
 | 
						|
 | 
						|
int ObInnerSQLConnection::get_foreign_key_cascade(bool& is_cascade) const
 | 
						|
{
 | 
						|
  int ret = OB_SUCCESS;
 | 
						|
  OV(is_extern_session());
 | 
						|
  OX(is_cascade = extern_session_->is_foreign_key_cascade());
 | 
						|
  return ret;
 | 
						|
}
 | 
						|
 | 
						|
int ObInnerSQLConnection::set_foreign_key_check_exist(bool is_check_exist)
 | 
						|
{
 | 
						|
  int ret = OB_SUCCESS;
 | 
						|
  OV(is_extern_session());
 | 
						|
  OX(extern_session_->set_foreign_key_check_exist(is_check_exist));
 | 
						|
  return ret;
 | 
						|
}
 | 
						|
 | 
						|
int ObInnerSQLConnection::get_foreign_key_check_exist(bool& is_check_exist) const
 | 
						|
{
 | 
						|
  int ret = OB_SUCCESS;
 | 
						|
  OV(is_extern_session());
 | 
						|
  OX(is_check_exist = extern_session_->is_foreign_key_check_exist());
 | 
						|
  return ret;
 | 
						|
}
 | 
						|
 | 
						|
int ObInnerSQLConnection::set_primary_schema_version(const common::ObIArray<int64_t>& primary_schema_versions)
 | 
						|
{
 | 
						|
  int ret = OB_SUCCESS;
 | 
						|
  if (OB_FAIL(primary_schema_versions_.assign(primary_schema_versions))) {
 | 
						|
    LOG_WARN("failed to copy assign schema version", K(ret), K(primary_schema_versions), K(primary_schema_versions_));
 | 
						|
  }
 | 
						|
  return ret;
 | 
						|
}
 | 
						|
}  // end of namespace observer
 | 
						|
}  // end of namespace oceanbase
 |