1509 lines
66 KiB
C++
1509 lines
66 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 PL
|
|
|
|
#include "pl/ob_pl_package_manager.h"
|
|
#include "pl/ob_pl.h"
|
|
#include "pl/ob_pl_package.h"
|
|
#include "pl/ob_pl_resolver.h"
|
|
#include "pl/ob_pl_compile.h"
|
|
#include "pl/ob_pl_stmt.h"
|
|
#include "pl/ob_pl_package_state.h"
|
|
#include "sql/session/ob_sql_session_info.h"
|
|
#include "sql/engine/ob_exec_context.h"
|
|
#include "sql/plan_cache/ob_cache_object_factory.h"
|
|
#include "sql/plan_cache/ob_plan_cache.h"
|
|
#include "sql/ob_sql_utils.h"
|
|
#include "observer/ob_server_struct.h"
|
|
#include "observer/ob_req_time_service.h"
|
|
#include "lib/file/file_directory_utils.h"
|
|
#include "pl/pl_cache/ob_pl_cache_mgr.h"
|
|
|
|
namespace oceanbase
|
|
{
|
|
using namespace common;
|
|
using namespace share::schema;
|
|
using namespace sql;
|
|
|
|
namespace pl
|
|
{
|
|
|
|
int ObPLPackageManager::read_package_sql(FILE* file, char* buf, int64_t buf_len, bool &eof)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
enum {S_LINE_START, S_NORMAL, S_COMMENT, S_TERMINATE} state = S_LINE_START;
|
|
if (OB_ISNULL(file)) {
|
|
ret = OB_ERR_NULL_VALUE;
|
|
LOG_WARN("package sql file is null", K(ret));
|
|
} else if (OB_ISNULL(buf)) {
|
|
ret = OB_ERR_NULL_VALUE;
|
|
LOG_WARN("sql buffer is null", K(ret));
|
|
} else if (buf_len <= 0) {
|
|
ret = OB_INVALID_ARGUMENT;
|
|
LOG_WARN("buffer length is invalid", K(buf_len), K(ret));
|
|
} else {
|
|
char *p = buf;
|
|
char *p_start = p;
|
|
char *p_end = p + buf_len - 1;
|
|
int c;
|
|
// clear buffer
|
|
*p = '\0';
|
|
*p_end = '\0';
|
|
while (OB_SUCC(ret) && state != S_TERMINATE) {
|
|
if (EOF == (c = fgetc(file))) {
|
|
ret = OB_IO_ERROR;
|
|
} else {
|
|
if (p >= p_end) {
|
|
ret = OB_INVALID_ARGUMENT;
|
|
LOG_WARN("query is too long", K(buf), K(buf_len), K(ret));
|
|
} else {
|
|
switch (state) {
|
|
case S_LINE_START: {
|
|
// row start with '#' or '--' is comment
|
|
if (isspace(c)) {
|
|
// ignore space
|
|
state = S_LINE_START;
|
|
} else if ('#' == c) {
|
|
state = S_COMMENT;
|
|
} else if ('-' == c) {
|
|
c = fgetc(file);
|
|
if ('-' == c) {
|
|
state = S_COMMENT;
|
|
} else if (EOF == c) {
|
|
ret = OB_IO_ERROR;
|
|
} else {
|
|
*p++ = '-';
|
|
*p++ = static_cast<char>(c);
|
|
state = S_NORMAL;
|
|
}
|
|
} else {
|
|
*p++ = static_cast<char>(c);
|
|
state = S_NORMAL;
|
|
}
|
|
}
|
|
break;
|
|
case S_COMMENT: {
|
|
if (c == '\n') {
|
|
state = S_LINE_START;
|
|
}
|
|
}
|
|
break;
|
|
case S_NORMAL: {
|
|
/* if ('#' == c) {
|
|
state = S_COMMENT;
|
|
} else */ if ('/' == c) {
|
|
if ((p != p_start) && '/' == *(p - 1)) {
|
|
*(p - 1) = '\0';
|
|
state = S_TERMINATE;
|
|
} else {
|
|
*p++ = static_cast<char>(c);
|
|
state = S_NORMAL;
|
|
}
|
|
} else {
|
|
*p++ = static_cast<char>(c);
|
|
if ('\n' == c) {
|
|
state = S_LINE_START;
|
|
} else {
|
|
state = S_NORMAL;
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
default: {
|
|
ret = OB_ERR_UNEXPECTED;
|
|
LOG_WARN("parser package file with wrong state", K(state), K(ret));
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
if (OB_FAIL(ret)) {
|
|
if (feof(file)) {
|
|
eof = true;
|
|
ret = OB_SUCCESS;
|
|
} else {
|
|
LOG_WARN("read package file error", K(errno), K(ret));
|
|
}
|
|
}
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int ObPLPackageManager::read_and_exec_package_sql(
|
|
ObMySQLProxy &sql_proxy, const char* package_full_path, ObCompatibilityMode compa_mode)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
if (!sql_proxy.is_inited() || !sql_proxy.is_active()) {
|
|
ret = OB_INVALID_ARGUMENT;
|
|
LOG_WARN("sql_proxy not inited or not active", "sql_proxy inited",
|
|
sql_proxy.is_inited(), "sql_proxy active", sql_proxy.is_active(), K(ret));
|
|
} else {
|
|
FILE* file = NULL;
|
|
int64_t affected_rows = 0;
|
|
if (access(package_full_path, F_OK) != 0) {
|
|
LOG_INFO("package sql file not exists", K(package_full_path), K(ret));
|
|
} else if (OB_ISNULL(file = fopen(package_full_path, "rb"))) {
|
|
ret = OB_IO_ERROR;
|
|
LOG_WARN("package sql file open failed", K(package_full_path), K(ret));
|
|
} else {
|
|
// system tenant will run with mysql compatibility mode
|
|
// but we need to create system packages with oralce compatibility
|
|
// here hack to oracle mode
|
|
bool eof = false;
|
|
SMART_VAR(char[OB_MAX_SQL_LENGTH], sql_buf) {
|
|
while (OB_SUCC(ret) && !eof) {
|
|
if (OB_FAIL(read_package_sql(file, sql_buf, OB_MAX_SQL_LENGTH, eof))) {
|
|
LOG_WARN("fail to read package sql file", K(ret));
|
|
} else if (strlen(sql_buf) != 0
|
|
&& OB_FAIL(sql_proxy.write(OB_SYS_TENANT_ID,
|
|
sql_buf,
|
|
affected_rows,
|
|
static_cast<int64_t>(compa_mode)))) {
|
|
LOG_WARN("fail to exec package sql", K(sql_buf), K(ret));
|
|
} else if (affected_rows != 0) {
|
|
ret = OB_ERR_UNEXPECTED;
|
|
LOG_WARN("affected_rows expected to be zero", K(affected_rows), K(ret));
|
|
} else {
|
|
OZ (ObSPIService::force_refresh_schema(OB_SYS_TENANT_ID));
|
|
}
|
|
}
|
|
}
|
|
fclose(file);
|
|
}
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int ObPLPackageManager::load_sys_package(
|
|
ObMySQLProxy &sql_proxy, const char *package_spec_name, const char *package_body_name, ObCompatibilityMode compa_mode)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
const int64_t begin_time = ObTimeUtility::current_time();
|
|
LOG_INFO("load sys package begin",
|
|
"package name", package_spec_name, "package body name", package_body_name);
|
|
|
|
if (OB_FAIL(read_and_exec_package_sql(sql_proxy, package_spec_name, compa_mode))) {
|
|
LOG_WARN("fail to read and exec package header sql", K(package_spec_name), K(ret));
|
|
} else if (OB_FAIL(read_and_exec_package_sql(sql_proxy, package_body_name, compa_mode))) {
|
|
LOG_WARN("fail to read and exec package body sql", K(package_body_name), K(ret));
|
|
}
|
|
|
|
const int64_t now = ObTimeUtility::current_time();
|
|
LOG_INFO("load sys package finish", "total_time_used", now - begin_time);
|
|
return ret;
|
|
}
|
|
|
|
static const char* sys_package_dir = "admin";
|
|
static ObSysPackageFile oracle_sys_package_file_table[] = {
|
|
#ifdef OB_BUILD_ORACLE_PL
|
|
{"dbms_standard", "dbms_standard.sql", "dbms_standard_body.sql"},
|
|
{"dbms_output", "dbms_output.sql", "dbms_output_body.sql"},
|
|
{"dbms_metadata", "dbms_metadata.sql", "dbms_metadata_body.sql"},
|
|
{"dbms_spm", "dbms_spm.sql", "dbms_spm_body.sql"},
|
|
{"utl_raw", "utl_raw.sql", "utl_raw_body.sql"},
|
|
{"dbms_lob", "dbms_lob.sql", "dbms_lob_body.sql"},
|
|
{"sa_components", "sa_components.sql", "sa_components_body.sql"},
|
|
{"sa_label_admin", "sa_label_admin.sql", "sa_label_admin_body.sql"},
|
|
{"sa_policy_admin", "sa_policy_admin.sql", "sa_policy_admin_body.sql"},
|
|
{"sa_session", "sa_session.sql", "sa_session_body.sql"},
|
|
{"sa_sysdba", "sa_sysdba.sql", "sa_sysdba_body.sql"},
|
|
{"sa_user_admin", "sa_user_admin.sql", "sa_user_admin_body.sql"},
|
|
{"utl_i18n", "utl_i18n.sql", "utl_i18n_body.sql"},
|
|
{"dbms_crypto", "dbms_crypto.sql","dbms_crypto_body.sql"},
|
|
{"dbms_random", "dbms_random.sql", "dbms_random_body.sql"},
|
|
{"dbms_debug", "dbms_debug.sql", "dbms_debug_body.sql"},
|
|
{"utl_inaddr", "utl_inaddr.sql", "utl_inaddr_body.sql"},
|
|
{"utl_encode", "dbms_utl_encode.sql", "dbms_utl_encode_body.sql"},
|
|
{"dbms_warning", "dbms_warning.sql", "dbms_warning_body.sql"},
|
|
{"dbms_errlog", "dbms_errlog.sql", "dbms_errlog_body.sql"},
|
|
{"dbms_lock", "dbms_lock.sql", "dbms_lock_body.sql"},
|
|
{"dbms_sql", "dbms_sql.sql", "dbms_sql_body.sql"},
|
|
{"dbms_xa", "dbms_xa.sql", "dbms_xa_body.sql"},
|
|
{"dbms_resource_manager", "dbms_resource_manager.sql", "dbms_resource_manager_body.sql"},
|
|
{"dbms_utility", "dbms_utility.sql", "dbms_utility_body.sql"},
|
|
{"odciconst", "odciconst.sql", "odciconst_body.sql"},
|
|
{"dbms_stats", "dbms_stats.sql", "dbms_stats_body.sql"},
|
|
{"dbms_any", "dbms_any.sql", "dbms_any_body.sql"},
|
|
{"xml_type", "xml_type.sql", "xml_type_body.sql"},
|
|
{"dbms_crypto", "dbms_crypto.sql", "dbms_crypto_body.sql"},
|
|
{"dbms_ijob", "dbms_ijob.sql", "dbms_ijob_body.sql"},
|
|
{"dbms_job", "dbms_job.sql", "dbms_job_body.sql"},
|
|
{"dbms_ischeduler", "dbms_ischeduler.sql", "dbms_ischeduler_body.sql"},
|
|
{"dbms_scheduler", "dbms_scheduler.sql", "dbms_scheduler_body.sql"},
|
|
{"catodci", "catodci.sql", "catodci_body.sql"},
|
|
{"dbms_describe", "dbms_describe.sql", "dbms_describe_body.sql"},
|
|
{"utl_file", "utl_file.sql", "utl_file_body.sql"},
|
|
{"dbms_plan_cache", "dbms_plancache.sql", "dbms_plancache_body.sql"},
|
|
{"dbms_sys_error", "dbms_sys_error.sql", "dbms_sys_error_body.sql"},
|
|
{"dbms_preprocessor", "dbms_preprocessor.sql", "dbms_preprocessor_body.sql"},
|
|
{"dbms_audit_mgmt", "dbms_audit_mgmt.sql", "dbms_audit_mgmt_body.sql"},
|
|
{"dbms_application", "dbms_application.sql", "dbms_application_body.sql"},
|
|
{"dbms_session", "dbms_session.sql", "dbms_session_body.sql"},
|
|
{"dbms_monitor", "dbms_monitor.sql", "dbms_monitor_body.sql"},
|
|
{"dbms_xplan", "dbms_xplan.sql", "dbms_xplan_body.sql"},
|
|
{"dbms_workload_repository", "dbms_workload_repository.sql", "dbms_workload_repository_body.sql"},
|
|
{"dbms_ash_internal", "dbms_ash_internal.sql", "dbms_ash_internal_body.sql"},
|
|
{"dbms_rls", "dbms_rls.sql", "dbms_rls_body.sql"},
|
|
{"dbms_udr", "dbms_udr.sql", "dbms_udr_body.sql"},
|
|
{"json_element_t", "json_element_type.sql", "json_element_type_body.sql"},
|
|
{"json_object_t", "json_object_type.sql", "json_object_type_body.sql"},
|
|
#endif
|
|
};
|
|
|
|
static ObSysPackageFile mysql_sys_package_file_table[] = {
|
|
{"dbms_stats", "dbms_stats_mysql.sql", "dbms_stats_body_mysql.sql"},
|
|
{"dbms_scheduler", "dbms_scheduler_mysql.sql", "dbms_scheduler_mysql_body.sql"},
|
|
{"dbms_application", "dbms_application_mysql.sql", "dbms_application_body_mysql.sql"},
|
|
{"dbms_session", "dbms_session_mysql.sql", "dbms_session_body_mysql.sql"},
|
|
{"dbms_monitor", "dbms_monitor_mysql.sql", "dbms_monitor_body_mysql.sql"},
|
|
{"dbms_resource_manager", "dbms_resource_manager_mysql.sql", "dbms_resource_manager_body_mysql.sql"},
|
|
#ifdef OB_BUILD_ORACLE_PL
|
|
{"dbms_xplan", "dbms_xplan_mysql.sql", "dbms_xplan_mysql_body.sql"},
|
|
{"dbms_spm", "dbms_spm_mysql.sql", "dbms_spm_body_mysql.sql"},
|
|
#endif
|
|
{"dbms_udr", "dbms_udr_mysql.sql", "dbms_udr_body_mysql.sql"},
|
|
{"dbms_workload_repository", "dbms_workload_repository_mysql.sql", "dbms_workload_repository_body_mysql.sql"}
|
|
};
|
|
|
|
int ObPLPackageManager::load_sys_package(ObMySQLProxy &sql_proxy, ObString &package_name, ObCompatibilityMode compa_mode)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
char package_spec_full_path[MAX_PATH_SIZE] = {};
|
|
char package_body_full_path[MAX_PATH_SIZE] = {};
|
|
bool dir_exists = false;
|
|
bool package_exists = false;
|
|
if (OB_FAIL(FileDirectoryUtils::is_exists(sys_package_dir, dir_exists))) {
|
|
LOG_WARN("check sys package dir whether exist failed", K(ret), K(sys_package_dir));
|
|
} else if (!dir_exists) {
|
|
ret = OB_ENTRY_NOT_EXIST;
|
|
LOG_WARN("sys package dir not exist", K(ret), K(sys_package_dir));
|
|
}
|
|
if (ObCompatibilityMode::ORACLE_MODE == compa_mode) {
|
|
int sys_package_count = ARRAYSIZEOF(oracle_sys_package_file_table);
|
|
for (int64_t i = 0; OB_SUCC(ret) && i < sys_package_count; ++i) {
|
|
if (0 == package_name.case_compare(ObString(oracle_sys_package_file_table[i].package_name))) {
|
|
const char *package_spec_name = oracle_sys_package_file_table[i].package_spec_file_name;
|
|
const char *package_body_name = oracle_sys_package_file_table[i].package_body_file_name;
|
|
OZ (databuff_printf(
|
|
package_spec_full_path, MAX_PATH_SIZE, "%s/%s", sys_package_dir, package_spec_name));
|
|
OZ (databuff_printf(
|
|
package_body_full_path, MAX_PATH_SIZE, "%s/%s", sys_package_dir, package_body_name));
|
|
OX (package_exists = true);
|
|
break;
|
|
}
|
|
}
|
|
} else if (ObCompatibilityMode::MYSQL_MODE == compa_mode) {
|
|
int sys_package_count = ARRAYSIZEOF(mysql_sys_package_file_table);
|
|
for (int64_t i = 0; OB_SUCC(ret) && i < sys_package_count; ++i) {
|
|
if (0 == package_name.case_compare(ObString(mysql_sys_package_file_table[i].package_name))) {
|
|
const char *package_spec_name = mysql_sys_package_file_table[i].package_spec_file_name;
|
|
const char *package_body_name = mysql_sys_package_file_table[i].package_body_file_name;
|
|
OZ (databuff_printf(
|
|
package_spec_full_path, MAX_PATH_SIZE, "%s/%s", sys_package_dir, package_spec_name));
|
|
OZ (databuff_printf(
|
|
package_body_full_path, MAX_PATH_SIZE, "%s/%s", sys_package_dir, package_body_name));
|
|
OX (package_exists = true);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
if (OB_SUCC(ret) && !package_exists) {
|
|
ret = OB_ERR_PACKAGE_DOSE_NOT_EXIST;
|
|
LOG_WARN("package not exists", K(ret), K(package_name));
|
|
LOG_USER_ERROR(OB_ERR_PACKAGE_DOSE_NOT_EXIST,
|
|
"PACKAGE",
|
|
ObString("oceanbase").length(), ObString("oceanbase").ptr(),
|
|
package_name.length(), package_name.ptr());
|
|
}
|
|
OZ (load_sys_package(sql_proxy, package_spec_full_path, package_body_full_path, compa_mode));
|
|
return ret;
|
|
}
|
|
|
|
int ObPLPackageManager::load_all_common_sys_package(ObMySQLProxy &sql_proxy,
|
|
const ObSysPackageFile *package_file,
|
|
int sys_package_count,
|
|
ObCompatibilityMode compa_mode)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
char package_spec_full_path[MAX_PATH_SIZE] = {};
|
|
char package_body_full_path[MAX_PATH_SIZE] = {};
|
|
CK (OB_NOT_NULL(package_file));
|
|
LOG_INFO("load all sys package begin", "sys package total count", sys_package_count);
|
|
for (int i = 0; OB_SUCC(ret) && i < sys_package_count; ++i) {
|
|
const char *package_spec_name = package_file[i].package_spec_file_name;
|
|
const char *package_body_name = package_file[i].package_body_file_name;
|
|
OZ (databuff_printf(
|
|
package_spec_full_path, MAX_PATH_SIZE, "%s/%s", sys_package_dir, package_spec_name));
|
|
OZ (databuff_printf(
|
|
package_body_full_path, MAX_PATH_SIZE, "%s/%s", sys_package_dir, package_body_name));
|
|
if (OB_SUCC(ret)) {
|
|
LOG_INFO("load sys package begin", K(package_spec_name));
|
|
if (OB_FAIL(load_sys_package(sql_proxy, package_spec_full_path, package_body_full_path, compa_mode))) {
|
|
LOG_WARN("load sys package failed",
|
|
K(package_spec_full_path), K(package_body_full_path), K(compa_mode), K(ret));
|
|
} else {
|
|
LOG_INFO("load sys package success", K(ret), K(package_spec_name));
|
|
}
|
|
}
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int ObPLPackageManager::load_all_common_sys_package(ObMySQLProxy &sql_proxy, ObCompatibilityMode need_compa_mode)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
bool exist = false;
|
|
if (OB_FAIL(FileDirectoryUtils::is_exists(sys_package_dir, exist))) {
|
|
LOG_WARN("check sys package dir whether exist failed", K(sys_package_dir), K(ret));
|
|
} else if (!exist) {
|
|
LOG_INFO("sys package dir not exist", K(sys_package_dir));
|
|
} else {
|
|
if (need_compa_mode == ObCompatibilityMode::OCEANBASE_MODE) {
|
|
OZ (load_all_common_sys_package(sql_proxy, oracle_sys_package_file_table,
|
|
ARRAYSIZEOF(oracle_sys_package_file_table), ObCompatibilityMode::ORACLE_MODE));
|
|
OZ (load_all_common_sys_package(sql_proxy, mysql_sys_package_file_table,
|
|
ARRAYSIZEOF(mysql_sys_package_file_table), ObCompatibilityMode::MYSQL_MODE));
|
|
} else if (need_compa_mode == ObCompatibilityMode::ORACLE_MODE) {
|
|
OZ (load_all_common_sys_package(sql_proxy, oracle_sys_package_file_table,
|
|
ARRAYSIZEOF(oracle_sys_package_file_table), ObCompatibilityMode::ORACLE_MODE));
|
|
} else if (need_compa_mode == ObCompatibilityMode::MYSQL_MODE) {
|
|
OZ (load_all_common_sys_package(sql_proxy, mysql_sys_package_file_table,
|
|
ARRAYSIZEOF(mysql_sys_package_file_table), ObCompatibilityMode::MYSQL_MODE));
|
|
}
|
|
}
|
|
if (OB_SUCC(ret)) {
|
|
LOG_INFO("load all common sys package success!");
|
|
} else {
|
|
LOG_INFO("load all common sys package failed!");
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int ObPLPackageManager::load_all_special_sys_package(ObMySQLProxy &sql_proxy)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
bool exist = false;
|
|
if (OB_FAIL(FileDirectoryUtils::is_exists(sys_package_dir, exist))) {
|
|
LOG_WARN("check sys package dir whether exist failed", K(sys_package_dir), K(ret));
|
|
} else if (!exist) {
|
|
LOG_INFO("sys package dir not exist", K(sys_package_dir));
|
|
} else {
|
|
// for now! we only have one special system package "__DBMS_UPGRADE"
|
|
char package_spec_full_path[MAX_PATH_SIZE] = {};
|
|
char package_body_full_path[MAX_PATH_SIZE] = {};
|
|
|
|
#ifdef OB_BUILD_ORACLE_PL
|
|
OZ (databuff_printf(
|
|
package_spec_full_path, MAX_PATH_SIZE, "%s/%s", sys_package_dir, "__dbms_upgrade.sql"));
|
|
OZ (databuff_printf(
|
|
package_body_full_path, MAX_PATH_SIZE, "%s/%s", sys_package_dir, "__dbms_upgrade_body.sql"));
|
|
OZ (load_sys_package(sql_proxy, package_spec_full_path, package_body_full_path, ObCompatibilityMode::ORACLE_MODE));
|
|
#endif
|
|
|
|
memset(package_spec_full_path, 0, sizeof(package_spec_full_path));
|
|
memset(package_body_full_path, 0, sizeof(package_body_full_path));
|
|
OZ (databuff_printf(
|
|
package_spec_full_path, MAX_PATH_SIZE, "%s/%s", sys_package_dir, "__dbms_upgrade_mysql.sql"));
|
|
OZ (databuff_printf(
|
|
package_body_full_path, MAX_PATH_SIZE, "%s/%s", sys_package_dir, "__dbms_upgrade_body_mysql.sql"));
|
|
OZ (load_sys_package(sql_proxy, package_spec_full_path, package_body_full_path, ObCompatibilityMode::MYSQL_MODE));
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int ObPLPackageManager::load_all_sys_package(ObMySQLProxy &sql_proxy)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
OZ (load_all_common_sys_package(sql_proxy, ObCompatibilityMode::OCEANBASE_MODE));
|
|
OZ (load_all_special_sys_package(sql_proxy));
|
|
if (OB_SUCC(ret)) {
|
|
LOG_INFO("load all sys package success!", K(ret));
|
|
} else {
|
|
LOG_INFO("load all sys package failed!", K(ret));
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int ObPLPackageManager::get_package_var(const ObPLResolveCtx &resolve_ctx, uint64_t package_id,
|
|
const ObString &var_name, const ObPLVar *&var, int64_t &var_idx)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
var = NULL;
|
|
var_idx = OB_INVALID_INDEX;
|
|
if (OB_INVALID_ID == package_id || var_name.empty()) {
|
|
ret = OB_ERR_UNEXPECTED;
|
|
LOG_WARN("package id or var name invalid", K(package_id), K(var_name), K(ret));
|
|
} else {
|
|
ObPLPackage *package_spec = NULL;
|
|
if (OB_FAIL(get_cached_package_spec(resolve_ctx, package_id, package_spec))) {
|
|
LOG_WARN("get cached package spec failed", K(package_id), K(ret));
|
|
} else if (OB_ISNULL(package_spec)){
|
|
ret = OB_ERR_PACKAGE_DOSE_NOT_EXIST;
|
|
LOG_WARN("package not exist", K(package_id), K(ret));
|
|
} else {
|
|
if (OB_FAIL(package_spec->get_var(var_name, var, var_idx))) {
|
|
LOG_WARN("package get var failed", K(package_id), K(var_name), K(ret));
|
|
}
|
|
}
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int ObPLPackageManager::get_package_var(const ObPLResolveCtx &resolve_ctx, uint64_t package_id,
|
|
int64_t var_idx, const ObPLVar *&var)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
var = NULL;
|
|
if (OB_INVALID_ID == package_id || OB_INVALID_INDEX == var_idx) {
|
|
ret = OB_ERR_UNEXPECTED;
|
|
LOG_WARN("package id or var index invalid", K(package_id), K(var_idx), K(ret));
|
|
} else {
|
|
ObPLPackage *package_spec = NULL;
|
|
ObPLPackage *package_body = NULL;
|
|
if (OB_FAIL(get_cached_package(resolve_ctx, package_id, package_spec, package_body, true))) {
|
|
LOG_WARN("get cached package failed", K(package_id), K(ret));
|
|
} else if (OB_ISNULL(package_spec)){
|
|
ret = OB_ERR_PACKAGE_DOSE_NOT_EXIST;
|
|
LOG_WARN("package spec not exist", K(package_id), K(ret));
|
|
} else {
|
|
const ObPLPackage *tmp_package = NULL;
|
|
if (package_id == package_spec->get_id()) {
|
|
tmp_package = package_spec;
|
|
} else if (!OB_ISNULL(package_body) && package_id == package_body->get_id()) {
|
|
tmp_package = package_body;
|
|
} else {
|
|
ret = OB_ERR_PACKAGE_DOSE_NOT_EXIST;
|
|
LOG_WARN("package body not exist", K(package_id), K(ret));
|
|
LOG_USER_ERROR(OB_ERR_PACKAGE_DOSE_NOT_EXIST, "PACKAGE BODY",
|
|
package_spec->get_db_name().length(), package_spec->get_db_name().ptr(),
|
|
package_spec->get_name().length(), package_spec->get_name().ptr());
|
|
}
|
|
if (OB_SUCC(ret)) {
|
|
if (OB_FAIL(tmp_package->get_var(var_idx, var))) {
|
|
LOG_WARN("package get var failed", K(ret));
|
|
} else if (OB_ISNULL(var)) {
|
|
ret = OB_ERR_UNEXPECTED;
|
|
LOG_WARN("package var not found", K(package_id), K(var_idx), K(ret));
|
|
} else if (!var->is_readonly() && OB_ISNULL(package_body)) {// 对于非constant值, 需要保证body的合法性
|
|
OZ (get_cached_package(resolve_ctx, package_id, package_spec, package_body, false));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int ObPLPackageManager::get_package_type(const ObPLResolveCtx &resolve_ctx,
|
|
uint64_t package_id,
|
|
const ObString &type_name,
|
|
const ObUserDefinedType *&user_type,
|
|
bool log_user_error)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
user_type = NULL;
|
|
if (OB_INVALID_ID == package_id || type_name.empty()) {
|
|
ret = OB_ERR_UNEXPECTED;
|
|
LOG_WARN("package id or type name invalid", K(package_id), K(type_name), K(ret));
|
|
} else {
|
|
observer::ObReqTimeGuard req_timeinfo_guard;
|
|
ObPLPackage *package_spec = NULL;
|
|
if (OB_FAIL(get_cached_package_spec(resolve_ctx, package_id, package_spec))) {
|
|
LOG_WARN("get cached package failed", K(ret));
|
|
} else if (OB_ISNULL(package_spec)){
|
|
ret = OB_ERR_PACKAGE_DOSE_NOT_EXIST;
|
|
LOG_WARN("package spec not exist", K(package_id), K(ret));
|
|
} else {
|
|
if (OB_FAIL(package_spec->get_type(type_name, user_type))) {
|
|
LOG_WARN("package get type failed", K(package_id), K(type_name), K(ret));
|
|
} else if (OB_ISNULL(user_type)) {
|
|
ret = OB_ERR_SP_UNDECLARED_TYPE;
|
|
LOG_WARN("package type not found", K(package_id), K(type_name), K(ret));
|
|
if (log_user_error) {
|
|
LOG_USER_ERROR(OB_ERR_SP_UNDECLARED_TYPE, type_name.length(), type_name.ptr());
|
|
} else {}
|
|
} else {}
|
|
}
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int ObPLPackageManager::get_package_type(const ObPLResolveCtx &resolve_ctx, uint64_t package_id,
|
|
uint64_t type_id, const ObUserDefinedType *&user_type)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
user_type = NULL;
|
|
if (OB_INVALID_ID == package_id || OB_INVALID_INDEX == type_id) {
|
|
ret = OB_ERR_UNEXPECTED;
|
|
LOG_WARN("package id or type index invalid", K(package_id), K(type_id), K(ret));
|
|
} else {
|
|
ObPLPackage *package_spec = NULL;
|
|
ObPLPackage *package_body = NULL;
|
|
if (OB_FAIL(get_cached_package(resolve_ctx, package_id, package_spec, package_body, true))) {
|
|
LOG_WARN("get cached package failed", K(ret));
|
|
} else if (OB_ISNULL(package_spec)){
|
|
ret = OB_ERR_PACKAGE_DOSE_NOT_EXIST;
|
|
LOG_WARN("package spec not exist", K(package_id), K(ret));
|
|
} else {
|
|
const ObPLPackage *tmp_package = NULL;
|
|
if (package_id == package_spec->get_id()) {
|
|
tmp_package = package_spec;
|
|
} else if (OB_NOT_NULL(package_body) && package_id == package_body->get_id()) {
|
|
tmp_package = package_body;
|
|
} else {
|
|
ret = OB_ERR_PACKAGE_DOSE_NOT_EXIST;
|
|
LOG_WARN("package body not exist", K(package_id), K(ret));
|
|
LOG_USER_ERROR(OB_ERR_PACKAGE_DOSE_NOT_EXIST, "PACKAGE BODY",
|
|
package_spec->get_db_name().length(), package_spec->get_db_name().ptr(),
|
|
package_spec->get_name().length(), package_spec->get_name().ptr());
|
|
}
|
|
if (OB_SUCC(ret)) {
|
|
if (OB_FAIL(tmp_package->get_type(type_id, user_type))) {
|
|
LOG_WARN("get package type failed", K(ret));
|
|
} else if (OB_ISNULL(user_type)) {
|
|
ret = OB_ERR_UNEXPECTED;
|
|
LOG_WARN("package type not found", K(ret));
|
|
} else {}
|
|
}
|
|
}
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int ObPLPackageManager::get_package_expr(const ObPLResolveCtx &resolve_ctx,
|
|
uint64_t package_id,
|
|
int64_t expr_idx,
|
|
ObSqlExpression *&expr)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
if (OB_INVALID_ID == package_id || OB_INVALID_ID == expr_idx) {
|
|
ret = OB_ERR_UNEXPECTED;
|
|
LOG_WARN("package id or expr idx invalid", K(ret), K(package_id), K(expr_idx));
|
|
} else {
|
|
observer::ObReqTimeGuard req_timeinfo_guard;
|
|
ObPLPackage *package_spec = NULL;
|
|
if (OB_FAIL(get_cached_package_spec(resolve_ctx, package_id, package_spec))) {
|
|
LOG_WARN("get cached package failed", K(ret));
|
|
} else if (OB_ISNULL(package_spec)){
|
|
ret = OB_ERR_PACKAGE_DOSE_NOT_EXIST;
|
|
LOG_WARN("package spec not exist", K(package_id), K(ret));
|
|
} else if (OB_ISNULL(expr = package_spec->get_default_expr(expr_idx))) {
|
|
ret = OB_ERR_UNEXPECTED;
|
|
LOG_WARN("package expr not exist",
|
|
K(ret), K(expr_idx), K(package_id), K(package_spec->get_default_exprs().count()));
|
|
}
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int ObPLPackageManager::get_package_cursor(const ObPLResolveCtx &resolve_ctx,
|
|
uint64_t package_id,
|
|
int64_t cursor_id,
|
|
const ObPLCursor *&cursor)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
ObPLPackage *package_spec = NULL;
|
|
ObPLPackage *package_body = NULL;
|
|
ObPLPackage *tmp_package = NULL;
|
|
cursor = NULL;
|
|
CK (package_id != OB_INVALID_ID);
|
|
CK (cursor_id != OB_INVALID_INDEX);
|
|
OZ (get_cached_package(resolve_ctx, package_id, package_spec, package_body));
|
|
OX (tmp_package = package_spec != NULL && package_spec->get_id() == package_id
|
|
? package_spec
|
|
: package_body != NULL && package_body->get_id() == package_id
|
|
? package_body : NULL);
|
|
if (OB_SUCC(ret) && OB_ISNULL(tmp_package)) {
|
|
ret = OB_ERR_PACKAGE_DOSE_NOT_EXIST;
|
|
LOG_WARN("package spec does not exist", K(ret), K(package_id));
|
|
}
|
|
OZ (tmp_package->get_cursor(cursor_id, cursor));
|
|
return ret;
|
|
}
|
|
|
|
int ObPLPackageManager::get_package_cursor(const ObPLResolveCtx &resolve_ctx,
|
|
uint64_t package_id,
|
|
const ObString &cursor_name,
|
|
const ObPLCursor *&cursor,
|
|
int64_t &cursor_idx)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
ObPLPackage *package_spec = NULL;
|
|
ObPLPackage *package_body = NULL;
|
|
ObPLPackage *tmp_package = NULL;
|
|
cursor = NULL;
|
|
cursor_idx = OB_INVALID_INDEX;
|
|
CK (package_id != OB_INVALID_ID);
|
|
CK (!cursor_name.empty());
|
|
OZ (get_cached_package(resolve_ctx, package_id, package_spec, package_body));
|
|
OX (tmp_package = package_spec != NULL && package_spec->get_id() == package_id
|
|
? package_spec
|
|
: package_body != NULL && package_body->get_id() == package_id
|
|
? package_body : NULL);
|
|
if (OB_SUCC(ret) && OB_ISNULL(tmp_package)) {
|
|
ret = OB_ERR_PACKAGE_DOSE_NOT_EXIST;
|
|
LOG_WARN("package spec does not exist", K(ret), K(package_id));
|
|
}
|
|
OZ (tmp_package->get_cursor(cursor_name, cursor, cursor_idx));
|
|
if (OB_FAIL(ret) || OB_ISNULL(cursor)) {
|
|
} else if (ObPLCursor::DUP_DECL == cursor->get_state()) {
|
|
ret = OB_ERR_SP_DUP_CURSOR;
|
|
LOG_WARN("too many declarations of cursor match this call",
|
|
K(ret), K(cursor_name), K(cursor_idx));
|
|
} else if (ObPLCursor::DECLARED == cursor->get_state()) {
|
|
CK (tmp_package != package_body);
|
|
CK (OB_NOT_NULL(package_body));
|
|
OZ (package_body->get_cursor(
|
|
cursor->get_package_id(), cursor->get_routine_id(), cursor->get_index(), cursor));
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int ObPLPackageManager::get_package_condition(const ObPLResolveCtx &resolve_ctx,
|
|
uint64_t package_id,
|
|
const ObString &condition_name,
|
|
const ObPLCondition *&value)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
ObPLPackage *package_spec = NULL;
|
|
ObPLPackage *package_body = NULL;
|
|
ObPLPackage *tmp_package = NULL;
|
|
value = NULL;
|
|
CK (package_id != OB_INVALID_ID);
|
|
CK (!condition_name.empty());
|
|
OZ (get_cached_package(resolve_ctx, package_id, package_spec, package_body, true));
|
|
OX (tmp_package = (package_spec != NULL && package_spec->get_id() == package_id) ? package_spec :
|
|
(package_body != NULL && package_body->get_id() == package_id) ? package_body :
|
|
NULL);
|
|
if (OB_SUCC(ret) && OB_ISNULL(tmp_package)) {
|
|
ret = OB_ERR_PACKAGE_DOSE_NOT_EXIST;
|
|
LOG_WARN("package spec does not exist", K(ret), K(package_id));
|
|
}
|
|
CK (OB_NOT_NULL(tmp_package));
|
|
OZ (tmp_package->get_condition(condition_name, value));
|
|
return ret;
|
|
}
|
|
|
|
int ObPLPackageManager::get_package_routine(const ObPLResolveCtx &ctx,
|
|
sql::ObExecContext &exec_ctx,
|
|
uint64_t package_id,
|
|
int64_t routine_idx,
|
|
ObPLFunction *&routine)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
routine = NULL;
|
|
bool is_overflow = false;
|
|
if (OB_FAIL(check_stack_overflow(is_overflow))) {
|
|
LOG_WARN("failed to check stack overflow", K(ret));
|
|
} else if (is_overflow) {
|
|
ret = OB_SIZE_OVERFLOW;
|
|
LOG_WARN("too deep recusive", K(ret));
|
|
}
|
|
CK (OB_LIKELY(OB_INVALID_ID != package_id));
|
|
CK (OB_LIKELY(OB_INVALID_INDEX != routine_idx));
|
|
|
|
if (OB_SUCC(ret)) {
|
|
ObPLPackage *package_spec = NULL;
|
|
ObPLPackage *package_body = NULL;
|
|
OZ (get_cached_package(ctx, package_id, package_spec, package_body));
|
|
CK (OB_NOT_NULL(package_spec));
|
|
if (OB_SUCC(ret) && OB_ISNULL(package_body)){
|
|
ret = OB_ERR_PACKAGE_DOSE_NOT_EXIST;
|
|
LOG_USER_ERROR(OB_ERR_PACKAGE_DOSE_NOT_EXIST, "PACKAGE BODY",
|
|
package_spec->get_db_name().length(), package_spec->get_db_name().ptr(),
|
|
package_spec->get_name().length(), package_spec->get_name().ptr());
|
|
}
|
|
OZ (package_body->get_routine(routine_idx, routine));
|
|
if (OB_SUCC(ret) && OB_ISNULL(routine)) {
|
|
ret = OB_ERR_SP_DOES_NOT_EXIST;
|
|
LOG_WARN("can not found package routine in package body", K(ret), K(routine_idx), K(routine));
|
|
} else {
|
|
ObPLPackageState *dummy_state = NULL;
|
|
if (OB_SUCC(ret) && OB_NOT_NULL(package_body->get_init_routine())) {
|
|
// call一个pacakge 函数的时候,去执行package的init 函数
|
|
OZ (get_package_state(ctx, exec_ctx, package_id, dummy_state));
|
|
}
|
|
}
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int ObPLPackageManager::get_package_var_val(const ObPLResolveCtx &resolve_ctx,
|
|
sql::ObExecContext &exec_ctx,
|
|
uint64_t package_id,
|
|
int64_t spec_version,
|
|
int64_t body_version,
|
|
int64_t var_idx,
|
|
ObObj &var_val)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
const ObPLVar *var = NULL;
|
|
ObPLPackageState *package_state = NULL;
|
|
ObPackageStateVersion version(spec_version, body_version);
|
|
CK (package_id != OB_INVALID_ID);
|
|
CK (var_idx != OB_INVALID_INDEX);
|
|
OZ (get_package_item_state(
|
|
resolve_ctx.session_info_, package_id, version, package_state));
|
|
if (OB_SUCC(ret) && OB_ISNULL(package_state)) {
|
|
OZ (get_package_var(resolve_ctx, package_id, var_idx, var),
|
|
K(package_id), K(var_idx));
|
|
CK (OB_NOT_NULL(var));
|
|
OZ (get_package_state(
|
|
resolve_ctx, exec_ctx, package_id, package_state, var->is_readonly()),
|
|
K(package_id), K(var_idx), K(var->is_readonly()));
|
|
}
|
|
OZ (package_state->get_package_var_val(var_idx, var_val),
|
|
K(var_idx));
|
|
return ret;
|
|
}
|
|
|
|
int ObPLPackageManager::set_package_var_val(const ObPLResolveCtx &resolve_ctx,
|
|
sql::ObExecContext &exec_ctx,
|
|
uint64_t package_id,
|
|
int64_t var_idx,
|
|
const ObObj &var_val,
|
|
bool need_deserialize,
|
|
bool from_proxy)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
ObPLPackageState *package_state = NULL;
|
|
ObObj old_var_val;
|
|
ObObj new_var_val = var_val;
|
|
const ObPLVar *var = NULL;
|
|
CK (package_id != OB_INVALID_ID);
|
|
CK (var_idx != OB_INVALID_INDEX);
|
|
OZ (get_package_state(resolve_ctx, exec_ctx, package_id, package_state),
|
|
K(package_id), K(var_idx), K(var_val));
|
|
OZ (package_state->get_package_var_val(var_idx, old_var_val), K(package_id), K(var_idx));
|
|
OZ (get_package_var(resolve_ctx, package_id, var_idx, var), K(package_id), K(var_idx));
|
|
OV (OB_NOT_NULL(var), OB_ERR_UNEXPECTED, K(package_id), K(var_idx));
|
|
if (need_deserialize) {
|
|
OZ (var->get_type().init_session_var(resolve_ctx,
|
|
var->get_type().is_cursor_type() ?
|
|
package_state->get_pkg_cursor_allocator()
|
|
: package_state->get_pkg_allocator(),
|
|
exec_ctx,
|
|
NULL,
|
|
false,
|
|
new_var_val), K(package_id), K(var_idx), K(var_val));
|
|
if (OB_FAIL(ret)) {
|
|
} else if (var->get_type().is_cursor_type()) {
|
|
OV (var_val.is_tinyint() || var_val.is_number(), OB_ERR_UNEXPECTED, K(var_val));
|
|
if (OB_SUCC(ret)
|
|
&& (var_val.is_tinyint() ? var_val.get_bool() : !var_val.is_zero_number())) {
|
|
if (from_proxy) {
|
|
ret = OB_NOT_SUPPORTED;
|
|
LOG_WARN("can not sync package open cursor from proxy,"
|
|
"need route current sql to orignal server", K(ret));
|
|
LOG_USER_ERROR(OB_NOT_SUPPORTED, "sync package open cursor from proxy");
|
|
} else {
|
|
ObPLCursorInfo *cursor = reinterpret_cast<ObPLCursorInfo *>(new_var_val.get_ext());
|
|
CK (OB_NOT_NULL(cursor));
|
|
OX (cursor->set_sync_cursor());
|
|
}
|
|
}
|
|
} else if (var->get_type().is_opaque_type()) {
|
|
if (var_val.is_null()) {
|
|
ret = OB_NOT_SUPPORTED;
|
|
LOG_WARN("can not sync package opaque type", K(ret));
|
|
LOG_USER_ERROR(OB_NOT_SUPPORTED, "sync package opaque type");
|
|
}
|
|
} else {
|
|
OZ (var->get_type().deserialize(resolve_ctx,
|
|
var->get_type().is_cursor_type() ?
|
|
package_state->get_pkg_cursor_allocator()
|
|
: package_state->get_pkg_allocator(),
|
|
var_val.get_hex_string().ptr(),
|
|
var_val.get_hex_string().length(),
|
|
new_var_val), K(package_id), K(var_idx), K(var_val));
|
|
}
|
|
LOG_DEBUG("deserialize package var", K(package_id), K(var_idx), K(var_val), K(new_var_val));
|
|
}
|
|
if (OB_SUCC(ret) && var->is_not_null() && new_var_val.is_null()) {
|
|
ret = OB_ERR_NUMERIC_OR_VALUE_ERROR;
|
|
LOG_WARN("not null check violated", K(var->is_not_null()), K(var_val.is_null()), K(ret));
|
|
}
|
|
OZ (package_state->set_package_var_val(var_idx, new_var_val, !need_deserialize));
|
|
if (OB_NOT_NULL(var) && var->get_type().is_cursor_type() && !var->get_type().is_cursor_var()) {
|
|
// package ref cursor variable, refrence outside, do not destruct it.
|
|
} else if (OB_FAIL(ret)) {
|
|
OZ (ObUserDefinedType::destruct_obj(new_var_val, &(resolve_ctx.session_info_)));
|
|
} else {
|
|
OZ (ObUserDefinedType::destruct_obj(old_var_val, &(resolve_ctx.session_info_)));
|
|
}
|
|
if (!need_deserialize) {
|
|
OZ (package_state->update_changed_vars(var_idx));
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
|
|
|
|
|
|
int ObPLPackageManager::load_package_spec(const ObPLResolveCtx &resolve_ctx,
|
|
const ObPackageInfo &package_spec_info,
|
|
ObPLPackage *&package_spec)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
package_spec = NULL;
|
|
const uint64_t tenant_id = package_spec_info.get_tenant_id();
|
|
uint64_t db_id = package_spec_info.get_database_id();
|
|
uint64_t package_id = package_spec_info.get_package_id();
|
|
ObPLBlockNS *null_parent_ns = NULL;
|
|
uint64_t effective_tenant_id = resolve_ctx.session_info_.get_effective_tenant_id();
|
|
HEAP_VAR(ObPLPackageAST, package_spec_ast, resolve_ctx.allocator_) {
|
|
const ObDatabaseSchema *db_schema = NULL;
|
|
ObPLCompiler compiler(resolve_ctx.allocator_,
|
|
resolve_ctx.session_info_,
|
|
resolve_ctx.schema_guard_,
|
|
resolve_ctx.package_guard_,
|
|
resolve_ctx.sql_proxy_);
|
|
OZ (resolve_ctx.schema_guard_.get_database_schema(tenant_id, db_id, db_schema));
|
|
CK (OB_NOT_NULL(db_schema));
|
|
OZ (package_spec_ast.init(db_schema->get_database_name_str(),
|
|
package_spec_info.get_package_name(),
|
|
PL_PACKAGE_SPEC,
|
|
package_spec_info.get_database_id(),
|
|
package_id,
|
|
package_spec_info.get_schema_version(),
|
|
NULL));
|
|
// generate cacheobj_guard to protect package and package will be destoried by map's destructor
|
|
ObCacheObjGuard* cacheobj_guard = NULL;
|
|
void* buf = NULL;
|
|
if (OB_ISNULL(buf = resolve_ctx.package_guard_.alloc_.alloc(sizeof(ObCacheObjGuard)))) {
|
|
ret = OB_ALLOCATE_MEMORY_FAILED;
|
|
LOG_WARN("failed to allocate memory.", K(ret));
|
|
} else if (FALSE_IT(cacheobj_guard = new (buf)ObCacheObjGuard(PACKAGE_SPEC_HANDLE))) {
|
|
// do nothing
|
|
} else {
|
|
OZ (ObCacheObjectFactory::alloc(*cacheobj_guard, ObLibCacheNameSpace::NS_PKG,
|
|
effective_tenant_id));
|
|
OX (package_spec = static_cast<ObPLPackage*>(cacheobj_guard->get_cache_obj()));
|
|
CK (OB_NOT_NULL(package_spec));
|
|
OZ (package_spec->init(package_spec_ast));
|
|
OZ (compiler.compile_package(package_spec_info,
|
|
null_parent_ns,
|
|
package_spec_ast,
|
|
*package_spec));
|
|
if (OB_SUCC(ret)) {
|
|
if (package_spec->get_can_cached()
|
|
&& OB_FAIL(add_package_to_plan_cache(resolve_ctx, package_spec))) {
|
|
LOG_WARN("failed to add package spec to cached", K(ret));
|
|
ret = OB_SUCCESS; // cache add failed, need not fail execute path
|
|
} else {
|
|
LOG_DEBUG("success to add package spec to cached",
|
|
K(ret), K(package_id), K(package_spec->get_can_cached()));
|
|
}
|
|
}
|
|
OZ (resolve_ctx.package_guard_.put(package_id, cacheobj_guard), package_id);
|
|
if (OB_FAIL(ret) && OB_NOT_NULL(package_spec)) {
|
|
// pointer should be free manually
|
|
cacheobj_guard->~ObCacheObjGuard();
|
|
package_spec = NULL;
|
|
}
|
|
}
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int ObPLPackageManager::load_package_body(const ObPLResolveCtx &resolve_ctx,
|
|
const share::schema::ObPackageInfo &package_spec_info,
|
|
const share::schema::ObPackageInfo &package_body_info,
|
|
ObPLPackage *&package_body)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
package_body = NULL;
|
|
ObPLCompiler compiler(resolve_ctx.allocator_,
|
|
resolve_ctx.session_info_,
|
|
resolve_ctx.schema_guard_,
|
|
resolve_ctx.package_guard_,
|
|
resolve_ctx.sql_proxy_);
|
|
const uint64_t tenant_id = package_spec_info.get_tenant_id();
|
|
uint64_t db_id = package_spec_info.get_database_id();
|
|
uint64_t package_spec_id = package_spec_info.get_package_id();
|
|
uint64_t package_body_id = package_body_info.get_package_id();
|
|
ObPLBlockNS *null_parent_ns = NULL;
|
|
const ObDatabaseSchema *db_schema = NULL;
|
|
uint64_t effective_tenant_id = resolve_ctx.session_info_.get_effective_tenant_id();
|
|
HEAP_VARS_2((ObPLPackageAST, package_spec_ast, resolve_ctx.allocator_),
|
|
(ObPLPackageAST, package_body_ast, resolve_ctx.allocator_)) {
|
|
ObString source;
|
|
if (package_spec_info.is_for_trigger()) {
|
|
OZ (ObTriggerInfo::gen_package_source(package_spec_info.get_tenant_id(),
|
|
package_spec_info.get_package_id(),
|
|
source,
|
|
PACKAGE_TYPE,
|
|
resolve_ctx.schema_guard_,
|
|
resolve_ctx.allocator_));
|
|
} else {
|
|
source = package_spec_info.get_source();
|
|
}
|
|
OZ (resolve_ctx.schema_guard_.get_database_schema(tenant_id, db_id, db_schema));
|
|
OZ (package_spec_ast.init(db_schema->get_database_name_str(),
|
|
package_spec_info.get_package_name(),
|
|
PL_PACKAGE_SPEC,
|
|
package_spec_info.get_database_id(),
|
|
package_spec_id,
|
|
package_spec_info.get_schema_version(),
|
|
NULL));
|
|
OZ (ObSQLUtils::convert_sql_text_from_schema_for_resolve(
|
|
resolve_ctx.allocator_, resolve_ctx.session_info_.get_dtc_params(), source));
|
|
{
|
|
ObPLCompilerEnvGuard guard(
|
|
package_spec_info, resolve_ctx.session_info_, resolve_ctx.schema_guard_, ret);
|
|
OZ (compiler.analyze_package(source, null_parent_ns,
|
|
package_spec_ast, package_spec_info.is_for_trigger()));
|
|
}
|
|
|
|
OZ (package_body_ast.init(db_schema->get_database_name_str(),
|
|
package_body_info.get_package_name(),
|
|
PL_PACKAGE_BODY,
|
|
package_body_info.get_database_id(),
|
|
package_body_id,
|
|
package_body_info.get_schema_version(),
|
|
&package_spec_ast));
|
|
// generate cacheobj_guard to protect package and package will be
|
|
// destoried by map's destructor
|
|
ObCacheObjGuard* cacheobj_guard = NULL;
|
|
void* buf = NULL;
|
|
if (OB_ISNULL(buf = resolve_ctx.package_guard_.alloc_.alloc(sizeof(ObCacheObjGuard)))) {
|
|
ret = OB_ALLOCATE_MEMORY_FAILED;
|
|
LOG_WARN("failed to allocate memory.", K(ret));
|
|
} else if (FALSE_IT(cacheobj_guard = new (buf)ObCacheObjGuard(PACKAGE_BODY_HANDLE))) {
|
|
// do nothing
|
|
} else {
|
|
OZ (ObCacheObjectFactory::alloc(*cacheobj_guard, ObLibCacheNameSpace::NS_PKG,
|
|
effective_tenant_id));
|
|
OX (package_body = static_cast<ObPLPackage*>(cacheobj_guard->get_cache_obj()));
|
|
CK (OB_NOT_NULL(package_body));
|
|
OZ (package_body->init(package_body_ast));
|
|
|
|
for (int64_t i = 0; OB_SUCC(ret) && i < package_spec_ast.get_dependency_table().count(); ++i) {
|
|
OZ (package_body_ast.add_dependency_object(package_spec_ast.get_dependency_table().at(i)));
|
|
}
|
|
OZ (compiler.compile_package(package_body_info,
|
|
&(package_spec_ast.get_body()->get_namespace()),
|
|
package_body_ast,
|
|
*package_body));
|
|
if (OB_SUCC(ret)
|
|
&& package_body->get_can_cached()
|
|
&& OB_FAIL(add_package_to_plan_cache(resolve_ctx, package_body))) {
|
|
LOG_WARN("add package body to plan cache failed", K(package_body_id), K(ret));
|
|
ret = OB_SUCCESS; //cache add failed, need not fail execute path
|
|
}
|
|
OZ (resolve_ctx.package_guard_.put(package_body_id, cacheobj_guard));
|
|
if (OB_FAIL(ret) && OB_NOT_NULL(package_body)) {
|
|
// pointer should be free manually
|
|
cacheobj_guard->~ObCacheObjGuard();
|
|
package_body = NULL;
|
|
}
|
|
}
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int ObPLPackageManager::check_version(const ObPLResolveCtx &resolve_ctx, uint64_t package_id,
|
|
const ObPackageStateVersion &state_version, bool &match)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
match = true;
|
|
if (OB_INVALID_ID == package_id
|
|
|| !state_version.is_valid()) {
|
|
ret = OB_ERR_UNEXPECTED;
|
|
LOG_WARN("tenant or package id is invalid", K(ret), K(package_id));
|
|
} else {
|
|
ObPLPackage *package_spec = NULL;
|
|
ObPLPackage *package_body = NULL;
|
|
if (OB_FAIL(get_cached_package(resolve_ctx, package_id, package_spec, package_body))) {
|
|
LOG_WARN("failed to get cached package", K(ret), K(package_id));
|
|
} else {
|
|
if (state_version.package_version_ == package_spec->get_version()) {
|
|
if (OB_NOT_NULL(package_body) && state_version.package_body_version_ != package_body->get_version()) {
|
|
match = false;
|
|
}
|
|
} else {
|
|
match = false;
|
|
}
|
|
}
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int ObPLPackageManager::get_package_schema_info(ObSchemaGetterGuard &schema_guard,
|
|
uint64_t package_id,
|
|
const ObPackageInfo *&package_spec_info,
|
|
const ObPackageInfo *&package_body_info)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
package_spec_info = NULL;
|
|
package_body_info = NULL;
|
|
int64_t compatible_mode = lib::is_oracle_mode() ? COMPATIBLE_ORACLE_MODE
|
|
: COMPATIBLE_MYSQL_MODE;
|
|
if (!ObTriggerInfo::is_trigger_package_id(package_id)) {
|
|
const uint64_t tenant_id = get_tenant_id_by_object_id(package_id);
|
|
const ObPackageInfo *tmp_package_info = NULL;
|
|
if (OB_FAIL(schema_guard.get_package_info(tenant_id, package_id, tmp_package_info))) {
|
|
LOG_WARN("failed to get package info", K(tenant_id), K(package_id), K(ret));
|
|
} else if (OB_ISNULL(tmp_package_info)) {
|
|
ret = OB_ERR_PACKAGE_DOSE_NOT_EXIST;
|
|
LOG_WARN("package info is NULL", K(package_id), K(ret));
|
|
} else {
|
|
if (PACKAGE_TYPE == tmp_package_info->get_type()) {
|
|
package_spec_info = tmp_package_info;
|
|
if (OB_FAIL(schema_guard.get_package_info(tmp_package_info->get_tenant_id(),
|
|
tmp_package_info->get_database_id(),
|
|
tmp_package_info->get_package_name(),
|
|
PACKAGE_BODY_TYPE,
|
|
compatible_mode,
|
|
package_body_info))) {
|
|
LOG_WARN("failed to get package body info", "package name", package_spec_info->get_package_name(), K(ret));
|
|
}
|
|
} else {
|
|
package_body_info = tmp_package_info;
|
|
if (OB_FAIL(schema_guard.get_package_info(tmp_package_info->get_tenant_id(),
|
|
tmp_package_info->get_database_id(),
|
|
tmp_package_info->get_package_name(),
|
|
PACKAGE_TYPE,
|
|
compatible_mode,
|
|
package_spec_info))) {
|
|
LOG_WARN("failed to get package info", "package name", package_body_info->get_package_name(), K(ret));
|
|
} else if (OB_ISNULL(package_spec_info)) {
|
|
ret = OB_ERR_PACKAGE_DOSE_NOT_EXIST;
|
|
LOG_WARN("package body info is NULL", K(ret));
|
|
{
|
|
ObString db_name("");
|
|
const ObDatabaseSchema *database_schema = NULL;
|
|
if (OB_SUCCESS == schema_guard.get_database_schema(tmp_package_info->get_tenant_id(),
|
|
tmp_package_info->get_database_id(), database_schema)) {
|
|
if (NULL != database_schema) {
|
|
db_name =database_schema->get_database_name_str();
|
|
}
|
|
}
|
|
LOG_USER_ERROR(OB_ERR_PACKAGE_DOSE_NOT_EXIST, "PACKAGE",
|
|
db_name.length(), db_name.ptr(),
|
|
tmp_package_info->get_package_name().length(),
|
|
tmp_package_info->get_package_name().ptr());
|
|
}
|
|
}
|
|
}
|
|
}
|
|
} else {
|
|
if (OB_FAIL(schema_guard.get_package_info_from_trigger(MTL_ID(),
|
|
package_id,
|
|
package_spec_info,
|
|
package_body_info))) {
|
|
LOG_WARN("failed to get package info from trigger", K(ret), K(package_id));
|
|
}
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int ObPLPackageManager::get_cached_package_spec(const ObPLResolveCtx &resolve_ctx,
|
|
uint64_t package_id,
|
|
ObPLPackage *&package_spec)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
package_spec = NULL;
|
|
bool is_overflow = false;
|
|
if (OB_FAIL(check_stack_overflow(is_overflow))) {
|
|
LOG_WARN("failed to check stack overflow", K(ret));
|
|
} else if (is_overflow) {
|
|
ret = OB_SIZE_OVERFLOW;
|
|
LOG_WARN("too deep recusive", K(ret));
|
|
}
|
|
CK (OB_LIKELY(OB_INVALID_ID != package_id));
|
|
|
|
ObCacheObjGuard* guard = NULL;
|
|
OX (ret = resolve_ctx.package_guard_.get(package_id, guard));
|
|
if (OB_SUCC(ret) && OB_NOT_NULL(guard)) {
|
|
OX (package_spec = static_cast<ObPLPackage*>(guard->get_cache_obj()));
|
|
CK (OB_NOT_NULL(package_spec));
|
|
} else if (OB_HASH_NOT_EXIST == ret) {
|
|
ret = OB_SUCCESS;
|
|
const ObPackageInfo *package_info = NULL;
|
|
const uint64_t tenant_id = get_tenant_id_by_object_id(package_id);
|
|
OZ (resolve_ctx.schema_guard_.get_package_info(tenant_id, package_id, package_info), package_id);
|
|
OV (OB_NOT_NULL(package_info), OB_ERR_UNEXPECTED, K(tenant_id), K(package_id));
|
|
OZ (get_package_from_plan_cache(resolve_ctx, package_id, package_spec), package_id);
|
|
if (OB_SUCC(ret)) {
|
|
if (OB_ISNULL(package_spec)) {
|
|
OZ (load_package_spec(resolve_ctx, *package_info, package_spec), package_id);
|
|
} else {
|
|
if (package_info->get_schema_version() != package_spec->get_version()) {
|
|
ret = OB_NEED_RETRY;
|
|
LOG_ERROR("package version changed",
|
|
K(package_id), K(ret), KPC(package_info), KPC(package_spec));
|
|
}
|
|
}
|
|
}
|
|
} else if (OB_FAIL(ret)) {
|
|
LOG_WARN("failed to get package from local cache", K(ret), K(package_id));
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int ObPLPackageManager::get_cached_package(const ObPLResolveCtx &resolve_ctx,
|
|
uint64_t package_id,
|
|
ObPLPackage *&package_spec,
|
|
ObPLPackage *&package_body,
|
|
bool for_static_member)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
package_spec = NULL;
|
|
package_body = NULL;
|
|
bool is_overflow = false;
|
|
if (OB_FAIL(check_stack_overflow(is_overflow))) {
|
|
LOG_WARN("failed to check stack overflow", K(ret));
|
|
} else if (is_overflow) {
|
|
ret = OB_SIZE_OVERFLOW;
|
|
LOG_WARN("too deep recusive", K(ret));
|
|
}
|
|
CK (OB_LIKELY(OB_INVALID_ID != package_id));
|
|
if (OB_SUCC(ret)) {
|
|
const ObPackageInfo *package_spec_info = NULL;
|
|
const ObPackageInfo *package_body_info = NULL;
|
|
uint64_t package_spec_id = OB_INVALID_ID;
|
|
uint64_t package_body_id = OB_INVALID_ID;
|
|
OZ (get_package_schema_info(resolve_ctx.schema_guard_, package_id, package_spec_info, package_body_info));
|
|
OV (OB_NOT_NULL(package_spec_info), OB_ERR_UNEXPECTED, K(package_id));
|
|
OX (package_spec_id = package_spec_info->get_package_id());
|
|
OZ (get_cached_package_spec(resolve_ctx, package_spec_id, package_spec));
|
|
CK (OB_NOT_NULL(package_spec));
|
|
if (OB_SUCC(ret)
|
|
&& OB_NOT_NULL(package_body_info)
|
|
&& (!for_static_member || package_id != package_spec_id)) {
|
|
OX (package_body_id = package_body_info->get_package_id());
|
|
|
|
ObCacheObjGuard* guard = NULL;
|
|
OX (ret = resolve_ctx.package_guard_.get(package_body_id, guard));
|
|
if (OB_SUCC(ret) && OB_NOT_NULL(guard)) {
|
|
OX (package_body = static_cast<ObPLPackage*>(guard->get_cache_obj()));
|
|
CK (OB_NOT_NULL(package_body));
|
|
} else if (OB_HASH_NOT_EXIST == ret) {
|
|
ret = OB_SUCCESS;
|
|
OZ (get_package_from_plan_cache(resolve_ctx, package_body_id, package_body));
|
|
if (OB_SUCC(ret) && OB_ISNULL(package_body)) {
|
|
OZ (load_package_body(resolve_ctx, *package_spec_info, *package_body_info, package_body));
|
|
CK (OB_NOT_NULL(package_body));
|
|
}
|
|
if (OB_SUCC(ret)
|
|
&& package_body_info->get_schema_version() != package_body->get_version()) {
|
|
ret = OB_NEED_RETRY;
|
|
LOG_ERROR("package body version changed", K(package_body_id), K(ret));
|
|
}
|
|
} else {
|
|
LOG_WARN("failed to get package body from local cache", K(ret), K(package_body_id));
|
|
}
|
|
}
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int ObPLPackageManager::get_package_item_state(ObSQLSessionInfo &session_info,
|
|
int64_t package_id,
|
|
const ObPackageStateVersion &state_version,
|
|
ObPLPackageState *&package_state)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
int hash_ret = session_info.get_package_state(package_id, package_state);
|
|
if (OB_HASH_NOT_EXIST == hash_ret) {
|
|
package_state = NULL;
|
|
} else if (hash_ret != OB_SUCCESS) {
|
|
ret = hash_ret;
|
|
LOG_WARN("failed to get package state from session", K(hash_ret), K(ret));
|
|
} else if (OB_NOT_NULL(package_state) && !package_state->check_version(state_version)) {
|
|
package_state = NULL;
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int ObPLPackageManager::get_package_item_state(const ObPLResolveCtx &resolve_ctx,
|
|
ObExecContext &exec_ctx,
|
|
ObPLPackage &package,
|
|
const ObPackageStateVersion &state_version,
|
|
ObPLPackageState *&package_state)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
package_state = NULL;
|
|
ObIAllocator &session_allocator = resolve_ctx.session_info_.get_package_allocator();
|
|
uint64_t package_id = package.get_id();
|
|
bool need_new = false;
|
|
int hash_ret = resolve_ctx.session_info_.get_package_state(package_id, package_state);
|
|
if (OB_HASH_NOT_EXIST == hash_ret) {
|
|
need_new = true;
|
|
} else if (OB_SUCCESS != hash_ret) {
|
|
ret = hash_ret;
|
|
LOG_WARN("get package state failed", K(package_id), K(ret));
|
|
} else if (!package_state->check_version(state_version)) {
|
|
OZ (resolve_ctx.session_info_.del_package_state(package_id));
|
|
if (OB_SUCC(ret)) {
|
|
package_state->reset(&(resolve_ctx.session_info_));
|
|
package_state->~ObPLPackageState();
|
|
session_allocator.free(package_state);
|
|
package_state = NULL;
|
|
need_new = true;
|
|
}
|
|
}
|
|
if (OB_SUCC(ret) && need_new) {
|
|
CK (OB_ISNULL(package_state));
|
|
if (OB_FAIL(ret)) {
|
|
} else if (OB_ISNULL(package_state =
|
|
static_cast<ObPLPackageState *>(session_allocator.alloc(sizeof(ObPLPackageState))))) {
|
|
ret = OB_ALLOCATE_MEMORY_FAILED;
|
|
LOG_WARN("memory allocate failed", K(ret));
|
|
} else {
|
|
new (package_state)
|
|
ObPLPackageState(package_id, state_version, package.get_serially_reusable());
|
|
ExecCtxBak exec_ctx_bak;
|
|
OX (exec_ctx_bak.backup(exec_ctx));
|
|
sql::ObPhysicalPlanCtx phy_plan_ctx(exec_ctx.get_allocator());
|
|
OX (exec_ctx.set_physical_plan_ctx(&phy_plan_ctx));
|
|
if (OB_SUCC(ret) && package.get_expr_op_size() > 0) {
|
|
OZ (exec_ctx.init_expr_op(package.get_expr_op_size()));
|
|
}
|
|
// 要先加到SESSION上然后在初始化, 反之会造成死循环
|
|
OZ (resolve_ctx.session_info_.add_package_state(package_id, package_state));
|
|
if (OB_SUCC(ret)) {
|
|
// TODO bin.lb: how about the memory?
|
|
//
|
|
OZ(package.get_frame_info().pre_alloc_exec_memory(exec_ctx));
|
|
}
|
|
if (OB_SUCC(ret)
|
|
&& OB_FAIL(package.instantiate_package_state(resolve_ctx, exec_ctx, *package_state))) {
|
|
int tmp_ret = OB_SUCCESS;
|
|
if (OB_SUCCESS != (tmp_ret = resolve_ctx.session_info_.del_package_state(package_id))) {
|
|
// 删除失败, 为了避免一个未知的状态, 重新初始化这段内存, 使之是无效状态
|
|
new (package_state)
|
|
ObPLPackageState(package_id, state_version, package.get_serially_reusable());
|
|
LOG_WARN("failed to del package state", K(ret), K(package_id), K(tmp_ret));
|
|
} else {
|
|
// 删除成功将内存释放
|
|
package_state->reset(&(resolve_ctx.session_info_));
|
|
package_state->~ObPLPackageState();
|
|
session_allocator.free(package_state);
|
|
package_state = NULL;
|
|
LOG_WARN("failed to call instantiate_package_state", K(ret), K(package_id));
|
|
}
|
|
}
|
|
if (package.get_expr_op_size() > 0) {
|
|
//Memory leak
|
|
//Must be reset before free expr_op_ctx!
|
|
exec_ctx.reset_expr_op();
|
|
exec_ctx.get_allocator().free(exec_ctx.get_expr_op_ctx_store());
|
|
}
|
|
exec_ctx_bak.restore(exec_ctx);
|
|
}
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int ObPLPackageManager::get_package_state(const ObPLResolveCtx &resolve_ctx,
|
|
sql::ObExecContext &exec_ctx,
|
|
uint64_t package_id,
|
|
ObPLPackageState *&package_state,
|
|
bool for_static_member)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
package_state = NULL;
|
|
if (OB_INVALID_ID == package_id) {
|
|
ret = OB_ERR_UNEXPECTED;
|
|
LOG_WARN("invalid package id", K(ret));
|
|
} else {
|
|
ObPLPackage* package_spec = NULL;
|
|
ObPLPackage* package_body = NULL;
|
|
if (OB_FAIL(get_cached_package(
|
|
resolve_ctx, package_id, package_spec, package_body, for_static_member))) {
|
|
LOG_WARN("get package failed", K(package_id), K(ret));
|
|
} else if (OB_ISNULL(package_spec)) {
|
|
ret = OB_ERR_PACKAGE_DOSE_NOT_EXIST;
|
|
LOG_WARN("package spec not exist", K(package_id), K(ret));
|
|
} else {
|
|
ObPackageStateVersion state_version(package_spec->get_version(), NULL==package_body?OB_INVALID_VERSION:package_body->get_version());
|
|
ObPLPackageState *package_spec_state = NULL;
|
|
ObPLPackageState *package_body_state = NULL;
|
|
if (OB_FAIL(get_package_item_state(resolve_ctx, exec_ctx, *package_spec, state_version, package_spec_state))) {
|
|
LOG_WARN("get pacakge spec state failed", K(ret));
|
|
} else if (!OB_ISNULL(package_body) && OB_FAIL(get_package_item_state(resolve_ctx, exec_ctx, *package_body, state_version, package_body_state))) {
|
|
LOG_WARN("get pacakge body state failed", K(ret));
|
|
} else {
|
|
if (package_id == package_spec->get_id()) {
|
|
package_state = package_spec_state;
|
|
} else {
|
|
package_state = package_body_state;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int ObPLPackageManager::add_package_to_plan_cache(const ObPLResolveCtx &resolve_ctx, ObPLPackage *package)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
ObPlanCache *plan_cache = NULL;
|
|
if (OB_ISNULL(package)) {
|
|
ret = OB_ERR_UNEXPECTED;
|
|
LOG_WARN("cached package is null", K(package));
|
|
} else if (OB_ISNULL(plan_cache = resolve_ctx.session_info_.get_plan_cache())) {
|
|
ret = OB_ERR_UNEXPECTED;
|
|
LOG_WARN("plan cache is null");
|
|
} else {
|
|
int64_t tenant_id = resolve_ctx.session_info_.get_effective_tenant_id();
|
|
uint64_t package_id = package->get_id();
|
|
ObString sql("package");
|
|
//ObArenaAllocator allocator(ObModIds::OB_PL_TEMP);
|
|
|
|
//HEAP_VAR(ObExecContext, exec_ctx, allocator) {
|
|
|
|
uint64_t database_id = OB_INVALID_ID;
|
|
resolve_ctx.session_info_.get_database_id(database_id);
|
|
|
|
ObPLCacheCtx pc_ctx;
|
|
pc_ctx.session_info_ = &resolve_ctx.session_info_;
|
|
pc_ctx.schema_guard_ = &resolve_ctx.schema_guard_;
|
|
(void)ObSQLUtils::md5(sql,pc_ctx.sql_id_, (int32_t)sizeof(pc_ctx.sql_id_));
|
|
int64_t sys_schema_version = OB_INVALID_VERSION;
|
|
int64_t tenant_schema_version = OB_INVALID_VERSION;
|
|
|
|
pc_ctx.key_.namespace_ = ObLibCacheNameSpace::NS_PKG;
|
|
pc_ctx.key_.db_id_ = database_id;
|
|
pc_ctx.key_.key_id_ = package_id;
|
|
pc_ctx.key_.sessid_ =
|
|
(get_tenant_id_by_object_id(package_id) != OB_SYS_TENANT_ID && resolve_ctx.session_info_.is_pl_debug_on())
|
|
? resolve_ctx.session_info_.get_sessid() : 0;
|
|
|
|
if (OB_FAIL(ret)) {
|
|
} else if (OB_FAIL(resolve_ctx.schema_guard_.get_schema_version(tenant_id, tenant_schema_version))
|
|
|| OB_FAIL(resolve_ctx.schema_guard_.get_schema_version(OB_SYS_TENANT_ID, sys_schema_version))) {
|
|
LOG_WARN("fail to get schema version", K(ret), K(tenant_id));
|
|
} else {
|
|
package->set_tenant_schema_version(tenant_schema_version);
|
|
package->set_sys_schema_version(sys_schema_version);
|
|
}
|
|
if (OB_FAIL(ret)) {
|
|
// do nothing
|
|
} else if (OB_FAIL(ObPLCacheMgr::add_pl_cache(resolve_ctx.session_info_.get_plan_cache(), package, pc_ctx))) {
|
|
if (OB_SQL_PC_PLAN_DUPLICATE == ret) {
|
|
LOG_INFO("package has been added by others, need not add again", K(package_id), K(ret));
|
|
ret = OB_SUCCESS;
|
|
} else if (OB_REACH_MEMORY_LIMIT == ret || OB_SQL_PC_PLAN_SIZE_LIMIT == ret) {
|
|
if (REACH_TIME_INTERVAL(1000000)) { //1s, 当内存达到上限时, 该日志打印会比较频繁, 所以以1s为间隔打印
|
|
LOG_INFO("can't add plan to plan cache",
|
|
K(package_id), K(package->get_mem_size()), K(plan_cache->get_mem_used()), K(ret));
|
|
}
|
|
ret = OB_SUCCESS;
|
|
} else if (OB_REACH_MAX_CONCURRENT_NUM != ret) { //如果是达到限流上限, 则将错误码抛出去
|
|
LOG_WARN("add package to ObPlanCache failed",
|
|
K(package_id), K(ret), K(package->get_dependency_table()));
|
|
ret = OB_SUCCESS; //add package出错, 覆盖错误码, 确保因plan cache失败不影响正常执行路径
|
|
}
|
|
} else {
|
|
LOG_INFO("add pl package to plan cache success",
|
|
K(ret), K(package_id), K(package->get_dependency_table()), K(pc_ctx.key_));
|
|
}
|
|
//exec_ctx.set_physical_plan_ctx(NULL);
|
|
//}
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int ObPLPackageManager::get_package_from_plan_cache(const ObPLResolveCtx &resolve_ctx,
|
|
uint64_t package_id,
|
|
ObPLPackage *&package)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
package = NULL;
|
|
bool is_overflow = false;
|
|
if (OB_FAIL(check_stack_overflow(is_overflow))) {
|
|
LOG_WARN("failed to check stack overflow", K(ret));
|
|
} else if (is_overflow) {
|
|
ret = OB_SIZE_OVERFLOW;
|
|
LOG_WARN("too deep recusive", K(ret));
|
|
}
|
|
if (OB_FAIL(ret)) {
|
|
// do nothing
|
|
} else {
|
|
ObString sql("package");
|
|
//SMART_VAR(ObExecContext, exec_ctx, resolve_ctx.allocator_) {
|
|
|
|
uint64_t database_id = OB_INVALID_ID;
|
|
resolve_ctx.session_info_.get_database_id(database_id);
|
|
|
|
ObPLCacheCtx pc_ctx;
|
|
pc_ctx.session_info_ = &resolve_ctx.session_info_;
|
|
pc_ctx.schema_guard_ = &resolve_ctx.schema_guard_;
|
|
(void)ObSQLUtils::md5(sql,pc_ctx.sql_id_, (int32_t)sizeof(pc_ctx.sql_id_));
|
|
pc_ctx.key_.namespace_ = ObLibCacheNameSpace::NS_PKG;
|
|
pc_ctx.key_.db_id_ = database_id;
|
|
pc_ctx.key_.key_id_ = package_id;
|
|
pc_ctx.key_.sessid_ =
|
|
(get_tenant_id_by_object_id(package_id) != OB_SYS_TENANT_ID && resolve_ctx.session_info_.is_pl_debug_on())
|
|
? resolve_ctx.session_info_.get_sessid() : 0;
|
|
|
|
// get package from plan cache
|
|
ObCacheObjGuard* cacheobj_guard = NULL;
|
|
void* buf = NULL;
|
|
if (OB_FAIL(ret)) {
|
|
} else if (OB_ISNULL(buf = resolve_ctx.package_guard_.alloc_.alloc(sizeof(ObCacheObjGuard)))) {
|
|
ret = OB_ALLOCATE_MEMORY_FAILED;
|
|
LOG_WARN("failed to allocate memory.", K(ret));
|
|
} else if (FALSE_IT(cacheobj_guard = new (buf)ObCacheObjGuard(GET_PKG_HANDLE))) {
|
|
// do nothing
|
|
} else if (OB_FAIL(ObPLCacheMgr::get_pl_cache(resolve_ctx.session_info_.get_plan_cache(), *cacheobj_guard, pc_ctx))) {
|
|
LOG_INFO("get pl package from plan cache failed", K(ret), K(package_id));
|
|
if (OB_ERR_UNEXPECTED != ret) {
|
|
ret = OB_SUCCESS;
|
|
}
|
|
} else if (FALSE_IT(package = static_cast<ObPLPackage*>(cacheobj_guard->get_cache_obj()))) {
|
|
// do nothing
|
|
} else if (OB_NOT_NULL(package)) {
|
|
if (OB_FAIL(resolve_ctx.package_guard_.put(package_id, cacheobj_guard))) {
|
|
LOG_WARN("failed to put package to package guard", K(ret), K(package_id));
|
|
// pointer should be free manualy
|
|
cacheobj_guard->~ObCacheObjGuard();
|
|
package = NULL;
|
|
} else {
|
|
LOG_DEBUG("get package from plan cache success", K(ret), K(package_id));
|
|
}
|
|
} else {}
|
|
//}
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int ObPLPackageManager::destory_package_state(sql::ObSQLSessionInfo &session_info, uint64_t package_id)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
ObPLPackageState *package_state;
|
|
if (OB_FAIL(session_info.get_package_state(package_id, package_state))) {
|
|
if (OB_HASH_NOT_EXIST != ret) {
|
|
LOG_WARN("get package state failed", K(ret));
|
|
} else {
|
|
ret = OB_SUCCESS;
|
|
}
|
|
} else if (OB_ISNULL(package_state)) {
|
|
ret = OB_ERR_UNEXPECTED;
|
|
LOG_WARN("package state is null", K(ret));
|
|
} else if (OB_FAIL(session_info.del_package_state(package_id))) {
|
|
LOG_WARN("delete package state failed", K(package_state), K(ret));
|
|
} else {
|
|
package_state->reset(&session_info);
|
|
package_state->~ObPLPackageState();
|
|
session_info.get_package_allocator().free(package_state);
|
|
package_state = NULL;
|
|
}
|
|
return ret;
|
|
}
|
|
} // end namespace pl
|
|
} // end namespace oceanbase
|